| | @@ -34,51 +34,79 @@ |
| 34 | 34 | ** Return the integer record ID of the similar record. Or return |
| 35 | 35 | ** 0 if none is found. |
| 36 | 36 | */ |
| 37 | 37 | static int similar_record(int rid, int traceFlag){ |
| 38 | 38 | int inCnt, outCnt; |
| 39 | + int i; |
| 39 | 40 | Stmt q; |
| 40 | 41 | int queue[100]; |
| 41 | | - |
| 42 | | -return 0; |
| 43 | | - |
| 44 | | - db_prepare(&q, |
| 42 | + static const char *azQuery[] = { |
| 43 | + /* Scan the delta table first */ |
| 45 | 44 | "SELECT srcid, EXISTS(SELECT 1 FROM onremote WHERE rid=srcid)" |
| 46 | 45 | " FROM delta" |
| 47 | 46 | " WHERE rid=:x" |
| 47 | + " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=srcid)" |
| 48 | 48 | " UNION ALL " |
| 49 | 49 | "SELECT rid, EXISTS(SELECT 1 FROM onremote WHERE rid=delta.rid)" |
| 50 | 50 | " FROM delta" |
| 51 | 51 | " WHERE srcid=:x" |
| 52 | | - ); |
| 53 | | - queue[0] = rid; |
| 54 | | - inCnt = 1; |
| 55 | | - outCnt = 0; |
| 56 | | - while( outCnt<inCnt ){ |
| 57 | | - int xid = queue[outCnt%64]; |
| 58 | | - outCnt++; |
| 59 | | - db_bind_int(&q, ":x", xid); |
| 60 | | - if( traceFlag ) printf("xid=%d\n", xid); |
| 61 | | - while( db_step(&q)==SQLITE_ROW ){ |
| 62 | | - int nid = db_column_int(&q, 0); |
| 63 | | - int hit = db_column_int(&q, 1); |
| 64 | | - if( traceFlag ) printf("nid=%d hit=%d\n", nid, hit); |
| 65 | | - if( hit ){ |
| 66 | | - db_finalize(&q); |
| 67 | | - return nid; |
| 68 | | - } |
| 69 | | - if( inCnt<sizeof(queue)/sizeof(queue[0]) ){ |
| 70 | | - int i; |
| 71 | | - for(i=0; i<inCnt && queue[i]!=nid; i++){} |
| 72 | | - if( i>=inCnt ){ |
| 73 | | - queue[inCnt++] = nid; |
| 74 | | - } |
| 75 | | - } |
| 76 | | - } |
| 77 | | - db_reset(&q); |
| 78 | | - } |
| 79 | | - db_finalize(&q); |
| 52 | + " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=delta.rid)", |
| 53 | + |
| 54 | + /* Then the plink table */ |
| 55 | + "SELECT pid, EXISTS(SELECT 1 FROM onremote WHERE rid=pid)" |
| 56 | + " FROM plink" |
| 57 | + " WHERE cid=:x" |
| 58 | + " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 59 | + " UNION ALL " |
| 60 | + "SELECT cid, EXISTS(SELECT 1 FROM onremote WHERE rid=cid)" |
| 61 | + " FROM plink" |
| 62 | + " WHERE pid=:x" |
| 63 | + " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=cid)", |
| 64 | + |
| 65 | + /* Finally the mlink table */ |
| 66 | + "SELECT pid, EXISTS(SELECT 1 FROM onremote WHERE rid=pid)" |
| 67 | + " FROM mlink" |
| 68 | + " WHERE fid=:x AND pid>0" |
| 69 | + " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 70 | + " UNION ALL " |
| 71 | + "SELECT fid, EXISTS(SELECT 1 FROM onremote WHERE rid=fid)" |
| 72 | + " FROM mlink" |
| 73 | + " WHERE pid=:x AND fid>0" |
| 74 | + " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=fid)", |
| 75 | + }; |
| 76 | + |
| 77 | + for(i=0; i<sizeof(azQuery)/sizeof(azQuery[0]); i++){ |
| 78 | + db_prepare(&q, azQuery[i]); |
| 79 | + queue[0] = rid; |
| 80 | + inCnt = 1; |
| 81 | + outCnt = 0; |
| 82 | + if( traceFlag ) printf("PASS %d\n", i+1); |
| 83 | + while( outCnt<inCnt ){ |
| 84 | + int xid = queue[outCnt%64]; |
| 85 | + outCnt++; |
| 86 | + db_bind_int(&q, ":x", xid); |
| 87 | + if( traceFlag ) printf("xid=%d\n", xid); |
| 88 | + while( db_step(&q)==SQLITE_ROW ){ |
| 89 | + int nid = db_column_int(&q, 0); |
| 90 | + int hit = db_column_int(&q, 1); |
| 91 | + if( traceFlag ) printf("nid=%d hit=%d\n", nid, hit); |
| 92 | + if( hit ){ |
| 93 | + db_finalize(&q); |
| 94 | + return nid; |
| 95 | + } |
| 96 | + if( inCnt<sizeof(queue)/sizeof(queue[0]) ){ |
| 97 | + int i; |
| 98 | + for(i=0; i<inCnt && queue[i]!=nid; i++){} |
| 99 | + if( i>=inCnt ){ |
| 100 | + queue[inCnt++] = nid; |
| 101 | + } |
| 102 | + } |
| 103 | + } |
| 104 | + db_reset(&q); |
| 105 | + } |
| 106 | + db_finalize(&q); |
| 107 | + } |
| 80 | 108 | return 0; |
| 81 | 109 | } |
| 82 | 110 | |
| 83 | 111 | /* |
| 84 | 112 | ** COMMAND: test-similar-record |
| | @@ -172,43 +200,37 @@ |
| 172 | 200 | if( blob_size(&uuid)==0 ){ |
| 173 | 201 | return 0; |
| 174 | 202 | } |
| 175 | 203 | content_get(rid, &content); |
| 176 | 204 | |
| 177 | | - srcid = similar_record(rid, 0); |
| 178 | | - if( srcid ){ |
| 179 | | - Blob src, delta; |
| 180 | | - Blob srcuuid; |
| 181 | | - content_get(srcid, &src); |
| 182 | | - blob_delta_create(&src, &content, &delta); |
| 183 | | - blob_reset(&src); |
| 184 | | - blob_reset(&content); |
| 185 | | - blob_zero(&srcuuid); |
| 186 | | - db_blob(&srcuuid, "SELECT uuid FROM blob WHERE rid=%d", srcid); |
| 187 | | - size = blob_size(&delta); |
| 188 | | - if( pOut ){ |
| 189 | | - blob_appendf(pOut, "file %b %b %d\n", &uuid, &srcuuid, size); |
| 190 | | - blob_append(pOut, blob_buffer(&delta), size); |
| 191 | | - }else{ |
| 192 | | - cgi_printf("file %b %b %d\n", &uuid, &srcuuid, size); |
| 193 | | - cgi_append_content(blob_buffer(&delta), size); |
| 194 | | - } |
| 195 | | - blob_reset(&delta); |
| 196 | | - blob_reset(&srcuuid); |
| 197 | | - blob_reset(&uuid); |
| 198 | | - }else{ |
| 199 | | - size = blob_size(&content); |
| 200 | | - if( pOut ){ |
| 201 | | - blob_appendf(pOut, "file %b %d\n", &uuid, size); |
| 202 | | - blob_append(pOut, blob_buffer(&content), size); |
| 203 | | - }else{ |
| 204 | | - cgi_printf("file %b %d\n", &uuid, size); |
| 205 | | - cgi_append_content(blob_buffer(&content), size); |
| 206 | | - } |
| 207 | | - blob_reset(&content); |
| 208 | | - blob_reset(&uuid); |
| 209 | | - } |
| 205 | + if( blob_size(&content)>100 ){ |
| 206 | + srcid = similar_record(rid, 0); |
| 207 | + if( srcid ){ |
| 208 | + Blob src; |
| 209 | + content_get(srcid, &src); |
| 210 | + if( blob_size(&src)>100 ){ |
| 211 | + Blob delta; |
| 212 | + blob_delta_create(&src, &content, &delta); |
| 213 | + blob_reset(&content); |
| 214 | + content = delta; |
| 215 | + blob_append(&uuid, " ", 1); |
| 216 | + blob_append(&content, "\n", 1); |
| 217 | + db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", srcid); |
| 218 | + } |
| 219 | + blob_reset(&src); |
| 220 | + } |
| 221 | + } |
| 222 | + size = blob_size(&content); |
| 223 | + if( pOut ){ |
| 224 | + blob_appendf(pOut, "file %b %d\n", &uuid, size); |
| 225 | + blob_append(pOut, blob_buffer(&content), size); |
| 226 | + }else{ |
| 227 | + cgi_printf("file %b %d\n", &uuid, size); |
| 228 | + cgi_append_content(blob_buffer(&content), size); |
| 229 | + } |
| 230 | + blob_reset(&content); |
| 231 | + blob_reset(&uuid); |
| 210 | 232 | db_multi_exec("INSERT OR IGNORE INTO onremote VALUES(%d)", rid); |
| 211 | 233 | return size; |
| 212 | 234 | } |
| 213 | 235 | |
| 214 | 236 | |
| | @@ -467,11 +489,11 @@ |
| 467 | 489 | } |
| 468 | 490 | isPull = 1; |
| 469 | 491 | @ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x")) |
| 470 | 492 | db_multi_exec( |
| 471 | 493 | "INSERT OR IGNORE INTO pending(rid) " |
| 472 | | - "SELECT rid FROM blob WHERE size>=0" |
| 494 | + "SELECT mid FROM mlink JOIN blob ON mid=rid" |
| 473 | 495 | ); |
| 474 | 496 | }else |
| 475 | 497 | |
| 476 | 498 | /* login USER NONCE SIGNATURE |
| 477 | 499 | ** |
| | @@ -495,14 +517,22 @@ |
| 495 | 517 | } |
| 496 | 518 | |
| 497 | 519 | /* The input message has now been processed. Generate a reply. */ |
| 498 | 520 | if( isPush ){ |
| 499 | 521 | Stmt q; |
| 500 | | - db_prepare(&q, "SELECT uuid FROM blob WHERE size<0"); |
| 501 | | - while( db_step(&q)==SQLITE_ROW ){ |
| 522 | + int nReq = 0; |
| 523 | + db_prepare(&q, "SELECT uuid, rid FROM phantom JOIN blob USING (rid)"); |
| 524 | + while( db_step(&q)==SQLITE_ROW && nReq++ < 200 ){ |
| 502 | 525 | const char *zUuid = db_column_text(&q, 0); |
| 526 | + int rid = db_column_int(&q, 1); |
| 527 | + int xid = similar_record(rid, 0); |
| 503 | 528 | @ gimme %s(zUuid) |
| 529 | + if( xid ){ |
| 530 | + char *zXUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", xid); |
| 531 | + @ igot %s(zXUuid); |
| 532 | + free(zXUuid); |
| 533 | + } |
| 504 | 534 | } |
| 505 | 535 | db_finalize(&q); |
| 506 | 536 | } |
| 507 | 537 | if( isPull ){ |
| 508 | 538 | send_all_pending(0); |
| | @@ -622,15 +652,21 @@ |
| 622 | 652 | |
| 623 | 653 | if( pullFlag ){ |
| 624 | 654 | /* Send gimme message for every phantom that we hold. |
| 625 | 655 | */ |
| 626 | 656 | Stmt q; |
| 627 | | - db_prepare(&q, "SELECT uuid FROM blob WHERE size<0"); |
| 628 | | - while( db_step(&q)==SQLITE_ROW ){ |
| 657 | + db_prepare(&q, "SELECT uuid, rid FROM phantom JOIN blob USING (rid)"); |
| 658 | + while( db_step(&q)==SQLITE_ROW && nReq<200 ){ |
| 629 | 659 | const char *zUuid = db_column_text(&q, 0); |
| 660 | + int rid = db_column_int(&q, 1); |
| 661 | + int xid = similar_record(rid, 0); |
| 630 | 662 | blob_appendf(&send,"gimme %s\n", zUuid); |
| 631 | 663 | nReq++; |
| 664 | + if( xid ){ |
| 665 | + blob_appendf(&send, "igot %z\n", |
| 666 | + db_text(0, "SELECT uuid FROM blob WHERE rid=%d", xid)); |
| 667 | + } |
| 632 | 668 | } |
| 633 | 669 | db_finalize(&q); |
| 634 | 670 | } |
| 635 | 671 | |
| 636 | 672 | if( pushFlag ){ |
| | @@ -716,11 +752,11 @@ |
| 716 | 752 | if( db_changes()>0 ){ |
| 717 | 753 | go = 1; |
| 718 | 754 | } |
| 719 | 755 | } |
| 720 | 756 | if( pullFlag && !go && |
| 721 | | - db_exists("SELECT 1 FROM blob WHERE rid=%d AND size<0", rid) ){ |
| 757 | + db_exists("SELECT 1 FROM phantom WHERE rid=%d", rid) ){ |
| 722 | 758 | go = 1; |
| 723 | 759 | } |
| 724 | 760 | }else if( pullFlag ){ |
| 725 | 761 | go = 1; |
| 726 | 762 | content_put(0, blob_str(&aToken[1])); |
| 727 | 763 | |