updates.
[silc.git] / lib / silccore / silcidcache.c
index 02ed07e07ba4fe39ce16b76a8685e507d8b9ae3f..c4b658e80ed02f3827d06ad687de3c154e9577e1 100644 (file)
@@ -90,6 +90,7 @@ struct SilcIDCacheListStruct {
   uint32 cache_dyn_count;
   uint32 cache_count;
   uint32 pos;
+  bool dyn;
 };
 
 /* Allocates new ID cache object. The initial amount of allocated entries
@@ -197,6 +198,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;
 }
@@ -238,7 +241,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;
 }
@@ -261,6 +265,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;
 }
@@ -276,6 +282,12 @@ 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,
@@ -286,12 +298,22 @@ static void silc_idcache_purge_foreach(void *key, void *context,
   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);
   }
 }
 
@@ -308,24 +330,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;
 }
@@ -476,7 +504,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++;
@@ -496,17 +524,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;
   }
 }
 
@@ -536,25 +564,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];