]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Make use of the extra information in the WAL header and frame header to
authordrh <drh@noemail.net>
Thu, 20 May 2010 21:21:09 +0000 (21:21 +0000)
committerdrh <drh@noemail.net>
Thu, 20 May 2010 21:21:09 +0000 (21:21 +0000)
enhance robustness.

FossilOrigin-Name: 9580ecb7e3beb1949a71784a3dcd1823a88e4a9d

manifest
manifest.uuid
src/wal.c
test/wal.test
test/wal2.test

index a63f4d3873eebe8afdb95588abba999d576c1024..52aed1db639398b42a6969f24fd1eeb2e56ab8de 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,8 @@
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
-C Convert\sthe\swal-header\sand\sframe-header\sto\s24\sbytes.\s\sExtra\sinformation\sin\nboth\sheaders\sis\sdesigned\sto\senhance\srobustness\safter\scrashes,\sthough\sthe\nextra\sinformation\sis\scurrently\sunused.\s\sThis\sis\sa\ssnapshot\sof\sa\swork\sin\nprogress.
-D 2010-05-20T16:45:59
+C Make\suse\sof\sthe\sextra\sinformation\sin\sthe\sWAL\sheader\sand\sframe\sheader\sto\nenhance\srobustness.
+D 2010-05-20T21:21:10
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -227,7 +227,7 @@ F src/vdbeblob.c 5327132a42a91e8b7acfb60b9d2c3b1c5c863e0e
 F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
 F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda
-F src/wal.c 25969e598b3ce8748295801826cda538232d9200
+F src/wal.c fd4377f7fe58cd5063b547b7f0f9a220d68335de
 F src/wal.h 434f76f51225bb614e43ccb6bd2341541ba6a06e
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
 F src/where.c 75fee9e255b62f773fcadd1d1f25b6f63ac7a356
@@ -764,8 +764,8 @@ F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
 F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
 F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
-F test/wal.test 1ea87f3bc6c597ea6ca10e9f5f819c0e6c0ce2f8
-F test/wal2.test 03059bc4d450c37f4b53278ddc3e2c7d53ac2d3f
+F test/wal.test 90afd254ece957a716751b1c35fac02d6353c2a7
+F test/wal2.test ed0d505726343408b8f88b281dadc95ba0a00ba2
 F test/walbak.test e7650a26eb4b8abeca9b145b1af1e63026dde432
 F test/walcrash.test f6d5fb2bb108876f04848720a488065d9deef69f
 F test/walfault.test 98df47444944a6db2161eed5cef71d6c00bcb8c3
@@ -816,14 +816,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 43377663fc3569c361867cdea19e8abaf91a163f
-R 47b0032c37d93d195eb69ddfe3dd9d8c
+P 669706431f186f92fdc0856a6206419a1e843f46
+R 7ce0bc2b62787cca31ab42b34ac1e9ef
 U drh
-Z bc14d892f085709c56913a5ad734eeb0
+Z 335bcf01b684b4b622e461b91e26e309
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.6 (GNU/Linux)
 
-iD8DBQFL9WdKoxKgR168RlERAjyUAJ9c2KtaS5H2pdO1uUyrfgizw26dywCffxrC
-bcVcl+tQYJI9XMFw4UKZNxs=
-=Bxmw
+iD8DBQFL9afIoxKgR168RlERAma7AJ9zhPYbudAO43Ry1pxCArWXbiP7QwCffSB2
+UDhUaZ/h1EszzPxcYgfA5bo=
+=RESX
 -----END PGP SIGNATURE-----
index d02d2936cadf1ce47358555e699cefc5a3508652..ba5b221dc8c196e451b7cbc2f3ed021c94c1d912 100644 (file)
@@ -1 +1 @@
-669706431f186f92fdc0856a6206419a1e843f46
\ No newline at end of file
+9580ecb7e3beb1949a71784a3dcd1823a88e4a9d
\ No newline at end of file
index d4897fda37362128162662858b66a9ef8f7d884f..5e4c927a77ac485d81c2b846ac446bbbc154568e 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -15,7 +15,7 @@
 **
 ** WRITE-AHEAD LOG (WAL) FILE FORMAT
 **
-** A wal file consists of a header followed by zero or more "frames".
+** A WAL file consists of a header followed by zero or more "frames".
 ** Each frame records the revised content of a single page from the
 ** database file.  All changes to the database are recorded by writing
 ** frames into the WAL.  Transactions commit when a frame is written that
