Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a bug whereby an old snapshot could be checkpointed (and subsequent transactions discarded) if the last connection to disconnect from a WAL database happended to be holding an out-of-date wal-index header. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
d0c0034b0baa83046c1d6b94c886f703 |
User & Date: | dan 2010-05-06 17:28:09.000 |
Context
2010-05-06
| ||
18:04 | Only pass -1 as the size parameter to xShmGet when the caller does not care what size mapping is returned. Only call xShmSize when the underlying allocation (not the mapping) should be resized. (check-in: 637f51ddf9 user: dan tags: trunk) | |
17:28 | Fix a bug whereby an old snapshot could be checkpointed (and subsequent transactions discarded) if the last connection to disconnect from a WAL database happended to be holding an out-of-date wal-index header. (check-in: d0c0034b0b user: dan tags: trunk) | |
16:06 | After throwing an error to say that one cannot change into WAL mode within a tranactions, do not then go and change into WAL mode. (check-in: 56a17dae91 user: drh tags: trunk) | |
Changes
Changes to src/wal.c.
︙ | ︙ | |||
365 366 367 368 369 370 371 372 373 374 375 376 377 378 | static int walIndexEntry(u32 iFrame){ return ( (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED)/sizeof(u32) + (((iFrame-1)>>8)<<6) /* Indexes that occur before iFrame */ + iFrame-1 /* Db page numbers that occur before iFrame */ ); } /* ** Release our reference to the wal-index memory map, if we are holding ** it. */ static void walIndexUnmap(Wal *pWal){ if( pWal->pWiData ){ | > > > > > > > > > > > > > | 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 | static int walIndexEntry(u32 iFrame){ return ( (WALINDEX_LOCK_OFFSET+WALINDEX_LOCK_RESERVED)/sizeof(u32) + (((iFrame-1)>>8)<<6) /* Indexes that occur before iFrame */ + iFrame-1 /* Db page numbers that occur before iFrame */ ); } /* ** Return the minimum mapping size in bytes that can be used to read the ** wal-index up to and including frame iFrame. If iFrame is the last frame ** in a block of 256 frames, the returned byte-count includes the space ** required by the 256-byte index block. */ static int walMappingSize(u32 iFrame){ return ( WALINDEX_LOCK_OFFSET + WALINDEX_LOCK_RESERVED + iFrame*sizeof(u32) + (iFrame>>8)*256 ); } /* ** Release our reference to the wal-index memory map, if we are holding ** it. */ static void walIndexUnmap(Wal *pWal){ if( pWal->pWiData ){ |
︙ | ︙ | |||
831 832 833 834 835 836 837 | ** the database. In this case checkpoint the database and unlink both ** the wal and wal-index files. ** ** The EXCLUSIVE lock is not released before returning. */ rc = sqlite3OsLock(pFd, SQLITE_LOCK_EXCLUSIVE); if( rc==SQLITE_OK ){ | | | 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 | ** the database. In this case checkpoint the database and unlink both ** the wal and wal-index files. ** ** The EXCLUSIVE lock is not released before returning. */ rc = sqlite3OsLock(pFd, SQLITE_LOCK_EXCLUSIVE); if( rc==SQLITE_OK ){ rc = sqlite3WalCheckpoint(pWal, pFd, sync_flags, nBuf, zBuf, 0, 0); if( rc==SQLITE_OK ){ isDelete = 1; } walIndexUnmap(pWal); } walIndexClose(pWal, isDelete); |
︙ | ︙ |
Changes to test/wal.test.
︙ | ︙ | |||
272 273 274 275 276 277 278 279 280 281 282 283 284 285 | execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2 } {1 2} do_test wal-4.5.7 { execsql { PRAGMA integrity_check } db2 } {ok} db2 close reopen_db do_test wal-5.1 { execsql { CREATE TEMP TABLE t2(a, b); INSERT INTO t2 VALUES(1, 2); } | > > > > > > > > > > > > > > | 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 | execsql { SELECT count(*) FROM t2 ; SELECT count(*) FROM t1 } db2 } {1 2} do_test wal-4.5.7 { execsql { PRAGMA integrity_check } db2 } {ok} db2 close do_test wal-4.6.1 { execsql { DELETE FROM t2; PRAGMA wal_checkpoint; BEGIN; INSERT INTO t2 VALUES('w', 'x'); SAVEPOINT save; INSERT INTO t2 VALUES('y', 'z'); ROLLBACK TO save; COMMIT; SELECT * FROM t2; } } {w x} reopen_db do_test wal-5.1 { execsql { CREATE TEMP TABLE t2(a, b); INSERT INTO t2 VALUES(1, 2); } |
︙ | ︙ | |||
1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 | set rc [catch { db one {PRAGMA integrity_check} } msg] expr { $rc!=0 || $msg!="ok" } } $works db close } } catch { db2 close } catch { db close } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 | set rc [catch { db one {PRAGMA integrity_check} } msg] expr { $rc!=0 || $msg!="ok" } } $works db close } } #------------------------------------------------------------------------- # The following test - wal-19.* - fixes a bug that was present during # development. # # When a database connection in WAL mode is closed, it attempts an # EXCLUSIVE lock on the database file. If the lock is obtained, the # connection knows that it is the last connection to disconnect from # the database, so it runs a checkpoint operation. The bug was that # the connection was not updating its private copy of the wal-index # header before doing so, meaning that it could checkpoint an old # snapshot. # do_test wal-19.1 { file delete -force test.db test.db-wal test.db-journal sqlite3 db test.db sqlite3 db2 test.db execsql { PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); } execsql { SELECT * FROM t1 } db2 } {1 2 3 4} do_test wal-19.2 { execsql { INSERT INTO t1 VALUES(5, 6); SELECT * FROM t1; } } {1 2 3 4 5 6} do_test wal-19.3 { db close db2 close file exists test.db-wal } {0} do_test wal-19.4 { # When the bug was present, the following was returning {1 2 3 4} only, # as [db2] had an out-of-date copy of the wal-index header when it was # closed. # sqlite3 db test.db execsql { SELECT * FROM t1 } } {1 2 3 4 5 6} catch { db2 close } catch { db close } finish_test |