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
This commit is contained in:
dan 2010-06-01 15:44:57 +00:00
parent 964bf9c8bb
commit 9971e710e4
3 changed files with 77 additions and 52 deletions

View File

@ -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

View File

@ -1 +1 @@
1d3e569e59ba89cc167f0a48951ecd82f10322ba
b1abfaaf5309cc0d0dda4fb2c237862c8cf83261

103
src/wal.c
View File

@ -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, &notUsed, 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, &notUsed, 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 */