From 237768dad34ae4a72ac4acf47e4f81cb143089ab Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 20 Feb 2011 03:11:27 +0000 Subject: [PATCH] Backport the SQLITE_PROTOCOL fix and the extra defensive measure to version 3.7.4. FossilOrigin-Name: bcc22c4b800e1f5b5619193890548d2a6bc19280 --- manifest | 22 ++++++++++-------- manifest.uuid | 2 +- src/wal.c | 62 ++++++++++++++++++++++++++++++++++----------------- 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index 6f9e049703..6e326189e4 100644 --- a/manifest +++ b/manifest @@ -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 Backport\sthe\sSQLITE_PROTOCOL\sfix\sand\sthe\sextra\sdefensive\smeasure\sto\sversion\n3.7.4. +D 2011-02-20T03:11:27.935 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 4547616ad2286053af6ccccefa242dc925e49bf0 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -240,7 +240,7 @@ 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 20a07fb265abeae6d7a1908e9f7c50f2584a2dfa F src/wal.h c1aac6593a0b02b15dc625987e619edeab39292e F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f F src/where.c fa22d45b2577c77146f2e894d58011d472d64103 @@ -897,14 +897,18 @@ 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 a586a4deeb25330037a49df295b36aaf624d0f45 +R d771e0380dc80bd4c14fcbb1ae00b759 +T *bgcolor * #ffd0c0 +T *branch * branch-3.7.4 +T *sym-branch-3.7.4 * +T -sym-trunk * U drh -Z 584aed3667b20c0c4d105810047e9fd4 +Z af96b97a7d73ec7f5853e8cfa091cc04 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) -iD8DBQFM/pWUoxKgR168RlERAuOQAJ9BLHxhysfzWC+psYkAVcf2xDsyTgCeIRqp -FF5a9ESJ6yucR80Re9sEWmU= -=ZPd3 +iD8DBQFNYIZkoxKgR168RlERAmtNAJwL9JL9iqNlElhdUnfzKoR8DfDpoACcD2V8 +Ukcg1He63egBJnFmVWmm6mY= +=ngBz -----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index 420ef50389..cf1815f9da 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a586a4deeb25330037a49df295b36aaf624d0f45 \ No newline at end of file +bcc22c4b800e1f5b5619193890548d2a6bc19280 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 3b217908b7..92d79513dd 100644 --- a/src/wal.c +++ b/src/wal.c @@ -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; inBackfill==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; iaReadMark[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; } -- 2.47.2