diff options
author | drh <> | 2022-12-07 16:58:04 +0000 |
---|---|---|
committer | drh <> | 2022-12-07 16:58:04 +0000 |
commit | 7c66faa634be0e89553e0a985270788751f82238 (patch) | |
tree | cbd2fd476b739ab1e49a08a230b7169bef3623ea /src/memdb.c | |
parent | b54f71e205c578303fa50cfb11a985e9b73ca3b0 (diff) | |
download | sqlite-7c66faa634be0e89553e0a985270788751f82238.tar.gz sqlite-7c66faa634be0e89553e0a985270788751f82238.zip |
Streamline and improve testing of the locking in the memdb VFS.
Follow-on to [15f0be8a640e7bfa].
FossilOrigin-Name: d71a08375aeb525c10037c373b8eeb7e29f7dfaf7c4bfc02f4d99616c5940405
Diffstat (limited to 'src/memdb.c')
-rw-r--r-- | src/memdb.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/src/memdb.c b/src/memdb.c index 7485f51ff..4ea3cffde 100644 --- a/src/memdb.c +++ b/src/memdb.c @@ -370,21 +370,33 @@ static int memdbLock(sqlite3_file *pFile, int eLock){ int rc = SQLITE_OK; if( eLock==pThis->eLock ) return SQLITE_OK; memdbEnter(p); + assert( p->nWrLock==0 || p->nWrLock==1 ); /* No more than 1 write lock */ if( eLock>SQLITE_LOCK_SHARED ){ assert( pThis->eLock>=SQLITE_LOCK_SHARED ); if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){ rc = SQLITE_READONLY; }else if( eLock==SQLITE_LOCK_EXCLUSIVE ){ - /* Taking an EXCLUSIVE lock. Fail if we only have SHARED and any - ** other client has any kind of write-lock. Also fail if any other - ** client is holding read-lock. */ - if( pThis->eLock<=SQLITE_LOCK_SHARED && p->nWrLock ){ - rc = SQLITE_BUSY; - }else if( p->nRdLock>1 ){ + /* We never go for an EXCLUSIVE lock unless we already hold SHARED or + ** higher */ + assert( pThis->eLock>=SQLITE_LOCK_SHARED ); + testcase( pThis->eLock==SQLITE_LOCK_SHARED ); + + /* Because we are holding SHARED or more, there must be at least + ** one read lock */ + assert( p->nRdLock>0 ); + + /* The only way that there can be an existing write lock is if we + ** currently hold it. Otherwise, we would have never been able to + ** promote from NONE to SHARED. */ + assert( p->nWrLock==0 || pThis->eLock>SQLITE_LOCK_SHARED ); + + if( p->nRdLock>1 ){ + /* Cannot take EXCLUSIVE if somebody else is holding SHARED */ rc = SQLITE_BUSY; + }else{ + p->nWrLock = 1; } - p->nWrLock = 1; - }else if( pThis->eLock<=SQLITE_LOCK_SHARED ){ + }else if( ALWAYS(pThis->eLock<=SQLITE_LOCK_SHARED) ){ /* Upgrading to RESERVED or PENDING from SHARED. Fail if any other ** client has a write-lock of any kind. */ if( p->nWrLock ){ |