Modify the crash-recovery test code in test6.c for 3.5. Also change some other code to use the new sqlite3_io_methods interface. Lots of things are broken now. (CVS 4228)
FossilOrigin-Name: af9503daf3f7703fcddad754bc1dc9e179830b6e
This commit is contained in:
parent
4c3645c601
commit
6207906027
28
manifest
28
manifest
@ -1,5 +1,5 @@
|
||||
C Add\sa\sdebugging\smemory\sallocator.\s(CVS\s4227)
|
||||
D 2007-08-15T17:07:57
|
||||
C Modify\sthe\scrash-recovery\stest\scode\sin\stest6.c\sfor\s3.5.\sAlso\schange\ssome\sother\scode\sto\suse\sthe\snew\ssqlite3_io_methods\sinterface.\sLots\sof\sthings\sare\sbroken\snow.\s(CVS\s4228)
|
||||
D 2007-08-15T17:08:46
|
||||
F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe
|
||||
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@ -91,18 +91,18 @@ F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
|
||||
F src/mem1.c ef73642a171d174cd556d0168f8edbceaf94933b
|
||||
F src/mem2.c b8173ddcca23e99829617185154a35a6f046b214
|
||||
F src/mutex.c 667dae0de95f8fb92a3ffc8c3f20c0d26115a1a6
|
||||
F src/os.c 1f10b47acc1177fb9225edb4f5f0d25ed716f9cb
|
||||
F src/os.h cea2e179bb33f4fc09dbb9fcd51b2246544bd2db
|
||||
F src/os.c e2faefbe0f5a8ca5e3b1c49ee1b5c6cfa0f0e279
|
||||
F src/os.h 8eff07babf74e5bc3f895f8a6c7c294dad5ff997
|
||||
F src/os_common.h a5c446d3b93f09f369d13bf217de4bed3437dd1c
|
||||
F src/os_os2.c cba4e96fadb949076c717108fe0599d1a3c2e446
|
||||
F src/os_os2.h e5f17dd69333632bbc3112881ea407c37d245eb3
|
||||
F src/os_test.c 49833426101f99aee4bb5f6a44b7c4b2029fda1c
|
||||
F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3
|
||||
F src/os_unix.c 9d2a421acc607262e63ccf31e3fe86e5f2520af6
|
||||
F src/os_unix.c 05ad65c32b4937fd47b17b472955aa5dfc438074
|
||||
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
|
||||
F src/os_win.c d868d5f9e95ec9c1b9e2a30c54c996053db6dddd
|
||||
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c cdf561d3ae4009be902df714da4518dc3522e206
|
||||
F src/pager.c 05ea9dcbc4de4e9d9ca332ca1f8a9ba65fe2cbf5
|
||||
F src/pager.h 94110a5570dca30d54a883e880a3633b2e4c05ae
|
||||
F src/parse.y ad2ce25665be7f7303137f774a4e3e72e0d036ff
|
||||
F src/pragma.c 7914a6b9ea05f158800116dfcae11e52ab8e39c4
|
||||
@ -112,18 +112,18 @@ F src/random.c 6119474a6f6917f708c1dee25b9a8e519a620e88
|
||||
F src/select.c 3b167744fc375bddfddcef87feb18f5171737677
|
||||
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||
F src/shell.c ac29402b538515fa4697282387be9c1205e6e9eb
|
||||
F src/sqlite.h.in 025e9fd6c519f2945296a9db46ca9da4571c22d7
|
||||
F src/sqlite.h.in 165913eb3426fbaa8a2a51d87f84593bfe5bee15
|
||||
F src/sqlite3ext.h a27bedc222df5e5f0f458ac99726d0483b953a91
|
||||
F src/sqliteInt.h fc9f6e8d916e182c04983a089c4ce4057fac5003
|
||||
F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa
|
||||
F src/table.c a8de75bcedf84d4060d804264b067ab3b1a3561d
|
||||
F src/tclsqlite.c 648e6f53041ce4974234d4963e71680926760925
|
||||
F src/test1.c 94bd41c24a4d8d782e39c1275421511587d8b293
|
||||
F src/test2.c 24458b17ab2f3c90cbc1c8446bd7ffe69be62f88
|
||||
F src/test2.c 5c3edc610852a8f67990cd08c5d5dbb79e3f8db9
|
||||
F src/test3.c a280931fb40222b7c90da45eea926459beee8904
|
||||
F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
|
||||
F src/test5.c c40a4cf43266c1c6da7bcb737d294304a177e6cc
|
||||
F src/test6.c 2c4ed21787944bd8896cba80d4a544d8bed5473e
|
||||
F src/test6.c 4d812a5ea1fe08693f4189bfc974b341102a3bea
|
||||
F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3
|
||||
F src/test8.c 27a61c60f736066646a9e9ca21acdfdf0f3ea11e
|
||||
F src/test9.c c0f38f7795cc51d37db6c63874d90f40f10d0f0e
|
||||
@ -147,7 +147,7 @@ F src/vdbe.c cf973bd1af5fbda845b0f759bb06eb19ff42e215
|
||||
F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3
|
||||
F src/vdbeInt.h c3514903cad9e36d6b3242be20261351d09db56c
|
||||
F src/vdbeapi.c 220b81132abaf0f620edb8da48799a77daef12a7
|
||||
F src/vdbeaux.c d626e0f8cd78b4280bcb7af25d5c5566348ba87a
|
||||
F src/vdbeaux.c 8e6dbe3dac3bdd7d37c87ba553059b5251ba07e5
|
||||
F src/vdbeblob.c bb30b3e387c35ba869949494b2736aff97159470
|
||||
F src/vdbefifo.c 3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f
|
||||
F src/vdbemem.c ca4d3994507cb0a9504820293af69f5c778b4abd
|
||||
@ -528,7 +528,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P c0fa3769790af199a4c8715c80bb8ff900730520
|
||||
R afa459b840a3b96de70924b91a0e1dbb
|
||||
U drh
|
||||
Z 9341f1481e29775e7a036e24546ed5fc
|
||||
P 8d2d1c4ff9dca61f75e3048107ee9712d346a28c
|
||||
R 7d9819ae0c3408fa1555b7b8d9a48850
|
||||
U danielk1977
|
||||
Z 41f21c80ce49e631fe5dbf7930bb9145
|
||||
|
@ -1 +1 @@
|
||||
8d2d1c4ff9dca61f75e3048107ee9712d346a28c
|
||||
af9503daf3f7703fcddad754bc1dc9e179830b6e
|
74
src/os.c
74
src/os.c
@ -20,63 +20,65 @@
|
||||
|
||||
/*
|
||||
** The following routines are convenience wrappers around methods
|
||||
** of the OsFile object. This is mostly just syntactic sugar. All
|
||||
** of the sqlite3_file object. This is mostly just syntactic sugar. All
|
||||
** of this would be completely automatic if SQLite were coded using
|
||||
** C++ instead of plain old C.
|
||||
*/
|
||||
int sqlite3OsClose(OsFile **pId){
|
||||
OsFile *id;
|
||||
int sqlite3OsClose(sqlite3_file **pId){
|
||||
int rc = SQLITE_OK;
|
||||
sqlite3_file *id;
|
||||
if( pId!=0 && (id = *pId)!=0 ){
|
||||
return id->pMethod->xClose(pId);
|
||||
}else{
|
||||
return SQLITE_OK;
|
||||
rc = id->pMethods->xClose(id);
|
||||
if( rc==SQLITE_OK ){
|
||||
*pId = 0;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3OsOpenDirectory(OsFile *id, const char *zName){
|
||||
return id->pMethod->xOpenDirectory(id, zName);
|
||||
int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
|
||||
return id->pMethods->xRead(id, pBuf, amt, offset);
|
||||
}
|
||||
int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
|
||||
return id->pMethod->xRead(id, pBuf, amt);
|
||||
int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
|
||||
return id->pMethods->xWrite(id, pBuf, amt, offset);
|
||||
}
|
||||
int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
|
||||
return id->pMethod->xWrite(id, pBuf, amt);
|
||||
int sqlite3OsTruncate(sqlite3_file *id, i64 size){
|
||||
return id->pMethods->xTruncate(id, size);
|
||||
}
|
||||
int sqlite3OsSeek(OsFile *id, i64 offset){
|
||||
return id->pMethod->xSeek(id, offset);
|
||||
int sqlite3OsSync(sqlite3_file *id, int fullsync){
|
||||
return id->pMethods->xSync(id, fullsync);
|
||||
}
|
||||
int sqlite3OsTruncate(OsFile *id, i64 size){
|
||||
return id->pMethod->xTruncate(id, size);
|
||||
int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
|
||||
return id->pMethods->xFileSize(id, pSize);
|
||||
}
|
||||
int sqlite3OsSync(OsFile *id, int fullsync){
|
||||
return id->pMethod->xSync(id, fullsync);
|
||||
int sqlite3OsLock(sqlite3_file *id, int lockType){
|
||||
return id->pMethods->xLock(id, lockType);
|
||||
}
|
||||
void sqlite3OsSetFullSync(OsFile *id, int value){
|
||||
id->pMethod->xSetFullSync(id, value);
|
||||
int sqlite3OsUnlock(sqlite3_file *id, int lockType){
|
||||
return id->pMethods->xUnlock(id, lockType);
|
||||
}
|
||||
int sqlite3OsFileSize(OsFile *id, i64 *pSize){
|
||||
return id->pMethod->xFileSize(id, pSize);
|
||||
int sqlite3OsBreakLock(sqlite3_file *id){
|
||||
return id->pMethods->xBreakLock(id);
|
||||
}
|
||||
int sqlite3OsLock(OsFile *id, int lockType){
|
||||
return id->pMethod->xLock(id, lockType);
|
||||
int sqlite3OsCheckReservedLock(sqlite3_file *id){
|
||||
return id->pMethods->xCheckReservedLock(id);
|
||||
}
|
||||
int sqlite3OsUnlock(OsFile *id, int lockType){
|
||||
return id->pMethod->xUnlock(id, lockType);
|
||||
}
|
||||
int sqlite3OsCheckReservedLock(OsFile *id){
|
||||
return id->pMethod->xCheckReservedLock(id);
|
||||
}
|
||||
int sqlite3OsSectorSize(OsFile *id){
|
||||
int (*xSectorSize)(OsFile*) = id->pMethod->xSectorSize;
|
||||
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);
|
||||
}
|
||||
|
||||
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
|
||||
/* These methods are currently only used for testing and debugging. */
|
||||
int sqlite3OsFileHandle(OsFile *id){
|
||||
return id->pMethod->xFileHandle(id);
|
||||
int sqlite3OsFileHandle(sqlite3_file *id){
|
||||
/* return id->pMethods->xFileHandle(id); */
|
||||
return 0;
|
||||
}
|
||||
int sqlite3OsLockState(OsFile *id){
|
||||
return id->pMethod->xLockState(id);
|
||||
int sqlite3OsLockState(sqlite3_file *id){
|
||||
/* return id->pMethods->xLockState(id); */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
43
src/os.h
43
src/os.h
@ -348,27 +348,28 @@ extern unsigned int sqlite3_pending_byte;
|
||||
/*
|
||||
** Prototypes for operating system interface routines.
|
||||
*/
|
||||
int sqlite3OsClose(OsFile**);
|
||||
int sqlite3OsOpenDirectory(OsFile*, const char*);
|
||||
int sqlite3OsRead(OsFile*, void*, int amt);
|
||||
int sqlite3OsWrite(OsFile*, const void*, int amt);
|
||||
int sqlite3OsSeek(OsFile*, i64 offset);
|
||||
int sqlite3OsTruncate(OsFile*, i64 size);
|
||||
int sqlite3OsSync(OsFile*, int);
|
||||
void sqlite3OsSetFullSync(OsFile *id, int setting);
|
||||
int sqlite3OsFileSize(OsFile*, i64 *pSize);
|
||||
int sqlite3OsLock(OsFile*, int);
|
||||
int sqlite3OsUnlock(OsFile*, int);
|
||||
int sqlite3OsCheckReservedLock(OsFile *id);
|
||||
int sqlite3OsOpenReadWrite(const char*, OsFile**, int*);
|
||||
int sqlite3OsOpenExclusive(const char*, OsFile**, int);
|
||||
int sqlite3OsOpenReadOnly(const char*, OsFile**);
|
||||
int sqlite3OsClose(sqlite3_file**);
|
||||
int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
|
||||
int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
|
||||
int sqlite3OsTruncate(sqlite3_file*, i64 size);
|
||||
int sqlite3OsSync(sqlite3_file*, int);
|
||||
int sqlite3OsFileSize(sqlite3_file*, i64 *pSize);
|
||||
int sqlite3OsLock(sqlite3_file*, int);
|
||||
int sqlite3OsUnlock(sqlite3_file*, int);
|
||||
int sqlite3OsBreakLock(sqlite3_file*);
|
||||
int sqlite3OsCheckReservedLock(sqlite3_file *id);
|
||||
int sqlite3OsSectorSize(sqlite3_file *id);
|
||||
int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
|
||||
|
||||
int sqlite3OsOpenReadWrite(const char*, sqlite3_file**, int*);
|
||||
int sqlite3OsOpenExclusive(const char*, sqlite3_file**, int);
|
||||
int sqlite3OsOpenReadOnly(const char*, sqlite3_file**);
|
||||
|
||||
int sqlite3OsDelete(const char*);
|
||||
int sqlite3OsFileExists(const char*);
|
||||
char *sqlite3OsFullPathname(const char*);
|
||||
int sqlite3OsIsDirWritable(char*);
|
||||
int sqlite3OsSyncDirectory(const char*);
|
||||
int sqlite3OsSectorSize(OsFile *id);
|
||||
int sqlite3OsTempFileName(char*);
|
||||
int sqlite3OsRandomSeed(char*);
|
||||
int sqlite3OsSleep(int ms);
|
||||
@ -386,8 +387,8 @@ void *sqlite3OsDlsym(void*, const char*);
|
||||
int sqlite3OsDlclose(void*);
|
||||
|
||||
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
|
||||
int sqlite3OsFileHandle(OsFile *id);
|
||||
int sqlite3OsLockState(OsFile *id);
|
||||
int sqlite3OsFileHandle(sqlite3_file *id);
|
||||
int sqlite3OsLockState(sqlite3_file *id);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -409,9 +410,9 @@ int sqlite3OsDlclose(void*);
|
||||
** operating system interfaces or behaviors.
|
||||
*/
|
||||
struct sqlite3OsVtbl {
|
||||
int (*xOpenReadWrite)(const char*, OsFile**, int*);
|
||||
int (*xOpenExclusive)(const char*, OsFile**, int);
|
||||
int (*xOpenReadOnly)(const char*, OsFile**);
|
||||
int (*xOpenReadWrite)(const char*, sqlite3_file**, int*);
|
||||
int (*xOpenExclusive)(const char*, sqlite3_file**, int);
|
||||
int (*xOpenReadOnly)(const char*, sqlite3_file**);
|
||||
|
||||
int (*xDelete)(const char*);
|
||||
int (*xFileExists)(const char*);
|
||||
|
159
src/os_unix.c
159
src/os_unix.c
@ -82,7 +82,7 @@
|
||||
*/
|
||||
typedef struct unixFile unixFile;
|
||||
struct unixFile {
|
||||
IoMethod const *pMethod; /* Always the first entry */
|
||||
sqlite3_io_methods const *pMethod; /* Always the first entry */
|
||||
struct openCnt *pOpen; /* Info about all open fd's on this inode */
|
||||
struct lockInfo *pLock; /* Info about locks on this inode */
|
||||
#ifdef SQLITE_ENABLE_LOCKING_STYLE
|
||||
@ -99,6 +99,7 @@ struct unixFile {
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Provide the ability to override some OS-layer functions during
|
||||
** testing. This is used to simulate OS crashes to verify that
|
||||
@ -106,13 +107,15 @@ struct unixFile {
|
||||
*/
|
||||
#ifdef SQLITE_CRASH_TEST
|
||||
extern int sqlite3CrashTestEnable;
|
||||
extern int sqlite3CrashOpenReadWrite(const char*, OsFile**, int*);
|
||||
extern int sqlite3CrashOpenExclusive(const char*, OsFile**, int);
|
||||
extern int sqlite3CrashOpenReadOnly(const char*, OsFile**, int);
|
||||
# define CRASH_TEST_OVERRIDE(X,A,B,C) \
|
||||
if(sqlite3CrashTestEnable){ return X(A,B,C); }
|
||||
int sqlite3CrashFileWrap(sqlite3_file *, const char *, sqlite3_file **);
|
||||
static int CRASH_TEST_OVERRIDE(const char *zFile, sqlite3_file **pId, int rc){
|
||||
if( rc==SQLITE_OK && sqlite3CrashTestEnable ){
|
||||
rc = sqlite3CrashFileWrap(*pId, zFile, pId);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
# define CRASH_TEST_OVERRIDE(X,A,B,C) /* no-op */
|
||||
# define CRASH_TEST_OVERRIDE(A,B,C) C
|
||||
#endif
|
||||
|
||||
|
||||
@ -801,7 +804,7 @@ int sqlite3UnixFileExists(const char *zFilename){
|
||||
/* Forward declaration */
|
||||
static int allocateUnixFile(
|
||||
int h, /* File descriptor of the open file */
|
||||
OsFile **pId, /* Write the real file descriptor here */
|
||||
sqlite3_file **pId, /* Write the real file descriptor here */
|
||||
const char *zFilename, /* Name of the file being opened */
|
||||
int delFlag /* If true, make sure the file deletes on close */
|
||||
);
|
||||
@ -821,12 +824,11 @@ static int allocateUnixFile(
|
||||
*/
|
||||
int sqlite3UnixOpenReadWrite(
|
||||
const char *zFilename,
|
||||
OsFile **pId,
|
||||
sqlite3_file **pId,
|
||||
int *pReadonly
|
||||
){
|
||||
int h;
|
||||
|
||||
CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadWrite, zFilename, pId, pReadonly);
|
||||
assert( 0==*pId );
|
||||
h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY,
|
||||
SQLITE_DEFAULT_FILE_PERMISSIONS);
|
||||
@ -844,7 +846,10 @@ int sqlite3UnixOpenReadWrite(
|
||||
}else{
|
||||
*pReadonly = 0;
|
||||
}
|
||||
return allocateUnixFile(h, pId, zFilename, 0);
|
||||
|
||||
return CRASH_TEST_OVERRIDE(
|
||||
zFilename, pId, allocateUnixFile(h, pId, zFilename, 0)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -862,10 +867,13 @@ int sqlite3UnixOpenReadWrite(
|
||||
**
|
||||
** On failure, return SQLITE_CANTOPEN.
|
||||
*/
|
||||
int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
|
||||
int sqlite3UnixOpenExclusive(
|
||||
const char *zFilename,
|
||||
sqlite3_file **pId,
|
||||
int delFlag
|
||||
){
|
||||
int h;
|
||||
|
||||
CRASH_TEST_OVERRIDE(sqlite3CrashOpenExclusive, zFilename, pId, delFlag);
|
||||
assert( 0==*pId );
|
||||
h = open(zFilename,
|
||||
O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY,
|
||||
@ -873,7 +881,9 @@ int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
|
||||
if( h<0 ){
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
return allocateUnixFile(h, pId, zFilename, delFlag);
|
||||
return CRASH_TEST_OVERRIDE(
|
||||
zFilename, pId, allocateUnixFile(h, pId, zFilename, delFlag)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -883,16 +893,17 @@ int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
|
||||
**
|
||||
** On failure, return SQLITE_CANTOPEN.
|
||||
*/
|
||||
int sqlite3UnixOpenReadOnly(const char *zFilename, OsFile **pId){
|
||||
int sqlite3UnixOpenReadOnly(const char *zFilename, sqlite3_file **pId){
|
||||
int h;
|
||||
|
||||
CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadOnly, zFilename, pId, 0);
|
||||
assert( 0==*pId );
|
||||
h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
|
||||
if( h<0 ){
|
||||
return SQLITE_CANTOPEN;
|
||||
}
|
||||
return allocateUnixFile(h, pId, zFilename, 0);
|
||||
return CRASH_TEST_OVERRIDE(
|
||||
zFilename, pId, allocateUnixFile(h, pId, zFilename, 0)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -994,29 +1005,26 @@ int sqlite3UnixIsDirWritable(char *zBuf){
|
||||
** Seek to the offset in id->offset then read cnt bytes into pBuf.
|
||||
** Return the number of bytes actually read. Update the offset.
|
||||
*/
|
||||
static int seekAndRead(unixFile *id, void *pBuf, int cnt){
|
||||
static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
|
||||
int got;
|
||||
i64 newOffset;
|
||||
TIMER_START;
|
||||
#if defined(USE_PREAD)
|
||||
got = pread(id->h, pBuf, cnt, id->offset);
|
||||
got = pread(id->h, pBuf, cnt, offset);
|
||||
SimulateIOError( got = -1 );
|
||||
#elif defined(USE_PREAD64)
|
||||
got = pread64(id->h, pBuf, cnt, id->offset);
|
||||
got = pread64(id->h, pBuf, cnt, offset);
|
||||
SimulateIOError( got = -1 );
|
||||
#else
|
||||
newOffset = lseek(id->h, id->offset, SEEK_SET);
|
||||
newOffset = lseek(id->h, offset, SEEK_SET);
|
||||
SimulateIOError( newOffset-- );
|
||||
if( newOffset!=id->offset ){
|
||||
if( newOffset!=offset ){
|
||||
return -1;
|
||||
}
|
||||
got = read(id->h, pBuf, cnt);
|
||||
#endif
|
||||
TIMER_END;
|
||||
OSTRACE5("READ %-3d %5d %7lld %d\n", id->h, got, id->offset, TIMER_ELAPSED);
|
||||
if( got>0 ){
|
||||
id->offset += got;
|
||||
}
|
||||
return got;
|
||||
}
|
||||
|
||||
@ -1025,10 +1033,15 @@ static int seekAndRead(unixFile *id, void *pBuf, int cnt){
|
||||
** bytes were read successfully and SQLITE_IOERR if anything goes
|
||||
** wrong.
|
||||
*/
|
||||
static int unixRead(OsFile *id, void *pBuf, int amt){
|
||||
static int unixRead(
|
||||
sqlite3_file *id,
|
||||
void *pBuf,
|
||||
int amt,
|
||||
sqlite3_int64 offset
|
||||
){
|
||||
int got;
|
||||
assert( id );
|
||||
got = seekAndRead((unixFile*)id, pBuf, amt);
|
||||
got = seekAndRead((unixFile*)id, offset, pBuf, amt);
|
||||
if( got==amt ){
|
||||
return SQLITE_OK;
|
||||
}else if( got<0 ){
|
||||
@ -1043,26 +1056,23 @@ static int unixRead(OsFile *id, void *pBuf, int amt){
|
||||
** Seek to the offset in id->offset then read cnt bytes into pBuf.
|
||||
** Return the number of bytes actually read. Update the offset.
|
||||
*/
|
||||
static int seekAndWrite(unixFile *id, const void *pBuf, int cnt){
|
||||
static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
|
||||
int got;
|
||||
i64 newOffset;
|
||||
TIMER_START;
|
||||
#if defined(USE_PREAD)
|
||||
got = pwrite(id->h, pBuf, cnt, id->offset);
|
||||
got = pwrite(id->h, pBuf, cnt, offset);
|
||||
#elif defined(USE_PREAD64)
|
||||
got = pwrite64(id->h, pBuf, cnt, id->offset);
|
||||
got = pwrite64(id->h, pBuf, cnt, offset);
|
||||
#else
|
||||
newOffset = lseek(id->h, id->offset, SEEK_SET);
|
||||
if( newOffset!=id->offset ){
|
||||
newOffset = lseek(id->h, offset, SEEK_SET);
|
||||
if( newOffset!=offset ){
|
||||
return -1;
|
||||
}
|
||||
got = write(id->h, pBuf, cnt);
|
||||
#endif
|
||||
TIMER_END;
|
||||
OSTRACE5("WRITE %-3d %5d %7lld %d\n", id->h, got, id->offset, TIMER_ELAPSED);
|
||||
if( got>0 ){
|
||||
id->offset += got;
|
||||
}
|
||||
OSTRACE5("WRITE %-3d %5d %7lld %d\n", id->h, got, offset, TIMER_ELAPSED);
|
||||
return got;
|
||||
}
|
||||
|
||||
@ -1071,12 +1081,18 @@ static int seekAndWrite(unixFile *id, const void *pBuf, int cnt){
|
||||
** Write data from a buffer into a file. Return SQLITE_OK on success
|
||||
** or some other error code on failure.
|
||||
*/
|
||||
static int unixWrite(OsFile *id, const void *pBuf, int amt){
|
||||
static int unixWrite(
|
||||
sqlite3_file *id,
|
||||
const void *pBuf,
|
||||
int amt,
|
||||
sqlite3_int64 offset
|
||||
){
|
||||
int wrote = 0;
|
||||
assert( id );
|
||||
assert( amt>0 );
|
||||
while( amt>0 && (wrote = seekAndWrite((unixFile*)id, pBuf, amt))>0 ){
|
||||
while( amt>0 && (wrote = seekAndWrite((unixFile*)id, offset, pBuf, amt))>0 ){
|
||||
amt -= wrote;
|
||||
offset += wrote;
|
||||
pBuf = &((char*)pBuf)[wrote];
|
||||
}
|
||||
SimulateIOError(( wrote=(-1), amt=1 ));
|
||||
@ -1205,7 +1221,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
|
||||
** the directory entry for the journal was never created) and the transaction
|
||||
** will not roll back - possibly leading to database corruption.
|
||||
*/
|
||||
static int unixSync(OsFile *id, int dataOnly){
|
||||
static int unixSync(sqlite3_file *id, int dataOnly){
|
||||
int rc;
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
assert( pFile );
|
||||
@ -1272,7 +1288,7 @@ int sqlite3UnixSyncDirectory(const char *zDirname){
|
||||
/*
|
||||
** Truncate an open file to a specified size
|
||||
*/
|
||||
static int unixTruncate(OsFile *id, i64 nByte){
|
||||
static int unixTruncate(sqlite3_file *id, i64 nByte){
|
||||
int rc;
|
||||
assert( id );
|
||||
rc = ftruncate(((unixFile*)id)->h, (off_t)nByte);
|
||||
@ -1287,7 +1303,7 @@ static int unixTruncate(OsFile *id, i64 nByte){
|
||||
/*
|
||||
** Determine the current size of a file in bytes
|
||||
*/
|
||||
static int unixFileSize(OsFile *id, i64 *pSize){
|
||||
static int unixFileSize(sqlite3_file *id, i64 *pSize){
|
||||
int rc;
|
||||
struct stat buf;
|
||||
assert( id );
|
||||
@ -1306,7 +1322,7 @@ static int unixFileSize(OsFile *id, i64 *pSize){
|
||||
** non-zero. If the file is unlocked or holds only SHARED locks, then
|
||||
** return zero.
|
||||
*/
|
||||
static int unixCheckReservedLock(OsFile *id){
|
||||
static int unixCheckReservedLock(sqlite3_file *id){
|
||||
int r = 0;
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
|
||||
@ -1362,7 +1378,7 @@ static int unixCheckReservedLock(OsFile *id){
|
||||
** This routine will only increase a lock. Use the sqlite3OsUnlock()
|
||||
** routine to lower a locking level.
|
||||
*/
|
||||
static int unixLock(OsFile *id, int locktype){
|
||||
static int unixLock(sqlite3_file *id, int locktype){
|
||||
/* The following describes the implementation of the various locks and
|
||||
** lock transitions in terms of the POSIX advisory shared and exclusive
|
||||
** lock primitives (called read-locks and write-locks below, to avoid
|
||||
@ -1564,7 +1580,7 @@ end_lock:
|
||||
** If the locking level of the file descriptor is already at or below
|
||||
** the requested locking level, this routine is a no-op.
|
||||
*/
|
||||
static int unixUnlock(OsFile *id, int locktype){
|
||||
static int unixUnlock(sqlite3_file *id, int locktype){
|
||||
struct lockInfo *pLock;
|
||||
struct flock lock;
|
||||
int rc = SQLITE_OK;
|
||||
@ -1650,44 +1666,42 @@ static int unixUnlock(OsFile *id, int locktype){
|
||||
/*
|
||||
** Close a file.
|
||||
*/
|
||||
static int unixClose(OsFile **pId){
|
||||
unixFile *id = (unixFile*)*pId;
|
||||
|
||||
if( !id ) return SQLITE_OK;
|
||||
unixUnlock(*pId, NO_LOCK);
|
||||
if( id->dirfd>=0 ) close(id->dirfd);
|
||||
id->dirfd = -1;
|
||||
static int unixClose(sqlite3_file *id){
|
||||
unixFile *pFile = (unixFile *)id;
|
||||
if( !pFile ) return SQLITE_OK;
|
||||
unixUnlock(id, NO_LOCK);
|
||||
if( pFile->dirfd>=0 ) close(pFile->dirfd);
|
||||
pFile->dirfd = -1;
|
||||
sqlite3OsEnterMutex();
|
||||
|
||||
if( id->pOpen->nLock ){
|
||||
if( pFile->pOpen->nLock ){
|
||||
/* If there are outstanding locks, do not actually close the file just
|
||||
** yet because that would clear those locks. Instead, add the file
|
||||
** descriptor to pOpen->aPending. It will be automatically closed when
|
||||
** the last lock is cleared.
|
||||
*/
|
||||
int *aNew;
|
||||
struct openCnt *pOpen = id->pOpen;
|
||||
struct openCnt *pOpen = pFile->pOpen;
|
||||
aNew = realloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
|
||||
if( aNew==0 ){
|
||||
/* If a malloc fails, just leak the file descriptor */
|
||||
}else{
|
||||
pOpen->aPending = aNew;
|
||||
pOpen->aPending[pOpen->nPending] = id->h;
|
||||
pOpen->aPending[pOpen->nPending] = pFile->h;
|
||||
pOpen->nPending++;
|
||||
}
|
||||
}else{
|
||||
/* There are no outstanding locks so we can close the file immediately */
|
||||
close(id->h);
|
||||
close(pFile->h);
|
||||
}
|
||||
releaseLockInfo(id->pLock);
|
||||
releaseOpenCnt(id->pOpen);
|
||||
releaseLockInfo(pFile->pLock);
|
||||
releaseOpenCnt(pFile->pOpen);
|
||||
|
||||
sqlite3OsLeaveMutex();
|
||||
id->isOpen = 0;
|
||||
OSTRACE2("CLOSE %-3d\n", id->h);
|
||||
pFile->isOpen = 0;
|
||||
OSTRACE2("CLOSE %-3d\n", pFile->h);
|
||||
OpenCounter(-1);
|
||||
sqlite3ThreadSafeFree(id);
|
||||
*pId = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@ -2348,30 +2362,37 @@ static int unixLockState(OsFile *id){
|
||||
** a database and it's journal file) that the sector size will be the
|
||||
** same for both.
|
||||
*/
|
||||
static int unixSectorSize(OsFile *id){
|
||||
static int unixSectorSize(sqlite3_file *id){
|
||||
return SQLITE_DEFAULT_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
static int unixDeviceCharacteristics(sqlite3_file *id){
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unixBreakLock(sqlite3_file *id){
|
||||
assert(!"TODO: unixBreakLock()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This vector defines all the methods that can operate on an OsFile
|
||||
** for unix.
|
||||
*/
|
||||
static const IoMethod sqlite3UnixIoMethod = {
|
||||
static const sqlite3_io_methods sqlite3UnixIoMethod = {
|
||||
1, /* iVersion */
|
||||
unixClose,
|
||||
unixOpenDirectory,
|
||||
unixRead,
|
||||
unixWrite,
|
||||
unixSeek,
|
||||
unixTruncate,
|
||||
unixSync,
|
||||
unixSetFullSync,
|
||||
unixFileHandle,
|
||||
unixFileSize,
|
||||
unixLock,
|
||||
unixUnlock,
|
||||
unixLockState,
|
||||
unixCheckReservedLock,
|
||||
unixBreakLock,
|
||||
unixSectorSize,
|
||||
unixDeviceCharacteristics
|
||||
};
|
||||
|
||||
#ifdef SQLITE_ENABLE_LOCKING_STYLE
|
||||
@ -2573,7 +2594,7 @@ static int allocateUnixFile(
|
||||
#else /* SQLITE_ENABLE_LOCKING_STYLE */
|
||||
static int allocateUnixFile(
|
||||
int h, /* Open file descriptor on file being opened */
|
||||
OsFile **pId, /* Write the resul unixFile structure here */
|
||||
sqlite3_file **pId, /* Write the resul unixFile structure here */
|
||||
const char *zFilename, /* Name of the file being opened */
|
||||
int delFlag /* If true, delete the file on or before closing */
|
||||
){
|
||||
@ -2611,7 +2632,7 @@ static int allocateUnixFile(
|
||||
}else{
|
||||
*pNew = f;
|
||||
pNew->pMethod = &sqlite3UnixIoMethod;
|
||||
*pId = (OsFile*)pNew;
|
||||
*pId = (sqlite3_file*)pNew;
|
||||
OpenCounter(+1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
173
src/pager.c
173
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.355 2007/08/11 00:26:21 drh Exp $
|
||||
** @(#) $Id: pager.c,v 1.356 2007/08/15 17:08:46 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
#include "sqliteInt.h"
|
||||
@ -50,7 +50,7 @@
|
||||
** to print out file-descriptors.
|
||||
**
|
||||
** PAGERID() takes a pointer to a Pager struct as it's argument. The
|
||||
** associated file-descriptor is returned. FILEHANDLEID() takes an OsFile
|
||||
** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
|
||||
** struct as it's argument.
|
||||
*/
|
||||
#define PAGERID(p) ((int)(p->fd))
|
||||
@ -336,8 +336,8 @@ struct Pager {
|
||||
char *zFilename; /* Name of the database file */
|
||||
char *zJournal; /* Name of the journal file */
|
||||
char *zDirectory; /* Directory hold database and journal files */
|
||||
OsFile *fd, *jfd; /* File descriptors for database and journal */
|
||||
OsFile *stfd; /* File descriptor for the statement subjournal*/
|
||||
sqlite3_file *fd, *jfd; /* File descriptors for database and journal */
|
||||
sqlite3_file *stfd; /* File descriptor for the statement subjournal*/
|
||||
BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */
|
||||
PgHdr *pFirst, *pLast; /* List of free pages */
|
||||
PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */
|
||||
@ -526,9 +526,9 @@ static void pager_resize_hash_table(Pager *pPager, int N){
|
||||
**
|
||||
** All values are stored on disk as big-endian.
|
||||
*/
|
||||
static int read32bits(OsFile *fd, u32 *pRes){
|
||||
static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){
|
||||
unsigned char ac[4];
|
||||
int rc = sqlite3OsRead(fd, ac, sizeof(ac));
|
||||
int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset);
|
||||
if( rc==SQLITE_OK ){
|
||||
*pRes = sqlite3Get4byte(ac);
|
||||
}
|
||||
@ -544,10 +544,10 @@ static int read32bits(OsFile *fd, u32 *pRes){
|
||||
** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK
|
||||
** on success or an error code is something goes wrong.
|
||||
*/
|
||||
static int write32bits(OsFile *fd, u32 val){
|
||||
static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
|
||||
char ac[4];
|
||||
put32bits(ac, val);
|
||||
return sqlite3OsWrite(fd, ac, 4);
|
||||
return sqlite3OsWrite(fd, ac, 4, offset);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -627,7 +627,7 @@ static void checkPage(PgHdr *pPg){
|
||||
** If no master journal file name is present *pzMaster is set to 0 and
|
||||
** SQLITE_OK returned.
|
||||
*/
|
||||
static int readMasterJournal(OsFile *pJrnl, char **pzMaster){
|
||||
static int readMasterJournal(sqlite3_file *pJrnl, char **pzMaster){
|
||||
int rc;
|
||||
u32 len;
|
||||
i64 szJ;
|
||||
@ -640,26 +640,20 @@ static int readMasterJournal(OsFile *pJrnl, char **pzMaster){
|
||||
rc = sqlite3OsFileSize(pJrnl, &szJ);
|
||||
if( rc!=SQLITE_OK || szJ<16 ) return rc;
|
||||
|
||||
rc = sqlite3OsSeek(pJrnl, szJ-16);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
rc = read32bits(pJrnl, &len);
|
||||
rc = read32bits(pJrnl, szJ-16, &len);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
rc = read32bits(pJrnl, &cksum);
|
||||
rc = read32bits(pJrnl, szJ-12, &cksum);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
rc = sqlite3OsRead(pJrnl, aMagic, 8);
|
||||
rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-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);
|
||||
rc = sqlite3OsRead(pJrnl, *pzMaster, len, szJ-16-len);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqliteFree(*pzMaster);
|
||||
*pzMaster = 0;
|
||||
@ -700,7 +694,7 @@ static int readMasterJournal(OsFile *pJrnl, char **pzMaster){
|
||||
** 2000 2048
|
||||
**
|
||||
*/
|
||||
static int seekJournalHdr(Pager *pPager){
|
||||
static void seekJournalHdr(Pager *pPager){
|
||||
i64 offset = 0;
|
||||
i64 c = pPager->journalOff;
|
||||
if( c ){
|
||||
@ -710,7 +704,6 @@ static int seekJournalHdr(Pager *pPager){
|
||||
assert( offset>=c );
|
||||
assert( (offset-c)<JOURNAL_HDR_SZ(pPager) );
|
||||
pPager->journalOff = offset;
|
||||
return sqlite3OsSeek(pPager->jfd, pPager->journalOff);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -735,11 +728,8 @@ static int writeJournalHdr(Pager *pPager){
|
||||
pPager->stmtHdrOff = pPager->journalOff;
|
||||
}
|
||||
|
||||
rc = seekJournalHdr(pPager);
|
||||
if( rc ) return rc;
|
||||
|
||||
seekJournalHdr(pPager);
|
||||
pPager->journalHdr = pPager->journalOff;
|
||||
pPager->journalOff += JOURNAL_HDR_SZ(pPager);
|
||||
|
||||
/* FIX ME:
|
||||
**
|
||||
@ -760,17 +750,15 @@ static int writeJournalHdr(Pager *pPager){
|
||||
/* The assumed sector size for this process */
|
||||
put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
|
||||
IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, sizeof(zHeader)))
|
||||
rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader));
|
||||
rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader),pPager->journalOff);
|
||||
pPager->journalOff += JOURNAL_HDR_SZ(pPager);
|
||||
|
||||
/* The journal header has been written successfully. Seek the journal
|
||||
** file descriptor to the end of the journal header sector.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
IOTRACE(("JTAIL %p %lld\n", pPager, pPager->journalOff-1))
|
||||
rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff-1);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3OsWrite(pPager->jfd, "\000", 1);
|
||||
}
|
||||
rc = sqlite3OsWrite(pPager->jfd, "\000", 1, pPager->journalOff-1);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -799,28 +787,29 @@ static int readJournalHdr(
|
||||
){
|
||||
int rc;
|
||||
unsigned char aMagic[8]; /* A buffer to hold the magic header */
|
||||
i64 jrnlOff;
|
||||
|
||||
rc = seekJournalHdr(pPager);
|
||||
if( rc ) return rc;
|
||||
|
||||
seekJournalHdr(pPager);
|
||||
if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
jrnlOff = pPager->journalOff;
|
||||
|
||||
rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic));
|
||||
rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), jrnlOff);
|
||||
if( rc ) return rc;
|
||||
jrnlOff += sizeof(aMagic);
|
||||
|
||||
if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
|
||||
rc = read32bits(pPager->jfd, pNRec);
|
||||
rc = read32bits(pPager->jfd, jrnlOff, pNRec);
|
||||
if( rc ) return rc;
|
||||
|
||||
rc = read32bits(pPager->jfd, &pPager->cksumInit);
|
||||
rc = read32bits(pPager->jfd, jrnlOff+4, &pPager->cksumInit);
|
||||
if( rc ) return rc;
|
||||
|
||||
rc = read32bits(pPager->jfd, pDbSize);
|
||||
rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize);
|
||||
if( rc ) return rc;
|
||||
|
||||
/* Update the assumed sector-size to match the value used by
|
||||
@ -829,12 +818,11 @@ static int readJournalHdr(
|
||||
** is being called from within pager_playback(). The local value
|
||||
** of Pager.sectorSize is restored at the end of that routine.
|
||||
*/
|
||||
rc = read32bits(pPager->jfd, (u32 *)&pPager->sectorSize);
|
||||
rc = read32bits(pPager->jfd, jrnlOff+12, (u32 *)&pPager->sectorSize);
|
||||
if( rc ) return rc;
|
||||
|
||||
pPager->journalOff += JOURNAL_HDR_SZ(pPager);
|
||||
rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff);
|
||||
return rc;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -861,6 +849,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
|
||||
int rc;
|
||||
int len;
|
||||
int i;
|
||||
i64 jrnlOff;
|
||||
u32 cksum = 0;
|
||||
char zBuf[sizeof(aJournalMagic)+2*4];
|
||||
|
||||
@ -877,21 +866,23 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
|
||||
** the journal has already been synced.
|
||||
*/
|
||||
if( pPager->fullSync ){
|
||||
rc = seekJournalHdr(pPager);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
seekJournalHdr(pPager);
|
||||
}
|
||||
jrnlOff = pPager->journalOff;
|
||||
pPager->journalOff += (len+20);
|
||||
|
||||
rc = write32bits(pPager->jfd, PAGER_MJ_PGNO(pPager));
|
||||
rc = write32bits(pPager->jfd, jrnlOff, PAGER_MJ_PGNO(pPager));
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
jrnlOff += 4;
|
||||
|
||||
rc = sqlite3OsWrite(pPager->jfd, zMaster, len);
|
||||
rc = sqlite3OsWrite(pPager->jfd, zMaster, len, jrnlOff);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
jrnlOff += len;
|
||||
|
||||
put32bits(zBuf, len);
|
||||
put32bits(&zBuf[4], cksum);
|
||||
memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic));
|
||||
rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic));
|
||||
rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic), jrnlOff);
|
||||
pPager->needSync = !pPager->noSync;
|
||||
return rc;
|
||||
}
|
||||
@ -1026,7 +1017,6 @@ static int pager_end_transaction(Pager *pPager){
|
||||
if( pPager->journalOpen ){
|
||||
if( pPager->exclusiveMode
|
||||
&& (rc = sqlite3OsTruncate(pPager->jfd, 0))==SQLITE_OK ){;
|
||||
sqlite3OsSeek(pPager->jfd, 0);
|
||||
pPager->journalOff = 0;
|
||||
pPager->journalStarted = 0;
|
||||
}else{
|
||||
@ -1111,7 +1101,12 @@ static void makeClean(PgHdr*);
|
||||
** are not used in statement journals because statement journals do not
|
||||
** need to survive power failures.
|
||||
*/
|
||||
static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
|
||||
static int pager_playback_one_page(
|
||||
Pager *pPager,
|
||||
sqlite3_file *jfd,
|
||||
i64 offset,
|
||||
int useCksum
|
||||
){
|
||||
int rc;
|
||||
PgHdr *pPg; /* An existing page in the cache */
|
||||
Pgno pgno; /* The page number of a page in journal */
|
||||
@ -1124,9 +1119,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
|
||||
assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) );
|
||||
assert( aData );
|
||||
|
||||
rc = read32bits(jfd, &pgno);
|
||||
rc = read32bits(jfd, offset, &pgno);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
rc = sqlite3OsRead(jfd, aData, pPager->pageSize);
|
||||
rc = sqlite3OsRead(jfd, aData, pPager->pageSize, offset+4);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
pPager->journalOff += pPager->pageSize + 4;
|
||||
|
||||
@ -1142,7 +1137,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( useCksum ){
|
||||
rc = read32bits(jfd, &cksum);
|
||||
rc = read32bits(jfd, offset+pPager->pageSize+4, &cksum);
|
||||
if( rc ) return rc;
|
||||
pPager->journalOff += 4;
|
||||
if( pager_cksum(pPager, aData)!=cksum ){
|
||||
@ -1184,10 +1179,8 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
|
||||
PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n",
|
||||
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData));
|
||||
if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) ){
|
||||
rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize);
|
||||
}
|
||||
i64 offset = (pgno-1)*(i64)pPager->pageSize;
|
||||
rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, offset);
|
||||
if( pPg ){
|
||||
makeClean(pPg);
|
||||
}
|
||||
@ -1235,7 +1228,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
|
||||
static int pager_delmaster(const char *zMaster){
|
||||
int rc;
|
||||
int master_open = 0;
|
||||
OsFile *master = 0;
|
||||
sqlite3_file *master = 0;
|
||||
char *zMasterJournal = 0; /* Contents of master journal file */
|
||||
i64 nMasterJournal; /* Size of master journal file */
|
||||
|
||||
@ -1261,7 +1254,7 @@ static int pager_delmaster(const char *zMaster){
|
||||
rc = SQLITE_NOMEM;
|
||||
goto delmaster_out;
|
||||
}
|
||||
rc = sqlite3OsRead(master, zMasterJournal, nMasterJournal);
|
||||
rc = sqlite3OsRead(master, zMasterJournal, nMasterJournal, 0);
|
||||
if( rc!=SQLITE_OK ) goto delmaster_out;
|
||||
|
||||
zJournal = zMasterJournal;
|
||||
@ -1271,7 +1264,7 @@ static int pager_delmaster(const char *zMaster){
|
||||
** Open it and check if it points at the master journal. If
|
||||
** so, return without deleting the master journal file.
|
||||
*/
|
||||
OsFile *journal = 0;
|
||||
sqlite3_file *journal = 0;
|
||||
int c;
|
||||
|
||||
rc = sqlite3OsOpenReadOnly(zJournal, &journal);
|
||||
@ -1424,7 +1417,6 @@ static int pager_playback(Pager *pPager, int isHot){
|
||||
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
|
||||
goto end_playback;
|
||||
}
|
||||
sqlite3OsSeek(pPager->jfd, 0);
|
||||
pPager->journalOff = 0;
|
||||
|
||||
/* This loop terminates either when the readJournalHdr() call returns
|
||||
@ -1480,7 +1472,7 @@ static int pager_playback(Pager *pPager, int isHot){
|
||||
/* Copy original pages out of the journal and back into the database file.
|
||||
*/
|
||||
for(i=0; i<nRec; i++){
|
||||
rc = pager_playback_one_page(pPager, pPager->jfd, 1);
|
||||
rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
@ -1567,7 +1559,6 @@ static int pager_stmt_playback(Pager *pPager){
|
||||
/* Figure out how many records are in the statement journal.
|
||||
*/
|
||||
assert( pPager->stmtInUse && pPager->journalOpen );
|
||||
sqlite3OsSeek(pPager->stfd, 0);
|
||||
nRec = pPager->stmtNRec;
|
||||
|
||||
/* Copy original pages out of the statement journal and back into the
|
||||
@ -1575,8 +1566,9 @@ static int pager_stmt_playback(Pager *pPager){
|
||||
** each record since power-failure recovery is not important to statement
|
||||
** journals.
|
||||
*/
|
||||
for(i=nRec-1; i>=0; i--){
|
||||
rc = pager_playback_one_page(pPager, pPager->stfd, 0);
|
||||
for(i=0; i<nRec; i++){
|
||||
i64 offset = i*(4+pPager->pageSize);
|
||||
rc = pager_playback_one_page(pPager, pPager->stfd, offset, 0);
|
||||
assert( rc!=SQLITE_DONE );
|
||||
if( rc!=SQLITE_OK ) goto end_stmt_playback;
|
||||
}
|
||||
@ -1589,14 +1581,10 @@ static int pager_stmt_playback(Pager *pPager){
|
||||
** If it is not zero, then Pager.stmtHdrOff is the offset to the start
|
||||
** of the first journal header written during this statement transaction.
|
||||
*/
|
||||
rc = sqlite3OsSeek(pPager->jfd, pPager->stmtJSize);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto end_stmt_playback;
|
||||
}
|
||||
pPager->journalOff = pPager->stmtJSize;
|
||||
pPager->cksumInit = pPager->stmtCksum;
|
||||
while( pPager->journalOff < hdrOff ){
|
||||
rc = pager_playback_one_page(pPager, pPager->jfd, 1);
|
||||
rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1);
|
||||
assert( rc!=SQLITE_DONE );
|
||||
if( rc!=SQLITE_OK ) goto end_stmt_playback;
|
||||
}
|
||||
@ -1613,7 +1601,7 @@ static int pager_stmt_playback(Pager *pPager){
|
||||
nJRec = (szJ - pPager->journalOff) / (pPager->pageSize+8);
|
||||
}
|
||||
for(i=nJRec-1; i>=0 && pPager->journalOff < szJ; i--){
|
||||
rc = pager_playback_one_page(pPager, pPager->jfd, 1);
|
||||
rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1);
|
||||
assert( rc!=SQLITE_DONE );
|
||||
if( rc!=SQLITE_OK ) goto end_stmt_playback;
|
||||
}
|
||||
@ -1693,7 +1681,7 @@ int sqlite3_opentemp_count = 0;
|
||||
** The OS will automatically delete the temporary file when it is
|
||||
** closed.
|
||||
*/
|
||||
static int sqlite3PagerOpentemp(OsFile **pFd){
|
||||
static int sqlite3PagerOpentemp(sqlite3_file **pFd){
|
||||
int cnt = 8;
|
||||
int rc;
|
||||
char zFile[SQLITE_TEMPNAME_SIZE];
|
||||
@ -1733,7 +1721,7 @@ int sqlite3PagerOpen(
|
||||
Pager *pPager = 0;
|
||||
char *zFullPathname = 0;
|
||||
int nameLen; /* Compiler is wrong. This is always initialized before use */
|
||||
OsFile *fd = 0;
|
||||
sqlite3_file *fd = 0;
|
||||
int rc = SQLITE_OK;
|
||||
int i;
|
||||
int tempFile = 0;
|
||||
@ -1970,11 +1958,8 @@ int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
|
||||
int rc = SQLITE_OK;
|
||||
memset(pDest, 0, N);
|
||||
if( MEMDB==0 ){
|
||||
disable_simulated_io_errors();
|
||||
sqlite3OsSeek(pPager->fd, 0);
|
||||
enable_simulated_io_errors();
|
||||
IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
|
||||
rc = sqlite3OsRead(pPager->fd, pDest, N);
|
||||
rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
|
||||
if( rc==SQLITE_IOERR_SHORT_READ ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
@ -2381,6 +2366,8 @@ static int syncJournal(Pager *pPager){
|
||||
}
|
||||
#endif
|
||||
{
|
||||
i64 jrnlOff;
|
||||
|
||||
/* Write the nRec value into the journal file header. If in
|
||||
** full-synchronous mode, sync the journal first. This ensures that
|
||||
** all data has really hit the disk before nRec is updated to mark
|
||||
@ -2392,15 +2379,10 @@ static int syncJournal(Pager *pPager){
|
||||
rc = sqlite3OsSync(pPager->jfd, 0);
|
||||
if( rc!=0 ) return rc;
|
||||
}
|
||||
rc = sqlite3OsSeek(pPager->jfd,
|
||||
pPager->journalHdr + sizeof(aJournalMagic));
|
||||
if( rc ) return rc;
|
||||
IOTRACE(("JHDR %p %lld %d\n", pPager,
|
||||
pPager->journalHdr + sizeof(aJournalMagic), 4))
|
||||
rc = write32bits(pPager->jfd, pPager->nRec);
|
||||
if( rc ) return rc;
|
||||
|
||||
rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff);
|
||||
jrnlOff = pPager->journalHdr + sizeof(aJournalMagic);
|
||||
IOTRACE(("JHDR %p %lld %d\n", pPager, jrnlOff, 4));
|
||||
rc = write32bits(pPager->jfd, jrnlOff, pPager->nRec);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager));
|
||||
@ -2545,19 +2527,18 @@ static int pager_write_pagelist(PgHdr *pList){
|
||||
pList = sort_pagelist(pList);
|
||||
while( pList ){
|
||||
assert( pList->dirty );
|
||||
rc = sqlite3OsSeek(pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize);
|
||||
if( rc ) return rc;
|
||||
/* If there are dirty pages in the page cache with page numbers greater
|
||||
** than Pager.dbSize, this means sqlite3PagerTruncate() was called to
|
||||
** make the file smaller (presumably by auto-vacuum code). Do not write
|
||||
** any such pages to the file.
|
||||
*/
|
||||
if( pList->pgno<=pPager->dbSize ){
|
||||
i64 offset = (pList->pgno-1)*(i64)pPager->pageSize;
|
||||
char *pData = CODEC2(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
|
||||
PAGERTRACE4("STORE %d page %d hash(%08x)\n",
|
||||
PAGERID(pPager), pList->pgno, pager_pagehash(pList));
|
||||
IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno));
|
||||
rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize);
|
||||
rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
|
||||
PAGER_INCR(sqlite3_pager_writedb_count);
|
||||
PAGER_INCR(pPager->nWrite);
|
||||
if( pList->pgno==1 ){
|
||||
@ -2796,12 +2777,10 @@ int sqlite3PagerReleaseMemory(int nReq){
|
||||
*/
|
||||
static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){
|
||||
int rc;
|
||||
i64 offset;
|
||||
assert( MEMDB==0 );
|
||||
rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg),
|
||||
pPager->pageSize);
|
||||
}
|
||||
offset = (pgno-1)*(i64)pPager->pageSize;
|
||||
rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize, offset);
|
||||
PAGER_INCR(sqlite3_pager_readdb_count);
|
||||
PAGER_INCR(pPager->nRead);
|
||||
IOTRACE(("PGIN %p %d\n", pPager, pgno));
|
||||
@ -2934,11 +2913,7 @@ static int pagerSharedLock(Pager *pPager){
|
||||
|
||||
if( pPager->dbSize>0 ){
|
||||
IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
|
||||
rc = sqlite3OsSeek(pPager->fd, 24);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers));
|
||||
rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
@ -3332,9 +3307,11 @@ static int pager_open_journal(Pager *pPager){
|
||||
}
|
||||
goto failed_to_open_journal;
|
||||
}
|
||||
#if 0
|
||||
sqlite3OsSetFullSync(pPager->jfd, pPager->full_fsync);
|
||||
sqlite3OsSetFullSync(pPager->fd, pPager->full_fsync);
|
||||
sqlite3OsOpenDirectory(pPager->jfd, pPager->zDirectory);
|
||||
#endif
|
||||
pPager->journalOpen = 1;
|
||||
pPager->journalStarted = 0;
|
||||
pPager->needSync = 0;
|
||||
@ -3583,7 +3560,7 @@ static int pager_write(PgHdr *pPg){
|
||||
put32bits(pEnd, cksum);
|
||||
szPg = pPager->pageSize+8;
|
||||
put32bits(pData2, pPg->pgno);
|
||||
rc = sqlite3OsWrite(pPager->jfd, pData2, szPg);
|
||||
rc = sqlite3OsWrite(pPager->jfd, pData2, szPg, pPager->journalOff);
|
||||
IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
|
||||
pPager->journalOff, szPg));
|
||||
PAGER_INCR(sqlite3_pager_writej_count);
|
||||
@ -3638,9 +3615,10 @@ static int pager_write(PgHdr *pPg){
|
||||
PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
|
||||
page_add_to_stmt_list(pPg);
|
||||
}else{
|
||||
i64 offset = pPager->stmtNRec*(4+pPager->pageSize);
|
||||
char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7)-4;
|
||||
put32bits(pData2, pPg->pgno);
|
||||
rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize+4);
|
||||
rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize+4, offset);
|
||||
PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
@ -4215,7 +4193,6 @@ int sqlite3PagerStmtCommit(Pager *pPager){
|
||||
PgHdr *pPg, *pNext;
|
||||
PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
|
||||
if( !MEMDB ){
|
||||
sqlite3OsSeek(pPager->stfd, 0);
|
||||
/* sqlite3OsTruncate(pPager->stfd, 0); */
|
||||
sqliteFree( pPager->aInStmt );
|
||||
pPager->aInStmt = 0;
|
||||
|
@ -30,7 +30,7 @@
|
||||
** the version number) and changes its name to "sqlite3.h" as
|
||||
** part of the build process.
|
||||
**
|
||||
** @(#) $Id: sqlite.h.in,v 1.223 2007/08/15 13:04:54 drh Exp $
|
||||
** @(#) $Id: sqlite.h.in,v 1.224 2007/08/15 17:08:46 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITE3_H_
|
||||
#define _SQLITE3_H_
|
||||
@ -488,7 +488,7 @@ struct sqlite3_io_methods {
|
||||
int iVersion;
|
||||
int (*xClose)(sqlite3_file*);
|
||||
int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite_int64 iOfst);
|
||||
int (*xWrite)(sqlite3_file*, void*, int iAmt, sqlite_int64 iOfst);
|
||||
int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite_int64 iOfst);
|
||||
int (*xTruncate)(sqlite3_file*, sqlite_int64 size);
|
||||
int (*xSync)(sqlite3_file*, int flags);
|
||||
int (*xFileSize)(sqlite3_file*, sqlite_int64 *pSize);
|
||||
|
@ -13,7 +13,7 @@
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test2.c,v 1.43 2007/04/02 05:07:47 danielk1977 Exp $
|
||||
** $Id: test2.c,v 1.44 2007/08/15 17:08:46 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@ -546,12 +546,7 @@ static int fake_big_file(
|
||||
}
|
||||
offset = n;
|
||||
offset *= 1024*1024;
|
||||
rc = sqlite3OsSeek(fd, offset);
|
||||
if( rc ){
|
||||
Tcl_AppendResult(interp, "seek failed: ", errorName(rc), 0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = sqlite3OsWrite(fd, "Hello, World!", 14);
|
||||
rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset);
|
||||
sqlite3OsClose(&fd);
|
||||
if( rc ){
|
||||
Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0);
|
||||
|
948
src/test6.c
948
src/test6.c
File diff suppressed because it is too large
Load Diff
@ -1129,7 +1129,8 @@ static int vdbeCommit(sqlite3 *db){
|
||||
int needSync = 0;
|
||||
char *zMaster = 0; /* File-name for the master journal */
|
||||
char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
|
||||
OsFile *master = 0;
|
||||
sqlite3_file *master = 0;
|
||||
i64 offset = 0;
|
||||
|
||||
/* Select a master journal file name */
|
||||
do {
|
||||
@ -1164,7 +1165,8 @@ static int vdbeCommit(sqlite3 *db){
|
||||
if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){
|
||||
needSync = 1;
|
||||
}
|
||||
rc = sqlite3OsWrite(master, zFile, strlen(zFile)+1);
|
||||
rc = sqlite3OsWrite(master, zFile, strlen(zFile)+1, offset);
|
||||
offset += strlen(zFile)+1;
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3OsClose(&master);
|
||||
sqlite3OsDelete(zMaster);
|
||||
@ -1179,6 +1181,7 @@ static int vdbeCommit(sqlite3 *db){
|
||||
** the master journal file is store in so that it gets synced too.
|
||||
*/
|
||||
zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);
|
||||
#if 0
|
||||
rc = sqlite3OsOpenDirectory(master, zMainFile);
|
||||
if( rc!=SQLITE_OK ||
|
||||
(needSync && (rc=sqlite3OsSync(master,0))!=SQLITE_OK) ){
|
||||
@ -1187,6 +1190,7 @@ static int vdbeCommit(sqlite3 *db){
|
||||
sqliteFree(zMaster);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sync all the db files involved in the transaction. The same call
|
||||
** sets the master journal pointer in each individual journal. If
|
||||
|
Loading…
Reference in New Issue
Block a user