updates. New data types.
[silc.git] / lib / silccore / idcache.c
index b35d23bf0d03ec798c5911db681833ec4f4ecd20..caf6549fc45319a3e7be78c80ff78b0c3cb025d8 100644 (file)
@@ -42,7 +42,7 @@ static void silc_idcache_list_add(SilcIDCacheList list,
        Table of the cache entries allocated by silc_idcache_add function.
        This table is reallocated when new entry is added into the cache.
 
-   unsigned int cache_count
+   uint32 cache_count
 
        Number of cache entries in the cache.
 
@@ -61,12 +61,20 @@ static void silc_idcache_list_add(SilcIDCacheList list,
        is to provide faster access to the cache when searching by data.
        This is updated by silc_idcache_add and sorting functions.
 
+   SilcIDCacheDestructor destructor
+
+       Destructor callback that is called when an cache entry expires or is
+       purged from the ID cache. The application must not free cache entry
+       because the library will do it automatically. The appliation, however,
+       is responsible of freeing any data in the entry.
+
 */
 struct SilcIDCacheStruct {
   SilcIDCacheEntry cache;
-  unsigned int cache_count;
+  uint32 cache_count;
   int sorted;
   int fast_access[256];
+  SilcIDCacheDestructor destructor;
 };
 
 /* 
@@ -86,15 +94,16 @@ struct SilcIDCacheStruct {
 struct SilcIDCacheListStruct {
   SilcIDCacheEntry cache[64];
   SilcIDCacheEntry *cache_dyn;
-  unsigned int cache_dyn_count;
-  unsigned int cache_count;
-  unsigned int pos;
+  uint32 cache_dyn_count;
+  uint32 cache_count;
+  uint32 pos;
 };
 
 /* Allocates new ID cache object. The initial amount of allocated entries
    can be sent as argument. If `count' is 0 the system uses default values. */
 
-SilcIDCache silc_idcache_alloc(unsigned int count)
+SilcIDCache silc_idcache_alloc(uint32 count,
+                              SilcIDCacheDestructor destructor)
 {
   SilcIDCache cache;
 
@@ -104,6 +113,7 @@ SilcIDCache silc_idcache_alloc(unsigned int count)
   cache->cache = silc_calloc(count ? count : 5, sizeof(*cache->cache));
   cache->cache_count = count ? count : 5;
   memset(cache->fast_access, -1, sizeof(cache->fast_access));
+  cache->destructor = destructor;
 
   return cache;
 }
@@ -190,12 +200,14 @@ int silc_idcache_find_by_data(SilcIDCache cache, unsigned char *data,
       break;
 
     if (cache->cache[i].data && 
-       !memcmp(cache->cache[i].data, data, strlen(cache->cache[i].data)))
+       !memcmp(cache->cache[i].data, data, cache->cache[i].data_len))
       silc_idcache_list_add(list, &(cache->cache[i]));
   }
 
-  if (!silc_idcache_list_count(list))
+  if (!silc_idcache_list_count(list)) {
+    silc_idcache_list_free(list);
     return FALSE;
+  }
 
   if (ret)
     *ret = list;
@@ -226,7 +238,7 @@ int silc_idcache_find_by_data_one(SilcIDCache cache, unsigned char *data,
 
   for (i = i; i < cache->cache_count; i++)
     if (cache->cache[i].data && 
-       !memcmp(cache->cache[i].data, data, strlen(cache->cache[i].data))) {
+       !memcmp(cache->cache[i].data, data, cache->cache[i].data_len)) {
       if (ret)
        *ret = &(cache->cache[i]);
       return TRUE;
@@ -285,8 +297,10 @@ int silc_idcache_find_by_data_loose(SilcIDCache cache, unsigned char *data,
     }
   }
     
-  if (!silc_idcache_list_count(list))
+  if (!silc_idcache_list_count(list)) {
+    silc_idcache_list_free(list);
     return FALSE;
+  }
 
   if (ret)
     *ret = list;
@@ -322,8 +336,10 @@ int silc_idcache_find_by_id(SilcIDCache cache, void *id, SilcIdType type,
        silc_idcache_list_add(list, &(cache->cache[i]));
   }
 
-  if (!silc_idcache_list_count(list))
+  if (!silc_idcache_list_count(list)) {
+    silc_idcache_list_free(list);
     return FALSE;
+  }
 
   if (ret)
     *ret = list;
@@ -381,12 +397,12 @@ int silc_idcache_find_by_context(SilcIDCache cache, void *context,
    however, it is not mandatory. */
 
 int silc_idcache_add(SilcIDCache cache, unsigned char *data, 
-                    SilcIdType id_type,
-                    void *id, void *context, int sort)
+                    uint32 data_len, SilcIdType id_type, void *id, 
+                    void *context, int sort, int expire)
 {
   int i;
-  unsigned int count;
-  unsigned long curtime = time(NULL);
+  uint32 count;
+  uint32 curtime = time(NULL);
   SilcIDCacheEntry c;
 
   if (!cache || !cache->cache)
@@ -410,9 +426,10 @@ int silc_idcache_add(SilcIDCache cache, unsigned char *data,
   for (i = 0; i < count; i++) {
     if (c[i].data == NULL && c[i].id == NULL) {
       c[i].data = data;
+      c[i].data_len = data_len;
       c[i].type = id_type;
       c[i].id = id;
-      c[i].expire = curtime + SILC_ID_CACHE_EXPIRE;
+      c[i].expire = (expire ? (curtime + SILC_ID_CACHE_EXPIRE) : 0);
       c[i].context = context;
       break;
     }
@@ -425,9 +442,10 @@ int silc_idcache_add(SilcIDCache cache, unsigned char *data,
       c[i].id = NULL;
     }
     c[count].data = data;
+    c[count].data_len = data_len;
     c[count].type = id_type;
     c[count].id = id;
-    c[count].expire = curtime + SILC_ID_CACHE_EXPIRE;
+    c[count].expire = (expire ? (curtime + SILC_ID_CACHE_EXPIRE) : 0);
     c[count].context = context;
     count += 5;
   }
@@ -502,7 +520,7 @@ int silc_idcache_del_all(SilcIDCache cache)
 int silc_idcache_purge(SilcIDCache cache)
 {
   SilcIDCacheEntry c;
-  unsigned long curtime = time(NULL);
+  uint32 curtime = time(NULL);
   int i;
 
   if (!cache || !cache->cache)
@@ -511,8 +529,12 @@ int silc_idcache_purge(SilcIDCache cache)
   c = cache->cache;
 
   for (i = 0; i < cache->cache_count; i++) {
-    if (c[i].data && 
-       (c[i].expire == 0 || c[i].expire < curtime)) {
+    if (c[i].data && c[i].expire && c[i].expire < curtime) {
+
+      /* Call the destructor */
+      if (cache->destructor)
+       cache->destructor(cache, &c[i]);
+
       c[i].id = NULL;
       c[i].data = NULL;
       c[i].type = 0;
@@ -524,6 +546,27 @@ int silc_idcache_purge(SilcIDCache cache)
   return TRUE;
 }
 
+/* Purges the specific entry by context. */
+
+int silc_idcache_purge_by_context(SilcIDCache cache, void *context)
+{
+  SilcIDCacheEntry entry;
+
+  if (!silc_idcache_find_by_context(cache, context, &entry))
+    return FALSE;
+
+  /* Call the destructor */
+  if (cache->destructor)
+    cache->destructor(cache, entry);
+  
+  entry->id = NULL;
+  entry->data = NULL;
+  entry->type = 0;
+  entry->expire = 0;
+  entry->context = NULL;
+  return TRUE;
+}
+
 /* Allocates ID cache list. */
 
 static SilcIDCacheList silc_idcache_list_alloc()