Browse code

cache: cacheset_remove fix and better logging

David Raynor authored on 2013/04/16 06:58:26
Showing 1 changed files
... ...
@@ -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");