diff --git a/Makefile.in b/Makefile.in index 3b0f9a12b8..6f2dbd6fcc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -371,6 +371,7 @@ TESTSRC = \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_func.c \ $(TOP)/src/test_hexio.c \ + $(TOP)/src/test_journal.c \ $(TOP)/src/test_malloc.c \ $(TOP)/src/test_md5.c \ $(TOP)/src/test_mutex.c \ diff --git a/manifest b/manifest index a9a0f08d33..e556dd5f0d 100644 --- a/manifest +++ b/manifest @@ -1,7 +1,7 @@ -C Fix\sa\svariable\stype\sto\sprevent\sa\swarning\sin\sthe\sproxy-locking\scode.\s(CVS\s6051) -D 2008-12-22T03:37:00 +C Add\sa\scase\sto\spermutations.test\sto\srun\stests\swith\sthe\stest_journal.c\sbackend\sinstalled.\sAlso\smany\sfixes\sto\stest_journal.c\sand\sone\squite\sobscure\sfix\sto\spager.c.\s(CVS\s6052) +D 2008-12-22T10:58:46 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 -F Makefile.in f7e4c81c347b04f7b0f1c1b081a168645d7b8af7 +F Makefile.in 77635d0909c2067cee03889a1e04ce910d8fb809 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.vxwSH4 d53b4be86491060d498b22148951b6d765884cab F README b974cdc3f9f12b87e851b04e75996d720ebf81ac @@ -142,7 +142,7 @@ F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60 F src/os_os2.c bed77dc26e3a95ce4a204936b9a1ca6fe612fcc5 F src/os_unix.c e6eacc7ec735ded605fefcbaf250058baa8feb12 F src/os_win.c 496e3ceb499aedc63622a89ef76f7af2dd902709 -F src/pager.c 5c2b49c37db966bc312ff28d296767961fb894c3 +F src/pager.c 4fc24d29d699c00169a129fa6835a1ea31598873 F src/pager.h 7191294438881eb4d13eedade97891e8dc993905 F src/parse.y 4d0e33a702dc3ea7b69d8ae1914b3fbd32e46057 F src/pcache.c 16dc8da6e6ba6250f8dfd9ee46036db1cbceedc6 @@ -179,7 +179,7 @@ F src/test_config.c 4f85387a52f3c7966c3ffab913e988a3830fe1af F src/test_devsym.c 9f4bc2551e267ce7aeda195f3897d0f30c5228f4 F src/test_func.c a55c4d5479ff2eb5c0a22d4d88e9528ab59c953b F src/test_hexio.c 2f1122aa3f012fa0142ee3c36ce5c902a70cd12f -F src/test_journal.c 74b97d631841b0ebd55e54ba059f61299f537667 +F src/test_journal.c aec37656038150fa60f0418d54b1c535b5b33430 F src/test_loadext.c 97dc8800e46a46ed002c2968572656f37e9c0dd9 F src/test_malloc.c 5127337c9fb4c851a7f604c0170e0e5ca1fbfe33 F src/test_md5.c 28209a4e2068711b5443c33104fe41f21d160071 @@ -476,7 +476,7 @@ F test/pageropt.test 3ee6578891baaca967f0bd349e4abfa736229e1a F test/pagesize.test 0d9ff3fedfce6e5ffe8fa7aca9b6d3433a2e843b F test/pcache.test 515b4c26e9f57660357dfff5b6b697acac1abc5f F test/pcache2.test 46efd980a89f737847b99327bda19e08fe11e402 -F test/permutations.test 5308a94878efc81a8e8ce133926dfb2c53d19133 +F test/permutations.test 4fd4c7944c42201799c0e2855261f54e1bfda6d2 F test/pragma.test 0f299601c3b15e8941eb48d2f7a43e6678e3f735 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 262a5acd3158f788e9bdf7f18d718f3af32ff6ef @@ -493,7 +493,7 @@ F test/rowid.test 1c8fc43c60d273e6ea44dfb992db587f3164312c F test/rtree.test b85fd4f0861a40ca366ac195e363be2528dcfadf F test/safety.test b69e2b2dd5d52a3f78e216967086884bbc1a09c6 F test/savepoint.test 24b7d67971c0b7a8d22ba1cabbfd846e72f21594 -F test/savepoint2.test e1c29bd8341a0214903455971833603852254279 +F test/savepoint2.test 18f6c75d5c133b93838019df8988b8cdf379d3de F test/savepoint3.test b3c9aa5af3f777ccb8b9e15597c75c93eb5bc369 F test/savepoint4.test fd8850063e3c40565545f5c291e7f79a30591670 F test/schema.test a8b000723375fd42c68d310091bdbd744fde647c @@ -607,7 +607,7 @@ F test/tkt3541.test 5dc257bde9bc833ab9cc6844bf170b998dbb950a F test/tkt35xx.test 53bca895091e968126a858ee7da186f59f328994 F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7 F test/trace.test 951cd0f5f571e7f36bf7bfe04be70f90fb16fb00 -F test/trans.test 2fd24cd7aa0b879d49a224cbd647d698f1e7ac5c +F test/trans.test b3f0c696ddf8c3f113fd2edf49318b2bf431c99a F test/trans2.test d5337e61de45e66b1fcbf9db833fa8c82e624b22 F test/trans3.test d728abaa318ca364dc370e06576aa7e5fbed7e97 F test/trigger1.test 53342dfd582155a599518f1918fdc997e9413177 @@ -684,7 +684,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 778e91ddb834f6084ecdf3909692b54bb7da8f6d -R 24c69e7f21063e09d372b85b48a9e328 +P d9595b961800a13c141bebdb8c0a67377f30efad +R b5374e09d172c2ab41305c978396d82d U danielk1977 -Z a57801844c740a64a631ffb37d80b4cc +Z 98d2c97eeee17c8939e3e7380b43abd8 diff --git a/manifest.uuid b/manifest.uuid index 11a3904553..317617eaa2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d9595b961800a13c141bebdb8c0a67377f30efad \ No newline at end of file +bb177e3072ab61d0af7af91660ebe4dafa487b42 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index acc923e3d4..bb869523bb 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.519 2008/12/20 08:39:57 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.520 2008/12/22 10:58:46 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -3280,6 +3280,17 @@ static int pager_write(PgHdr *pPg){ PAGERID(pPager), pPg->pgno, ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)); + /* Even if an IO or diskfull error occurred while journalling the + ** page in the block above, set the need-sync flag for the page. + ** Otherwise, when the transaction is rolled back, the logic in + ** playback_one_page() will think that the page needs to be restored + ** in the database file. And if an IO error occurs while doing so, + ** then corruption may follow. + */ + if( !pPager->noSync ){ + pPg->flags |= PGHDR_NEED_SYNC; + } + /* An error has occured writing to the journal file. The ** transaction will be rolled back by the layer above. */ @@ -3290,9 +3301,6 @@ static int pager_write(PgHdr *pPg){ pPager->nRec++; assert( pPager->pInJournal!=0 ); sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); - if( !pPager->noSync ){ - pPg->flags |= PGHDR_NEED_SYNC; - } addToSavepointBitvecs(pPager, pPg->pgno); }else{ if( !pPager->journalStarted && !pPager->noSync ){ @@ -4001,11 +4009,11 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ pPager->nSavepoint = nNew; if( op==SAVEPOINT_ROLLBACK ){ - PagerSavepoint *pSavepoint = (nNew==0) ? 0 : &pPager->aSavepoint[nNew-1]; + PagerSavepoint *pSavepoint = (nNew==0)?0:&pPager->aSavepoint[nNew-1]; rc = pagerPlaybackSavepoint(pPager, pSavepoint); assert(rc!=SQLITE_DONE); } - + /* If this is a release of the outermost savepoint, truncate ** the sub-journal. */ if( nNew==0 && op==SAVEPOINT_RELEASE && pPager->sjfd->pMethods ){ diff --git a/src/test_journal.c b/src/test_journal.c index 73fc8b9416..aa29cbf9bd 100644 --- a/src/test_journal.c +++ b/src/test_journal.c @@ -19,7 +19,7 @@ ** b) the page was not a free-list leaf page when the transaction was ** first opened. ** -** $Id: test_journal.c,v 1.1 2008/12/20 18:33:59 danielk1977 Exp $ +** $Id: test_journal.c,v 1.2 2008/12/22 10:58:46 danielk1977 Exp $ */ #if SQLITE_TEST /* This file is used for testing only */ @@ -134,6 +134,11 @@ struct JtGlobal { }; static struct JtGlobal g = {0, 0}; +static void closeTransaction(jt_file *p){ + sqlite3BitvecDestroy(p->pWritable); + p->pWritable = 0; +} + /* ** Close an jt-file. */ @@ -142,7 +147,7 @@ static int jtClose(sqlite3_file *pFile){ jt_file *p = (jt_file *)pFile; if( p->zName ){ - for(pp=&g.pList; *pp!=p; *pp=(*pp)->pNext); + for(pp=&g.pList; *pp!=p; pp=&(*pp)->pNext); *pp = p->pNext; } @@ -183,23 +188,25 @@ static u32 decodeUint32(const unsigned char *z){ return (z[0]<<24) + (z[1]<<16) + (z[2]<<8) + z[3]; } -static void readFreelist(jt_file *pMain){ +static int readFreelist(jt_file *pMain){ + int rc; sqlite3_file *p = pMain->pReal; sqlite3_int64 iSize; - sqlite3OsFileSize(p, &iSize); - if( iSize>=pMain->nPagesize ){ + rc = sqlite3OsFileSize(p, &iSize); + if( rc==SQLITE_OK && iSize>=pMain->nPagesize ){ unsigned char *zBuf = (unsigned char *)malloc(pMain->nPagesize); u32 iTrunk; - sqlite3OsRead(p, zBuf, pMain->nPagesize, 0); + rc = sqlite3OsRead(p, zBuf, pMain->nPagesize, 0); iTrunk = decodeUint32(&zBuf[32]); - while( iTrunk>0 ){ + while( rc==SQLITE_OK && iTrunk>0 ){ u32 nLeaf; u32 iLeaf; - sqlite3OsRead(p, zBuf, pMain->nPagesize, (iTrunk-1)*pMain->nPagesize); + sqlite3_int64 iOff = (iTrunk-1)*pMain->nPagesize; + rc = sqlite3OsRead(p, zBuf, pMain->nPagesize, iOff); nLeaf = decodeUint32(&zBuf[4]); - for(iLeaf=0; iLeafpWritable, pgno); } @@ -208,6 +215,8 @@ static void readFreelist(jt_file *pMain){ free(zBuf); } + + return rc; } /* @@ -249,20 +258,24 @@ static int jtWrite( if( decodeJournalHdr(zBuf, 0, &pMain->nPage, 0, &pMain->nPagesize) ){ /* Zeroing the first journal-file header. This is the end of a ** transaction. */ - sqlite3BitvecDestroy(pMain->pWritable); - pMain->pWritable = 0; + closeTransaction(pMain); }else{ /* Writing the first journal header to a journal file. This happens ** when a transaction is first started. */ + int rc; pMain->pWritable = sqlite3BitvecCreate(pMain->nPage); - readFreelist(pMain); + if( !pMain->pWritable ){ + return SQLITE_IOERR_NOMEM; + } + rc = readFreelist(pMain); + if( rc!=SQLITE_OK ){ + return rc; + } } } - if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){ - u32 pgno; - assert( iAmt==p->nPagesize ); - pgno = iOfst/p->nPagesize + 1; + if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable && iAmt==p->nPagesize ){ + u32 pgno = iOfst/p->nPagesize + 1; assert( pgno>p->nPage || sqlite3BitvecTest(p->pWritable, pgno) ); } @@ -277,8 +290,7 @@ static int jtTruncate(sqlite3_file *pFile, sqlite_int64 size){ if( p->flags&SQLITE_OPEN_MAIN_JOURNAL && size==0 ){ /* Truncating a journal file. This is the end of a transaction. */ jt_file *pMain = locateDatabaseHandle(p->zName); - sqlite3BitvecDestroy(pMain->pWritable); - pMain->pWritable = 0; + closeTransaction(pMain); } return sqlite3OsTruncate(p->pReal, size); } @@ -288,31 +300,41 @@ static int jtTruncate(sqlite3_file *pFile, sqlite_int64 size){ ** This function reads the journal file and adds the page number for each ** page in the journal to the Bitvec object passed as the second argument. */ -static void readJournalFile(jt_file *p, jt_file *pMain){ +static int readJournalFile(jt_file *p, jt_file *pMain){ + int rc; unsigned char zBuf[28]; sqlite3_file *pReal = p->pReal; sqlite3_int64 iOff = 0; sqlite3_int64 iSize = 0; - sqlite3OsFileSize(p->pReal, &iSize); - while( iOffpReal, &iSize); + while( rc==SQLITE_OK && iOffnPagesize + 8); + } + for(ii=0; rc==SQLITE_OK && iinPagesize); - sqlite3BitvecSet(pMain->pWritable, pgno); + rc = sqlite3OsRead(pReal, zBuf, 4, iOff); + if( rc==SQLITE_OK ){ + pgno = decodeUint32(zBuf); + iOff += (8 + pMain->nPagesize); + sqlite3BitvecSet(pMain->pWritable, pgno); + } } iOff = ((iOff + (nSector-1)) / nSector) * nSector; } + + return rc; } /* @@ -322,6 +344,7 @@ static int jtSync(sqlite3_file *pFile, int flags){ jt_file *p = (jt_file *)pFile; if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){ + int rc; jt_file *pMain; /* The associated database file */ /* The journal file is being synced. At this point, we inspect the @@ -331,10 +354,14 @@ static int jtSync(sqlite3_file *pFile, int flags){ */ pMain = locateDatabaseHandle(p->zName); assert(pMain); - assert(pMain->pWritable); /* Set the bitvec values */ - readJournalFile(p, pMain); + if( pMain->pWritable ){ + rc = readJournalFile(p, pMain); + if( rc!=SQLITE_OK ){ + return rc; + } + } } return sqlite3OsSync(p->pReal, flags); @@ -426,6 +453,7 @@ static int jtOpen( p->zName = zName; p->flags = flags; p->pNext = 0; + p->pWritable = 0; if( zName ){ p->pNext = g.pList; g.pList = p; @@ -444,8 +472,9 @@ static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){ /* Deleting a journal file. The end of a transaction. */ jt_file *pMain = locateDatabaseHandle(zPath); - sqlite3BitvecDestroy(pMain->pWritable); - pMain->pWritable = 0; + if( pMain ){ + closeTransaction(pMain); + } } return sqlite3OsDelete(g.pVfs, zPath, dirSync); diff --git a/test/permutations.test b/test/permutations.test index c4cfaa9ea6..db9e49fea5 100644 --- a/test/permutations.test +++ b/test/permutations.test @@ -9,7 +9,7 @@ # #*********************************************************************** # -# $Id: permutations.test,v 1.39 2008/11/19 01:20:26 drh Exp $ +# $Id: permutations.test,v 1.40 2008/12/22 10:58:46 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -39,7 +39,7 @@ if {$::perm::testmode eq "all" || $::perm::testmode eq ""} { set ::perm::testmode { memsubsys1 memsubsys2 singlethread multithread onefile utf16 exclusive persistent_journal persistent_journal_error no_journal no_journal_error - autovacuum_ioerr no_mutex_try fullmutex + autovacuum_ioerr no_mutex_try fullmutex journaltest } } if {$::perm::testmode eq "targets"} { @@ -705,6 +705,21 @@ run_tests "pcache100" -description { sqlite3_initialize } -include ${perm-alt-pcache-testset} +run_tests "journaltest" -description { + Check that pages are synced before being written (test_journal.c). +} -initialize { + set ISQUICK 1 + catch {db close} + register_jt_vfs -default "" +} -shutdown { + unregister_jt_vfs +} -exclude [concat $EXCLUDE { + incrvacuum.test + ioerr.test + corrupt4.test + io.test +}] + # End of tests ############################################################################# diff --git a/test/savepoint2.test b/test/savepoint2.test index e7d4f8b202..2b630366d1 100644 --- a/test/savepoint2.test +++ b/test/savepoint2.test @@ -9,7 +9,7 @@ # #*********************************************************************** # -# $Id: savepoint2.test,v 1.3 2008/12/20 18:33:59 danielk1977 Exp $ +# $Id: savepoint2.test,v 1.4 2008/12/22 10:58:46 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -18,10 +18,6 @@ source $testdir/tester.tcl # avtrans.test. # -db close -register_jt_vfs -default "" -sqlite3 db test.db -vfs jt - proc signature {} { return [db eval {SELECT count(*), md5sum(x) FROM t3}] } @@ -149,7 +145,5 @@ for {set ii 2} {$ii < ($iterations+2)} {incr ii} { unset -nocomplain ::sig unset -nocomplain SQL -unregister_jt_vfs - finish_test diff --git a/test/trans.test b/test/trans.test index e5ffcd2cb0..be315641bd 100644 --- a/test/trans.test +++ b/test/trans.test @@ -11,13 +11,12 @@ # This file implements regression tests for SQLite library. The # focus of this script is database locks. # -# $Id: trans.test,v 1.38 2008/04/19 20:34:19 drh Exp $ +# $Id: trans.test,v 1.39 2008/12/22 10:58:46 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl - # Create several tables to work with. # do_test trans-1.0 {