-C Fix\ssome\sproblems\swith\shandling\sIO\serrors\son\sthe\sexperimental\sbranch.
-D 2010-06-12T12:02:36
+C Add\ssome\sfault-injection\stests\sto\simprove\scoverage.
+D 2010-06-14T07:53:26
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c aa9919c885a1fe53eafc73492f0898ee6c0a0726
-F src/test_vfs.c c3643e985b000e1f7555bd843a508512a33ab60e
+F src/test_vfs.c 15bddcddf6b1bf6360130e09aee950f5f563d5f3
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 25ceb0f0a746ea1d0f9553787f3f0a56853cfaeb
F src/trigger.c 8927588cb9e6d47f933b53bfe74200fbb504100d
F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda
-F src/wal.c ca3e0bf68c78005dee4e0d44d112e26975476d10
+F src/wal.c 75c55049c0923418f10bbef842b846374637b595
F src/wal.h 4ace25262452d17e7d3ec970c89ee17794004008
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c 1c895bef33d0dfc7ed90fb1f74120435d210ea56
F test/walcksum.test 4efa8fb88c32bed8288ea4385a9cc113a5c8f0bf
F test/walcrash.test f6d5fb2bb108876f04848720a488065d9deef69f
F test/walcrash2.test 14585ad1a2c85da2de721caa3b4deeea55213008
-F test/walfault.test 0f9524cedbba0e5d48b58cabdc2dd7ae2c375476
+F test/walfault.test f6c1d0eade34fd0102e083726092d9bebd48bf7b
F test/walhook.test 67e675127f4acb72f061a12667ce6e5460b06b78
F test/walmode.test 6ca9d710cc9f6545b913abcded6d6b0b15641048
F test/walslow.test d21625e2e99e11c032ce949e8a94661576548933
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P ca68472db01c14a899892007d1cbaff5e86ae193
-R 8c9eec4fce430c14365187b617d56771
+P eade8bc238df580412f5cf1b91a91532ae671e46
+R d24014573c5813c3e5f096c2f4031503
U dan
-Z 808594079cf8cc56f07144318e40eca2
+Z e43653a42fa5b8fa5bb9c7db25e1bbd8
-eade8bc238df580412f5cf1b91a91532ae671e46
\ No newline at end of file
+37b26d125f4b1d8e75bb38800fefd145611f94aa
\ No newline at end of file
if( p->pScript && p->mask&TESTVFS_SHMPAGE_MASK ){
Tcl_Obj *pArg = Tcl_NewObj();
+ Tcl_IncrRefCount(pArg);
Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(iPage));
Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz));
Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite));
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg
);
tvfsResultCode(p, &rc);
+ Tcl_DecrRefCount(pArg);
}
if( rc==SQLITE_OK && p->mask&TESTVFS_SHMPAGE_MASK && tvfsInjectIoerr(p) ){
rc = SQLITE_IOERR;
Tcl_WrongNumArgs(interp, 2, objv, "FILE ?VALUE?");
return TCL_ERROR;
}
- zName = Tcl_GetString(objv[2]);
+ zName = ckalloc(p->pParent->mxPathname);
+ p->pParent->xFullPathname(
+ p->pParent, Tcl_GetString(objv[2]),
+ p->pParent->mxPathname, zName
+ );
for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){
if( 0==strcmp(pBuffer->zFile, zName) ) break;
}
+ ckfree(zName);
if( !pBuffer ){
- Tcl_AppendResult(interp, "no such file: ", zName, 0);
+ Tcl_AppendResult(interp, "no such file: ", Tcl_GetString(objv[2]), 0);
return TCL_ERROR;
}
if( objc==4 ){
{ "xShmLock", TESTVFS_SHMLOCK_MASK },
{ "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
{ "xShmClose", TESTVFS_SHMCLOSE_MASK },
+ { "xShmPage", TESTVFS_SHMPAGE_MASK },
{ "xSync", TESTVFS_SYNC_MASK },
{ "xOpen", TESTVFS_OPEN_MASK },
};
ckfree((char *)p->apScript);
p->apScript = 0;
p->nScript = 0;
+ p->pScript = 0;
}
Tcl_GetStringFromObj(objv[2], &nByte);
if( nByte>0 ){
p = (Testvfs *)ckalloc(nByte);
memset(p, 0, nByte);
+ /* Create the new object command before querying SQLite for a default VFS
+ ** to use for 'real' IO operations. This is because creating the new VFS
+ ** may delete an existing [testvfs] VFS of the same name. If such a VFS
+ ** is currently the default, the new [testvfs] may end up calling the
+ ** methods of a deleted object.
+ */
+ Tcl_CreateObjCommand(interp, zVfs, testvfs_obj_cmd, p, testvfs_obj_del);
p->pParent = sqlite3_vfs_find(0);
p->interp = interp;
p->isNoshm = isNoshm;
p->mask = TESTVFS_ALL_MASK;
- Tcl_CreateObjCommand(interp, zVfs, testvfs_obj_cmd, p, testvfs_obj_del);
sqlite3_vfs_register(pVfs, isDefault);
return TCL_OK;
#endif
}
+/*
+** Free an iterator allocated by walIteratorInit().
+*/
+static void walIteratorFree(WalIterator *p){
+ sqlite3_free(p);
+}
+
/*
** Map the wal-index into memory owned by this thread, if it is not
** mapped already. Then construct a WalInterator object that can be
rc = walHashGet(pWal, i, &aHash, &aPgno, &iZero);
if( rc!=SQLITE_OK ){
+ walIteratorFree(p);
return rc;
}
nEntry = ((i+1)==nSegment)?iLast-iZero:(u32 *)aHash-(u32 *)&aPgno[iZero+1];
return SQLITE_OK ;
}
-/*
-** Free an iterator allocated by walIteratorInit().
-*/
-static void walIteratorFree(WalIterator *p){
- sqlite3_free(p);
-}
-
/*
** Copy as much content as we can from the WAL back into the database file
** in response to an sqlite3_wal_checkpoint() request or the equivalent.
Pgno iMax = pWal->hdr.mxFrame;
Pgno iFrame;
- rc = walIndexReadHdr(pWal, &unused);
- if( rc==SQLITE_OK ){
- for(iFrame=pWal->hdr.mxFrame+1;
- ALWAYS(rc==SQLITE_OK) && iFrame<=iMax;
- iFrame++
- ){
- /* This call cannot fail. Unless the page for which the page number
- ** is passed as the second argument is (a) in the cache and
- ** (b) has an outstanding reference, then xUndo is either a no-op
- ** (if (a) is false) or simply expels the page from the cache (if (b)
- ** is false).
- **
- ** If the upper layer is doing a rollback, it is guaranteed that there
- ** are no outstanding references to any page other than page 1. And
- ** page 1 is never written to the log until the transaction is
- ** committed. As a result, the call to xUndo may not fail.
- */
- assert( pWal->writeLock );
- assert( walFramePgno(pWal, iFrame)!=1 );
- rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
- }
- walCleanupHash(pWal);
+ /* Restore the clients cache of the wal-index header to the state it
+ ** was in before the client began writing to the database.
+ */
+ memcpy(&pWal->hdr, walIndexHdr(pWal), sizeof(WalIndexHdr));
+
+ for(iFrame=pWal->hdr.mxFrame+1;
+ ALWAYS(rc==SQLITE_OK) && iFrame<=iMax;
+ iFrame++
+ ){
+ /* This call cannot fail. Unless the page for which the page number
+ ** is passed as the second argument is (a) in the cache and
+ ** (b) has an outstanding reference, then xUndo is either a no-op
+ ** (if (a) is false) or simply expels the page from the cache (if (b)
+ ** is false).
+ **
+ ** If the upper layer is doing a rollback, it is guaranteed that there
+ ** are no outstanding references to any page other than page 1. And
+ ** page 1 is never written to the log until the transaction is
+ ** committed. As a result, the call to xUndo may not fail.
+ */
+ assert( pWal->writeLock );
+ assert( walFramePgno(pWal, iFrame)!=1 );
+ rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
}
+ walCleanupHash(pWal);
}
+ assert( rc==SQLITE_OK );
return rc;
}
pWal->hdr.mxFrame = aWalData[0];
pWal->hdr.aFrameCksum[0] = aWalData[1];
pWal->hdr.aFrameCksum[1] = aWalData[2];
- if( rc==SQLITE_OK ){
- walCleanupHash(pWal);
- }
+ walCleanupHash(pWal);
}
return rc;
faultsim_test_result {0 {}}
}
+
#--------------------------------------------------------------------------
#
faultsim_delete_and_reopen
do_faultsim_test walfault-5 -faults shmerr* -prep {
faultsim_restore_and_reopen
execsql { PRAGMA wal_autocheckpoint = 0 }
- shmfault filter xShmSize
+ shmfault filter xShmPage
} -body {
execsql {
CREATE TABLE t1(x);
} {}
do_faultsim_test walfault-6 -faults shmerr* -prep {
faultsim_restore_and_reopen
- shmfault filter xShmSize
+ shmfault filter xShmPage
} -body {
execsql { SELECT count(*) FROM t1 }
} -test {
faultsim_delete_and_reopen
execsql {
PRAGMA journal_mode = WAL;
- PRAGMA wal_checkpoint = 0;
+ PRAGMA wal_autocheckpoint = 0;
CREATE TABLE z(zz INTEGER PRIMARY KEY, zzz BLOB);
CREATE INDEX zzzz ON z(zzz);
INSERT INTO z VALUES(NULL, randomblob(800));
if {$n != "64 51200"} { error "Incorrect data: $n" }
}
+#--------------------------------------------------------------------------
+# Test fault injection while checkpointing a large WAL file, if the
+# checkpoint is the first operation run after opening the database.
+# This means that some of the required wal-index pages are mapped as part of
+# the checkpoint process, which means there are a few more opportunities
+# for IO errors.
+#
+# To speed this up, IO errors are only simulated within xShmPage() calls.
+#
+do_test walfault-11-pre-1 {
+ sqlite3 db test.db
+ execsql {
+ PRAGMA journal_mode = WAL;
+ PRAGMA wal_autocheckpoint = 0;
+ BEGIN;
+ CREATE TABLE abc(a PRIMARY KEY);
+ INSERT INTO abc VALUES(randomblob(1500));
+ INSERT INTO abc VALUES(randomblob(1500));
+ INSERT INTO abc SELECT randomblob(1500) FROM abc; -- 4
+ INSERT INTO abc SELECT randomblob(1500) FROM abc; -- 8
+ INSERT INTO abc SELECT randomblob(1500) FROM abc; -- 16
+ INSERT INTO abc SELECT randomblob(1500) FROM abc; -- 32
+ INSERT INTO abc SELECT randomblob(1500) FROM abc; -- 64
+ INSERT INTO abc SELECT randomblob(1500) FROM abc; -- 128
+ INSERT INTO abc SELECT randomblob(1500) FROM abc; -- 256
+ INSERT INTO abc SELECT randomblob(1500) FROM abc; -- 512
+ INSERT INTO abc SELECT randomblob(1500) FROM abc; -- 1024
+ INSERT INTO abc SELECT randomblob(1500) FROM abc; -- 2048
+ INSERT INTO abc SELECT randomblob(1500) FROM abc; -- 4096
+ COMMIT;
+ }
+ faultsim_save_and_close
+} {}
+do_faultsim_test walfault-11 -faults shmerr* -prep {
+ catch { db2 close }
+ faultsim_restore_and_reopen
+ shmfault filter xShmPage
+} -body {
+ db eval { SELECT count(*) FROM abc }
+ sqlite3 db2 test.db -vfs shmfault
+ db2 eval { PRAGMA wal_checkpoint }
+} -test {
+ faultsim_test_result {0 {}}
+}
+
+#-------------------------------------------------------------------------
+# Test the handling of the various IO/OOM/SHM errors that may occur during
+# a log recovery operation undertaken as part of a call to
+# sqlite3_wal_checkpoint().
+#
+do_test walfault-12-pre-1 {
+ faultsim_delete_and_reopen
+ execsql {
+ PRAGMA journal_mode = WAL;
+ PRAGMA wal_autocheckpoint = 0;
+ BEGIN;
+ CREATE TABLE abc(a PRIMARY KEY);
+ INSERT INTO abc VALUES(randomblob(1500));
+ INSERT INTO abc VALUES(randomblob(1500));
+ COMMIT;
+ }
+ faultsim_save_and_close
+} {}
+do_faultsim_test walfault-12 -prep {
+ if {[info commands shmfault] == ""} {
+ testvfs shmfault -default true
+ }
+ faultsim_restore_and_reopen
+ db eval { SELECT * FROM sqlite_master }
+ shmfault shm test.db [string repeat "\000" 40]
+} -body {
+ set rc [sqlite3_wal_checkpoint db]
+ if {$rc != "SQLITE_OK"} { error [sqlite3_errmsg db] }
+} -test {
+ db close
+ faultsim_test_result {0 {}}
+}
+
+
finish_test