-C Pass\sthe\snames\sof\sboth\sthe\sorigin\sand\sthe\sreplica\sdatabases\sto\sthe\sremote\nside,\sso\sthat\sif\sthe\sremote\sis\sthe\sreplica,\sit\swill\shave\saccess\sto\sthe\norigin\sdatabase\sname\sin\scase\sthe\sreplica\sname\sis\sreally\sa\sdirectory.
-D 2024-09-12T15:51:56.339
+C Improved\s--commcheck.\s\sAdd\sthe\sinfoMsg()\sfunction\swhich\sis\suseful\sfor\ndebugging.
+D 2024-09-12T16:54:34.620
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
F tool/split-sqlite3c.tcl 5aa60643afca558bc732b1444ae81a522326f91e1dc5665b369c54f09e20de60
F tool/sqldiff.c 847fc8fcfddf5ce4797b7394cad6372f2f5dc17d8186e2ef8fb44d50fae4f44a
-F tool/sqlite3-rsync.c 7b7d24177b27f42dfcd7e962be4a526e775b073f2044cd1f7d3414581810baea
+F tool/sqlite3-rsync.c 72632a237c91c97a7320cf064b8f2d6662721b61fc5f123e40e6d272207b4a96
F tool/sqlite3_analyzer.c.in 8da2b08f56eeac331a715036cf707cc20f879f231362be0c22efd682e2b89b4f
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P df0623aae1154281157409f62d6d3fb3ce41829281d53bc55868ce44b3d36883
-R 137e53956a972f25c62e4e4b74ab6074
+P 435c30171d3c6073b7aaf5cc11cc4813f6a2d225ae6dce1b0e478f0cd5a0b532
+R aafd9793078a7056ec93ac4f3aad0430
U drh
-Z 061042360cfb45012e27693425840440
+Z 9f40e243e2ff00f83272b62111b602fb
# Remove this line to create a well-formed Fossil manifest.
u8 eVerbose; /* Bigger for more output. 0 means none. */
u8 bCommCheck; /* True to debug the communication protocol */
u8 isRemote; /* On the remote side of a connection */
+ u8 isReplica; /* True if running on the replica side */
u8 iProtocol; /* Protocol version number */
sqlite3_uint64 nOut; /* Bytes transmitted */
sqlite3_uint64 nIn; /* Bytes received */
#define ORIGIN_ERROR 0x43 /* Error message from the remote */
#define ORIGIN_PAGE 0x44 /* New page data */
#define ORIGIN_TXN 0x45 /* Transaction commit */
+#define ORIGIN_MSG 0x46 /* Informational message */
#define REPLICA_BEGIN 0x61 /* Welcome message */
#define REPLICA_ERROR 0x62 /* Error. Report and quit. */
#define REPLICA_END 0x63 /* Replica wants to stop */
#define REPLICA_HASH 0x64 /* One or more pages hashes to report */
#define REPLICA_READY 0x65 /* Read to receive page content */
+#define REPLICA_MSG 0x66 /* Informational message */
/****************************************************************************
** End of the append_escaped_arg() routine, adapted from the Fossil **
*****************************************************************************/
-
-/* For Debugging, specifically for --commcheck:
-**
-** Read a single line of text from p->pIn. Write this to standard
-** output if and only if p->eVerbose>0.
-*/
-static void echoOneLine(SQLiteRsync *p){
- char zLine[1000];
- if( fgets(zLine, sizeof(zLine), p->pIn) ){
- if( p->eVerbose ) printf("GOT: %s", zLine);
- }
-}
-
/*
** Return the tail of a file pathname. The tail is the last component
** of the path. For example, the tail of "/a/b/c.d" is "c.d".
/* Report an error.
**
-** If this happens on the remote side, we send back a REMOTE_ERROR
+** If this happens on the remote side, we send back a *_ERROR
** message. On the local side, the error message goes to stderr.
*/
static void reportError(SQLiteRsync *p, const char *zFormat, ...){
va_end(ap);
nMsg = zMsg ? (unsigned int)strlen(zMsg) : 0;
if( p->isRemote ){
- if( p->zReplica ){
+ if( p->isReplica ){
putc(REPLICA_ERROR, p->pOut);
}else{
putc(ORIGIN_ERROR, p->pOut);
p->nErr++;
}
+/* Send an informational message.
+**
+** If this happens on the remote side, we send back a *_MSG
+** message. On the local side, the message goes to stdout.
+*/
+static void infoMsg(SQLiteRsync *p, const char *zFormat, ...){
+ va_list ap;
+ char *zMsg;
+ unsigned int nMsg;
+ va_start(ap, zFormat);
+ zMsg = sqlite3_vmprintf(zFormat, ap);
+ va_end(ap);
+ nMsg = zMsg ? (unsigned int)strlen(zMsg) : 0;
+ if( p->isRemote ){
+ if( p->isReplica ){
+ putc(REPLICA_MSG, p->pOut);
+ }else{
+ putc(ORIGIN_MSG, p->pOut);
+ }
+ writeUint32(p, nMsg);
+ writeBytes(p, nMsg, zMsg);
+ fflush(p->pOut);
+ }else{
+ printf("%s\n", zMsg);
+ }
+ sqlite3_free(zMsg);
+}
+
/* Receive and report an error message coming from the other side.
*/
-static void readAndDisplayError(SQLiteRsync *p){
+static void readAndDisplayMessage(SQLiteRsync *p, int c){
unsigned int n = 0;
char *zMsg;
- (void)readUint32(p, &n);
+ const char *zPrefix;
+ if( c==ORIGIN_ERROR || c==REPLICA_ERROR ){
+ zPrefix = "ERROR: ";
+ p->nErr++;
+ }else{
+ zPrefix = "";
+ }
+ readUint32(p, &n);
if( n==0 ){
fprintf(stderr,"ERROR: unknown (possibly out-of-memory)\n");
}else{
}
memset(zMsg, 0, n+1);
readBytes(p, n, zMsg);
- fprintf(stderr,"ERROR: %s\n", zMsg);
+ fprintf(stderr,"%s%s\n", zPrefix, zMsg);
sqlite3_free(zMsg);
}
- p->nErr++;
}
/* Construct a new prepared statement. Report an error and return NULL
sqlite3_stmt *pCkHash = 0;
char buf[200];
+ p->isReplica = 0;
if( p->bCommCheck ){
- fprintf(p->pOut, "sqlite3-rsync origin-begin %s\n", p->zOrigin);
- fflush(p->pOut);
- echoOneLine(p);
- fprintf(p->pOut, "origin-end\n");
- fflush(p->pOut);
- echoOneLine(p);
- return;
- }
-
- /* Open the ORIGIN database. */
- rc = sqlite3_open_v2(p->zOrigin, &p->db, SQLITE_OPEN_READWRITE, 0);
- if( rc ){
- reportError(p, "unable to open origin database file \"%s\": %s",
- sqlite3_errmsg(p->db));
- closeDb(p);
- return;
- }
- sqlite3_sha_init(p->db, 0, 0);
- runSql(p, "BEGIN");
- runSqlReturnText(p, buf, "PRAGMA journal_mode");
- if( sqlite3_stricmp(buf,"wal")!=0 ){
- reportError(p, "Origin database is not in WAL mode");
- }
- runSqlReturnUInt(p, &nPage, "PRAGMA page_count");
- runSqlReturnUInt(p, &szPg, "PRAGMA page_size");
-
- if( p->nErr==0 ){
- /* Send the ORIGIN_BEGIN message */
- writeByte(p, ORIGIN_BEGIN);
- writeByte(p, PROTOCOL_VERSION);
- writePow2(p, szPg);
- writeUint32(p, nPage);
+ infoMsg(p, "origin zOrigin=%Q zReplica=%Q isRemote=%d protocol=%d",
+ p->zOrigin, p->zReplica, p->isRemote, PROTOCOL_VERSION);
+ writeByte(p, ORIGIN_END);
fflush(p->pOut);
- p->nPage = nPage;
- p->szPage = szPg;
- p->iProtocol = PROTOCOL_VERSION;
+ }else{
+ /* Open the ORIGIN database. */
+ rc = sqlite3_open_v2(p->zOrigin, &p->db, SQLITE_OPEN_READWRITE, 0);
+ if( rc ){
+ reportError(p, "unable to open origin database file \"%s\": %s",
+ sqlite3_errmsg(p->db));
+ closeDb(p);
+ return;
+ }
+ sqlite3_sha_init(p->db, 0, 0);
+ runSql(p, "BEGIN");
+ runSqlReturnText(p, buf, "PRAGMA journal_mode");
+ if( sqlite3_stricmp(buf,"wal")!=0 ){
+ reportError(p, "Origin database is not in WAL mode");
+ }
+ runSqlReturnUInt(p, &nPage, "PRAGMA page_count");
+ runSqlReturnUInt(p, &szPg, "PRAGMA page_size");
+
+ if( p->nErr==0 ){
+ /* Send the ORIGIN_BEGIN message */
+ writeByte(p, ORIGIN_BEGIN);
+ writeByte(p, PROTOCOL_VERSION);
+ writePow2(p, szPg);
+ writeUint32(p, nPage);
+ fflush(p->pOut);
+ p->nPage = nPage;
+ p->szPage = szPg;
+ p->iProtocol = PROTOCOL_VERSION;
+ }
}
-
+
/* Respond to message from the replica */
while( p->nErr==0 && (c = readByte(p))!=EOF && c!=REPLICA_END ){
switch( c ){
writeUint32(p, p->nPage);
break;
}
+ case REPLICA_MSG:
case REPLICA_ERROR: {
- readAndDisplayError(p);
+ readAndDisplayMessage(p, c);
break;
}
case REPLICA_HASH: {
sqlite3_stmt *pIns = 0;
unsigned int szOPage = 0;
char buf[65536];
+
+ p->isReplica = 1;
if( p->bCommCheck ){
- echoOneLine(p);
- fprintf(p->pOut, "replica-begin %s\n", p->zReplica);
- fflush(p->pOut);
- echoOneLine(p);
- fprintf(p->pOut, "replica-end\n");
+ infoMsg(p, "replica zOrigin=%Q zReplica=%Q isRemote=%d protocol=%d",
+ p->zOrigin, p->zReplica, p->isRemote, PROTOCOL_VERSION);
+ writeByte(p, REPLICA_END);
fflush(p->pOut);
- return;
}
/* Respond to message from the origin. The origin will initiate the
*/
while( p->nErr==0 && (c = readByte(p))!=EOF && c!=ORIGIN_END ){
switch( c ){
+ case ORIGIN_MSG:
case ORIGIN_ERROR: {
- readAndDisplayError(p);
+ readAndDisplayMessage(p, c);
break;
}
case ORIGIN_BEGIN: {