From c9a9022b216aab23fb756d4a6a47c14cfeb69da7 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 9 Jan 2016 18:57:35 +0000 Subject: [PATCH] If it is known that checksums will be recalculated on transaction commit, skip calculating checksums when appending frames to the wal file. When recalculating checksums, recalculate them starting with the first overwritten frame - not the first frame in the transaction. FossilOrigin-Name: 16b34f2537bbc7846d8e6dc2b35daae5af241c1b --- manifest | 15 +++++------ manifest.uuid | 2 +- src/wal.c | 71 +++++++++++++++++++++++++-------------------------- 3 files changed, 42 insertions(+), 46 deletions(-) diff --git a/manifest b/manifest index 929a82b2bd..0d9cd20891 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\sa\ssingle\spage\sis\swritten\sto\sthe\swal\sfile\smore\sthan\sonce,\shave\seach\ssubsequent\scopy\soverwrite\sthe\soriginal\sframe. -D 2016-01-09T16:39:29.213 +C If\sit\sis\sknown\sthat\schecksums\swill\sbe\srecalculated\son\stransaction\scommit,\sskip\scalculating\schecksums\swhen\sappending\sframes\sto\sthe\swal\sfile.\sWhen\srecalculating\schecksums,\srecalculate\sthem\sstarting\swith\sthe\sfirst\soverwritten\sframe\s-\snot\sthe\sfirst\sframe\sin\sthe\stransaction. +D 2016-01-09T18:57:35.280 F Makefile.in 7c8cc4c2f0179efc6fa9492141d1fb65f4807054 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e45d8b9b56dfa3f2cd860b2c28bd9d304513b042 @@ -409,7 +409,7 @@ F src/vdbesort.c a7ec02da4494c59dfd071126dd3726be5a11459d F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0 F src/vtab.c 2a8b44aa372c33f6154208e7a7f6c44254549806 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb -F src/wal.c 88661c24c86d88e40560c0be5df39d902502a29a +F src/wal.c 38ca0c41b510b636dfada0801fad8a99a982dfa6 F src/wal.h 907943dfdef10b583e81906679a347e0ec6f1b1b F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba F src/where.c c6d3d2f6af57d574a7365ee2b225a5024f2a6bec @@ -1407,10 +1407,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 52c166039831cc8423e2252019ef64a21b9d7c2a -R 7ec438cc7bd0e0a87d33dca3e9bb783a -T *branch * wal-overwrite-frames -T *sym-wal-overwrite-frames * -T -sym-trunk * +P 5d113aef2c7d746e8eda88d4e36c04a39b0a11be +R 68fe235d45cc69355e6b4ad2de6e1633 U dan -Z eba50524221f3f22640b286e867693f1 +Z 339ef03cecb2ba4cae1a0043b973d562 diff --git a/manifest.uuid b/manifest.uuid index 2b25ead966..44ce854f87 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5d113aef2c7d746e8eda88d4e36c04a39b0a11be \ No newline at end of file +16b34f2537bbc7846d8e6dc2b35daae5af241c1b \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index c900879d12..d3e2908ba1 100644 --- a/src/wal.c +++ b/src/wal.c @@ -445,6 +445,7 @@ struct Wal { u8 padToSectorBoundary; /* Pad transactions out to the next sector */ WalIndexHdr hdr; /* Wal-index header for current transaction */ u32 minFrame; /* Ignore wal frames before this one */ + u32 iReCksum; /* On commit, recalculate checksums from here */ const char *zWalName; /* Name of WAL file */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ #ifdef SQLITE_DEBUG @@ -462,13 +463,6 @@ struct Wal { #define WAL_EXCLUSIVE_MODE 1 #define WAL_HEAPMEMORY_MODE 2 -/* -** Values for Wal.writeLock. -*/ -#define WAL_WRITELOCK_UNLOCKED 0 -#define WAL_WRITELOCK_LOCKED 1 -#define WAL_WRITELOCK_RECKSUM 2 - /* ** Possible values for WAL.readOnly */ @@ -705,14 +699,16 @@ static void walEncodeFrame( assert( WAL_FRAME_HDRSIZE==24 ); sqlite3Put4byte(&aFrame[0], iPage); sqlite3Put4byte(&aFrame[4], nTruncate); - memcpy(&aFrame[8], pWal->hdr.aSalt, 8); + if( pWal->iReCksum==0 ){ + memcpy(&aFrame[8], pWal->hdr.aSalt, 8); - nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN); - walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum); - walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum); + nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN); + walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum); + walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum); - sqlite3Put4byte(&aFrame[16], aCksum[0]); - sqlite3Put4byte(&aFrame[20], aCksum[1]); + sqlite3Put4byte(&aFrame[16], aCksum[0]); + sqlite3Put4byte(&aFrame[20], aCksum[1]); + } } /* @@ -2639,6 +2635,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){ /* Cannot start a write transaction without first holding a read ** transaction. */ assert( pWal->readLock>=0 ); + assert( pWal->writeLock==0 && pWal->iReCksum==0 ); if( pWal->readOnly ){ return SQLITE_READONLY; @@ -2674,6 +2671,7 @@ int sqlite3WalEndWriteTransaction(Wal *pWal){ if( pWal->writeLock ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); pWal->writeLock = 0; + pWal->iReCksum = 0; pWal->truncateOnCommit = 0; } return SQLITE_OK; @@ -2895,41 +2893,40 @@ static int walWriteOneFrame( /* ** This function is called as part of committing a transaction within which ** one or more frames have been overwritten. It updates the checksums for -** all frames written to the wal file by the current transaction. -** -** Argument pLive is a pointer to the first wal-index header in shared -** memory (the copy readers will see if they open a read-transaction now, -** before the current commit is finished). This is safe to use because the -** caller holds the WRITER lock. The first frame to update the checksum -** for is (pLive->mxFrame+1). The last is argument iLast. +** all frames written to the wal file by the current transaction starting +** with the earliest to have been overwritten. ** ** SQLITE_OK is returned if successful, or an SQLite error code otherwise. */ -static int walRewriteChecksums(Wal *pWal, WalIndexHdr *pLive, u32 iLast){ +static int walRewriteChecksums(Wal *pWal, u32 iLast){ const int szPage = pWal->szPage;/* Database page size */ int rc = SQLITE_OK; /* Return code */ u8 *aBuf; /* Buffer to load data from wal file into */ u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-headers in */ u32 iRead; /* Next frame to read from wal file */ + i64 iCksumOff; aBuf = sqlite3_malloc(szPage + WAL_FRAME_HDRSIZE); if( aBuf==0 ) return SQLITE_NOMEM; - /* Find the checksum values to use as input for the checksum of the - ** first frame written by this transaction. If that frame is frame 1 - ** (implying that the current transaction restarted the wal file), - ** these values must be read from the wal-file header. If the first - ** frame to update the checksum of is not frame 1, then the initial - ** checksum values can be copied from pLive. */ - if( pLive->mxFrame==0 ){ - rc = sqlite3OsRead(pWal->pWalFd, aBuf, sizeof(u32)*2, 24); - pWal->hdr.aFrameCksum[0] = sqlite3Get4byte(aBuf); - pWal->hdr.aFrameCksum[1] = sqlite3Get4byte(&aBuf[sizeof(u32)]); + /* Find the checksum values to use as input for the recalculating the + ** first checksum. If the first frame is frame 1 (implying that the current + ** transaction restarted the wal file), these values must be read from the + ** wal-file header. Otherwise, read them from the frame header of the + ** previous frame. */ + assert( pWal->iReCksum>0 ); + if( pWal->iReCksum==1 ){ + iCksumOff = 24; }else{ - memcpy(pWal->hdr.aFrameCksum, pLive->aFrameCksum, sizeof(u32)*2); + iCksumOff = walFrameOffset(pWal->iReCksum-1, szPage) + 16; } + rc = sqlite3OsRead(pWal->pWalFd, aBuf, sizeof(u32)*2, iCksumOff); + pWal->hdr.aFrameCksum[0] = sqlite3Get4byte(aBuf); + pWal->hdr.aFrameCksum[1] = sqlite3Get4byte(&aBuf[sizeof(u32)]); - for(iRead=pLive->mxFrame+1; rc==SQLITE_OK && iRead<=iLast; iRead++){ + iRead = pWal->iReCksum; + pWal->iReCksum = 0; + for(; rc==SQLITE_OK && iRead<=iLast; iRead++){ i64 iOff = walFrameOffset(iRead, szPage); rc = sqlite3OsRead(pWal->pWalFd, aBuf, szPage+WAL_FRAME_HDRSIZE, iOff); if( rc==SQLITE_OK ){ @@ -3065,7 +3062,9 @@ int sqlite3WalFrames( if( rc ) return rc; if( iWrite>=iFirst ){ i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE; - pWal->writeLock = WAL_WRITELOCK_RECKSUM; + if( pWal->iReCksum==0 || iWriteiReCksum ){ + pWal->iReCksum = iWrite; + } rc = sqlite3OsWrite(pWal->pWalFd, p->pData, szPage, iOff); if( rc ) return rc; p->flags &= ~PGHDR_WAL_APPEND; @@ -3084,8 +3083,8 @@ int sqlite3WalFrames( } /* Recalculate checksums within the wal file if required. */ - if( isCommit && pWal->writeLock==WAL_WRITELOCK_RECKSUM ){ - rc = walRewriteChecksums(pWal, pLive, iFrame); + if( isCommit && pWal->iReCksum ){ + rc = walRewriteChecksums(pWal, iFrame); if( rc ) return rc; } -- 2.47.2