[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b
aCaB
acab at clamav.net
Sun Apr 4 01:14:21 UTC 2010
The following commit has been merged in the debian/unstable branch:
commit 5b95022bbf9ab0367192a448a8198c7efa4bc962
Author: aCaB <acab at clamav.net>
Date: Sat Jan 9 02:19:25 2010 +0100
splay
diff --git a/libclamav/cache.c b/libclamav/cache.c
index 43236cc..ec1fe7b 100644
--- a/libclamav/cache.c
+++ b/libclamav/cache.c
@@ -33,7 +33,12 @@
#include "cache.h"
#include "fmap.h"
+static mpool_t *mempool = NULL;
+
+//#define USE_LRUHASHCACHE
+#define USE_SPLAY
+#ifdef USE_LRUHASHCACHE
struct cache_key {
char digest[16];
uint32_t size; /* 0 is used to mark an empty hash slot! */
@@ -90,40 +95,14 @@ static void cacheset_lru_remove(struct cache_set *map, size_t howmany)
}
}
-static inline uint32_t hash32shift(uint32_t key)
-{
- key = ~key + (key << 15);
- key = key ^ (key >> 12);
- key = key + (key << 2);
- key = key ^ (key >> 4);
- key = (key + (key << 3)) + (key << 11);
- key = key ^ (key >> 16);
- return key;
-}
-
-static inline size_t hash(const unsigned char* k,const size_t len,const size_t SIZE)
-{
- size_t Hash = 1;
- size_t i;
- for(i=0;i<len;i++) {
- /* a simple add is good, because we use the mixing function below */
- Hash += k[i];
- /* mixing function */
- Hash = hash32shift(Hash);
- }
- /* SIZE is power of 2 */
- return Hash & (SIZE - 1);
-}
-
-int cacheset_lookup_internal(struct cache_set *map, const struct cache_key *key,
- uint32_t *insert_pos, int deletedok)
+int cacheset_lookup_internal(struct cache_set *map, unsigned char *md5, size_t size, uint32_t *insert_pos, int deletedok)
{
- uint32_t idx = hash((const unsigned char*)key, sizeof(*key), map->capacity);
+ uint32_t idx = cli_readint32(md5+8) & (map->capacity -1);
uint32_t tries = 0;
struct cache_key *k = &map->data[idx];
while (k->size != CACHE_KEY_EMPTY) {
- if (k->size == key->size &&
- !memcmp(k->digest, key, 16)) {
+ if (k->size == size &&
+ !memcmp(k->digest, md5, 16)) {
/* found key */
*insert_pos = idx;
return 1;
@@ -162,7 +141,7 @@ static inline void lru_addtail(struct cache_set *map, struct cache_key *newkey)
map->lru_tail = newkey;
}
-static void cacheset_add(struct cache_set *map, const struct cache_key *key)
+static void cacheset_add(struct cache_set *map, unsigned char *md5, size_t size)
{
int ret;
uint32_t pos;
@@ -171,28 +150,28 @@ static void cacheset_add(struct cache_set *map, const struct cache_key *key)
cacheset_lru_remove(map, 1);
assert(map->elements < map->maxelements);
- ret = cacheset_lookup_internal(map, key, &pos, 1);
+ ret = cacheset_lookup_internal(map, md5, size, &pos, 1);
newkey = &map->data[pos];
if (ret) {
/* was already added, remove from LRU list */
lru_remove(map, newkey);
}
/* add new key to tail of LRU list */
- memcpy(&map->data[pos], key, sizeof(*key));
+ memcpy(&map->data[pos].digest, md5, sizeof(map->data[pos].digest));
+ map->data[pos].size = size;
lru_addtail(map, newkey);
map->elements++;
assert(pos < map->maxelements);
-
}
-static int cacheset_lookup(struct cache_set *map, const struct cache_key *key)
+static int cacheset_lookup(struct cache_set *map, unsigned char *md5, size_t size)
{
struct cache_key *newkey;
int ret;
uint32_t pos;
- ret = cacheset_lookup_internal(map, key, &pos, 0);
+ ret = cacheset_lookup_internal(map, md5, size, &pos, 0);
if (!ret)
return CACHE_INVALID_VERSION;
newkey = &map->data[pos];
@@ -203,13 +182,137 @@ static int cacheset_lookup(struct cache_set *map, const struct cache_key *key)
return map->version;
}
-static mpool_t *mempool = NULL;
-static struct CACHE {
- struct cache_set cacheset;
- pthread_mutex_t mutex;
- uint32_t lastdb;
-} *cache = NULL;
-static unsigned int cache_entries = 0;
+
+static int cacheset_init(struct cache_set *map, unsigned int entries) {
+ map->data = mpool_calloc(mempool, 256, sizeof(*map->data));
+ if (!map->data)
+ return CL_EMEM;
+ map->capacity = entries;
+ map->maxelements = 80*entries / 100;
+ map->elements = 0;
+ map->version = CACHE_INVALID_VERSION;
+ map->lru_head = map->lru_tail = NULL;
+ map->version = 1337;
+ return 0;
+}
+
+#else
+#ifdef USE_SPLAY
+struct node {
+ uint64_t digest[2];
+ struct node *left;
+ struct node *right;
+ uint32_t size; /* 0 is used to mark an empty hash slot! */
+};
+
+struct cache_set {
+ struct node *data;
+ struct node *root;
+ unsigned int used;
+ unsigned int total;
+};
+
+static int cacheset_init(struct cache_set *map, unsigned int entries) {
+ map->data = mpool_calloc(mempool, entries, sizeof(*map->data));
+ map->root = NULL;
+
+ if(!map->data)
+ return CL_EMEM;
+ map->used = 0;
+ map->total = entries;
+ return 0;
+}
+
+void splay(uint64_t *md5, struct cache_set *cs) {
+ struct node next = {{0, 0}, NULL, NULL, 0}, *right = &next, *left = &next, *temp, *root = cs->root;
+
+ if(!root)
+ return;
+
+ while(1) {
+ if(md5[1] < root->digest[1] || md5[1] == root->digest[1] && md5[0] < root->digest[0]) {
+ if(!root->left) break;
+ if(md5[1] < root->left->digest[1] || md5[1] == root->left->digest[1] && md5[0] < root->left->digest[0]) {
+ temp = root->left;
+ root->left = temp->right;
+ temp->right = root;
+ root = temp;
+ if (!root->left) break;
+ }
+ right->left = root;
+ right = root;
+ root = root->left;
+ } else if(md5[1] > root->digest[1] || md5[1] == root->digest[1] && md5[0] > root->digest[0]) {
+ if(!root->right) break;
+ if(md5[1] > root->right->digest[1] || md5[1] == root->right->digest[1] && md5[0] > root->right->digest[0]) {
+ temp = root->right;
+ root->right = temp->left;
+ temp->left = root;
+ root = temp;
+ if(!root->right) break;
+ }
+ left->right = root;
+ left = root;
+ root = root->right;
+ } else break;
+ }
+ left->right = root->left;
+ right->left = root->right;
+ root->left = next.right;
+ root->right = next.left;
+ cs->root = root;
+}
+
+
+static int cacheset_lookup(struct cache_set *cs, unsigned char *md5, size_t size) {
+ uint64_t hash[2];
+
+ memcpy(hash, md5, 16);
+ splay(hash, cs);
+ if(!cs->root || cs->root->digest[1] != hash[1] || cs->root->digest[0] != hash[0])
+ return 0;
+ return 1337;
+}
+
+
+static void cacheset_add(struct cache_set *cs, unsigned char *md5, size_t size) {
+ uint64_t hash[2];
+ struct node *newnode;
+
+ memcpy(hash, md5, 16);
+ splay(hash, cs);
+ if(cs->root && cs->root->digest[1] == hash[1] && cs->root->digest[0] == hash[0])
+ return; /* Already there */
+
+ if(cs->used == cs->total) {
+ /* FIXME: drop something */
+ cli_errmsg("FULL!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+ return;
+ } else {
+ newnode = &cs->data[cs->used++];
+ }
+
+ if(!cs->root) {
+ newnode->left = NULL;
+ newnode->right = NULL;
+ } else if(hash[1] < cs->root->digest[1] || hash[1] == cs->root->digest[1] && hash[0] < cs->root->digest[0]) {
+ newnode->left = cs->root->left;
+ newnode->right = cs->root;
+ cs->root->left = NULL;
+ } else {
+ newnode->right = cs->root->right;
+ newnode->left = cs->root;
+ cs->root->right = NULL;
+ }
+ newnode->digest[0] = hash[0];
+ newnode->digest[1] = hash[1];
+ cs->root = newnode;
+}
+
+
+#endif /* USE_SPLAY */
+#endif /* USE_LRUHASHCACHE */
+
#define TREES 256
static inline unsigned int getkey(uint8_t *hash) { return *hash; }
@@ -220,11 +323,17 @@ static inline unsigned int getkey(uint8_t *hash) { return *hash; }
/* #define TREES 65536 */
/* static inline unsigned int getkey(uint8_t *hash) { return hash[0] | (((unsigned int)hash[1])<<8) ; } */
+static struct CACHE {
+ struct cache_set cacheset;
+ pthread_mutex_t mutex;
+ uint32_t lastdb;
+} *cache = NULL;
+
int cl_cache_init(unsigned int entries) {
unsigned int i;
+ int ret;
- entries = MAX(entries / (TREES / 256), 10);
if(!(mempool = mpool_create())) {
cli_errmsg("mpool init fail\n");
return 1;
@@ -244,23 +353,19 @@ int cl_cache_init(unsigned int entries) {
cache = NULL;
return 1;
}
-
- cache[i].cacheset.data = mpool_calloc(mempool, 256, sizeof(*cache[i].cacheset.data));
- if (!cache[i].cacheset.data)
- return CL_EMEM;
- cache_setversion(&cache[i].cacheset, 1337);
- cache[i].cacheset.capacity = 256;
- cache[i].cacheset.maxelements = 80*256 / 100;
- cache[i].cacheset.elements = 0;
- cache[i].cacheset.version = CACHE_INVALID_VERSION;
- cache[i].cacheset.lru_head = cache[i].cacheset.lru_tail = NULL;
+ ret = cacheset_init(&cache[i].cacheset, entries);
+ if(ret) {
+ mpool_destroy(mempool);
+ mempool = NULL;
+ cache = NULL;
+ return 1;
+ }
}
- cache_entries = entries;
return 0;
}
+
static int cache_lookup_hash(unsigned char *md5, cli_ctx *ctx) {
- struct cache_key entry;
int ret = CL_VIRUS;
unsigned int key = getkey(md5);
struct CACHE *c;
@@ -272,16 +377,14 @@ static int cache_lookup_hash(unsigned char *md5, cli_ctx *ctx) {
cli_errmsg("mutex lock fail\n");
return ret;
}
- entry.size = 1024;
- memcpy(entry.digest, md5, 16);
- ret = (cacheset_lookup(&c->cacheset, &entry) == 1337) ? CL_CLEAN : CL_VIRUS;
- pthread_mutex_unlock(&c->mutex);
+
+ ret = (cacheset_lookup(&c->cacheset, md5, 1024) == 1337) ? CL_CLEAN : CL_VIRUS;
if(ret == CL_CLEAN) cli_warnmsg("cached\n");
+ pthread_mutex_unlock(&c->mutex);
return ret;
}
void cache_add(unsigned char *md5, cli_ctx *ctx) {
- struct cache_key entry;
unsigned int key = getkey(md5);
struct CACHE *c;
@@ -292,9 +395,9 @@ void cache_add(unsigned char *md5, cli_ctx *ctx) {
cli_errmsg("mutex lock fail\n");
return;
}
- entry.size = 1024;
- memcpy(entry.digest, md5, 16);
- cacheset_add(&c->cacheset, &entry);
+
+ cacheset_add(&c->cacheset, md5, 1024);
+
pthread_mutex_unlock(&c->mutex);
return;
}
--
Debian repository for ClamAV
More information about the Pkg-clamav-commits
mailing list