... | ... |
@@ -38,10 +38,9 @@ |
38 | 38 |
#include "cache.h" |
39 | 39 |
#include "fmap.h" |
40 | 40 |
|
41 |
-static mpool_t *mempool = NULL; |
|
41 |
+#define NODES 256 |
|
42 | 42 |
|
43 |
-//#define DONT_CACHE |
|
44 |
-//#define USE_LRUHASHCACHE |
|
43 |
+/*#define USE_LRUHASHCACHE*/ |
|
45 | 44 |
#define USE_SPLAY |
46 | 45 |
|
47 | 46 |
#ifdef USE_LRUHASHCACHE |
... | ... |
@@ -53,38 +52,23 @@ struct cache_key { |
53 | 53 |
|
54 | 54 |
struct cache_set { |
55 | 55 |
struct cache_key *data; |
56 |
- size_t capacity; |
|
57 | 56 |
size_t maxelements; /* considering load factor */ |
58 | 57 |
size_t maxdeleted; |
59 | 58 |
size_t elements; |
60 | 59 |
size_t deleted; |
61 |
- size_t version; |
|
62 | 60 |
struct cache_key *lru_head, *lru_tail; |
63 | 61 |
}; |
64 | 62 |
|
65 |
-#define CACHE_INVALID_VERSION ~0u |
|
66 | 63 |
#define CACHE_KEY_DELETED ~0u |
67 | 64 |
#define CACHE_KEY_EMPTY 0 |
68 | 65 |
|
69 |
-static void cache_setversion(struct cache_set* map, uint32_t version) |
|
70 |
-{ |
|
71 |
- unsigned i; |
|
72 |
- if (map->version == version) |
|
73 |
- return; |
|
74 |
- map->version = version; |
|
75 |
- map->elements = 0; /* all elements have expired now */ |
|
76 |
- for (i=0;i<map->capacity;i++) |
|
77 |
- map->data[i].size = 0; |
|
78 |
- map->lru_head = map->lru_tail = NULL; |
|
79 |
-} |
|
80 |
- |
|
81 | 66 |
static void cacheset_lru_remove(struct cache_set *map, size_t howmany) |
82 | 67 |
{ |
83 | 68 |
while (howmany--) { |
84 | 69 |
struct cache_key *old; |
85 | 70 |
assert(map->lru_head); |
86 | 71 |
assert(!old->lru_prev); |
87 |
- // Remove a key from the head of the list |
|
72 |
+ /* Remove a key from the head of the list */ |
|
88 | 73 |
old = map->lru_head; |
89 | 74 |
map->lru_head = old->lru_next; |
90 | 75 |
old->size = CACHE_KEY_DELETED; |
... | ... |
@@ -110,7 +94,7 @@ static inline int cacheset_lookup_internal(struct cache_set *map, |
110 | 110 |
uint32_t *insert_pos, int deletedok) |
111 | 111 |
{ |
112 | 112 |
const struct cache_key*data = map->data; |
113 |
- uint32_t capmask = map->capacity - 1; |
|
113 |
+ uint32_t capmask = NODES - 1; |
|
114 | 114 |
const struct cache_key *k; |
115 | 115 |
uint32_t idx, tries = 0; |
116 | 116 |
uint64_t md5_0, md5_1; |
... | ... |
@@ -165,24 +149,24 @@ static inline void lru_addtail(struct cache_set *map, struct cache_key *newkey) |
165 | 165 |
|
166 | 166 |
static pthread_mutex_t pool_mutex = PTHREAD_MUTEX_INITIALIZER; |
167 | 167 |
|
168 |
-static void cacheset_add(struct cache_set *map, unsigned char *md5, size_t size); |
|
169 |
-static int cacheset_init(struct cache_set *map, unsigned int entries); |
|
168 |
+static void cacheset_add(struct cache_set *map, unsigned char *md5, size_t size, mpool_t *mempool); |
|
169 |
+static int cacheset_init(struct cache_set *map, mpool_t *mempool); |
|
170 | 170 |
|
171 |
-static void cacheset_rehash(struct cache_set *map) |
|
171 |
+static void cacheset_rehash(struct cache_set *map, mpool_t *mempool) |
|
172 | 172 |
{ |
173 | 173 |
unsigned i; |
174 | 174 |
int ret; |
175 | 175 |
struct cache_set tmp_set; |
176 | 176 |
struct cache_key *key; |
177 | 177 |
pthread_mutex_lock(&pool_mutex); |
178 |
- ret = cacheset_init(&tmp_set, map->capacity); |
|
178 |
+ ret = cacheset_init(&tmp_set, mempool); |
|
179 | 179 |
pthread_mutex_unlock(&pool_mutex); |
180 | 180 |
if (ret) |
181 | 181 |
return; |
182 | 182 |
|
183 | 183 |
key = map->lru_head; |
184 | 184 |
for (i=0;key && i < tmp_set.maxelements/2;i++) { |
185 |
- cacheset_add(&tmp_set, (unsigned char*)&key->digest, key->size); |
|
185 |
+ cacheset_add(&tmp_set, (unsigned char*)&key->digest, key->size, mempool); |
|
186 | 186 |
key = key->lru_next; |
187 | 187 |
} |
188 | 188 |
pthread_mutex_lock(&pool_mutex); |
... | ... |
@@ -191,7 +175,7 @@ static void cacheset_rehash(struct cache_set *map) |
191 | 191 |
memcpy(map, &tmp_set, sizeof(tmp_set)); |
192 | 192 |
} |
193 | 193 |
|
194 |
-static void cacheset_add(struct cache_set *map, unsigned char *md5, size_t size) |
|
194 |
+static void cacheset_add(struct cache_set *map, unsigned char *md5, size_t size, mpool_t *mempool) |
|
195 | 195 |
{ |
196 | 196 |
int ret; |
197 | 197 |
uint32_t pos; |
... | ... |
@@ -200,7 +184,7 @@ static void cacheset_add(struct cache_set *map, unsigned char *md5, size_t size) |
200 | 200 |
if (map->elements >= map->maxelements) { |
201 | 201 |
cacheset_lru_remove(map, 1); |
202 | 202 |
if (map->deleted >= map->maxdeleted) { |
203 |
- cacheset_rehash(map); |
|
203 |
+ cacheset_rehash(map, mempool); |
|
204 | 204 |
} |
205 | 205 |
} |
206 | 206 |
assert(map->elements < map->maxelements); |
... | ... |
@@ -231,27 +215,30 @@ static int cacheset_lookup(struct cache_set *map, unsigned char *md5, size_t siz |
231 | 231 |
|
232 | 232 |
ret = cacheset_lookup_internal(map, md5, size, &pos, 0); |
233 | 233 |
if (!ret) |
234 |
- return CACHE_INVALID_VERSION; |
|
234 |
+ return 0; |
|
235 | 235 |
newkey = &map->data[pos]; |
236 | 236 |
/* update LRU position: move to tail */ |
237 | 237 |
lru_remove(map, newkey); |
238 | 238 |
lru_addtail(map, newkey); |
239 |
- return map->version; |
|
239 |
+ return 1; |
|
240 | 240 |
} |
241 | 241 |
|
242 |
-static int cacheset_init(struct cache_set *map, unsigned int entries) { |
|
243 |
- map->data = mpool_calloc(mempool, entries, sizeof(*map->data)); |
|
242 |
+static int cacheset_init(struct cache_set *map, mpool_t *mempool) { |
|
243 |
+ map->data = mpool_calloc(mempool, NODES, sizeof(*map->data)); |
|
244 | 244 |
if (!map->data) |
245 | 245 |
return CL_EMEM; |
246 |
- map->capacity = entries; |
|
247 |
- map->maxelements = 80*entries / 100; |
|
248 |
- map->maxdeleted = map->capacity - map->maxelements - 1; |
|
246 |
+ map->maxelements = 80 * NODES / 100; |
|
247 |
+ map->maxdeleted = NODES - map->maxelements - 1; |
|
249 | 248 |
map->elements = 0; |
250 |
- map->version = CACHE_INVALID_VERSION; |
|
251 | 249 |
map->lru_head = map->lru_tail = NULL; |
252 |
- map->version = 1337; |
|
253 | 250 |
return 0; |
254 | 251 |
} |
252 |
+ |
|
253 |
+static inline void cacheset_destroy(struct cache_set *cs, mpool_t *mempool) { |
|
254 |
+ mpool_free(mempool, cs->data); |
|
255 |
+ cs->data = NULL; |
|
256 |
+} |
|
257 |
+ |
|
255 | 258 |
#endif /* USE_LRUHASHCACHE */ |
256 | 259 |
|
257 | 260 |
#ifdef USE_SPLAY |
... | ... |
@@ -272,25 +259,30 @@ struct cache_set { |
272 | 272 |
struct node *last; |
273 | 273 |
}; |
274 | 274 |
|
275 |
-static int cacheset_init(struct cache_set *cs, unsigned int entries) { |
|
275 |
+static int cacheset_init(struct cache_set *cs, mpool_t *mempool) { |
|
276 | 276 |
unsigned int i; |
277 |
- cs->data = mpool_calloc(mempool, entries, sizeof(*cs->data)); |
|
277 |
+ cs->data = mpool_calloc(mempool, NODES, sizeof(*cs->data)); |
|
278 | 278 |
cs->root = NULL; |
279 | 279 |
|
280 | 280 |
if(!cs->data) |
281 |
- return CL_EMEM; |
|
281 |
+ return 1; |
|
282 | 282 |
|
283 |
- for(i=1; i<entries; i++) { |
|
283 |
+ for(i=1; i<NODES; i++) { |
|
284 | 284 |
cs->data[i-1].next = &cs->data[i]; |
285 | 285 |
cs->data[i].prev = &cs->data[i-1]; |
286 | 286 |
} |
287 | 287 |
|
288 | 288 |
cs->first = cs->data; |
289 |
- cs->last = &cs->data[entries-1]; |
|
289 |
+ cs->last = &cs->data[NODES-1]; |
|
290 | 290 |
|
291 | 291 |
return 0; |
292 | 292 |
} |
293 | 293 |
|
294 |
+static inline void cacheset_destroy(struct cache_set *cs, mpool_t *mempool) { |
|
295 |
+ mpool_free(mempool, cs->data); |
|
296 |
+ cs->data = NULL; |
|
297 |
+} |
|
298 |
+ |
|
294 | 299 |
static inline int cmp(int64_t *a, int64_t *b) { |
295 | 300 |
if(a[1] < b[1]) return -1; |
296 | 301 |
if(a[1] > b[1]) return 1; |
... | ... |
@@ -304,14 +296,14 @@ static inline int cmp(int64_t *a, int64_t *b) { |
304 | 304 |
/* } */ |
305 | 305 |
|
306 | 306 |
|
307 |
-//#define PRINT_TREE |
|
307 |
+/*#define PRINT_TREE*/ |
|
308 | 308 |
#ifdef PRINT_TREE |
309 | 309 |
#define ptree printf |
310 | 310 |
#else |
311 | 311 |
#define ptree (void) |
312 | 312 |
#endif |
313 | 313 |
|
314 |
-//#define CHECK_TREE |
|
314 |
+/*#define CHECK_TREE*/ |
|
315 | 315 |
#ifdef CHECK_TREE |
316 | 316 |
static int printtree(struct cache_set *cs, struct node *n, int d) { |
317 | 317 |
int i; |
... | ... |
@@ -355,9 +347,7 @@ static int printtree(struct cache_set *cs, struct node *n, int d) { |
355 | 355 |
return ab; |
356 | 356 |
} |
357 | 357 |
#else |
358 |
-static inline int printtree(struct cache_set *cs, struct node *n, int d) { |
|
359 |
- return 0; |
|
360 |
-} |
|
358 |
+#define printtree(a,b,c) (0) |
|
361 | 359 |
#endif |
362 | 360 |
|
363 | 361 |
static int splay(int64_t *md5, struct cache_set *cs) { |
... | ... |
@@ -484,7 +474,7 @@ static int cacheset_lookup(struct cache_set *cs, unsigned char *md5, size_t size |
484 | 484 |
printf("\n"); |
485 | 485 |
} |
486 | 486 |
#endif |
487 |
- return 1337; |
|
487 |
+ return 1; |
|
488 | 488 |
} |
489 | 489 |
return 0; |
490 | 490 |
} |
... | ... |
@@ -503,7 +493,7 @@ static void cacheset_add(struct cache_set *cs, unsigned char *md5, size_t size) |
503 | 503 |
} |
504 | 504 |
|
505 | 505 |
newnode = cs->first; |
506 |
- //#define TAKE_FIRST |
|
506 |
+ /*#define TAKE_FIRST*/ |
|
507 | 507 |
#ifdef TAKE_FIRST |
508 | 508 |
if((newnode->left || newnode->right || newnode->up)) { |
509 | 509 |
if(!splay(newnode->digest, cs)) { |
... | ... |
@@ -616,90 +606,71 @@ static inline unsigned int getkey(uint8_t *hash) { return *hash; } |
616 | 616 |
/* #define TREES 65536 */ |
617 | 617 |
/* static inline unsigned int getkey(uint8_t *hash) { return hash[0] | (((unsigned int)hash[1])<<8) ; } */ |
618 | 618 |
|
619 |
-static struct CACHE { |
|
619 |
+struct CACHE { |
|
620 | 620 |
struct cache_set cacheset; |
621 | 621 |
pthread_mutex_t mutex; |
622 |
- uint32_t lastdb; |
|
623 |
-} *cache = NULL; |
|
624 |
- |
|
625 |
- |
|
626 |
-static int cache_lookup_hash(unsigned char *md5, cli_ctx *ctx); |
|
622 |
+}; |
|
627 | 623 |
|
628 |
-int cl_cache_init(unsigned int entries) { |
|
629 |
- unsigned int i; |
|
630 |
- int ret; |
|
631 | 624 |
|
632 |
-#ifndef DONT_CACHE |
|
633 |
- if(!entries) |
|
634 |
-#endif |
|
635 |
- return 0; |
|
625 |
+int cli_cache_init(struct cl_engine *engine) { |
|
626 |
+ static struct CACHE *cache; |
|
627 |
+ unsigned int i, j; |
|
636 | 628 |
|
637 |
- if(!(mempool = mpool_create())) { |
|
638 |
- cli_errmsg("mpool init fail\n"); |
|
629 |
+ if(!engine) { |
|
630 |
+ cli_errmsg("cli_cache_init: mpool malloc fail\n"); |
|
639 | 631 |
return 1; |
640 | 632 |
} |
641 |
- if(!(cache = mpool_malloc(mempool, sizeof(struct CACHE) * TREES))) { |
|
642 |
- cli_errmsg("mpool malloc fail\n"); |
|
643 |
- mpool_destroy(mempool); |
|
644 |
- mempool = NULL; |
|
633 |
+ |
|
634 |
+ if(!(cache = mpool_malloc(engine->mempool, sizeof(struct CACHE) * TREES))) { |
|
635 |
+ cli_errmsg("cli_cache_init: mpool malloc fail\n"); |
|
645 | 636 |
return 1; |
646 | 637 |
} |
647 | 638 |
|
648 | 639 |
for(i=0; i<TREES; i++) { |
649 | 640 |
if(pthread_mutex_init(&cache[i].mutex, NULL)) { |
650 |
- cli_errmsg("mutex init fail\n"); |
|
651 |
- mpool_destroy(mempool); |
|
652 |
- mempool = NULL; |
|
653 |
- cache = NULL; |
|
641 |
+ cli_errmsg("cli_cache_init: mutex init fail\n"); |
|
642 |
+ for(j=0; j<i; j++) cacheset_destroy(&cache[j].cacheset, engine->mempool); |
|
643 |
+ for(j=0; j<i; j++) pthread_mutex_destroy(&cache[j].mutex); |
|
644 |
+ mpool_free(engine->mempool, cache); |
|
654 | 645 |
return 1; |
655 | 646 |
} |
656 |
- ret = cacheset_init(&cache[i].cacheset, entries); |
|
657 |
- if(ret) { |
|
658 |
- mpool_destroy(mempool); |
|
659 |
- mempool = NULL; |
|
660 |
- cache = NULL; |
|
647 |
+ if(cacheset_init(&cache[i].cacheset, engine->mempool)) { |
|
648 |
+ for(j=0; j<i; j++) cacheset_destroy(&cache[j].cacheset, engine->mempool); |
|
649 |
+ for(j=0; j<=i; j++) pthread_mutex_destroy(&cache[j].mutex); |
|
650 |
+ mpool_free(engine->mempool, cache); |
|
661 | 651 |
return 1; |
662 | 652 |
} |
663 | 653 |
} |
664 |
- |
|
665 |
- { |
|
666 |
- int f = open("/home/acab/hashes", O_RDONLY); |
|
667 |
- struct stat s; |
|
668 |
- fstat(f, &s); |
|
669 |
- char *pippo = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, f, 0); |
|
670 |
- while(s.st_size >= 17) { |
|
671 |
- if(*pippo == 'C') |
|
672 |
- cache_lookup_hash(pippo+1, NULL); |
|
673 |
- else if(*pippo == 'A') |
|
674 |
- cache_add(pippo+1, NULL); |
|
675 |
- else { |
|
676 |
- printf("bad hash\n"); |
|
677 |
- abort(); |
|
678 |
- } |
|
679 |
- pippo += 17; |
|
680 |
- s.st_size -= 17; |
|
681 |
- } |
|
682 |
- printf("that's all\n"); |
|
683 |
- abort(); |
|
684 |
- } |
|
654 |
+ engine->cache = cache; |
|
685 | 655 |
return 0; |
686 | 656 |
} |
687 | 657 |
|
658 |
+void cli_cache_destroy(struct cl_engine *engine) { |
|
659 |
+ static struct CACHE *cache; |
|
660 |
+ unsigned int i; |
|
688 | 661 |
|
689 |
-static int cache_lookup_hash(unsigned char *md5, cli_ctx *ctx) { |
|
690 |
- int ret = CL_VIRUS; |
|
662 |
+ if(!engine || !(cache = engine->cache)) |
|
663 |
+ return; |
|
664 |
+ |
|
665 |
+ for(i=0; i<TREES; i++) { |
|
666 |
+ cacheset_destroy(&cache[i].cacheset, engine->mempool); |
|
667 |
+ pthread_mutex_destroy(&cache[i].mutex); |
|
668 |
+ } |
|
669 |
+ mpool_free(engine->mempool, cache); |
|
670 |
+} |
|
671 |
+ |
|
672 |
+static int cache_lookup_hash(unsigned char *md5, struct CACHE *cache) { |
|
691 | 673 |
unsigned int key = getkey(md5); |
674 |
+ int ret = CL_VIRUS; |
|
692 | 675 |
struct CACHE *c; |
693 | 676 |
|
694 |
- if(!cache) return ret; |
|
695 |
- |
|
696 | 677 |
c = &cache[key]; |
697 | 678 |
if(pthread_mutex_lock(&c->mutex)) { |
698 |
- cli_errmsg("mutex lock fail\n"); |
|
679 |
+ cli_errmsg("cache_lookup_hash: cache_lookup_hash: mutex lock fail\n"); |
|
699 | 680 |
return ret; |
700 | 681 |
} |
701 | 682 |
|
702 |
- ret = (cacheset_lookup(&c->cacheset, md5, 1024) == 1337) ? CL_CLEAN : CL_VIRUS; |
|
683 |
+ ret = (cacheset_lookup(&c->cacheset, md5, 1024)) ? CL_CLEAN : CL_VIRUS; |
|
703 | 684 |
if(ret == CL_CLEAN) cli_warnmsg("cached\n"); |
704 | 685 |
pthread_mutex_unlock(&c->mutex); |
705 | 686 |
return ret; |
... | ... |
@@ -709,15 +680,24 @@ void cache_add(unsigned char *md5, cli_ctx *ctx) { |
709 | 709 |
unsigned int key = getkey(md5); |
710 | 710 |
struct CACHE *c; |
711 | 711 |
|
712 |
- if(!cache) return; |
|
712 |
+ if(!ctx || !ctx->engine || !ctx->engine->cache) |
|
713 |
+ return; |
|
713 | 714 |
|
714 |
- c = &cache[key]; |
|
715 |
+ c = &ctx->engine->cache[key]; |
|
715 | 716 |
if(pthread_mutex_lock(&c->mutex)) { |
716 |
- cli_errmsg("mutex lock fail\n"); |
|
717 |
+ cli_errmsg("cli_add: mutex lock fail\n"); |
|
717 | 718 |
return; |
718 | 719 |
} |
719 | 720 |
|
721 |
+#ifdef USE_LRUHASHCACHE |
|
722 |
+ cacheset_add(&c->cacheset, md5, 1024, ctx->engine->mempool); |
|
723 |
+#else |
|
724 |
+#ifdef USE_SPLAY |
|
720 | 725 |
cacheset_add(&c->cacheset, md5, 1024); |
726 |
+#else |
|
727 |
+#error #define USE_SPLAY or USE_LRUHASHCACHE |
|
728 |
+#endif |
|
729 |
+#endif |
|
721 | 730 |
|
722 | 731 |
pthread_mutex_unlock(&c->mutex); |
723 | 732 |
return; |
... | ... |
@@ -728,7 +708,8 @@ int cache_check(unsigned char *hash, cli_ctx *ctx) { |
728 | 728 |
size_t todo = map->len, at = 0; |
729 | 729 |
cli_md5_ctx md5; |
730 | 730 |
|
731 |
- if(!cache) return CL_VIRUS; |
|
731 |
+ if(!ctx || !ctx->engine || !ctx->engine->cache) |
|
732 |
+ return CL_VIRUS; |
|
732 | 733 |
|
733 | 734 |
cli_md5_init(&md5); |
734 | 735 |
while(todo) { |
... | ... |
@@ -741,5 +722,5 @@ int cache_check(unsigned char *hash, cli_ctx *ctx) { |
741 | 741 |
cli_md5_update(&md5, buf, readme); |
742 | 742 |
} |
743 | 743 |
cli_md5_final(hash, &md5); |
744 |
- return cache_lookup_hash(hash, ctx); |
|
744 |
+ return cache_lookup_hash(hash, ctx->engine->cache); |
|
745 | 745 |
} |
... | ... |
@@ -2188,6 +2188,9 @@ int cl_load(const char *path, struct cl_engine *engine, unsigned int *signo, uns |
2188 | 2188 |
cli_dbgmsg("Bytecode engine disabled\n"); |
2189 | 2189 |
} |
2190 | 2190 |
|
2191 |
+ if(cli_cache_init(engine)) |
|
2192 |
+ return CL_EMEM; |
|
2193 |
+ |
|
2191 | 2194 |
engine->dboptions |= dboptions; |
2192 | 2195 |
|
2193 | 2196 |
switch(sb.st_mode & S_IFMT) { |
... | ... |
@@ -2537,6 +2540,9 @@ int cl_engine_free(struct cl_engine *engine) |
2537 | 2537 |
if(engine->tmpdir) |
2538 | 2538 |
mpool_free(engine->mempool, engine->tmpdir); |
2539 | 2539 |
|
2540 |
+ if(engine->cache) |
|
2541 |
+ cli_cache_destroy(engine); |
|
2542 |
+ |
|
2540 | 2543 |
cli_ftfree(engine); |
2541 | 2544 |
if(engine->ignored) { |
2542 | 2545 |
cli_bm_free(engine->ignored); |