Add tests for malloc() failure when the atomic-write optimization is being used. Also fix things so that rollback can occur without a malloc(), even if there is a master journal file. (CVS 4330)
FossilOrigin-Name: 481fd3a89e50e329596d96565170e3d9977aae29
This commit is contained in:
parent
c1a7f94098
commit
65839c6afd
15
manifest
15
manifest
@ -1,5 +1,5 @@
|
|||||||
C Test\scase\sfixes\sfor\sfulltest.\s(CVS\s4329)
|
C Add\stests\sfor\smalloc()\sfailure\swhen\sthe\satomic-write\soptimization\sis\sbeing\sused.\sAlso\sfix\sthings\sso\sthat\srollback\scan\soccur\swithout\sa\smalloc(),\seven\sif\sthere\sis\sa\smaster\sjournal\sfile.\s(CVS\s4330)
|
||||||
D 2007-08-30T02:26:54
|
D 2007-08-30T08:08:17
|
||||||
F Makefile.in bfcc303429a5d9dcd552d807ee016c77427418c3
|
F Makefile.in bfcc303429a5d9dcd552d807ee016c77427418c3
|
||||||
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
||||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||||
@ -120,7 +120,7 @@ F src/os_unix.c 89bf24aa2475048a7833c45c522e7c6a81b83bb8
|
|||||||
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
|
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
|
||||||
F src/os_win.c 3ffd3aacff4cb69848284e29dcec0feff23b0752
|
F src/os_win.c 3ffd3aacff4cb69848284e29dcec0feff23b0752
|
||||||
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||||
F src/pager.c f9830adfd3752c860a4024da5b871df5af4ed8a4
|
F src/pager.c 847674a74c232f3f7c386d4b902df41a60f781c4
|
||||||
F src/pager.h 1ac4468049348ec72df09d138fc1d7e3a9d0d3a6
|
F src/pager.h 1ac4468049348ec72df09d138fc1d7e3a9d0d3a6
|
||||||
F src/parse.y 2d2ce439dc6184621fb0b86f4fc5aca7f391a590
|
F src/parse.y 2d2ce439dc6184621fb0b86f4fc5aca7f391a590
|
||||||
F src/pragma.c 65109b3d6a62f9a0d64e739653b76afa1122a00d
|
F src/pragma.c 65109b3d6a62f9a0d64e739653b76afa1122a00d
|
||||||
@ -357,6 +357,7 @@ F test/malloc9.test fb99833476bc1a9b0b15573b9a56ae13af843ef9
|
|||||||
F test/mallocA.test bec59bb8c9837cea463d1e76e62d0ea5113c4292
|
F test/mallocA.test bec59bb8c9837cea463d1e76e62d0ea5113c4292
|
||||||
F test/mallocB.test 56fd615f3fea97180132a89dd1dd2068852ef6a0
|
F test/mallocB.test 56fd615f3fea97180132a89dd1dd2068852ef6a0
|
||||||
F test/mallocC.test 3c6385336c82c9c2249c6c28ed23f430e1d66bd3
|
F test/mallocC.test 3c6385336c82c9c2249c6c28ed23f430e1d66bd3
|
||||||
|
F test/mallocD.test 03164dad24407f2a833b8215789f05a342647926
|
||||||
F test/malloc_common.tcl 3c2fb94035e9085f8a687d724b6b61fdac8d961f
|
F test/malloc_common.tcl 3c2fb94035e9085f8a687d724b6b61fdac8d961f
|
||||||
F test/manydb.test 8de36b8d33aab5ef295b11d9e95310aeded31af8
|
F test/manydb.test 8de36b8d33aab5ef295b11d9e95310aeded31af8
|
||||||
F test/memdb.test a67bda4ff90a38f2b19f6c7f95aa7289e051d893
|
F test/memdb.test a67bda4ff90a38f2b19f6c7f95aa7289e051d893
|
||||||
@ -567,7 +568,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||||
P e40d40a5d41c491bef852a92e5846b273b206909
|
P cddce4950569ac49c1a5224b200b00dcd83a2ba4
|
||||||
R c839fab02b445dc9c276b91a0eebee5f
|
R e861f1719df1b7e8bf2776501010b8d3
|
||||||
U drh
|
U danielk1977
|
||||||
Z 319e3e5c3c386bc32b0490ba9c2b3ff7
|
Z d772ae35eed9ac8826bc4538e7174609
|
||||||
|
@ -1 +1 @@
|
|||||||
cddce4950569ac49c1a5224b200b00dcd83a2ba4
|
481fd3a89e50e329596d96565170e3d9977aae29
|
72
src/pager.c
72
src/pager.c
@ -18,7 +18,7 @@
|
|||||||
** file simultaneously, or one process from reading the database while
|
** file simultaneously, or one process from reading the database while
|
||||||
** another is writing.
|
** another is writing.
|
||||||
**
|
**
|
||||||
** @(#) $Id: pager.c,v 1.380 2007/08/29 12:31:27 danielk1977 Exp $
|
** @(#) $Id: pager.c,v 1.381 2007/08/30 08:08:17 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef SQLITE_OMIT_DISKIO
|
#ifndef SQLITE_OMIT_DISKIO
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
@ -872,14 +872,19 @@ static void checkPage(PgHdr *pPg){
|
|||||||
/*
|
/*
|
||||||
** When this is called the journal file for pager pPager must be open.
|
** When this is called the journal file for pager pPager must be open.
|
||||||
** The master journal file name is read from the end of the file and
|
** The master journal file name is read from the end of the file and
|
||||||
** written into memory obtained from sqlite3_malloc(). *pzMaster is
|
** written into memory supplied by the caller.
|
||||||
** set to point at the memory and SQLITE_OK returned. The caller must
|
|
||||||
** sqlite3_free() *pzMaster.
|
|
||||||
**
|
**
|
||||||
** If no master journal file name is present *pzMaster is set to 0 and
|
** zMaster must point to a buffer of at least nMaster bytes allocated by
|
||||||
|
** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
|
||||||
|
** enough space to write the master journal name). If the master journal
|
||||||
|
** name in the journal is longer than nMaster bytes (including a
|
||||||
|
** nul-terminator), then this is handled as if no master journal name
|
||||||
|
** were present in the journal.
|
||||||
|
**
|
||||||
|
** If no master journal file name is present zMaster[0] is set to 0 and
|
||||||
** SQLITE_OK returned.
|
** SQLITE_OK returned.
|
||||||
*/
|
*/
|
||||||
static int readMasterJournal(sqlite3_file *pJrnl, char **pzMaster){
|
static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, int nMaster){
|
||||||
int rc;
|
int rc;
|
||||||
u32 len;
|
u32 len;
|
||||||
i64 szJ;
|
i64 szJ;
|
||||||
@ -887,7 +892,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char **pzMaster){
|
|||||||
int i;
|
int i;
|
||||||
unsigned char aMagic[8]; /* A buffer to hold the magic header */
|
unsigned char aMagic[8]; /* A buffer to hold the magic header */
|
||||||
|
|
||||||
*pzMaster = 0;
|
zMaster[0] = '\0';
|
||||||
|
|
||||||
rc = sqlite3OsFileSize(pJrnl, &szJ);
|
rc = sqlite3OsFileSize(pJrnl, &szJ);
|
||||||
if( rc!=SQLITE_OK || szJ<16 ) return rc;
|
if( rc!=SQLITE_OK || szJ<16 ) return rc;
|
||||||
@ -895,37 +900,33 @@ static int readMasterJournal(sqlite3_file *pJrnl, char **pzMaster){
|
|||||||
rc = read32bits(pJrnl, szJ-16, &len);
|
rc = read32bits(pJrnl, szJ-16, &len);
|
||||||
if( rc!=SQLITE_OK ) return rc;
|
if( rc!=SQLITE_OK ) return rc;
|
||||||
|
|
||||||
|
if( len>=nMaster ){
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
rc = read32bits(pJrnl, szJ-12, &cksum);
|
rc = read32bits(pJrnl, szJ-12, &cksum);
|
||||||
if( rc!=SQLITE_OK ) return rc;
|
if( rc!=SQLITE_OK ) return rc;
|
||||||
|
|
||||||
rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8);
|
rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8);
|
||||||
if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc;
|
if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc;
|
||||||
|
|
||||||
*pzMaster = (char *)sqlite3MallocZero(len+1);
|
rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len);
|
||||||
if( !*pzMaster ){
|
|
||||||
return SQLITE_NOMEM;
|
|
||||||
}
|
|
||||||
rc = sqlite3OsRead(pJrnl, *pzMaster, len, szJ-16-len);
|
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
sqlite3_free(*pzMaster);
|
|
||||||
*pzMaster = 0;
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
zMaster[len] = '\0';
|
||||||
|
|
||||||
/* See if the checksum matches the master journal name */
|
/* See if the checksum matches the master journal name */
|
||||||
for(i=0; i<len; i++){
|
for(i=0; i<len; i++){
|
||||||
cksum -= (*pzMaster)[i];
|
cksum -= zMaster[i];
|
||||||
}
|
}
|
||||||
if( cksum ){
|
if( cksum ){
|
||||||
/* If the checksum doesn't add up, then one or more of the disk sectors
|
/* If the checksum doesn't add up, then one or more of the disk sectors
|
||||||
** containing the master journal filename is corrupted. This means
|
** containing the master journal filename is corrupted. This means
|
||||||
** definitely roll back, so just return SQLITE_OK and report a (nul)
|
** definitely roll back, so just return SQLITE_OK and report a (nul)
|
||||||
** master-journal filename.
|
** master-journal filename.
|
||||||
*/
|
*/
|
||||||
sqlite3_free(*pzMaster);
|
zMaster[0] = '\0';
|
||||||
*pzMaster = 0;
|
|
||||||
}else{
|
|
||||||
(*pzMaster)[len] = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
@ -1493,6 +1494,10 @@ static int pager_playback_one_page(
|
|||||||
** This routine checks if it is possible to delete the master journal file,
|
** This routine checks if it is possible to delete the master journal file,
|
||||||
** and does so if it is.
|
** and does so if it is.
|
||||||
**
|
**
|
||||||
|
** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not
|
||||||
|
** available for use within this function.
|
||||||
|
**
|
||||||
|
**
|
||||||
** The master journal file contains the names of all child journals.
|
** The master journal file contains the names of all child journals.
|
||||||
** To tell if a master journal can be deleted, check to each of the
|
** To tell if a master journal can be deleted, check to each of the
|
||||||
** children. If all children are either missing or do not refer to
|
** children. If all children are either missing or do not refer to
|
||||||
@ -1527,15 +1532,17 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){
|
|||||||
if( nMasterJournal>0 ){
|
if( nMasterJournal>0 ){
|
||||||
char *zJournal;
|
char *zJournal;
|
||||||
char *zMasterPtr = 0;
|
char *zMasterPtr = 0;
|
||||||
|
int nMasterPtr = pPager->pVfs->mxPathname+1;
|
||||||
|
|
||||||
/* Load the entire master journal file into space obtained from
|
/* Load the entire master journal file into space obtained from
|
||||||
** sqlite3_malloc() and pointed to by zMasterJournal.
|
** sqlite3_malloc() and pointed to by zMasterJournal.
|
||||||
*/
|
*/
|
||||||
zMasterJournal = (char *)sqlite3_malloc(nMasterJournal);
|
zMasterJournal = (char *)sqlite3_malloc(nMasterJournal + nMasterPtr);
|
||||||
if( !zMasterJournal ){
|
if( !zMasterJournal ){
|
||||||
rc = SQLITE_NOMEM;
|
rc = SQLITE_NOMEM;
|
||||||
goto delmaster_out;
|
goto delmaster_out;
|
||||||
}
|
}
|
||||||
|
zMasterPtr = &zMasterJournal[nMasterJournal];
|
||||||
rc = sqlite3OsRead(pMaster, zMasterJournal, nMasterJournal, 0);
|
rc = sqlite3OsRead(pMaster, zMasterJournal, nMasterJournal, 0);
|
||||||
if( rc!=SQLITE_OK ) goto delmaster_out;
|
if( rc!=SQLITE_OK ) goto delmaster_out;
|
||||||
|
|
||||||
@ -1553,14 +1560,13 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){
|
|||||||
goto delmaster_out;
|
goto delmaster_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = readMasterJournal(pJournal, &zMasterPtr);
|
rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
|
||||||
sqlite3OsClose(pJournal);
|
sqlite3OsClose(pJournal);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
goto delmaster_out;
|
goto delmaster_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = zMasterPtr!=0 && strcmp(zMasterPtr, zMaster)==0;
|
c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
|
||||||
sqlite3_free(zMasterPtr);
|
|
||||||
if( c ){
|
if( c ){
|
||||||
/* We have a match. Do not delete the master journal file. */
|
/* We have a match. Do not delete the master journal file. */
|
||||||
goto delmaster_out;
|
goto delmaster_out;
|
||||||
@ -1698,17 +1704,18 @@ static int pager_playback(Pager *pPager, int isHot){
|
|||||||
** present on disk, then the journal is not hot and does not need to be
|
** present on disk, then the journal is not hot and does not need to be
|
||||||
** played back.
|
** played back.
|
||||||
*/
|
*/
|
||||||
rc = readMasterJournal(pPager->jfd, &zMaster);
|
zMaster = pPager->pTmpSpace;
|
||||||
|
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
|
||||||
assert( rc!=SQLITE_DONE );
|
assert( rc!=SQLITE_DONE );
|
||||||
if( rc!=SQLITE_OK
|
if( rc!=SQLITE_OK
|
||||||
|| (zMaster && !sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS))
|
|| (zMaster[0] && !sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS))
|
||||||
){
|
){
|
||||||
sqlite3_free(zMaster);
|
|
||||||
zMaster = 0;
|
zMaster = 0;
|
||||||
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
|
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
|
||||||
goto end_playback;
|
goto end_playback;
|
||||||
}
|
}
|
||||||
pPager->journalOff = 0;
|
pPager->journalOff = 0;
|
||||||
|
zMaster = 0;
|
||||||
|
|
||||||
/* This loop terminates either when the readJournalHdr() call returns
|
/* This loop terminates either when the readJournalHdr() call returns
|
||||||
** SQLITE_DONE or an IO error occurs. */
|
** SQLITE_DONE or an IO error occurs. */
|
||||||
@ -1779,17 +1786,18 @@ static int pager_playback(Pager *pPager, int isHot){
|
|||||||
assert( 0 );
|
assert( 0 );
|
||||||
|
|
||||||
end_playback:
|
end_playback:
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
zMaster = pPager->pTmpSpace;
|
||||||
|
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
|
||||||
|
}
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
rc = pager_end_transaction(pPager);
|
rc = pager_end_transaction(pPager);
|
||||||
}
|
}
|
||||||
if( zMaster ){
|
if( rc==SQLITE_OK && zMaster[0] ){
|
||||||
/* If there was a master journal and this routine will return success,
|
/* If there was a master journal and this routine will return success,
|
||||||
** see if it is possible to delete the master journal.
|
** see if it is possible to delete the master journal.
|
||||||
*/
|
*/
|
||||||
if( rc==SQLITE_OK ){
|
rc = pager_delmaster(pPager, zMaster);
|
||||||
rc = pager_delmaster(pPager, zMaster);
|
|
||||||
}
|
|
||||||
sqlite3_free(zMaster);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The Pager.sectorSize variable may have been updated while rolling
|
/* The Pager.sectorSize variable may have been updated while rolling
|
||||||
|
54
test/mallocD.test
Normal file
54
test/mallocD.test
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# 2007 Aug 29
|
||||||
|
#
|
||||||
|
# The author disclaims copyright to this source code. In place of
|
||||||
|
# a legal notice, here is a blessing:
|
||||||
|
#
|
||||||
|
# May you do good and not evil.
|
||||||
|
# May you find forgiveness for yourself and forgive others.
|
||||||
|
# May you share freely, never taking more than you give.
|
||||||
|
#
|
||||||
|
#***********************************************************************
|
||||||
|
#
|
||||||
|
# $Id: mallocD.test,v 1.1 2007/08/30 08:08:17 danielk1977 Exp $
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
source $testdir/malloc_common.tcl
|
||||||
|
|
||||||
|
sqlite3_simulate_device -char atomic
|
||||||
|
|
||||||
|
set PREP {
|
||||||
|
PRAGMA page_size = 1024;
|
||||||
|
CREATE TABLE abc(a, b, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
do_malloc_test mallocD-1 -sqlprep $PREP -sqlbody {
|
||||||
|
INSERT INTO abc VALUES(1, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
do_malloc_test mallocD-2 -sqlprep $PREP -sqlbody {
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO abc VALUES(1, 2, 3);
|
||||||
|
INSERT INTO abc VALUES(4, 5, 6);
|
||||||
|
ROLLBACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_malloc_test mallocD-3 -sqlprep $PREP -sqlbody {
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO abc VALUES(1, 2, 3);
|
||||||
|
INSERT INTO abc VALUES(4, 5, randstr(1500,1500));
|
||||||
|
COMMIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_malloc_test mallocD-4 -sqlprep $PREP -sqlbody {
|
||||||
|
ATTACH 'test2.db' AS aux;
|
||||||
|
BEGIN;
|
||||||
|
CREATE TABLE aux.def(d, e, f);
|
||||||
|
INSERT INTO abc VALUES(4, 5, 6);
|
||||||
|
COMMIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_simulate_device -char {}
|
||||||
|
|
||||||
|
finish_test
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user