Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a case where a checkpoint operation could write to an invalid part of a memory mapped region. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | experimental-mmap |
Files: | files | file ages | folders |
SHA1: |
8dbe89d05ce91428c69003f0da79d883 |
User & Date: | dan 2013-03-23 14:20:42.975 |
Context
2013-03-23
| ||
17:29 | Improve a comment in wal.c. No code changes. (check-in: 60b9f5e4dd user: dan tags: experimental-mmap) | |
14:20 | Fix a case where a checkpoint operation could write to an invalid part of a memory mapped region. (check-in: 8dbe89d05c user: dan tags: experimental-mmap) | |
12:15 | In the winMremap VFS function, unmap the region prior to attempting to truncate the file. (check-in: 8870c4cc6c user: mistachkin tags: experimental-mmap) | |
Changes
Changes to src/pager.c.
︙ | ︙ | |||
4228 4229 4230 4231 4232 4233 4234 | ** * If mmap is being used, then the mapping is extended to szReq ** bytes in size. ** ** SQLITE_OK is returned if successful, or an error code if an error occurs. */ int sqlite3PagerSetFilesize(Pager *pPager, i64 szReq){ int rc; | | > | | | < < | | > | 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 | ** * If mmap is being used, then the mapping is extended to szReq ** bytes in size. ** ** SQLITE_OK is returned if successful, or an error code if an error occurs. */ int sqlite3PagerSetFilesize(Pager *pPager, i64 szReq){ int rc; i64 sz; /* Size of file on disk in bytes */ assert( pPager->eState==PAGER_OPEN ); assert( pPager->nMmapOut==0 ); rc = sqlite3OsFileSize(pPager->fd, &sz); if( rc==SQLITE_OK ){ if( sz>szReq ){ sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &sz); } } if( rc==SQLITE_OK ){ i64 szMap = (szReq > pPager->nMapLimit) ? pPager->nMapLimit : szReq; if( pPager->nMapValid!=pPager->nMap || szMap!=pPager->nMap ){ pPager->dbFileSize = (szReq / pPager->pageSize); rc = pagerMap(pPager, 1); } } return rc; } /* ** The argument is the first in a linked list of dirty pages connected |
︙ | ︙ |
Changes to test/mmap1.test.
︙ | ︙ | |||
19 20 21 22 23 24 25 | set bt [btree_from_db $db] db_enter $db array set stats [btree_pager_stats $bt] db_leave $db return $stats(read) } | | | | | > > > > | 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 | set bt [btree_from_db $db] db_enter $db array set stats [btree_pager_stats $bt] db_leave $db return $stats(read) } foreach {t mmap_size nRead c2init} { 1.1 { PRAGMA mmap_size = -65536 } 4 {} 1.2 { PRAGMA mmap_size = -50 } 156 {} 1.3 { PRAGMA mmap_size = 0 } 344 {} 1.4 { PRAGMA mmap_size = -65536 } 4 {PRAGMA mmap_size = -65536} 1.5 { PRAGMA mmap_size = -50 } 156 {PRAGMA mmap_size = -65536} 1.6 { PRAGMA mmap_size = 0 } 344 {PRAGMA mmap_size = -65536} } { do_multiclient_test tn { sql1 $mmap_size sql2 $c2init code2 { set ::rcnt 0 proc rblob {n} { set ::rcnt [expr (($::rcnt << 3) + $::rcnt + 456) & 0xFFFFFFFF] set str [format %.8x [expr $::rcnt ^ 0xbdf20da3]] string range [string repeat $str [expr $n/4]] 1 $n |
︙ | ︙ | |||
75 76 77 78 79 80 81 | # Check that the number of pages read by connection 1 indicates that the # "PRAGMA mmap_size" command worked. do_test $t.$tn.5 { nRead db } $nRead } } | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | # Check that the number of pages read by connection 1 indicates that the # "PRAGMA mmap_size" command worked. do_test $t.$tn.5 { nRead db } $nRead } } set ::rcnt 0 proc rblob {n} { set ::rcnt [expr (($::rcnt << 3) + $::rcnt + 456) & 0xFFFFFFFF] set str [format %.8x [expr $::rcnt ^ 0xbdf20da3]] string range [string repeat $str [expr $n/4]] 1 $n } reset_db db func rblob rblob do_execsql_test 2.1 { PRAGMA auto_vacuum = 1; PRAGMA mmap_size = -65536; PRAGMA journal_mode = wal; CREATE TABLE t1(a, b, UNIQUE(a, b)); INSERT INTO t1 VALUES(rblob(500), rblob(500)); INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 2 INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 4 INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 8 INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 16 INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 32 PRAGMA wal_checkpoint; } {wal 0 103 103} do_execsql_test 2.2 { PRAGMA auto_vacuum; SELECT count(*) FROM t1; } {1 32} do_test 2.3 { sqlite3 db2 test.db db2 func rblob rblob db2 eval { DELETE FROM t1 WHERE (rowid%4); PRAGMA wal_checkpoint; } db2 eval { INSERT INTO t1 SELECT rblob(500), rblob(500) FROM t1; -- 16 SELECT count(*) FROM t1; } } {16} do_execsql_test 2.4 { PRAGMA wal_checkpoint; } {0 24 24} finish_test |
Changes to test/speed1p.test.
︙ | ︙ | |||
61 62 63 64 65 66 67 | return $txt } # Create a database schema. # do_test speed1p-1.0 { execsql { | < < < | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | return $txt } # Create a database schema. # do_test speed1p-1.0 { execsql { PRAGMA page_size=1024; PRAGMA cache_size=500; PRAGMA locking_mode=EXCLUSIVE; CREATE TABLE t1(a INTEGER, b INTEGER, c TEXT); CREATE TABLE t2(a INTEGER, b INTEGER, c TEXT); CREATE INDEX i2a ON t2(a); CREATE INDEX i2b ON t2(b); |
︙ | ︙ |