From 6f1501481f3acb932fbf76618cf7e78809b55e19 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 21 May 2010 15:31:56 +0000 Subject: [PATCH] Remove entries from wal-index hash tables when a rollback or savepoint rollback occurs. FossilOrigin-Name: 36795c2b23a78978528cace193e386138adacd41 --- manifest | 26 ++++++++---------------- manifest.uuid | 2 +- src/wal.c | 55 ++++++++++++++++++++++++++++++++++++++++++++------ test/wal2.test | 27 ++++++++++++++++++++++++- 4 files changed, 84 insertions(+), 26 deletions(-) diff --git a/manifest b/manifest index 5a581f39da..4e7dd7e25f 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Fix\sthe\swal-index\sheader\sread\sroutine\sso\sthat\sit\scorrectly\sdetects\sa\szero\nheader\sas\sbeing\smalformed\sand\sin\sneed\sof\sa\swal-index\srebuild. -D 2010-05-21T13:16:19 +C Remove\sentries\sfrom\swal-index\shash\stables\swhen\sa\srollback\sor\ssavepoint\srollback\soccurs. +D 2010-05-21T15:31: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 1c3abceacad9659ecd1558be75a2114d953d3b7e +F src/wal.c c05f4091810a4cf4ff0e87f667c6e6341e143516 F src/wal.h 434f76f51225bb614e43ccb6bd2341541ba6a06e F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f F src/where.c 75fee9e255b62f773fcadd1d1f25b6f63ac7a356 @@ -765,7 +762,7 @@ F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d F test/wal.test 90afd254ece957a716751b1c35fac02d6353c2a7 -F test/wal2.test c9f470f7e4f09274a7a4d35dbbae8587115c6e19 +F test/wal2.test 6033cec945f51e3fc19502a69995aecb4252ca03 F test/walbak.test e7650a26eb4b8abeca9b145b1af1e63026dde432 F test/walcrash.test f6d5fb2bb108876f04848720a488065d9deef69f F test/walfault.test 98df47444944a6db2161eed5cef71d6c00bcb8c3 @@ -816,14 +813,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 1bd011c9fed5ef29fb616b4d0a52df3b82221b1f -R b1aca10baf167dbb95ab7e54f5a950e6 -U drh -Z 69b1bc82a1680c243dd4a43f4faa2d67 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFL9oenoxKgR168RlERAhg+AJ9n9qywdfuiNJpDkY+WtSlKP+eZVgCffwF8 -SmDbNBLJmDSM4k/xfAbThXY= -=j0sy ------END PGP SIGNATURE----- +P 1a4eb3a3efe86c7caff4d9a5894953bce378f841 +R 8ca2ea872b35ad91571755768a000a84 +U dan +Z 71ea7d7c3c51659a819f7c811c09c6cb diff --git a/manifest.uuid b/manifest.uuid index b7c453becd..b080f4751c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1a4eb3a3efe86c7caff4d9a5894953bce378f841 \ No newline at end of file +36795c2b23a78978528cace193e386138adacd41 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index a320d25e99..d6e712d531 100644 --- a/src/wal.c +++ b/src/wal.c @@ -193,8 +193,9 @@ ** second reader using K1 will see additional values that were inserted ** later, which is exactly what reader two wants. ** -** When a rollback occurs, the value of K is decreased. This has the -** effect of automatically removing entries from the hash table. +** When a rollback occurs, the value of K is decreased. Hash table entries +** that correspond to frames greater than the new K value are removed +** from the hash table at this point. */ #ifndef SQLITE_OMIT_WAL @@ -644,10 +645,10 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){ walHashFind(pWal, iFrame, &aHash, &aPgno, &iZero); idx = iFrame - iZero; - if( idx==1 ) memset((void*)aHash, 0xff, HASHTABLE_NBYTE); + if( idx==1 ) memset((void*)aHash, 0, HASHTABLE_NBYTE); assert( idx <= HASHTABLE_NSLOT/2 + 1 ); aPgno[iFrame] = iPage; - for(iKey=walHash(iPage); aHash[iKey] HASHTABLE_NPAGE ) mxHash = HASHTABLE_NPAGE; - for(iKey=walHash(pgno); aHash[iKey]<=mxHash; iKey=walNextHash(iKey)){ + for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ u32 iFrame = aHash[iKey] + iZero; - if( ALWAYS(iFrame<=iLast) && aPgno[iFrame]==pgno && iFrame>iRead ){ + if( iFrame<=iLast && aPgno[iFrame]==pgno && iFrame>iRead ){ iRead = iFrame; } } @@ -1465,6 +1466,40 @@ int sqlite3WalWriteLock(Wal *pWal, int op){ return rc; } +/* +** Remove entries from zero or more hash-table indexes in the wal-index +** file. +** +** This function is called when rolling back a transaction or savepoint +** transaction in WAL mode. Argument iNewMx is the value that +** Wal.hdr.mxFrame will be set to following the rollback. Argument iOldMx +** is the value that it had before the rollback. This function removes +** entries that refer to frames with frame numbers greater than iNewMx +** from the hash table that contains the entry associated with iNewMx. +** It is not necessary to remove any entries from any subsequent hash +** tables, as they will be zeroed by walIndexAppend() before they are +** next used. +*/ +static void walClearHash(Wal *pWal, u32 iOldMx, u32 iNewMx){ + if( iOldMx>iNewMx ){ + volatile HASHTABLE_DATATYPE *aHash; /* Pointer to hash table to clear */ + volatile u32 *unused1; /* Only to satisfy walHashFind() */ + u32 iZero; /* frame == (aHash[x]+iZero) */ + int iLimit; /* Zero values greater than this */ + + walHashFind(pWal, iNewMx+1, &aHash, &unused1, &iZero); + iLimit = iNewMx - iZero; + if( iLimit>0 ){ + int i; /* Used to iterate through aHash[] */ + for(i=1; i<=HASHTABLE_NPAGE; i++){ + if( aHash[i]>iLimit ){ + aHash[i] = 0; + } + } + } + } +} + /* ** If any data has been written (but not committed) to the log file, this ** function moves the write-pointer back to the start of the transaction. @@ -1490,6 +1525,9 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){ assert( pWal->lockState==SQLITE_SHM_WRITE ); rc = xUndo(pUndoCtx, pWal->pWiData[walIndexEntry(iFrame)]); } + if( rc==SQLITE_OK ){ + walClearHash(pWal, iMax, pWal->hdr.mxFrame); + } walIndexUnmap(pWal); } return rc; @@ -1510,6 +1548,11 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 iFrame){ int rc = SQLITE_OK; assert( pWal->lockState==SQLITE_SHM_WRITE ); + rc = walIndexMap(pWal, walMappingSize(pWal->hdr.mxFrame)); + if( rc==SQLITE_OK ){ + walClearHash(pWal, pWal->hdr.mxFrame, iFrame); + walIndexUnmap(pWal); + } pWal->hdr.mxFrame = iFrame; return rc; } diff --git a/test/wal2.test b/test/wal2.test index ead8cbbb17..ece7543eb8 100644 --- a/test/wal2.test +++ b/test/wal2.test @@ -600,7 +600,32 @@ do_test wal2-6.5.2 { do_test wal2-6.5.3 { execsql { PRAGMA wal_checkpoint } } {} - db close +#------------------------------------------------------------------------- +# Test a theory about the checksum algorithm. Theory was false and this +# test did not provoke a bug. +file delete -force test.db test.db-wal test.db-journal +do_test wal2-7.1.1 { + sqlite3 db test.db + execsql { + PRAGMA page_size = 4096; + PRAGMA journal_mode = WAL; + CREATE TABLE t1(a, b); + } + file size test.db +} {4096} +do_test wal2-7.1.2 { + file copy -force test.db test2.db + file copy -force test.db-wal test2.db-wal + hexio_write test2.db-wal 48 FF +} {1} +do_test wal2-7.1.3 { + sqlite3 db2 test2.db + execsql { PRAGMA wal_checkpoint } db2 + execsql { SELECT * FROM sqlite_master } db2 +} {} +db2 close + finish_test +