Fossil SCM

Add the test-clusters command to verify that all artifacts are reachable through cluster chains. Fix the cluster creator so that it does not create gaps if the number of unclustered entries exceeds 800.

drh 2010-12-27 21:40 UTC trunk
Commit 64a9c81a222733aebcfb4ec6630280b41361e4fb
2 files changed +68 +10 -2
--- src/rebuild.c
+++ src/rebuild.c
@@ -427,10 +427,78 @@
427427
}
428428
db_begin_transaction();
429429
create_cluster();
430430
db_end_transaction(0);
431431
}
432
+
433
+/*
434
+** COMMAND: test-clusters
435
+**
436
+** Verify that all non-private and non-shunned artifacts are accessible
437
+** through the cluster chain.
438
+*/
439
+void test_clusters_cmd(void){
440
+ Bag pending;
441
+ Stmt q;
442
+ int n;
443
+
444
+ db_find_and_open_repository(0, 2);
445
+ bag_init(&pending);
446
+ db_multi_exec(
447
+ "CREATE TEMP TABLE xdone(x INTEGER PRIMARY KEY);"
448
+ "INSERT INTO xdone SELECT rid FROM unclustered;"
449
+ "INSERT OR IGNORE INTO xdone SELECT rid FROM private;"
450
+ "INSERT OR IGNORE INTO xdone"
451
+ " SELECT blob.rid FROM shun JOIN blob USING(uuid);"
452
+ );
453
+ db_prepare(&q,
454
+ "SELECT rid FROM unclustered WHERE rid IN"
455
+ " (SELECT rid FROM tagxref WHERE tagid=%d)", TAG_CLUSTER
456
+ );
457
+ while( db_step(&q)==SQLITE_ROW ){
458
+ bag_insert(&pending, db_column_int(&q, 0));
459
+ }
460
+ db_finalize(&q);
461
+ while( bag_count(&pending)>0 ){
462
+ Manifest *p;
463
+ int rid = bag_first(&pending);
464
+ int i;
465
+
466
+ bag_remove(&pending, rid);
467
+ p = manifest_get(rid, CFTYPE_CLUSTER);
468
+ if( p==0 ){
469
+ fossil_fatal("bad cluster: rid=%d", rid);
470
+ }
471
+ for(i=0; i<p->nCChild; i++){
472
+ const char *zUuid = p->azCChild[i];
473
+ int crid = name_to_rid(zUuid);
474
+ if( crid==0 ){
475
+ fossil_warning("cluster (rid=%d) references unknown artifact %s",
476
+ rid, zUuid);
477
+ continue;
478
+ }
479
+ db_multi_exec("INSERT OR IGNORE INTO xdone VALUES(%d)", crid);
480
+ if( db_exists("SELECT 1 FROM tagxref WHERE tagid=%d AND rid=%d",
481
+ TAG_CLUSTER, crid) ){
482
+ bag_insert(&pending, crid);
483
+ }
484
+ }
485
+ manifest_destroy(p);
486
+ }
487
+ n = db_int(0, "SELECT count(*) FROM /*scan*/"
488
+ " (SELECT rid FROM blob EXCEPT SELECT x FROM xdone)");
489
+ if( n==0 ){
490
+ printf("all artifacts reachable through clusters\n");
491
+ }else{
492
+ printf("%d unreachable artifacts:\n", n);
493
+ db_prepare(&q, "SELECT rid, uuid FROM blob WHERE rid NOT IN xdone");
494
+ while( db_step(&q)==SQLITE_ROW ){
495
+ printf(" %3d %s\n", db_column_int(&q,0), db_column_text(&q,1));
496
+ }
497
+ db_finalize(&q);
498
+ }
499
+}
432500
433501
/*
434502
** COMMAND: scrub
435503
** %fossil scrub [--verily] [--force] [REPOSITORY]
436504
**
437505
--- src/rebuild.c
+++ src/rebuild.c
@@ -427,10 +427,78 @@
427 }
428 db_begin_transaction();
429 create_cluster();
430 db_end_transaction(0);
431 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
432
433 /*
434 ** COMMAND: scrub
435 ** %fossil scrub [--verily] [--force] [REPOSITORY]
436 **
437
--- src/rebuild.c
+++ src/rebuild.c
@@ -427,10 +427,78 @@
427 }
428 db_begin_transaction();
429 create_cluster();
430 db_end_transaction(0);
431 }
432
433 /*
434 ** COMMAND: test-clusters
435 **
436 ** Verify that all non-private and non-shunned artifacts are accessible
437 ** through the cluster chain.
438 */
439 void test_clusters_cmd(void){
440 Bag pending;
441 Stmt q;
442 int n;
443
444 db_find_and_open_repository(0, 2);
445 bag_init(&pending);
446 db_multi_exec(
447 "CREATE TEMP TABLE xdone(x INTEGER PRIMARY KEY);"
448 "INSERT INTO xdone SELECT rid FROM unclustered;"
449 "INSERT OR IGNORE INTO xdone SELECT rid FROM private;"
450 "INSERT OR IGNORE INTO xdone"
451 " SELECT blob.rid FROM shun JOIN blob USING(uuid);"
452 );
453 db_prepare(&q,
454 "SELECT rid FROM unclustered WHERE rid IN"
455 " (SELECT rid FROM tagxref WHERE tagid=%d)", TAG_CLUSTER
456 );
457 while( db_step(&q)==SQLITE_ROW ){
458 bag_insert(&pending, db_column_int(&q, 0));
459 }
460 db_finalize(&q);
461 while( bag_count(&pending)>0 ){
462 Manifest *p;
463 int rid = bag_first(&pending);
464 int i;
465
466 bag_remove(&pending, rid);
467 p = manifest_get(rid, CFTYPE_CLUSTER);
468 if( p==0 ){
469 fossil_fatal("bad cluster: rid=%d", rid);
470 }
471 for(i=0; i<p->nCChild; i++){
472 const char *zUuid = p->azCChild[i];
473 int crid = name_to_rid(zUuid);
474 if( crid==0 ){
475 fossil_warning("cluster (rid=%d) references unknown artifact %s",
476 rid, zUuid);
477 continue;
478 }
479 db_multi_exec("INSERT OR IGNORE INTO xdone VALUES(%d)", crid);
480 if( db_exists("SELECT 1 FROM tagxref WHERE tagid=%d AND rid=%d",
481 TAG_CLUSTER, crid) ){
482 bag_insert(&pending, crid);
483 }
484 }
485 manifest_destroy(p);
486 }
487 n = db_int(0, "SELECT count(*) FROM /*scan*/"
488 " (SELECT rid FROM blob EXCEPT SELECT x FROM xdone)");
489 if( n==0 ){
490 printf("all artifacts reachable through clusters\n");
491 }else{
492 printf("%d unreachable artifacts:\n", n);
493 db_prepare(&q, "SELECT rid, uuid FROM blob WHERE rid NOT IN xdone");
494 while( db_step(&q)==SQLITE_ROW ){
495 printf(" %3d %s\n", db_column_int(&q,0), db_column_text(&q,1));
496 }
497 db_finalize(&q);
498 }
499 }
500
501 /*
502 ** COMMAND: scrub
503 ** %fossil scrub [--verily] [--force] [REPOSITORY]
504 **
505
+10 -2
--- src/xfer.c
+++ src/xfer.c
@@ -584,13 +584,15 @@
584584
** count toward the 100 total. And phantoms are never added to a new
585585
** cluster.
586586
*/
587587
void create_cluster(void){
588588
Blob cluster, cksum;
589
+ Blob deleteWhere;
589590
Stmt q;
590591
int nUncl;
591592
int nRow = 0;
593
+ int rid;
592594
593595
/* We should not ever get any private artifacts in the unclustered table.
594596
** But if we do (because of a bug) now is a good time to delete them. */
595597
db_multi_exec(
596598
"DELETE FROM unclustered WHERE rid IN (SELECT rid FROM private)"
@@ -599,10 +601,11 @@
599601
nUncl = db_int(0, "SELECT count(*) FROM unclustered /*scan*/"
600602
" WHERE NOT EXISTS(SELECT 1 FROM phantom"
601603
" WHERE rid=unclustered.rid)");
602604
if( nUncl>=100 ){
603605
blob_zero(&cluster);
606
+ blob_zero(&deleteWhere);
604607
db_prepare(&q, "SELECT uuid FROM unclustered, blob"
605608
" WHERE NOT EXISTS(SELECT 1 FROM phantom"
606609
" WHERE rid=unclustered.rid)"
607610
" AND unclustered.rid=blob.rid"
608611
" AND NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
@@ -612,18 +615,23 @@
612615
nRow++;
613616
if( nRow>=800 && nUncl>nRow+100 ){
614617
md5sum_blob(&cluster, &cksum);
615618
blob_appendf(&cluster, "Z %b\n", &cksum);
616619
blob_reset(&cksum);
617
- content_put(&cluster, 0, 0, 0);
620
+ rid = content_put(&cluster, 0, 0, 0);
618621
blob_reset(&cluster);
619622
nUncl -= nRow;
620623
nRow = 0;
624
+ blob_appendf(&deleteWhere, ",%d", rid);
621625
}
622626
}
623627
db_finalize(&q);
624
- db_multi_exec("DELETE FROM unclustered");
628
+ db_multi_exec(
629
+ "DELETE FROM unclustered WHERE rid NOT IN (0 %s)",
630
+ blob_str(&deleteWhere)
631
+ );
632
+ blob_reset(&deleteWhere);
625633
if( nRow>0 ){
626634
md5sum_blob(&cluster, &cksum);
627635
blob_appendf(&cluster, "Z %b\n", &cksum);
628636
blob_reset(&cksum);
629637
content_put(&cluster, 0, 0, 0);
630638
--- src/xfer.c
+++ src/xfer.c
@@ -584,13 +584,15 @@
584 ** count toward the 100 total. And phantoms are never added to a new
585 ** cluster.
586 */
587 void create_cluster(void){
588 Blob cluster, cksum;
 
589 Stmt q;
590 int nUncl;
591 int nRow = 0;
 
592
593 /* We should not ever get any private artifacts in the unclustered table.
594 ** But if we do (because of a bug) now is a good time to delete them. */
595 db_multi_exec(
596 "DELETE FROM unclustered WHERE rid IN (SELECT rid FROM private)"
@@ -599,10 +601,11 @@
599 nUncl = db_int(0, "SELECT count(*) FROM unclustered /*scan*/"
600 " WHERE NOT EXISTS(SELECT 1 FROM phantom"
601 " WHERE rid=unclustered.rid)");
602 if( nUncl>=100 ){
603 blob_zero(&cluster);
 
604 db_prepare(&q, "SELECT uuid FROM unclustered, blob"
605 " WHERE NOT EXISTS(SELECT 1 FROM phantom"
606 " WHERE rid=unclustered.rid)"
607 " AND unclustered.rid=blob.rid"
608 " AND NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
@@ -612,18 +615,23 @@
612 nRow++;
613 if( nRow>=800 && nUncl>nRow+100 ){
614 md5sum_blob(&cluster, &cksum);
615 blob_appendf(&cluster, "Z %b\n", &cksum);
616 blob_reset(&cksum);
617 content_put(&cluster, 0, 0, 0);
618 blob_reset(&cluster);
619 nUncl -= nRow;
620 nRow = 0;
 
621 }
622 }
623 db_finalize(&q);
624 db_multi_exec("DELETE FROM unclustered");
 
 
 
 
625 if( nRow>0 ){
626 md5sum_blob(&cluster, &cksum);
627 blob_appendf(&cluster, "Z %b\n", &cksum);
628 blob_reset(&cksum);
629 content_put(&cluster, 0, 0, 0);
630
--- src/xfer.c
+++ src/xfer.c
@@ -584,13 +584,15 @@
584 ** count toward the 100 total. And phantoms are never added to a new
585 ** cluster.
586 */
587 void create_cluster(void){
588 Blob cluster, cksum;
589 Blob deleteWhere;
590 Stmt q;
591 int nUncl;
592 int nRow = 0;
593 int rid;
594
595 /* We should not ever get any private artifacts in the unclustered table.
596 ** But if we do (because of a bug) now is a good time to delete them. */
597 db_multi_exec(
598 "DELETE FROM unclustered WHERE rid IN (SELECT rid FROM private)"
@@ -599,10 +601,11 @@
601 nUncl = db_int(0, "SELECT count(*) FROM unclustered /*scan*/"
602 " WHERE NOT EXISTS(SELECT 1 FROM phantom"
603 " WHERE rid=unclustered.rid)");
604 if( nUncl>=100 ){
605 blob_zero(&cluster);
606 blob_zero(&deleteWhere);
607 db_prepare(&q, "SELECT uuid FROM unclustered, blob"
608 " WHERE NOT EXISTS(SELECT 1 FROM phantom"
609 " WHERE rid=unclustered.rid)"
610 " AND unclustered.rid=blob.rid"
611 " AND NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
@@ -612,18 +615,23 @@
615 nRow++;
616 if( nRow>=800 && nUncl>nRow+100 ){
617 md5sum_blob(&cluster, &cksum);
618 blob_appendf(&cluster, "Z %b\n", &cksum);
619 blob_reset(&cksum);
620 rid = content_put(&cluster, 0, 0, 0);
621 blob_reset(&cluster);
622 nUncl -= nRow;
623 nRow = 0;
624 blob_appendf(&deleteWhere, ",%d", rid);
625 }
626 }
627 db_finalize(&q);
628 db_multi_exec(
629 "DELETE FROM unclustered WHERE rid NOT IN (0 %s)",
630 blob_str(&deleteWhere)
631 );
632 blob_reset(&deleteWhere);
633 if( nRow>0 ){
634 md5sum_blob(&cluster, &cksum);
635 blob_appendf(&cluster, "Z %b\n", &cksum);
636 blob_reset(&cksum);
637 content_put(&cluster, 0, 0, 0);
638

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button