Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add a version number to the wal-index header. If SQLite encounters a version number in either the wal or wal-index files that it does not understand, the operation is abandoned and SQLITE_CANTOPEN returned. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
8d0f8a7f70d6fb42369411a934b30f8c |
User & Date: | dan 2010-06-23 15:55:43.000 |
Context
2010-06-23
| ||
17:58 | Adjust the shared-memory locking range to account for the new version number values in the wal-index header. (check-in: a6dc0df304 user: drh tags: trunk) | |
15:55 | Add a version number to the wal-index header. If SQLite encounters a version number in either the wal or wal-index files that it does not understand, the operation is abandoned and SQLITE_CANTOPEN returned. (check-in: 8d0f8a7f70 user: dan tags: trunk) | |
15:18 | Fix the xCurrentTimeInt64 interface on windows. It was off by a factor of 10. (check-in: 51ef43b9f7 user: drh tags: trunk) | |
Changes
Changes to src/wal.c.
︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 45 46 47 48 49 | ** ** 0: Magic number. 0x377f0682 or 0x377f0683 ** 4: File format version. Currently 3007000 ** 8: Database page size. Example: 1024 ** 12: Checkpoint sequence number ** 16: Salt-1, random integer incremented with each checkpoint ** 20: Salt-2, a different random integer changing with each ckpt ** ** Immediately following the wal-header are zero or more frames. Each ** frame consists of a 24-byte frame-header followed by a <page-size> bytes ** of page data. The frame-header is broken into 6 big-endian 32-bit unsigned ** integer values, as follows: ** ** 0: Page number. | > > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | ** ** 0: Magic number. 0x377f0682 or 0x377f0683 ** 4: File format version. Currently 3007000 ** 8: Database page size. Example: 1024 ** 12: Checkpoint sequence number ** 16: Salt-1, random integer incremented with each checkpoint ** 20: Salt-2, a different random integer changing with each ckpt ** 24: Checksum-1 (first part of checksum for first 24 bytes of header). ** 28: Checksum-2 (second part of checksum for first 24 bytes of header). ** ** Immediately following the wal-header are zero or more frames. Each ** frame consists of a 24-byte frame-header followed by a <page-size> bytes ** of page data. The frame-header is broken into 6 big-endian 32-bit unsigned ** integer values, as follows: ** ** 0: Page number. |
︙ | ︙ | |||
242 243 244 245 246 247 248 249 250 251 252 253 254 255 | #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) int sqlite3WalTrace = 0; # define WALTRACE(X) if(sqlite3WalTrace) sqlite3DebugPrintf X #else # define WALTRACE(X) #endif /* ** Indices of various locking bytes. WAL_NREADER is the number ** of available reader locks and should be at least 3. */ #define WAL_WRITE_LOCK 0 #define WAL_ALL_BUT_WRITE 1 | > > > > > > > > > > > > > > > | 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | #if defined(SQLITE_TEST) && defined(SQLITE_DEBUG) int sqlite3WalTrace = 0; # define WALTRACE(X) if(sqlite3WalTrace) sqlite3DebugPrintf X #else # define WALTRACE(X) #endif /* ** The maximum (and only) versions of the wal and wal-index formats ** that may be interpreted by this version of SQLite. ** ** If a client begins recovering a WAL file and finds that (a) the checksum ** values in the wal-header are correct and (b) the version field is not ** WAL_MAX_VERSION, recovery fails and SQLite returns SQLITE_CANTOPEN. ** ** Similarly, if a client successfully reads a wal-index header (i.e. the ** checksum test is successful) and finds that the version field is not ** WALINDEX_MAX_VERSION, then no read-transaction is opened and SQLite ** returns SQLITE_CANTOPEN. */ #define WAL_MAX_VERSION 3007000 #define WALINDEX_MAX_VERSION 3007000 /* ** Indices of various locking bytes. WAL_NREADER is the number ** of available reader locks and should be at least 3. */ #define WAL_WRITE_LOCK 0 #define WAL_ALL_BUT_WRITE 1 |
︙ | ︙ | |||
268 269 270 271 272 273 274 275 276 277 278 279 280 281 | /* ** The following object holds a copy of the wal-index header content. ** ** The actual header in the wal-index consists of two copies of this ** object. */ struct WalIndexHdr { u32 iChange; /* Counter incremented each transaction */ u8 isInit; /* 1 when initialized */ u8 bigEndCksum; /* True if checksums in WAL are big-endian */ u16 szPage; /* Database page size in bytes */ u32 mxFrame; /* Index of last valid frame in the WAL */ u32 nPage; /* Size of database in pages */ u32 aFrameCksum[2]; /* Checksum of last frame in log */ | > > | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | /* ** The following object holds a copy of the wal-index header content. ** ** The actual header in the wal-index consists of two copies of this ** object. */ struct WalIndexHdr { u32 iVersion; /* Wal-index version */ u32 unused; /* Unused (padding) field */ u32 iChange; /* Counter incremented each transaction */ u8 isInit; /* 1 when initialized */ u8 bigEndCksum; /* True if checksums in WAL are big-endian */ u16 szPage; /* Database page size in bytes */ u32 mxFrame; /* Index of last valid frame in the WAL */ u32 nPage; /* Size of database in pages */ u32 aFrameCksum[2]; /* Checksum of last frame in log */ |
︙ | ︙ | |||
347 348 349 350 351 352 353 | #define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2 + sizeof(WalCkptInfo)) #define WALINDEX_LOCK_RESERVED 16 #define WALINDEX_HDR_SIZE (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED) /* Size of header before each frame in wal */ #define WAL_FRAME_HDRSIZE 24 | | > | | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | #define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2 + sizeof(WalCkptInfo)) #define WALINDEX_LOCK_RESERVED 16 #define WALINDEX_HDR_SIZE (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED) /* Size of header before each frame in wal */ #define WAL_FRAME_HDRSIZE 24 /* Size of write ahead log header, including checksum. */ /* #define WAL_HDRSIZE 24 */ #define WAL_HDRSIZE 32 /* WAL magic value. Either this value, or the same value with the least ** significant bit also set (WAL_MAGIC | 0x00000001) is stored in 32-bit ** big-endian format in the first 4 bytes of a WAL file. ** ** If the LSB is set, then the checksums for each frame within the WAL ** file are calculated by treating all data as an array of 32-bit |
︙ | ︙ | |||
576 577 578 579 580 581 582 583 584 585 586 587 588 589 | */ static void walIndexWriteHdr(Wal *pWal){ volatile WalIndexHdr *aHdr = walIndexHdr(pWal); const int nCksum = offsetof(WalIndexHdr, aCksum); assert( pWal->writeLock ); pWal->hdr.isInit = 1; walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum); memcpy((void *)&aHdr[1], (void *)&pWal->hdr, sizeof(WalIndexHdr)); sqlite3OsShmBarrier(pWal->pDbFd); memcpy((void *)&aHdr[0], (void *)&pWal->hdr, sizeof(WalIndexHdr)); } /* | > | 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 | */ static void walIndexWriteHdr(Wal *pWal){ volatile WalIndexHdr *aHdr = walIndexHdr(pWal); const int nCksum = offsetof(WalIndexHdr, aCksum); assert( pWal->writeLock ); pWal->hdr.isInit = 1; pWal->hdr.iVersion = WALINDEX_MAX_VERSION; walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum); memcpy((void *)&aHdr[1], (void *)&pWal->hdr, sizeof(WalIndexHdr)); sqlite3OsShmBarrier(pWal->pDbFd); memcpy((void *)&aHdr[0], (void *)&pWal->hdr, sizeof(WalIndexHdr)); } /* |
︙ | ︙ | |||
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 | u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */ int szFrame; /* Number of bytes in buffer aFrame[] */ u8 *aData; /* Pointer to data part of aFrame buffer */ int iFrame; /* Index of last frame read */ i64 iOffset; /* Next offset to read from log file */ int szPage; /* Page size according to the log */ u32 magic; /* Magic value read from WAL header */ /* Read in the WAL header. */ rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0); if( rc!=SQLITE_OK ){ goto recovery_error; } | > | 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 | u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */ int szFrame; /* Number of bytes in buffer aFrame[] */ u8 *aData; /* Pointer to data part of aFrame buffer */ int iFrame; /* Index of last frame read */ i64 iOffset; /* Next offset to read from log file */ int szPage; /* Page size according to the log */ u32 magic; /* Magic value read from WAL header */ u32 version; /* Magic value read from WAL header */ /* Read in the WAL header. */ rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0); if( rc!=SQLITE_OK ){ goto recovery_error; } |
︙ | ︙ | |||
1051 1052 1053 1054 1055 1056 1057 | goto finished; } pWal->hdr.bigEndCksum = (magic&0x00000001); pWal->szPage = szPage; pWal->nCkpt = sqlite3Get4byte(&aBuf[12]); memcpy(&pWal->hdr.aSalt, &aBuf[16], 8); walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, | | > > > > > > > > > > > > | 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 | goto finished; } pWal->hdr.bigEndCksum = (magic&0x00000001); pWal->szPage = szPage; pWal->nCkpt = sqlite3Get4byte(&aBuf[12]); memcpy(&pWal->hdr.aSalt, &aBuf[16], 8); walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum ); if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24]) || pWal->hdr.aFrameCksum[1]!=sqlite3Get4byte(&aBuf[28]) ){ goto finished; } version = sqlite3Get4byte(&aBuf[4]); if( version!=WAL_MAX_VERSION ){ rc = SQLITE_CANTOPEN_BKPT; goto finished; } /* Malloc a buffer to read frames into. */ szFrame = szPage + WAL_FRAME_HDRSIZE; aFrame = (u8 *)sqlite3_malloc(szFrame); if( !aFrame ){ rc = SQLITE_NOMEM; goto recovery_error; |
︙ | ︙ | |||
1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 | /* If the first page of the wal-index has been mapped, try to read the ** wal-index header immediately, without holding any lock. This usually ** works, but may fail if the wal-index header is corrupt or currently ** being modified by another user. */ badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1); /* If the first attempt failed, it might have been due to a race ** with a writer. So get a WRITE lock and try again. */ assert( badHdr==0 || pWal->writeLock==0 ); if( badHdr && SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){ pWal->writeLock = 1; | > > > | 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 | /* If the first page of the wal-index has been mapped, try to read the ** wal-index header immediately, without holding any lock. This usually ** works, but may fail if the wal-index header is corrupt or currently ** being modified by another user. */ badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1); if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){ rc = SQLITE_CANTOPEN_BKPT; } /* If the first attempt failed, it might have been due to a race ** with a writer. So get a WRITE lock and try again. */ assert( badHdr==0 || pWal->writeLock==0 ); if( badHdr && SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){ pWal->writeLock = 1; |
︙ | ︙ | |||
2261 2262 2263 2264 2265 2266 2267 | /* 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. */ iFrame = pWal->hdr.mxFrame; if( iFrame==0 ){ | | > > | > > > > > > | > | < | 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 | /* 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. */ iFrame = pWal->hdr.mxFrame; if( iFrame==0 ){ u8 aWalHdr[WAL_HDRSIZE]; /* Buffer to assemble wal-header in */ u32 aCksum[2]; /* Checksum for wal-header */ sqlite3Put4byte(&aWalHdr[0], (WAL_MAGIC | SQLITE_BIGENDIAN)); sqlite3Put4byte(&aWalHdr[4], WAL_MAX_VERSION); sqlite3Put4byte(&aWalHdr[8], szPage); sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt); memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8); walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum); sqlite3Put4byte(&aWalHdr[24], aCksum[0]); sqlite3Put4byte(&aWalHdr[28], aCksum[1]); pWal->szPage = szPage; pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN; pWal->hdr.aFrameCksum[0] = aCksum[0]; pWal->hdr.aFrameCksum[1] = aCksum[1]; rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0); WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok")); if( rc!=SQLITE_OK ){ return rc; } } assert( pWal->szPage==szPage ); /* 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 */ |
︙ | ︙ |
Changes to test/backup2.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # of the TCL interface - methods which are based on the # sqlite3_backup_XXX API. # # $Id: backup2.test,v 1.4 2009/04/07 14:14:23 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !trigger||!view { finish_test ; return } # Fill a database with test data. # do_test backup2-1 { db eval { | > > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # of the TCL interface - methods which are based on the # sqlite3_backup_XXX API. # # $Id: backup2.test,v 1.4 2009/04/07 14:14:23 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl do_not_use_codec ifcapable !trigger||!view { finish_test ; return } # Fill a database with test data. # do_test backup2-1 { db eval { |
︙ | ︙ |
Changes to test/date.test.
︙ | ︙ | |||
496 497 498 499 500 501 502 | # Test for issues reported by BareFeet (list.sql at tandb.com.au) # on mailing list on 2008-06-12. # # Put a floating point number in the database so that we can manipulate # raw bits using the hexio interface. # | > | | | | | | | | | | | | | | | | | | | | | | | | | > | 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 | # Test for issues reported by BareFeet (list.sql at tandb.com.au) # on mailing list on 2008-06-12. # # Put a floating point number in the database so that we can manipulate # raw bits using the hexio interface. # if {0==[sqlite3 -has-codec]} { do_test date-14.1 { execsql { PRAGMA auto_vacuum=OFF; PRAGMA page_size = 1024; CREATE TABLE t1(x); INSERT INTO t1 VALUES(1.1); } db close hexio_write test.db 2040 4142ba32bffffff9 sqlite3 db test.db db eval {SELECT * FROM t1} } {2454629.5} # Changing the least significant byte of the floating point value between # 00 and FF should always generate a time of either 23:59:59 or 00:00:00, # never 24:00:00 # for {set i 0} {$i<=255} {incr i} { db close hexio_write test.db 2047 [format %02x $i] sqlite3 db test.db do_test date-14.2.$i { set date [db one {SELECT datetime(x) FROM t1}] expr {$date eq "2008-06-12 00:00:00" || $date eq "2008-06-11 23:59:59"} } {1} } } finish_test |
Changes to test/pager1.test.
︙ | ︙ | |||
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 | # pager1-4.5.4: Restore the file-system. Corrupt the first record in the # journal. Check the transaction is not rolled back. # # pager1-4.5.5: Restore the file-system. Corrupt the second record in the # journal. Check that the first record in the transaction is # played back, but not the second. # faultsim_restore_and_reopen do_execsql_test pager1.4.5.3 { SELECT * FROM t1; SELECT * FROM t2; } {I II III IV} faultsim_restore_and_reopen hexio_write test.db-journal [expr 512+4+1024 - 202] 0123456789ABCDEF do_execsql_test pager1.4.5.4 { SELECT * FROM t1; SELECT * FROM t2; } {I II 1 2 III IV 3 4} faultsim_restore_and_reopen hexio_write test.db-journal [expr 512+4+1024+4+4+1024 - 202] 0123456789ABCDEF do_execsql_test pager1.4.5.5 { SELECT * FROM t1; SELECT * FROM t2; } {I II III IV 3 4} db close tv delete #------------------------------------------------------------------------- # The following tests deal with multi-file commits. # | > > > > > > > > > > > > | 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | # pager1-4.5.4: Restore the file-system. Corrupt the first record in the # journal. Check the transaction is not rolled back. # # pager1-4.5.5: Restore the file-system. Corrupt the second record in the # journal. Check that the first record in the transaction is # played back, but not the second. # # pager1-4.5.6: Restore the file-system. Try to open the database with a # readonly connection. This should fail, as a read-only # connection cannot roll back the database file. # faultsim_restore_and_reopen do_execsql_test pager1.4.5.3 { SELECT * FROM t1; SELECT * FROM t2; } {I II III IV} faultsim_restore_and_reopen hexio_write test.db-journal [expr 512+4+1024 - 202] 0123456789ABCDEF do_execsql_test pager1.4.5.4 { SELECT * FROM t1; SELECT * FROM t2; } {I II 1 2 III IV 3 4} faultsim_restore_and_reopen hexio_write test.db-journal [expr 512+4+1024+4+4+1024 - 202] 0123456789ABCDEF do_execsql_test pager1.4.5.5 { SELECT * FROM t1; SELECT * FROM t2; } {I II III IV 3 4} faultsim_restore_and_reopen db close sqlite3 db test.db -readonly 1 do_catchsql_test pager1.4.5.6 { SELECT * FROM t1; SELECT * FROM t2; } {1 {disk I/O error}} db close tv delete #------------------------------------------------------------------------- # The following tests deal with multi-file commits. # |
︙ | ︙ |
Changes to test/wal.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # "PRAGMA journal_mode=WAL" mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/malloc_common.tcl ifcapable !wal {finish_test ; return } proc reopen_db {} { catch { db close } file delete -force test.db test.db-wal test.db-wal-summary sqlite3_wal db test.db | > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # "PRAGMA journal_mode=WAL" mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/malloc_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } proc reopen_db {} { catch { db close } file delete -force test.db test.db-wal test.db-wal-summary sqlite3_wal db test.db |
︙ | ︙ | |||
37 38 39 40 41 42 43 | [lindex $args 0] eval { PRAGMA auto_vacuum = 0 } [lindex $args 0] eval { PRAGMA page_size = 1024 } [lindex $args 0] eval { PRAGMA journal_mode = wal } [lindex $args 0] eval { PRAGMA synchronous = normal } [lindex $args 0] function blob blob } | < < < < | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | [lindex $args 0] eval { PRAGMA auto_vacuum = 0 } [lindex $args 0] eval { PRAGMA page_size = 1024 } [lindex $args 0] eval { PRAGMA journal_mode = wal } [lindex $args 0] eval { PRAGMA synchronous = normal } [lindex $args 0] function blob blob } proc log_deleted {logfile} { return [expr [file exists $logfile]==0] } # # These are 'warm-body' tests used while developing the WAL code. They # serve to prove that a few really simple cases work: |
︙ | ︙ | |||
83 84 85 86 87 88 89 | do_test wal-1.1 { execsql COMMIT list [file exists test.db-journal] [file exists test.db-wal] } {0 1} do_test wal-1.2 { # There are now two pages in the log. file size test.db-wal | | | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | do_test wal-1.1 { execsql COMMIT list [file exists test.db-journal] [file exists test.db-wal] } {0 1} do_test wal-1.2 { # There are now two pages in the log. file size test.db-wal } [wal_file_size 2 1024] do_test wal-1.3 { execsql { SELECT * FROM sqlite_master } } {table t1 t1 2 {CREATE TABLE t1(a, b)}} do_test wal-1.4 { execsql { INSERT INTO t1 VALUES(1, 2) } |
︙ | ︙ | |||
362 363 364 365 366 367 368 | sqlite3_wal db test.db execsql { PRAGMA page_size = 1024; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); } list [file size test.db] [file size test.db-wal] | | | | 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | sqlite3_wal db test.db execsql { PRAGMA page_size = 1024; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); } list [file size test.db] [file size test.db-wal] } [list 1024 [wal_file_size 3 1024]] do_test wal-7.2 { execsql { PRAGMA wal_checkpoint } list [file size test.db] [file size test.db-wal] } [list 2048 [wal_file_size 3 1024]] # Execute some transactions in auto-vacuum mode to test database file # truncation. # do_test wal-8.1 { reopen_db catch { db close } |
︙ | ︙ | |||
681 682 683 684 685 686 687 | CREATE TABLE t1(x PRIMARY KEY); } list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044] } {1 3} do_test wal-11.2 { execsql { PRAGMA wal_checkpoint } list [expr [file size test.db]/1024] [file size test.db-wal] | | | | | | | | | | | 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 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 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 | CREATE TABLE t1(x PRIMARY KEY); } list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044] } {1 3} do_test wal-11.2 { execsql { PRAGMA wal_checkpoint } list [expr [file size test.db]/1024] [file size test.db-wal] } [list 3 [wal_file_size 3 1024]] do_test wal-11.3 { execsql { INSERT INTO t1 VALUES( blob(900) ) } list [expr [file size test.db]/1024] [file size test.db-wal] } [list 3 [wal_file_size 4 1024]] do_test wal-11.4 { execsql { BEGIN; INSERT INTO t1 SELECT blob(900) FROM t1; -- 2 INSERT INTO t1 SELECT blob(900) FROM t1; -- 4 INSERT INTO t1 SELECT blob(900) FROM t1; -- 8 INSERT INTO t1 SELECT blob(900) FROM t1; -- 16 } list [expr [file size test.db]/1024] [file size test.db-wal] } [list 3 [wal_file_size 32 1024]] do_test wal-11.5 { execsql { SELECT count(*) FROM t1; PRAGMA integrity_check; } } {16 ok} do_test wal-11.6 { execsql COMMIT list [expr [file size test.db]/1024] [file size test.db-wal] } [list 3 [wal_file_size 41 1024]] do_test wal-11.7 { execsql { SELECT count(*) FROM t1; PRAGMA integrity_check; } } {16 ok} do_test wal-11.8 { execsql { PRAGMA wal_checkpoint } list [expr [file size test.db]/1024] [file size test.db-wal] } [list 37 [wal_file_size 41 1024]] do_test wal-11.9 { db close list [expr [file size test.db]/1024] [log_deleted test.db-wal] } {37 1} sqlite3_wal db test.db do_test wal-11.10 { execsql { PRAGMA cache_size = 10; BEGIN; INSERT INTO t1 SELECT blob(900) FROM t1; -- 32 SELECT count(*) FROM t1; } list [expr [file size test.db]/1024] [file size test.db-wal] } [list 37 [wal_file_size 37 1024]] do_test wal-11.11 { execsql { SELECT count(*) FROM t1; ROLLBACK; SELECT count(*) FROM t1; } } {32 16} do_test wal-11.12 { list [expr [file size test.db]/1024] [file size test.db-wal] } [list 37 [wal_file_size 37 1024]] do_test wal-11.13 { execsql { INSERT INTO t1 VALUES( blob(900) ); SELECT count(*) FROM t1; PRAGMA integrity_check; } } {17 ok} do_test wal-11.14 { list [expr [file size test.db]/1024] [file size test.db-wal] } [list 37 [wal_file_size 37 1024]] #------------------------------------------------------------------------- # This block of tests, wal-12.*, tests the fix for a problem that # could occur if a log that is a prefix of an older log is written # into a reused log file. # reopen_db do_test wal-12.1 { execsql { PRAGMA page_size = 1024; CREATE TABLE t1(x, y); CREATE TABLE t2(x, y); INSERT INTO t1 VALUES('A', 1); } list [expr [file size test.db]/1024] [file size test.db-wal] } [list 1 [wal_file_size 5 1024]] do_test wal-12.2 { db close sqlite3 db test.db execsql { PRAGMA synchronous = normal; UPDATE t1 SET y = 0 WHERE x = 'A'; } |
︙ | ︙ | |||
861 862 863 864 865 866 867 | db function blob blob for {set i 0} {$i < 16} {incr i} { execsql { INSERT INTO t2 SELECT blob(400), blob(400) FROM t2 } } execsql { SELECT count(*) FROM t2 } } [expr int(pow(2, 16))] do_test wal-13.2.3 { | | | 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 | db function blob blob for {set i 0} {$i < 16} {incr i} { execsql { INSERT INTO t2 SELECT blob(400), blob(400) FROM t2 } } execsql { SELECT count(*) FROM t2 } } [expr int(pow(2, 16))] do_test wal-13.2.3 { expr [file size test.db-wal] > [wal_file_size 33000 1024] } 1 do_multiclient_test tn { incr tn 2 do_test wal-13.$tn.0 { sql1 { |
︙ | ︙ | |||
1063 1064 1065 1066 1067 1068 1069 | INSERT INTO t2 VALUES(1, randomblob(1000)); INSERT INTO t2 VALUES(2, randomblob(1000)); INSERT INTO t1 SELECT * FROM t2; } list [file size test.db] [file size test.db-wal] | | | | | | | | | | | | | | | | 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 | INSERT INTO t2 VALUES(1, randomblob(1000)); INSERT INTO t2 VALUES(2, randomblob(1000)); INSERT INTO t1 SELECT * FROM t2; } list [file size test.db] [file size test.db-wal] } [list [expr 1*1024] [wal_file_size 10 1024]] do_test wal-16.$tn.3 { list [file size test2.db] [file size test2.db-wal] } [list [expr 1*1024] [wal_file_size 16 1024]] do_test wal-16.$tn.4 [list eval $ckpt_cmd] $ckpt_res do_test wal-16.$tn.5 { list [file size test.db] [file size test.db-wal] } [list [expr ($ckpt_main ? 7 : 1)*1024] [wal_file_size 10 1024]] do_test wal-16.$tn.6 { list [file size test2.db] [file size test2.db-wal] } [list [expr ($ckpt_aux ? 7 : 1)*1024] [wal_file_size 16 1024]] catch { db close } } #------------------------------------------------------------------------- # The following tests - wal-17.* - attempt to verify that the correct # number of "padding" frames are appended to the log file when a transaction # is committed in synchronous=FULL mode. # # Do this by creating a database that uses 512 byte pages. Then writing # a transaction that modifies 171 pages. In synchronous=NORMAL mode, this # produces a log file of: # # 32 + (24+512)*171 = 90312 bytes. # # Slightly larger than 11*8192 = 90112 bytes. # # Run the test using various different sector-sizes. In each case, the # WAL code should write the 90300 bytes of log file containing the # transaction, then append as may frames as are required to extend the # log file so that no part of the next transaction will be written into # a disk-sector used by transaction just committed. # set old_pending_byte [sqlite3_test_control_pending_byte 0x10000000] catch { db close } foreach {tn sectorsize logsize} " 1 128 [wal_file_size 172 512] 2 256 [wal_file_size 172 512] 3 512 [wal_file_size 172 512] 4 1024 [wal_file_size 172 512] 5 2048 [wal_file_size 172 512] 6 4096 [wal_file_size 176 512] 7 8192 [wal_file_size 184 512] " { file delete -force test.db test.db-wal test.db-journal sqlite3_simulate_device -sectorsize $sectorsize sqlite3 db test.db -vfs devsym do_test wal-17.$tn.1 { execsql { PRAGMA auto_vacuum = 0; |
︙ | ︙ | |||
1177 1178 1179 1180 1181 1182 1183 | INSERT INTO t1 VALUES(5, 6); -- frames 5 and 6 } file copy -force test.db testX.db file copy -force test.db-wal testX.db-wal db close list [file size testX.db] [file size testX.db-wal] | | | 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 | INSERT INTO t1 VALUES(5, 6); -- frames 5 and 6 } file copy -force test.db testX.db file copy -force test.db-wal testX.db-wal db close list [file size testX.db] [file size testX.db-wal] } [list [expr 3*1024] [wal_file_size 6 1024]] unset -nocomplain nFrame result foreach {nFrame result} { 0 {0 0} 1 {0 0} 2 {0 0 1 2} 3 {0 0 1 2} |
︙ | ︙ | |||
1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 | # set walhdr [binary format IIIIII 931071618 3007000 $pgsz 1234 22 23] set framebody [randomblob $pgsz] set framehdr [binary format IIII $pg 5 22 23] set c1 0 set c2 0 logcksum c1 c2 $walhdr logcksum c1 c2 [string range $framehdr 0 7] logcksum c1 c2 $framebody set framehdr [binary format IIIIII $pg 5 22 23 $c1 $c2] set fd [open test.db-wal w] fconfigure $fd -encoding binary -translation binary puts -nonewline $fd $walhdr puts -nonewline $fd $framehdr puts -nonewline $fd $framebody close $fd file size test.db-wal | > > | | 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 | # set walhdr [binary format IIIIII 931071618 3007000 $pgsz 1234 22 23] set framebody [randomblob $pgsz] set framehdr [binary format IIII $pg 5 22 23] set c1 0 set c2 0 logcksum c1 c2 $walhdr append walhdr [binary format II $c1 $c2] logcksum c1 c2 [string range $framehdr 0 7] logcksum c1 c2 $framebody set framehdr [binary format IIIIII $pg 5 22 23 $c1 $c2] set fd [open test.db-wal w] fconfigure $fd -encoding binary -translation binary puts -nonewline $fd $walhdr puts -nonewline $fd $framehdr puts -nonewline $fd $framebody close $fd file size test.db-wal } [wal_file_size 1 $pgsz] do_test wal-18.2.$tn.$pg.5 { sqlite3 db test.db set rc [catch { db one {PRAGMA integrity_check} } msg] expr { $rc!=0 || $msg!="ok" } } $works |
︙ | ︙ | |||
1410 1411 1412 1413 1414 1415 1416 | sqlite3 db test.db execsql { SELECT count(*) FROM t1 } } {16384} integrity_check wal-20.5 catch { db2 close } catch { db close } | < < > | 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 | sqlite3 db test.db execsql { SELECT count(*) FROM t1 } } {16384} integrity_check wal-20.5 catch { db2 close } catch { db close } do_test wal-21.1 { faultsim_delete_and_reopen execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); INSERT INTO t1 VALUES(7, 8); |
︙ | ︙ |
Changes to test/wal2.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 | # focus of this file is testing the operation of the library in # "PRAGMA journal_mode=WAL" mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl ifcapable !wal {finish_test ; return } proc set_tvfs_hdr {file args} { # Set $nHdr to the number of bytes in the wal-index header: | > > > | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # focus of this file is testing the operation of the library in # "PRAGMA journal_mode=WAL" mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/malloc_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } proc set_tvfs_hdr {file args} { # Set $nHdr to the number of bytes in the wal-index header: set nHdr 48 set nInt [expr {$nHdr/4}] if {[llength $args]>2} { error {wrong # args: should be "set_tvfs_hdr fileName ?val1? ?val2?"} } set blob [tvfs shm $file] |
︙ | ︙ | |||
876 877 878 879 880 881 882 | foreach {tn hdr1 hdr2 res} [list \ 3 $wih(1) $wih(1) {Barton Deakin} \ 4 $wih(1) $wih(2) {Barton Deakin Watson} \ 5 $wih(2) $wih(1) {Barton Deakin Watson} \ 6 $wih(2) $wih(2) {Barton Deakin Watson} \ 7 $wih(1) $wih(1) {Barton Deakin} \ | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 | foreach {tn hdr1 hdr2 res} [list \ 3 $wih(1) $wih(1) {Barton Deakin} \ 4 $wih(1) $wih(2) {Barton Deakin Watson} \ 5 $wih(2) $wih(1) {Barton Deakin Watson} \ 6 $wih(2) $wih(2) {Barton Deakin Watson} \ 7 $wih(1) $wih(1) {Barton Deakin} \ 8 {0 0 0 0 0 0 0 0 0 0 0 0} {0 0 0 0 0 0 0 0 0 0 0 0} {Barton Deakin Watson} ] { do_test wal2-9.$tn { set_tvfs_hdr $::filename $hdr1 $hdr2 execsql { SELECT * FROM x } db2 } $res } db2 close db close #------------------------------------------------------------------------- # This block of tests - wal2-10.* - focus on the libraries response to # new versions of the wal or wal-index formats. # # wal2-10.1.*: Test that the library refuses to "recover" a new WAL # format. # # wal2-10.2.*: Test that the library refuses to read or write a database # if the wal-index version is newer than it understands. # # At time of writing, the only versions of the wal and wal-index formats # that exist are versions 3007000 (corresponding to SQLite version 3.7.0, # the first version of SQLite to feature wal mode). # do_test wal2-10.1.1 { faultsim_delete_and_reopen execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); PRAGMA wal_checkpoint; INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); } faultsim_save_and_close } {} do_test wal2-10.1.2 { faultsim_restore_and_reopen execsql { SELECT * FROM t1 } } {1 2 3 4} do_test wal2-10.1.3 { faultsim_restore_and_reopen set hdr [wal_set_walhdr test.db-wal] lindex $hdr 1 } {3007000} do_test wal2-10.1.4 { lset hdr 1 3007001 wal_set_walhdr test.db-wal $hdr catchsql { SELECT * FROM t1 } } {1 {unable to open database file}} testvfs tvfs -default 1 do_test wal2-10.2.1 { faultsim_restore_and_reopen execsql { SELECT * FROM t1 } } {1 2 3 4} do_test wal2-10.2.2 { set hdr [set_tvfs_hdr $::filename] lindex $hdr 0 } {3007000} breakpoint do_test wal2-10.2.3 { lset hdr 0 3007001 wal_fix_walindex_cksum hdr set_tvfs_hdr $::filename $hdr catchsql { SELECT * FROM t1 } } {1 {unable to open database file}} finish_test |
Changes to test/wal_common.tcl.
︙ | ︙ | |||
10 11 12 13 14 15 16 | #*********************************************************************** # # This file contains common code used by many different malloc tests # within the test suite. # proc wal_file_size {nFrame pgsz} { | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | #*********************************************************************** # # This file contains common code used by many different malloc tests # within the test suite. # proc wal_file_size {nFrame pgsz} { expr {32 + ($pgsz+24)*$nFrame} } proc wal_frame_count {zFile pgsz} { set f [file size $zFile] expr {($f - 32) / ($pgsz+24)} } proc wal_cksum_intlist {ckv1 ckv2 intlist} { upvar $ckv1 c1 upvar $ckv2 c2 foreach {v1 v2} $intlist { set c1 [expr {($c1 + $v1 + $c2)&0xFFFFFFFF}] set c2 [expr {($c2 + $v2 + $c1)&0xFFFFFFFF}] } } # This proc calculates checksums in the same way as those used by SQLite # in WAL files. If the $endian argument is "big", then checksums are # calculated by interpreting data as an array of big-endian integers. If # it is "little", data is interpreted as an array of little-endian integers. # proc wal_cksum {endian ckv1 ckv2 blob} { upvar $ckv1 c1 upvar $ckv2 c2 if {$endian!="big" && $endian!="little"} { return -error "Bad value \"$endian\" - must be \"big\" or \"little\"" } set scanpattern I* if {$endian == "little"} { set scanpattern i* } binary scan $blob $scanpattern values wal_cksum_intlist c1 c2 $values } proc wal_set_walhdr {filename {intlist {}}} { if {[llength $intlist]==6} { set blob [binary format I6 $intlist] set endian little if {[lindex $intlist 0] & 0x00000001} { set endian big } set c1 0 set c2 0 wal_cksum $endian c1 c2 $blob append blob [binary format II $c1 $c2] set fd [open $filename r+] fconfigure $fd -translation binary fconfigure $fd -encoding binary seek $fd 0 puts -nonewline $fd $blob close $fd } set fd [open $filename] fconfigure $fd -translation binary fconfigure $fd -encoding binary set blob [read $fd 24] binary scan $blob I6 ints set ints } proc wal_fix_walindex_cksum {hdrvar} { upvar $hdrvar hdr set c1 0 set c2 0 wal_cksum_intlist c1 c2 [lrange $hdr 0 9] lset hdr 10 $c1 lset hdr 11 $c2 } |
Changes to test/walbak.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 | # This file implements regression tests for SQLite library. The # focus of this file is testing the operation of the library in # "PRAGMA journal_mode=WAL" mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal {finish_test ; return } | > > > < < < | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # This file implements regression tests for SQLite library. The # focus of this file is testing the operation of the library in # "PRAGMA journal_mode=WAL" mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/wal_common.tcl do_not_use_codec ifcapable !wal {finish_test ; return } # Test organization: # # walback-1.*: Simple tests. # walback-2.*: Test backups when the source db is modified mid-backup. # |
︙ | ︙ | |||
65 66 67 68 69 70 71 | execsql { VACUUM; PRAGMA main.journal_mode; } } {wal} do_test walbak-1.5 { list [file size test.db] [file size test.db-wal] | | | | | | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | execsql { VACUUM; PRAGMA main.journal_mode; } } {wal} do_test walbak-1.5 { list [file size test.db] [file size test.db-wal] } [list 1024 [wal_file_size 6 1024]] do_test walbak-1.6 { execsql { PRAGMA wal_checkpoint } list [file size test.db] [file size test.db-wal] } [list [expr 3*1024] [wal_file_size 6 1024]] do_test walbak-1.7 { execsql { CREATE TABLE t2(a, b); INSERT INTO t2 SELECT * FROM t1; DROP TABLE t1; } list [file size test.db] [file size test.db-wal] } [list [expr 3*1024] [wal_file_size 6 1024]] do_test walbak-1.8 { execsql { VACUUM } list [file size test.db] [file size test.db-wal] } [list [expr 3*1024] [wal_file_size 8 1024]] do_test walbak-1.9 { execsql { PRAGMA wal_checkpoint } list [file size test.db] [file size test.db-wal] } [list [expr 2*1024] [wal_file_size 8 1024]] #------------------------------------------------------------------------- # Backups when the source db is modified mid-backup. # proc sig {{db db}} { $db eval { PRAGMA integrity_check; |
︙ | ︙ |
Changes to test/walcksum.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 | # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl ifcapable !wal {finish_test ; return } | > < < < < < < < < < < < < < < < < < < < < < < < < < < | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } # Read and return the contents of file $filename. Treat the content as # binary data. # proc readfile {filename} { set fd [open $filename] fconfigure $fd -encoding binary fconfigure $fd -translation binary |
︙ | ︙ | |||
68 69 70 71 72 73 74 | binary scan [string range $data $offset [expr $offset+7]] II expect1 expect2 set expect1 [expr $expect1&0xFFFFFFFF] set expect2 [expr $expect2&0xFFFFFFFF] expr {$c1==$expect1 && $c2==$expect2} } | < > > > > > > > > > > > > > > > > > | | | | | > > > > > > > > > > > > | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | binary scan [string range $data $offset [expr $offset+7]] II expect1 expect2 set expect1 [expr $expect1&0xFFFFFFFF] set expect2 [expr $expect2&0xFFFFFFFF] expr {$c1==$expect1 && $c2==$expect2} } # File $filename must be a WAL file on disk. Compute the checksum for frame # $iFrame in the file by interpreting data as $endian-endian integers # ($endian must be either "big" or "little"). Then write the computed # checksum into the file. # proc log_checksum_write {filename iFrame endian} { set data [readfile $filename] foreach {offset c1 c2} [log_checksum_calc $data $iFrame $endian] {} set bin [binary format II $c1 $c2] set fd [open $filename r+] fconfigure $fd -encoding binary fconfigure $fd -translation binary seek $fd $offset puts -nonewline $fd $bin close $fd } # Calculate and return the checksum for a particular frame in a WAL. # # Arguments are: # # $data Blob containing the entire contents of a WAL. # # $iFrame Frame number within the $data WAL. Frames are numbered # starting at 1. # # $endian One of "big" or "little". # # Returns a list of three elements, as follows: # # * The byte offset of the checksum belonging to frame $iFrame in the WAL. # * The first integer in the calculated version of the checksum. # * The second integer in the calculated version of the checksum. # proc log_checksum_calc {data iFrame endian} { binary scan [string range $data 8 11] I pgsz if {$iFrame > 1} { set n [wal_file_size [expr $iFrame-2] $pgsz] binary scan [string range $data [expr $n+16] [expr $n+23]] II c1 c2 } else { set c1 0 set c2 0 wal_cksum $endian c1 c2 [string range $data 0 23] } set n [wal_file_size [expr $iFrame-1] $pgsz] wal_cksum $endian c1 c2 [string range $data $n [expr $n+7]] wal_cksum $endian c1 c2 [string range $data [expr $n+24] [expr $n+24+$pgsz-1]] list [expr $n+16] $c1 $c2 } # # File $filename must be a WAL file on disk. Set the 'magic' field of the # WAL header to indicate that checksums are $endian-endian ($endian must be # either "big" or "little"). # # Also update the wal header checksum (since the wal header contents may # have changed). # proc log_checksum_writemagic {filename endian} { set val [expr {0x377f0682 | ($endian == "big" ? 1 : 0)}] set bin [binary format I $val] set fd [open $filename r+] fconfigure $fd -encoding binary fconfigure $fd -translation binary puts -nonewline $fd $bin seek $fd 0 set blob [read $fd 24] set c1 0 set c2 0 wal_cksum $endian c1 c2 $blob seek $fd 24 puts -nonewline $fd [binary format II $c1 $c2] close $fd } #------------------------------------------------------------------------- # Test cases walcksum-1.* attempt to verify the following: # # * That both native and non-native order checksum log files can |
︙ | ︙ | |||
170 171 172 173 174 175 176 | } file copy -force test.db test2.db file copy -force test.db-wal test2.db-wal db close list [file size test2.db] [file size test2.db-wal] | | | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | } file copy -force test.db test2.db file copy -force test.db-wal test2.db-wal db close list [file size test2.db] [file size test2.db-wal] } [list [expr 1024*3] [wal_file_size 6 1024]] # Verify that the checksums are valid for all frames and that they # are calculated by interpreting data in native byte-order. # for {set f 1} {$f <= 6} {incr f} { do_test walcksum-1.$endian.2.$f { log_checksum_verify test2.db-wal $f $native |
︙ | ︙ | |||
207 208 209 210 211 212 213 | # do_test walcksum-1.$endian.5.0 { execsql { PRAGMA synchronous = NORMAL; INSERT INTO t1 VALUES(34, 'thirtyfour'); } list [file size test.db] [file size test.db-wal] | | | 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | # do_test walcksum-1.$endian.5.0 { execsql { PRAGMA synchronous = NORMAL; INSERT INTO t1 VALUES(34, 'thirtyfour'); } list [file size test.db] [file size test.db-wal] } [list [expr 1024*3] [wal_file_size 8 1024]] for {set f 1} {$f <= 8} {incr f} { do_test walcksum-1.$endian.5.$f { log_checksum_verify test.db-wal $f $endian } {1} } # Now connect a second connection to the database. Check that this one |
︙ | ︙ | |||
231 232 233 234 235 236 237 | } {ok 1 2 3 5 8 13 21 34} do_test walcksum-1.$endian.7.0 { execsql { PRAGMA synchronous = NORMAL; INSERT INTO t1 VALUES(55, 'fiftyfive'); } db2 list [file size test.db] [file size test.db-wal] | | | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | } {ok 1 2 3 5 8 13 21 34} do_test walcksum-1.$endian.7.0 { execsql { PRAGMA synchronous = NORMAL; INSERT INTO t1 VALUES(55, 'fiftyfive'); } db2 list [file size test.db] [file size test.db-wal] } [list [expr 1024*3] [wal_file_size 10 1024]] for {set f 1} {$f <= 10} {incr f} { do_test walcksum-1.$endian.7.$f { log_checksum_verify test.db-wal $f $endian } {1} } # Now that both the recoverer and non-recoverer have added frames to the |
︙ | ︙ | |||
347 348 349 350 351 352 353 | INSERT INTO t1 VALUES(1, randomblob(300)); INSERT INTO t1 VALUES(2, randomblob(300)); PRAGMA journal_mode = WAL; INSERT INTO t1 VALUES(3, randomblob(300)); } file size test.db-wal | | | | 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 | INSERT INTO t1 VALUES(1, randomblob(300)); INSERT INTO t1 VALUES(2, randomblob(300)); PRAGMA journal_mode = WAL; INSERT INTO t1 VALUES(3, randomblob(300)); } file size test.db-wal } [wal_file_size 1 1024] do_test walcksum-3.2 { file copy -force test.db-wal test2.db-wal file copy -force test.db test2.db sqlite3 db2 test2.db execsql { SELECT a FROM t1 } db2 } {1 2 3} db2 close file copy -force test.db test2.db foreach incr {1 2 3 20 40 60 80 100 120 140 160 180 200 220 240 253 254 255} { do_test walcksum-3.3.$incr { set FAIL 0 for {set iOff 0} {$iOff < [wal_file_size 1 1024]} {incr iOff} { file copy -force test.db-wal test2.db-wal set fd [open test2.db-wal r+] fconfigure $fd -encoding binary fconfigure $fd -translation binary seek $fd $iOff |
︙ | ︙ |
Changes to test/walcrash2.test.
︙ | ︙ | |||
10 11 12 13 14 15 16 17 18 | #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl ifcapable !wal {finish_test ; return } | > < < < | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/lock_common.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } #------------------------------------------------------------------------- # This test case demonstrates a flaw in the wal-index manipulation that # existed at one point: If a process crashes mid-transaction, it may have # already added some entries to one of the hash-tables in the wal-index. # If the transaction were to be explicitly rolled back at this point, the # hash-table entries would be removed as part of the rollback. However, |
︙ | ︙ |
Changes to test/walhook.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 | # More specifically, this file contains regression tests for the # sqlite3_wal_hook() mechanism, including the sqlite3_wal_autocheckpoint() # and "PRAGMA wal_autocheckpoint" convenience interfaces. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !wal {finish_test ; return } | > < < < < | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # More specifically, this file contains regression tests for the # sqlite3_wal_hook() mechanism, including the sqlite3_wal_autocheckpoint() # and "PRAGMA wal_autocheckpoint" convenience interfaces. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/wal_common.tcl ifcapable !wal {finish_test ; return } set ::wal_hook [list] proc wal_hook {zDb nEntry} { lappend ::wal_hook $zDb $nEntry return 0 } db wal_hook wal_hook |
︙ | ︙ | |||
100 101 102 103 104 105 106 | 7 "INSERT INTO t4 VALUES(3, 'three')" 6 9 8 "INSERT INTO t4 VALUES(4, 'four')" 8 11 9 "INSERT INTO t4 VALUES(5, 'five')" 8 11 } { do_test walhook-2.$tn { execsql $sql list [file size test.db] [file size test.db-wal] | | | 97 98 99 100 101 102 103 104 105 106 107 108 109 | 7 "INSERT INTO t4 VALUES(3, 'three')" 6 9 8 "INSERT INTO t4 VALUES(4, 'four')" 8 11 9 "INSERT INTO t4 VALUES(5, 'five')" 8 11 } { do_test walhook-2.$tn { execsql $sql list [file size test.db] [file size test.db-wal] } [list [expr $dbpages*1024] [wal_file_size $logpages 1024]] } catch { db2 close } catch { db close } finish_test |