Example #1
0
File: fscache.c Project: guban/git
/*
 * Looks up or creates a cache entry for the specified key.
 */
static struct fsentry *fscache_get(struct fsentry *key)
{
	struct fsentry *fse, *future, *waiter;
	int dir_not_found;

	EnterCriticalSection(&mutex);
	/* check if entry is in cache */
	fse = fscache_get_wait(key);
	if (fse) {
		if (fse->st_mode)
			fsentry_addref(fse);
		else
			fse = NULL; /* non-existing directory */
		LeaveCriticalSection(&mutex);
		return fse;
	}
	/* if looking for a file, check if directory listing is in cache */
	if (!fse && key->list) {
		fse = fscache_get_wait(key->list);
		if (fse) {
			LeaveCriticalSection(&mutex);
			/*
			 * dir entry without file entry, or dir does not
			 * exist -> file doesn't exist
			 */
			errno = ENOENT;
			return NULL;
		}
	}

	/* add future entry to indicate that we're loading it */
	future = key->list ? key->list : key;
	future->next = NULL;
	future->refcnt = 0;
	hashmap_add(&map, future);

	/* create the directory listing (outside mutex!) */
	LeaveCriticalSection(&mutex);
	fse = fsentry_create_list(future, &dir_not_found);
	EnterCriticalSection(&mutex);

	/* remove future entry and signal waiting threads */
	hashmap_remove(&map, future, NULL);
	waiter = future->next;
	while (waiter) {
		HANDLE h = waiter->hwait;
		waiter = waiter->next;
		SetEvent(h);
	}

	/* leave on error (errno set by fsentry_create_list) */
	if (!fse) {
		if (dir_not_found && key->list) {
			/*
			 * Record that the directory does not exist (or is
			 * empty, which for all practical matters is the same
			 * thing as far as fscache is concerned).
			 */
			fse = fsentry_alloc(key->list->list,
					    key->list->name, key->list->len);
			fse->st_mode = 0;
			hashmap_add(&map, fse);
		}
		LeaveCriticalSection(&mutex);
		return NULL;
	}

	/* add directory listing to the cache */
	fscache_add(fse);

	/* lookup file entry if requested (fse already points to directory) */
	if (key->list)
		fse = hashmap_get(&map, key, NULL);

	if (fse && !fse->st_mode)
		fse = NULL; /* non-existing directory */

	/* return entry or ENOENT */
	if (fse)
		fsentry_addref(fse);
	else
		errno = ENOENT;

	LeaveCriticalSection(&mutex);
	return fse;
}
Example #2
0
/*
 * Looks up or creates a cache entry for the specified key.
 */
static struct fsentry *fscache_get(struct fsentry *key)
{
	struct fsentry *fse, *future, *waiter;

	EnterCriticalSection(&mutex);
	/* check if entry is in cache */
	fse = fscache_get_wait(key);
	if (fse) {
		fsentry_addref(fse);
		LeaveCriticalSection(&mutex);
		return fse;
	}
	/* if looking for a file, check if directory listing is in cache */
	if (!fse && key->list) {
		fse = fscache_get_wait(key->list);
		if (fse) {
			LeaveCriticalSection(&mutex);
			/* dir entry without file entry -> file doesn't exist */
			errno = ENOENT;
			return NULL;
		}
	}

	/* add future entry to indicate that we're loading it */
	future = key->list ? key->list : key;
	future->next = NULL;
	future->refcnt = 0;
	hashmap_add(&map, future);

	/* create the directory listing (outside mutex!) */
	LeaveCriticalSection(&mutex);
	fse = fsentry_create_list(future);
	EnterCriticalSection(&mutex);

	/* remove future entry and signal waiting threads */
	hashmap_remove(&map, future, NULL);
	waiter = future->next;
	while (waiter) {
		HANDLE h = waiter->hwait;
		waiter = waiter->next;
		SetEvent(h);
	}

	/* leave on error (errno set by fsentry_create_list) */
	if (!fse) {
		LeaveCriticalSection(&mutex);
		return NULL;
	}

	/* add directory listing to the cache */
	fscache_add(fse);

	/* lookup file entry if requested (fse already points to directory) */
	if (key->list)
		fse = hashmap_get(&map, key, NULL);

	/* return entry or ENOENT */
	if (fse)
		fsentry_addref(fse);
	else
		errno = ENOENT;

	LeaveCriticalSection(&mutex);
	return fse;
}