@@ -38,8 +38,8 @@
 **     4: File format version.  Currently 3007000
 **     8: Database page size.  Example: 1024
 **    12: Checkpoint sequence number
-**    16: Salt-1, random integer that changes with each checkpoint
-**    20: Salt-2, a different random integer changing with salt-1
+**    16: Salt-1, random integer incremented with each checkpoint
+**    20: Salt-2, a different random integer changing with each ckpt
 **
 ** Immediately following the wal-header are zero or more frames. Each
 ** frame consists of a 24-byte frame-header followed by a <page-size> bytes
 **     0: Page number.
 **     4: For commit records, the size of the database image in pages 
 **        after the commit. For all other records, zero.
-**     8: Checkpoint sequence number (copied from the header)
-**    12: Salt-1 (copied from the header)
+**     8: Salt-1 (copied from the header)
+**    12: Salt-2 (copied from the header)
 **    16: Checksum-1.
 **    20: Checksum-2.
 **
+** A frame is considered valid if and only if the following conditions are
+** true:
+**
+**    (1) The salt-1 and salt-2 values in the frame-header match
+**        salt values in the wal-header
+**
+**    (2) The checksum values in the final 8 bytes of the frame-header
+**        exactly match the checksum computed consecutively on
+**        (a) the first 16 bytes of the frame-header, and
+**        (b) the frame data.
+**
+** On a checkpoint, the WAL is first VFS.xSync-ed, then valid content of the
+** WAL is transferred into the database, then the database is VFS.xSync-ed.
+** The VFS.xSync operations server as write barriers - all writes launched
+** before the xSync must complete before any write that launches after the
+** xSync begins.
+**
+** After each checkpoint, the salt-1 value is incremented and the salt-2
+** value is randomized.  This prevents old and new frames in the WAL from
+** being considered valid at the same time and being checkpointing together
+** following a crash.
+**
 ** READER ALGORITHM
 **
 ** To read a page from the database (call it page number P), a reader
@@ -185,32 +207,23 @@ typedef struct WalIterator WalIterator;
 
 
 /*
-** The following object stores information from the wal-index header.
-**
-** This object is *not* a copy of the wal-index header.
-**
-** Member variables iCheck1 and iCheck2 contain the checksum for the
-** last frame written to the wal, or 2 and 3 respectively if the log 
-** is currently empty.
+** The following object holds an exact copy of the wal-index header.
 */
 struct WalIndexHdr {
-  u32 iChange;          /* Counter incremented each transaction */
-  u32 szPage;           /* Database page size in bytes */
-  u32 mxFrame;          /* Index of last valid frame in the WAL */
-  u32 nPage;            /* Size of database in pages */
-  u32 iCheck1;          /* Checksum value 1 */
-  u32 iCheck2;          /* Checksum value 2 */
+  u32 iChange;      /* Counter incremented each transaction */
+  u32 szPage;       /* Database page size in bytes */
+  u32 mxFrame;      /* Index of last valid frame in the WAL */
+  u32 nPage;        /* Size of database in pages */
+  u32 aSalt[2];     /* Salt-1 and salt-2 values copied from WAL header */
+  u32 aCksum[2];    /* Checksum over all prior fields */
 };
 
-/* Size of serialized WalIndexHdr object. */
-#define WALINDEX_HDR_NFIELD (sizeof(WalIndexHdr) / sizeof(u32))
-
-/* A block of 16 bytes beginning at WALINDEX_LOCK_OFFSET is reserved
-** for locks. Since some systems only feature mandatory file-locks, we
-** do not read or write data from the region of the file on which locks
-** are applied.
+/* A block of WALINDEX_LOCK_RESERVED bytes beginning at
+** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems
+** only support mandatory file-locks, we do not read or write data
+** from the region of the file on which locks are applied.
 */
-#define WALINDEX_LOCK_OFFSET   ((sizeof(WalIndexHdr))+2*sizeof(u32))
+#define WALINDEX_LOCK_OFFSET   (sizeof(WalIndexHdr))
 #define WALINDEX_LOCK_RESERVED 8
 
 /* Size of header before each frame in wal */
