diff --git a/manifest b/manifest index a63f4d3873..52aed1db63 100644 --- 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----- diff --git a/manifest.uuid b/manifest.uuid index d02d2936ca..ba5b221dc8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -669706431f186f92fdc0856a6206419a1e843f46 \ No newline at end of file +9580ecb7e3beb1949a71784a3dcd1823a88e4a9d \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index d4897fda37..5e4c927a77 100644 --- 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 bytes @@ -49,11 +49,33 @@ ** 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( ahdr 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]) ){ + /* 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; } - if( pWal->iSalt1!=sqlite3Get4byte(&aFrame[12]) ){ - 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; ipWiData, 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( iOffsetpgno, 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; } } diff --git a/test/wal.test b/test/wal.test index 49db065ade..3140f802cd 100644 --- a/test/wal.test +++ b/test/wal.test @@ -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 diff --git a/test/wal2.test b/test/wal2.test index b8fe5fc4da..3248bdbc7e 100644 --- a/test/wal2.test +++ b/test/wal2.test @@ -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 -