mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Add some tests for the atomic-write optimization. (CVS 4275)
FossilOrigin-Name: e2cc7b4a3476a733b2701546f6b4ec9abc18152b
This commit is contained in:
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
|||||||
C Change\snames\sof\sconstants\sin\slemon.c\sto\swork\saround\sname\sconflicts\non\sSolaris.\s\sTicket\s#2583.\s(CVS\s4274)
|
C Add\ssome\stests\sfor\sthe\satomic-write\soptimization.\s(CVS\s4275)
|
||||||
D 2007-08-23T02:50:56
|
D 2007-08-23T08:06:45
|
||||||
F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe
|
F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe
|
||||||
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
||||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||||
@ -94,7 +94,7 @@ F src/func.c aa8a3a8db571c46e5197664ddbc2784006ee5525
|
|||||||
F src/hash.c 2f322979071dd2bdba7503b5276d66f028744382
|
F src/hash.c 2f322979071dd2bdba7503b5276d66f028744382
|
||||||
F src/hash.h 3ad3da76bfb954978d227bf495568b0e6da2c19e
|
F src/hash.h 3ad3da76bfb954978d227bf495568b0e6da2c19e
|
||||||
F src/insert.c 633322aef1799f6604fa805e12488bc628570b0c
|
F src/insert.c 633322aef1799f6604fa805e12488bc628570b0c
|
||||||
F src/journal.c 5ba2a1443b181741d3f2984d9d49e730073d74d1
|
F src/journal.c 03d6b5cc1afe7c5e3cd0af55415f5168eb094398
|
||||||
F src/legacy.c 7e1b1c57694e49cbadf561e2a7d9cd984dc743b5
|
F src/legacy.c 7e1b1c57694e49cbadf561e2a7d9cd984dc743b5
|
||||||
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
|
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
|
||||||
F src/loadext.c 8b31e2e0e961918fa045515459aee1c122d8c266
|
F src/loadext.c 8b31e2e0e961918fa045515459aee1c122d8c266
|
||||||
@ -104,7 +104,7 @@ F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
|
|||||||
F src/mem1.c 7b023d45dd71944414db469c742457239e24d74d
|
F src/mem1.c 7b023d45dd71944414db469c742457239e24d74d
|
||||||
F src/mem2.c 48919353f72b8f6e957a0021eb9deaf863998189
|
F src/mem2.c 48919353f72b8f6e957a0021eb9deaf863998189
|
||||||
F src/mutex.c 9cf641f556a4119ef90ed41b82f2d5647f81686e
|
F src/mutex.c 9cf641f556a4119ef90ed41b82f2d5647f81686e
|
||||||
F src/os.c d8f029317c95dcd2887b9f0f154281cdfbd303ad
|
F src/os.c 86593b6e8cc22304d7c2d24b06c0aae49254b181
|
||||||
F src/os.h 399c89cafa93b9ef35c3dc70f77644d10936b535
|
F src/os.h 399c89cafa93b9ef35c3dc70f77644d10936b535
|
||||||
F src/os_common.h a5c446d3b93f09f369d13bf217de4bed3437dd1c
|
F src/os_common.h a5c446d3b93f09f369d13bf217de4bed3437dd1c
|
||||||
F src/os_os2.c 8769301bff502de642ad2634cedcb77d967ce199
|
F src/os_os2.c 8769301bff502de642ad2634cedcb77d967ce199
|
||||||
@ -136,7 +136,7 @@ F src/test2.c 4f742e99ed1bea5c14692f627bdb59a146f30504
|
|||||||
F src/test3.c a7d011c51d6b2e2a73c43983d5c2b731d69c74d7
|
F src/test3.c a7d011c51d6b2e2a73c43983d5c2b731d69c74d7
|
||||||
F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
|
F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
|
||||||
F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
|
F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
|
||||||
F src/test6.c 1191c2305c85aa192f04186b59b05a4fb40018cc
|
F src/test6.c 2c141f367ba483eef99a7f4d00f07431caff791e
|
||||||
F src/test7.c a9d509d0e9ad214b4772696f49f6e61be26213d1
|
F src/test7.c a9d509d0e9ad214b4772696f49f6e61be26213d1
|
||||||
F src/test8.c e6a543c8b248efe120ae33a6859fcd55dcf46a96
|
F src/test8.c e6a543c8b248efe120ae33a6859fcd55dcf46a96
|
||||||
F src/test9.c b46c8fe02ac7cca1a7316436d8d38d50c66f4b2f
|
F src/test9.c b46c8fe02ac7cca1a7316436d8d38d50c66f4b2f
|
||||||
@ -318,7 +318,7 @@ F test/insert3.test 72ea6056811fd234f80d923f977c196089947381
|
|||||||
F test/insert4.test 1e27f0a3e5670d5f03c1636f699aa44270945bca
|
F test/insert4.test 1e27f0a3e5670d5f03c1636f699aa44270945bca
|
||||||
F test/interrupt.test 81555fb0f8179bb2d0dc7151fd75428223f93cf2
|
F test/interrupt.test 81555fb0f8179bb2d0dc7151fd75428223f93cf2
|
||||||
F test/intpkey.test af4fd826c4784ec5c93b444de07adea0254d0d30
|
F test/intpkey.test af4fd826c4784ec5c93b444de07adea0254d0d30
|
||||||
F test/io.test 6b7ee16f78560c4b81b52da2ea1051b8a2a93ce3
|
F test/io.test ca9db7cd57a1b02cd983863c1be1153e1900e68b
|
||||||
F test/ioerr.test 491d42c49bbec598966d26b01ed7901f55e5ee2d
|
F test/ioerr.test 491d42c49bbec598966d26b01ed7901f55e5ee2d
|
||||||
F test/ioerr2.test f938eadb12108048813869b86beee4a2f98e34b8
|
F test/ioerr2.test f938eadb12108048813869b86beee4a2f98e34b8
|
||||||
F test/join.test af0443185378b64878750aa1cf4b83c216f246b4
|
F test/join.test af0443185378b64878750aa1cf4b83c216f246b4
|
||||||
@ -559,7 +559,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 21f6b31097692171c6493e6ca6de6acbd62dc595
|
P e4e74cd0f9343448ea38e57f08bb4f0616825f31
|
||||||
R eedd9c3af3e8b7da02c2c75af15e1919
|
R 630334db112909a8743c928d15787556
|
||||||
U drh
|
U danielk1977
|
||||||
Z e69a56f3f634fc877bc9bea036855b24
|
Z 01e41e90624e3bb8ea0ae5e4ad13b9f8
|
||||||
|
@ -1 +1 @@
|
|||||||
e4e74cd0f9343448ea38e57f08bb4f0616825f31
|
e2cc7b4a3476a733b2701546f6b4ec9abc18152b
|
@ -10,7 +10,7 @@
|
|||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
**
|
**
|
||||||
** @(#) $Id: journal.c,v 1.1 2007/08/22 11:22:04 danielk1977 Exp $
|
** @(#) $Id: journal.c,v 1.2 2007/08/23 08:06:45 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||||
@ -54,11 +54,14 @@ typedef struct JournalFile JournalFile;
|
|||||||
static int createFile(JournalFile *p){
|
static int createFile(JournalFile *p){
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
if( !p->pReal ){
|
if( !p->pReal ){
|
||||||
p->pReal = (sqlite3_file *)&p[1];
|
sqlite3_file *pReal = (sqlite3_file *)&p[1];
|
||||||
rc = sqlite3OsOpen(p->pVfs, p->zJournal, p->pReal, p->flags, 0);
|
rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0);
|
||||||
if( rc==SQLITE_OK && p->iSize>0 ){
|
if( rc==SQLITE_OK ){
|
||||||
assert(p->iSize<=p->nBuf);
|
p->pReal = pReal;
|
||||||
rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
|
if( p->iSize>0 ){
|
||||||
|
assert(p->iSize<=p->nBuf);
|
||||||
|
rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
36
src/os.c
36
src/os.c
@ -58,13 +58,35 @@ int sqlite3OsBreakLock(sqlite3_file *id){
|
|||||||
int sqlite3OsCheckReservedLock(sqlite3_file *id){
|
int sqlite3OsCheckReservedLock(sqlite3_file *id){
|
||||||
return id->pMethods->xCheckReservedLock(id);
|
return id->pMethods->xCheckReservedLock(id);
|
||||||
}
|
}
|
||||||
int sqlite3OsSectorSize(sqlite3_file *id){
|
|
||||||
int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
|
#ifdef SQLITE_TEST
|
||||||
return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
|
/* The following two variables are used to override the values returned
|
||||||
}
|
** by the xSectorSize() and xDeviceCharacteristics() vfs methods for
|
||||||
int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
|
** testing purposes. They are usually set by a test command implemented
|
||||||
return id->pMethods->xDeviceCharacteristics(id);
|
** in test6.c.
|
||||||
}
|
*/
|
||||||
|
int sqlite3_test_sector_size = 0;
|
||||||
|
int sqlite3_test_device_characteristics = 0;
|
||||||
|
int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
|
||||||
|
int dc = id->pMethods->xDeviceCharacteristics(id);
|
||||||
|
return dc | sqlite3_test_device_characteristics;
|
||||||
|
}
|
||||||
|
int sqlite3OsSectorSize(sqlite3_file *id){
|
||||||
|
if( sqlite3_test_sector_size==0 ){
|
||||||
|
int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
|
||||||
|
return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
|
||||||
|
}
|
||||||
|
return sqlite3_test_sector_size;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int sqlite3OsSectorSize(sqlite3_file *id){
|
||||||
|
int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
|
||||||
|
return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
|
||||||
|
}
|
||||||
|
int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
|
||||||
|
return id->pMethods->xDeviceCharacteristics(id);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
|
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
|
||||||
/* These methods are currently only used for testing and debugging. */
|
/* These methods are currently only used for testing and debugging. */
|
||||||
|
200
src/test6.c
200
src/test6.c
@ -540,6 +540,98 @@ static int cfCurrentTime(void *pAppData, double *pTimeOut){
|
|||||||
return pVfs->xCurrentTime(pVfs->pAppData, pTimeOut);
|
return pVfs->xCurrentTime(pVfs->pAppData, pTimeOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int processDevSymArgs(
|
||||||
|
Tcl_Interp *interp,
|
||||||
|
int objc,
|
||||||
|
Tcl_Obj *CONST objv[],
|
||||||
|
int *piDeviceChar,
|
||||||
|
int *piSectorSize
|
||||||
|
){
|
||||||
|
struct DeviceFlag {
|
||||||
|
char *zName;
|
||||||
|
int iValue;
|
||||||
|
} aFlag[] = {
|
||||||
|
{ "atomic", SQLITE_IOCAP_ATOMIC },
|
||||||
|
{ "atomic512", SQLITE_IOCAP_ATOMIC512 },
|
||||||
|
{ "atomic1k", SQLITE_IOCAP_ATOMIC1K },
|
||||||
|
{ "atomic2k", SQLITE_IOCAP_ATOMIC2K },
|
||||||
|
{ "atomic4k", SQLITE_IOCAP_ATOMIC4K },
|
||||||
|
{ "atomic8k", SQLITE_IOCAP_ATOMIC8K },
|
||||||
|
{ "atomic16k", SQLITE_IOCAP_ATOMIC16K },
|
||||||
|
{ "atomic32k", SQLITE_IOCAP_ATOMIC32K },
|
||||||
|
{ "atomic64k", SQLITE_IOCAP_ATOMIC64K },
|
||||||
|
{ "sequential", SQLITE_IOCAP_SEQUENTIAL },
|
||||||
|
{ "safe_append", SQLITE_IOCAP_SAFE_APPEND },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int iDc = 0;
|
||||||
|
int iSectorSize = 0;
|
||||||
|
int setSectorsize = 0;
|
||||||
|
int setDeviceChar = 0;
|
||||||
|
|
||||||
|
for(i=0; i<objc; i+=2){
|
||||||
|
int nOpt;
|
||||||
|
char *zOpt = Tcl_GetStringFromObj(objv[i], &nOpt);
|
||||||
|
|
||||||
|
if( (nOpt>11 || nOpt<2 || strncmp("-sectorsize", zOpt, nOpt))
|
||||||
|
&& (nOpt>16 || nOpt<2 || strncmp("-characteristics", zOpt, nOpt))
|
||||||
|
){
|
||||||
|
Tcl_AppendResult(interp,
|
||||||
|
"Bad option: \"", zOpt,
|
||||||
|
"\" - must be \"-characteristics\" or \"-sectorsize\"", 0
|
||||||
|
);
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
if( i==objc-1 ){
|
||||||
|
Tcl_AppendResult(interp, "Option requires an argument: \"", zOpt, "\"",0);
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( zOpt[1]=='s' ){
|
||||||
|
if( Tcl_GetIntFromObj(interp, objv[i+1], &iSectorSize) ){
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
setSectorsize = 1;
|
||||||
|
}else{
|
||||||
|
int j;
|
||||||
|
Tcl_Obj **apObj;
|
||||||
|
int nObj;
|
||||||
|
if( Tcl_ListObjGetElements(interp, objv[i+1], &nObj, &apObj) ){
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
for(j=0; j<nObj; j++){
|
||||||
|
int rc;
|
||||||
|
int iChoice;
|
||||||
|
Tcl_Obj *pFlag = Tcl_DuplicateObj(apObj[j]);
|
||||||
|
Tcl_IncrRefCount(pFlag);
|
||||||
|
Tcl_UtfToLower(Tcl_GetString(pFlag));
|
||||||
|
|
||||||
|
rc = Tcl_GetIndexFromObjStruct(
|
||||||
|
interp, pFlag, aFlag, sizeof(aFlag[0]), "no such flag", 0, &iChoice
|
||||||
|
);
|
||||||
|
Tcl_DecrRefCount(pFlag);
|
||||||
|
if( rc ){
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
iDc |= aFlag[iChoice].iValue;
|
||||||
|
}
|
||||||
|
setDeviceChar = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( setDeviceChar ){
|
||||||
|
*piDeviceChar = iDc;
|
||||||
|
}
|
||||||
|
if( setSectorsize ){
|
||||||
|
*piSectorSize = iSectorSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TCL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** tclcmd: sqlite_crashparams ?OPTIONS? DELAY CRASHFILE
|
** tclcmd: sqlite_crashparams ?OPTIONS? DELAY CRASHFILE
|
||||||
**
|
**
|
||||||
@ -564,7 +656,6 @@ static int crashParamsObjCmd(
|
|||||||
int objc,
|
int objc,
|
||||||
Tcl_Obj *CONST objv[]
|
Tcl_Obj *CONST objv[]
|
||||||
){
|
){
|
||||||
int i;
|
|
||||||
int iDelay;
|
int iDelay;
|
||||||
const char *zCrashFile;
|
const char *zCrashFile;
|
||||||
int nCrashFile;
|
int nCrashFile;
|
||||||
@ -606,29 +697,9 @@ static int crashParamsObjCmd(
|
|||||||
sqlite3_vfs_register(&crashVfs, 1);
|
sqlite3_vfs_register(&crashVfs, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int iDc = 0;
|
int iDc = -1;
|
||||||
int iSectorSize = 0;
|
int iSectorSize = -1;
|
||||||
int setSectorsize = 0;
|
|
||||||
int setDeviceChar = 0;
|
|
||||||
|
|
||||||
struct DeviceFlag {
|
|
||||||
char *zName;
|
|
||||||
int iValue;
|
|
||||||
} aFlag[] = {
|
|
||||||
{ "atomic", SQLITE_IOCAP_ATOMIC },
|
|
||||||
{ "atomic512", SQLITE_IOCAP_ATOMIC512 },
|
|
||||||
{ "atomic1k", SQLITE_IOCAP_ATOMIC1K },
|
|
||||||
{ "atomic2k", SQLITE_IOCAP_ATOMIC2K },
|
|
||||||
{ "atomic4k", SQLITE_IOCAP_ATOMIC4K },
|
|
||||||
{ "atomic8k", SQLITE_IOCAP_ATOMIC8K },
|
|
||||||
{ "atomic16k", SQLITE_IOCAP_ATOMIC16K },
|
|
||||||
{ "atomic32k", SQLITE_IOCAP_ATOMIC32K },
|
|
||||||
{ "atomic64k", SQLITE_IOCAP_ATOMIC64K },
|
|
||||||
{ "sequential", SQLITE_IOCAP_SEQUENTIAL },
|
|
||||||
{ "safe_append", SQLITE_IOCAP_SAFE_APPEND },
|
|
||||||
{ 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
if( objc<3 ){
|
if( objc<3 ){
|
||||||
Tcl_WrongNumArgs(interp, 1, objv, "?OPTIONS? DELAY CRASHFILE");
|
Tcl_WrongNumArgs(interp, 1, objv, "?OPTIONS? DELAY CRASHFILE");
|
||||||
goto error;
|
goto error;
|
||||||
@ -643,63 +714,17 @@ static int crashParamsObjCmd(
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=1; i<(objc-2); i+=2){
|
if( processDevSymArgs(interp, objc-3, &objv[1], &iDc, &iSectorSize) ){
|
||||||
int nOpt;
|
return TCL_ERROR;
|
||||||
char *zOpt = Tcl_GetStringFromObj(objv[i], &nOpt);
|
|
||||||
|
|
||||||
if( (nOpt>11 || nOpt<2 || strncmp("-sectorsize", zOpt, nOpt))
|
|
||||||
&& (nOpt>16 || nOpt<2 || strncmp("-characteristics", zOpt, nOpt))
|
|
||||||
){
|
|
||||||
Tcl_AppendResult(interp,
|
|
||||||
"Bad option: \"", zOpt,
|
|
||||||
"\" - must be \"-characteristics\" or \"-sectorsize\"", 0
|
|
||||||
);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if( i==objc-3 ){
|
|
||||||
Tcl_AppendResult(interp, "Option requires an argument: \"", zOpt, "\"",0);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( zOpt[1]=='s' ){
|
|
||||||
if( Tcl_GetIntFromObj(interp, objv[i+1], &iSectorSize) ){
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
setSectorsize = 1;
|
|
||||||
}else{
|
|
||||||
int j;
|
|
||||||
Tcl_Obj **apObj;
|
|
||||||
int nObj;
|
|
||||||
if( Tcl_ListObjGetElements(interp, objv[i+1], &nObj, &apObj) ){
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
for(j=0; j<nObj; j++){
|
|
||||||
int rc;
|
|
||||||
int iChoice;
|
|
||||||
Tcl_Obj *pFlag = Tcl_DuplicateObj(apObj[j]);
|
|
||||||
Tcl_IncrRefCount(pFlag);
|
|
||||||
Tcl_UtfToLower(Tcl_GetString(pFlag));
|
|
||||||
|
|
||||||
rc = Tcl_GetIndexFromObjStruct(
|
|
||||||
interp, pFlag, aFlag, sizeof(aFlag[0]), "no such flag", 0, &iChoice
|
|
||||||
);
|
|
||||||
Tcl_DecrRefCount(pFlag);
|
|
||||||
if( rc ){
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
iDc |= aFlag[iChoice].iValue;
|
|
||||||
}
|
|
||||||
setDeviceChar = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( setDeviceChar ){
|
if( iDc>=0 ){
|
||||||
g.iDeviceCharacteristics = iDc;
|
g.iDeviceCharacteristics = iDc;
|
||||||
}
|
}
|
||||||
if( setSectorsize ){
|
if( iSectorSize>=0 ){
|
||||||
g.iSectorSize = iSectorSize;
|
g.iSectorSize = iSectorSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
g.iCrash = iDelay;
|
g.iCrash = iDelay;
|
||||||
memcpy(g.zCrashFile, zCrashFile, nCrashFile+1);
|
memcpy(g.zCrashFile, zCrashFile, nCrashFile+1);
|
||||||
sqlite3CrashTestEnable = 1;
|
sqlite3CrashTestEnable = 1;
|
||||||
@ -709,6 +734,32 @@ error:
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int devSymObjCmd(
|
||||||
|
void * clientData,
|
||||||
|
Tcl_Interp *interp,
|
||||||
|
int objc,
|
||||||
|
Tcl_Obj *CONST objv[]
|
||||||
|
){
|
||||||
|
|
||||||
|
extern int sqlite3_test_device_characteristics;
|
||||||
|
extern int sqlite3_test_sector_size;
|
||||||
|
|
||||||
|
int iDc = -1;
|
||||||
|
int iSectorSize = -1;
|
||||||
|
if( processDevSymArgs(interp, objc-1, &objv[1], &iDc, &iSectorSize) ){
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( iDc>=0 ){
|
||||||
|
sqlite3_test_device_characteristics = iDc;
|
||||||
|
}
|
||||||
|
if( iSectorSize>=0 ){
|
||||||
|
sqlite3_test_sector_size = iSectorSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TCL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* SQLITE_OMIT_DISKIO */
|
#endif /* SQLITE_OMIT_DISKIO */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -717,6 +768,7 @@ error:
|
|||||||
int Sqlitetest6_Init(Tcl_Interp *interp){
|
int Sqlitetest6_Init(Tcl_Interp *interp){
|
||||||
#ifndef SQLITE_OMIT_DISKIO
|
#ifndef SQLITE_OMIT_DISKIO
|
||||||
Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
|
Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
|
||||||
|
Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
|
188
test/io.test
188
test/io.test
@ -13,11 +13,18 @@
|
|||||||
# IO traffic generated by SQLite (making sure SQLite is not writing out
|
# IO traffic generated by SQLite (making sure SQLite is not writing out
|
||||||
# more database pages than it has to, stuff like that).
|
# more database pages than it has to, stuff like that).
|
||||||
#
|
#
|
||||||
# $Id: io.test,v 1.2 2007/08/22 02:56:44 drh Exp $
|
# $Id: io.test,v 1.3 2007/08/23 08:06:45 danielk1977 Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
|
|
||||||
|
# Test summary:
|
||||||
|
#
|
||||||
|
# io-1.* - Test that quick-balance does not journal pages unnecessarily.
|
||||||
|
# io-2.* - Test that when the atomic-write optimisation is used no
|
||||||
|
# journal file is created.
|
||||||
|
#
|
||||||
|
|
||||||
set ::nWrite 0
|
set ::nWrite 0
|
||||||
proc nWrite {db} {
|
proc nWrite {db} {
|
||||||
set bt [btree_from_db $db]
|
set bt [btree_from_db $db]
|
||||||
@ -29,6 +36,13 @@ proc nWrite {db} {
|
|||||||
set res
|
set res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set ::nSync 0
|
||||||
|
proc nSync {} {
|
||||||
|
set res [expr {$::sqlite_sync_count - $::nSync}]
|
||||||
|
set ::nSync $::sqlite_sync_count
|
||||||
|
set res
|
||||||
|
}
|
||||||
|
|
||||||
do_test io-1.1 {
|
do_test io-1.1 {
|
||||||
execsql {
|
execsql {
|
||||||
PRAGMA page_size = 1024;
|
PRAGMA page_size = 1024;
|
||||||
@ -75,8 +89,6 @@ do_test io-1.4 {
|
|||||||
lappend ret [nWrite db]
|
lappend ret [nWrite db]
|
||||||
} {2 2 2}
|
} {2 2 2}
|
||||||
|
|
||||||
#db eval {select * from sqlite_master} {btree_tree_dump [btree_from_db db] 2}
|
|
||||||
|
|
||||||
# This insert should use the quick-balance trick to add a third leaf
|
# This insert should use the quick-balance trick to add a third leaf
|
||||||
# to the b-tree used to store table abc. It should only be necessary to
|
# to the b-tree used to store table abc. It should only be necessary to
|
||||||
# write to 3 pages to do this: the change-counter, the root-page and
|
# write to 3 pages to do this: the change-counter, the root-page and
|
||||||
@ -86,6 +98,174 @@ do_test io-1.5 {
|
|||||||
nWrite db
|
nWrite db
|
||||||
} {3}
|
} {3}
|
||||||
|
|
||||||
#db eval {select * from sqlite_master} {btree_tree_dump [btree_from_db db] 2}
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# Test cases io-2.* test the atomic-write optimization.
|
||||||
|
#
|
||||||
|
do_test io-2.1 {
|
||||||
|
execsql { DELETE FROM abc; VACUUM; }
|
||||||
|
} {}
|
||||||
|
|
||||||
|
# Clear the write and sync counts.
|
||||||
|
nWrite db ; nSync
|
||||||
|
|
||||||
|
# The following INSERT updates 2 pages and requires 4 calls to fsync():
|
||||||
|
#
|
||||||
|
# 1) The directory in which the journal file is created,
|
||||||
|
# 2) The journal file (to sync the page data),
|
||||||
|
# 3) The journal file (to sync the journal file header),
|
||||||
|
# 4) The database file.
|
||||||
|
#
|
||||||
|
do_test io-2.2 {
|
||||||
|
execsql { INSERT INTO abc VALUES(1, 2) }
|
||||||
|
list [nWrite db] [nSync]
|
||||||
|
} {2 4}
|
||||||
|
|
||||||
|
# Set the device-characteristic mask to include the SQLITE_IOCAP_ATOMIC,
|
||||||
|
# then do another INSERT similar to the one in io-2.2. This should
|
||||||
|
# only write 1 page and require a single fsync().
|
||||||
|
#
|
||||||
|
# The single fsync() is the database file. Only one page is reported as
|
||||||
|
# written because page 1 - the change-counter page - is written using
|
||||||
|
# an out-of-band method that bypasses the write counter.
|
||||||
|
#
|
||||||
|
sqlite3_simulate_device -char atomic
|
||||||
|
do_test io-2.3 {
|
||||||
|
execsql { INSERT INTO abc VALUES(3, 4) }
|
||||||
|
list [nWrite db] [nSync]
|
||||||
|
} {1 1}
|
||||||
|
|
||||||
|
# Test that the journal file is not created and the change-counter is
|
||||||
|
# updated when the atomic-write optimization is used.
|
||||||
|
#
|
||||||
|
do_test io-2.4.1 {
|
||||||
|
execsql {
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO abc VALUES(5, 6);
|
||||||
|
}
|
||||||
|
sqlite3 db2 test.db
|
||||||
|
execsql { SELECT * FROM abc } db2
|
||||||
|
} {1 2 3 4}
|
||||||
|
do_test io-2.4.2 {
|
||||||
|
file exists test.db-journal
|
||||||
|
} {0}
|
||||||
|
do_test io-2.4.3 {
|
||||||
|
execsql { COMMIT }
|
||||||
|
execsql { SELECT * FROM abc } db2
|
||||||
|
} {1 2 3 4 5 6}
|
||||||
|
db2 close
|
||||||
|
|
||||||
|
# Test that the journal file is created and sync()d if the transaction
|
||||||
|
# modifies more than one database page, even if the IOCAP_ATOMIC flag
|
||||||
|
# is set.
|
||||||
|
#
|
||||||
|
do_test io-2.5.1 {
|
||||||
|
execsql { CREATE TABLE def(d, e) }
|
||||||
|
nWrite db ; nSync
|
||||||
|
execsql {
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO abc VALUES(7, 8);
|
||||||
|
}
|
||||||
|
file exists test.db-journal
|
||||||
|
} {0}
|
||||||
|
do_test io-2.5.2 {
|
||||||
|
execsql { INSERT INTO def VALUES('a', 'b'); }
|
||||||
|
file exists test.db-journal
|
||||||
|
} {1}
|
||||||
|
do_test io-2.5.3 {
|
||||||
|
execsql { COMMIT }
|
||||||
|
list [nWrite db] [nSync]
|
||||||
|
} {3 4}
|
||||||
|
|
||||||
|
# Test that the journal file is created and sync()d if the transaction
|
||||||
|
# modifies a single database page and also appends a page to the file.
|
||||||
|
# Internally, this case is handled differently to the one above. The
|
||||||
|
# journal file is not actually created until the 'COMMIT' statement
|
||||||
|
# is executed.
|
||||||
|
#
|
||||||
|
do_test io-2.6.1 {
|
||||||
|
execsql {
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO abc VALUES(9, randstr(1000,1000));
|
||||||
|
}
|
||||||
|
file exists test.db-journal
|
||||||
|
} {0}
|
||||||
|
do_test io-2.6.2 {
|
||||||
|
# Create a file at "test.db-journal". This will prevent SQLite from
|
||||||
|
# opening the journal for exclusive access. As a result, the COMMIT
|
||||||
|
# should fail with SQLITE_CANTOPEN and the transaction rolled back.
|
||||||
|
#
|
||||||
|
set fd [open test.db-journal w]
|
||||||
|
puts $fd "This is not a journal file"
|
||||||
|
close $fd
|
||||||
|
catchsql { COMMIT }
|
||||||
|
} {1 {unable to open database file}}
|
||||||
|
do_test io-2.6.3 {
|
||||||
|
file delete -force test.db-journal
|
||||||
|
catchsql { COMMIT }
|
||||||
|
} {1 {cannot commit - no transaction is active}}
|
||||||
|
do_test io-2.6.4 {
|
||||||
|
execsql { SELECT * FROM abc }
|
||||||
|
} {1 2 3 4 5 6 7 8}
|
||||||
|
|
||||||
|
|
||||||
|
# Test that if the database modification is part of multi-file commit,
|
||||||
|
# the journal file is always created. In this case, the journal file
|
||||||
|
# is created during execution of the COMMIT statement, so we have to
|
||||||
|
# use the same technique to check that it is created as in the above
|
||||||
|
# block.
|
||||||
|
file delete -force test2.db test2.db-journal
|
||||||
|
do_test io-2.7.1 {
|
||||||
|
execsql {
|
||||||
|
ATTACH 'test2.db' AS aux;
|
||||||
|
CREATE TABLE aux.abc2(a, b);
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO abc VALUES(9, 10);
|
||||||
|
}
|
||||||
|
file exists test.db-journal
|
||||||
|
} {0}
|
||||||
|
do_test io-2.7.2 {
|
||||||
|
execsql { INSERT INTO abc2 SELECT * FROM abc }
|
||||||
|
file exists test2.db-journal
|
||||||
|
} {0}
|
||||||
|
do_test io-2.7.3 {
|
||||||
|
execsql { SELECT * FROM abc UNION ALL SELECT * FROM abc2 }
|
||||||
|
} {1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10}
|
||||||
|
do_test io-2.7.4 {
|
||||||
|
set fd [open test2.db-journal w]
|
||||||
|
puts $fd "This is not a journal file"
|
||||||
|
close $fd
|
||||||
|
catchsql { COMMIT }
|
||||||
|
} {1 {unable to open database file}}
|
||||||
|
do_test io-2.7.5 {
|
||||||
|
file delete -force test2.db-journal
|
||||||
|
catchsql { COMMIT }
|
||||||
|
} {1 {cannot commit - no transaction is active}}
|
||||||
|
do_test io-2.7.6 {
|
||||||
|
execsql { SELECT * FROM abc UNION ALL SELECT * FROM abc2 }
|
||||||
|
} {1 2 3 4 5 6 7 8}
|
||||||
|
|
||||||
|
# Try an explicit ROLLBACK before the journal file is created.
|
||||||
|
#
|
||||||
|
do_test io-2.8.1 {
|
||||||
|
execsql {
|
||||||
|
BEGIN;
|
||||||
|
DELETE FROM abc;
|
||||||
|
}
|
||||||
|
file exists test.db-journal
|
||||||
|
} {0}
|
||||||
|
do_test io-2.8.2 {
|
||||||
|
execsql { SELECT * FROM abc }
|
||||||
|
} {}
|
||||||
|
do_test io-2.8.3 {
|
||||||
|
execsql {
|
||||||
|
ROLLBACK;
|
||||||
|
SELECT * FROM abc;
|
||||||
|
}
|
||||||
|
} {1 2 3 4 5 6 7 8}
|
||||||
|
|
||||||
|
sqlite3_simulate_device -char {} -sectorsize 0
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user