Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a2dab93215 | |||
| c2e57196cb | |||
| 320cebe7d1 | |||
| f4ae60eb7a | |||
| bb250298e6 | |||
| 7972768979 | |||
| dd541f2a13 | |||
| 5abbf16602 | |||
| 237768dad3 |
@@ -1,8 +1,8 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA1
|
||||
|
||||
C Version\s3.7.4\srelease\scandidate\s4
|
||||
D 2010-12-07T20:14:09
|
||||
C Automatically\sretry\ssystem\scalls\sthat\sfail\swith\sEINTR.\s\sThis\sis\sa\sbackport\nof\sthe\schanges\sfrom\s[b9d29ea385bafc]\sand\s[af9ba2a6d2c379].
|
||||
D 2011-02-23T14:33:31.368
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 4547616ad2286053af6ccccefa242dc925e49bf0
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -122,7 +122,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c d5b0137bc20327af08c14772227cc35134839c30
|
||||
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
|
||||
F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff
|
||||
F src/btree.c b70bf1dc563ec532851715ce51aa1ea0c0c592b9
|
||||
F src/btree.c 9fd4438357ede1e67229cce75336f364e1ca58c9
|
||||
F src/btree.h 10f9296bf4edf034f5adce921b7b4383a56a1c90
|
||||
F src/btreeInt.h c424f2f131cc61ddf130f9bd736b3df12c8a51f0
|
||||
F src/build.c 00a327120d81ace6267e714ae8010c997d55de5d
|
||||
@@ -163,9 +163,9 @@ F src/os.c 22ac61d06e72a0dac900400147333b07b13d8e1d
|
||||
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
|
||||
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
||||
F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e
|
||||
F src/os_unix.c 0240c5b547b4cf585c8cac351a95c3e85ce00772
|
||||
F src/os_unix.c ef71b9892af48871a448c7f4ca662ecd287e70dd
|
||||
F src/os_win.c 2f90f7bdec714fad51cd31b4ecad3cc1b4bb5aad
|
||||
F src/pager.c c0aca5c733c15a16fe158c3215d857841a4e5381
|
||||
F src/pager.c 5b2210b4307c626a3b3ed7312161ec533958c094
|
||||
F src/pager.h 0ea59db2a33bc6c2c02cae34de33367e1effdf76
|
||||
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
|
||||
F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
|
||||
@@ -240,10 +240,10 @@ F src/vdbeblob.c 18955f0ee6b133cd08e1592010cb9a6b11e9984c
|
||||
F src/vdbemem.c 411649a35686f54268ccabeda175322c4697f5a6
|
||||
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
|
||||
F src/vtab.c b297e8fa656ab5e66244ab15680d68db0adbec30
|
||||
F src/wal.c f26b8d297bd11cb792e609917f9d4c6718ac8e0e
|
||||
F src/wal.c 5b0f0a2a12208544721b5b46cc18f97efb203ea3
|
||||
F src/wal.h c1aac6593a0b02b15dc625987e619edeab39292e
|
||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||
F src/where.c fa22d45b2577c77146f2e894d58011d472d64103
|
||||
F src/where.c af069e6b53234118014dabfece96a9515b69d76b
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 51756962d522e474338e9b2ebb26e7364d4aa125
|
||||
@@ -376,12 +376,12 @@ F test/enc4.test 4b575ef09e0eff896e73bd24076f96c2aa6a42de
|
||||
F test/eqp.test 69670e7919030f21de29fb99bf1d68f97aedcbdb
|
||||
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
|
||||
F test/exclusive.test 53e1841b422e554cecf0160f937c473d6d0e3062
|
||||
F test/exclusive2.test 76e63c05349cb70d09d60b99d2ae625525ff5155
|
||||
F test/exclusive2.test c2f2b2242dc436a12df8dd531e06843053bd3b9a
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/expr.test 620a636cf7b7d4e5834a0b9d83a4da372e24a7b7
|
||||
F test/fallocate.test 43dc34b8c24be6baffadc3b4401ee15710ce83c6
|
||||
F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e
|
||||
F test/filefmt.test f77c92141960b7933bc6691631d2ad62257ef40a
|
||||
F test/filefmt.test f178cfc29501a14565954c961b226e61877dd32c
|
||||
F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
|
||||
F test/fkey2.test e028cd80aa0bd38541c99214e3ba2dfccadffe6f
|
||||
F test/fkey3.test 42f88d6048d8dc079e2a8cf7baad1cc1483a7620
|
||||
@@ -578,6 +578,7 @@ F test/notify3.test d60923e186e0900f4812a845fcdfd8eea096e33a
|
||||
F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
|
||||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
|
||||
F test/oserror.test 5775264a41039856d211168713d916949227fedd
|
||||
F test/pager1.test e066fb2e2dc1ac1cd9ef2b44a28ae3cc79a9150f
|
||||
F test/pager2.test 0fbb6b6dc40ce1fecfe758c555a748ad2e9beaa3
|
||||
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
||||
@@ -875,7 +876,7 @@ F tool/mkkeywordhash.c d2e6b4a5965e23afb80fbe74bb54648cd371f309
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c.tcl e0db70c2c52b0e3d0867ca931229e5b90ffe7837
|
||||
F tool/mksqlite3h.tcl 03b6ca938c833814923674d8a160e91fcedb4571
|
||||
F tool/mksqlite3h.tcl d76c226a5e8e1f3b5f6593bcabe5e98b3b1ec9ff
|
||||
F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
|
||||
F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
@@ -897,14 +898,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P fe441df9ba447d97571e919099846efa3ec87427
|
||||
R 6bbeb99b0a61f7ea1af21c5b74072ff6
|
||||
P a4333b1545c6f96caef5b6dfaf94c8446e1b5d44
|
||||
R 110fc06a15d59c992fa93576aaf0f07d
|
||||
U drh
|
||||
Z 584aed3667b20c0c4d105810047e9fd4
|
||||
Z 728d442c3a16d050cc4bf0099d5aa1fd
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||
|
||||
iD8DBQFM/pWUoxKgR168RlERAuOQAJ9BLHxhysfzWC+psYkAVcf2xDsyTgCeIRqp
|
||||
FF5a9ESJ6yucR80Re9sEWmU=
|
||||
=ZPd3
|
||||
iD8DBQFNZRq+oxKgR168RlERAjAUAJ4icN9NAHBEFsKwW+tePI8D7yuS5QCeJfkr
|
||||
4CvelEbFUjjp0LZiOQzb+aA=
|
||||
=6ZlI
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
a586a4deeb25330037a49df295b36aaf624d0f45
|
||||
8609a15dfad23a7c5311b52617d5c4818c0b8d1e
|
||||
+1
-1
@@ -2386,7 +2386,7 @@ static int lockBtree(BtShared *pBt){
|
||||
pageSize-usableSize);
|
||||
return rc;
|
||||
}
|
||||
if( nPageHeader>nPageFile ){
|
||||
if( (pBt->db->flags & SQLITE_RecoveryMode)==0 && nPage>nPageFile ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto page1_init_failed;
|
||||
}
|
||||
|
||||
+139
-37
@@ -394,6 +394,19 @@ static int lockTrace(int fd, int op, struct flock *p){
|
||||
#endif /* SQLITE_LOCK_TRACE */
|
||||
|
||||
|
||||
/*
|
||||
** Retry ftruncate() calls that fail due to EINTR
|
||||
*/
|
||||
#ifdef EINTR
|
||||
static int robust_ftruncate(int h, sqlite3_int64 sz){
|
||||
int rc;
|
||||
do{ rc = ftruncate(h,sz); }while( rc<0 && errno==EINTR );
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
# define robust_ftruncate(a,b) ftruncate(a,b)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** This routine translates a standard POSIX errno code into something
|
||||
@@ -736,6 +749,75 @@ struct unixInodeInfo {
|
||||
*/
|
||||
static unixInodeInfo *inodeList = 0;
|
||||
|
||||
/*
|
||||
**
|
||||
** This function - unixLogError_x(), is only ever called via the macro
|
||||
** unixLogError().
|
||||
**
|
||||
** It is invoked after an error occurs in an OS function and errno has been
|
||||
** set. It logs a message using sqlite3_log() containing the current value of
|
||||
** errno and, if possible, the human-readable equivalent from strerror() or
|
||||
** strerror_r().
|
||||
**
|
||||
** The first argument passed to the macro should be the error code that
|
||||
** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
|
||||
** The two subsequent arguments should be the name of the OS function that
|
||||
** failed (e.g. "unlink", "open") and the the associated file-system path,
|
||||
** if any.
|
||||
*/
|
||||
#define unixLogError(a,b,c) unixLogError_x(a,b,c,__LINE__)
|
||||
static int unixLogError_x(
|
||||
int errcode, /* SQLite error code */
|
||||
const char *zFunc, /* Name of OS function that failed */
|
||||
const char *zPath, /* File path associated with error */
|
||||
int iLine /* Source line number where error occurred */
|
||||
){
|
||||
char *zErr; /* Message from strerror() or equivalent */
|
||||
|
||||
/* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
|
||||
** the strerror() function to obtain the human-readable error message
|
||||
** equivalent to errno. Otherwise, use strerror_r().
|
||||
*/
|
||||
#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
|
||||
char aErr[80];
|
||||
memset(aErr, 0, sizeof(aErr));
|
||||
zErr = aErr;
|
||||
|
||||
/* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
|
||||
** assume that the system provides the the GNU version of strerror_r() that
|
||||
** returns a pointer to a buffer containing the error message. That pointer
|
||||
** may point to aErr[], or it may point to some static storage somewhere.
|
||||
** Otherwise, assume that the system provides the POSIX version of
|
||||
** strerror_r(), which always writes an error message into aErr[].
|
||||
**
|
||||
** If the code incorrectly assumes that it is the POSIX version that is
|
||||
** available, the error message will often be an empty string. Not a
|
||||
** huge problem. Incorrectly concluding that the GNU version is available
|
||||
** could lead to a segfault though.
|
||||
*/
|
||||
#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
|
||||
zErr =
|
||||
# endif
|
||||
strerror_r(errno, aErr, sizeof(aErr)-1);
|
||||
|
||||
#elif SQLITE_THREADSAFE
|
||||
/* This is a threadsafe build, but strerror_r() is not available. */
|
||||
zErr = "";
|
||||
#else
|
||||
/* Non-threadsafe build, use strerror(). */
|
||||
zErr = strerror(errno);
|
||||
#endif
|
||||
|
||||
assert( errcode!=SQLITE_OK );
|
||||
sqlite3_log(errcode,
|
||||
"os_unix.c: %s() at line %d - \"%s\" errno=%d path=%s",
|
||||
zFunc, iLine, zErr, errno, (zPath ? zPath : "n/a")
|
||||
);
|
||||
|
||||
return errcode;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
|
||||
** If all such file descriptors are closed without error, the list is
|
||||
@@ -755,7 +837,7 @@ static int closePendingFds(unixFile *pFile){
|
||||
pNext = p->pNext;
|
||||
if( close(p->fd) ){
|
||||
pFile->lastErrno = errno;
|
||||
rc = SQLITE_IOERR_CLOSE;
|
||||
rc = unixLogError(SQLITE_IOERR_CLOSE, "close", pFile->zPath);
|
||||
p->pNext = pError;
|
||||
pError = p;
|
||||
}else{
|
||||
@@ -843,7 +925,7 @@ static int findInodeInfo(
|
||||
** the first page of the database, no damage is done.
|
||||
*/
|
||||
if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
|
||||
rc = write(fd, "S", 1);
|
||||
do{ rc = write(fd, "S", 1); }while( rc<0 && errno==EINTR );
|
||||
if( rc!=1 ){
|
||||
pFile->lastErrno = errno;
|
||||
return SQLITE_IOERR;
|
||||
@@ -1408,7 +1490,7 @@ static int closeUnixFile(sqlite3_file *id){
|
||||
int err = close(pFile->dirfd);
|
||||
if( err ){
|
||||
pFile->lastErrno = errno;
|
||||
return SQLITE_IOERR_DIR_CLOSE;
|
||||
return unixLogError(SQLITE_IOERR_DIR_CLOSE, "close", pFile->zPath);
|
||||
}else{
|
||||
pFile->dirfd=-1;
|
||||
}
|
||||
@@ -1417,7 +1499,7 @@ static int closeUnixFile(sqlite3_file *id){
|
||||
int err = close(pFile->h);
|
||||
if( err ){
|
||||
pFile->lastErrno = errno;
|
||||
return SQLITE_IOERR_CLOSE;
|
||||
return unixLogError(SQLITE_IOERR_CLOSE, "close", pFile->zPath);
|
||||
}
|
||||
}
|
||||
#if OS_VXWORKS
|
||||
@@ -1719,6 +1801,20 @@ static int dotlockClose(sqlite3_file *id) {
|
||||
*/
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
|
||||
|
||||
/*
|
||||
** Retry flock() calls that fail with EINTR
|
||||
*/
|
||||
#ifdef EINTR
|
||||
static int robust_flock(int fd, int op){
|
||||
int rc;
|
||||
do{ rc = flock(fd,op); }while( rc<0 && errno==EINTR );
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
# define robust_flock(a,b) flock(a,b)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** This routine checks if there is a RESERVED lock held on the specified
|
||||
** file by this or any other process. If such a lock is held, set *pResOut
|
||||
@@ -1742,10 +1838,10 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
/* Otherwise see if some other process holds it. */
|
||||
if( !reserved ){
|
||||
/* attempt to get the lock */
|
||||
int lrc = flock(pFile->h, LOCK_EX | LOCK_NB);
|
||||
int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
|
||||
if( !lrc ){
|
||||
/* got the lock, unlock it */
|
||||
lrc = flock(pFile->h, LOCK_UN);
|
||||
lrc = robust_flock(pFile->h, LOCK_UN);
|
||||
if ( lrc ) {
|
||||
int tErrno = errno;
|
||||
/* unlock failed with an error */
|
||||
@@ -1822,7 +1918,7 @@ static int flockLock(sqlite3_file *id, int eFileLock) {
|
||||
|
||||
/* grab an exclusive lock */
|
||||
|
||||
if (flock(pFile->h, LOCK_EX | LOCK_NB)) {
|
||||
if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
|
||||
int tErrno = errno;
|
||||
/* didn't get, must be busy */
|
||||
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
||||
@@ -1871,7 +1967,7 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) {
|
||||
}
|
||||
|
||||
/* no, really, unlock. */
|
||||
int rc = flock(pFile->h, LOCK_UN);
|
||||
int rc = robust_flock(pFile->h, LOCK_UN);
|
||||
if (rc) {
|
||||
int r, tErrno = errno;
|
||||
r = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
|
||||
@@ -2608,10 +2704,10 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
|
||||
#endif
|
||||
TIMER_START;
|
||||
#if defined(USE_PREAD)
|
||||
got = pread(id->h, pBuf, cnt, offset);
|
||||
do{ got = pread(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
|
||||
SimulateIOError( got = -1 );
|
||||
#elif defined(USE_PREAD64)
|
||||
got = pread64(id->h, pBuf, cnt, offset);
|
||||
do{ got = pread64(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
|
||||
SimulateIOError( got = -1 );
|
||||
#else
|
||||
newOffset = lseek(id->h, offset, SEEK_SET);
|
||||
@@ -2624,7 +2720,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
got = read(id->h, pBuf, cnt);
|
||||
do{ got = read(id->h, pBuf, cnt); }while( got<0 && errno==EINTR );
|
||||
#endif
|
||||
TIMER_END;
|
||||
if( got<0 ){
|
||||
@@ -2686,9 +2782,9 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
|
||||
#endif
|
||||
TIMER_START;
|
||||
#if defined(USE_PREAD)
|
||||
got = pwrite(id->h, pBuf, cnt, offset);
|
||||
do{ got = pwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
|
||||
#elif defined(USE_PREAD64)
|
||||
got = pwrite64(id->h, pBuf, cnt, offset);
|
||||
do{ got = pwrite64(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
|
||||
#else
|
||||
newOffset = lseek(id->h, offset, SEEK_SET);
|
||||
if( newOffset!=offset ){
|
||||
@@ -2699,7 +2795,7 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
got = write(id->h, pBuf, cnt);
|
||||
do{ got = write(id->h, pBuf, cnt); }while( got<0 && errno==EINTR );
|
||||
#endif
|
||||
TIMER_END;
|
||||
if( got<0 ){
|
||||
@@ -2939,7 +3035,7 @@ static int unixSync(sqlite3_file *id, int flags){
|
||||
SimulateIOError( rc=1 );
|
||||
if( rc ){
|
||||
pFile->lastErrno = errno;
|
||||
return SQLITE_IOERR_FSYNC;
|
||||
return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
|
||||
}
|
||||
if( pFile->dirfd>=0 ){
|
||||
int err;
|
||||
@@ -2966,7 +3062,7 @@ static int unixSync(sqlite3_file *id, int flags){
|
||||
pFile->dirfd = -1;
|
||||
}else{
|
||||
pFile->lastErrno = errno;
|
||||
rc = SQLITE_IOERR_DIR_CLOSE;
|
||||
rc = unixLogError(SQLITE_IOERR_DIR_CLOSE, "close", pFile->zPath);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
@@ -2990,10 +3086,10 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
|
||||
nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
|
||||
}
|
||||
|
||||
rc = ftruncate(pFile->h, (off_t)nByte);
|
||||
rc = robust_ftruncate(pFile->h, (off_t)nByte);
|
||||
if( rc ){
|
||||
pFile->lastErrno = errno;
|
||||
return SQLITE_IOERR_TRUNCATE;
|
||||
return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
|
||||
}else{
|
||||
#ifndef NDEBUG
|
||||
/* If we are doing a normal write to a database file (as opposed to
|
||||
@@ -3065,9 +3161,11 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
|
||||
nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
|
||||
if( nSize>(i64)buf.st_size ){
|
||||
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
|
||||
if( posix_fallocate(pFile->h, buf.st_size, nSize-buf.st_size) ){
|
||||
return SQLITE_IOERR_WRITE;
|
||||
}
|
||||
int rc;
|
||||
do{
|
||||
rc = posix_fallocate(pFile-.h, buf.st_size, nSize-buf.st_size;
|
||||
}while( rc<0 && errno=EINTR );
|
||||
if( rc ) return SQLITE_IOERR_WRITE;
|
||||
#else
|
||||
/* If the OS does not have posix_fallocate(), fake it. First use
|
||||
** ftruncate() to set the file size, then write a single byte to
|
||||
@@ -3079,9 +3177,9 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
|
||||
i64 iWrite; /* Next offset to write to */
|
||||
int nWrite; /* Return value from seekAndWrite() */
|
||||
|
||||
if( ftruncate(pFile->h, nSize) ){
|
||||
if( robust_ftruncate(pFile->h, nSize) ){
|
||||
pFile->lastErrno = errno;
|
||||
return SQLITE_IOERR_TRUNCATE;
|
||||
return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
|
||||
}
|
||||
iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
|
||||
do {
|
||||
@@ -3427,7 +3525,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
||||
|
||||
pShmNode->h = open(zShmFilename, O_RDWR|O_CREAT, (sStat.st_mode & 0777));
|
||||
if( pShmNode->h<0 ){
|
||||
rc = SQLITE_CANTOPEN_BKPT;
|
||||
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
|
||||
goto shm_open_err;
|
||||
}
|
||||
|
||||
@@ -3436,8 +3534,8 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
||||
*/
|
||||
rc = SQLITE_OK;
|
||||
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
|
||||
if( ftruncate(pShmNode->h, 0) ){
|
||||
rc = SQLITE_IOERR_SHMOPEN;
|
||||
if( robust_ftruncate(pShmNode->h, 0) ){
|
||||
rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -3542,8 +3640,8 @@ static int unixShmMap(
|
||||
** the requested memory region.
|
||||
*/
|
||||
if( !bExtend ) goto shmpage_out;
|
||||
if( ftruncate(pShmNode->h, nByte) ){
|
||||
rc = SQLITE_IOERR_SHMSIZE;
|
||||
if( robust_ftruncate(pShmNode->h, nByte) ){
|
||||
rc = unixLogError(SQLITE_IOERR_SHMSIZE,"ftruncate",pShmNode->zFilename);
|
||||
goto shmpage_out;
|
||||
}
|
||||
}
|
||||
@@ -4262,7 +4360,7 @@ static int openDirectory(const char *zFilename, int *pFd){
|
||||
}
|
||||
}
|
||||
*pFd = fd;
|
||||
return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN_BKPT);
|
||||
return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4603,7 +4701,7 @@ static int unixOpen(
|
||||
fd = open(zName, openFlags, openMode);
|
||||
}
|
||||
if( fd<0 ){
|
||||
rc = SQLITE_CANTOPEN_BKPT;
|
||||
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
|
||||
goto open_finished;
|
||||
}
|
||||
}
|
||||
@@ -4735,7 +4833,7 @@ static int unixDelete(
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
SimulateIOError(return SQLITE_IOERR_DELETE);
|
||||
if( unlink(zPath)==(-1) && errno!=ENOENT ){
|
||||
return SQLITE_IOERR_DELETE;
|
||||
return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
|
||||
}
|
||||
#ifndef SQLITE_DISABLE_DIRSYNC
|
||||
if( dirSync ){
|
||||
@@ -4748,10 +4846,10 @@ static int unixDelete(
|
||||
if( fsync(fd) )
|
||||
#endif
|
||||
{
|
||||
rc = SQLITE_IOERR_DIR_FSYNC;
|
||||
rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
|
||||
}
|
||||
if( close(fd)&&!rc ){
|
||||
rc = SQLITE_IOERR_DIR_CLOSE;
|
||||
rc = unixLogError(SQLITE_IOERR_DIR_CLOSE, "close", zPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4835,7 +4933,7 @@ static int unixFullPathname(
|
||||
}else{
|
||||
int nCwd;
|
||||
if( getcwd(zOut, nOut-1)==0 ){
|
||||
return SQLITE_CANTOPEN_BKPT;
|
||||
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
|
||||
}
|
||||
nCwd = (int)strlen(zOut);
|
||||
sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
|
||||
@@ -4939,7 +5037,7 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
|
||||
assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
|
||||
nBuf = sizeof(t) + sizeof(pid);
|
||||
}else{
|
||||
nBuf = read(fd, zBuf, nBuf);
|
||||
do{ nBuf = read(fd, zBuf, nBuf); }while( nBuf<0 && errno==EINTR );
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
@@ -5699,7 +5797,7 @@ static int proxyTakeConch(unixFile *pFile){
|
||||
strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
|
||||
}
|
||||
writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
|
||||
ftruncate(conchFile->h, writeSize);
|
||||
robust_ftruncate(conchFile->h, writeSize);
|
||||
rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
|
||||
fsync(conchFile->h);
|
||||
/* If we created a new conch file (not just updated the contents of a
|
||||
@@ -5707,6 +5805,7 @@ static int proxyTakeConch(unixFile *pFile){
|
||||
*/
|
||||
if( rc==SQLITE_OK && createConch ){
|
||||
struct stat buf;
|
||||
int rc;
|
||||
int err = fstat(pFile->h, &buf);
|
||||
if( err==0 ){
|
||||
mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
|
||||
@@ -5715,7 +5814,10 @@ static int proxyTakeConch(unixFile *pFile){
|
||||
#ifndef SQLITE_PROXY_DEBUG
|
||||
fchmod(conchFile->h, cmode);
|
||||
#else
|
||||
if( fchmod(conchFile->h, cmode)!=0 ){
|
||||
do{
|
||||
rc = fchmod(conchFile->h, cmode);
|
||||
}while( rc==(-1) && errno==EINTR );
|
||||
if( rc!=0 ){
|
||||
int code = errno;
|
||||
fprintf(stderr, "fchmod %o FAILED with %d %s\n",
|
||||
cmode, code, strerror(code));
|
||||
|
||||
+51
-17
@@ -2915,11 +2915,37 @@ static int pagerRollbackWal(Pager *pPager){
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Update the value of the change-counter at offsets 24 and 92 in
|
||||
** the header and the sqlite version number at offset 96.
|
||||
**
|
||||
** This is an unconditional update. See also the pager_incr_changecounter()
|
||||
** routine which only updates the change-counter if the update is actually
|
||||
** needed, as determined by the pPager->changeCountDone state variable.
|
||||
*/
|
||||
static void pager_write_changecounter(PgHdr *pPg){
|
||||
u32 change_counter;
|
||||
|
||||
/* Increment the value just read and write it back to byte 24. */
|
||||
change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
|
||||
put32bits(((char*)pPg->pData)+24, change_counter);
|
||||
|
||||
/* Also store the SQLite version number in bytes 96..99 and in
|
||||
** bytes 92..95 store the change counter for which the version number
|
||||
** is valid. */
|
||||
put32bits(((char*)pPg->pData)+92, change_counter);
|
||||
put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER);
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is a wrapper around sqlite3WalFrames(). As well as logging
|
||||
** the contents of the list of pages headed by pList (connected by pDirty),
|
||||
** this function notifies any active backup processes that the pages have
|
||||
** changed.
|
||||
** changed.
|
||||
**
|
||||
** The list of pages passed into this routine is always sorted by page number.
|
||||
** Hence, if page 1 appears anywhere on the list, it will be the first page.
|
||||
*/
|
||||
static int pagerWalFrames(
|
||||
Pager *pPager, /* Pager object */
|
||||
@@ -2929,8 +2955,19 @@ static int pagerWalFrames(
|
||||
int syncFlags /* Flags to pass to OsSync() (or 0) */
|
||||
){
|
||||
int rc; /* Return code */
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
|
||||
PgHdr *p; /* For looping over pages */
|
||||
#endif
|
||||
|
||||
assert( pPager->pWal );
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Verify that the page list is in accending order */
|
||||
for(p=pList; p && p->pDirty; p=p->pDirty){
|
||||
assert( p->pgno < p->pDirty->pgno );
|
||||
}
|
||||
#endif
|
||||
|
||||
if( pList->pgno==1 ) pager_write_changecounter(pList);
|
||||
rc = sqlite3WalFrames(pPager->pWal,
|
||||
pPager->pageSize, pList, nTruncate, isCommit, syncFlags
|
||||
);
|
||||
@@ -2942,9 +2979,8 @@ static int pagerWalFrames(
|
||||
}
|
||||
|
||||
#ifdef SQLITE_CHECK_PAGES
|
||||
{
|
||||
PgHdr *p;
|
||||
for(p=pList; p; p=p->pDirty) pager_set_pagehash(p);
|
||||
for(p=pList; p; p=p->pDirty){
|
||||
pager_set_pagehash(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3969,6 +4005,7 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
|
||||
char *pData; /* Data to write */
|
||||
|
||||
assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
|
||||
if( pList->pgno==1 ) pager_write_changecounter(pList);
|
||||
|
||||
/* Encode the database */
|
||||
CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData);
|
||||
@@ -5489,7 +5526,13 @@ void sqlite3PagerDontWrite(PgHdr *pPg){
|
||||
/*
|
||||
** This routine is called to increment the value of the database file
|
||||
** change-counter, stored as a 4-byte big-endian integer starting at
|
||||
** byte offset 24 of the pager file.
|
||||
** byte offset 24 of the pager file. The secondary change counter at
|
||||
** 92 is also updated, as is the SQLite version number at offset 96.
|
||||
**
|
||||
** But this only happens if the pPager->changeCountDone flag is false.
|
||||
** To avoid excess churning of page 1, the update only happens once.
|
||||
** See also the pager_write_changecounter() routine that does an
|
||||
** unconditional update of the change counters.
|
||||
**
|
||||
** If the isDirectMode flag is zero, then this is done by calling
|
||||
** sqlite3PagerWrite() on page 1, then modifying the contents of the
|
||||
@@ -5530,7 +5573,6 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
|
||||
|
||||
if( !pPager->changeCountDone && pPager->dbSize>0 ){
|
||||
PgHdr *pPgHdr; /* Reference to page 1 */
|
||||
u32 change_counter; /* Initial value of change-counter field */
|
||||
|
||||
assert( !pPager->tempFile && isOpen(pPager->fd) );
|
||||
|
||||
@@ -5543,21 +5585,13 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
|
||||
** direct mode, page 1 is always held in cache and hence the PagerGet()
|
||||
** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
|
||||
*/
|
||||
if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){
|
||||
if( !DIRECT_MODE && rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerWrite(pPgHdr);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
/* Increment the value just read and write it back to byte 24. */
|
||||
change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers);
|
||||
change_counter++;
|
||||
put32bits(((char*)pPgHdr->pData)+24, change_counter);
|
||||
|
||||
/* Also store the SQLite version number in bytes 96..99 and in
|
||||
** bytes 92..95 store the change counter for which the version number
|
||||
** is valid. */
|
||||
put32bits(((char*)pPgHdr->pData)+92, change_counter);
|
||||
put32bits(((char*)pPgHdr->pData)+96, SQLITE_VERSION_NUMBER);
|
||||
/* Actually do the update of the change counter */
|
||||
pager_write_changecounter(pPgHdr);
|
||||
|
||||
/* If running in direct mode, write the contents of page 1 to the file. */
|
||||
if( DIRECT_MODE ){
|
||||
|
||||
@@ -1573,7 +1573,8 @@ static int walCheckpoint(
|
||||
szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
|
||||
testcase( szPage<=32768 );
|
||||
testcase( szPage>=65536 );
|
||||
if( pWal->hdr.mxFrame==0 ) return SQLITE_OK;
|
||||
pInfo = walCkptInfo(pWal);
|
||||
if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
|
||||
|
||||
/* Allocate the iterator */
|
||||
rc = walIteratorInit(pWal, &pIter);
|
||||
@@ -1595,7 +1596,6 @@ static int walCheckpoint(
|
||||
*/
|
||||
mxSafeFrame = pWal->hdr.mxFrame;
|
||||
mxPage = pWal->hdr.nPage;
|
||||
pInfo = walCkptInfo(pWal);
|
||||
for(i=1; i<WAL_NREADER; i++){
|
||||
u32 y = pInfo->aReadMark[i];
|
||||
if( mxSafeFrame>=y ){
|
||||
@@ -1916,10 +1916,31 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
|
||||
assert( pWal->readLock<0 ); /* Not currently locked */
|
||||
|
||||
/* Take steps to avoid spinning forever if there is a protocol error. */
|
||||
/* Take steps to avoid spinning forever if there is a protocol error.
|
||||
**
|
||||
** Circumstances that cause a RETRY should only last for the briefest
|
||||
** instances of time. No I/O or other system calls are done while the
|
||||
** locks are held, so the locks should not be held for very long. But
|
||||
** if we are unlucky, another process that is holding a lock might get
|
||||
** paged out or take a page-fault that is time-consuming to resolve,
|
||||
** during the few nanoseconds that it is holding the lock. In that case,
|
||||
** it might take longer than normal for the lock to free.
|
||||
**
|
||||
** After 5 RETRYs, we begin calling sqlite3OsSleep(). The first few
|
||||
** calls to sqlite3OsSleep() have a delay of 1 microsecond. Really this
|
||||
** is more of a scheduler yield than an actual delay. But on the 10th
|
||||
** an subsequent retries, the delays start becoming longer and longer,
|
||||
** so that on the 100th (and last) RETRY we delay for 21 milliseconds.
|
||||
** The total delay time before giving up is less than 1 second.
|
||||
*/
|
||||
if( cnt>5 ){
|
||||
if( cnt>100 ) return SQLITE_PROTOCOL;
|
||||
sqlite3OsSleep(pWal->pVfs, 1);
|
||||
int nDelay = 1; /* Pause time in microseconds */
|
||||
if( cnt>100 ){
|
||||
VVA_ONLY( pWal->lockError = 1; )
|
||||
return SQLITE_PROTOCOL;
|
||||
}
|
||||
if( cnt>=10 ) nDelay = (cnt-9)*238; /* Max delay 21ms. Total delay 996ms */
|
||||
sqlite3OsSleep(pWal->pVfs, nDelay);
|
||||
}
|
||||
|
||||
if( !useWal ){
|
||||
@@ -2001,22 +2022,9 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
mxI = i;
|
||||
}
|
||||
}
|
||||
if( mxI==0 ){
|
||||
/* If we get here, it means that all of the aReadMark[] entries between
|
||||
** 1 and WAL_NREADER-1 are zero. Try to initialize aReadMark[1] to
|
||||
** be mxFrame, then retry.
|
||||
*/
|
||||
rc = walLockExclusive(pWal, WAL_READ_LOCK(1), 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
pInfo->aReadMark[1] = pWal->hdr.mxFrame;
|
||||
walUnlockExclusive(pWal, WAL_READ_LOCK(1), 1);
|
||||
rc = WAL_RETRY;
|
||||
}else if( rc==SQLITE_BUSY ){
|
||||
rc = WAL_RETRY;
|
||||
}
|
||||
return rc;
|
||||
}else{
|
||||
if( mxReadMark < pWal->hdr.mxFrame ){
|
||||
/* There was once an "if" here. The extra "{" is to preserve indentation. */
|
||||
{
|
||||
if( mxReadMark < pWal->hdr.mxFrame || mxI==0 ){
|
||||
for(i=1; i<WAL_NREADER; i++){
|
||||
rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -2029,6 +2037,10 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||
}
|
||||
}
|
||||
}
|
||||
if( mxI==0 ){
|
||||
assert( rc==SQLITE_BUSY );
|
||||
return WAL_RETRY;
|
||||
}
|
||||
|
||||
rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
|
||||
if( rc ){
|
||||
@@ -2089,6 +2101,10 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
||||
do{
|
||||
rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
|
||||
}while( rc==WAL_RETRY );
|
||||
testcase( (rc&0xff)==SQLITE_BUSY );
|
||||
testcase( (rc&0xff)==SQLITE_IOERR );
|
||||
testcase( rc==SQLITE_PROTOCOL );
|
||||
testcase( rc==SQLITE_OK );
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2406,6 +2422,8 @@ static int walRestartLog(Wal *pWal){
|
||||
volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
|
||||
assert( pInfo->nBackfill==pWal->hdr.mxFrame );
|
||||
if( pInfo->nBackfill>0 ){
|
||||
u32 salt1;
|
||||
sqlite3_randomness(4, &salt1);
|
||||
rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
|
||||
if( rc==SQLITE_OK ){
|
||||
/* If all readers are using WAL_READ_LOCK(0) (in other words if no
|
||||
@@ -2423,7 +2441,7 @@ static int walRestartLog(Wal *pWal){
|
||||
pWal->nCkpt++;
|
||||
pWal->hdr.mxFrame = 0;
|
||||
sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
|
||||
sqlite3_randomness(4, &aSalt[1]);
|
||||
aSalt[1] = salt1;
|
||||
walIndexWriteHdr(pWal);
|
||||
pInfo->nBackfill = 0;
|
||||
for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
|
||||
@@ -2440,6 +2458,10 @@ static int walRestartLog(Wal *pWal){
|
||||
int notUsed;
|
||||
rc = walTryBeginRead(pWal, ¬Used, 1, ++cnt);
|
||||
}while( rc==WAL_RETRY );
|
||||
assert( (rc&0xff)!=SQLITE_BUSY ); /* BUSY not possible when useWal==1 */
|
||||
testcase( (rc&0xff)==SQLITE_IOERR );
|
||||
testcase( rc==SQLITE_PROTOCOL );
|
||||
testcase( rc==SQLITE_OK );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
+3
-4
@@ -2315,10 +2315,9 @@ static int valueFromExpr(
|
||||
u8 aff,
|
||||
sqlite3_value **pp
|
||||
){
|
||||
/* The evalConstExpr() function will have already converted any TK_VARIABLE
|
||||
** expression involved in an comparison into a TK_REGISTER. */
|
||||
assert( pExpr->op!=TK_VARIABLE );
|
||||
if( pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE ){
|
||||
if( pExpr->op==TK_VARIABLE
|
||||
|| (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
|
||||
){
|
||||
int iVar = pExpr->iColumn;
|
||||
sqlite3VdbeSetVarmask(pParse->pVdbe, iVar); /* IMP: R-23257-02778 */
|
||||
*pp = sqlite3VdbeGetValue(pParse->pReprepare, iVar, aff);
|
||||
|
||||
@@ -299,13 +299,13 @@ do_test exclusive2-3.5 {
|
||||
INSERT INTO t1 VALUES(randstr(10, 400));
|
||||
}
|
||||
readPagerChangeCounter test.db
|
||||
} {4}
|
||||
} {5}
|
||||
do_test exclusive2-3.6 {
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(randstr(10, 400));
|
||||
}
|
||||
readPagerChangeCounter test.db
|
||||
} {5}
|
||||
} {6}
|
||||
sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -193,4 +193,24 @@ db close
|
||||
sqlite3 db test.db
|
||||
integrity_check filefmt-2.2.7
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Check that ticket 89b8c9ac54 is fixed. Before the fix, the SELECT
|
||||
# statement would return SQLITE_CORRUPT. The database file was not actually
|
||||
# corrupted, but SQLite was reporting that it was.
|
||||
#
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
do_execsql_test filefmt-3.1 {
|
||||
PRAGMA auto_vacuum = 1;
|
||||
CREATE TABLE t1(a, b);
|
||||
} {}
|
||||
do_test filefmt-3.2 {
|
||||
sql36231 { DROP TABLE t1 }
|
||||
} {}
|
||||
do_execsql_test filefmt-3.3 {
|
||||
SELECT * FROM sqlite_master;
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
# 2011 February 19
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing that error messages are logged via the
|
||||
# sqlite3_log() mechanism when certain errors are encountered in the
|
||||
# default unix or windows VFS modules.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
if {$::tcl_platform(platform)!="unix"} { finish_test ; return }
|
||||
set ::testprefix oserror
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
test_sqlite3_log xLog
|
||||
proc xLog {error_code msg} {
|
||||
if {[string match os_* $msg]} {
|
||||
lappend ::log $msg
|
||||
}
|
||||
}
|
||||
|
||||
proc do_re_test {tn script expression} {
|
||||
uplevel do_test $tn [list [subst -nocommands {
|
||||
set res [eval { $script }]
|
||||
if {[regexp {$expression} [set res]]} {
|
||||
set {} {$expression}
|
||||
} else {
|
||||
set res
|
||||
}
|
||||
}]] [list $expression]
|
||||
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Tests oserror-1.* test failures in the open() system call.
|
||||
#
|
||||
|
||||
# Test a failure in open() due to too many files.
|
||||
#
|
||||
do_test 1.1.1 {
|
||||
set ::log [list]
|
||||
list [catch {
|
||||
for {set i 0} {$i < 2000} {incr i} { sqlite3 dbh_$i test.db -readonly 1 }
|
||||
} msg] $msg
|
||||
} {1 {unable to open database file}}
|
||||
do_test 1.1.2 {
|
||||
catch { for {set i 0} {$i < 2000} {incr i} { dbh_$i close } }
|
||||
} {1}
|
||||
|
||||
do_re_test 1.1.3 { lindex $::log 0 } {^os_unix.c: open.*test.db$}
|
||||
|
||||
|
||||
# Test a failure in open() due to the path being a directory.
|
||||
#
|
||||
do_test 1.2.1 {
|
||||
file mkdir dir.db
|
||||
set ::log [list]
|
||||
list [catch { sqlite3 dbh dir.db } msg] $msg
|
||||
} {1 {unable to open database file}}
|
||||
|
||||
do_re_test 1.2.2 { lindex $::log 0 } {^os_unix.c: open.*dir.db$}
|
||||
|
||||
# Test a failure in open() due to the path not existing.
|
||||
#
|
||||
do_test 1.3.1 {
|
||||
set ::log [list]
|
||||
list [catch { sqlite3 dbh /x/y/z/test.db } msg] $msg
|
||||
} {1 {unable to open database file}}
|
||||
|
||||
do_re_test 1.3.2 { lindex $::log 0 } {^os_unix.c: open.*test.db$}
|
||||
|
||||
# Test a failure in open() due to the path not existing.
|
||||
#
|
||||
do_test 1.4.1 {
|
||||
set ::log [list]
|
||||
list [catch { sqlite3 dbh /root/test.db } msg] $msg
|
||||
} {1 {unable to open database file}}
|
||||
|
||||
do_re_test 1.4.2 { lindex $::log 0 } {^os_unix.c: open.*test.db$}
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Tests oserror-1.* test failures in the unlink() system call.
|
||||
#
|
||||
do_test 2.1.1 {
|
||||
set ::log [list]
|
||||
file mkdir test.db-wal
|
||||
forcedelete test.db
|
||||
sqlite3 dbh test.db
|
||||
catchsql { SELECT * FROM sqlite_master } dbh
|
||||
} {1 {disk I/O error}}
|
||||
|
||||
do_re_test 2.1.2 { lindex $::log 0 } {^os_unix.c: unlink.*test.db-wal$}
|
||||
do_test 2.1.3 {
|
||||
dbh close
|
||||
forcedelete test.db-wal
|
||||
} {}
|
||||
|
||||
|
||||
sqlite3_shutdown
|
||||
test_sqlite3_log
|
||||
sqlite3_initialize
|
||||
finish_test
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ set in [open $TOP/manifest]
|
||||
set zDate {}
|
||||
while {![eof $in]} {
|
||||
set line [gets $in]
|
||||
if {[regexp {^D (2.*[0-9])} $line all date]} {
|
||||
if {[regexp {^D (2[-0-9T:]+)} $line all date]} {
|
||||
set zDate [string map {T { }} $date]
|
||||
break
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user