Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add a case to permutations.test to run tests with the test_journal.c backend installed. Also many fixes to test_journal.c and one quite obscure fix to pager.c. (CVS 6052) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
bb177e3072ab61d0af7af91660ebe4da |
User & Date: | danielk1977 2008-12-22 10:58:46.000 |
Context
2008-12-22
| ||
11:43 | Changes to test scripts so that veryquick.test runs with SQLITE_TEMP_STORE=3 defined. Also a fix to stop the same switch causing a crash in the savepoint code. (CVS 6053) (check-in: ee0e6eae9f user: danielk1977 tags: trunk) | |
10:58 | Add a case to permutations.test to run tests with the test_journal.c backend installed. Also many fixes to test_journal.c and one quite obscure fix to pager.c. (CVS 6052) (check-in: bb177e3072 user: danielk1977 tags: trunk) | |
03:37 | Fix a variable type to prevent a warning in the proxy-locking code. (CVS 6051) (check-in: d9595b9618 user: danielk1977 tags: trunk) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
367 368 369 370 371 372 373 374 375 376 377 378 379 380 | $(TOP)/src/test_autoext.c \ $(TOP)/src/test_async.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_func.c \ $(TOP)/src/test_hexio.c \ $(TOP)/src/test_malloc.c \ $(TOP)/src/test_md5.c \ $(TOP)/src/test_mutex.c \ $(TOP)/src/test_onefile.c \ $(TOP)/src/test_osinst.c \ $(TOP)/src/test_pcache.c \ $(TOP)/src/test_schema.c \ | > | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 | $(TOP)/src/test_autoext.c \ $(TOP)/src/test_async.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ $(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 \ $(TOP)/src/test_onefile.c \ $(TOP)/src/test_osinst.c \ $(TOP)/src/test_pcache.c \ $(TOP)/src/test_schema.c \ |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.520 2008/12/22 10:58:46 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" /* ** Macros for troubleshooting. Normally turned off */ |
︙ | ︙ | |||
3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 | } IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, pPager->journalOff, pPager->pageSize)); PAGER_INCR(sqlite3_pager_writej_count); PAGERTRACE5("JOURNAL %d page %d needSync=%d hash(%08x)\n", PAGERID(pPager), pPg->pgno, ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)); /* An error has occured writing to the journal file. The ** transaction will be rolled back by the layer above. */ if( rc!=SQLITE_OK ){ return rc; } pPager->nRec++; assert( pPager->pInJournal!=0 ); sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); | > > > > > > > > > > > < < < | 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 | } IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, pPager->journalOff, pPager->pageSize)); PAGER_INCR(sqlite3_pager_writej_count); PAGERTRACE5("JOURNAL %d page %d needSync=%d hash(%08x)\n", 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. */ if( rc!=SQLITE_OK ){ return rc; } pPager->nRec++; assert( pPager->pInJournal!=0 ); sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); addToSavepointBitvecs(pPager, pPg->pgno); }else{ if( !pPager->journalStarted && !pPager->noSync ){ pPg->flags |= PGHDR_NEED_SYNC; } PAGERTRACE4("APPEND %d page %d needSync=%d\n", PAGERID(pPager), pPg->pgno, |
︙ | ︙ | |||
3997 3998 3999 4000 4001 4002 4003 | int nNew = iSavepoint + (op==SAVEPOINT_ROLLBACK); for(ii=nNew; ii<pPager->nSavepoint; ii++){ sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); } pPager->nSavepoint = nNew; if( op==SAVEPOINT_ROLLBACK ){ | | | | 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 | int nNew = iSavepoint + (op==SAVEPOINT_ROLLBACK); for(ii=nNew; ii<pPager->nSavepoint; ii++){ sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint); } pPager->nSavepoint = nNew; if( op==SAVEPOINT_ROLLBACK ){ 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 ){ assert( rc==SQLITE_OK ); rc = sqlite3OsTruncate(pPager->sjfd, 0); pPager->stmtNRec = 0; } |
︙ | ︙ |
Changes to src/test_journal.c.
︙ | ︙ | |||
15 16 17 18 19 20 21 | ** bug in SQLite - writing data to a database file page when: ** ** a) the original page data is not stored in a synced portion of the ** journal file, and ** b) the page was not a free-list leaf page when the transaction was ** first opened. ** | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ** bug in SQLite - writing data to a database file page when: ** ** a) the original page data is not stored in a synced portion of the ** journal file, and ** b) the page was not a free-list leaf page when the transaction was ** first opened. ** ** $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 */ #include "sqlite3.h" #include "sqliteInt.h" /* |
︙ | ︙ | |||
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | }; struct JtGlobal { sqlite3_vfs *pVfs; jt_file *pList; }; static struct JtGlobal g = {0, 0}; /* ** Close an jt-file. */ static int jtClose(sqlite3_file *pFile){ jt_file **pp; jt_file *p = (jt_file *)pFile; if( p->zName ){ | > > > > > | | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | }; struct JtGlobal { sqlite3_vfs *pVfs; jt_file *pList; }; static struct JtGlobal g = {0, 0}; static void closeTransaction(jt_file *p){ sqlite3BitvecDestroy(p->pWritable); p->pWritable = 0; } /* ** Close an jt-file. */ static int jtClose(sqlite3_file *pFile){ jt_file **pp; jt_file *p = (jt_file *)pFile; if( p->zName ){ for(pp=&g.pList; *pp!=p; pp=&(*pp)->pNext); *pp = p->pNext; } return sqlite3OsClose(p->pReal); } /* |
︙ | ︙ | |||
179 180 181 182 183 184 185 | } static u32 decodeUint32(const unsigned char *z){ return (z[0]<<24) + (z[1]<<16) + (z[2]<<8) + z[3]; } | | > | | | | > | | > > | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | } static u32 decodeUint32(const unsigned char *z){ return (z[0]<<24) + (z[1]<<16) + (z[2]<<8) + z[3]; } static int readFreelist(jt_file *pMain){ int rc; sqlite3_file *p = pMain->pReal; sqlite3_int64 iSize; rc = sqlite3OsFileSize(p, &iSize); if( rc==SQLITE_OK && iSize>=pMain->nPagesize ){ unsigned char *zBuf = (unsigned char *)malloc(pMain->nPagesize); u32 iTrunk; rc = sqlite3OsRead(p, zBuf, pMain->nPagesize, 0); iTrunk = decodeUint32(&zBuf[32]); while( rc==SQLITE_OK && iTrunk>0 ){ u32 nLeaf; u32 iLeaf; sqlite3_int64 iOff = (iTrunk-1)*pMain->nPagesize; rc = sqlite3OsRead(p, zBuf, pMain->nPagesize, iOff); nLeaf = decodeUint32(&zBuf[4]); for(iLeaf=0; rc==SQLITE_OK && iLeaf<nLeaf; iLeaf++){ u32 pgno = decodeUint32(&zBuf[8+4*iLeaf]); sqlite3BitvecSet(pMain->pWritable, pgno); } iTrunk = decodeUint32(zBuf); } free(zBuf); } return rc; } /* ** The first argument, zBuf, points to a buffer containing a 28 byte ** serialized journal header. This function deserializes four of the ** integer fields contained in the journal header and writes their ** values to the output variables. |
︙ | ︙ | |||
245 246 247 248 249 250 251 | if( p->flags&SQLITE_OPEN_MAIN_JOURNAL && iOfst==0 ){ jt_file *pMain = locateDatabaseHandle(p->zName); assert( pMain ); if( decodeJournalHdr(zBuf, 0, &pMain->nPage, 0, &pMain->nPagesize) ){ /* Zeroing the first journal-file header. This is the end of a ** transaction. */ | < | > > > > | > > > | < < | < | | > | | | > | > | > > > | | > | | | > > > > < > | > > > > | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | if( p->flags&SQLITE_OPEN_MAIN_JOURNAL && iOfst==0 ){ jt_file *pMain = locateDatabaseHandle(p->zName); assert( pMain ); if( decodeJournalHdr(zBuf, 0, &pMain->nPage, 0, &pMain->nPagesize) ){ /* Zeroing the first journal-file header. This is the end of a ** transaction. */ 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); 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 && iAmt==p->nPagesize ){ u32 pgno = iOfst/p->nPagesize + 1; assert( pgno>p->nPage || sqlite3BitvecTest(p->pWritable, pgno) ); } return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); } /* ** Truncate an jt-file. */ static int jtTruncate(sqlite3_file *pFile, sqlite_int64 size){ jt_file *p = (jt_file *)pFile; 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); closeTransaction(pMain); } return sqlite3OsTruncate(p->pReal, size); } /* ** The first argument to this function is a handle open on a journal file. ** 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 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; rc = sqlite3OsFileSize(p->pReal, &iSize); while( rc==SQLITE_OK && iOff<iSize ){ u32 nRec, nPage, nSector, nPagesize; u32 ii; rc = sqlite3OsRead(pReal, zBuf, 28, iOff); if( rc!=SQLITE_OK || decodeJournalHdr(zBuf, &nRec, &nPage, &nSector, &nPagesize) ){ return rc; } iOff += nSector; if( nRec==0 ){ nRec = (iSize - iOff)/(pMain->nPagesize + 8); } for(ii=0; rc==SQLITE_OK && ii<nRec && iOff<iSize; ii++){ u32 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; } /* ** Sync an jt-file. */ 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 ** contents of the file up to this point and set each bit in the ** jt_file.pWritable bitvec of the main database file associated with ** this journal file. */ pMain = locateDatabaseHandle(p->zName); assert(pMain); /* Set the bitvec values */ if( pMain->pWritable ){ rc = readJournalFile(p, pMain); if( rc!=SQLITE_OK ){ return rc; } } } return sqlite3OsSync(p->pReal, flags); } /* ** Return the current file-size of an jt-file. |
︙ | ︙ | |||
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 | rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags); if( p->pReal->pMethods ){ pFile->pMethods = &jt_io_methods; p->eLock = 0; p->zName = zName; p->flags = flags; p->pNext = 0; if( zName ){ p->pNext = g.pList; g.pList = p; } } return rc; } /* ** Delete the file located at zPath. If the dirSync argument is true, ** ensure the file-system modifications are synced to disk before ** returning. */ static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ int nPath = strlen(zPath); if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){ /* Deleting a journal file. The end of a transaction. */ jt_file *pMain = locateDatabaseHandle(zPath); | > | | > | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags); if( p->pReal->pMethods ){ pFile->pMethods = &jt_io_methods; p->eLock = 0; p->zName = zName; p->flags = flags; p->pNext = 0; p->pWritable = 0; if( zName ){ p->pNext = g.pList; g.pList = p; } } return rc; } /* ** Delete the file located at zPath. If the dirSync argument is true, ** ensure the file-system modifications are synced to disk before ** returning. */ static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ int nPath = strlen(zPath); if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){ /* Deleting a journal file. The end of a transaction. */ jt_file *pMain = locateDatabaseHandle(zPath); if( pMain ){ closeTransaction(pMain); } } return sqlite3OsDelete(g.pVfs, zPath, dirSync); } /* ** Test for access permissions. Return true if the requested permission |
︙ | ︙ |
Changes to test/permutations.test.
1 2 3 4 5 6 7 8 9 10 11 | # 2008 June 21 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # 2008 June 21 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # $Id: permutations.test,v 1.40 2008/12/22 10:58:46 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Argument processing. # #puts "PERM-DEBUG: argv=$argv" |
︙ | ︙ | |||
35 36 37 38 39 40 41 | set ::perm::testmode [list persistent_journal no_journal autovacuum_ioerr] set ISQUICK 1 } 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 | | | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | set ::perm::testmode [list persistent_journal no_journal autovacuum_ioerr] set ISQUICK 1 } 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 journaltest } } if {$::perm::testmode eq "targets"} { puts "" puts -nonewline "veryquick " puts "Same as persistent_journal and no_journal" puts -nonewline "quick " |
︙ | ︙ | |||
700 701 702 703 704 705 706 707 708 709 710 711 712 713 | } -shutdown { catch {db close} sqlite3_reset_auto_extension sqlite3_shutdown sqlite3_config_alt_pcache 0 0 0 sqlite3_initialize } -include ${perm-alt-pcache-testset} # End of tests ############################################################################# if {$::perm::testmode eq "targets"} { puts "" ; exit } # Restore the [sqlite3] command. | > > > > > > > > > > > > > > > | 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 | } -shutdown { catch {db close} sqlite3_reset_auto_extension sqlite3_shutdown sqlite3_config_alt_pcache 0 0 0 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 ############################################################################# if {$::perm::testmode eq "targets"} { puts "" ; exit } # Restore the [sqlite3] command. |
︙ | ︙ |
Changes to test/savepoint2.test.
1 2 3 4 5 6 7 8 9 10 11 | # 2008 December 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # | | < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # 2008 December 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # $Id: savepoint2.test,v 1.4 2008/12/22 10:58:46 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Tests in this file are quite similar to those run by trans.test and # avtrans.test. # proc signature {} { return [db eval {SELECT count(*), md5sum(x) FROM t3}] } do_test savepoint2-1 { execsql { PRAGMA cache_size=10; |
︙ | ︙ | |||
145 146 147 148 149 150 151 | } {1} integrity_check savepoint2-$ii.6.1 } unset -nocomplain ::sig unset -nocomplain SQL | < < | 141 142 143 144 145 146 147 148 149 | } {1} integrity_check savepoint2-$ii.6.1 } unset -nocomplain ::sig unset -nocomplain SQL finish_test |
Changes to test/trans.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is database locks. # | | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is database locks. # # $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 { execsql { CREATE TABLE one(a int PRIMARY KEY, b text); INSERT INTO one VALUES(1,'one'); |
︙ | ︙ |