Fossil SCM
Sync opertions warn about clock skew between client and server.
Commit
71c40d3bdb9186b96d34d2be3683d8a83e7fa273
Parent
fa29769a3d411ff…
2 files changed
+43
+18
-1
M
src/db.c
+43
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -1640,5 +1640,48 @@ | ||
| 1640 | 1640 | } |
| 1641 | 1641 | }else{ |
| 1642 | 1642 | usage("?PROPERTY? ?VALUE?"); |
| 1643 | 1643 | } |
| 1644 | 1644 | } |
| 1645 | + | |
| 1646 | +/* | |
| 1647 | +** The input in a a timespan measured in days. Return a string which | |
| 1648 | +** describes that timespan in units of seconds, minutes, hours, days, | |
| 1649 | +** or years, depending on its duration. | |
| 1650 | +*/ | |
| 1651 | +char *db_timespan_name(double rSpan){ | |
| 1652 | + if( rSpan<0 ) rSpan = -rSpan; | |
| 1653 | + rSpan *= 24.0*3600.0; /* Convert units to seconds */ | |
| 1654 | + if( rSpan<120.0 ){ | |
| 1655 | + return sqlite3_mprintf("%.1f seconds", rSpan); | |
| 1656 | + } | |
| 1657 | + rSpan /= 60.0; /* Convert units to minutes */ | |
| 1658 | + if( rSpan<90.0 ){ | |
| 1659 | + return sqlite3_mprintf("%.1f minutes", rSpan); | |
| 1660 | + } | |
| 1661 | + rSpan /= 60.0; /* Convert units to hours */ | |
| 1662 | + if( rSpan<=48.0 ){ | |
| 1663 | + return sqlite3_mprintf("%.1f hours", rSpan); | |
| 1664 | + } | |
| 1665 | + rSpan /= 24.0; /* Convert units to days */ | |
| 1666 | + if( rSpan<=365.0 ){ | |
| 1667 | + return sqlite3_mprintf("%.1f days", rSpan); | |
| 1668 | + } | |
| 1669 | + rSpan /= 356.24; /* Convert units to years */ | |
| 1670 | + return sqlite3_mprintf("%.1f years", rSpan); | |
| 1671 | +} | |
| 1672 | + | |
| 1673 | +/* | |
| 1674 | +** COMMAND: test-timespan | |
| 1675 | +** %fossil test-timespan TIMESTAMP | |
| 1676 | +** | |
| 1677 | +** Print the approximate span of time from now to TIMESTAMP. | |
| 1678 | +*/ | |
| 1679 | +void test_timespan_cmd(void){ | |
| 1680 | + double rDiff; | |
| 1681 | + if( g.argc!=3 ) usage("TIMESTAMP"); | |
| 1682 | + sqlite3_open(":memory:", &g.db); | |
| 1683 | + rDiff = db_double(0.0, "SELECT julianday('now') - julianday(%Q)", g.argv[2]); | |
| 1684 | + printf("Time differences: %s\n", db_timespan_name(rDiff)); | |
| 1685 | + sqlite3_close(g.db); | |
| 1686 | + g.db = 0; | |
| 1687 | +} | |
| 1645 | 1688 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1640,5 +1640,48 @@ | |
| 1640 | } |
| 1641 | }else{ |
| 1642 | usage("?PROPERTY? ?VALUE?"); |
| 1643 | } |
| 1644 | } |
| 1645 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1640,5 +1640,48 @@ | |
| 1640 | } |
| 1641 | }else{ |
| 1642 | usage("?PROPERTY? ?VALUE?"); |
| 1643 | } |
| 1644 | } |
| 1645 | |
| 1646 | /* |
| 1647 | ** The input in a a timespan measured in days. Return a string which |
| 1648 | ** describes that timespan in units of seconds, minutes, hours, days, |
| 1649 | ** or years, depending on its duration. |
| 1650 | */ |
| 1651 | char *db_timespan_name(double rSpan){ |
| 1652 | if( rSpan<0 ) rSpan = -rSpan; |
| 1653 | rSpan *= 24.0*3600.0; /* Convert units to seconds */ |
| 1654 | if( rSpan<120.0 ){ |
| 1655 | return sqlite3_mprintf("%.1f seconds", rSpan); |
| 1656 | } |
| 1657 | rSpan /= 60.0; /* Convert units to minutes */ |
| 1658 | if( rSpan<90.0 ){ |
| 1659 | return sqlite3_mprintf("%.1f minutes", rSpan); |
| 1660 | } |
| 1661 | rSpan /= 60.0; /* Convert units to hours */ |
| 1662 | if( rSpan<=48.0 ){ |
| 1663 | return sqlite3_mprintf("%.1f hours", rSpan); |
| 1664 | } |
| 1665 | rSpan /= 24.0; /* Convert units to days */ |
| 1666 | if( rSpan<=365.0 ){ |
| 1667 | return sqlite3_mprintf("%.1f days", rSpan); |
| 1668 | } |
| 1669 | rSpan /= 356.24; /* Convert units to years */ |
| 1670 | return sqlite3_mprintf("%.1f years", rSpan); |
| 1671 | } |
| 1672 | |
| 1673 | /* |
| 1674 | ** COMMAND: test-timespan |
| 1675 | ** %fossil test-timespan TIMESTAMP |
| 1676 | ** |
| 1677 | ** Print the approximate span of time from now to TIMESTAMP. |
| 1678 | */ |
| 1679 | void test_timespan_cmd(void){ |
| 1680 | double rDiff; |
| 1681 | if( g.argc!=3 ) usage("TIMESTAMP"); |
| 1682 | sqlite3_open(":memory:", &g.db); |
| 1683 | rDiff = db_double(0.0, "SELECT julianday('now') - julianday(%Q)", g.argv[2]); |
| 1684 | printf("Time differences: %s\n", db_timespan_name(rDiff)); |
| 1685 | sqlite3_close(g.db); |
| 1686 | g.db = 0; |
| 1687 | } |
| 1688 |
+18
-1
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -476,11 +476,11 @@ | ||
| 476 | 476 | ** But if we do (because of a bug) now is a good time to delete them. */ |
| 477 | 477 | db_multi_exec( |
| 478 | 478 | "DELETE FROM unclustered WHERE rid IN (SELECT rid FROM private)" |
| 479 | 479 | ); |
| 480 | 480 | |
| 481 | - nUncl = db_int(0, "SELECT count(*) FROM unclustered" | |
| 481 | + nUncl = db_int(0, "SELECT count(*) FROM unclustered /*scan*/" | |
| 482 | 482 | " WHERE NOT EXISTS(SELECT 1 FROM phantom" |
| 483 | 483 | " WHERE rid=unclustered.rid)"); |
| 484 | 484 | if( nUncl<100 ){ |
| 485 | 485 | return; |
| 486 | 486 | } |
| @@ -593,10 +593,11 @@ | ||
| 593 | 593 | int deltaFlag = 0; |
| 594 | 594 | int isClone = 0; |
| 595 | 595 | int nGimme = 0; |
| 596 | 596 | int size; |
| 597 | 597 | int recvConfig = 0; |
| 598 | + char *zNow; | |
| 598 | 599 | |
| 599 | 600 | if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){ |
| 600 | 601 | fossil_redirect_home(); |
| 601 | 602 | } |
| 602 | 603 | memset(&xfer, 0, sizeof(xfer)); |
| @@ -610,10 +611,12 @@ | ||
| 610 | 611 | |
| 611 | 612 | db_begin_transaction(); |
| 612 | 613 | db_multi_exec( |
| 613 | 614 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 614 | 615 | ); |
| 616 | + zNow = db_text(0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%S', 'now')"); | |
| 617 | + @ # timestamp %s(zNow) | |
| 615 | 618 | manifest_crosslink_begin(); |
| 616 | 619 | while( blob_line(xfer.pIn, &xfer.line) ){ |
| 617 | 620 | if( blob_buffer(&xfer.line)[0]=='#' ) continue; |
| 618 | 621 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 619 | 622 | |
| @@ -1082,10 +1085,24 @@ | ||
| 1082 | 1085 | go = 0; |
| 1083 | 1086 | |
| 1084 | 1087 | /* Process the reply that came back from the server */ |
| 1085 | 1088 | while( blob_line(&recv, &xfer.line) ){ |
| 1086 | 1089 | if( blob_buffer(&xfer.line)[0]=='#' ){ |
| 1090 | + const char *zLine = blob_buffer(&xfer.line); | |
| 1091 | + if( memcmp(zLine, "# timestamp ", 12)==0 ){ | |
| 1092 | + char zTime[20]; | |
| 1093 | + double rDiff; | |
| 1094 | + sqlite3_snprintf(sizeof(zTime), zTime, "%.19s", &zLine[12]); | |
| 1095 | + rDiff = db_double(9e99, "SELECT julianday('%q') - julianday('now')", | |
| 1096 | + zTime); | |
| 1097 | + if( rDiff<0.0 ) rDiff = -rDiff; | |
| 1098 | + if( rDiff>9e98 ) rDiff = 0.0; | |
| 1099 | + if( (rDiff*24.0*3600.0)>=60.0 ){ | |
| 1100 | + fossil_warning("*** time skew *** server time differs by %s", | |
| 1101 | + db_timespan_name(rDiff)); | |
| 1102 | + } | |
| 1103 | + } | |
| 1087 | 1104 | continue; |
| 1088 | 1105 | } |
| 1089 | 1106 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 1090 | 1107 | nCardRcvd++; |
| 1091 | 1108 | if( !g.cgiOutput && !g.fQuiet ){ |
| 1092 | 1109 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -476,11 +476,11 @@ | |
| 476 | ** But if we do (because of a bug) now is a good time to delete them. */ |
| 477 | db_multi_exec( |
| 478 | "DELETE FROM unclustered WHERE rid IN (SELECT rid FROM private)" |
| 479 | ); |
| 480 | |
| 481 | nUncl = db_int(0, "SELECT count(*) FROM unclustered" |
| 482 | " WHERE NOT EXISTS(SELECT 1 FROM phantom" |
| 483 | " WHERE rid=unclustered.rid)"); |
| 484 | if( nUncl<100 ){ |
| 485 | return; |
| 486 | } |
| @@ -593,10 +593,11 @@ | |
| 593 | int deltaFlag = 0; |
| 594 | int isClone = 0; |
| 595 | int nGimme = 0; |
| 596 | int size; |
| 597 | int recvConfig = 0; |
| 598 | |
| 599 | if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){ |
| 600 | fossil_redirect_home(); |
| 601 | } |
| 602 | memset(&xfer, 0, sizeof(xfer)); |
| @@ -610,10 +611,12 @@ | |
| 610 | |
| 611 | db_begin_transaction(); |
| 612 | db_multi_exec( |
| 613 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 614 | ); |
| 615 | manifest_crosslink_begin(); |
| 616 | while( blob_line(xfer.pIn, &xfer.line) ){ |
| 617 | if( blob_buffer(&xfer.line)[0]=='#' ) continue; |
| 618 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 619 | |
| @@ -1082,10 +1085,24 @@ | |
| 1082 | go = 0; |
| 1083 | |
| 1084 | /* Process the reply that came back from the server */ |
| 1085 | while( blob_line(&recv, &xfer.line) ){ |
| 1086 | if( blob_buffer(&xfer.line)[0]=='#' ){ |
| 1087 | continue; |
| 1088 | } |
| 1089 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 1090 | nCardRcvd++; |
| 1091 | if( !g.cgiOutput && !g.fQuiet ){ |
| 1092 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -476,11 +476,11 @@ | |
| 476 | ** But if we do (because of a bug) now is a good time to delete them. */ |
| 477 | db_multi_exec( |
| 478 | "DELETE FROM unclustered WHERE rid IN (SELECT rid FROM private)" |
| 479 | ); |
| 480 | |
| 481 | nUncl = db_int(0, "SELECT count(*) FROM unclustered /*scan*/" |
| 482 | " WHERE NOT EXISTS(SELECT 1 FROM phantom" |
| 483 | " WHERE rid=unclustered.rid)"); |
| 484 | if( nUncl<100 ){ |
| 485 | return; |
| 486 | } |
| @@ -593,10 +593,11 @@ | |
| 593 | int deltaFlag = 0; |
| 594 | int isClone = 0; |
| 595 | int nGimme = 0; |
| 596 | int size; |
| 597 | int recvConfig = 0; |
| 598 | char *zNow; |
| 599 | |
| 600 | if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){ |
| 601 | fossil_redirect_home(); |
| 602 | } |
| 603 | memset(&xfer, 0, sizeof(xfer)); |
| @@ -610,10 +611,12 @@ | |
| 611 | |
| 612 | db_begin_transaction(); |
| 613 | db_multi_exec( |
| 614 | "CREATE TEMP TABLE onremote(rid INTEGER PRIMARY KEY);" |
| 615 | ); |
| 616 | zNow = db_text(0, "SELECT strftime('%%Y-%%m-%%dT%%H:%%M:%%S', 'now')"); |
| 617 | @ # timestamp %s(zNow) |
| 618 | manifest_crosslink_begin(); |
| 619 | while( blob_line(xfer.pIn, &xfer.line) ){ |
| 620 | if( blob_buffer(&xfer.line)[0]=='#' ) continue; |
| 621 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 622 | |
| @@ -1082,10 +1085,24 @@ | |
| 1085 | go = 0; |
| 1086 | |
| 1087 | /* Process the reply that came back from the server */ |
| 1088 | while( blob_line(&recv, &xfer.line) ){ |
| 1089 | if( blob_buffer(&xfer.line)[0]=='#' ){ |
| 1090 | const char *zLine = blob_buffer(&xfer.line); |
| 1091 | if( memcmp(zLine, "# timestamp ", 12)==0 ){ |
| 1092 | char zTime[20]; |
| 1093 | double rDiff; |
| 1094 | sqlite3_snprintf(sizeof(zTime), zTime, "%.19s", &zLine[12]); |
| 1095 | rDiff = db_double(9e99, "SELECT julianday('%q') - julianday('now')", |
| 1096 | zTime); |
| 1097 | if( rDiff<0.0 ) rDiff = -rDiff; |
| 1098 | if( rDiff>9e98 ) rDiff = 0.0; |
| 1099 | if( (rDiff*24.0*3600.0)>=60.0 ){ |
| 1100 | fossil_warning("*** time skew *** server time differs by %s", |
| 1101 | db_timespan_name(rDiff)); |
| 1102 | } |
| 1103 | } |
| 1104 | continue; |
| 1105 | } |
| 1106 | xfer.nToken = blob_tokenize(&xfer.line, xfer.aToken, count(xfer.aToken)); |
| 1107 | nCardRcvd++; |
| 1108 | if( !g.cgiOutput && !g.fQuiet ){ |
| 1109 |