Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add further test cases for the logic in sqlite3WalBeginReadTransaction(). |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
a49713db39d0d6940b368206d4e669aa |
User & Date: | dan 2010-06-05 19:18:59.000 |
Context
2010-06-07
| ||
06:11 | Add a couple of extra coverage tests for wal.c. (check-in: cfe60254df user: dan tags: trunk) | |
2010-06-05
| ||
19:18 | Add further test cases for the logic in sqlite3WalBeginReadTransaction(). (check-in: a49713db39 user: dan tags: trunk) | |
18:34 | Clarify the purpose of a test for a race-condition in sqlite3WalBeginReadTransaction(). (check-in: c041c6a978 user: dan tags: trunk) | |
Changes
Changes to src/wal.c.
︙ | ︙ | |||
1743 1744 1745 1746 1747 1748 1749 | if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){ /* The WAL has been completely backfilled (or it is empty). ** and can be safely ignored. */ rc = walLockShared(pWal, WAL_READ_LOCK(0)); sqlite3OsShmBarrier(pWal->pDbFd); if( rc==SQLITE_OK ){ | | | 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 | if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){ /* The WAL has been completely backfilled (or it is empty). ** and can be safely ignored. */ rc = walLockShared(pWal, WAL_READ_LOCK(0)); sqlite3OsShmBarrier(pWal->pDbFd); if( rc==SQLITE_OK ){ if( memcmp((void *)pHdr, &pWal->hdr, sizeof(WalIndexHdr)) ){ /* It is not safe to allow the reader to continue here if frames ** may have been appended to the log before READ_LOCK(0) was obtained. ** When holding READ_LOCK(0), the reader ignores the entire log file, ** which implies that the database file contains a trustworthy ** snapshoT. Since holding READ_LOCK(0) prevents a checkpoint from ** happening, this is usually correct. ** |
︙ | ︙ | |||
1828 1829 1830 1831 1832 1833 1834 | ** that the log file may have been wrapped by a writer, or that frames ** that occur later in the log than pWal->hdr.mxFrame may have been ** copied into the database by a checkpointer. If either of these things ** happened, then reading the database with the current value of ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry ** instead. ** | | | | | | 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 | ** that the log file may have been wrapped by a writer, or that frames ** that occur later in the log than pWal->hdr.mxFrame may have been ** copied into the database by a checkpointer. If either of these things ** happened, then reading the database with the current value of ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry ** instead. ** ** This does not guarantee that the copy of the wal-index header is up to ** date before proceeding. That would not be possible without somehow ** blocking writers. It only guarantees that a dangerous checkpoint or ** log-wrap (either of which would require an exclusive lock on ** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid. */ sqlite3OsShmBarrier(pWal->pDbFd); if( pInfo->aReadMark[mxI]!=mxReadMark || memcmp((void *)pHdr, &pWal->hdr, sizeof(WalIndexHdr)) ){ walUnlockShared(pWal, WAL_READ_LOCK(mxI)); return WAL_RETRY; }else{ pWal->readLock = mxI; } } |
︙ | ︙ |
Changes to test/wal3.test.
︙ | ︙ | |||
416 417 418 419 420 421 422 | db close T delete #------------------------------------------------------------------------- # When opening a read-transaction on a database, if the entire log has # already been copied to the database file, the reader grabs a special | | | | 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 | db close T delete #------------------------------------------------------------------------- # When opening a read-transaction on a database, if the entire log has # already been copied to the database file, the reader grabs a special # kind of read lock (on aReadMark[0]). This set of test cases tests the # outcome of the following: # # + The reader discovering that between the time when it determined # that the log had been completely backfilled and the lock is obtained # that a writer has written to the log. In this case the reader should # acquire a different read-lock (not aReadMark[0]) and read the new # snapshot. # |
︙ | ︙ | |||
559 560 561 562 563 564 565 | expr {$sz2 == $sz1} } {1} db2 close db close T delete | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 | expr {$sz2 == $sz1} } {1} db2 close db close T delete #------------------------------------------------------------------------- # When opening a read-transaction on a database, if the entire log has # not yet been copied to the database file, the reader grabs a read # lock on aReadMark[x], where x>0. The following test cases experiment # with the outcome of the following: # # + The reader discovering that between the time when it read the # wal-index header and the lock was obtained that a writer has # written to the log. In this case the reader should re-read the # wal-index header and lock a snapshot corresponding to the new # header. # # + The value in the aReadMark[x] slot has been modified since it was # read. # catch {db close} testvfs T -default 1 do_test wal3-7.1.1 { file delete -force test.db test.db-journal test.db wal sqlite3 db test.db execsql { PRAGMA journal_mode = WAL; CREATE TABLE blue(red PRIMARY KEY, green); } } {wal} T script method_callback T filter xOpen proc method_callback {method args} { if {$method == "xOpen"} { return "reader" } } do_test wal3-7.1.2 { sqlite3 db2 test.db execsql { SELECT * FROM blue } db2 } {} T filter xShmLock set ::locks [list] proc method_callback {method file handle spec} { if {$handle != "reader" } { return } if {$method == "xShmLock"} { catch { execsql { INSERT INTO blue VALUES(1, 2) } } catch { execsql { INSERT INTO blue VALUES(3, 4) } } } lappend ::locks $spec } do_test wal3-7.1.3 { execsql { SELECT * FROM blue } db2 } {1 2 3 4} do_test wal3-7.1.4 { set ::locks } {{4 1 lock shared} {4 1 unlock shared} {5 1 lock shared} {5 1 unlock shared}} set ::locks [list] proc method_callback {method file handle spec} { if {$handle != "reader" } { return } if {$method == "xShmLock"} { catch { execsql { INSERT INTO blue VALUES(5, 6) } } } lappend ::locks $spec } do_test wal3-7.2.1 { execsql { SELECT * FROM blue } db2 } {1 2 3 4 5 6} do_test wal3-7.2.2 { set ::locks } {{5 1 lock shared} {5 1 unlock shared} {4 1 lock shared} {4 1 unlock shared}} db close db2 close T delete finish_test |