... | ... |
@@ -352,7 +352,7 @@ static inline int cmp(int64_t *a, ssize_t sa, int64_t *b, ssize_t sb) { |
352 | 352 |
static int printtree(struct cache_set *cs, struct node *n, int d) { |
353 | 353 |
int i; |
354 | 354 |
int ab = 0; |
355 |
- if (n == NULL) return 0; |
|
355 |
+ if ((n == NULL) || (cs == NULL) || (cs->data == NULL)) return 0; |
|
356 | 356 |
if(n == cs->root) { ptree("--------------------------\n"); } |
357 | 357 |
ab |= printtree(cs, n->right, d+1); |
358 | 358 |
if(n->right) { |
... | ... |
@@ -373,17 +373,17 @@ static int printtree(struct cache_set *cs, struct node *n, int d) { |
373 | 373 |
} |
374 | 374 |
if(d){ |
375 | 375 |
if(!n->up) { |
376 |
- ptree("no parent!\n"); |
|
376 |
+ printf("no parent, [node %02u]!\n", n - cs->data); |
|
377 | 377 |
ab = 1; |
378 | 378 |
} else { |
379 | 379 |
if(n->up->left != n && n->up->right != n) { |
380 |
- ptree("broken parent\n"); |
|
380 |
+ printf("broken parent [node %02u, parent node %02u]\n", n - cs->data, n->up - cs->data); |
|
381 | 381 |
ab = 1; |
382 | 382 |
} |
383 | 383 |
} |
384 | 384 |
} else { |
385 | 385 |
if(n->up) { |
386 |
- ptree("root with a parent!\n"); |
|
386 |
+ printf("root with a parent, [node %02u]!\n", n - cs->data); |
|
387 | 387 |
ab = 1; |
388 | 388 |
} |
389 | 389 |
} |
... | ... |
@@ -394,6 +394,81 @@ static int printtree(struct cache_set *cs, struct node *n, int d) { |
394 | 394 |
#define printtree(a,b,c) (0) |
395 | 395 |
#endif |
396 | 396 |
|
397 |
+/* For troubleshooting only; prints out one specific node */ |
|
398 |
+/* #define PRINT_NODE */ |
|
399 |
+#ifdef PRINT_NODE |
|
400 |
+static void printnode(const char *prefix, struct cache_set *cs, struct node *n) { |
|
401 |
+ if (!prefix || !cs || !cs->data) { |
|
402 |
+ printf("bad args!\n"); |
|
403 |
+ return; |
|
404 |
+ } |
|
405 |
+ if (!n) { |
|
406 |
+ printf("no node!\n"); |
|
407 |
+ return; |
|
408 |
+ } |
|
409 |
+ printf("%s node [%02u]:", prefix, n - cs->data); |
|
410 |
+ printf(" size=%lu digest=%llx,%llx\n", (unsigned long)(n->size), n->digest[0], n->digest[1]); |
|
411 |
+ printf("\tleft="); |
|
412 |
+ if(n->left) |
|
413 |
+ printf("%02u ", n->left - cs->data); |
|
414 |
+ else |
|
415 |
+ printf("NULL "); |
|
416 |
+ printf("right="); |
|
417 |
+ if(n->right) |
|
418 |
+ printf("%02u ", n->right - cs->data); |
|
419 |
+ else |
|
420 |
+ printf("NULL "); |
|
421 |
+ printf("up="); |
|
422 |
+ if(n->up) |
|
423 |
+ printf("%02u ", n->up - cs->data); |
|
424 |
+ else |
|
425 |
+ printf("NULL "); |
|
426 |
+ |
|
427 |
+ printf("\tprev="); |
|
428 |
+ if(n->prev) |
|
429 |
+ printf("%02u ", n->prev - cs->data); |
|
430 |
+ else |
|
431 |
+ printf("NULL "); |
|
432 |
+ printf("next="); |
|
433 |
+ if(n->next) |
|
434 |
+ printf("%02u\n", n->next - cs->data); |
|
435 |
+ else |
|
436 |
+ printf("NULL\n"); |
|
437 |
+} |
|
438 |
+#else |
|
439 |
+#define printnode(a,b,c) (0) |
|
440 |
+#endif |
|
441 |
+ |
|
442 |
+/* #define PRINT_CHAINS */ |
|
443 |
+#ifdef PRINT_CHAINS |
|
444 |
+/* For troubleshooting only, print the chain forwards and back */ |
|
445 |
+static inline void printchain(const char *prefix, struct cache_set *cs) { |
|
446 |
+ if (!cs || !cs->data) return; |
|
447 |
+ if (prefix) printf("%s: ", prefix); |
|
448 |
+ printf("chain by next: "); |
|
449 |
+ { |
|
450 |
+ unsigned int i = 0; |
|
451 |
+ struct node *x = cs->first; |
|
452 |
+ while(x) { |
|
453 |
+ printf("%02d,", x - cs->data); |
|
454 |
+ x=x->next; |
|
455 |
+ i++; |
|
456 |
+ } |
|
457 |
+ printf(" [count=%u]\nchain by prev: ", i); |
|
458 |
+ x=cs->last; |
|
459 |
+ i=0; |
|
460 |
+ while(x) { |
|
461 |
+ printf("%02d,", x - cs->data); |
|
462 |
+ x=x->prev; |
|
463 |
+ i++; |
|
464 |
+ } |
|
465 |
+ printf(" [count=%u]\n", i); |
|
466 |
+ } |
|
467 |
+} |
|
468 |
+#else |
|
469 |
+#define printchain(a,b) (0) |
|
470 |
+#endif |
|
471 |
+ |
|
397 | 472 |
/* Looks up a node and splays it up to the root of the tree */ |
398 | 473 |
static int splay(int64_t *md5, size_t len, struct cache_set *cs) { |
399 | 474 |
struct node next = {{0, 0}, NULL, NULL, NULL, NULL, NULL, 0, 0}, *right = &next, *left = &next, *temp, *root = cs->root; |
... | ... |
@@ -463,21 +538,7 @@ static inline int cacheset_lookup(struct cache_set *cs, unsigned char *md5, size |
463 | 463 |
struct node *o = cs->root->prev, *p = cs->root, *q = cs->root->next; |
464 | 464 |
#ifdef PRINT_CHAINS |
465 | 465 |
printf("promoting %02d\n", p - cs->data); |
466 |
- { |
|
467 |
- struct node *x = cs->first; |
|
468 |
- printf("before: "); |
|
469 |
- while(x) { |
|
470 |
- printf("%02d,", x - cs->data); |
|
471 |
- x=x->next; |
|
472 |
- } |
|
473 |
- printf(" --- "); |
|
474 |
- x=cs->last; |
|
475 |
- while(x) { |
|
476 |
- printf("%02d,", x - cs->data); |
|
477 |
- x=x->prev; |
|
478 |
- } |
|
479 |
- printf("\n"); |
|
480 |
- } |
|
466 |
+ printchain("before", cs); |
|
481 | 467 |
#endif |
482 | 468 |
if(q) { |
483 | 469 |
if(o) |
... | ... |
@@ -491,21 +552,7 @@ static inline int cacheset_lookup(struct cache_set *cs, unsigned char *md5, size |
491 | 491 |
cs->last = p; |
492 | 492 |
} |
493 | 493 |
#ifdef PRINT_CHAINS |
494 |
- { |
|
495 |
- struct node *x = cs->first; |
|
496 |
- printf("after : "); |
|
497 |
- while(x) { |
|
498 |
- printf("%02d,", x - cs->data); |
|
499 |
- x=x->next; |
|
500 |
- } |
|
501 |
- printf(" --- "); |
|
502 |
- x=cs->last; |
|
503 |
- while(x) { |
|
504 |
- printf("%02d,", x - cs->data); |
|
505 |
- x=x->prev; |
|
506 |
- } |
|
507 |
- printf("\n"); |
|
508 |
- } |
|
494 |
+ printchain("after", cs); |
|
509 | 495 |
#endif |
510 | 496 |
if(reclevel >= p->minrec) |
511 | 497 |
return 1; |
... | ... |
@@ -537,10 +584,16 @@ static inline void cacheset_add(struct cache_set *cs, unsigned char *md5, size_t |
537 | 537 |
while(newnode) { |
538 | 538 |
if(!newnode->right && !newnode->left) |
539 | 539 |
break; |
540 |
- newnode = newnode->next; |
|
541 |
- if(newnode == newnode->next) { |
|
542 |
- cli_errmsg("cacheset_add: cache chain in a bad state\n"); |
|
543 |
- return; |
|
540 |
+ if(newnode->next) { |
|
541 |
+ if(newnode == newnode->next) { |
|
542 |
+ cli_errmsg("cacheset_add: cache chain in a bad state\n"); |
|
543 |
+ return; |
|
544 |
+ } |
|
545 |
+ newnode = newnode->next; |
|
546 |
+ } |
|
547 |
+ else { |
|
548 |
+ cli_warnmsg("cacheset_add: end of chain reached\n"); |
|
549 |
+ return; |
|
544 | 550 |
} |
545 | 551 |
} |
546 | 552 |
if(!newnode) { |
... | ... |
@@ -599,7 +652,9 @@ static inline void cacheset_add(struct cache_set *cs, unsigned char *md5, size_t |
599 | 599 |
cli_errmsg("cacheset_add: inconsistent tree after adding newnode, good luck\n"); |
600 | 600 |
return; |
601 | 601 |
} |
602 |
+ printnode("newnode", cs, newnode); |
|
602 | 603 |
} |
604 |
+ |
|
603 | 605 |
/* If the hash is not present nothing happens other than splaying the tree. |
604 | 606 |
Otherwise the identified node is removed from the tree and then placed back at |
605 | 607 |
the front of the chain. */ |
... | ... |
@@ -616,6 +671,7 @@ static inline void cacheset_remove(struct cache_set *cs, unsigned char *md5, siz |
616 | 616 |
|
617 | 617 |
ptree("cacheset_remove: node found and splayed to root\n"); |
618 | 618 |
targetnode = cs->root; |
619 |
+ printnode("targetnode", cs, targetnode); |
|
619 | 620 |
|
620 | 621 |
/* First fix the tree */ |
621 | 622 |
if(targetnode->left == NULL) { |
... | ... |
@@ -630,15 +686,19 @@ static inline void cacheset_remove(struct cache_set *cs, unsigned char *md5, siz |
630 | 630 |
cs->root->up = NULL; |
631 | 631 |
/* splay tree, expecting not found, bringing rightmost member to root */ |
632 | 632 |
splay(hash, size, cs); |
633 |
- |
|
633 |
+ |
|
634 | 634 |
if (targetnode->right) { |
635 | 635 |
/* reattach right tree to clean right-side attach point */ |
636 | 636 |
reattachnode = cs->root; |
637 | 637 |
while (reattachnode->right) |
638 | 638 |
reattachnode = reattachnode->right; /* shouldn't happen, but safer in case of dupe */ |
639 | 639 |
reattachnode->right = targetnode->right; |
640 |
+ targetnode->right->up = reattachnode; |
|
640 | 641 |
} |
641 | 642 |
} |
643 |
+ targetnode->size = (size_t)0; |
|
644 |
+ targetnode->digest[0] = 0; |
|
645 |
+ targetnode->digest[1] = 0; |
|
642 | 646 |
targetnode->up = NULL; |
643 | 647 |
targetnode->left = NULL; |
644 | 648 |
targetnode->right = NULL; |
... | ... |
@@ -659,6 +719,12 @@ static inline void cacheset_remove(struct cache_set *cs, unsigned char *md5, siz |
659 | 659 |
cs->first = targetnode; |
660 | 660 |
} |
661 | 661 |
targetnode->prev = NULL; |
662 |
+ |
|
663 |
+ printnode("root", cs, cs->root); |
|
664 |
+ printnode("first", cs, cs->first); |
|
665 |
+ printnode("last", cs, cs->last); |
|
666 |
+ |
|
667 |
+ printchain("remove (after)", cs); |
|
662 | 668 |
} |
663 | 669 |
#endif /* USE_SPLAY */ |
664 | 670 |
|
... | ... |
@@ -733,6 +799,8 @@ static int cache_lookup_hash(unsigned char *md5, size_t len, struct CACHE *cache |
733 | 733 |
return ret; |
734 | 734 |
} |
735 | 735 |
|
736 |
+ /* cli_warnmsg("cache_lookup_hash: key is %u\n", key); */ |
|
737 |
+ |
|
736 | 738 |
ret = (cacheset_lookup(&c->cacheset, md5, len, reclevel)) ? CL_CLEAN : CL_VIRUS; |
737 | 739 |
pthread_mutex_unlock(&c->mutex); |
738 | 740 |
/* if(ret == CL_CLEAN) cli_warnmsg("cached\n"); */ |
... | ... |
@@ -757,6 +825,8 @@ void cache_add(unsigned char *md5, size_t size, cli_ctx *ctx) { |
757 | 757 |
return; |
758 | 758 |
} |
759 | 759 |
|
760 |
+ /* cli_warnmsg("cache_add: key is %u\n", key); */ |
|
761 |
+ |
|
760 | 762 |
#ifdef USE_LRUHASHCACHE |
761 | 763 |
cacheset_add(&c->cacheset, md5, size, ctx->engine->mempool); |
762 | 764 |
#else |
... | ... |
@@ -780,6 +850,8 @@ void cache_remove(unsigned char *md5, size_t size, const struct cl_engine *engin |
780 | 780 |
if(!engine || !engine->cache) |
781 | 781 |
return; |
782 | 782 |
|
783 |
+ /* cli_warnmsg("cache_remove: key is %u\n", key); */ |
|
784 |
+ |
|
783 | 785 |
c = &engine->cache[key]; |
784 | 786 |
if(pthread_mutex_lock(&c->mutex)) { |
785 | 787 |
cli_errmsg("cli_add: mutex lock fail\n"); |