GNU General Public License for more details.
*/
-/*
- * $Id$
- * $Log$
- * Revision 1.3 2000/07/12 05:54:01 priikone
- * Major rewrite of whole ID Cache system.
- *
- * Revision 1.2 2000/07/05 06:06:35 priikone
- * Global cosmetic change.
- *
- * Revision 1.1.1.1 2000/06/27 11:36:55 priikone
- * Imported from internal CVS/Added Log headers.
- *
- *
- */
+/* $Id$ */
#include "silcincludes.h"
#include "idcache.h"
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.
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;
};
/*
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;
- SILC_LOG_DEBUG(("Allocating new cache")),
+ SILC_LOG_DEBUG(("Allocating new cache"));
cache = silc_calloc(1, sizeof(*cache));
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;
}
/* Find ID Cache entry by data. The data maybe anything that must
match exactly. Returns list of cache entries. */
-int silc_idcache_find_by_data(SilcIDCache cache, char *data,
+int silc_idcache_find_by_data(SilcIDCache cache, unsigned char *data,
SilcIDCacheList *ret)
{
int i;
else
i = 0;
+ if (i == -1)
+ i = 0;
+
for (i = i; i < cache->cache_count; i++) {
if (cache->sorted && cache->cache[i].data &&
cache->cache[i].data[0] != data[0])
break;
if (cache->cache[i].data &&
- !memcmp(cache->cache[i].data, data, strlen(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;
/* Find ID Cache entry by data. The data maybe anything that must
match exactly. Returns one cache entry. */
-int silc_idcache_find_by_data_one(SilcIDCache cache, char *data,
+int silc_idcache_find_by_data_one(SilcIDCache cache, unsigned char *data,
SilcIDCacheEntry *ret)
{
int i;
else
i = 0;
+ if (i == -1)
+ i = 0;
+
for (i = i; i < cache->cache_count; i++)
if (cache->cache[i].data &&
- !memcmp(cache->cache[i].data, data, strlen(data))) {
+ !memcmp(cache->cache[i].data, data, cache->cache[i].data_len)) {
if (ret)
*ret = &(cache->cache[i]);
return TRUE;
match. This ignores data case-sensitivity when searching with this
function. Returns list of cache entries. */
-int silc_idcache_find_by_data_loose(SilcIDCache cache, char *data,
+int silc_idcache_find_by_data_loose(SilcIDCache cache, unsigned char *data,
SilcIDCacheList *ret)
{
int i, c;
else
i = 0;
+ if (i == -1)
+ i = 0;
+
for (i = i; i < cache->cache_count; i++) {
if (cache->sorted && cache->cache[i].data &&
cache->cache[i].data[0] != (char)c)
}
}
- if (!silc_idcache_list_count(list))
+ if (!silc_idcache_list_count(list)) {
+ silc_idcache_list_free(list);
return FALSE;
+ }
if (ret)
*ret = list;
return TRUE;
}
-/* Find ID Cache entry by ID. Returns list of cache entries. */
-/* XXX this may be useless, need for list really? */
+/* Find ID Cache entry by ID. Returns list of cache entries. If `id' is
+ SILC_ID_CACHE_ANY this returns all ID's of type `type'. */
int silc_idcache_find_by_id(SilcIDCache cache, void *id, SilcIdType type,
SilcIDCacheList *ret)
{
- int i, id_len;
+ int i;
SilcIDCacheList list;
if (!cache || !cache->cache || !id)
return FALSE;
- id_len = silc_id_get_len(type);
-
list = silc_idcache_list_alloc();
- for (i = 0; i < cache->cache_count; i++)
- if (cache->cache[i].id && !memcmp(cache->cache[i].id, id, id_len))
- silc_idcache_list_add(list, &(cache->cache[i]));
+ if (id != SILC_ID_CACHE_ANY) {
+ for (i = 0; i < cache->cache_count; i++)
+ if (cache->cache[i].id && SILC_ID_COMPARE_TYPE(cache->cache[i].id,
+ id, type))
+ silc_idcache_list_add(list, &(cache->cache[i]));
+ } else {
+ for (i = 0; i < cache->cache_count; i++)
+ if (cache->cache[i].id && cache->cache[i].type == 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;
int silc_idcache_find_by_id_one(SilcIDCache cache, void *id, SilcIdType type,
SilcIDCacheEntry *ret)
{
- int i, id_len;
+ int i;
if (!cache || !cache->cache || !id)
return FALSE;
- id_len = silc_id_get_len(type);
-
for (i = 0; i < cache->cache_count; i++)
- if (cache->cache[i].id && !memcmp(cache->cache[i].id, id, id_len)) {
+ if (cache->cache[i].id && SILC_ID_COMPARE_TYPE(cache->cache[i].id,
+ id, type)) {
if (ret)
*ret = &(cache->cache[i]);
return TRUE;
cache must be sorted in order for the fast access feature to work,
however, it is not mandatory. */
-int silc_idcache_add(SilcIDCache cache, char *data, SilcIdType id_type,
- void *id, void *context, int sort)
+int silc_idcache_add(SilcIDCache cache, unsigned char *data,
+ 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)
return FALSE;
for (i = 0; i < count; i++) {
- if (c[i].data == NULL) {
+ 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;
}
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;
}
/* XXX */
-int silc_idcache_del_by_data(SilcIDCache cache, char *data)
+int silc_idcache_del_by_data(SilcIDCache cache, unsigned char *data)
{
return TRUE;
int silc_idcache_del_by_id(SilcIDCache cache, SilcIdType type, void *id)
{
- int i, id_len;
+ int i;
if (!cache || !cache->cache || !id)
return FALSE;
- id_len = silc_id_get_len(type);
-
for (i = 0; i < cache->cache_count; i++)
- if (cache->cache[i].id && !memcmp(cache->cache[i].id, id, id_len)) {
+ if (cache->cache[i].id && SILC_ID_COMPARE_TYPE(cache->cache[i].id,
+ id, type)) {
cache->cache[i].id = NULL;
cache->cache[i].data = NULL;
cache->cache[i].type = 0;
int silc_idcache_purge(SilcIDCache cache)
{
SilcIDCacheEntry c;
- unsigned long curtime = time(NULL);
+ uint32 curtime = time(NULL);
int i;
if (!cache || !cache->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;
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()