Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix some problems with multi-file transaction rollback. (CVS 1751) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
06e8e30b249c10512a225d6c7a5fcb5c |
User & Date: | danielk1977 2004-06-28 04:52:30.000 |
Context
2004-06-28
| ||
08:25 | Add a simple test case for inter-process locking. (CVS 1752) (check-in: b0fcc99d22 user: danielk1977 tags: trunk) | |
04:52 | Fix some problems with multi-file transaction rollback. (CVS 1751) (check-in: 06e8e30b24 user: danielk1977 tags: trunk) | |
01:16 | A few more warning fixes. (CVS 1750) (check-in: 81e4994045 user: danielk1977 tags: trunk) | |
Changes
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.147 2004/06/28 04:52:30 danielk1977 Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
420 421 422 423 424 425 426 | rc = read32bits(pJrnl, &cksum); if( rc!=SQLITE_OK ) return rc; rc = sqlite3OsRead(pJrnl, aMagic, 8); if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc; | | | | | > > > > > > | 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | rc = read32bits(pJrnl, &cksum); if( rc!=SQLITE_OK ) return rc; rc = sqlite3OsRead(pJrnl, aMagic, 8); if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc; rc = sqlite3OsSeek(pJrnl, szJ-16-len); if( rc!=SQLITE_OK ) return rc; *pzMaster = (char *)sqliteMalloc(len+1); if( !*pzMaster ){ return SQLITE_NOMEM; } rc = sqlite3OsRead(pJrnl, *pzMaster, len); if( rc!=SQLITE_OK ){ sqliteFree(*pzMaster); *pzMaster = 0; return rc; } /* See if the checksum matches the master journal name */ for(i=0; i<len; i++){ cksum -= (*pzMaster)[i]; } if( cksum ){ /* If the checksum doesn't add up, then one or more of the disk sectors ** containing the master journal filename is corrupted. This means ** definitely roll back, so just return SQLITE_OK and report a (nul) ** master-journal filename. */ sqliteFree(*pzMaster); *pzMaster = 0; } (*pzMaster)[len] = '\0'; return SQLITE_OK; } /* ** Seek the journal file descriptor to the next sector boundary where a ** journal header may be read or written. Pager.journalOff is updated with |
︙ | ︙ | |||
909 910 911 912 913 914 915 | char *zMasterJournal = 0; /* Contents of master journal file */ off_t nMasterJournal; /* Size of master journal file */ /* Open the master journal file exclusively in case some other process ** is running this routine also. Not that it makes too much difference. */ memset(&master, 0, sizeof(master)); | | | 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 | char *zMasterJournal = 0; /* Contents of master journal file */ off_t nMasterJournal; /* Size of master journal file */ /* Open the master journal file exclusively in case some other process ** is running this routine also. Not that it makes too much difference. */ memset(&master, 0, sizeof(master)); rc = sqlite3OsOpenReadOnly(zMaster, &master); if( rc!=SQLITE_OK ) goto delmaster_out; master_open = 1; rc = sqlite3OsFileSize(&master, &nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; if( nMasterJournal>0 ){ char *zJournal; |
︙ | ︙ | |||
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 | ** where not restored by the loop above. We have to restore those ** pages by reading them back from the original database. */ assert( rc==SQLITE_OK ); pager_reload_cache(pPager); end_playback: if( zMaster ){ /* If there was a master journal and this routine will return true, ** see if it is possible to delete the master journal. If errors ** occur during this process, ignore them. */ if( rc==SQLITE_OK ){ pager_delmaster(zMaster); } sqliteFree(zMaster); } | > > > < < < | 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 | ** where not restored by the loop above. We have to restore those ** pages by reading them back from the original database. */ assert( rc==SQLITE_OK ); pager_reload_cache(pPager); end_playback: if( rc==SQLITE_OK ){ rc = pager_unwritelock(pPager); } if( zMaster ){ /* If there was a master journal and this routine will return true, ** see if it is possible to delete the master journal. If errors ** occur during this process, ignore them. */ if( rc==SQLITE_OK ){ pager_delmaster(zMaster); } sqliteFree(zMaster); } /* The Pager.sectorSize variable may have been updated while rolling ** back a journal created by a process with a different PAGER_SECTOR_SIZE ** value. Reset it to the correct value for this process. */ pPager->sectorSize = PAGER_SECTOR_SIZE; return rc; |
︙ | ︙ |
Changes to test/crash.test.
︙ | ︙ | |||
16 17 18 19 20 21 22 | # module "crashtest" compiled with the special "os_test.c" backend is used. # The os_test.c simulates the kind of file corruption that can occur # when writes are happening at the moment of power loss. # # The special crash-test module with its os_test.c backend only works # on Unix. # | | | | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # module "crashtest" compiled with the special "os_test.c" backend is used. # The os_test.c simulates the kind of file corruption that can occur # when writes are happening at the moment of power loss. # # The special crash-test module with its os_test.c backend only works # on Unix. # # $Id: crash.test,v 1.7 2004/06/28 04:52:31 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # set repeats 100 set repeats 10 # This proc execs a seperate process that crashes midway through executing # the SQL script $sql on database test.db. # # The crash occurs during a sync() of file $crashfile. When the crash # occurs a random subset of all unsynced writes made by the process are # written into the files on disk. Argument $crashdelay indicates the |
︙ | ︙ | |||
245 246 247 248 249 250 251 | ATTACH 'test2.db' AS aux; PRAGMA aux.default_cache_size = 10; CREATE TABLE aux.abc2 AS SELECT 2*a as a, 2*b as b, 2*c as c FROM abc; } expr [file size test2.db] / 1024 } {559} | | | | > | > > | | > > > > > > | 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 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 300 301 302 303 304 | ATTACH 'test2.db' AS aux; PRAGMA aux.default_cache_size = 10; CREATE TABLE aux.abc2 AS SELECT 2*a as a, 2*b as b, 2*c as c FROM abc; } expr [file size test2.db] / 1024 } {559} for {set i 1} {$i<$repeats} {incr i} { set sig [signature] set sig2 [signature2] do_test crash-4.1.$i.1 { set c [crashsql $i test.db-journal " ATTACH 'test2.db' AS aux; BEGIN; SELECT random() FROM abc LIMIT $i; INSERT INTO abc VALUES(randstr(10,10), 0, 0); DELETE FROM abc WHERE random()%10!=0; INSERT INTO abc2 VALUES(randstr(10,10), 0, 0); DELETE FROM abc2 WHERE random()%10!=0; COMMIT; "] set c } {1 {child process exited abnormally}} do_test crash-4.1.$i.2 { signature } $sig do_test crash-4.1.$i.3 { signature2 } $sig2 } set i 0 while {[incr i]} { set sig [signature] set sig2 [signature2] set ::fin 0 do_test crash-4.2.$i.1 { set c [crashsql $i test2.db-journal " ATTACH 'test2.db' AS aux; BEGIN; SELECT random() FROM abc LIMIT $i; INSERT INTO abc VALUES(randstr(10,10), 0, 0); DELETE FROM abc WHERE random()%10!=0; INSERT INTO abc2 VALUES(randstr(10,10), 0, 0); DELETE FROM abc2 WHERE random()%10!=0; COMMIT; "] if { $c == {0 {}} } { set ::fin 1 set c {1 {child process exited abnormally}} } set c } {1 {child process exited abnormally}} if { $::fin } break do_test crash-4.2.$i.2 { signature } $sig do_test crash-4.2.$i.3 { signature2 } $sig2 } |
︙ | ︙ |