Fix a case where during a rollback triggered by an IO or malloc error an unjournalled region of the database could be written to (with it's original data). This was causing an assert in test_journal.c to fail. Add a test case in ioerr2.test to trigger this case. (CVS 6286)
FossilOrigin-Name: 315a6692f9a03a470871cce4f74567683546f343
This commit is contained in:
parent
ce14f6245e
commit
f7f33fb08a
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
||||
C Updated\sfor\sWindows\scompatibility.\s\sTest\sscripts\sonly.\s(CVS\s6285)
|
||||
D 2009-02-11T16:06:19
|
||||
C Fix\sa\scase\swhere\sduring\sa\srollback\striggered\sby\san\sIO\sor\smalloc\serror\san\sunjournalled\sregion\sof\sthe\sdatabase\scould\sbe\swritten\sto\s(with\sit's\soriginal\sdata).\sThis\swas\scausing\san\sassert\sin\stest_journal.c\sto\sfail.\sAdd\sa\stest\scase\sin\sioerr2.test\sto\strigger\sthis\scase.\s(CVS\s6286)
|
||||
D 2009-02-12T09:11:56
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in c7a5a30fb6852bd7839b1024e1661da8549878ee
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -143,7 +143,7 @@ F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60
|
||||
F src/os_os2.c bed77dc26e3a95ce4a204936b9a1ca6fe612fcc5
|
||||
F src/os_unix.c 4e916cafbf5ec0166213ac62d680ebbe12b8c5a7
|
||||
F src/os_win.c 45cb430884da7e9360a55a0fcd5c2c44c22dd79d
|
||||
F src/pager.c 8c946cca1c1e64bd2d4b15aa431481c96233c826
|
||||
F src/pager.c 57665d91e54da810df27176093936bdee02256b9
|
||||
F src/pager.h 0c9f3520c00d8a3b8e792ca56c9a11b6b02b4b0f
|
||||
F src/parse.y 4f4d16aee0d11f69fec2adb77dac88878043ed8d
|
||||
F src/pcache.c fcf7738c83c4d3e9d45836b2334c8a368cc41274
|
||||
@ -181,7 +181,7 @@ F src/test_config.c 9dd62f4bb725ad87d28b187b07377cb4f4a43197
|
||||
F src/test_devsym.c 9f4bc2551e267ce7aeda195f3897d0f30c5228f4
|
||||
F src/test_func.c a55c4d5479ff2eb5c0a22d4d88e9528ab59c953b
|
||||
F src/test_hexio.c 2f1122aa3f012fa0142ee3c36ce5c902a70cd12f
|
||||
F src/test_journal.c 15f9d0132d97bcc695b0c0e3e29ec8a73f0f430e
|
||||
F src/test_journal.c b0d0468f4f5c4c98f7d7a20669c4875741d18a45
|
||||
F src/test_loadext.c 97dc8800e46a46ed002c2968572656f37e9c0dd9
|
||||
F src/test_malloc.c d23050c7631ec9ee0369c7ca905e6c9233968e11
|
||||
F src/test_md5.c 032ae2bb6f81da350d2404e81fa8d560c8268026
|
||||
@ -409,7 +409,7 @@ F test/interrupt.test 42e7cf98646fd9cb4a3b131a93ed3c50b9e149f1
|
||||
F test/intpkey.test 537669fd535f62632ca64828e435b9e54e8d677f
|
||||
F test/io.test d0dfe567a05d2559b8508d115f1282c25967fee6
|
||||
F test/ioerr.test 12f9000bb9024b4b1386320e60badd5223e75b16
|
||||
F test/ioerr2.test a8428580ce12ce67a6f16d85e2640fa6ce2da888
|
||||
F test/ioerr2.test 021bdc16a9803de34a5ab6ddf211815cad1a4c9f
|
||||
F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
|
||||
F test/ioerr4.test fc6eddfec2efc2f1ed217b9eae4c1c1d3516ce86
|
||||
F test/ioerr5.test 89f69b09a6b5d4f5bbfe58d4231f28236d842dcb
|
||||
@ -701,7 +701,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
P 83e8308435be8c954fe7a347a64f28abcb81437b
|
||||
R d62da5384e66b5c0f55943bc61e79bcc
|
||||
U shane
|
||||
Z 03c6fdb38b642e1292cd435382a0287e
|
||||
P 2522ad1df3599fa71cd1d929142adaefaf3a4d67
|
||||
R 4c4c89955f208108534627e9cec8b7dc
|
||||
U danielk1977
|
||||
Z 02ac569d1f9ca588465f8c431f417f64
|
||||
|
@ -1 +1 @@
|
||||
2522ad1df3599fa71cd1d929142adaefaf3a4d67
|
||||
315a6692f9a03a470871cce4f74567683546f343
|
14
src/pager.c
14
src/pager.c
@ -18,7 +18,7 @@
|
||||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.566 2009/02/04 19:16:23 drh Exp $
|
||||
** @(#) $Id: pager.c,v 1.567 2009/02/12 09:11:56 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
#include "sqliteInt.h"
|
||||
@ -1416,6 +1416,7 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){
|
||||
static int pager_playback_one_page(
|
||||
Pager *pPager, /* The pager being played back */
|
||||
int isMainJrnl, /* 1 -> main journal. 0 -> sub-journal. */
|
||||
int isUnsync, /* True if reading from unsynced main journal */
|
||||
i64 *pOffset, /* Offset of record to playback */
|
||||
int isSavepnt, /* True for a savepoint rollback */
|
||||
Bitvec *pDone /* Bitvec of pages already played back */
|
||||
@ -1511,6 +1512,7 @@ static int pager_playback_one_page(
|
||||
if( (pPager->state>=PAGER_EXCLUSIVE)
|
||||
&& (pPg==0 || 0==(pPg->flags&PGHDR_NEED_SYNC))
|
||||
&& isOpen(pPager->fd)
|
||||
&& !isUnsync
|
||||
){
|
||||
i64 ofst = (pgno-1)*(i64)pPager->pageSize;
|
||||
rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, ofst);
|
||||
@ -1951,6 +1953,7 @@ static int pager_playback(Pager *pPager, int isHot){
|
||||
** occurs.
|
||||
*/
|
||||
while( 1 ){
|
||||
int isUnsync = 0;
|
||||
|
||||
/* Read the next journal header from the journal file. If there are
|
||||
** not enough bytes left in the journal file for a complete header, or
|
||||
@ -1997,6 +2000,7 @@ static int pager_playback(Pager *pPager, int isHot){
|
||||
if( nRec==0 && !isHot &&
|
||||
pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){
|
||||
nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager));
|
||||
isUnsync = 1;
|
||||
}
|
||||
|
||||
/* If this is the first header read from the journal, truncate the
|
||||
@ -2018,7 +2022,7 @@ static int pager_playback(Pager *pPager, int isHot){
|
||||
pager_reset(pPager);
|
||||
needPagerReset = 0;
|
||||
}
|
||||
rc = pager_playback_one_page(pPager, 1, &pPager->journalOff, 0, 0);
|
||||
rc = pager_playback_one_page(pPager,1,isUnsync,&pPager->journalOff,0,0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
@ -2160,7 +2164,7 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
|
||||
iHdrOff = pSavepoint->iHdrOffset ? pSavepoint->iHdrOffset : szJ;
|
||||
pPager->journalOff = pSavepoint->iOffset;
|
||||
while( rc==SQLITE_OK && pPager->journalOff<iHdrOff ){
|
||||
rc = pager_playback_one_page(pPager, 1, &pPager->journalOff, 1, pDone);
|
||||
rc = pager_playback_one_page(pPager, 1, 0, &pPager->journalOff, 1, pDone);
|
||||
}
|
||||
assert( rc!=SQLITE_DONE );
|
||||
}else{
|
||||
@ -2195,7 +2199,7 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
|
||||
nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager));
|
||||
}
|
||||
for(ii=0; rc==SQLITE_OK && ii<nJRec && pPager->journalOff<szJ; ii++){
|
||||
rc = pager_playback_one_page(pPager, 1, &pPager->journalOff, 1, pDone);
|
||||
rc = pager_playback_one_page(pPager, 1, 0, &pPager->journalOff, 1, pDone);
|
||||
}
|
||||
assert( rc!=SQLITE_DONE );
|
||||
}
|
||||
@ -2210,7 +2214,7 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
|
||||
i64 offset = pSavepoint->iSubRec*(4+pPager->pageSize);
|
||||
for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
|
||||
assert( offset==ii*(4+pPager->pageSize) );
|
||||
rc = pager_playback_one_page(pPager, 0, &offset, 1, pDone);
|
||||
rc = pager_playback_one_page(pPager, 0, 0, &offset, 1, pDone);
|
||||
}
|
||||
assert( rc!=SQLITE_DONE );
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
** correctly populates and syncs a journal file before writing to a
|
||||
** corresponding database file.
|
||||
**
|
||||
** $Id: test_journal.c,v 1.10 2009/02/11 07:38:12 danielk1977 Exp $
|
||||
** $Id: test_journal.c,v 1.11 2009/02/12 09:11:56 danielk1977 Exp $
|
||||
*/
|
||||
#if SQLITE_TEST /* This file is used for testing only */
|
||||
|
||||
@ -206,6 +206,15 @@ struct JtGlobal {
|
||||
};
|
||||
static struct JtGlobal g = {0, 0};
|
||||
|
||||
extern int sqlite3_io_error_pending;
|
||||
static void stop_ioerr_simulation(int *piSave){
|
||||
*piSave = sqlite3_io_error_pending;
|
||||
sqlite3_io_error_pending = -1;
|
||||
}
|
||||
static void start_ioerr_simulation(int iSave){
|
||||
sqlite3_io_error_pending = iSave;
|
||||
}
|
||||
|
||||
/*
|
||||
** The jt_file pointed to by the argument may or may not be a file-handle
|
||||
** open on a main database file. If it is, and a transaction is currently
|
||||
@ -343,6 +352,9 @@ static int openTransaction(jt_file *pMain, jt_file *pJournal){
|
||||
rc = SQLITE_IOERR_NOMEM;
|
||||
}else if( pMain->nPage>0 ){
|
||||
u32 iTrunk;
|
||||
int iSave;
|
||||
|
||||
stop_ioerr_simulation(&iSave);
|
||||
|
||||
/* Read the database free-list. Add the page-number for each free-list
|
||||
** leaf to the jt_file.pWritable bitvec.
|
||||
@ -372,6 +384,8 @@ static int openTransaction(jt_file *pMain, jt_file *pJournal){
|
||||
pMain->aCksum[ii] = genCksum(aData, pMain->nPagesize);
|
||||
}
|
||||
}
|
||||
|
||||
start_ioerr_simulation(iSave);
|
||||
}
|
||||
|
||||
sqlite3_free(aData);
|
||||
@ -465,12 +479,15 @@ static int readJournalFile(jt_file *p, jt_file *pMain){
|
||||
sqlite3_int64 iOff = 0;
|
||||
sqlite3_int64 iSize = p->iMaxOff;
|
||||
unsigned char *aPage;
|
||||
int iSave;
|
||||
|
||||
aPage = sqlite3_malloc(pMain->nPagesize);
|
||||
if( !aPage ){
|
||||
return SQLITE_IOERR_NOMEM;
|
||||
}
|
||||
|
||||
stop_ioerr_simulation(&iSave);
|
||||
|
||||
while( rc==SQLITE_OK && iOff<iSize ){
|
||||
u32 nRec, nPage, nSector, nPagesize;
|
||||
u32 ii;
|
||||
@ -522,6 +539,7 @@ static int readJournalFile(jt_file *p, jt_file *pMain){
|
||||
}
|
||||
|
||||
finish_rjf:
|
||||
start_ioerr_simulation(iSave);
|
||||
sqlite3_free(aPage);
|
||||
if( rc==SQLITE_IOERR_SHORT_READ ){
|
||||
rc = SQLITE_OK;
|
||||
|
@ -15,7 +15,7 @@
|
||||
# The tests in this file use special facilities that are only
|
||||
# available in the SQLite test fixture.
|
||||
#
|
||||
# $Id: ioerr2.test,v 1.10 2008/09/16 14:38:04 danielk1977 Exp $
|
||||
# $Id: ioerr2.test,v 1.11 2009/02/12 09:11:56 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -145,4 +145,27 @@ if {$::tcl_platform(platform) == "unix"} {
|
||||
} {1 {not a writable directory}}
|
||||
}
|
||||
|
||||
do_ioerr_test ioerr2-7 -persist 0 -sqlprep {
|
||||
PRAGMA cache_size = 10;
|
||||
PRAGMA auto_vacuum = 1;
|
||||
CREATE TABLE ab(a, b);
|
||||
CREATE TABLE de(d, e);
|
||||
INSERT INTO ab VALUES(1, randstr(200,200));
|
||||
INSERT INTO ab SELECT a+1, randstr(200,200) FROM ab;
|
||||
INSERT INTO ab SELECT a+2, randstr(200,200) FROM ab;
|
||||
INSERT INTO ab SELECT a+4, randstr(200,200) FROM ab;
|
||||
INSERT INTO ab SELECT a+8, randstr(200,200) FROM ab;
|
||||
INSERT INTO ab SELECT a+16, randstr(200,200) FROM ab;
|
||||
INSERT INTO ab SELECT a+32, randstr(200,200) FROM ab;
|
||||
INSERT INTO ab SELECT a+64, randstr(200,200) FROM ab;
|
||||
INSERT INTO de SELECT * FROM ab;
|
||||
} -sqlbody {
|
||||
BEGIN;
|
||||
UPDATE ab SET b = randstr(200,200);
|
||||
UPDATE de SET e = randstr(200,200) WHERE d = (SELECT max(d) FROM de);
|
||||
DELETE FROM ab;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user