X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilccore%2Fsilcidcache.c;h=a28c6833034bc19cc92c0d2073593b1612f6cb94;hb=a818c5b5411bbc4436d1c5f011236985c96bb787;hp=b99859b52d638320f624bbe395993230aa93f92e;hpb=89329650d986e09749d9c6a039797aaccfb30f27;p=silc.git diff --git a/lib/silccore/silcidcache.c b/lib/silccore/silcidcache.c index b99859b5..a28c6833 100644 --- a/lib/silccore/silcidcache.c +++ b/lib/silccore/silcidcache.c @@ -87,9 +87,10 @@ struct SilcIDCacheStruct { struct SilcIDCacheListStruct { SilcIDCacheEntry cache[64]; SilcIDCacheEntry *cache_dyn; - uint32 cache_dyn_count; - uint32 cache_count; - uint32 pos; + SilcUInt32 cache_dyn_count; + SilcUInt32 cache_count; + SilcUInt32 pos; + bool dyn; }; /* Allocates new ID cache object. The initial amount of allocated entries @@ -97,7 +98,7 @@ struct SilcIDCacheListStruct { The `id_type' defines the types of the ID's that will be saved to the cache. */ -SilcIDCache silc_idcache_alloc(uint32 count, SilcIdType id_type, +SilcIDCache silc_idcache_alloc(SilcUInt32 count, SilcIdType id_type, SilcIDCacheDestructor destructor) { SilcIDCache cache; @@ -106,9 +107,9 @@ SilcIDCache silc_idcache_alloc(uint32 count, SilcIdType id_type, cache = silc_calloc(1, sizeof(*cache)); cache->id_table = silc_hash_table_alloc(count, silc_hash_id, - (void *)(uint32)id_type, + (void *)(SilcUInt32)id_type, silc_hash_id_compare, - (void *)(uint32)id_type, + (void *)(SilcUInt32)id_type, silc_idcache_destructor, NULL, FALSE); cache->name_table = silc_hash_table_alloc(count, silc_hash_string, NULL, @@ -122,7 +123,7 @@ SilcIDCache silc_idcache_alloc(uint32 count, SilcIdType id_type, return cache; } -/* Free's ID cache object and cache entries */ +/* Frees ID cache object and cache entries */ void silc_idcache_free(SilcIDCache cache) { @@ -134,13 +135,16 @@ void silc_idcache_free(SilcIDCache cache) } } -/* Add new entry to the cache. */ +/* Add new entry to the cache. Returns TRUE if the entry was added and + FALSE if it could not be added. The `name' is the name associated with + the ID, the `id' the actual ID and the `context' a used specific context. + If the `expire' is TRUE the entry expires in default time and if FALSE + the entry never expires from the cache. */ bool silc_idcache_add(SilcIDCache cache, char *name, void *id, - void *context, int expire) + void *context, int expire, SilcIDCacheEntry *ret) { SilcIDCacheEntry c; - uint32 curtime = time(NULL); SILC_LOG_DEBUG(("Adding cache entry")); @@ -148,7 +152,7 @@ bool silc_idcache_add(SilcIDCache cache, char *name, void *id, c = silc_calloc(1, sizeof(*c)); c->id = id; c->name = name; - c->expire = (expire ? (curtime + SILC_ID_CACHE_EXPIRE) : 0); + c->expire = expire; c->context = context; /* Add the new entry to the hash tables */ @@ -168,6 +172,9 @@ bool silc_idcache_add(SilcIDCache cache, char *name, void *id, silc_hash_table_rehash(cache->context_table, 0); } + if (ret) + *ret = c; + return TRUE; } @@ -193,6 +200,8 @@ bool silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry old) ret = silc_hash_table_del(cache->context_table, old->context); if (old->id) ret = silc_hash_table_del(cache->id_table, old->id); + else + silc_free(old); return ret; } @@ -234,7 +243,8 @@ bool silc_idcache_del_by_id_ext(SilcIDCache cache, void *id, ret = silc_hash_table_del(cache->context_table, c->context); if (c->id) ret = silc_hash_table_del_ext(cache->id_table, c->id, hash, - hash_context, compare, compare_context); + hash_context, compare, compare_context, + NULL, NULL); return ret; } @@ -257,6 +267,8 @@ bool silc_idcache_del_by_context(SilcIDCache cache, void *context) ret = silc_hash_table_del(cache->context_table, c->context); if (c->id) ret = silc_hash_table_del_by_context(cache->id_table, c->id, c); + else + silc_free(c); return ret; } @@ -272,22 +284,38 @@ bool silc_idcache_del_all(SilcIDCache cache) return TRUE; } +static void silc_idcache_destructor_dummy(void *key, void *context, + void *user_context) +{ + /* Dummy - nothing */ +} + /* Foreach callback fro silc_idcache_purge. */ static void silc_idcache_purge_foreach(void *key, void *context, void *user_context) { SilcIDCache cache = (SilcIDCache)user_context; - uint32 curtime = time(NULL); + SilcUInt32 curtime = time(NULL); SilcIDCacheEntry c = (SilcIDCacheEntry)context; if (c->expire && c->expire < curtime) { + /* Remove the entry from the hash tables */ + if (c->name) + silc_hash_table_del_by_context(cache->name_table, c->name, c); + if (c->context) + silc_hash_table_del(cache->context_table, c->context); + if (c->id) + silc_hash_table_del_by_context_ext(cache->id_table, c->id, c, + NULL, NULL, NULL, NULL, + silc_idcache_destructor_dummy, NULL); + /* Call the destructor */ if (cache->destructor) cache->destructor(cache, c); - /* Delete the entry */ - silc_idcache_del(cache, c); + /* Free the entry, it has been deleted from the hash tables */ + silc_free(c); } } @@ -304,24 +332,30 @@ bool silc_idcache_purge(SilcIDCache cache) bool silc_idcache_purge_by_context(SilcIDCache cache, void *context) { - SilcIDCacheEntry entry; + SilcIDCacheEntry c; bool ret = FALSE; if (!silc_hash_table_find(cache->context_table, context, NULL, - (void *)&entry)) + (void *)&c)) return FALSE; + /* Remove the entry from the hash tables */ + if (c->name) + ret = silc_hash_table_del_by_context(cache->name_table, c->name, c); + if (c->context) + ret = silc_hash_table_del(cache->context_table, c->context); + if (c->id) + ret = + silc_hash_table_del_by_context_ext(cache->id_table, c->id, c, + NULL, NULL, NULL, NULL, + silc_idcache_destructor_dummy, NULL); + /* Call the destructor */ if (cache->destructor) - cache->destructor(cache, entry); - - if (entry->name) - ret = silc_hash_table_del_by_context(cache->name_table, entry->name, - entry); - if (entry->context) - ret = silc_hash_table_del(cache->context_table, entry->context); - if (entry->id) - ret = silc_hash_table_del_by_context(cache->id_table, entry->id, entry); + cache->destructor(cache, c); + + /* Free the entry, it has been deleted from the hash tables */ + silc_free(c); return ret; } @@ -472,7 +506,7 @@ static void silc_idcache_list_add(SilcIDCacheList list, SilcIDCacheEntry cache) /* Try to add to static cache */ if (!list->cache_dyn_count) - for (i = 0; i < sizeof(list->cache); i++) { + for (i = 0; i < (sizeof(list->cache) / sizeof(list->cache[0])); i++) { if (!list->cache[i]) { list->cache[i] = cache; list->cache_count++; @@ -492,17 +526,17 @@ static void silc_idcache_list_add(SilcIDCacheList list, SilcIDCacheEntry cache) if (i >= list->cache_dyn_count) { int k; - i += 5; + i = list->cache_dyn_count; list->cache_dyn = silc_realloc(list->cache_dyn, - sizeof(*list->cache) * (i)); + sizeof(*list->cache_dyn) * (i + 5)); /* NULL the reallocated area */ - for (k = list->cache_dyn_count; k < i; k++) + for (k = i; k < (i + 5); k++) list->cache_dyn[k] = NULL; - list->cache_dyn[list->cache_dyn_count] = cache; - list->cache_dyn_count = i; + list->cache_dyn[i] = cache; list->cache_count++; + list->cache_dyn_count += 5; } } @@ -532,25 +566,25 @@ bool silc_idcache_list_first(SilcIDCacheList list, SilcIDCacheEntry *ret) bool silc_idcache_list_next(SilcIDCacheList list, SilcIDCacheEntry *ret) { - int dyn = FALSE; list->pos++; - if (list->pos >= sizeof(list->cache)) { + if (!list->dyn && + list->pos >= (sizeof(list->cache) / sizeof(list->cache[0]))) { list->pos = 0; - dyn = TRUE; + list->dyn = TRUE; } - if (dyn && list->pos >= list->cache_dyn_count) + if (list->dyn && list->pos >= list->cache_dyn_count) return FALSE; - if (!dyn && !list->cache[list->pos]) + if (!list->dyn && !list->cache[list->pos]) return FALSE; - if (dyn && !list->cache_dyn[list->pos]) + if (list->dyn && !list->cache_dyn[list->pos]) return FALSE; if (ret) { - if (!dyn) + if (!list->dyn) *ret = list->cache[list->pos]; else *ret = list->cache_dyn[list->pos]; @@ -559,7 +593,7 @@ bool silc_idcache_list_next(SilcIDCacheList list, SilcIDCacheEntry *ret) return TRUE; } -/* Free's ID cache list. User must free the list object returned by +/* Frees ID cache list. User must free the list object returned by any of the searching functions. */ void silc_idcache_list_free(SilcIDCacheList list)