mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Better asserts(). But now some of the tests are busted again. (CVS 4320)
FossilOrigin-Name: e8060f85e7871572e2a38dc96f03e6e1f34cc8fd
This commit is contained in:
20
manifest
20
manifest
@@ -1,5 +1,5 @@
|
|||||||
C More\slocking\sfixes.\s\sNow\smakes\sit\sall\sthe\sway\sthrough\squick.test.\s\sThere\nare\serrors\sbut\sno\sassertion\sfaults.\s\sProgress.\s(CVS\s4319)
|
C Better\sasserts().\s\sBut\snow\ssome\sof\sthe\stests\sare\sbusted\sagain.\s(CVS\s4320)
|
||||||
D 2007-08-29T00:33:07
|
D 2007-08-29T04:00:58
|
||||||
F Makefile.in bfcc303429a5d9dcd552d807ee016c77427418c3
|
F Makefile.in bfcc303429a5d9dcd552d807ee016c77427418c3
|
||||||
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
||||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||||
@@ -76,13 +76,13 @@ F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
|
|||||||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||||
F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
|
F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
|
||||||
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
|
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
|
||||||
F src/alter.c fd78c6005456c727a6cb7c01c5266f2aacf6d401
|
F src/alter.c 977eeee31adc5c2b7b41c256ccbb84342e7e2ed4
|
||||||
F src/analyze.c a14237d869c6bea0846493b59317e4097e81a0b6
|
F src/analyze.c a28b43a5f79bfa7616ab506bb917077242098469
|
||||||
F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8
|
F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8
|
||||||
F src/auth.c 083c1205b45e3f52291ec539d396b4fc557856b3
|
F src/auth.c 083c1205b45e3f52291ec539d396b4fc557856b3
|
||||||
F src/btmutex.c 0abcf98bd6eff466c2c471c96259635169d53981
|
F src/btmutex.c c04e67d99d949a12beb17209f307950f21313980
|
||||||
F src/btree.c 0241f79766d718d524a28857c3899aee7a728194
|
F src/btree.c f9ea7d1e30d58cb1708aaa0c4c81a2761bd2bd13
|
||||||
F src/btree.h 21cea6453a7ed73c90535329b44910610f3c635e
|
F src/btree.h 7391b9e78ae441fe0fb3a6d3ae772770d35a4375
|
||||||
F src/btreeInt.h 1fa6510aa8601dc0358a5240d191335236d3cf76
|
F src/btreeInt.h 1fa6510aa8601dc0358a5240d191335236d3cf76
|
||||||
F src/build.c 99b0b0c44ce7673c00d8c0c97ce536e3b796328b
|
F src/build.c 99b0b0c44ce7673c00d8c0c97ce536e3b796328b
|
||||||
F src/callback.c a542236a68060caad378efa30006ca46cf77b1b2
|
F src/callback.c a542236a68060caad378efa30006ca46cf77b1b2
|
||||||
@@ -567,7 +567,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||||
P f093a0d7b29a819605e0527bf23a047e16c32688
|
P 844d40b8379d3374130e2d94f6e32c2cda34e0ca
|
||||||
R 61c7afc6574f5208f9d0bca844fc0424
|
R cf2e80aed60a12c772fc5c9b86deea93
|
||||||
U drh
|
U drh
|
||||||
Z b78638b8a0836a1559717f1c34999b51
|
Z b6b3d6523c723ce59d75a6cacc6da8b8
|
||||||
|
@@ -1 +1 @@
|
|||||||
844d40b8379d3374130e2d94f6e32c2cda34e0ca
|
e8060f85e7871572e2a38dc96f03e6e1f34cc8fd
|
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that used to generate VDBE code
|
** This file contains C code routines that used to generate VDBE code
|
||||||
** that implements the ALTER TABLE command.
|
** that implements the ALTER TABLE command.
|
||||||
**
|
**
|
||||||
** $Id: alter.c,v 1.30 2007/08/25 13:09:26 danielk1977 Exp $
|
** $Id: alter.c,v 1.31 2007/08/29 04:00:58 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -234,6 +234,7 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
|
|||||||
|
|
||||||
v = sqlite3GetVdbe(pParse);
|
v = sqlite3GetVdbe(pParse);
|
||||||
if( !v ) return;
|
if( !v ) return;
|
||||||
|
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
|
||||||
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||||
assert( iDb>=0 );
|
assert( iDb>=0 );
|
||||||
|
|
||||||
@@ -288,6 +289,7 @@ void sqlite3AlterRenameTable(
|
|||||||
|
|
||||||
if( db->mallocFailed ) goto exit_rename_table;
|
if( db->mallocFailed ) goto exit_rename_table;
|
||||||
assert( pSrc->nSrc==1 );
|
assert( pSrc->nSrc==1 );
|
||||||
|
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
|
||||||
|
|
||||||
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
|
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
|
||||||
if( !pTab ) goto exit_rename_table;
|
if( !pTab ) goto exit_rename_table;
|
||||||
@@ -446,6 +448,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
|
|||||||
assert( pNew );
|
assert( pNew );
|
||||||
|
|
||||||
db = pParse->db;
|
db = pParse->db;
|
||||||
|
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||||
iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
|
iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
|
||||||
zDb = db->aDb[iDb].zName;
|
zDb = db->aDb[iDb].zName;
|
||||||
zTab = pNew->zName;
|
zTab = pNew->zName;
|
||||||
@@ -556,6 +559,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
|
|||||||
|
|
||||||
/* Look up the table being altered. */
|
/* Look up the table being altered. */
|
||||||
assert( pParse->pNewTable==0 );
|
assert( pParse->pNewTable==0 );
|
||||||
|
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||||
if( db->mallocFailed ) goto exit_begin_add_column;
|
if( db->mallocFailed ) goto exit_begin_add_column;
|
||||||
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
|
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
|
||||||
if( !pTab ) goto exit_begin_add_column;
|
if( !pTab ) goto exit_begin_add_column;
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** This file contains code associated with the ANALYZE command.
|
** This file contains code associated with the ANALYZE command.
|
||||||
**
|
**
|
||||||
** @(#) $Id: analyze.c,v 1.21 2007/08/16 10:09:02 danielk1977 Exp $
|
** @(#) $Id: analyze.c,v 1.22 2007/08/29 04:00:58 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef SQLITE_OMIT_ANALYZE
|
#ifndef SQLITE_OMIT_ANALYZE
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
@@ -37,6 +37,8 @@ static void openStatTable(
|
|||||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||||
|
|
||||||
if( v==0 ) return;
|
if( v==0 ) return;
|
||||||
|
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||||
|
assert( sqlite3VdbeDb(v)==db );
|
||||||
pDb = &db->aDb[iDb];
|
pDb = &db->aDb[iDb];
|
||||||
if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){
|
if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){
|
||||||
/* The sqlite_stat1 tables does not exist. Create it.
|
/* The sqlite_stat1 tables does not exist. Create it.
|
||||||
@@ -100,7 +102,7 @@ static void analyzeOneTable(
|
|||||||
/* Do no analysis for tables that have no indices */
|
/* Do no analysis for tables that have no indices */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
|
||||||
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||||
assert( iDb>=0 );
|
assert( iDb>=0 );
|
||||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||||
@@ -258,6 +260,7 @@ static void analyzeTable(Parse *pParse, Table *pTab){
|
|||||||
int iStatCur;
|
int iStatCur;
|
||||||
|
|
||||||
assert( pTab!=0 );
|
assert( pTab!=0 );
|
||||||
|
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
|
||||||
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||||
iStatCur = pParse->nTab++;
|
iStatCur = pParse->nTab++;
|
||||||
@@ -288,6 +291,7 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
|
|||||||
|
|
||||||
/* Read the database schema. If an error occurs, leave an error message
|
/* Read the database schema. If an error occurs, leave an error message
|
||||||
** and code in pParse and return NULL. */
|
** and code in pParse and return NULL. */
|
||||||
|
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
|
||||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -382,6 +386,8 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
|||||||
char *zSql;
|
char *zSql;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||||
|
|
||||||
/* Clear any prior statistics */
|
/* Clear any prior statistics */
|
||||||
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
|
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
|
||||||
Index *pIdx = sqliteHashData(i);
|
Index *pIdx = sqliteHashData(i);
|
||||||
|
102
src/btmutex.c
102
src/btmutex.c
@@ -10,7 +10,7 @@
|
|||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
**
|
**
|
||||||
** $Id: btmutex.c,v 1.4 2007/08/29 00:33:07 drh Exp $
|
** $Id: btmutex.c,v 1.5 2007/08/29 04:00:58 drh Exp $
|
||||||
**
|
**
|
||||||
** This file contains code used to implement mutexes on Btree objects.
|
** This file contains code used to implement mutexes on Btree objects.
|
||||||
** This code really belongs in btree.c. But btree.c is getting too
|
** This code really belongs in btree.c. But btree.c is getting too
|
||||||
@@ -55,7 +55,7 @@ void sqlite3BtreeEnter(Btree *p){
|
|||||||
assert( p->sharable || p->wantToLock==0 );
|
assert( p->sharable || p->wantToLock==0 );
|
||||||
|
|
||||||
/* We should already hold a lock on the database connection */
|
/* We should already hold a lock on the database connection */
|
||||||
assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) );
|
assert( sqlite3_mutex_held(p->pSqlite->mutex) );
|
||||||
|
|
||||||
if( !p->sharable ) return;
|
if( !p->sharable ) return;
|
||||||
p->wantToLock++;
|
p->wantToLock++;
|
||||||
@@ -109,6 +109,20 @@ void sqlite3BtreeLeave(Btree *p){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
/*
|
||||||
|
** Return true if a mutex is held on the btree.
|
||||||
|
**
|
||||||
|
** This routine is used only from within assert() statements.
|
||||||
|
*/
|
||||||
|
int sqlite3BtreeHoldsMutex(Btree *p){
|
||||||
|
return sqlite3_mutex_held(p->pSqlite->mutex) &&
|
||||||
|
(p->sharable==0 ||
|
||||||
|
(p->locked && p->wantToLock && sqlite3_mutex_held(p->pBt->mutex)));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Enter the mutex on every Btree associated with a database
|
** Enter the mutex on every Btree associated with a database
|
||||||
** connection. This is needed (for example) prior to parsing
|
** connection. This is needed (for example) prior to parsing
|
||||||
@@ -125,24 +139,28 @@ void sqlite3BtreeLeave(Btree *p){
|
|||||||
*/
|
*/
|
||||||
void sqlite3BtreeEnterAll(sqlite3 *db){
|
void sqlite3BtreeEnterAll(sqlite3 *db){
|
||||||
int i;
|
int i;
|
||||||
Btree *p;
|
Btree *p, *pLater;
|
||||||
assert( sqlite3_mutex_held(db->mutex) );
|
assert( sqlite3_mutex_held(db->mutex) );
|
||||||
for(i=0; i<db->nDb && ((p = db->aDb[i].pBt)==0 || p->sharable==0); i++){}
|
for(i=0; i<db->nDb; i++){
|
||||||
if( i<db->nDb ){
|
p = db->aDb[i].pBt;
|
||||||
while( p->pNext ) p = p->pNext;
|
if( p && p->sharable ){
|
||||||
while( 1 ){
|
|
||||||
if( p->locked ){
|
|
||||||
sqlite3_mutex_leave(p->pBt->mutex);
|
|
||||||
p->locked = 0;
|
|
||||||
}
|
|
||||||
if( p->pPrev==0 ) break;
|
|
||||||
p = p->pPrev;
|
|
||||||
}
|
|
||||||
while( p ){
|
|
||||||
p->wantToLock++;
|
p->wantToLock++;
|
||||||
sqlite3_mutex_enter(p->pBt->mutex);
|
if( !p->locked ){
|
||||||
p->locked = 1;
|
assert( p->wantToLock==1 );
|
||||||
p = p->pNext;
|
while( p->pPrev ) p = p->pPrev;
|
||||||
|
while( p->locked && p->pNext ) p = p->pNext;
|
||||||
|
for(pLater = p->pNext; pLater; pLater=pLater->pNext){
|
||||||
|
if( pLater->locked ){
|
||||||
|
sqlite3_mutex_leave(pLater->pBt->mutex);
|
||||||
|
pLater->locked = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while( p ){
|
||||||
|
sqlite3_mutex_enter(p->pBt->mutex);
|
||||||
|
p->locked++;
|
||||||
|
p = p->pNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,20 +168,44 @@ void sqlite3BtreeLeaveAll(sqlite3 *db){
|
|||||||
int i;
|
int i;
|
||||||
Btree *p;
|
Btree *p;
|
||||||
assert( sqlite3_mutex_held(db->mutex) );
|
assert( sqlite3_mutex_held(db->mutex) );
|
||||||
for(i=0; i<db->nDb && ((p = db->aDb[i].pBt)==0 || p->sharable==0); i++){}
|
for(i=0; i<db->nDb; i++){
|
||||||
if( i<db->nDb ){
|
p = db->aDb[i].pBt;
|
||||||
while( p->pPrev ) p = p->pPrev;
|
if( p && p->sharable ){
|
||||||
while( p ){
|
assert( p->wantToLock>0 );
|
||||||
p->wantToLock--;
|
p->wantToLock--;
|
||||||
if( p->wantToLock==0 ){
|
if( p->wantToLock==0 ){
|
||||||
|
assert( p->locked );
|
||||||
sqlite3_mutex_leave(p->pBt->mutex);
|
sqlite3_mutex_leave(p->pBt->mutex);
|
||||||
p->locked = 0;
|
p->locked = 0;
|
||||||
}
|
}
|
||||||
p = p->pNext;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
/*
|
||||||
|
** Return true if the current thread holds the database connection
|
||||||
|
** mutex and all required BtShared mutexes.
|
||||||
|
**
|
||||||
|
** This routine is used inside assert() statements only.
|
||||||
|
*/
|
||||||
|
int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
|
||||||
|
int i;
|
||||||
|
if( !sqlite3_mutex_held(db->mutex) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for(i=0; i<db->nDb; i++){
|
||||||
|
Btree *p;
|
||||||
|
p = db->aDb[i].pBt;
|
||||||
|
if( p && p->sharable &&
|
||||||
|
(p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Potentially dd a new Btree pointer to a BtreeMutexArray.
|
** Potentially dd a new Btree pointer to a BtreeMutexArray.
|
||||||
** Really only add the Btree if it can possibly be shared with
|
** Really only add the Btree if it can possibly be shared with
|
||||||
@@ -180,7 +222,7 @@ void sqlite3BtreeLeaveAll(sqlite3 *db){
|
|||||||
void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){
|
void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){
|
||||||
int i, j;
|
int i, j;
|
||||||
BtShared *pBt;
|
BtShared *pBt;
|
||||||
if( !pBtree->sharable ) return;
|
if( pBtree->sharable==0 ) return;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
{
|
{
|
||||||
for(i=0; i<pArray->nMutex; i++){
|
for(i=0; i<pArray->nMutex; i++){
|
||||||
@@ -217,13 +259,12 @@ void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){
|
|||||||
/* Some basic sanity checking */
|
/* Some basic sanity checking */
|
||||||
assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
|
assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
|
||||||
assert( !p->locked || p->wantToLock>0 );
|
assert( !p->locked || p->wantToLock>0 );
|
||||||
assert( p->sharable );
|
|
||||||
|
|
||||||
/* We should already hold a lock on the database connection */
|
/* We should already hold a lock on the database connection */
|
||||||
assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) );
|
assert( sqlite3_mutex_held(p->pSqlite->mutex) );
|
||||||
|
|
||||||
p->wantToLock++;
|
p->wantToLock++;
|
||||||
if( !p->locked ){
|
if( !p->locked && p->sharable ){
|
||||||
sqlite3_mutex_enter(p->pBt->mutex);
|
sqlite3_mutex_enter(p->pBt->mutex);
|
||||||
p->locked = 1;
|
p->locked = 1;
|
||||||
}
|
}
|
||||||
@@ -239,15 +280,14 @@ void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){
|
|||||||
Btree *p = pArray->aBtree[i];
|
Btree *p = pArray->aBtree[i];
|
||||||
/* Some basic sanity checking */
|
/* Some basic sanity checking */
|
||||||
assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
|
assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
|
||||||
assert( p->locked );
|
assert( p->locked || !p->sharable );
|
||||||
assert( p->sharable );
|
|
||||||
assert( p->wantToLock>0 );
|
assert( p->wantToLock>0 );
|
||||||
|
|
||||||
/* We should already hold a lock on the database connection */
|
/* We should already hold a lock on the database connection */
|
||||||
assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) );
|
assert( sqlite3_mutex_held(p->pSqlite->mutex) );
|
||||||
|
|
||||||
p->wantToLock--;
|
p->wantToLock--;
|
||||||
if( p->wantToLock==0 ){
|
if( p->wantToLock==0 && p->locked ){
|
||||||
sqlite3_mutex_leave(p->pBt->mutex);
|
sqlite3_mutex_leave(p->pBt->mutex);
|
||||||
p->locked = 0;
|
p->locked = 0;
|
||||||
}
|
}
|
||||||
|
243
src/btree.c
243
src/btree.c
@@ -9,7 +9,7 @@
|
|||||||
** May you share freely, never taking more than you give.
|
** May you share freely, never taking more than you give.
|
||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
** $Id: btree.c,v 1.415 2007/08/28 23:28:08 drh Exp $
|
** $Id: btree.c,v 1.416 2007/08/29 04:00:58 drh Exp $
|
||||||
**
|
**
|
||||||
** This file implements a external (disk-based) database using BTrees.
|
** This file implements a external (disk-based) database using BTrees.
|
||||||
** See the header comment on "btreeInt.h" for additional information.
|
** See the header comment on "btreeInt.h" for additional information.
|
||||||
@@ -96,8 +96,7 @@ static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){
|
|||||||
BtShared *pBt = p->pBt;
|
BtShared *pBt = p->pBt;
|
||||||
BtLock *pIter;
|
BtLock *pIter;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) );
|
assert( sqlite3BtreeHoldsMutex(p) );
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
|
||||||
|
|
||||||
/* This is a no-op if the shared-cache is not enabled */
|
/* This is a no-op if the shared-cache is not enabled */
|
||||||
if( !p->sharable ){
|
if( !p->sharable ){
|
||||||
@@ -149,8 +148,7 @@ static int lockTable(Btree *p, Pgno iTable, u8 eLock){
|
|||||||
BtLock *pLock = 0;
|
BtLock *pLock = 0;
|
||||||
BtLock *pIter;
|
BtLock *pIter;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) );
|
assert( sqlite3BtreeHoldsMutex(p) );
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
|
||||||
|
|
||||||
/* This is a no-op if the shared-cache is not enabled */
|
/* This is a no-op if the shared-cache is not enabled */
|
||||||
if( !p->sharable ){
|
if( !p->sharable ){
|
||||||
@@ -216,8 +214,7 @@ static int lockTable(Btree *p, Pgno iTable, u8 eLock){
|
|||||||
static void unlockAllTables(Btree *p){
|
static void unlockAllTables(Btree *p){
|
||||||
BtLock **ppIter = &p->pBt->pLock;
|
BtLock **ppIter = &p->pBt->pLock;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) );
|
assert( sqlite3BtreeHoldsMutex(p) );
|
||||||
assert( sqlite3BtreeMutexHeld(p->pBt->mutex) );
|
|
||||||
assert( p->sharable || 0==*ppIter );
|
assert( p->sharable || 0==*ppIter );
|
||||||
|
|
||||||
while( *ppIter ){
|
while( *ppIter ){
|
||||||
@@ -234,12 +231,22 @@ static void unlockAllTables(Btree *p){
|
|||||||
|
|
||||||
static void releasePage(MemPage *pPage); /* Forward reference */
|
static void releasePage(MemPage *pPage); /* Forward reference */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Verify that the cursor holds a mutex on the BtShared
|
||||||
|
*/
|
||||||
|
#ifndef NDEBUG
|
||||||
|
static int cursorHoldsMutex(BtCursor *p){
|
||||||
|
return sqlite3BtreeHoldsMutex(p->pBtree);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_INCRBLOB
|
#ifndef SQLITE_OMIT_INCRBLOB
|
||||||
/*
|
/*
|
||||||
** Invalidate the overflow page-list cache for cursor pCur, if any.
|
** Invalidate the overflow page-list cache for cursor pCur, if any.
|
||||||
*/
|
*/
|
||||||
static void invalidateOverflowCache(BtCursor *pCur){
|
static void invalidateOverflowCache(BtCursor *pCur){
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
sqlite3_free(pCur->aOverflow);
|
sqlite3_free(pCur->aOverflow);
|
||||||
pCur->aOverflow = 0;
|
pCur->aOverflow = 0;
|
||||||
}
|
}
|
||||||
@@ -250,7 +257,7 @@ static void invalidateOverflowCache(BtCursor *pCur){
|
|||||||
*/
|
*/
|
||||||
static void invalidateAllOverflowCache(BtShared *pBt){
|
static void invalidateAllOverflowCache(BtShared *pBt){
|
||||||
BtCursor *p;
|
BtCursor *p;
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
for(p=pBt->pCursor; p; p=p->pNext){
|
for(p=pBt->pCursor; p; p=p->pNext){
|
||||||
invalidateOverflowCache(p);
|
invalidateOverflowCache(p);
|
||||||
}
|
}
|
||||||
@@ -269,7 +276,7 @@ static int saveCursorPosition(BtCursor *pCur){
|
|||||||
|
|
||||||
assert( CURSOR_VALID==pCur->eState );
|
assert( CURSOR_VALID==pCur->eState );
|
||||||
assert( 0==pCur->pKey );
|
assert( 0==pCur->pKey );
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
|
|
||||||
rc = sqlite3BtreeKeySize(pCur, &pCur->nKey);
|
rc = sqlite3BtreeKeySize(pCur, &pCur->nKey);
|
||||||
|
|
||||||
@@ -311,7 +318,7 @@ static int saveCursorPosition(BtCursor *pCur){
|
|||||||
*/
|
*/
|
||||||
static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
|
static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
|
||||||
BtCursor *p;
|
BtCursor *p;
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
assert( pExcept==0 || pExcept->pBt==pBt );
|
assert( pExcept==0 || pExcept->pBt==pBt );
|
||||||
for(p=pBt->pCursor; p; p=p->pNext){
|
for(p=pBt->pCursor; p; p=p->pNext){
|
||||||
if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) &&
|
if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) &&
|
||||||
@@ -329,7 +336,7 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
|
|||||||
** Clear the current cursor position.
|
** Clear the current cursor position.
|
||||||
*/
|
*/
|
||||||
static void clearCursorPosition(BtCursor *pCur){
|
static void clearCursorPosition(BtCursor *pCur){
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
sqlite3_free(pCur->pKey);
|
sqlite3_free(pCur->pKey);
|
||||||
pCur->pKey = 0;
|
pCur->pKey = 0;
|
||||||
pCur->eState = CURSOR_INVALID;
|
pCur->eState = CURSOR_INVALID;
|
||||||
@@ -348,7 +355,7 @@ static void clearCursorPosition(BtCursor *pCur){
|
|||||||
*/
|
*/
|
||||||
int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){
|
int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){
|
||||||
int rc;
|
int rc;
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( pCur->eState==CURSOR_REQUIRESEEK );
|
assert( pCur->eState==CURSOR_REQUIRESEEK );
|
||||||
#ifndef SQLITE_OMIT_INCRBLOB
|
#ifndef SQLITE_OMIT_INCRBLOB
|
||||||
if( pCur->isIncrblobHandle ){
|
if( pCur->isIncrblobHandle ){
|
||||||
@@ -378,7 +385,7 @@ int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){
|
|||||||
*/
|
*/
|
||||||
static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
|
static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
|
||||||
int nPagesPerMapPage, iPtrMap, ret;
|
int nPagesPerMapPage, iPtrMap, ret;
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
nPagesPerMapPage = (pBt->usableSize/5)+1;
|
nPagesPerMapPage = (pBt->usableSize/5)+1;
|
||||||
iPtrMap = (pgno-2)/nPagesPerMapPage;
|
iPtrMap = (pgno-2)/nPagesPerMapPage;
|
||||||
ret = (iPtrMap*nPagesPerMapPage) + 2;
|
ret = (iPtrMap*nPagesPerMapPage) + 2;
|
||||||
@@ -402,7 +409,7 @@ static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){
|
|||||||
int offset; /* Offset in pointer map page */
|
int offset; /* Offset in pointer map page */
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
/* The master-journal page number must never be used as a pointer map page */
|
/* The master-journal page number must never be used as a pointer map page */
|
||||||
assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) );
|
assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) );
|
||||||
|
|
||||||
@@ -445,7 +452,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
|
|||||||
int offset; /* Offset of entry in pointer map */
|
int offset; /* Offset of entry in pointer map */
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
|
|
||||||
iPtrmap = PTRMAP_PAGENO(pBt, key);
|
iPtrmap = PTRMAP_PAGENO(pBt, key);
|
||||||
rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage);
|
rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage);
|
||||||
@@ -489,7 +496,7 @@ u8 *sqlite3BtreeFindCell(MemPage *pPage, int iCell){
|
|||||||
*/
|
*/
|
||||||
static u8 *findOverflowCell(MemPage *pPage, int iCell){
|
static u8 *findOverflowCell(MemPage *pPage, int iCell){
|
||||||
int i;
|
int i;
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
for(i=pPage->nOverflow-1; i>=0; i--){
|
for(i=pPage->nOverflow-1; i>=0; i--){
|
||||||
int k;
|
int k;
|
||||||
struct _OvflCell *pOvfl;
|
struct _OvflCell *pOvfl;
|
||||||
@@ -522,7 +529,7 @@ void sqlite3BtreeParseCellPtr(
|
|||||||
int n; /* Number bytes in cell content header */
|
int n; /* Number bytes in cell content header */
|
||||||
u32 nPayload; /* Number of bytes of cell payload */
|
u32 nPayload; /* Number of bytes of cell payload */
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
|
|
||||||
pInfo->pCell = pCell;
|
pInfo->pCell = pCell;
|
||||||
assert( pPage->leaf==0 || pPage->leaf==1 );
|
assert( pPage->leaf==0 || pPage->leaf==1 );
|
||||||
@@ -636,7 +643,7 @@ static int ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell){
|
|||||||
*/
|
*/
|
||||||
static int ptrmapPutOvfl(MemPage *pPage, int iCell){
|
static int ptrmapPutOvfl(MemPage *pPage, int iCell){
|
||||||
u8 *pCell;
|
u8 *pCell;
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
pCell = findOverflowCell(pPage, iCell);
|
pCell = findOverflowCell(pPage, iCell);
|
||||||
return ptrmapPutOvflPtr(pPage, pCell);
|
return ptrmapPutOvflPtr(pPage, pCell);
|
||||||
}
|
}
|
||||||
@@ -666,7 +673,7 @@ static int defragmentPage(MemPage *pPage){
|
|||||||
assert( pPage->pBt!=0 );
|
assert( pPage->pBt!=0 );
|
||||||
assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
|
assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
|
||||||
assert( pPage->nOverflow==0 );
|
assert( pPage->nOverflow==0 );
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
temp = sqlite3_malloc( pPage->pBt->pageSize );
|
temp = sqlite3_malloc( pPage->pBt->pageSize );
|
||||||
if( temp==0 ) return SQLITE_NOMEM;
|
if( temp==0 ) return SQLITE_NOMEM;
|
||||||
data = pPage->aData;
|
data = pPage->aData;
|
||||||
@@ -723,7 +730,7 @@ static int allocateSpace(MemPage *pPage, int nByte){
|
|||||||
data = pPage->aData;
|
data = pPage->aData;
|
||||||
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
||||||
assert( pPage->pBt );
|
assert( pPage->pBt );
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
if( nByte<4 ) nByte = 4;
|
if( nByte<4 ) nByte = 4;
|
||||||
if( pPage->nFree<nByte || pPage->nOverflow>0 ) return 0;
|
if( pPage->nFree<nByte || pPage->nOverflow>0 ) return 0;
|
||||||
pPage->nFree -= nByte;
|
pPage->nFree -= nByte;
|
||||||
@@ -782,7 +789,7 @@ static void freeSpace(MemPage *pPage, int start, int size){
|
|||||||
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
||||||
assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) );
|
assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) );
|
||||||
assert( (start + size)<=pPage->pBt->usableSize );
|
assert( (start + size)<=pPage->pBt->usableSize );
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
if( size<4 ) size = 4;
|
if( size<4 ) size = 4;
|
||||||
|
|
||||||
#ifdef SQLITE_SECURE_DELETE
|
#ifdef SQLITE_SECURE_DELETE
|
||||||
@@ -843,7 +850,7 @@ static void decodeFlags(MemPage *pPage, int flagByte){
|
|||||||
BtShared *pBt; /* A copy of pPage->pBt */
|
BtShared *pBt; /* A copy of pPage->pBt */
|
||||||
|
|
||||||
assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) );
|
assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) );
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
pPage->intKey = (flagByte & (PTF_INTKEY|PTF_LEAFDATA))!=0;
|
pPage->intKey = (flagByte & (PTF_INTKEY|PTF_LEAFDATA))!=0;
|
||||||
pPage->zeroData = (flagByte & PTF_ZERODATA)!=0;
|
pPage->zeroData = (flagByte & PTF_ZERODATA)!=0;
|
||||||
pPage->leaf = (flagByte & PTF_LEAF)!=0;
|
pPage->leaf = (flagByte & PTF_LEAF)!=0;
|
||||||
@@ -890,7 +897,7 @@ int sqlite3BtreeInitPage(
|
|||||||
pBt = pPage->pBt;
|
pBt = pPage->pBt;
|
||||||
assert( pBt!=0 );
|
assert( pBt!=0 );
|
||||||
assert( pParent==0 || pParent->pBt==pBt );
|
assert( pParent==0 || pParent->pBt==pBt );
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
|
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
|
||||||
assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] );
|
assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] );
|
||||||
if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){
|
if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){
|
||||||
@@ -961,7 +968,7 @@ static void zeroPage(MemPage *pPage, int flags){
|
|||||||
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
|
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
|
||||||
assert( &data[pBt->pageSize] == (unsigned char*)pPage );
|
assert( &data[pBt->pageSize] == (unsigned char*)pPage );
|
||||||
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
memset(&data[hdr], 0, pBt->usableSize - hdr);
|
memset(&data[hdr], 0, pBt->usableSize - hdr);
|
||||||
data[hdr] = flags;
|
data[hdr] = flags;
|
||||||
first = hdr + 8 + 4*((flags&PTF_LEAF)==0);
|
first = hdr + 8 + 4*((flags&PTF_LEAF)==0);
|
||||||
@@ -999,7 +1006,7 @@ int sqlite3BtreeGetPage(
|
|||||||
MemPage *pPage;
|
MemPage *pPage;
|
||||||
DbPage *pDbPage;
|
DbPage *pDbPage;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent);
|
rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage);
|
pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage);
|
||||||
@@ -1024,7 +1031,7 @@ static int getAndInitPage(
|
|||||||
MemPage *pParent /* Parent of the page */
|
MemPage *pParent /* Parent of the page */
|
||||||
){
|
){
|
||||||
int rc;
|
int rc;
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
if( pgno==0 ){
|
if( pgno==0 ){
|
||||||
return SQLITE_CORRUPT_BKPT;
|
return SQLITE_CORRUPT_BKPT;
|
||||||
}
|
}
|
||||||
@@ -1044,7 +1051,7 @@ static void releasePage(MemPage *pPage){
|
|||||||
assert( pPage->aData );
|
assert( pPage->aData );
|
||||||
assert( pPage->pBt );
|
assert( pPage->pBt );
|
||||||
assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage );
|
assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage );
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
sqlite3PagerUnref(pPage->pDbPage);
|
sqlite3PagerUnref(pPage->pDbPage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1058,7 +1065,7 @@ static void pageDestructor(DbPage *pData, int pageSize){
|
|||||||
MemPage *pPage;
|
MemPage *pPage;
|
||||||
assert( (pageSize & 7)==0 );
|
assert( (pageSize & 7)==0 );
|
||||||
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
|
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
|
||||||
assert( pPage->isInit==0 || sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
if( pPage->pParent ){
|
if( pPage->pParent ){
|
||||||
MemPage *pParent = pPage->pParent;
|
MemPage *pParent = pPage->pParent;
|
||||||
assert( pPage->isInit==1 );
|
assert( pPage->isInit==1 );
|
||||||
@@ -1082,7 +1089,7 @@ static void pageReinit(DbPage *pData, int pageSize){
|
|||||||
assert( (pageSize & 7)==0 );
|
assert( (pageSize & 7)==0 );
|
||||||
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
|
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
|
||||||
if( pPage->isInit ){
|
if( pPage->isInit ){
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
pPage->isInit = 0;
|
pPage->isInit = 0;
|
||||||
sqlite3BtreeInitPage(pPage, pPage->pParent);
|
sqlite3BtreeInitPage(pPage, pPage->pParent);
|
||||||
}
|
}
|
||||||
@@ -1393,17 +1400,6 @@ int sqlite3BtreeClose(Btree *p){
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE)
|
|
||||||
/*
|
|
||||||
** Short-cuts for entering and leaving mutexes on a cursor.
|
|
||||||
*/
|
|
||||||
# define cursorEnter(X) assert( sqlite3_mutex_held(X->pBt->mutex) )
|
|
||||||
# define cursorLeave(X)
|
|
||||||
#else
|
|
||||||
# define cursorEnter(X)
|
|
||||||
# define cursorLeave(X)
|
|
||||||
#endif /* !SQLITE_OMIT_SHARED_CACHE */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Change the busy handler callback function.
|
** Change the busy handler callback function.
|
||||||
*/
|
*/
|
||||||
@@ -1599,7 +1595,7 @@ static int lockBtree(BtShared *pBt){
|
|||||||
int rc, pageSize;
|
int rc, pageSize;
|
||||||
MemPage *pPage1;
|
MemPage *pPage1;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
if( pBt->pPage1 ) return SQLITE_OK;
|
if( pBt->pPage1 ) return SQLITE_OK;
|
||||||
rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0);
|
rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0);
|
||||||
if( rc!=SQLITE_OK ) return rc;
|
if( rc!=SQLITE_OK ) return rc;
|
||||||
@@ -1676,8 +1672,7 @@ page1_init_failed:
|
|||||||
static int lockBtreeWithRetry(Btree *pRef){
|
static int lockBtreeWithRetry(Btree *pRef){
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pRef->pSqlite->mutex) );
|
assert( sqlite3BtreeHoldsMutex(pRef) );
|
||||||
assert( sqlite3BtreeMutexHeld(pRef->pBt->mutex) );
|
|
||||||
if( pRef->inTrans==TRANS_NONE ){
|
if( pRef->inTrans==TRANS_NONE ){
|
||||||
u8 inTransaction = pRef->pBt->inTransaction;
|
u8 inTransaction = pRef->pBt->inTransaction;
|
||||||
btreeIntegrity(pRef);
|
btreeIntegrity(pRef);
|
||||||
@@ -1704,7 +1699,7 @@ static int lockBtreeWithRetry(Btree *pRef){
|
|||||||
** If there is a transaction in progress, this routine is a no-op.
|
** If there is a transaction in progress, this routine is a no-op.
|
||||||
*/
|
*/
|
||||||
static void unlockBtreeIfUnused(BtShared *pBt){
|
static void unlockBtreeIfUnused(BtShared *pBt){
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){
|
if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){
|
||||||
if( sqlite3PagerRefcount(pBt->pPager)>=1 ){
|
if( sqlite3PagerRefcount(pBt->pPager)>=1 ){
|
||||||
if( pBt->pPage1->aData==0 ){
|
if( pBt->pPage1->aData==0 ){
|
||||||
@@ -1729,7 +1724,7 @@ static int newDatabase(BtShared *pBt){
|
|||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
if( sqlite3PagerPagecount(pBt->pPager)>0 ) return SQLITE_OK;
|
if( sqlite3PagerPagecount(pBt->pPager)>0 ) return SQLITE_OK;
|
||||||
pP1 = pBt->pPage1;
|
pP1 = pBt->pPage1;
|
||||||
assert( pP1!=0 );
|
assert( pP1!=0 );
|
||||||
@@ -1878,7 +1873,7 @@ static int setChildPtrmaps(MemPage *pPage){
|
|||||||
int isInitOrig = pPage->isInit;
|
int isInitOrig = pPage->isInit;
|
||||||
Pgno pgno = pPage->pgno;
|
Pgno pgno = pPage->pgno;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
rc = sqlite3BtreeInitPage(pPage, pPage->pParent);
|
rc = sqlite3BtreeInitPage(pPage, pPage->pParent);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
goto set_child_ptrmaps_out;
|
goto set_child_ptrmaps_out;
|
||||||
@@ -1926,7 +1921,7 @@ set_child_ptrmaps_out:
|
|||||||
** overflow page in the list.
|
** overflow page in the list.
|
||||||
*/
|
*/
|
||||||
static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
|
static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
if( eType==PTRMAP_OVERFLOW2 ){
|
if( eType==PTRMAP_OVERFLOW2 ){
|
||||||
/* The pointer is always the first 4 bytes of the page in this case. */
|
/* The pointer is always the first 4 bytes of the page in this case. */
|
||||||
if( get4byte(pPage->aData)!=iFrom ){
|
if( get4byte(pPage->aData)!=iFrom ){
|
||||||
@@ -1992,7 +1987,7 @@ static int relocatePage(
|
|||||||
|
|
||||||
assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||
|
assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||
|
||||||
eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );
|
eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
assert( pDbPage->pBt==pBt );
|
assert( pDbPage->pBt==pBt );
|
||||||
|
|
||||||
/* Move page iDbPage from it's current location to page number iFreePage */
|
/* Move page iDbPage from it's current location to page number iFreePage */
|
||||||
@@ -2072,7 +2067,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin){
|
|||||||
Pgno iLastPg; /* Last page in the database */
|
Pgno iLastPg; /* Last page in the database */
|
||||||
Pgno nFreeList; /* Number of pages still on the free-list */
|
Pgno nFreeList; /* Number of pages still on the free-list */
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
iLastPg = pBt->nTrunc;
|
iLastPg = pBt->nTrunc;
|
||||||
if( iLastPg==0 ){
|
if( iLastPg==0 ){
|
||||||
iLastPg = sqlite3PagerPagecount(pBt->pPager);
|
iLastPg = sqlite3PagerPagecount(pBt->pPager);
|
||||||
@@ -2198,7 +2193,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){
|
|||||||
int nRef = sqlite3PagerRefcount(pPager);
|
int nRef = sqlite3PagerRefcount(pPager);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
invalidateAllOverflowCache(pBt);
|
invalidateAllOverflowCache(pBt);
|
||||||
assert(pBt->autoVacuum);
|
assert(pBt->autoVacuum);
|
||||||
if( !pBt->incrVacuum ){
|
if( !pBt->incrVacuum ){
|
||||||
@@ -2605,8 +2600,7 @@ static int btreeCursor(
|
|||||||
BtCursor *pCur;
|
BtCursor *pCur;
|
||||||
BtShared *pBt = p->pBt;
|
BtShared *pBt = p->pBt;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3BtreeHoldsMutex(p) );
|
||||||
assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) );
|
|
||||||
*ppCur = 0;
|
*ppCur = 0;
|
||||||
if( wrFlag ){
|
if( wrFlag ){
|
||||||
if( pBt->readOnly ){
|
if( pBt->readOnly ){
|
||||||
@@ -2691,7 +2685,7 @@ int sqlite3BtreeCursor(
|
|||||||
int sqlite3BtreeCloseCursor(BtCursor *pCur){
|
int sqlite3BtreeCloseCursor(BtCursor *pCur){
|
||||||
BtShared *pBt = pCur->pBt;
|
BtShared *pBt = pCur->pBt;
|
||||||
|
|
||||||
assert( sqlite3_mutex_held(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) );
|
assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) );
|
||||||
clearCursorPosition(pCur);
|
clearCursorPosition(pCur);
|
||||||
if( pCur->pPrev ){
|
if( pCur->pPrev ){
|
||||||
@@ -2714,14 +2708,13 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
|
|||||||
** The temporary cursor is not on the cursor list for the Btree.
|
** The temporary cursor is not on the cursor list for the Btree.
|
||||||
*/
|
*/
|
||||||
void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){
|
void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){
|
||||||
cursorEnter(pCur);
|
assert( cursorHoldsMutex(pCur) );
|
||||||
memcpy(pTempCur, pCur, sizeof(*pCur));
|
memcpy(pTempCur, pCur, sizeof(*pCur));
|
||||||
pTempCur->pNext = 0;
|
pTempCur->pNext = 0;
|
||||||
pTempCur->pPrev = 0;
|
pTempCur->pPrev = 0;
|
||||||
if( pTempCur->pPage ){
|
if( pTempCur->pPage ){
|
||||||
sqlite3PagerRef(pTempCur->pPage->pDbPage);
|
sqlite3PagerRef(pTempCur->pPage->pDbPage);
|
||||||
}
|
}
|
||||||
cursorLeave(pCur);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2729,11 +2722,10 @@ void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){
|
|||||||
** function above.
|
** function above.
|
||||||
*/
|
*/
|
||||||
void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){
|
void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){
|
||||||
cursorEnter(pCur);
|
assert( cursorHoldsMutex(pCur) );
|
||||||
if( pCur->pPage ){
|
if( pCur->pPage ){
|
||||||
sqlite3PagerUnref(pCur->pPage->pDbPage);
|
sqlite3PagerUnref(pCur->pPage->pDbPage);
|
||||||
}
|
}
|
||||||
cursorLeave(pCur);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2791,7 +2783,7 @@ void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){
|
|||||||
int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
|
int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( sqlite3_mutex_held(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
rc = restoreOrClearCursorPosition(pCur);
|
rc = restoreOrClearCursorPosition(pCur);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
|
assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
|
||||||
@@ -2815,7 +2807,7 @@ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
|
|||||||
int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
|
int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( sqlite3_mutex_held(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
rc = restoreOrClearCursorPosition(pCur);
|
rc = restoreOrClearCursorPosition(pCur);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
|
assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID );
|
||||||
@@ -2856,7 +2848,7 @@ static int getOverflowPage(
|
|||||||
Pgno next = 0;
|
Pgno next = 0;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
/* One of these must not be NULL. Otherwise, why call this function? */
|
/* One of these must not be NULL. Otherwise, why call this function? */
|
||||||
assert(ppPage || pPgnoNext);
|
assert(ppPage || pPgnoNext);
|
||||||
|
|
||||||
@@ -2996,7 +2988,7 @@ static int accessPayload(
|
|||||||
assert( pCur->eState==CURSOR_VALID );
|
assert( pCur->eState==CURSOR_VALID );
|
||||||
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
|
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
|
||||||
assert( offset>=0 );
|
assert( offset>=0 );
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
|
|
||||||
getCellInfo(pCur);
|
getCellInfo(pCur);
|
||||||
aPayload = pCur->info.pCell + pCur->info.nHeader;
|
aPayload = pCur->info.pCell + pCur->info.nHeader;
|
||||||
@@ -3122,20 +3114,18 @@ static int accessPayload(
|
|||||||
int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
|
int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
cursorEnter(pCur);
|
assert( cursorHoldsMutex(pCur) );
|
||||||
rc = restoreOrClearCursorPosition(pCur);
|
rc = restoreOrClearCursorPosition(pCur);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
assert( pCur->eState==CURSOR_VALID );
|
assert( pCur->eState==CURSOR_VALID );
|
||||||
assert( pCur->pPage!=0 );
|
assert( pCur->pPage!=0 );
|
||||||
if( pCur->pPage->intKey ){
|
if( pCur->pPage->intKey ){
|
||||||
cursorLeave(pCur);
|
|
||||||
return SQLITE_CORRUPT_BKPT;
|
return SQLITE_CORRUPT_BKPT;
|
||||||
}
|
}
|
||||||
assert( pCur->pPage->intKey==0 );
|
assert( pCur->pPage->intKey==0 );
|
||||||
assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
|
assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
|
||||||
rc = accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0, 0);
|
rc = accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0, 0);
|
||||||
}
|
}
|
||||||
cursorLeave(pCur);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3151,7 +3141,7 @@ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
|
|||||||
int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
|
int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
cursorEnter(pCur);
|
assert( cursorHoldsMutex(pCur) );
|
||||||
rc = restoreOrClearCursorPosition(pCur);
|
rc = restoreOrClearCursorPosition(pCur);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
assert( pCur->eState==CURSOR_VALID );
|
assert( pCur->eState==CURSOR_VALID );
|
||||||
@@ -3159,7 +3149,6 @@ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
|
|||||||
assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
|
assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
|
||||||
rc = accessPayload(pCur, offset, amt, pBuf, 1, 0);
|
rc = accessPayload(pCur, offset, amt, pBuf, 1, 0);
|
||||||
}
|
}
|
||||||
cursorLeave(pCur);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3194,7 +3183,7 @@ static const unsigned char *fetchPayload(
|
|||||||
|
|
||||||
assert( pCur!=0 && pCur->pPage!=0 );
|
assert( pCur!=0 && pCur->pPage!=0 );
|
||||||
assert( pCur->eState==CURSOR_VALID );
|
assert( pCur->eState==CURSOR_VALID );
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
pPage = pCur->pPage;
|
pPage = pCur->pPage;
|
||||||
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
|
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
|
||||||
getCellInfo(pCur);
|
getCellInfo(pCur);
|
||||||
@@ -3234,14 +3223,14 @@ static const unsigned char *fetchPayload(
|
|||||||
** in the common case where no overflow pages are used.
|
** in the common case where no overflow pages are used.
|
||||||
*/
|
*/
|
||||||
const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){
|
const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
if( pCur->eState==CURSOR_VALID ){
|
if( pCur->eState==CURSOR_VALID ){
|
||||||
return (const void*)fetchPayload(pCur, pAmt, 0);
|
return (const void*)fetchPayload(pCur, pAmt, 0);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){
|
const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
if( pCur->eState==CURSOR_VALID ){
|
if( pCur->eState==CURSOR_VALID ){
|
||||||
return (const void*)fetchPayload(pCur, pAmt, 1);
|
return (const void*)fetchPayload(pCur, pAmt, 1);
|
||||||
}
|
}
|
||||||
@@ -3259,7 +3248,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
|
|||||||
MemPage *pOldPage;
|
MemPage *pOldPage;
|
||||||
BtShared *pBt = pCur->pBt;
|
BtShared *pBt = pCur->pBt;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( pCur->eState==CURSOR_VALID );
|
assert( pCur->eState==CURSOR_VALID );
|
||||||
rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage);
|
rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
@@ -3288,7 +3277,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
|
|||||||
int sqlite3BtreeIsRootPage(MemPage *pPage){
|
int sqlite3BtreeIsRootPage(MemPage *pPage){
|
||||||
MemPage *pParent;
|
MemPage *pParent;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
pParent = pPage->pParent;
|
pParent = pPage->pParent;
|
||||||
if( pParent==0 ) return 1;
|
if( pParent==0 ) return 1;
|
||||||
if( pParent->pgno>1 ) return 0;
|
if( pParent->pgno>1 ) return 0;
|
||||||
@@ -3309,7 +3298,7 @@ void sqlite3BtreeMoveToParent(BtCursor *pCur){
|
|||||||
MemPage *pPage;
|
MemPage *pPage;
|
||||||
int idxParent;
|
int idxParent;
|
||||||
|
|
||||||
cursorEnter(pCur);
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( pCur->eState==CURSOR_VALID );
|
assert( pCur->eState==CURSOR_VALID );
|
||||||
pPage = pCur->pPage;
|
pPage = pCur->pPage;
|
||||||
assert( pPage!=0 );
|
assert( pPage!=0 );
|
||||||
@@ -3323,7 +3312,6 @@ void sqlite3BtreeMoveToParent(BtCursor *pCur){
|
|||||||
pCur->info.nSize = 0;
|
pCur->info.nSize = 0;
|
||||||
assert( pParent->idxShift==0 );
|
assert( pParent->idxShift==0 );
|
||||||
pCur->idx = idxParent;
|
pCur->idx = idxParent;
|
||||||
cursorLeave(pCur);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3335,7 +3323,7 @@ static int moveToRoot(BtCursor *pCur){
|
|||||||
Btree *p = pCur->pBtree;
|
Btree *p = pCur->pBtree;
|
||||||
BtShared *pBt = p->pBt;
|
BtShared *pBt = p->pBt;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
if( pCur->eState==CURSOR_REQUIRESEEK ){
|
if( pCur->eState==CURSOR_REQUIRESEEK ){
|
||||||
clearCursorPosition(pCur);
|
clearCursorPosition(pCur);
|
||||||
}
|
}
|
||||||
@@ -3378,7 +3366,7 @@ static int moveToLeftmost(BtCursor *pCur){
|
|||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
MemPage *pPage;
|
MemPage *pPage;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( pCur->eState==CURSOR_VALID );
|
assert( pCur->eState==CURSOR_VALID );
|
||||||
while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){
|
while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){
|
||||||
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
|
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
|
||||||
@@ -3403,7 +3391,7 @@ static int moveToRightmost(BtCursor *pCur){
|
|||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
MemPage *pPage;
|
MemPage *pPage;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( pCur->eState==CURSOR_VALID );
|
assert( pCur->eState==CURSOR_VALID );
|
||||||
while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){
|
while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){
|
||||||
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
||||||
@@ -3424,8 +3412,8 @@ static int moveToRightmost(BtCursor *pCur){
|
|||||||
int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
|
int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) );
|
assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) );
|
||||||
rc = moveToRoot(pCur);
|
rc = moveToRoot(pCur);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
if( pCur->eState==CURSOR_INVALID ){
|
if( pCur->eState==CURSOR_INVALID ){
|
||||||
@@ -3448,8 +3436,8 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
|
|||||||
int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) );
|
assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) );
|
||||||
rc = moveToRoot(pCur);
|
rc = moveToRoot(pCur);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
if( CURSOR_INVALID==pCur->eState ){
|
if( CURSOR_INVALID==pCur->eState ){
|
||||||
@@ -3501,8 +3489,8 @@ int sqlite3BtreeMoveto(
|
|||||||
){
|
){
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) );
|
assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) );
|
||||||
rc = moveToRoot(pCur);
|
rc = moveToRoot(pCur);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
return rc;
|
return rc;
|
||||||
@@ -3643,7 +3631,7 @@ static int btreeNext(BtCursor *pCur, int *pRes){
|
|||||||
int rc;
|
int rc;
|
||||||
MemPage *pPage;
|
MemPage *pPage;
|
||||||
|
|
||||||
assert( sqlite3_mutex_held(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
rc = restoreOrClearCursorPosition(pCur);
|
rc = restoreOrClearCursorPosition(pCur);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
return rc;
|
return rc;
|
||||||
@@ -3700,9 +3688,8 @@ static int btreeNext(BtCursor *pCur, int *pRes){
|
|||||||
}
|
}
|
||||||
int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
|
int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
|
||||||
int rc;
|
int rc;
|
||||||
cursorEnter(pCur);
|
assert( cursorHoldsMutex(pCur) );
|
||||||
rc = btreeNext(pCur, pRes);
|
rc = btreeNext(pCur, pRes);
|
||||||
cursorLeave(pCur);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3718,7 +3705,7 @@ static int btreePrevious(BtCursor *pCur, int *pRes){
|
|||||||
Pgno pgno;
|
Pgno pgno;
|
||||||
MemPage *pPage;
|
MemPage *pPage;
|
||||||
|
|
||||||
assert( sqlite3_mutex_held(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
rc = restoreOrClearCursorPosition(pCur);
|
rc = restoreOrClearCursorPosition(pCur);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
return rc;
|
return rc;
|
||||||
@@ -3767,9 +3754,8 @@ static int btreePrevious(BtCursor *pCur, int *pRes){
|
|||||||
}
|
}
|
||||||
int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
|
int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
|
||||||
int rc;
|
int rc;
|
||||||
cursorEnter(pCur);
|
assert( cursorHoldsMutex(pCur) );
|
||||||
rc = btreePrevious(pCur, pRes);
|
rc = btreePrevious(pCur, pRes);
|
||||||
cursorLeave(pCur);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3808,7 +3794,7 @@ static int allocateBtreePage(
|
|||||||
MemPage *pTrunk = 0;
|
MemPage *pTrunk = 0;
|
||||||
MemPage *pPrevTrunk = 0;
|
MemPage *pPrevTrunk = 0;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
pPage1 = pBt->pPage1;
|
pPage1 = pBt->pPage1;
|
||||||
n = get4byte(&pPage1->aData[36]);
|
n = get4byte(&pPage1->aData[36]);
|
||||||
if( n>0 ){
|
if( n>0 ){
|
||||||
@@ -4041,7 +4027,7 @@ static int freePage(MemPage *pPage){
|
|||||||
int rc, n, k;
|
int rc, n, k;
|
||||||
|
|
||||||
/* Prepare the page for freeing */
|
/* Prepare the page for freeing */
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
assert( pPage->pgno>1 );
|
assert( pPage->pgno>1 );
|
||||||
pPage->isInit = 0;
|
pPage->isInit = 0;
|
||||||
releasePage(pPage->pParent);
|
releasePage(pPage->pParent);
|
||||||
@@ -4124,7 +4110,7 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
|
|||||||
int nOvfl;
|
int nOvfl;
|
||||||
int ovflPageSize;
|
int ovflPageSize;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
sqlite3BtreeParseCellPtr(pPage, pCell, &info);
|
sqlite3BtreeParseCellPtr(pPage, pCell, &info);
|
||||||
if( info.iOverflow==0 ){
|
if( info.iOverflow==0 ){
|
||||||
return SQLITE_OK; /* No overflow pages. Return without doing anything */
|
return SQLITE_OK; /* No overflow pages. Return without doing anything */
|
||||||
@@ -4181,7 +4167,7 @@ static int fillInCell(
|
|||||||
int nHeader;
|
int nHeader;
|
||||||
CellInfo info;
|
CellInfo info;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
|
|
||||||
/* Fill in the header. */
|
/* Fill in the header. */
|
||||||
nHeader = 0;
|
nHeader = 0;
|
||||||
@@ -4295,7 +4281,7 @@ static int reparentPage(BtShared *pBt, Pgno pgno, MemPage *pNewParent, int idx){
|
|||||||
MemPage *pThis;
|
MemPage *pThis;
|
||||||
DbPage *pDbPage;
|
DbPage *pDbPage;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
assert( pNewParent!=0 );
|
assert( pNewParent!=0 );
|
||||||
if( pgno==0 ) return SQLITE_OK;
|
if( pgno==0 ) return SQLITE_OK;
|
||||||
assert( pBt->pPager!=0 );
|
assert( pBt->pPager!=0 );
|
||||||
@@ -4339,7 +4325,7 @@ static int reparentChildPages(MemPage *pPage){
|
|||||||
BtShared *pBt = pPage->pBt;
|
BtShared *pBt = pPage->pBt;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
if( pPage->leaf ) return SQLITE_OK;
|
if( pPage->leaf ) return SQLITE_OK;
|
||||||
|
|
||||||
for(i=0; i<pPage->nCell; i++){
|
for(i=0; i<pPage->nCell; i++){
|
||||||
@@ -4374,7 +4360,7 @@ static void dropCell(MemPage *pPage, int idx, int sz){
|
|||||||
assert( idx>=0 && idx<pPage->nCell );
|
assert( idx>=0 && idx<pPage->nCell );
|
||||||
assert( sz==cellSize(pPage, idx) );
|
assert( sz==cellSize(pPage, idx) );
|
||||||
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
data = pPage->aData;
|
data = pPage->aData;
|
||||||
ptr = &data[pPage->cellOffset + 2*idx];
|
ptr = &data[pPage->cellOffset + 2*idx];
|
||||||
pc = get2byte(ptr);
|
pc = get2byte(ptr);
|
||||||
@@ -4427,7 +4413,7 @@ static int insertCell(
|
|||||||
|
|
||||||
assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
|
assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
|
||||||
assert( sz==cellSizePtr(pPage, pCell) );
|
assert( sz==cellSizePtr(pPage, pCell) );
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
if( pPage->nOverflow || sz+2>pPage->nFree ){
|
if( pPage->nOverflow || sz+2>pPage->nFree ){
|
||||||
if( pTemp ){
|
if( pTemp ){
|
||||||
memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip);
|
memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip);
|
||||||
@@ -4507,7 +4493,7 @@ static void assemblePage(
|
|||||||
u8 *data; /* Data for the page */
|
u8 *data; /* Data for the page */
|
||||||
|
|
||||||
assert( pPage->nOverflow==0 );
|
assert( pPage->nOverflow==0 );
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
totalSize = 0;
|
totalSize = 0;
|
||||||
for(i=0; i<nCell; i++){
|
for(i=0; i<nCell; i++){
|
||||||
totalSize += aSize[i];
|
totalSize += aSize[i];
|
||||||
@@ -4582,7 +4568,7 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){
|
|||||||
int parentSize; /* Size of new divider cell */
|
int parentSize; /* Size of new divider cell */
|
||||||
u8 parentCell[64]; /* Space for the new divider cell */
|
u8 parentCell[64]; /* Space for the new divider cell */
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
|
|
||||||
/* Allocate a new page. Insert the overflow cell from pPage
|
/* Allocate a new page. Insert the overflow cell from pPage
|
||||||
** into it. Then remove the overflow cell from pPage.
|
** into it. Then remove the overflow cell from pPage.
|
||||||
@@ -4708,7 +4694,7 @@ static int balance_nonroot(MemPage *pPage){
|
|||||||
u8 *aFrom = 0;
|
u8 *aFrom = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Find the parent page.
|
** Find the parent page.
|
||||||
@@ -5261,7 +5247,7 @@ static int balance_shallower(MemPage *pPage){
|
|||||||
|
|
||||||
assert( pPage->pParent==0 );
|
assert( pPage->pParent==0 );
|
||||||
assert( pPage->nCell==0 );
|
assert( pPage->nCell==0 );
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
pBt = pPage->pBt;
|
pBt = pPage->pBt;
|
||||||
mxCellPerPage = MX_CELL(pBt);
|
mxCellPerPage = MX_CELL(pBt);
|
||||||
apCell = sqlite3_malloc( mxCellPerPage*(sizeof(u8*)+sizeof(int)) );
|
apCell = sqlite3_malloc( mxCellPerPage*(sizeof(u8*)+sizeof(int)) );
|
||||||
@@ -5366,7 +5352,7 @@ static int balance_deeper(MemPage *pPage){
|
|||||||
assert( pPage->pParent==0 );
|
assert( pPage->pParent==0 );
|
||||||
assert( pPage->nOverflow>0 );
|
assert( pPage->nOverflow>0 );
|
||||||
pBt = pPage->pBt;
|
pBt = pPage->pBt;
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0);
|
rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
assert( sqlite3PagerIswriteable(pChild->pDbPage) );
|
assert( sqlite3PagerIswriteable(pChild->pDbPage) );
|
||||||
@@ -5415,7 +5401,7 @@ balancedeeper_out:
|
|||||||
*/
|
*/
|
||||||
static int balance(MemPage *pPage, int insert){
|
static int balance(MemPage *pPage, int insert){
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||||
if( pPage->pParent==0 ){
|
if( pPage->pParent==0 ){
|
||||||
rc = sqlite3PagerWrite(pPage->pDbPage);
|
rc = sqlite3PagerWrite(pPage->pDbPage);
|
||||||
if( rc==SQLITE_OK && pPage->nOverflow>0 ){
|
if( rc==SQLITE_OK && pPage->nOverflow>0 ){
|
||||||
@@ -5453,8 +5439,7 @@ static int checkReadLocks(Btree *pBtree, Pgno pgnoRoot, BtCursor *pExclude){
|
|||||||
BtCursor *p;
|
BtCursor *p;
|
||||||
BtShared *pBt = pBtree->pBt;
|
BtShared *pBt = pBtree->pBt;
|
||||||
sqlite3 *db = pBtree->pSqlite;
|
sqlite3 *db = pBtree->pSqlite;
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3BtreeHoldsMutex(pBtree) );
|
||||||
assert( sqlite3BtreeMutexHeld(db->mutex) );
|
|
||||||
for(p=pBt->pCursor; p; p=p->pNext){
|
for(p=pBt->pCursor; p; p=p->pNext){
|
||||||
if( p==pExclude ) continue;
|
if( p==pExclude ) continue;
|
||||||
if( p->eState!=CURSOR_VALID ) continue;
|
if( p->eState!=CURSOR_VALID ) continue;
|
||||||
@@ -5497,20 +5482,17 @@ int sqlite3BtreeInsert(
|
|||||||
unsigned char *oldCell;
|
unsigned char *oldCell;
|
||||||
unsigned char *newCell = 0;
|
unsigned char *newCell = 0;
|
||||||
|
|
||||||
cursorEnter(pCur);
|
assert( cursorHoldsMutex(pCur) );
|
||||||
if( pBt->inTransaction!=TRANS_WRITE ){
|
if( pBt->inTransaction!=TRANS_WRITE ){
|
||||||
/* Must start a transaction before doing an insert */
|
/* Must start a transaction before doing an insert */
|
||||||
rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
|
rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
|
||||||
cursorLeave(pCur);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
assert( !pBt->readOnly );
|
assert( !pBt->readOnly );
|
||||||
if( !pCur->wrFlag ){
|
if( !pCur->wrFlag ){
|
||||||
cursorLeave(pCur);
|
|
||||||
return SQLITE_PERM; /* Cursor not open for writing */
|
return SQLITE_PERM; /* Cursor not open for writing */
|
||||||
}
|
}
|
||||||
if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){
|
if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){
|
||||||
cursorLeave(pCur);
|
|
||||||
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
|
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5520,7 +5502,6 @@ int sqlite3BtreeInsert(
|
|||||||
SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
|
SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
|
||||||
SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
|
SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
|
||||||
){
|
){
|
||||||
cursorLeave(pCur);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5569,7 +5550,6 @@ int sqlite3BtreeInsert(
|
|||||||
}
|
}
|
||||||
end_insert:
|
end_insert:
|
||||||
sqlite3_free(newCell);
|
sqlite3_free(newCell);
|
||||||
cursorLeave(pCur);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5585,25 +5565,21 @@ int sqlite3BtreeDelete(BtCursor *pCur){
|
|||||||
Btree *p = pCur->pBtree;
|
Btree *p = pCur->pBtree;
|
||||||
BtShared *pBt = p->pBt;
|
BtShared *pBt = p->pBt;
|
||||||
|
|
||||||
cursorEnter(pCur);
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( pPage->isInit );
|
assert( pPage->isInit );
|
||||||
if( pBt->inTransaction!=TRANS_WRITE ){
|
if( pBt->inTransaction!=TRANS_WRITE ){
|
||||||
/* Must start a transaction before doing a delete */
|
/* Must start a transaction before doing a delete */
|
||||||
rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
|
rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
|
||||||
cursorLeave(pCur);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
assert( !pBt->readOnly );
|
assert( !pBt->readOnly );
|
||||||
if( pCur->idx >= pPage->nCell ){
|
if( pCur->idx >= pPage->nCell ){
|
||||||
cursorLeave(pCur);
|
|
||||||
return SQLITE_ERROR; /* The cursor is not pointing to anything */
|
return SQLITE_ERROR; /* The cursor is not pointing to anything */
|
||||||
}
|
}
|
||||||
if( !pCur->wrFlag ){
|
if( !pCur->wrFlag ){
|
||||||
cursorLeave(pCur);
|
|
||||||
return SQLITE_PERM; /* Did not open this cursor for writing */
|
return SQLITE_PERM; /* Did not open this cursor for writing */
|
||||||
}
|
}
|
||||||
if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){
|
if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){
|
||||||
cursorLeave(pCur);
|
|
||||||
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
|
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5617,7 +5593,6 @@ int sqlite3BtreeDelete(BtCursor *pCur){
|
|||||||
(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 ||
|
(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 ||
|
||||||
(rc = sqlite3PagerWrite(pPage->pDbPage))!=0
|
(rc = sqlite3PagerWrite(pPage->pDbPage))!=0
|
||||||
){
|
){
|
||||||
cursorLeave(pCur);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5631,7 +5606,6 @@ int sqlite3BtreeDelete(BtCursor *pCur){
|
|||||||
}
|
}
|
||||||
rc = clearCell(pPage, pCell);
|
rc = clearCell(pPage, pCell);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
cursorLeave(pCur);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5690,7 +5664,6 @@ int sqlite3BtreeDelete(BtCursor *pCur){
|
|||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
moveToRoot(pCur);
|
moveToRoot(pCur);
|
||||||
}
|
}
|
||||||
cursorLeave(pCur);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5711,8 +5684,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int flags){
|
|||||||
Pgno pgnoRoot;
|
Pgno pgnoRoot;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( sqlite3_mutex_held(p->pSqlite->mutex) );
|
assert( sqlite3BtreeHoldsMutex(p) );
|
||||||
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
||||||
if( pBt->inTransaction!=TRANS_WRITE ){
|
if( pBt->inTransaction!=TRANS_WRITE ){
|
||||||
/* Must start a transaction first */
|
/* Must start a transaction first */
|
||||||
rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
|
rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
|
||||||
@@ -5860,7 +5832,7 @@ static int clearDatabasePage(
|
|||||||
unsigned char *pCell;
|
unsigned char *pCell;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||||
if( pgno>sqlite3PagerPagecount(pBt->pPager) ){
|
if( pgno>sqlite3PagerPagecount(pBt->pPager) ){
|
||||||
return SQLITE_CORRUPT_BKPT;
|
return SQLITE_CORRUPT_BKPT;
|
||||||
}
|
}
|
||||||
@@ -5942,7 +5914,7 @@ static int btreeDropTable(Btree *p, int iTable, int *piMoved){
|
|||||||
MemPage *pPage = 0;
|
MemPage *pPage = 0;
|
||||||
BtShared *pBt = p->pBt;
|
BtShared *pBt = p->pBt;
|
||||||
|
|
||||||
assert( sqlite3BtreeMutexHeld(pBt->mutex) );
|
assert( sqlite3BtreeHoldsMutex(p) );
|
||||||
if( p->inTrans!=TRANS_WRITE ){
|
if( p->inTrans!=TRANS_WRITE ){
|
||||||
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
|
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
@@ -6143,7 +6115,7 @@ int sqlite3BtreeFlags(BtCursor *pCur){
|
|||||||
** restoreOrClearCursorPosition() here.
|
** restoreOrClearCursorPosition() here.
|
||||||
*/
|
*/
|
||||||
MemPage *pPage = pCur->pPage;
|
MemPage *pPage = pCur->pPage;
|
||||||
assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( pPage->pBt==pCur->pBt );
|
assert( pPage->pBt==pCur->pBt );
|
||||||
return pPage ? pPage->aData[pPage->hdrOffset] : 0;
|
return pPage ? pPage->aData[pPage->hdrOffset] : 0;
|
||||||
}
|
}
|
||||||
@@ -6603,7 +6575,7 @@ char *sqlite3BtreeIntegrityCheck(
|
|||||||
*/
|
*/
|
||||||
const char *sqlite3BtreeGetFilename(Btree *p){
|
const char *sqlite3BtreeGetFilename(Btree *p){
|
||||||
assert( p->pBt->pPager!=0 );
|
assert( p->pBt->pPager!=0 );
|
||||||
assert( sqlite3_mutex_held(p->pSqlite->mutex) );
|
/* assert( sqlite3BtreeHoldsMutex(p) ); */
|
||||||
return sqlite3PagerFilename(p->pBt->pPager);
|
return sqlite3PagerFilename(p->pBt->pPager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6615,7 +6587,7 @@ const char *sqlite3BtreeGetFilename(Btree *p){
|
|||||||
*/
|
*/
|
||||||
const char *sqlite3BtreeGetDirname(Btree *p){
|
const char *sqlite3BtreeGetDirname(Btree *p){
|
||||||
assert( p->pBt->pPager!=0 );
|
assert( p->pBt->pPager!=0 );
|
||||||
assert( sqlite3_mutex_held(p->pSqlite->mutex) );
|
assert( sqlite3BtreeHoldsMutex(p) );
|
||||||
return sqlite3PagerDirname(p->pBt->pPager);
|
return sqlite3PagerDirname(p->pBt->pPager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6629,7 +6601,7 @@ const char *sqlite3BtreeGetDirname(Btree *p){
|
|||||||
*/
|
*/
|
||||||
const char *sqlite3BtreeGetJournalname(Btree *p){
|
const char *sqlite3BtreeGetJournalname(Btree *p){
|
||||||
assert( p->pBt->pPager!=0 );
|
assert( p->pBt->pPager!=0 );
|
||||||
assert( sqlite3_mutex_held(p->pSqlite->mutex) );
|
assert( sqlite3BtreeHoldsMutex(p) );
|
||||||
return sqlite3PagerJournalname(p->pBt->pPager);
|
return sqlite3PagerJournalname(p->pBt->pPager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6709,7 +6681,7 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
|
|||||||
** Return non-zero if a transaction is active.
|
** Return non-zero if a transaction is active.
|
||||||
*/
|
*/
|
||||||
int sqlite3BtreeIsInTrans(Btree *p){
|
int sqlite3BtreeIsInTrans(Btree *p){
|
||||||
assert( p==0 || sqlite3BtreeMutexHeld(p->pSqlite->mutex) );
|
assert( p==0 || sqlite3_mutex_held(p->pSqlite->mutex) );
|
||||||
return (p && (p->inTrans==TRANS_WRITE));
|
return (p && (p->inTrans==TRANS_WRITE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6717,8 +6689,7 @@ int sqlite3BtreeIsInTrans(Btree *p){
|
|||||||
** Return non-zero if a statement transaction is active.
|
** Return non-zero if a statement transaction is active.
|
||||||
*/
|
*/
|
||||||
int sqlite3BtreeIsInStmt(Btree *p){
|
int sqlite3BtreeIsInStmt(Btree *p){
|
||||||
assert( sqlite3BtreeMutexHeld(p->pBt->mutex) );
|
assert( sqlite3BtreeHoldsMutex(p) );
|
||||||
assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) );
|
|
||||||
return (p->pBt && p->pBt->inStmt);
|
return (p->pBt && p->pBt->inStmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6726,7 +6697,7 @@ int sqlite3BtreeIsInStmt(Btree *p){
|
|||||||
** Return non-zero if a read (or write) transaction is active.
|
** Return non-zero if a read (or write) transaction is active.
|
||||||
*/
|
*/
|
||||||
int sqlite3BtreeIsInReadTrans(Btree *p){
|
int sqlite3BtreeIsInReadTrans(Btree *p){
|
||||||
assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) );
|
assert( sqlite3_mutex_held(p->pSqlite->mutex) );
|
||||||
return (p && (p->inTrans!=TRANS_NONE));
|
return (p && (p->inTrans!=TRANS_NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6763,7 +6734,7 @@ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
|
|||||||
*/
|
*/
|
||||||
int sqlite3BtreeSchemaLocked(Btree *p){
|
int sqlite3BtreeSchemaLocked(Btree *p){
|
||||||
int rc;
|
int rc;
|
||||||
assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) );
|
assert( sqlite3_mutex_held(p->pSqlite->mutex) );
|
||||||
sqlite3BtreeEnter(p);
|
sqlite3BtreeEnter(p);
|
||||||
rc = (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK);
|
rc = (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK);
|
||||||
sqlite3BtreeLeave(p);
|
sqlite3BtreeLeave(p);
|
||||||
@@ -6799,8 +6770,8 @@ int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){
|
|||||||
** to change the length of the data stored.
|
** to change the length of the data stored.
|
||||||
*/
|
*/
|
||||||
int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
|
int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
|
||||||
assert( sqlite3BtreeMutexHeld(pCsr->pBt->mutex) );
|
assert( cursorHoldsMutex(pCsr) );
|
||||||
assert( sqlite3BtreeMutexHeld(pCsr->pBtree->pSqlite->mutex) );
|
assert( sqlite3_mutex_held(pCsr->pBtree->pSqlite->mutex) );
|
||||||
assert(pCsr->isIncrblobHandle);
|
assert(pCsr->isIncrblobHandle);
|
||||||
if( pCsr->eState==CURSOR_REQUIRESEEK ){
|
if( pCsr->eState==CURSOR_REQUIRESEEK ){
|
||||||
return SQLITE_ABORT;
|
return SQLITE_ABORT;
|
||||||
@@ -6837,8 +6808,8 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
|
|||||||
** sqlite3BtreePutData()).
|
** sqlite3BtreePutData()).
|
||||||
*/
|
*/
|
||||||
void sqlite3BtreeCacheOverflow(BtCursor *pCur){
|
void sqlite3BtreeCacheOverflow(BtCursor *pCur){
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) );
|
assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) );
|
||||||
assert(!pCur->isIncrblobHandle);
|
assert(!pCur->isIncrblobHandle);
|
||||||
assert(!pCur->aOverflow);
|
assert(!pCur->aOverflow);
|
||||||
pCur->isIncrblobHandle = 1;
|
pCur->isIncrblobHandle = 1;
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
** subsystem. See comments in the source code for a detailed description
|
** subsystem. See comments in the source code for a detailed description
|
||||||
** of what each interface routine does.
|
** of what each interface routine does.
|
||||||
**
|
**
|
||||||
** @(#) $Id: btree.h,v 1.89 2007/08/29 00:33:07 drh Exp $
|
** @(#) $Id: btree.h,v 1.90 2007/08/29 04:00:58 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _BTREE_H_
|
#ifndef _BTREE_H_
|
||||||
#define _BTREE_H_
|
#define _BTREE_H_
|
||||||
@@ -175,23 +175,24 @@ int sqlite3BtreePageDump(Btree*, int, int recursive);
|
|||||||
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
|
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
|
||||||
void sqlite3BtreeEnter(Btree*);
|
void sqlite3BtreeEnter(Btree*);
|
||||||
void sqlite3BtreeLeave(Btree*);
|
void sqlite3BtreeLeave(Btree*);
|
||||||
# define sqlite3BtreeMutexHeld(X) sqlite3_mutex_held(X)
|
int sqlite3BtreeHoldsMutex(Btree*);
|
||||||
void sqlite3BtreeEnterAll(sqlite3*);
|
void sqlite3BtreeEnterAll(sqlite3*);
|
||||||
void sqlite3BtreeLeaveAll(sqlite3*);
|
void sqlite3BtreeLeaveAll(sqlite3*);
|
||||||
|
int sqlite3BtreeHoldsAllMutexes(sqlite3*);
|
||||||
void sqlite3BtreeMutexArrayEnter(BtreeMutexArray*);
|
void sqlite3BtreeMutexArrayEnter(BtreeMutexArray*);
|
||||||
void sqlite3BtreeMutexArrayLeave(BtreeMutexArray*);
|
void sqlite3BtreeMutexArrayLeave(BtreeMutexArray*);
|
||||||
void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*);
|
void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*);
|
||||||
#else
|
#else
|
||||||
# define sqlite3BtreeEnter(X)
|
# define sqlite3BtreeEnter(X)
|
||||||
# define sqlite3BtreeLeave(X)
|
# define sqlite3BtreeLeave(X)
|
||||||
# define sqlite3BtreeMutexHeld(X) 1
|
# define sqlite3BtreeHoldsMutex(X) 1
|
||||||
# define sqlite3BtreeEnterAll(X)
|
# define sqlite3BtreeEnterAll(X)
|
||||||
# define sqlite3BtreeLeaveAll(X)
|
# define sqlite3BtreeLeaveAll(X)
|
||||||
|
# define sqlite3BtreeHoldsAllMutexes(X) 1
|
||||||
# define sqlite3BtreeMutexArrayEnter(X)
|
# define sqlite3BtreeMutexArrayEnter(X)
|
||||||
# define sqlite3BtreeMutexArrayLeave(X)
|
# define sqlite3BtreeMutexArrayLeave(X)
|
||||||
# define sqlite3BtreeMutexArrayInsert(X,Y)
|
# define sqlite3BtreeMutexArrayInsert(X,Y)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _BTREE_H_ */
|
#endif /* _BTREE_H_ */
|
||||||
|
Reference in New Issue
Block a user