Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Handle the race condition that may occur if another process connects and then checkpoints and truncates the wal file while a readonly-shm client is building its heap-memory wal-index. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | readonly-wal-recovery |
Files: | files | file ages | folders |
SHA3-256: |
5a6703fc3f2174b3e9a624c7272ae013 |
User & Date: | dan 2017-11-07 21:15:07.949 |
Context
2017-11-07
| ||
21:25 | Update an assert in wal.c. (check-in: 94527b897b user: dan tags: readonly-wal-recovery) | |
21:15 | Handle the race condition that may occur if another process connects and then checkpoints and truncates the wal file while a readonly-shm client is building its heap-memory wal-index. (check-in: 5a6703fc3f user: dan tags: readonly-wal-recovery) | |
15:43 | On unix, if the *-shm file cannot be opened for read/write access, open it read-only and proceed as if the readonly_shm=1 URI option were specified. (check-in: ba718754fa user: dan tags: readonly-wal-recovery) | |
Changes
Changes to src/wal.c.
︙ | ︙ | |||
2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 | testcase( pWal->szPage>=65536 ); } /* The header was successfully read. Return zero. */ return 0; } /* ** Read the wal-index header from the wal-index and into pWal->hdr. ** If the wal-header appears to be corrupt, try to reconstruct the ** wal-index from the WAL before returning. ** ** Set *pChanged to 1 if the wal-index header value in pWal->hdr is ** changed by this operation. If pWal->hdr is unchanged, set *pChanged | > > > > > > | 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 | testcase( pWal->szPage>=65536 ); } /* The header was successfully read. Return zero. */ return 0; } /* ** This is the value that walTryBeginRead returns when it needs to ** be retried. */ #define WAL_RETRY (-1) /* ** Read the wal-index header from the wal-index and into pWal->hdr. ** If the wal-header appears to be corrupt, try to reconstruct the ** wal-index from the WAL before returning. ** ** Set *pChanged to 1 if the wal-index header value in pWal->hdr is ** changed by this operation. If pWal->hdr is unchanged, set *pChanged |
︙ | ︙ | |||
2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 | */ if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){ rc = SQLITE_CANTOPEN_BKPT; } if( pWal->bUnlocked ){ if( rc!=SQLITE_OK ){ walIndexClose(pWal, 0); } pWal->exclusiveMode = WAL_NORMAL_MODE; } return rc; } | > > > < < < < < < | 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 | */ if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){ rc = SQLITE_CANTOPEN_BKPT; } if( pWal->bUnlocked ){ if( rc!=SQLITE_OK ){ walIndexClose(pWal, 0); pWal->bUnlocked = 0; assert( pWal->nWiData>0 && pWal->apWiData[0]==0 ); if( rc==SQLITE_IOERR_SHORT_READ ) rc = WAL_RETRY; } pWal->exclusiveMode = WAL_NORMAL_MODE; } return rc; } /* ** Open an "unlocked" transaction. An unlocked transaction is a read ** transaction used by a read-only client in cases where the *-shm ** file cannot be mapped and its contents cannot be trusted. It is ** assumed that the *-wal file has been read and that a wal-index ** constructed in heap memory is currently available in Wal.apWiData[]. ** |
︙ | ︙ |
Changes to test/walro2.test.
︙ | ︙ | |||
331 332 333 334 335 336 337 | } {hello world ! world hello} do_test 5.3 { code1 { db close } code1 { tvfs delete } } {} | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | } {hello world ! world hello} do_test 5.3 { code1 { db close } code1 { tvfs delete } } {} #----------------------------------------------------------------------- # # catch { code1 { db close } } catch { code2 { db2 close } } catch { code3 { db3 close } } do_test 6.1 { code1 { forcedelete test.db } code1 { sqlite3 db test.db } sql1 { PRAGMA journal_mode = wal; CREATE TABLE t1(x); INSERT INTO t1 VALUES('hello'); INSERT INTO t1 VALUES('world'); INSERT INTO t1 VALUES('!'); INSERT INTO t1 VALUES('world'); INSERT INTO t1 VALUES('hello'); } forcecopy test.db test.db2 forcecopy test.db-wal test.db2-wal forcecopy test.db-shm test.db2-shm code1 { db close } } {} do_test 6.2 { code1 { set ::nRem 5 proc handle_read {op args} { if {$op=="xRead" && [file tail [lindex $args 0]]=="test.db2-wal"} { incr ::nRem -1 if {$::nRem==0} { code2 { sqlite3 db2 test.db2 } sql2 { PRAGMA wal_checkpoint = truncate } } } return "SQLITE_OK" } testvfs tvfs -fullshm 1 tvfs filter xRead tvfs script handle_read sqlite3 db file:test.db2?readonly_shm=1&vfs=tvfs db eval { SELECT * FROM t1 } } } {hello world ! world hello} do_test 6.3 { code1 { db close } code1 { tvfs delete } } {} } finish_test |