@@ -245,8 +258,8 @@ struct Wal {
   u8 isWindexOpen;           /* True if ShmOpen() called on pDbFd */
   WalIndexHdr hdr;           /* Wal-index for current snapshot */
   char *zWalName;            /* Name of WAL file */
-  u32 nCkpt;                 /* Checkpoint sequence number */
-  u32 iSalt1, iSalt2;        /* Two random salt values */
+  int szPage;                /* Database page size */
+  u32 nCkpt;                 /* Checkpoint sequence counter in the wal-header */
 };
 
 
@@ -278,13 +291,27 @@ struct WalIterator {
 
 
 /*
-** Generate an 8 byte checksum based on the data in array aByte[] and the
-** initial values of aCksum[0] and aCksum[1]. The checksum is written 
-** back into aCksum[] before returning.
+** Generate or extend an 8 byte checksum based on the data in 
+** array aByte[] and the initial values of aIn[0] and aIn[1] (or
+** initial values of 0 and 0 if aIn==NULL).
+**
+** The checksum is written back into aOut[] before returning.
+**
+** nByte must be a positive multiple of 8.
 */
-static void walChecksumBytes(u8 *a, int nByte, u32 *aCksum){
-  u32 s1 = aCksum[0];
-  u32 s2 = aCksum[1];
+static void walChecksumBytes(
+  u8 *a,           /* Content to be checksummed */
+  int nByte,       /* Bytes of content in a[].  Must be a multiple of 8. */
+  const u32 *aIn,  /* Initial checksum value input */
+  u32 *aOut        /* OUT: Final checksum value output */
+){
+  u32 s1, s2;
+  if( aIn ){
+    s1 = aIn[0];
+    s2 = aIn[1];
+  }else{
+    s1 = s2 = 0;
+  }
   u8 *aEnd = (u8*)&a[nByte];
 
   assert( nByte>=8 );
@@ -295,8 +322,8 @@ static void walChecksumBytes(u8 *a, int nByte, u32 *aCksum){
     s2 += (a[4]<<24) + (a[5]<<16) + (a[6]<<8) + a[7] + s1;
     a += 8;
   }while( a<aEnd );
-  aCksum[0] = s1;
-  aCksum[1] = s2;
+  aOut[0] = s1;
+  aOut[1] = s2;
 }
 
 /*
@@ -323,17 +350,15 @@ static int walSetLock(Wal *pWal, int desiredStatus){
 }
 
 /*
-** Update the header of the wal-index file.
+** Write the header information in pWal->hdr into the wal-index.
+**
+** The checksum on pWal->hdr is updated before it is written.
 */
-static void walIndexWriteHdr(Wal *pWal, WalIndexHdr *pHdr){
-  volatile u32 *aHdr = pWal->pWiData;                 /* Write header here */
-  volatile u32 *aCksum = &aHdr[WALINDEX_HDR_NFIELD];  /* Write cksum here */
-
-  assert( WALINDEX_HDR_NFIELD==sizeof(WalIndexHdr)/4 );
-  assert( aHdr!=0 );
-  memcpy((void*)aHdr, pHdr, sizeof(WalIndexHdr));
-  aCksum[0] = aCksum[1] = 1;
-  walChecksumBytes((u8*)aHdr, sizeof(WalIndexHdr), (u32*)aCksum);
+static void walIndexWriteHdr(Wal *pWal){
+  walChecksumBytes((u8*)&pWal->hdr,
+                   sizeof(pWal->hdr) - sizeof(pWal->hdr.aCksum),
+                   0, pWal->hdr.aCksum);
+  memcpy((void*)pWal->pWiData, &pWal->hdr, sizeof(pWal->hdr));
 }
 
 /*
@@ -344,60 +369,59 @@ static void walIndexWriteHdr(Wal *pWal, WalIndexHdr *pHdr){
 **     0: Page number.
 **     4: For commit records, the size of the database image in pages 
 **        after the commit. For all other records, zero.
-**     8: Checkpoint sequence number (copied from the header)
-**    12: Salt-1 (copied from the header)
+**     8: Salt-1 (copied from the wal-header)
+**    12: Salt-2 (copied from the wal-header)
 **    16: Checksum-1.
 **    20: Checksum-2.
 */
 static void walEncodeFrame(
   Wal *pWal,                      /* The write-ahead log */
-  u32 *aCksum,                    /* IN/OUT: Checksum values */
   u32 iPage,                      /* Database page number for frame */
   u32 nTruncate,                  /* New db size (or 0 for non-commit frames) */
-  int nData,                      /* Database page size (size of aData[]) */
-  u8 *aData,                      /* Pointer to page data (for checksum) */
+  u8 *aData,                      /* Pointer to page data */
   u8 *aFrame                      /* OUT: Write encoded frame here */
 ){
+  u32 aCksum[2];
   assert( WAL_FRAME_HDRSIZE==24 );
-
   sqlite3Put4byte(&aFrame[0], iPage);
   sqlite3Put4byte(&aFrame[4], nTruncate);
-  sqlite3Put4byte(&aFrame[8], pWal->nCkpt);
-  sqlite3Put4byte(&aFrame[12], pWal->iSalt1);
+  memcpy(&aFrame[8], pWal->hdr.aSalt, 8);
 
-  walChecksumBytes(aFrame, 8, aCksum);
-  walChecksumBytes(aData, nData, aCksum);
+  walChecksumBytes(aFrame, 16, 0, aCksum);
+  walChecksumBytes(aData, pWal->szPage, aCksum, aCksum);
 
   sqlite3Put4byte(&aFrame[16], aCksum[0]);
   sqlite3Put4byte(&aFrame[20], aCksum[1]);
 }
 
 /*
-** Return 1 and populate *piPage, *pnTruncate and aCksum if the 
-** frame checksum looks Ok. Otherwise return 0.
+** Check to see if the frame with header in aFrame[] and content
+** in aData[] is valid.  If it is a valid frame, fill *piPage and
+** *pnTruncate and return true.  Return if the frame is not valid.
 */
 static int walDecodeFrame(
   Wal *pWal,                      /* The write-ahead log */
-  u32 *aCksum,                    /* IN/OUT: Checksum values */
   u32 *piPage,                    /* OUT: Database page number for frame */
   u32 *pnTruncate,                /* OUT: New db size (or 0 if not commit) */
-  int nData,                      /* Database page size (size of aData[]) */
   u8 *aData,                      /* Pointer to page data (for checksum) */
   u8 *aFrame                      /* Frame data */
 ){
+  u32 aCksum[2];
   assert( WAL_FRAME_HDRSIZE==24 );
 
-#if 0
-  if( pWal->nCkpt!=sqlite3Get4byte(&aFrame[8]) ){
-    return 0;
-  }
-  if( pWal->iSalt1!=sqlite3Get4byte(&aFrame[12]) ){
+  /* A frame is only valid if the salt values in the frame-header
+  ** match the salt values in the wal-header. 
+  */
+  if( memcmp(&pWal->hdr.aSalt, &aFrame[8], 8)!=0 ){
     return 0;
   }
-#endif
 
-  walChecksumBytes(aFrame, 8, aCksum);
-  walChecksumBytes(aData, nData, aCksum);
+  /* A frame is only valid if a checksum of the first 16 bytes
+  ** of the frame-header, and the frame-data matches
+  ** the checksum in the last 8 bytes of the frame-header.
+  */
+  walChecksumBytes(aFrame, 16, 0, aCksum);
+  walChecksumBytes(aData, pWal->szPage, aCksum, aCksum);
   if( aCksum[0]!=sqlite3Get4byte(&aFrame[16]) 
    || aCksum[1]!=sqlite3Get4byte(&aFrame[20]) 
   ){
@@ -405,6 +429,9 @@ static int walDecodeFrame(
     return 0;
   }
 
+  /* If we reach this point, the frame is valid.  Return the page number
+  ** and the new database size.
+  */
   *piPage = sqlite3Get4byte(&aFrame[0]);
   *pnTruncate = sqlite3Get4byte(&aFrame[4]);
   return 1;
@@ -648,7 +675,6 @@ static int walIndexRecover(Wal *pWal){
     int iFrame;                   /* Index of last frame read */
     i64 iOffset;                  /* Next offset to read from log file */
     int szPage;                   /* Page size according to the log */
-    u32 aCksum[2];                /* Running checksum */
 
     /* Read in the first frame header in the file (to determine the 
     ** database page size).
@@ -665,9 +691,9 @@ static int walIndexRecover(Wal *pWal){
     if( szPage&(szPage-1) || szPage>SQLITE_MAX_PAGE_SIZE || szPage<512 ){
       goto finished;
     }
+    pWal->szPage = szPage;
     pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
-    aCksum[0] = sqlite3Get4byte(&aBuf[16]);
-    aCksum[1] = sqlite3Get4byte(&aBuf[20]);
+    memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
 
     /* Malloc a buffer to read frames into. */
     szFrame = szPage + WAL_FRAME_HDRSIZE;
@@ -687,16 +713,13 @@ static int walIndexRecover(Wal *pWal){
       /* Read and decode the next log frame. */
       rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
       if( rc!=SQLITE_OK ) break;
-      isValid = walDecodeFrame(pWal, aCksum, &pgno, &nTruncate, szPage,
-                               aData, aFrame);
+      isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame);
       if( !isValid ) break;
       rc = walIndexAppend(pWal, ++iFrame, pgno);
       if( rc!=SQLITE_OK ) break;
 
       /* If nTruncate is non-zero, this is a commit record. */
       if( nTruncate ){
-        hdr.iCheck1 = aCksum[0];
-        hdr.iCheck2 = aCksum[1];
         hdr.mxFrame = iFrame;
         hdr.nPage = nTruncate;
         hdr.szPage = szPage;
@@ -705,8 +728,7 @@ static int walIndexRecover(Wal *pWal){
 
     sqlite3_free(aFrame);
   }else{
-    hdr.iCheck1 = 2;
-    hdr.iCheck2 = 3;
+    memset(&hdr, 0, sizeof(hdr));
   }
 
 finished:
@@ -714,8 +736,8 @@ finished:
     rc = walIndexRemap(pWal, WALINDEX_MMAP_INCREMENT);
   }
   if( rc==SQLITE_OK ){
-    walIndexWriteHdr(pWal, &hdr);
     memcpy(&pWal->hdr, &hdr, sizeof(hdr));
+    walIndexWriteHdr(pWal);
   }
   return rc;
 }
@@ -774,6 +796,7 @@ int sqlite3WalOpen(
   pRet->pVfs = pVfs;
   pRet->pWalFd = (sqlite3_file *)&pRet[1];
   pRet->pDbFd = pDbFd;
+  sqlite3_randomness(8, &pRet->hdr.aSalt);
   pRet->zWalName = zWal = pVfs->szOsFile + (char*)pRet->pWalFd;
   sqlite3_snprintf(nWal, zWal, "%s-wal", zDbName);
   rc = sqlite3OsShmOpen(pDbFd);
@@ -1027,30 +1050,11 @@ static int walCheckpoint(
     if( rc!=SQLITE_OK ) goto out;
   }
   pWal->hdr.mxFrame = 0;
-  pWal->hdr.iCheck1 = 2;
-  pWal->hdr.iCheck2 = 3;
-  walIndexWriteHdr(pWal, &pWal->hdr);
   pWal->nCkpt++;
-
-  /* TODO: If a crash occurs and the current log is copied into the 
-  ** database there is no problem. However, if a crash occurs while
-  ** writing the next transaction into the start of the log, such that:
-  **
-  **   * The first transaction currently in the log is left intact, but
-  **   * The second (or subsequent) transaction is damaged,
-  **
-  ** then the database could become corrupt.
-  **
-  ** The easiest thing to do would be to write and sync a dummy header
-  ** into the log at this point. Unfortunately, that turns out to be
-  ** an unwelcome performance hit. Alternatives are...
-  */
-#if 0 
-  memset(zBuf, 0, WAL_FRAME_HDRSIZE);
-  rc = sqlite3OsWrite(pWal->pWalFd, zBuf, WAL_FRAME_HDRSIZE, 0);
-  if( rc!=SQLITE_OK ) goto out;
-  rc = sqlite3OsSync(pWal->pWalFd, pWal->sync_flags);
-#endif
+  sqlite3Put4byte((u8*)pWal->hdr.aSalt,
+                   1 + sqlite3Get4byte((u8*)pWal->hdr.aSalt));
+  sqlite3_randomness(4, &pWal->hdr.aSalt[1]);
+  walIndexWriteHdr(pWal);
 
  out:
   walIteratorFree(pIter);
@@ -1114,10 +1118,8 @@ int sqlite3WalClose(
 ** is read successfully and the checksum verified, return zero.
 */
 int walIndexTryHdr(Wal *pWal, int *pChanged){
-  int i;
-  volatile u32 *aWiData;
-  u32 aCksum[2] = {1, 1};
-  u32 aHdr[WALINDEX_HDR_NFIELD+2];
+  u32 aCksum[2];
+  WalIndexHdr hdr;
 
   assert( pWal->pWiData );
   if( pWal->szWIndex==0 ){
@@ -1133,20 +1135,16 @@ int walIndexTryHdr(Wal *pWal, int *pChanged){
   ** file, meaning it is possible that an inconsistent snapshot is read
   ** from the file. If this happens, return non-zero.
   */
-  aWiData = pWal->pWiData;
-  for(i=0; i<WALINDEX_HDR_NFIELD+2; i++){
-    aHdr[i] = aWiData[i];
-  }
-  walChecksumBytes((u8*)aHdr, sizeof(u32)*WALINDEX_HDR_NFIELD, aCksum);
-  if( aCksum[0]!=aHdr[WALINDEX_HDR_NFIELD]
-   || aCksum[1]!=aHdr[WALINDEX_HDR_NFIELD+1]
-  ){
+  memcpy(&hdr, (void*)pWal->pWiData, sizeof(hdr));
+  walChecksumBytes((u8*)&hdr, sizeof(hdr)-sizeof(hdr.aCksum), 0, aCksum);
+  if( aCksum[0]!=hdr.aCksum[0] || aCksum[1]!=hdr.aCksum[1] ){
     return 1;
   }
 
-  if( memcmp(&pWal->hdr, aHdr, sizeof(WalIndexHdr)) ){
+  if( memcmp(&pWal->hdr, &hdr, sizeof(WalIndexHdr)) ){
     *pChanged = 1;
-    memcpy(&pWal->hdr, aHdr, sizeof(WalIndexHdr));
+    memcpy(&pWal->hdr, &hdr, sizeof(WalIndexHdr));
+    pWal->szPage = pWal->hdr.szPage;
   }
 
   /* The header was successfully read. Return zero. */
@@ -1487,17 +1485,9 @@ u32 sqlite3WalSavepoint(Wal *pWal){
 */
 int sqlite3WalSavepointUndo(Wal *pWal, u32 iFrame){
   int rc = SQLITE_OK;
-  u8 aCksum[8];
   assert( pWal->lockState==SQLITE_SHM_WRITE );
 
   pWal->hdr.mxFrame = iFrame;
-  if( iFrame>0 ){
-    i64 iOffset = walFrameOffset(iFrame, pWal->hdr.szPage) + sizeof(u32)*4;
-    rc = sqlite3OsRead(pWal->pWalFd, aCksum, sizeof(aCksum), iOffset);
-    pWal->hdr.iCheck1 = sqlite3Get4byte(&aCksum[0]);
-    pWal->hdr.iCheck2 = sqlite3Get4byte(&aCksum[4]);
-  }
-
   return rc;
 }
 
@@ -1517,7 +1507,6 @@ int sqlite3WalFrames(
   u32 iFrame;                     /* Next frame address */
   u8 aFrame[WAL_FRAME_HDRSIZE];   /* Buffer to assemble frame-header in */
   PgHdr *p;                       /* Iterator to run through pList with. */
-  u32 aCksum[2];                  /* Checksums */
   PgHdr *pLast = 0;               /* Last frame in list */
   int nLast = 0;                  /* Number of extra copies of last page */
 
@@ -1535,20 +1524,17 @@ int sqlite3WalFrames(
     sqlite3Put4byte(&aWalHdr[0], 0x377f0682);
     sqlite3Put4byte(&aWalHdr[4], 3007000);
     sqlite3Put4byte(&aWalHdr[8], szPage);
+    pWal->szPage = szPage;
     sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt);
-    sqlite3_randomness(8, &aWalHdr[16]);
-    pWal->hdr.iCheck1 = pWal->iSalt1 = sqlite3Get4byte(&aWalHdr[16]);
-    pWal->hdr.iCheck2 = pWal->iSalt2 = sqlite3Get4byte(&aWalHdr[20]);
+    memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8);
     rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0);
     if( rc!=SQLITE_OK ){
       return rc;
     }
   }
+  assert( pWal->szPage==szPage );
 
-  aCksum[0] = pWal->hdr.iCheck1;
-  aCksum[1] = pWal->hdr.iCheck2;
-
-  /* Write the log file. */
+    /* Write the log file. */
   for(p=pList; p; p=p->pDirty){
     u32 nDbsize;                  /* Db-size field for frame header */
     i64 iOffset;                  /* Write offset in log file */
@@ -1557,7 +1543,7 @@ int sqlite3WalFrames(
     
     /* Populate and write the frame header */
     nDbsize = (isCommit && p->pDirty==0) ? nTruncate : 0;
-    walEncodeFrame(pWal, aCksum, p->pgno, nDbsize, szPage, p->pData, aFrame);
+    walEncodeFrame(pWal, p->pgno, nDbsize, p->pData, aFrame);
     rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOffset);
     if( rc!=SQLITE_OK ){
       return rc;
@@ -1581,8 +1567,7 @@ int sqlite3WalFrames(
 
     iSegment = (((iOffset+iSegment-1)/iSegment) * iSegment);
     while( iOffset<iSegment ){
-      walEncodeFrame(pWal, aCksum, pLast->pgno, nTruncate, szPage,
-                     pLast->pData, aFrame);
+      walEncodeFrame(pWal, pLast->pgno, nTruncate, pLast->pData, aFrame);
       rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOffset);
       if( rc!=SQLITE_OK ){
         return rc;
@@ -1625,12 +1610,9 @@ int sqlite3WalFrames(
       pWal->hdr.iChange++;
       pWal->hdr.nPage = nTruncate;
     }
-    pWal->hdr.iCheck1 = aCksum[0];
-    pWal->hdr.iCheck2 = aCksum[1];
-
     /* If this is a commit, update the wal-index header too. */
     if( isCommit ){
-      walIndexWriteHdr(pWal, &pWal->hdr);
+      walIndexWriteHdr(pWal);
       pWal->iCallback = iFrame;
     }
   }
index 49db065ade6e13ba93362fdc547f939631cbdb50..3140f802cd66ef0f642e7e6a66d5472a4cdaeffb 100644 (file)
@@ -556,7 +556,10 @@ foreach code [list {
     catchsql { INSERT INTO t1 VALUES(9, 10) }
   } {1 {database is locked}}
   do_test wal-10.$tn.10 {
-    execsql { COMMIT; BEGIN; INSERT INTO t1 VALUES(9, 10); COMMIT; }
+    execsql { COMMIT }
+    execsql { BEGIN }
+    execsql { INSERT INTO t1 VALUES(9, 10) }
+    execsql { COMMIT }
     execsql { SELECT * FROM t1 }
   } {1 2 3 4 5 6 7 8 9 10}
 
@@ -1336,15 +1339,14 @@ foreach {tn pgsz works} {
       # or too large), the db will not be corrupt as the log file will
       # be ignored.
       #
-      set c1 22
-      set c2 23
-      set walhdr [binary format IIIIII 931071618 3007000 $pgsz 1234 $c1 $c2]
-      set salt1 $c1
+      set walhdr [binary format IIIIII 931071618 3007000 $pgsz 1234 22 23]
       set framebody [randomblob $pgsz]
-      set framehdr  [binary format II $pg 5]
+      set framehdr  [binary format IIII $pg 5 22 23]
+      set c1 0
+      set c2 0
       logcksum c1 c2 $framehdr
       logcksum c1 c2 $framebody
-      set framehdr [binary format IIIIII $pg 5 1234 $salt1 $c1 $c2]
+      set framehdr [binary format IIIIII $pg 5 22 23 $c1 $c2]
       set fd [open test.db-wal w]
       fconfigure $fd -encoding binary -translation binary
       puts -nonewline $fd $walhdr
index b8fe5fc4daafcd85fecc0735dd93c2e78a789105..3248bdbc7e75486511993790b7a91afc37521127 100644 (file)
@@ -115,6 +115,7 @@ foreach {tn iInsert res wal_index_hdr_mod wal_locks} {
       return SQLITE_OK
     }
 
+breakpoint
     execsql { SELECT count(a), sum(a) FROM t1 } db2
   } $res
 
@@ -178,7 +179,7 @@ foreach {tn iInsert res0 res1 wal_index_hdr_mod} {
          8   11   {10 55}  {11 66}   6
          9   12   {11 66}  {12 78}   7
 } {
-  do_test wal2-1.$tn.1 {
+  do_test wal2-2.$tn.1 {
     set oldhdr [set_tvfs_hdr $::shm_file]
     execsql { INSERT INTO t1 VALUES($iInsert) }
     execsql { SELECT count(a), sum(a) FROM t1 }
@@ -603,4 +604,3 @@ do_test wal2-6.5.3 {
 db close
 
 finish_test
-