Fossil SCM
In the sync protocol, never send a gimme card for a phantom that we know the other side lacks because it has previously sent us the same gimme card.
Commit
405457c1613710562744ca77eb9e5ee84a05c4bd5a48e07404bb96365372fa1b
Parent
1d9e0897e3c1f34…
1 file changed
+21
-4
+21
-4
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -96,10 +96,22 @@ | ||
| 96 | 96 | db_bind_int(&q, ":r", rid); |
| 97 | 97 | db_step(&q); |
| 98 | 98 | db_reset(&q); |
| 99 | 99 | } |
| 100 | 100 | } |
| 101 | + | |
| 102 | +/* | |
| 103 | +** Remember that the other side of the connection lacks a copy of | |
| 104 | +** the artifact with the given hash. | |
| 105 | +*/ | |
| 106 | +static void remote_unk(Blob *pHash){ | |
| 107 | + static Stmt q; | |
| 108 | + db_static_prepare(&q, "INSERT OR IGNORE INTO unk VALUES(:h)"); | |
| 109 | + db_bind_text(&q, ":h", blob_str(pHash)); | |
| 110 | + db_step(&q); | |
| 111 | + db_reset(&q); | |
| 112 | +} | |
| 101 | 113 | |
| 102 | 114 | /* |
| 103 | 115 | ** The aToken[0..nToken-1] blob array is a parse of a "file" line |
| 104 | 116 | ** message. This routine finishes parsing that message and does |
| 105 | 117 | ** a record insert of the file. |
| @@ -749,11 +761,12 @@ | ||
| 749 | 761 | */ |
| 750 | 762 | static void request_phantoms(Xfer *pXfer, int maxReq){ |
| 751 | 763 | Stmt q; |
| 752 | 764 | db_prepare(&q, |
| 753 | 765 | "SELECT uuid FROM phantom CROSS JOIN blob USING(rid) /*scan*/" |
| 754 | - " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s", | |
| 766 | + " WHERE NOT EXISTS(SELECT 1 FROM unk WHERE unk.uuid=blob.uuid)" | |
| 767 | + " AND NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s", | |
| 755 | 768 | (pXfer->syncPrivate ? "" : |
| 756 | 769 | " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)") |
| 757 | 770 | ); |
| 758 | 771 | while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){ |
| 759 | 772 | const char *zUuid = db_column_text(&q, 0); |
| @@ -1203,10 +1216,11 @@ | ||
| 1203 | 1216 | g.xferPanic = 1; |
| 1204 | 1217 | |
| 1205 | 1218 | db_begin_transaction(); |
| 1206 | 1219 | db_multi_exec( |
| 1207 | 1220 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 1221 | + "CREATE TEMP TABLE unk(uuid TEXT PRIMARY KEY) WITHOUT ROWID;" | |
| 1208 | 1222 | ); |
| 1209 | 1223 | manifest_crosslink_begin(); |
| 1210 | 1224 | rc = xfer_run_common_script(); |
| 1211 | 1225 | if( rc==TH_ERROR ){ |
| 1212 | 1226 | cgi_reset_content(); |
| @@ -1286,10 +1300,11 @@ | ||
| 1286 | 1300 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 1287 | 1301 | && xfer.nToken==2 |
| 1288 | 1302 | && blob_is_hname(&xfer.aToken[1]) |
| 1289 | 1303 | ){ |
| 1290 | 1304 | nGimme++; |
| 1305 | + remote_unk(&xfer.aToken[1]); | |
| 1291 | 1306 | if( isPull ){ |
| 1292 | 1307 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 1293 | 1308 | if( rid ){ |
| 1294 | 1309 | send_file(&xfer, rid, &xfer.aToken[1], deltaFlag); |
| 1295 | 1310 | } |
| @@ -1724,11 +1739,11 @@ | ||
| 1724 | 1739 | }else if( isPull ){ |
| 1725 | 1740 | create_cluster(); |
| 1726 | 1741 | send_unclustered(&xfer); |
| 1727 | 1742 | if( xfer.syncPrivate ) send_private(&xfer); |
| 1728 | 1743 | } |
| 1729 | - db_multi_exec("DROP TABLE onremote"); | |
| 1744 | + db_multi_exec("DROP TABLE onremote; DROP TABLE unk;"); | |
| 1730 | 1745 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 1731 | 1746 | |
| 1732 | 1747 | /* Send the server timestamp last, in case prior processing happened |
| 1733 | 1748 | ** to use up a significant fraction of our time window. |
| 1734 | 1749 | */ |
| @@ -1964,10 +1979,11 @@ | ||
| 1964 | 1979 | char *zRandomness; |
| 1965 | 1980 | db_begin_transaction(); |
| 1966 | 1981 | db_record_repository_filename(0); |
| 1967 | 1982 | db_multi_exec( |
| 1968 | 1983 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 1984 | + "CREATE TEMP TABLE unk(uuid TEXT PRIMARY KEY) WITHOUT ROWID;" | |
| 1969 | 1985 | ); |
| 1970 | 1986 | manifest_crosslink_begin(); |
| 1971 | 1987 | |
| 1972 | 1988 | |
| 1973 | 1989 | /* Client sends the most recently received cookie back to the server. |
| @@ -2227,10 +2243,11 @@ | ||
| 2227 | 2243 | */ |
| 2228 | 2244 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 2229 | 2245 | && xfer.nToken==2 |
| 2230 | 2246 | && blob_is_hname(&xfer.aToken[1]) |
| 2231 | 2247 | ){ |
| 2248 | + remote_unk(&xfer.aToken[1]); | |
| 2232 | 2249 | if( syncFlags & SYNC_PUSH ){ |
| 2233 | 2250 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 2234 | 2251 | if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0); |
| 2235 | 2252 | } |
| 2236 | 2253 | }else |
| @@ -2603,11 +2620,11 @@ | ||
| 2603 | 2620 | |
| 2604 | 2621 | /* Continue looping as long as new uvfile cards are being received |
| 2605 | 2622 | ** and uvgimme cards are being sent. */ |
| 2606 | 2623 | if( nUvGimmeSent>0 && (nUvFileRcvd>0 || nCycle<3) ) go = 1; |
| 2607 | 2624 | |
| 2608 | - db_multi_exec("DROP TABLE onremote"); | |
| 2625 | + db_multi_exec("DROP TABLE onremote; DROP TABLE unk;"); | |
| 2609 | 2626 | if( go ){ |
| 2610 | 2627 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 2611 | 2628 | }else{ |
| 2612 | 2629 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 2613 | 2630 | content_enable_dephantomize(1); |
| @@ -2630,11 +2647,11 @@ | ||
| 2630 | 2647 | "%s done, sent: %lld received: %lld ip: %s\n", |
| 2631 | 2648 | zOpType, nSent, nRcvd, g.zIpAddr); |
| 2632 | 2649 | transport_close(&g.url); |
| 2633 | 2650 | transport_global_shutdown(&g.url); |
| 2634 | 2651 | if( nErr && go==2 ){ |
| 2635 | - db_multi_exec("DROP TABLE onremote"); | |
| 2652 | + db_multi_exec("DROP TABLE onremote; DROP TABLE unk;"); | |
| 2636 | 2653 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 2637 | 2654 | content_enable_dephantomize(1); |
| 2638 | 2655 | db_end_transaction(0); |
| 2639 | 2656 | } |
| 2640 | 2657 | if( nErr && autopushFailed ){ |
| 2641 | 2658 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -96,10 +96,22 @@ | |
| 96 | db_bind_int(&q, ":r", rid); |
| 97 | db_step(&q); |
| 98 | db_reset(&q); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | /* |
| 103 | ** The aToken[0..nToken-1] blob array is a parse of a "file" line |
| 104 | ** message. This routine finishes parsing that message and does |
| 105 | ** a record insert of the file. |
| @@ -749,11 +761,12 @@ | |
| 749 | */ |
| 750 | static void request_phantoms(Xfer *pXfer, int maxReq){ |
| 751 | Stmt q; |
| 752 | db_prepare(&q, |
| 753 | "SELECT uuid FROM phantom CROSS JOIN blob USING(rid) /*scan*/" |
| 754 | " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s", |
| 755 | (pXfer->syncPrivate ? "" : |
| 756 | " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)") |
| 757 | ); |
| 758 | while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){ |
| 759 | const char *zUuid = db_column_text(&q, 0); |
| @@ -1203,10 +1216,11 @@ | |
| 1203 | g.xferPanic = 1; |
| 1204 | |
| 1205 | db_begin_transaction(); |
| 1206 | db_multi_exec( |
| 1207 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 1208 | ); |
| 1209 | manifest_crosslink_begin(); |
| 1210 | rc = xfer_run_common_script(); |
| 1211 | if( rc==TH_ERROR ){ |
| 1212 | cgi_reset_content(); |
| @@ -1286,10 +1300,11 @@ | |
| 1286 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 1287 | && xfer.nToken==2 |
| 1288 | && blob_is_hname(&xfer.aToken[1]) |
| 1289 | ){ |
| 1290 | nGimme++; |
| 1291 | if( isPull ){ |
| 1292 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 1293 | if( rid ){ |
| 1294 | send_file(&xfer, rid, &xfer.aToken[1], deltaFlag); |
| 1295 | } |
| @@ -1724,11 +1739,11 @@ | |
| 1724 | }else if( isPull ){ |
| 1725 | create_cluster(); |
| 1726 | send_unclustered(&xfer); |
| 1727 | if( xfer.syncPrivate ) send_private(&xfer); |
| 1728 | } |
| 1729 | db_multi_exec("DROP TABLE onremote"); |
| 1730 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 1731 | |
| 1732 | /* Send the server timestamp last, in case prior processing happened |
| 1733 | ** to use up a significant fraction of our time window. |
| 1734 | */ |
| @@ -1964,10 +1979,11 @@ | |
| 1964 | char *zRandomness; |
| 1965 | db_begin_transaction(); |
| 1966 | db_record_repository_filename(0); |
| 1967 | db_multi_exec( |
| 1968 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 1969 | ); |
| 1970 | manifest_crosslink_begin(); |
| 1971 | |
| 1972 | |
| 1973 | /* Client sends the most recently received cookie back to the server. |
| @@ -2227,10 +2243,11 @@ | |
| 2227 | */ |
| 2228 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 2229 | && xfer.nToken==2 |
| 2230 | && blob_is_hname(&xfer.aToken[1]) |
| 2231 | ){ |
| 2232 | if( syncFlags & SYNC_PUSH ){ |
| 2233 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 2234 | if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0); |
| 2235 | } |
| 2236 | }else |
| @@ -2603,11 +2620,11 @@ | |
| 2603 | |
| 2604 | /* Continue looping as long as new uvfile cards are being received |
| 2605 | ** and uvgimme cards are being sent. */ |
| 2606 | if( nUvGimmeSent>0 && (nUvFileRcvd>0 || nCycle<3) ) go = 1; |
| 2607 | |
| 2608 | db_multi_exec("DROP TABLE onremote"); |
| 2609 | if( go ){ |
| 2610 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 2611 | }else{ |
| 2612 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 2613 | content_enable_dephantomize(1); |
| @@ -2630,11 +2647,11 @@ | |
| 2630 | "%s done, sent: %lld received: %lld ip: %s\n", |
| 2631 | zOpType, nSent, nRcvd, g.zIpAddr); |
| 2632 | transport_close(&g.url); |
| 2633 | transport_global_shutdown(&g.url); |
| 2634 | if( nErr && go==2 ){ |
| 2635 | db_multi_exec("DROP TABLE onremote"); |
| 2636 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 2637 | content_enable_dephantomize(1); |
| 2638 | db_end_transaction(0); |
| 2639 | } |
| 2640 | if( nErr && autopushFailed ){ |
| 2641 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -96,10 +96,22 @@ | |
| 96 | db_bind_int(&q, ":r", rid); |
| 97 | db_step(&q); |
| 98 | db_reset(&q); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | /* |
| 103 | ** Remember that the other side of the connection lacks a copy of |
| 104 | ** the artifact with the given hash. |
| 105 | */ |
| 106 | static void remote_unk(Blob *pHash){ |
| 107 | static Stmt q; |
| 108 | db_static_prepare(&q, "INSERT OR IGNORE INTO unk VALUES(:h)"); |
| 109 | db_bind_text(&q, ":h", blob_str(pHash)); |
| 110 | db_step(&q); |
| 111 | db_reset(&q); |
| 112 | } |
| 113 | |
| 114 | /* |
| 115 | ** The aToken[0..nToken-1] blob array is a parse of a "file" line |
| 116 | ** message. This routine finishes parsing that message and does |
| 117 | ** a record insert of the file. |
| @@ -749,11 +761,12 @@ | |
| 761 | */ |
| 762 | static void request_phantoms(Xfer *pXfer, int maxReq){ |
| 763 | Stmt q; |
| 764 | db_prepare(&q, |
| 765 | "SELECT uuid FROM phantom CROSS JOIN blob USING(rid) /*scan*/" |
| 766 | " WHERE NOT EXISTS(SELECT 1 FROM unk WHERE unk.uuid=blob.uuid)" |
| 767 | " AND NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s", |
| 768 | (pXfer->syncPrivate ? "" : |
| 769 | " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)") |
| 770 | ); |
| 771 | while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){ |
| 772 | const char *zUuid = db_column_text(&q, 0); |
| @@ -1203,10 +1216,11 @@ | |
| 1216 | g.xferPanic = 1; |
| 1217 | |
| 1218 | db_begin_transaction(); |
| 1219 | db_multi_exec( |
| 1220 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 1221 | "CREATE TEMP TABLE unk(uuid TEXT PRIMARY KEY) WITHOUT ROWID;" |
| 1222 | ); |
| 1223 | manifest_crosslink_begin(); |
| 1224 | rc = xfer_run_common_script(); |
| 1225 | if( rc==TH_ERROR ){ |
| 1226 | cgi_reset_content(); |
| @@ -1286,10 +1300,11 @@ | |
| 1300 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 1301 | && xfer.nToken==2 |
| 1302 | && blob_is_hname(&xfer.aToken[1]) |
| 1303 | ){ |
| 1304 | nGimme++; |
| 1305 | remote_unk(&xfer.aToken[1]); |
| 1306 | if( isPull ){ |
| 1307 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 1308 | if( rid ){ |
| 1309 | send_file(&xfer, rid, &xfer.aToken[1], deltaFlag); |
| 1310 | } |
| @@ -1724,11 +1739,11 @@ | |
| 1739 | }else if( isPull ){ |
| 1740 | create_cluster(); |
| 1741 | send_unclustered(&xfer); |
| 1742 | if( xfer.syncPrivate ) send_private(&xfer); |
| 1743 | } |
| 1744 | db_multi_exec("DROP TABLE onremote; DROP TABLE unk;"); |
| 1745 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 1746 | |
| 1747 | /* Send the server timestamp last, in case prior processing happened |
| 1748 | ** to use up a significant fraction of our time window. |
| 1749 | */ |
| @@ -1964,10 +1979,11 @@ | |
| 1979 | char *zRandomness; |
| 1980 | db_begin_transaction(); |
| 1981 | db_record_repository_filename(0); |
| 1982 | db_multi_exec( |
| 1983 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 1984 | "CREATE TEMP TABLE unk(uuid TEXT PRIMARY KEY) WITHOUT ROWID;" |
| 1985 | ); |
| 1986 | manifest_crosslink_begin(); |
| 1987 | |
| 1988 | |
| 1989 | /* Client sends the most recently received cookie back to the server. |
| @@ -2227,10 +2243,11 @@ | |
| 2243 | */ |
| 2244 | if( blob_eq(&xfer.aToken[0], "gimme") |
| 2245 | && xfer.nToken==2 |
| 2246 | && blob_is_hname(&xfer.aToken[1]) |
| 2247 | ){ |
| 2248 | remote_unk(&xfer.aToken[1]); |
| 2249 | if( syncFlags & SYNC_PUSH ){ |
| 2250 | int rid = rid_from_uuid(&xfer.aToken[1], 0, 0); |
| 2251 | if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0); |
| 2252 | } |
| 2253 | }else |
| @@ -2603,11 +2620,11 @@ | |
| 2620 | |
| 2621 | /* Continue looping as long as new uvfile cards are being received |
| 2622 | ** and uvgimme cards are being sent. */ |
| 2623 | if( nUvGimmeSent>0 && (nUvFileRcvd>0 || nCycle<3) ) go = 1; |
| 2624 | |
| 2625 | db_multi_exec("DROP TABLE onremote; DROP TABLE unk;"); |
| 2626 | if( go ){ |
| 2627 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 2628 | }else{ |
| 2629 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 2630 | content_enable_dephantomize(1); |
| @@ -2630,11 +2647,11 @@ | |
| 2647 | "%s done, sent: %lld received: %lld ip: %s\n", |
| 2648 | zOpType, nSent, nRcvd, g.zIpAddr); |
| 2649 | transport_close(&g.url); |
| 2650 | transport_global_shutdown(&g.url); |
| 2651 | if( nErr && go==2 ){ |
| 2652 | db_multi_exec("DROP TABLE onremote; DROP TABLE unk;"); |
| 2653 | manifest_crosslink_end(MC_PERMIT_HOOKS); |
| 2654 | content_enable_dephantomize(1); |
| 2655 | db_end_transaction(0); |
| 2656 | } |
| 2657 | if( nErr && autopushFailed ){ |
| 2658 |