Bug fix: sqlite_exec() would sometimes return SQLITE_PROTOCOL when it
should have returned SQLITE_BUSY. There was also a deadlock that the
previous bug was masking. (CVS 322)
FossilOrigin-Name: 585ed5ebf1c1afc8ae1d569b121208018d8ecd49
diff --git a/src/btree.c b/src/btree.c
index 574627d..00f8982 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.41 2001/11/23 00:24:12 drh Exp $
+** $Id: btree.c,v 1.42 2001/12/05 00:21:20 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@@ -677,6 +677,24 @@
}
/*
+** If there are no outstanding cursors and we are not in the middle
+** of a transaction but there is a read lock on the database, then
+** this routine unrefs the first page of the database file which
+** has the effect of releasing the read lock.
+**
+** If there are any outstanding cursors, this routine is a no-op.
+**
+** If there is a transaction in progress, this routine is a no-op.
+*/
+static void unlockBtreeIfUnused(Btree *pBt){
+ if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
+ sqlitepager_unref(pBt->page1);
+ pBt->page1 = 0;
+ pBt->inTrans = 0;
+ }
+}
+
+/*
** Create a new database by initializing the first two pages of the
** file.
*/
@@ -725,33 +743,19 @@
return rc;
}
}
- if( !sqlitepager_isreadonly(pBt->pPager) ){
- rc = sqlitepager_write(pBt->page1);
- if( rc!=SQLITE_OK ){
- return rc;
- }
+ if( sqlitepager_isreadonly(pBt->pPager) ){
+ return SQLITE_READONLY;
+ }
+ rc = sqlitepager_write(pBt->page1);
+ if( rc==SQLITE_OK ){
rc = newDatabase(pBt);
}
- pBt->inTrans = 1;
- return rc;
-}
-
-/*
-** If there are no outstanding cursors and we are not in the middle
-** of a transaction but there is a read lock on the database, then
-** this routine unrefs the first page of the database file which
-** has the effect of releasing the read lock.
-**
-** If there are any outstanding cursors, this routine is a no-op.
-**
-** If there is a transaction in progress, this routine is a no-op.
-*/
-static void unlockBtreeIfUnused(Btree *pBt){
- if( pBt->inTrans==0 && pBt->pCursor==0 && pBt->page1!=0 ){
- sqlitepager_unref(pBt->page1);
- pBt->page1 = 0;
- pBt->inTrans = 0;
+ if( rc==SQLITE_OK ){
+ pBt->inTrans = 1;
+ }else{
+ unlockBtreeIfUnused(pBt);
}
+ return rc;
}
/*
diff --git a/src/build.c b/src/build.c
index 625be67..006f459 100644
--- a/src/build.c
+++ b/src/build.c
@@ -25,7 +25,7 @@
** ROLLBACK
** PRAGMA
**
-** $Id: build.c,v 1.57 2001/11/22 00:01:27 drh Exp $
+** $Id: build.c,v 1.58 2001/12/05 00:21:20 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -553,7 +553,7 @@
*/
static void changeCookie(sqlite *db){
if( db->next_cookie==db->schema_cookie ){
- db->next_cookie = db->schema_cookie + sqliteRandomByte(db) + 1;
+ db->next_cookie = db->schema_cookie + sqliteRandomByte() + 1;
db->flags |= SQLITE_InternChanges;
}
}
diff --git a/src/main.c b/src/main.c
index a9beba9..d59c612 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.50 2001/11/23 00:24:12 drh Exp $
+** $Id: main.c,v 1.51 2001/12/05 00:21:20 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -265,7 +265,7 @@
if( db==0 ) goto no_mem_on_open;
sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0);
- db->nextRowid = sqliteRandomInteger(db);
+ db->nextRowid = sqliteRandomInteger();
/* Open the backend database driver */
rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe);
diff --git a/src/os.h b/src/os.h
index 31edc76..f90b525 100644
--- a/src/os.h
+++ b/src/os.h
@@ -59,8 +59,8 @@
int sqliteOsUnlock(OsFile);
int sqliteOsRandomSeed(char*);
int sqliteOsSleep(int ms);
-void sqliteOsEnterMutex();
-void sqliteOsLeaveMutex();
+void sqliteOsEnterMutex(void);
+void sqliteOsLeaveMutex(void);
diff --git a/src/pager.c b/src/pager.c
index a620a3a..378a9e4 100644
--- a/src/pager.c
+++ b/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.31 2001/11/22 00:01:27 drh Exp $
+** @(#) $Id: pager.c,v 1.32 2001/12/05 00:21:20 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
@@ -955,13 +955,20 @@
}
sqliteOsUnlock(pPager->fd);
if( sqliteOsLock(pPager->fd, 1)!=SQLITE_OK ){
+ sqliteOsUnlock(pPager->fd);
+ rc = sqliteOsLock(pPager->fd, 0);
sqliteFree(pPager->aInJournal);
sqliteOsClose(pPager->jfd);
sqliteOsDelete(pPager->zJournal);
pPager->journalOpen = 0;
- pPager->state = SQLITE_UNLOCK;
- pPager->errMask |= PAGER_ERR_LOCK;
- return SQLITE_PROTOCOL;
+ if( rc ){
+ pPager->state = SQLITE_UNLOCK;
+ pPager->errMask |= PAGER_ERR_LOCK;
+ return SQLITE_PROTOCOL;
+ }else{
+ pPager->state = SQLITE_READLOCK;
+ return SQLITE_BUSY;
+ }
}
pPager->state = SQLITE_WRITELOCK;
sqlitepager_pagecount(pPager);
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index b80eac9..03e0504 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.71 2001/11/22 00:01:27 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.72 2001/12/05 00:21:20 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
@@ -519,8 +519,8 @@
int sqliteExprAnalyzeAggregates(Parse*, Expr*);
void sqliteParseInfoReset(Parse*);
Vdbe *sqliteGetVdbe(Parse*);
-int sqliteRandomByte();
-int sqliteRandomInteger();
+int sqliteRandomByte(void);
+int sqliteRandomInteger(void);
void sqliteBeginTransaction(Parse*);
void sqliteCommitTransaction(Parse*);
void sqliteRollbackTransaction(Parse*);