]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
New debugging options: --logfile, --errorfile, --remote-errorfile.
authordrh <>
Sat, 14 Sep 2024 16:03:16 +0000 (16:03 +0000)
committerdrh <>
Sat, 14 Sep 2024 16:03:16 +0000 (16:03 +0000)
If page 1 changes, always send it last.

FossilOrigin-Name: 2d8cd76691554578e987ce682cf0c42c083711dd1511a178148978182ef43ba2

manifest
manifest.uuid
tool/sqlite3-rsync.c

index a69024423fda0e4da6077c1a308b3258c8675d19..311c60f135a7d4ad03f415c22a63bbb3a839f05e 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Always\sshow\sthe\s-v\straffic\smessage\seven\sif\sthere\sare\smultiple\s-v\soptions.
-D 2024-09-14T11:38:46.736
+C New\sdebugging\soptions:\s\s--logfile,\s--errorfile,\s--remote-errorfile.\nIf\spage\s1\schanges,\salways\ssend\sit\slast.
+D 2024-09-14T16:03:16.556
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -2174,7 +2174,7 @@ F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
 F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
 F tool/split-sqlite3c.tcl 5aa60643afca558bc732b1444ae81a522326f91e1dc5665b369c54f09e20de60
 F tool/sqldiff.c 847fc8fcfddf5ce4797b7394cad6372f2f5dc17d8186e2ef8fb44d50fae4f44a
-F tool/sqlite3-rsync.c ac2160892a2baf0317d1232c4678db148b90285c422ca3bc3ec3a96194cf4129
+F tool/sqlite3-rsync.c e73e4c7bbaf0a9c41e1ae8e81db45550d6722276ba7c1eda2771faf59ba1ac4f
 F tool/sqlite3_analyzer.c.in 8da2b08f56eeac331a715036cf707cc20f879f231362be0c22efd682e2b89b4f
 F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
 F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
@@ -2213,8 +2213,8 @@ F vsixtest/vsixtest.tcl 6195aba1f12a5e10efc2b8c0009532167be5e301abe5b31385638080
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 30e1b92d5663e24d2f325f2bab35f81b55848ef39d15688e40b9005269626303
-R 3a4c9e53edbc74f8aebbd484815d1c77
+P fc05a5b7f77cdbfcc659d49eb09569a64a172362cb90199e2861028085178f10
+R 0679514ffeda4dcc5dfb35cbac8e373b
 U drh
-Z 7d402ed7dd081ccd3ef9c52fe661c558
+Z e74e05952b36b86ecc8174c3233b0df1
 # Remove this line to create a well-formed Fossil manifest.
