Exemple #1
0
void
file_data_free(struct file *file, unsigned char *data)
{
	if (file->begin) {
		if (data == file->begin)
			return;
		if (data >= file->begin && data < file->end)
			return;
	}
	if (file->cache && data) {
		cache_entry_destroy(file_cache, data);
	} else
		g_free(data);
}
Exemple #2
0
static void * cache_maintain(void * arg)
{
	/* This code runs as a thread and is responsible for maintaining the
	 * cache. Every 10 seconds it scans 1/6 of the cache, so that in a
	 * minute it will scan the entire cache. It attempts to refresh cache
	 * entries which have expired, but only up to 5 times if they have not
	 * been used in the interim. After that they are removed. */
	int entries = HASH_SIZE / 6;
	int position = 0;
	for(;;)
	{
		int i;
		time_t now;
		struct timespec delay;
		
		delay.tv_sec = 10;
		delay.tv_nsec = 0;
		while(nanosleep(&delay, &delay) < 0 && errno == EINTR)
			if(debug)
				printf("Resuming interrupted sleep!\n");
		
		pthread_mutex_lock(&cache_mutex);
		if(debug)
			printf("Look over 1/6 of cache...\n");
		now = time(NULL);
		for(i = 0; i < entries; i++)
		{
			/* Since we'll potentially be removing entries from the
			 * linked list, we keep a pointer to the previous
			 * element's link to us so that we can update it and use
			 * that to get to the next element if we remove one. */
			struct cache_entry ** point = &hash_table[position];
			struct cache_entry * scan;
			while((scan = *point))
			{
				/* GET*ENT entries do not get refreshed here */
				if(scan->refreshes == 5 || (now > scan->expire_time &&
				   (scan->type == GETPWENT || scan->type == GETGRENT)))
					/* kill it */
					cache_entry_destroy(scan);
				else if(now > scan->expire_time)
				{
					request_header req = {version: NSCD_VERSION, type: scan->type, key_len: scan->key_len};
					int r;
					void * reply;
					int32_t reply_len;
					time_t refresh_interval;
					
					/* refresh it */
					if(debug)
						printf("Refreshing cache entry for [%s], refreshes %d\n", (char *) scan->key, scan->refreshes);
					pthread_mutex_unlock(&cache_mutex);
					r = generate_reply(&req, scan->key, -1, &reply, &reply_len, &refresh_interval);
					pthread_mutex_lock(&cache_mutex);
					now = time(NULL);
					
					/* while we were refreshing it, it may have
					 * been marked stale and a new copy fetched */
					if(scan->refreshes == 5 || r < 0)
					{
						/* kill it */
						cache_entry_destroy(scan);
						if(r >= 0)
							free(reply);
					}
					else
					{
						free(scan->reply);
						scan->reply = reply;
						scan->reply_len = reply_len;
						scan->expire_time += refresh_interval;
						scan->refresh_interval = refresh_interval;
						scan->refreshes++;
						/* go to next entry */
						point = &scan->chain;
					}
				}
				else
					/* go to next entry */
					point = &scan->chain;
			}
			if(++position == HASH_SIZE)
				position = 0;
		}
Exemple #3
0
int main (int argc, char *argv[])
{
    struct cache *cache;
    struct cache_entry *e1, *e2;
    json_object *o1;
    json_object *o2;
    wait_t *w;
    int count, i;

    plan (NO_PLAN);

    cache_destroy (NULL);
    cache_entry_destroy (NULL);
    diag ("cache_destroy and cache_entry_destroy accept NULL arg");

    ok ((cache = cache_create ()) != NULL,
        "cache_create works");
    ok (cache_count_entries (cache) == 0,
        "cache contains 0 entries");
    cache_destroy (cache);

    /* Play with one entry.
     * N.B.: json ref is NOT incremented by create or get_json.
     */
    o1 = Jnew ();
    Jadd_int (o1, "foo", 42);
    ok ((e1 = cache_entry_create (o1)) != NULL,
        "cache_entry_create works");
    ok (cache_entry_get_valid (e1) == true,
        "cache entry initially valid");
    ok (cache_entry_get_dirty (e1) == false,
        "cache entry initially not dirty");
    cache_entry_set_dirty (e1, true);
    ok (cache_entry_get_dirty (e1) == true,
        "cache entry succcessfully set dirty");
    ok ((o2 = cache_entry_get_json (e1)) != NULL,
        "json retrieved from cache entry");
    ok (Jget_int (o2, "foo", &i) == true && i == 42,
        "expected json object found");
    cache_entry_destroy (e1); /* destroys o1 */

    /* Test cache entry waiters.
     * N.B. waiter is destroyed when run.
     */
    count = 0;
    ok ((w = wait_create (wait_cb, &count)) != NULL,
        "wait_create works");
    ok ((e1 = cache_entry_create (NULL)) != NULL,
        "cache_entry_create created empty object");
    ok (cache_entry_get_valid (e1) == false,
        "cache entry invalid, adding waiter");
    o1 = Jnew ();
    Jadd_int (o1, "foo", 42);
    cache_entry_wait_valid (e1, w);
    cache_entry_set_json (e1, o1);
    ok (cache_entry_get_valid (e1) == true,
        "cache entry set valid with one waiter");
    ok (count == 1,
        "waiter callback ran");

    count = 0;
    ok ((w = wait_create (wait_cb, &count)) != NULL,
        "wait_create works");
    cache_entry_set_dirty (e1, true);
    ok (cache_entry_get_dirty (e1) == true,
        "cache entry set dirty, adding waiter");
    cache_entry_wait_notdirty (e1, w);
    cache_entry_set_dirty (e1, false);
    ok (cache_entry_get_dirty (e1) == false,
        "cache entry set not dirty with one waiter");
    ok (count == 1,
        "waiter callback ran");
    cache_entry_destroy (e1); /* destroys o1 */

    /* Put entry in cache and test lookup, expire
     */
    ok ((cache = cache_create ()) != NULL,
        "cache_create works");
    ok (cache_count_entries (cache) == 0,
        "cache contains 0 entries");
    o1 = Jnew ();
    Jadd_int (o1, "foo", 42);
    ok ((e1 = cache_entry_create (o1)) != NULL,
        "cache_entry_create works");
    cache_insert (cache, "xxx1", e1);
    ok (cache_count_entries (cache) == 1,
        "cache contains 1 entry after insert");
    ok (cache_lookup (cache, "yyy1", 0) == NULL,
        "cache_lookup of wrong hash fails");
    ok ((e2 = cache_lookup (cache, "xxx1", 42)) != NULL,
        "cache_lookup of correct hash works (last use=42)");
    i = 0;
    ok ((o2 = cache_entry_get_json (e2)) != NULL
        && Jget_int (o2, "foo", &i) == true && i == 42,
        "expected json object found");
    ok (cache_count_entries (cache) == 1,
        "cache contains 1 entry");
    ok (cache_expire_entries (cache, 43, 1) == 0,
        "cache_expire_entries now=43 thresh=1 expired 0");
    ok (cache_count_entries (cache) == 1,
        "cache contains 1 entry");
    ok (cache_expire_entries (cache, 44, 1) == 1,
        "cache_expire_entries now=44 thresh=1 expired 1");
    ok (cache_count_entries (cache) == 0,
        "cache contains 0 entries");
    cache_destroy (cache);

    done_testing ();
    return (0);
}