From: drh Date: Fri, 16 Dec 2011 19:34:36 +0000 (+0000) Subject: Proposed changes that ensure that the WAL header is written prior to the X-Git-Tag: mountain-lion~8^2~31^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=88f975a7a49dfd8786f0337add71d4841596a5f3;p=thirdparty%2Fsqlite.git Proposed changes that ensure that the WAL header is written prior to the first commit mark. FossilOrigin-Name: 91d0437c0702904d27f0ef7b1b52d0797efe1826 --- diff --git a/manifest b/manifest index 66736fbb73..8c212674db 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\sfix\sfor\s[a1fa75cbdd02]\sfrom\sthe\sexperimental\sbranch.\s\sAlso\nfix\sthe\spersistent-wal\smode\sfeature\sof\struncating\sthe\sWAL\son\sclose\sso\sthat\nit\salways\struncates\sthe\sWAL\sto\szero\sbytes. -D 2011-12-16T15:38:52.854 +C Proposed\schanges\sthat\sensure\sthat\sthe\sWAL\sheader\sis\swritten\sprior\sto\sthe\nfirst\scommit\smark. +D 2011-12-16T19:34:36.384 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -250,7 +250,7 @@ F src/vdbemem.c 2fc78b3e0fabcc1eaa23cd79dd2e30e6dcfe1e56 F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790 F src/vdbetrace.c d6e50e04e1ec498150e519058f617d91b8f5c843 F src/vtab.c e9318d88feac85be8e27ee783ac8f5397933fc8a -F src/wal.c 8575f2bdaed48e7ffbea8608b614bb7abd382a54 +F src/wal.c a1157f289ef700ce9148d8448916799cb364c20f F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f F src/where.c af623942514571895818b9b7ae11db95ae3b3d88 @@ -984,7 +984,10 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P b1005ef46cc2b46dd8e448ae1a9a9508bd5666ab 6492af76ea6585a1b377d69751af930c0ccfe688 -R 5e90bbe7156facb03e2de52b2217bc8c +P 09ccc4a1be7ba81890f10aac6623dd90dab4f990 +R e39509fa33546fba87ec45fa63df451b +T *branch * wal-header-sync +T *sym-wal-header-sync * +T -sym-trunk * U drh -Z 290df3a9d2eb83a09d72442af4b2f315 +Z 6469301a128bde2c8fea4c5b47d61847 diff --git a/manifest.uuid b/manifest.uuid index 689e39e8ad..cf227b205f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -09ccc4a1be7ba81890f10aac6623dd90dab4f990 \ No newline at end of file +91d0437c0702904d27f0ef7b1b52d0797efe1826 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 0fae6cbc74..915e014aaa 100644 --- a/src/wal.c +++ b/src/wal.c @@ -414,6 +414,7 @@ struct Wal { u32 iCallback; /* Value to pass to log callback (or 0) */ i64 mxWalSize; /* Truncate WAL to this size upon reset */ int nWiData; /* Size of array apWiData */ + int szFirstBlock; /* Size of first block written to WAL file */ volatile u32 **apWiData; /* Pointer to wal-index content in memory */ u32 szPage; /* Database page size */ i16 readLock; /* Which read lock is being held. -1 for none */ @@ -2617,6 +2618,40 @@ static int walRestartLog(Wal *pWal){ return rc; } +/* +** Write iAmt bytes of content into the WAL file beginning at iOffset. +** +** When crossing the boundary between the first and second sectors of the +** file, first write all of the first sector content, then fsync(), then +** continue writing content for the second sector. This ensures that +** the WAL header is overwritten before the first commit mark. +*/ +static int walWriteToLog( + Wal *pWal, /* WAL to write to */ + void *pContent, /* Content to be written */ + int iAmt, /* Number of bytes to write */ + sqlite3_int64 iOffset /* Start writing at this offset */ +){ + int rc; + if( iOffset>=pWal->szFirstBlock || iOffset+iAmtszFirstBlock ){ + /* The common and fast case. Just write the data. */ + rc = sqlite3OsWrite(pWal->pWalFd, pContent, iAmt, iOffset); + }else{ + /* If this write will cross the first sector boundary, it has to + ** be split it two with a sync in between. */ + int iFirstAmt = pWal->szFirstBlock - iOffset; + assert( iFirstAmt>0 && iFirstAmtpWalFd, pContent, iFirstAmt, iOffset); + if( rc ) return rc; + rc = sqlite3OsSync(pWal->pWalFd, SQLITE_SYNC_NORMAL); + if( rc ) return rc; + pContent = (void*)(iFirstAmt + (char*)pContent); + rc = sqlite3OsWrite(pWal->pWalFd, pContent, + iAmt-iFirstAmt, iOffset+iFirstAmt); + } + return rc; +} + /* ** Write a set of frames to the log. The caller must hold the write-lock ** on the log file (obtained using sqlite3WalBeginWriteTransaction()). @@ -2686,6 +2721,10 @@ int sqlite3WalFrames( } assert( (int)pWal->szPage==szPage ); + /* The size of the block containing the WAL header */ + pWal->szFirstBlock = sqlite3OsSectorSize(pWal->pWalFd); + if( szPage>pWal->szFirstBlock ) pWal->szFirstBlock = szPage; + /* Write the log file. */ for(p=pList; p; p=p->pDirty){ u32 nDbsize; /* Db-size field for frame header */ @@ -2703,13 +2742,13 @@ int sqlite3WalFrames( pData = p->pData; #endif walEncodeFrame(pWal, p->pgno, nDbsize, pData, aFrame); - rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOffset); + rc = walWriteToLog(pWal, aFrame, sizeof(aFrame), iOffset); if( rc!=SQLITE_OK ){ return rc; } /* Write the page data */ - rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOffset+sizeof(aFrame)); + rc = walWriteToLog(pWal, pData, szPage, iOffset+sizeof(aFrame)); if( rc!=SQLITE_OK ){ return rc; } @@ -2734,12 +2773,12 @@ int sqlite3WalFrames( #endif walEncodeFrame(pWal, pLast->pgno, nTruncate, pData, aFrame); /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */ - rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOffset); + rc = walWriteToLog(pWal, aFrame, sizeof(aFrame), iOffset); if( rc!=SQLITE_OK ){ return rc; } iOffset += WAL_FRAME_HDRSIZE; - rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOffset); + rc = walWriteToLog(pWal, pData, szPage, iOffset); if( rc!=SQLITE_OK ){ return rc; }