index 7ae6c7119ab07fed202375b7de38d24a671ad80c..57d9739c3f716f43c47e201de157da6df60c7942 100644 (file)
@@ -1 +1 @@
-fc05a5b7f77cdbfcc659d49eb09569a64a172362cb90199e2861028085178f10
+2d8cd76691554578e987ce682cf0c42c083711dd1511a178148978182ef43ba2
index 47f34b5132094a71be8f6284063f8a9ae312ebb0..f581ba84bf0031ee24926f3d3d994e2c8c157fbf 100644 (file)
@@ -43,6 +43,7 @@ typedef struct SQLiteRsync SQLiteRsync;
 struct SQLiteRsync {
   const char *zOrigin;     /* Name of the origin */
   const char *zReplica;    /* Name of the replica */
+  const char *zErrFile;    /* Append error messages to this file */
   FILE *pOut;              /* Transmit to the other side */
   FILE *pIn;               /* Receive from the other side */
   FILE *pLog;              /* Duplicate output here if not NULL */
@@ -813,6 +814,24 @@ const char *file_tail(const char *z){
   return zTail;
 }
 
+/*
+** Append error message text to the error file, if an error file is
+** specified.  In any case, increment the error count.
+*/
+static void logError(SQLiteRsync *p, const char *zFormat, ...){
+  if( p->zErrFile ){
+    FILE *pErr = fopen(p->zErrFile, "a");
+    if( pErr ){
+      va_list ap;
+      va_start(ap, zFormat);
+      vfprintf(pErr, zFormat, ap);
+      va_end(ap);
+      fclose(pErr);
+    }
+  }
+  p->nErr++;
+}
+
 
 /* Read a single big-endian 32-bit unsigned integer from the input
 ** stream.  Return 0 on success and 1 if there are any errors.
@@ -843,7 +862,7 @@ static int writeUint32(SQLiteRsync *p, unsigned int x){
   buf[0] = x;
   if( p->pLog ) fwrite(buf, sizeof(buf), 1, p->pLog);
   if( fwrite(buf, sizeof(buf), 1, p->pOut)!=1 ){
-    p->nErr++;
+    logError(p, "failed to write 32-bit integer 0x%x", x);
     return 1;
   }
   p->nOut += 4;
@@ -871,7 +890,7 @@ void writeByte(SQLiteRsync *p, int c){
 int readPow2(SQLiteRsync *p){
   int x = readByte(p);
   if( x>=32 ){
-    p->nErr++;
+    logError(p, "read invalid page size %d\n", x);
     return 0;
   }
   return 1<<x;
@@ -882,7 +901,7 @@ int readPow2(SQLiteRsync *p){
 void writePow2(SQLiteRsync *p, int c){
   int n;
   if( c<0 || (c&(c-1))!=0 ){
-    p->nErr++;
+    logError(p, "trying to read invalid page size %d\n", c);
   }
   for(n=0; c>1; n++){ c /= 2; }
   writeByte(p, n);
@@ -894,7 +913,7 @@ void readBytes(SQLiteRsync *p, int nByte, void *pData){
   if( fread(pData, 1, nByte, p->pIn)==nByte ){
     p->nIn += nByte;
   }else{
-    p->nErr++;
+    logError(p, "failed to read %d bytes", nByte);
   }
 }
 
@@ -905,7 +924,7 @@ void writeBytes(SQLiteRsync *p, int nByte, const void *pData){
   if( fwrite(pData, 1, nByte, p->pOut)==nByte ){
     p->nOut += nByte;
   }else{
-    p->nErr++;
+    logError(p, "failed to write %d bytes", nByte);
   }
 }
 
@@ -934,8 +953,8 @@ static void reportError(SQLiteRsync *p, const char *zFormat, ...){
   }else{
     fprintf(stderr, "%s\n", zMsg);
   }
+  logError(p, "%s\n", zMsg);
   sqlite3_free(zMsg);
-  p->nErr++;
 }
 
 /* Send an informational message.
@@ -974,7 +993,6 @@ static void readAndDisplayMessage(SQLiteRsync *p, int c){
   const char *zPrefix;
   if( c==ORIGIN_ERROR || c==REPLICA_ERROR ){
     zPrefix = "ERROR: ";
-    p->nErr++;
   }else{
     zPrefix = "";
   }
@@ -990,6 +1008,7 @@ static void readAndDisplayMessage(SQLiteRsync *p, int c){
     memset(zMsg, 0, n+1);
     readBytes(p, n, zMsg);
     fprintf(stderr,"%s%s\n", zPrefix, zMsg);
+    if( zPrefix[0] ) logError(p, "%s%s\n", zPrefix, zMsg);
     sqlite3_free(zMsg);
   }
 }
@@ -1259,32 +1278,56 @@ static void originSide(SQLiteRsync *p){
       }
       case REPLICA_READY: {
         sqlite3_stmt *pStmt;
+        int needPageOne = 0;
         sqlite3_finalize(pCkHash);
         pCkHash = 0;
+        if( iPage+1<p->nPage ){
+          runSql(p, "WITH RECURSIVE c(n) AS"
+                    " (VALUES(%d) UNION ALL SELECT n+1 FROM c WHERE n<%d)"
+                    " INSERT INTO badHash SELECT n FROM c",
+                    iPage+1, p->nPage);
+        }
         pStmt = prepareStmt(p,
                "SELECT pgno, data"
-               "  FROM badHash JOIN sqlite_dbpage('main') USING(pgno) "
-               "UNION ALL "
-               "SELECT pgno, data"
-               "  FROM sqlite_dbpage('main')"
-               " WHERE pgno>%d",
-               iPage);
+               "  FROM badHash JOIN sqlite_dbpage('main') USING(pgno)");
         if( pStmt==0 ) break;
         while( sqlite3_step(pStmt)==SQLITE_ROW && p->nErr==0 ){
+          unsigned int pgno = (unsigned int)sqlite3_column_int64(pStmt,0);
           const void *pContent = sqlite3_column_blob(pStmt, 1);
-          writeByte(p, ORIGIN_PAGE);
-          writeUint32(p, (unsigned int)sqlite3_column_int64(pStmt, 0));
-          writeBytes(p, szPg, pContent);
-          p->nPageSent++;
+          if( pgno==1 ){
+            needPageOne = 1;
+          }else{
+            writeByte(p, ORIGIN_PAGE);
+            writeUint32(p, (unsigned int)sqlite3_column_int64(pStmt, 0));
+            writeBytes(p, szPg, pContent);
+            p->nPageSent++;
+          }
         }
         sqlite3_finalize(pStmt);
+        if( needPageOne ){
+          pStmt = prepareStmt(p,
+                 "SELECT data"
+                 "  FROM sqlite_dbpage('main')"
+                 " WHERE pgno=1"
+          );
+          if( pStmt==0 ) break;
+          while( sqlite3_step(pStmt)==SQLITE_ROW && p->nErr==0 ){
+            const void *pContent = sqlite3_column_blob(pStmt, 0);
+            writeByte(p, ORIGIN_PAGE);
+            writeUint32(p, 1);
+            writeBytes(p, szPg, pContent);
+            p->nPageSent++;
+          }
+          sqlite3_finalize(pStmt);
+        }
         writeByte(p, ORIGIN_TXN);
         writeUint32(p, nPage);
         writeByte(p, ORIGIN_END);
         goto origin_end;
       }
       default: {
-        reportError(p, "Origin side received unknown message: 0x%02x", c);
+        reportError(p, "Unknown message 0x%02x %lld bytes into conversation",
+                       c, p->nIn);
         break;
       }
     }
@@ -1446,7 +1489,7 @@ static void replicaSide(SQLiteRsync *p){
         if( p->nErr ) break;
         if( pIns==0 ){
           pIns = prepareStmt(p,
-            "INSERT INTO sqlite_dbpage(pgno,data,schema) VALUES(?1,?2,'main')"
+            "INSERT INTO sqlite_dbpage(pgno,data) VALUES(?1,?2)"
           );
           if( pIns==0 ) break;
         }
@@ -1457,14 +1500,15 @@ static void replicaSide(SQLiteRsync *p){
         sqlite3_bind_blob(pIns, 2, buf, szOPage, SQLITE_STATIC);
         rc = sqlite3_step(pIns);
         if( rc!=SQLITE_DONE ){
-          reportError(p, "SQL statement [%s] failed: %s",
-                 sqlite3_sql(pIns), sqlite3_errmsg(p->db));
+          reportError(p, "SQL statement [%s] failed (pgno=%u): %s",
+                 sqlite3_sql(pIns), pgno, sqlite3_errmsg(p->db));
         }
         sqlite3_reset(pIns);
         break;
       }
       default: {
-        reportError(p, "Replica side received unknown message: 0x%02x", c);
+        reportError(p, "Unknown message 0x%02x %lld bytes into conversation",
+                       c, p->nIn);
         break;
       }
     }
@@ -1555,6 +1599,7 @@ int main(int argc, char const * const *argv){
   sqlite3_int64 tmStart;
   sqlite3_int64 tmEnd;
   sqlite3_int64 tmElapse;
+  const char *zRemoteErrFile = 0;
 
 #define cli_opt_val cmdline_option_value(argc, argv, ++i)
   memset(&ctx, 0, sizeof(ctx));
@@ -1581,6 +1626,8 @@ int main(int argc, char const * const *argv){
       continue;
     }
     if( strcmp(z, "--logfile")==0 ){
+      /* DEBUG OPTION:  --logfile FILENAME
+      ** Cause all local output traffic to be duplicated in FILENAME */
       if( ctx.pLog ) fclose(ctx.pLog);
       ctx.pLog = fopen(argv[++i],"wb");
       if( ctx.pLog==0 ){
@@ -1589,6 +1636,19 @@ int main(int argc, char const * const *argv){
       }
       continue;
     }
+    if( strcmp(z, "--errorfile")==0 ){
+      /* DEBUG OPTION:  --errorfile FILENAME
+      ** Error messages on the local side are written into FILENAME */
+      ctx.zErrFile = argv[++i];
+      continue;
+    }
+    if( strcmp(z, "--remote-errorfile")==0 ){
+      /* DEBUG OPTION:  --remote-errorfile FILENAME
+      ** Error messages on the remote side are written into FILENAME on
+      ** the remote side. */
+      zRemoteErrFile = argv[++i];
+      continue;
+    }
     if( strcmp(z, "-help")==0 || strcmp(z, "--help")==0
      || strcmp(z, "-?")==0
     ){
@@ -1678,6 +1738,10 @@ int main(int argc, char const * const *argv){
       append_escaped_arg(pStr, "--commcheck", 0);
       if( ctx.eVerbose==0 ) ctx.eVerbose = 1;
     }
+    if( zRemoteErrFile ){
+      append_escaped_arg(pStr, "--errorfile", 0);
+      append_escaped_arg(pStr, zRemoteErrFile, 1);
+    }
     append_escaped_arg(pStr, zDiv, 1);
     append_escaped_arg(pStr, file_tail(ctx.zReplica), 1);
     zCmd = sqlite3_str_finish(pStr);
@@ -1700,6 +1764,10 @@ int main(int argc, char const * const *argv){
       append_escaped_arg(pStr, "--commcheck", 0);
       if( ctx.eVerbose==0 ) ctx.eVerbose = 1;
     }
+    if( zRemoteErrFile ){
+      append_escaped_arg(pStr, "--errorfile", 0);
+      append_escaped_arg(pStr, zRemoteErrFile, 1);
+    }
     append_escaped_arg(pStr, file_tail(ctx.zOrigin), 1);
     append_escaped_arg(pStr, zDiv, 1);
     zCmd = sqlite3_str_finish(pStr);
@@ -1717,6 +1785,10 @@ int main(int argc, char const * const *argv){
     if( ctx.bCommCheck ){
       append_escaped_arg(pStr, "--commcheck", 0);
     }
+    if( zRemoteErrFile ){
+      append_escaped_arg(pStr, "--errorfile", 0);
+      append_escaped_arg(pStr, zRemoteErrFile, 1);
+    }
     append_escaped_arg(pStr, ctx.zOrigin, 1);
     append_escaped_arg(pStr, ctx.zReplica, 1);
     zCmd = sqlite3_str_finish(pStr);