Add tests to simulate power-failure on devices that support IOCAP_SEQUENTIAL or IOCAP_SAFE_APPEND. (CVS 4284)
FossilOrigin-Name: bdf5cb8d25d93d48220ce46acad2ccf967a87843
This commit is contained in:
parent
d5499d648f
commit
f55b899824
22
manifest
22
manifest
@ -1,5 +1,5 @@
|
||||
C Bug\sfix\sin\sthe\smemory\sleak\strace\soutput.\s(CVS\s4283)
|
||||
D 2007-08-24T04:15:00
|
||||
C Add\stests\sto\ssimulate\spower-failure\son\sdevices\sthat\ssupport\sIOCAP_SEQUENTIAL\sor\sIOCAP_SAFE_APPEND.\s(CVS\s4284)
|
||||
D 2007-08-24T08:15:54
|
||||
F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe
|
||||
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@ -94,7 +94,7 @@ F src/func.c aa8a3a8db571c46e5197664ddbc2784006ee5525
|
||||
F src/hash.c 2f322979071dd2bdba7503b5276d66f028744382
|
||||
F src/hash.h 3ad3da76bfb954978d227bf495568b0e6da2c19e
|
||||
F src/insert.c 633322aef1799f6604fa805e12488bc628570b0c
|
||||
F src/journal.c 03d6b5cc1afe7c5e3cd0af55415f5168eb094398
|
||||
F src/journal.c 573911e274738b3fda813d4f0a6e319f8a9ecd36
|
||||
F src/legacy.c 7e1b1c57694e49cbadf561e2a7d9cd984dc743b5
|
||||
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
|
||||
F src/loadext.c 8b31e2e0e961918fa045515459aee1c122d8c266
|
||||
@ -115,7 +115,7 @@ F src/os_unix.c c45b20f868fab1178710ea2f1c8043ce706d3a99
|
||||
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
|
||||
F src/os_win.c 1cb94dd33d38e01de82d77bef107c7f3323463ec
|
||||
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c 89dfc6a0bd72898d147264517a43bdf35348dd2c
|
||||
F src/pager.c a46c807f6c00d8172ea7f17b8bfd2c870d2e9d98
|
||||
F src/pager.h 53087c6fb9db01aed17c7fd044662a27507e89b8
|
||||
F src/parse.y 2d2ce439dc6184621fb0b86f4fc5aca7f391a590
|
||||
F src/pragma.c 9b989506a1b7c8aecd6befb8235e2f57a4aba7e5
|
||||
@ -127,7 +127,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||
F src/shell.c ac29402b538515fa4697282387be9c1205e6e9eb
|
||||
F src/sqlite.h.in 09a5256ee80dfc7cb4353739f78e4267be323574
|
||||
F src/sqlite3ext.h 9a26028378c288af500d8b94ed079666fed5806b
|
||||
F src/sqliteInt.h 951229c727f14f12f1c5555d2ed079bd2201415c
|
||||
F src/sqliteInt.h ea7a14a33c0a03479d2d98ce9ac83fe5e7f4bb55
|
||||
F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa
|
||||
F src/table.c c725e47f6f3092b9a7b569fc58e408e2173ee008
|
||||
F src/tclsqlite.c d76af53f45c9e9f7f7d39531fa4c7bee7d0adad6
|
||||
@ -136,7 +136,7 @@ F src/test2.c 4f742e99ed1bea5c14692f627bdb59a146f30504
|
||||
F src/test3.c a7d011c51d6b2e2a73c43983d5c2b731d69c74d7
|
||||
F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
|
||||
F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
|
||||
F src/test6.c de2dbcd67401f00bfa0affc044ba671aa62384a5
|
||||
F src/test6.c 37caea087882ecce1cbc6c83f9f1d457bd42b731
|
||||
F src/test7.c a9d509d0e9ad214b4772696f49f6e61be26213d1
|
||||
F src/test8.c e6a543c8b248efe120ae33a6859fcd55dcf46a96
|
||||
F src/test9.c b46c8fe02ac7cca1a7316436d8d38d50c66f4b2f
|
||||
@ -227,7 +227,7 @@ F test/corrupt2.test 572f8df0303d0ce63ddad5c5c9101a83a345ae46
|
||||
F test/corrupt3.test 263e8bb04e2728df832fddf6973cf54c91db0c32
|
||||
F test/crash.test 24020168cc42977a4dd83ff78d2b5eb6577715db
|
||||
F test/crash2.test 423c6ec404d15b7d7d0e40aef0a26740cce6075f
|
||||
F test/crash3.test caa79052f29ee5cb17ecede2c386251eb932c05f
|
||||
F test/crash3.test 96eee2301b000264d355591fe650a9ad5ac01be9
|
||||
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test b562aba1a65be49935fc43a04e90766e39231804
|
||||
F test/date.test 4834d022b2fa5982cafed20938f7523a7475e4cd
|
||||
@ -561,7 +561,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P 3a68fcddfa9184e4b310ce0a21312c54b9462ec8
|
||||
R 8577d385c536daf1df94ce55e3096cab
|
||||
U drh
|
||||
Z 81d0ac074a196345faf13b53e0789aed
|
||||
P a1b495c28a092c7eb79ffeeb6a217749acb4c12c
|
||||
R 9e378d30b0d2403f2a8c2ca36386519e
|
||||
U danielk1977
|
||||
Z cedf0a8ddde877cdc3adcde56bbd62a1
|
||||
|
@ -1 +1 @@
|
||||
a1b495c28a092c7eb79ffeeb6a217749acb4c12c
|
||||
bdf5cb8d25d93d48220ce46acad2ccf967a87843
|
@ -10,7 +10,7 @@
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** @(#) $Id: journal.c,v 1.2 2007/08/23 08:06:45 danielk1977 Exp $
|
||||
** @(#) $Id: journal.c,v 1.3 2007/08/24 08:15:54 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
@ -220,6 +220,17 @@ int sqlite3JournalOpen(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** If the argument p points to a JournalFile structure, and the underlying
|
||||
** file has not yet been created, create it now.
|
||||
*/
|
||||
int sqlite3JournalCreate(sqlite3_file *p){
|
||||
if( p->pMethods!=&JournalFileMethods ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
return createFile((JournalFile *)p);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of bytes required to store a JournalFile that uses vfs
|
||||
** pVfs to create the underlying on-disk files.
|
||||
|
21
src/pager.c
21
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.372 2007/08/24 03:51:34 drh Exp $
|
||||
** @(#) $Id: pager.c,v 1.373 2007/08/24 08:15:54 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
#include "sqliteInt.h"
|
||||
@ -4192,7 +4192,6 @@ int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){
|
||||
*/
|
||||
if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){
|
||||
PgHdr *pPg;
|
||||
assert( pPager->journalOpen );
|
||||
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
/* The atomic-write optimization can be used if all of the
|
||||
@ -4206,9 +4205,13 @@ int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){
|
||||
** If the optimization can be used, then the journal file will never
|
||||
** be created for this transaction.
|
||||
*/
|
||||
if( !zMaster && pPager->journalOff==jrnlBufferSize(pPager) && nTrunc==0
|
||||
&& (0==pPager->pDirty || 0==pPager->pDirty->pDirty)
|
||||
){
|
||||
int useAtomicWrite = (
|
||||
!zMaster &&
|
||||
pPager->journalOff==jrnlBufferSize(pPager) &&
|
||||
nTrunc==0 &&
|
||||
(0==pPager->pDirty || 0==pPager->pDirty->pDirty)
|
||||
);
|
||||
if( useAtomicWrite ){
|
||||
/* Update the nRec field in the journal file. */
|
||||
int offset = pPager->journalHdr + sizeof(aJournalMagic);
|
||||
assert(pPager->nRec==1);
|
||||
@ -4221,7 +4224,12 @@ int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){
|
||||
** this is safe.
|
||||
*/
|
||||
rc = pager_incr_changecounter(pPager, 1);
|
||||
}else
|
||||
}else{
|
||||
rc = sqlite3JournalCreate(pPager->jfd);
|
||||
if( rc!=SQLITE_OK ) goto sync_exit;
|
||||
}
|
||||
|
||||
if( !useAtomicWrite )
|
||||
#endif
|
||||
|
||||
/* If a master journal file name has already been written to the
|
||||
@ -4231,6 +4239,7 @@ int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){
|
||||
** transaction the m-j name will have already been written.
|
||||
*/
|
||||
if( !pPager->setMaster ){
|
||||
assert( pPager->journalOpen );
|
||||
rc = pager_incr_changecounter(pPager, 0);
|
||||
if( rc!=SQLITE_OK ) goto sync_exit;
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.598 2007/08/23 02:47:53 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.599 2007/08/24 08:15:54 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@ -1867,6 +1867,7 @@ CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
|
||||
int sqlite3JournalSize(sqlite3_vfs *);
|
||||
int sqlite3JournalCreate(sqlite3_file *);
|
||||
#else
|
||||
#define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile)
|
||||
#endif
|
||||
|
110
src/test6.c
110
src/test6.c
@ -14,7 +14,7 @@
|
||||
** the effect on the database file of an OS crash or power failure. This
|
||||
** is used to test the ability of SQLite to recover from those situations.
|
||||
*/
|
||||
#if SQLITE_TEST /* This file is used for the testing only */
|
||||
#if SQLITE_TEST /* This file is used for testing only */
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
|
||||
@ -162,13 +162,16 @@ static int sqlite3CrashTestEnable = 0;
|
||||
static int writeListSync(CrashFile *pFile, int isCrash){
|
||||
int rc = SQLITE_OK;
|
||||
int iDc = g.iDeviceCharacteristics;
|
||||
i64 iSize;
|
||||
|
||||
WriteBuffer *pWrite;
|
||||
WriteBuffer **ppPtr;
|
||||
|
||||
/* Set pFinal to point to the last element of the write-list that
|
||||
** is associated with file handle pFile.
|
||||
/* If this is not a crash simulation, set pFinal to point to the
|
||||
** last element of the write-list that is associated with file handle
|
||||
** pFile.
|
||||
**
|
||||
** If this is a crash simulation, set pFinal to an arbitrarily selected
|
||||
** element of the write-list.
|
||||
*/
|
||||
WriteBuffer *pFinal = 0;
|
||||
if( !isCrash ){
|
||||
@ -177,14 +180,20 @@ static int writeListSync(CrashFile *pFile, int isCrash){
|
||||
pFinal = pWrite;
|
||||
}
|
||||
}
|
||||
}else if( iDc&(SQLITE_IOCAP_SEQUENTIAL|SQLITE_IOCAP_SAFE_APPEND) ){
|
||||
int nWrite = 0;
|
||||
int iFinal;
|
||||
for(pWrite=g.pWriteList; pWrite; pWrite=pWrite->pNext) nWrite++;
|
||||
sqlite3Randomness(sizeof(int), &iFinal);
|
||||
iFinal = ((iFinal<0)?-1*iFinal:iFinal)%nWrite;
|
||||
for(pWrite=g.pWriteList; iFinal>0; pWrite=pWrite->pNext) iFinal--;
|
||||
pFinal = pWrite;
|
||||
}
|
||||
|
||||
#ifdef TRACE_CRASHTEST
|
||||
printf("Sync %s (is %s crash)\n", pFile->zName, (isCrash?"a":"not a"));
|
||||
#endif
|
||||
|
||||
sqlite3OsFileSize((sqlite3_file *)pFile, &iSize);
|
||||
|
||||
ppPtr = &g.pWriteList;
|
||||
for(pWrite=*ppPtr; rc==SQLITE_OK && pWrite; pWrite=*ppPtr){
|
||||
sqlite3_file *pRealFile = pWrite->pFile->pRealFile;
|
||||
@ -203,10 +212,33 @@ static int writeListSync(CrashFile *pFile, int isCrash){
|
||||
char random;
|
||||
sqlite3Randomness(1, &random);
|
||||
|
||||
if( iDc&SQLITE_IOCAP_ATOMIC || pWrite->zBuf==0 ){
|
||||
/* Do not select option 3 (sector trashing) if the IOCAP_ATOMIC flag
|
||||
** is set or this is an OsTruncate(), not an Oswrite().
|
||||
*/
|
||||
if( (iDc&SQLITE_IOCAP_ATOMIC) || (pWrite->zBuf==0) ){
|
||||
random &= 0x01;
|
||||
}
|
||||
|
||||
/* If IOCAP_SEQUENTIAL is set and this is not the final entry
|
||||
** in the truncated write-list, always select option 1 (write
|
||||
** out correctly).
|
||||
*/
|
||||
if( (iDc&SQLITE_IOCAP_SEQUENTIAL && pWrite!=pFinal) ){
|
||||
random = 0;
|
||||
}
|
||||
|
||||
/* If IOCAP_SAFE_APPEND is set and this OsWrite() operation is
|
||||
** an append (first byte of the written region is 1 byte past the
|
||||
** current EOF), always select option 1 (write out correctly).
|
||||
*/
|
||||
if( iDc&SQLITE_IOCAP_SAFE_APPEND && pWrite->zBuf ){
|
||||
i64 iSize;
|
||||
sqlite3OsFileSize(pRealFile, &iSize);
|
||||
if( iSize==pWrite->iOffset ){
|
||||
random = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( (random&0x06)==0x06 ){
|
||||
eAction = 3;
|
||||
}else{
|
||||
@ -226,7 +258,9 @@ static int writeListSync(CrashFile *pFile, int isCrash){
|
||||
*ppPtr = pWrite->pNext;
|
||||
#ifdef TRACE_CRASHTEST
|
||||
if( isCrash ){
|
||||
printf("Writing %d bytes @ %d\n", pWrite->nBuf, (int)pWrite->iOffset);
|
||||
printf("Writing %d bytes @ %d (%s)\n",
|
||||
pWrite->nBuf, (int)pWrite->iOffset, pWrite->pFile->zName
|
||||
);
|
||||
}
|
||||
#endif
|
||||
sqlite3_free(pWrite);
|
||||
@ -236,7 +270,9 @@ static int writeListSync(CrashFile *pFile, int isCrash){
|
||||
ppPtr = &pWrite->pNext;
|
||||
#ifdef TRACE_CRASHTEST
|
||||
if( isCrash ){
|
||||
printf("Omiting %d bytes @ %d\n", pWrite->nBuf, (int)pWrite->iOffset);
|
||||
printf("Omiting %d bytes @ %d (%s)\n",
|
||||
pWrite->nBuf, (int)pWrite->iOffset, pWrite->pFile->zName
|
||||
);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
@ -249,7 +285,9 @@ static int writeListSync(CrashFile *pFile, int isCrash){
|
||||
assert(pWrite->zBuf);
|
||||
|
||||
#ifdef TRACE_CRASHTEST
|
||||
printf("Trashing %d sectors @ sector %d\n", 1+iLast-iFirst, iFirst);
|
||||
printf("Trashing %d sectors @ sector %d (%s)\n",
|
||||
1+iLast-iFirst, iFirst, pWrite->pFile->zName
|
||||
);
|
||||
#endif
|
||||
|
||||
zGarbage = sqlite3_malloc(g.iSectorSize);
|
||||
@ -489,13 +527,13 @@ struct crashAppData {
|
||||
** equal or greater than sizeof(CrashFile).
|
||||
*/
|
||||
static int cfOpen(
|
||||
void *pAppData,
|
||||
sqlite3_vfs *pCfVfs,
|
||||
const char *zName,
|
||||
sqlite3_file *pFile,
|
||||
int flags,
|
||||
int *pOutFlags
|
||||
){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAppData;
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
|
||||
int rc;
|
||||
CrashFile *pWrapper = (CrashFile *)pFile;
|
||||
sqlite3_file *pReal = (sqlite3_file*)&pWrapper[1];
|
||||
@ -527,37 +565,37 @@ static int cfOpen(
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cfDelete(void *pAppData, const char *zPath, int dirSync){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAppData;
|
||||
return pVfs->xDelete(pVfs->pAppData, zPath, dirSync);
|
||||
static int cfDelete(sqlite3_vfs *pCfVfs, const char *zPath, int dirSync){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
|
||||
return pVfs->xDelete(pVfs, zPath, dirSync);
|
||||
}
|
||||
static int cfAccess(void *pAppData, const char *zPath, int flags){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAppData;
|
||||
return pVfs->xAccess(pVfs->pAppData, zPath, flags);
|
||||
static int cfAccess(sqlite3_vfs *pCfVfs, const char *zPath, int flags){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
|
||||
return pVfs->xAccess(pVfs, zPath, flags);
|
||||
}
|
||||
static int cfGetTempName(void *pAppData, char *zBufOut){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAppData;
|
||||
return pVfs->xGetTempName(pVfs->pAppData, zBufOut);
|
||||
static int cfGetTempName(sqlite3_vfs *pCfVfs, char *zBufOut){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
|
||||
return pVfs->xGetTempName(pVfs, zBufOut);
|
||||
}
|
||||
static int cfFullPathname(void *pAppData, const char *zPath, char *zPathOut){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAppData;
|
||||
return pVfs->xFullPathname(pVfs->pAppData, zPath, zPathOut);
|
||||
static int cfFullPathname(sqlite3_vfs *pCfVfs, const char *zPath, char *zPathOut){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
|
||||
return pVfs->xFullPathname(pVfs, zPath, zPathOut);
|
||||
}
|
||||
static void *cfDlOpen(void *pAppData, const char *zPath){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAppData;
|
||||
return pVfs->xDlOpen(pVfs->pAppData, zPath);
|
||||
static void *cfDlOpen(sqlite3_vfs *pCfVfs, const char *zPath){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
|
||||
return pVfs->xDlOpen(pVfs, zPath);
|
||||
}
|
||||
static int cfRandomness(void *pAppData, int nByte, char *zBufOut){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAppData;
|
||||
return pVfs->xRandomness(pVfs->pAppData, nByte, zBufOut);
|
||||
static int cfRandomness(sqlite3_vfs *pCfVfs, int nByte, char *zBufOut){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
|
||||
return pVfs->xRandomness(pVfs, nByte, zBufOut);
|
||||
}
|
||||
static int cfSleep(void *pAppData, int nMicro){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAppData;
|
||||
return pVfs->xSleep(pVfs->pAppData, nMicro);
|
||||
static int cfSleep(sqlite3_vfs *pCfVfs, int nMicro){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
|
||||
return pVfs->xSleep(pVfs, nMicro);
|
||||
}
|
||||
static int cfCurrentTime(void *pAppData, double *pTimeOut){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAppData;
|
||||
return pVfs->xCurrentTime(pVfs->pAppData, pTimeOut);
|
||||
static int cfCurrentTime(sqlite3_vfs *pCfVfs, double *pTimeOut){
|
||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
|
||||
return pVfs->xCurrentTime(pVfs, pTimeOut);
|
||||
}
|
||||
|
||||
static int processDevSymArgs(
|
||||
|
@ -9,7 +9,11 @@
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# $Id: crash3.test,v 1.1 2007/08/23 11:07:10 danielk1977 Exp $
|
||||
# This file contains tests that verify that SQLite can correctly rollback
|
||||
# databases after crashes when using the special IO modes triggered
|
||||
# by device IOCAP flags.
|
||||
#
|
||||
# $Id: crash3.test,v 1.2 2007/08/24 08:15:54 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -34,6 +38,8 @@ proc do_test2 {name tcl res1 res2} {
|
||||
uplevel $script
|
||||
}
|
||||
|
||||
# This block tests crash-recovery when the IOCAP_ATOMIC flags is set.
|
||||
#
|
||||
# Each iteration of the following loop sets up the database to contain
|
||||
# the following schema and data:
|
||||
#
|
||||
@ -96,5 +102,89 @@ foreach {sql res2} [list \
|
||||
}
|
||||
}
|
||||
|
||||
# This block tests both the IOCAP_SEQUENTIAL and IOCAP_SAFE_APPEND flags.
|
||||
#
|
||||
db close
|
||||
file delete -force test.db test.db-journal
|
||||
sqlite3 db test.db
|
||||
do_test crash3-2.0 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
CREATE TABLE abc(a PRIMARY KEY, b, c);
|
||||
CREATE TABLE def(d PRIMARY KEY, e, f);
|
||||
PRAGMA default_cache_size = 10;
|
||||
INSERT INTO abc VALUES(randstr(10,1000),randstr(10,1000),randstr(10,1000));
|
||||
INSERT INTO abc
|
||||
SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
|
||||
INSERT INTO abc
|
||||
SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
|
||||
INSERT INTO abc
|
||||
SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
|
||||
INSERT INTO abc
|
||||
SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
|
||||
INSERT INTO abc
|
||||
SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
|
||||
INSERT INTO abc
|
||||
SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000) FROM abc;
|
||||
COMMIT;
|
||||
}
|
||||
} {}
|
||||
|
||||
set tn 1
|
||||
foreach {::crashfile ::delay ::char} {
|
||||
test.db 1 sequential
|
||||
test.db 1 safe_append
|
||||
test.db-journal 1 sequential
|
||||
test.db-journal 1 safe_append
|
||||
test.db-journal 2 safe_append
|
||||
test.db-journal 2 sequential
|
||||
test.db-journal 3 sequential
|
||||
test.db-journal 3 safe_append
|
||||
} {
|
||||
for {set ii 0} {$ii < 100} {incr ii} {
|
||||
set ::SQL [subst {
|
||||
SELECT randstr($ii,$ii+10);
|
||||
BEGIN;
|
||||
DELETE FROM abc WHERE random()%5;
|
||||
INSERT INTO abc
|
||||
SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000)
|
||||
FROM abc
|
||||
WHERE (random()%5)==0;
|
||||
DELETE FROM def WHERE random()%5;
|
||||
INSERT INTO def
|
||||
SELECT randstr(10,1000),randstr(10,1000),randstr(10,1000)
|
||||
FROM def
|
||||
WHERE (random()%5)==0;
|
||||
COMMIT;
|
||||
}]
|
||||
|
||||
do_test crash3-2.$tn.$ii {
|
||||
crashsql -file $::crashfile -delay $::delay -char $::char $::SQL
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
execsql {PRAGMA integrity_check}
|
||||
} {ok}
|
||||
}
|
||||
incr tn
|
||||
}
|
||||
|
||||
# The following block tests an interaction between IOCAP_ATOMIC and
|
||||
# IOCAP_SEQUENTIAL. At one point, if both flags were set, small
|
||||
# journal files that contained only a single page, but were required
|
||||
# for some other reason (i.e. nTrunk) were not being written to
|
||||
# disk.
|
||||
#
|
||||
for {set ii 0} {$ii < 10} {incr ii} {
|
||||
db close
|
||||
file delete -force test.db test.db-journal
|
||||
crashsql -file test.db -char {sequential atomic} {
|
||||
CREATE TABLE abc(a, b, c);
|
||||
}
|
||||
sqlite3 db test.db
|
||||
do_test crash3-3.$ii {
|
||||
execsql {PRAGMA integrity_check}
|
||||
} {ok}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user