From 9971e710e4fbbe202d5956c0db0c0557f0332154 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 1 Jun 2010 15:44:57 +0000 Subject: [PATCH] Delay the decision to restart the log file until data is actually ready to be written to the log file (instead of at the start of a write transaction). FossilOrigin-Name: b1abfaaf5309cc0d0dda4fb2c237862c8cf83261 --- manifest | 24 ++++-------- manifest.uuid | 2 +- src/wal.c | 103 +++++++++++++++++++++++++++++++++----------------- 3 files changed, 77 insertions(+), 52 deletions(-) diff --git a/manifest b/manifest index 80de0fa850..9824a84442 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C The\sincremental\scheckpoint\sfeature\sis\snot\sperfect\syet,\sbut\sit\sis\sworking\nwell\senough\sto\smerge\sit\sinto\sthe\strunk. -D 2010-06-01T15:24:30 +C Delay\sthe\sdecision\sto\srestart\sthe\slog\sfile\suntil\sdata\sis\sactually\sready\sto\sbe\swritten\sto\sthe\slog\sfile\s(instead\sof\sat\sthe\sstart\sof\sa\swrite\stransaction). +D 2010-06-01T15:44:57 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -227,7 +224,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 131a5eaa59935cb3792ceed95a2b161a862c63f6 +F src/wal.c 2bd4ef3bfeb2481e9edd3d1858ff8db0bc3a650d F src/wal.h 1c1c9feb629b7f4afcbe0b47f80f47c5551d3a02 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f F src/where.c 75fee9e255b62f773fcadd1d1f25b6f63ac7a356 @@ -818,14 +815,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 15abbc34168f7a5bd418254c2b16aac97029e6ea f4b9003a2d3db88eaabb4b291e6cea8e8ea6ff51 -R 858d8d9dc0b3efa473b8ec6d14fcb8f5 -U drh -Z a6bb738fb568ab52924e606c6a5ae6d0 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFMBSYyoxKgR168RlERAlrVAJ9V4XzYgJAVXjVRCX0qxlsuSjehHgCdFXEg -GoCrBmurJgvyGZW2vBLkX4A= -=Giju ------END PGP SIGNATURE----- +P 1d3e569e59ba89cc167f0a48951ecd82f10322ba +R b704a2554ef7915333dfdde871fa034e +U dan +Z 3d2943f29bb11a4315abddbe2964e6d2 diff --git a/manifest.uuid b/manifest.uuid index 593dda5046..798ada6560 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d3e569e59ba89cc167f0a48951ecd82f10322ba \ No newline at end of file +b1abfaaf5309cc0d0dda4fb2c237862c8cf83261 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index dbac31ae35..dc143b4b17 100644 --- a/src/wal.c +++ b/src/wal.c @@ -2002,7 +2002,6 @@ void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno){ */ int sqlite3WalBeginWriteTransaction(Wal *pWal){ int rc; - volatile WalCkptInfo *pInfo; /* Cannot start a write transaction without first holding a read ** transaction. */ @@ -2030,39 +2029,9 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){ if( memcmp(&pWal->hdr, (void*)pWal->pWiData, sizeof(WalIndexHdr))!=0 ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); pWal->writeLock = 0; - walIndexUnmap(pWal); - return SQLITE_BUSY; + rc = SQLITE_BUSY; } - pInfo = walCkptInfo(pWal); - if( pWal->readLock==0 ){ - assert( pInfo->nBackfill==pWal->hdr.mxFrame ); - if( pInfo->nBackfill>0 ){ - rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); - if( rc==SQLITE_OK ){ - /* If all readers are using WAL_READ_LOCK(0) (in other words if no - ** readers are currently using the WAL) */ - pWal->nCkpt++; - pWal->hdr.mxFrame = 0; - sqlite3Put4byte((u8*)pWal->hdr.aSalt, - 1 + sqlite3Get4byte((u8*)pWal->hdr.aSalt)); - sqlite3_randomness(4, &pWal->hdr.aSalt[1]); - walIndexWriteHdr(pWal); - pInfo->nBackfill = 0; - memset((void*)&pInfo->aReadMark[1], 0, - sizeof(pInfo->aReadMark)-sizeof(u32)); - rc = sqlite3OsTruncate(pWal->pDbFd, - ((i64)pWal->hdr.nPage*(i64)pWal->szPage)); - walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); - } - } - walUnlockShared(pWal, WAL_READ_LOCK(0)); - pWal->readLock = -1; - do{ - int notUsed; - rc = walTryBeginRead(pWal, ¬Used, 1); - }while( rc==WAL_RETRY ); - } walIndexUnmap(pWal); return rc; } @@ -2150,9 +2119,66 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ return rc; } +/* +** This function is called just before writing a set of frames to the log +** file (see sqlite3WalFrames()). It checks to see if, instead of appending +** to the current log file, it is possible to overwrite the start of the +** existing log file with the new frames (i.e. "reset" the log). If so, +** it sets pWal->hdr.mxFrame to 0. Otherwise, pWal->hdr.mxFrame is left +** unchanged. +** +** SQLITE_OK is returned if no error is encountered (regardless of whether +** or not pWal->hdr.mxFrame is modified). An SQLite error code is returned +** if some error +*/ +static int walRestartLog(Wal *pWal){ + int rc = SQLITE_OK; + if( pWal->readLock==0 + && SQLITE_OK==(rc = walIndexMap(pWal, walMappingSize(pWal->hdr.mxFrame))) + ){ + volatile WalCkptInfo *pInfo = walCkptInfo(pWal); + assert( pInfo->nBackfill==pWal->hdr.mxFrame ); + if( pInfo->nBackfill>0 ){ + rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); + if( rc==SQLITE_OK ){ + /* If all readers are using WAL_READ_LOCK(0) (in other words if no + ** readers are currently using the WAL), then the transactions + ** frames will overwrite the start of the existing log. Update the + ** wal-index header to reflect this. + ** + ** In theory it would be Ok to update the cache of the header only + ** at this point. But updating the actual wal-index header is also + ** safe and means there is no special case for sqlite3WalUndo() + ** to handle if this transaction is rolled back. + */ + u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */ + pWal->nCkpt++; + pWal->hdr.mxFrame = 0; + sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0])); + sqlite3_randomness(4, &aSalt[1]); + walIndexWriteHdr(pWal); + memset((void*)pInfo, 0, sizeof(*pInfo)); + walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); + } + } + walUnlockShared(pWal, WAL_READ_LOCK(0)); + pWal->readLock = -1; + do{ + int notUsed; + rc = walTryBeginRead(pWal, ¬Used, 1); + }while( rc==WAL_RETRY ); + + /* Unmap the wal-index before returning. Otherwise the VFS layer may + ** hold a mutex for the duration of the IO performed by WalFrames(). + */ + walIndexUnmap(pWal); + } + return rc; +} + /* ** Write a set of frames to the log. The caller must hold the write-lock -** on the log file (obtained using sqlite3WalWriteLock()). +** on the log file (obtained using sqlite3WalBeginWriteTransaction()). */ int sqlite3WalFrames( Wal *pWal, /* Wal handle to write to */ @@ -2180,6 +2206,15 @@ int sqlite3WalFrames( } #endif + /* See if it is possible to write these frames into the start of the + ** log file, instead of appending to it at pWal->hdr.mxFrame. + */ + if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){ + assert( pWal->pWiData==0 ); + return rc; + } + assert( pWal->pWiData==0 && pWal->readLock>0 ); + /* If this is the first frame written into the log, write the WAL ** header to the start of the WAL file. See comments at the top of ** this source file for a description of the WAL header format. @@ -2203,7 +2238,7 @@ int sqlite3WalFrames( } assert( pWal->szPage==szPage ); - /* 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 */ -- 2.47.3