mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Changes to make WAL more robust against SHM locking failures and OOM errors.
FossilOrigin-Name: ebf4041383c3cdddb5861960359abd209d4a1028
This commit is contained in:
22
manifest
22
manifest
@@ -1,8 +1,8 @@
|
|||||||
-----BEGIN PGP SIGNED MESSAGE-----
|
-----BEGIN PGP SIGNED MESSAGE-----
|
||||||
Hash: SHA1
|
Hash: SHA1
|
||||||
|
|
||||||
C In\sthe\srowhash.test,\smake\ssure\sglobal\svariables\sare\scleared\sprior\sto\suse.
|
C Changes\sto\smake\sWAL\smore\srobust\sagainst\sSHM\slocking\sfailures\sand\sOOM\serrors.
|
||||||
D 2010-06-02T14:43:30
|
D 2010-06-02T14:45:51
|
||||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||||
F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
|
F Makefile.in a5cad1f8f3e021356bfcc6c77dc16f6f1952bbc3
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -155,7 +155,7 @@ F src/os.c 1516984144e26734f97748f891f1a04f9e294c2e
|
|||||||
F src/os.h 6f604986f0ef0ca288c2330b16051ff70b431e8c
|
F src/os.h 6f604986f0ef0ca288c2330b16051ff70b431e8c
|
||||||
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
||||||
F src/os_os2.c 665876d5eec7585226b0a1cf5e18098de2b2da19
|
F src/os_os2.c 665876d5eec7585226b0a1cf5e18098de2b2da19
|
||||||
F src/os_unix.c 31511480da88947d39c9e12560a11d4495e19832
|
F src/os_unix.c 7ae9257f65b32f20d777e880700a84e7dac8051e
|
||||||
F src/os_win.c f815403c51a2adad30244374c801dd7fd2734567
|
F src/os_win.c f815403c51a2adad30244374c801dd7fd2734567
|
||||||
F src/pager.c acbef227bf158776449907c275c5d9332e4e52f9
|
F src/pager.c acbef227bf158776449907c275c5d9332e4e52f9
|
||||||
F src/pager.h 76466c3a5af56943537f68b1f16567101a0cd1d0
|
F src/pager.h 76466c3a5af56943537f68b1f16567101a0cd1d0
|
||||||
@@ -171,7 +171,7 @@ F src/resolve.c ac5f1a713cd1ae77f08b83cc69581e11bf5ae6f9
|
|||||||
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
||||||
F src/select.c c03d8a0565febcde8c6a12c5d77d065fddae889b
|
F src/select.c c03d8a0565febcde8c6a12c5d77d065fddae889b
|
||||||
F src/shell.c fd4ccdb37c3b68de0623eb938a649e0990710714
|
F src/shell.c fd4ccdb37c3b68de0623eb938a649e0990710714
|
||||||
F src/sqlite.h.in 4f72e39f1edeccaf2a5913483bce2f704492b892
|
F src/sqlite.h.in 60f4fcfe18bcb53ed0002989837b68aeeba79a5e
|
||||||
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
|
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
|
||||||
F src/sqliteInt.h 4e26920ede6da1b6f154251fb4f89f65f78979e0
|
F src/sqliteInt.h 4e26920ede6da1b6f154251fb4f89f65f78979e0
|
||||||
F src/sqliteLimit.h 196e2f83c3b444c4548fc1874f52f84fdbda40f3
|
F src/sqliteLimit.h 196e2f83c3b444c4548fc1874f52f84fdbda40f3
|
||||||
@@ -227,7 +227,7 @@ F src/vdbeblob.c 5327132a42a91e8b7acfb60b9d2c3b1c5c863e0e
|
|||||||
F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
|
F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
|
||||||
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
|
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
|
||||||
F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda
|
F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda
|
||||||
F src/wal.c 2bd4ef3bfeb2481e9edd3d1858ff8db0bc3a650d
|
F src/wal.c e36af9e75768d1dc790392089b10cf272abccefa
|
||||||
F src/wal.h 1c1c9feb629b7f4afcbe0b47f80f47c5551d3a02
|
F src/wal.h 1c1c9feb629b7f4afcbe0b47f80f47c5551d3a02
|
||||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||||
F src/where.c 75fee9e255b62f773fcadd1d1f25b6f63ac7a356
|
F src/where.c 75fee9e255b62f773fcadd1d1f25b6f63ac7a356
|
||||||
@@ -818,14 +818,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
|||||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||||
P c24ac3563f46fc6bcf7e45ee171afd3ae7d2faa8
|
P 28efe0a40405567f3eaf334b6603282d5adac792
|
||||||
R 00a157c07ad0e7a71db4a2e73d42f8e4
|
R 9d892b2c2c5007a01a863a8338bf83dd
|
||||||
U drh
|
U drh
|
||||||
Z e46aac16978246262ba376cf49913464
|
Z 8d64b4080a97b8f66f1bf92b76c05ca5
|
||||||
-----BEGIN PGP SIGNATURE-----
|
-----BEGIN PGP SIGNATURE-----
|
||||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||||
|
|
||||||
iD8DBQFMBm4VoxKgR168RlERAhb3AJ9bqFhxwgZ6DohhkaiSxdI+Dne3iQCfS41x
|
iD8DBQFMBm6ioxKgR168RlERAqErAJ9ySZWhR4zIr4TMIPtUXND7LUScBACeK1dS
|
||||||
jKYaDVEfVJDuwV1vKuW32gg=
|
Xn9N4779qMX9jCkGApiXX1s=
|
||||||
=jOCy
|
=nr7w
|
||||||
-----END PGP SIGNATURE-----
|
-----END PGP SIGNATURE-----
|
||||||
|
@@ -1 +1 @@
|
|||||||
28efe0a40405567f3eaf334b6603282d5adac792
|
ebf4041383c3cdddb5861960359abd209d4a1028
|
@@ -3362,7 +3362,7 @@ static int unixShmOpen(
|
|||||||
rc = SQLITE_OK;
|
rc = SQLITE_OK;
|
||||||
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
|
if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
|
||||||
if( ftruncate(pShmNode->h, 0) ){
|
if( ftruncate(pShmNode->h, 0) ){
|
||||||
rc = SQLITE_IOERR;
|
rc = SQLITE_IOERR_SHMOPEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
@@ -3469,7 +3469,7 @@ static int unixShmSize(
|
|||||||
if( reqSize<=(int)sStat.st_size ) break;
|
if( reqSize<=(int)sStat.st_size ) break;
|
||||||
}else{
|
}else{
|
||||||
*pNewSize = 0;
|
*pNewSize = 0;
|
||||||
rc = SQLITE_IOERR;
|
rc = SQLITE_IOERR_SHMSIZE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rc = ftruncate(pShmNode->h, reqSize);
|
rc = ftruncate(pShmNode->h, reqSize);
|
||||||
|
@@ -388,7 +388,7 @@ int sqlite3_exec(
|
|||||||
#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */
|
#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */
|
||||||
#define SQLITE_FULL 13 /* Insertion failed because database is full */
|
#define SQLITE_FULL 13 /* Insertion failed because database is full */
|
||||||
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
|
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
|
||||||
#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */
|
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
|
||||||
#define SQLITE_EMPTY 16 /* Database is empty */
|
#define SQLITE_EMPTY 16 /* Database is empty */
|
||||||
#define SQLITE_SCHEMA 17 /* The database schema changed */
|
#define SQLITE_SCHEMA 17 /* The database schema changed */
|
||||||
#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
|
#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
|
||||||
@@ -444,6 +444,9 @@ int sqlite3_exec(
|
|||||||
#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
|
#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
|
||||||
#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
|
#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
|
||||||
#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
|
#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
|
||||||
|
#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
|
||||||
|
#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
|
||||||
|
#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
|
||||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||||
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
|
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
|
||||||
|
40
src/wal.c
40
src/wal.c
@@ -377,6 +377,9 @@ struct Wal {
|
|||||||
WalIndexHdr hdr; /* Wal-index header for current transaction */
|
WalIndexHdr hdr; /* Wal-index header for current transaction */
|
||||||
char *zWalName; /* Name of WAL file */
|
char *zWalName; /* Name of WAL file */
|
||||||
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
|
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
|
||||||
|
#ifdef SQLITE_DEBUG
|
||||||
|
u8 lockError; /* True if a locking error has occurred */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -629,6 +632,7 @@ static int walLockShared(Wal *pWal, int lockIdx){
|
|||||||
SQLITE_SHM_LOCK | SQLITE_SHM_SHARED);
|
SQLITE_SHM_LOCK | SQLITE_SHM_SHARED);
|
||||||
WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
|
WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
|
||||||
walLockName(lockIdx), rc ? "failed" : "ok"));
|
walLockName(lockIdx), rc ? "failed" : "ok"));
|
||||||
|
VVA_ONLY( pWal->lockError = (rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
static void walUnlockShared(Wal *pWal, int lockIdx){
|
static void walUnlockShared(Wal *pWal, int lockIdx){
|
||||||
@@ -644,6 +648,7 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){
|
|||||||
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
|
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
|
||||||
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
|
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
|
||||||
walLockName(lockIdx), n, rc ? "failed" : "ok"));
|
walLockName(lockIdx), n, rc ? "failed" : "ok"));
|
||||||
|
VVA_ONLY( pWal->lockError = (rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
|
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
|
||||||
@@ -1693,7 +1698,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
|
|||||||
** so it takes care to hold an exclusive lock on the corresponding
|
** so it takes care to hold an exclusive lock on the corresponding
|
||||||
** WAL_READ_LOCK() while changing values.
|
** WAL_READ_LOCK() while changing values.
|
||||||
*/
|
*/
|
||||||
static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal){
|
static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
|
||||||
volatile WalIndexHdr *pHdr; /* Header of the wal-index */
|
volatile WalIndexHdr *pHdr; /* Header of the wal-index */
|
||||||
volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */
|
volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */
|
||||||
u32 mxReadMark; /* Largest aReadMark[] value */
|
u32 mxReadMark; /* Largest aReadMark[] value */
|
||||||
@@ -1703,6 +1708,12 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal){
|
|||||||
|
|
||||||
assert( pWal->readLock<0 ); /* Not currently locked */
|
assert( pWal->readLock<0 ); /* Not currently locked */
|
||||||
|
|
||||||
|
/* Take steps to avoid spinning forever if there is a protocol error. */
|
||||||
|
if( cnt>5 ){
|
||||||
|
if( cnt>100 ) return SQLITE_PROTOCOL;
|
||||||
|
sqlite3OsSleep(pWal->pVfs, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if( !useWal ){
|
if( !useWal ){
|
||||||
rc = walIndexReadHdr(pWal, pChanged);
|
rc = walIndexReadHdr(pWal, pChanged);
|
||||||
if( rc==SQLITE_BUSY ){
|
if( rc==SQLITE_BUSY ){
|
||||||
@@ -1820,9 +1831,10 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal){
|
|||||||
*/
|
*/
|
||||||
int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
||||||
int rc; /* Return code */
|
int rc; /* Return code */
|
||||||
|
int cnt = 0; /* Number of TryBeginRead attempts */
|
||||||
|
|
||||||
do{
|
do{
|
||||||
rc = walTryBeginRead(pWal, pChanged, 0);
|
rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
|
||||||
}while( rc==WAL_RETRY );
|
}while( rc==WAL_RETRY );
|
||||||
walIndexUnmap(pWal);
|
walIndexUnmap(pWal);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -1859,8 +1871,8 @@ int sqlite3WalRead(
|
|||||||
u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */
|
u32 iLast = pWal->hdr.mxFrame; /* Last page in WAL for this reader */
|
||||||
int iHash; /* Used to loop through N hash tables */
|
int iHash; /* Used to loop through N hash tables */
|
||||||
|
|
||||||
/* This routine is only called from within a read transaction */
|
/* This routine is only be called from within a read transaction. */
|
||||||
assert( pWal->readLock>=0 );
|
assert( pWal->readLock>=0 || pWal->lockError );
|
||||||
|
|
||||||
/* If the "last page" field of the wal-index header snapshot is 0, then
|
/* If the "last page" field of the wal-index header snapshot is 0, then
|
||||||
** no data will be read from the wal under any circumstances. Return early
|
** no data will be read from the wal under any circumstances. Return early
|
||||||
@@ -1982,7 +1994,7 @@ int sqlite3WalRead(
|
|||||||
** Set *pPgno to the size of the database file (or zero, if unknown).
|
** Set *pPgno to the size of the database file (or zero, if unknown).
|
||||||
*/
|
*/
|
||||||
void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno){
|
void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno){
|
||||||
assert( pWal->readLock>=0 );
|
assert( pWal->readLock>=0 || pWal->lockError );
|
||||||
*pPgno = pWal->hdr.nPage;
|
*pPgno = pWal->hdr.nPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2133,6 +2145,8 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){
|
|||||||
*/
|
*/
|
||||||
static int walRestartLog(Wal *pWal){
|
static int walRestartLog(Wal *pWal){
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
|
int cnt;
|
||||||
|
|
||||||
if( pWal->readLock==0
|
if( pWal->readLock==0
|
||||||
&& SQLITE_OK==(rc = walIndexMap(pWal, walMappingSize(pWal->hdr.mxFrame)))
|
&& SQLITE_OK==(rc = walIndexMap(pWal, walMappingSize(pWal->hdr.mxFrame)))
|
||||||
){
|
){
|
||||||
@@ -2163,9 +2177,10 @@ static int walRestartLog(Wal *pWal){
|
|||||||
}
|
}
|
||||||
walUnlockShared(pWal, WAL_READ_LOCK(0));
|
walUnlockShared(pWal, WAL_READ_LOCK(0));
|
||||||
pWal->readLock = -1;
|
pWal->readLock = -1;
|
||||||
|
cnt = 0;
|
||||||
do{
|
do{
|
||||||
int notUsed;
|
int notUsed;
|
||||||
rc = walTryBeginRead(pWal, ¬Used, 1);
|
rc = walTryBeginRead(pWal, ¬Used, 1, ++cnt);
|
||||||
}while( rc==WAL_RETRY );
|
}while( rc==WAL_RETRY );
|
||||||
|
|
||||||
/* Unmap the wal-index before returning. Otherwise the VFS layer may
|
/* Unmap the wal-index before returning. Otherwise the VFS layer may
|
||||||
@@ -2418,22 +2433,25 @@ int sqlite3WalCallback(Wal *pWal){
|
|||||||
*/
|
*/
|
||||||
int sqlite3WalExclusiveMode(Wal *pWal, int op){
|
int sqlite3WalExclusiveMode(Wal *pWal, int op){
|
||||||
int rc;
|
int rc;
|
||||||
assert( pWal->writeLock==0 && pWal->readLock>=0 );
|
assert( pWal->writeLock==0 );
|
||||||
|
/* pWal->readLock is usually set, but might be -1 if there was a prior OOM */
|
||||||
|
assert( pWal->readLock>=0 || pWal->lockError );
|
||||||
if( op==0 ){
|
if( op==0 ){
|
||||||
if( pWal->exclusiveMode ){
|
if( pWal->exclusiveMode ){
|
||||||
pWal->exclusiveMode = 0;
|
pWal->exclusiveMode = 0;
|
||||||
if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){
|
if( pWal->readLock>=0
|
||||||
|
&& walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK
|
||||||
|
){
|
||||||
pWal->exclusiveMode = 1;
|
pWal->exclusiveMode = 1;
|
||||||
}
|
}
|
||||||
rc = pWal->exclusiveMode==0;
|
rc = pWal->exclusiveMode==0;
|
||||||
}else{
|
}else{
|
||||||
/* No changes. Either already in locking_mode=NORMAL or else the
|
/* Already in locking_mode=NORMAL */
|
||||||
** acquisition of the read-lock failed. The pager must continue to
|
|
||||||
** hold the database exclusive lock. */
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
}else if( op>0 ){
|
}else if( op>0 ){
|
||||||
assert( pWal->exclusiveMode==0 );
|
assert( pWal->exclusiveMode==0 );
|
||||||
|
assert( pWal->readLock>=0 );
|
||||||
walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
|
walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
|
||||||
pWal->exclusiveMode = 1;
|
pWal->exclusiveMode = 1;
|
||||||
rc = 1;
|
rc = 1;
|
||||||
|
Reference in New Issue
Block a user