mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Begin adding mutexes. Compiles without SQLITE_OMIT_SHARED_CACHE but we
get an assertion fault on the shared cache testing. (CVS 4239) FossilOrigin-Name: 4c1e9ffebe7c611a8b6a89153ae97ab9bca19ea3
This commit is contained in:
32
manifest
32
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Change\sthe\sdesign\sof\sthe\s\smutex\sinterface\sto\sallow\sfor\nboth\s"fast"\sand\s"recursive"\smutexes.\s(CVS\s4238)
|
C Begin\sadding\smutexes.\s\sCompiles\swithout\sSQLITE_OMIT_SHARED_CACHE\sbut\swe\nget\san\sassertion\sfault\son\sthe\sshared\scache\stesting.\s(CVS\s4239)
|
||||||
D 2007-08-16T19:40:17
|
D 2007-08-17T01:14:38
|
||||||
F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe
|
F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe
|
||||||
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
||||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||||
@@ -68,10 +68,10 @@ F src/alter.c f0aac0060ae8102e58f210b44d35b53438d53173
|
|||||||
F src/analyze.c a14237d869c6bea0846493b59317e4097e81a0b6
|
F src/analyze.c a14237d869c6bea0846493b59317e4097e81a0b6
|
||||||
F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8
|
F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8
|
||||||
F src/auth.c 5ea90bc93dfea46e9fe4bf531e14c7cd98219ecb
|
F src/auth.c 5ea90bc93dfea46e9fe4bf531e14c7cd98219ecb
|
||||||
F src/btree.c f371e9d7a24ba330c108bf1bb795280051f696ac
|
F src/btree.c 409e7362338d3cf1f72961a01e75e9fbb577cc9f
|
||||||
F src/btree.h 1d527bf61ed176f980c34999d5793a0fd45dcf8c
|
F src/btree.h 91ee529d581c1473d8e6e15299acc3b8de1d0674
|
||||||
F src/btreeInt.h ac1ab1fb624ffbe571786cd2bd9559f9ae336355
|
F src/btreeInt.h 6329e955a7dadd8628d5866e2465721b5fd25ef2
|
||||||
F src/build.c 923d6643c8f59fbcd10cd9e2f2690e82f48db69e
|
F src/build.c add67be992307b4b11849a6611bfd3352aacde92
|
||||||
F src/callback.c 143436453bb93e831c9574fea0b9b9eb90e40ff3
|
F src/callback.c 143436453bb93e831c9574fea0b9b9eb90e40ff3
|
||||||
F src/complete.c ea63834e798a0ab14159bdc6e6cabc3df21aa346
|
F src/complete.c ea63834e798a0ab14159bdc6e6cabc3df21aa346
|
||||||
F src/date.c c44aa498ee9a289ba2b2c62e8269b74b1b81351f
|
F src/date.c c44aa498ee9a289ba2b2c62e8269b74b1b81351f
|
||||||
@@ -85,12 +85,12 @@ F src/insert.c 633322aef1799f6604fa805e12488bc628570b0c
|
|||||||
F src/legacy.c 6013a7cb7da1b72550b3d35d4fc598b3c3e5b8c1
|
F src/legacy.c 6013a7cb7da1b72550b3d35d4fc598b3c3e5b8c1
|
||||||
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
|
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
|
||||||
F src/loadext.c aa1c6e584d39cc241226ec9390387bc2d4a23e8f
|
F src/loadext.c aa1c6e584d39cc241226ec9390387bc2d4a23e8f
|
||||||
F src/main.c 996df547489d4826f70629b16623d7408f55ecd7
|
F src/main.c 6e12fdab03efb8fb17aee8cfcd3bc32329cf1cda
|
||||||
F src/malloc.c 613c65f12ff0ee4edd017aa458209ab7a23cd7b1
|
F src/malloc.c 613c65f12ff0ee4edd017aa458209ab7a23cd7b1
|
||||||
F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
|
F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
|
||||||
F src/mem1.c 2c6a6e3b2c9c7cb8d398a8468095032407c3e0b7
|
F src/mem1.c 2c6a6e3b2c9c7cb8d398a8468095032407c3e0b7
|
||||||
F src/mem2.c 661ca7ebf6e4b964fecc95d24e8c89dbcfc9dfea
|
F src/mem2.c 661ca7ebf6e4b964fecc95d24e8c89dbcfc9dfea
|
||||||
F src/mutex.c 679d5d9c99bd302c0c43ee3eba61348c44aea366
|
F src/mutex.c 67b2efd36a1e67a7dc7b7fa852fd69953462c943
|
||||||
F src/os.c e2faefbe0f5a8ca5e3b1c49ee1b5c6cfa0f0e279
|
F src/os.c e2faefbe0f5a8ca5e3b1c49ee1b5c6cfa0f0e279
|
||||||
F src/os.h 8eff07babf74e5bc3f895f8a6c7c294dad5ff997
|
F src/os.h 8eff07babf74e5bc3f895f8a6c7c294dad5ff997
|
||||||
F src/os_common.h a5c446d3b93f09f369d13bf217de4bed3437dd1c
|
F src/os_common.h a5c446d3b93f09f369d13bf217de4bed3437dd1c
|
||||||
@@ -112,13 +112,13 @@ F src/random.c 6119474a6f6917f708c1dee25b9a8e519a620e88
|
|||||||
F src/select.c 98c367bce3f38c5adfcc97de9ab5c79b0e5dc2b2
|
F src/select.c 98c367bce3f38c5adfcc97de9ab5c79b0e5dc2b2
|
||||||
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||||
F src/shell.c ac29402b538515fa4697282387be9c1205e6e9eb
|
F src/shell.c ac29402b538515fa4697282387be9c1205e6e9eb
|
||||||
F src/sqlite.h.in 8efd7d5aca057a793d221973da1f22a22e69f4db
|
F src/sqlite.h.in 07eea55853b739b372d4744ceefd08795d013be9
|
||||||
F src/sqlite3ext.h 647a6b8a8f76ff6c9611e4a071531d8e63ff2d6b
|
F src/sqlite3ext.h 647a6b8a8f76ff6c9611e4a071531d8e63ff2d6b
|
||||||
F src/sqliteInt.h fa9baff32aef7ca1ecebcd014b3bd75c981829d0
|
F src/sqliteInt.h 7298c560e00f2305e2ecc1d2cbdd66134f5049de
|
||||||
F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa
|
F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa
|
||||||
F src/table.c c725e47f6f3092b9a7b569fc58e408e2173ee008
|
F src/table.c c725e47f6f3092b9a7b569fc58e408e2173ee008
|
||||||
F src/tclsqlite.c 0606c4f31711492eb4d7480a981eebb80914f3d9
|
F src/tclsqlite.c 0606c4f31711492eb4d7480a981eebb80914f3d9
|
||||||
F src/test1.c 8afb22ec54ee9f28c103c2a212e2e6970626995a
|
F src/test1.c a1d6eb85149053fac75b01b71439f00908a07c68
|
||||||
F src/test2.c 4db48e4a487d4d18c2926d9600875613ad286ba8
|
F src/test2.c 4db48e4a487d4d18c2926d9600875613ad286ba8
|
||||||
F src/test3.c b87e8fcce45e1d3153aae9f04236076b7707a714
|
F src/test3.c b87e8fcce45e1d3153aae9f04236076b7707a714
|
||||||
F src/test4.c d22cb3ab4f9fdfd0a595b70d5328cee923b7322c
|
F src/test4.c d22cb3ab4f9fdfd0a595b70d5328cee923b7322c
|
||||||
@@ -129,7 +129,7 @@ F src/test8.c 719c284607c1e91a893f5425df1e92b74c859aef
|
|||||||
F src/test9.c c0f38f7795cc51d37db6c63874d90f40f10d0f0e
|
F src/test9.c c0f38f7795cc51d37db6c63874d90f40f10d0f0e
|
||||||
F src/test_async.c 871ffbe4a520be74b403aca87aa622ebdb690232
|
F src/test_async.c 871ffbe4a520be74b403aca87aa622ebdb690232
|
||||||
F src/test_autoext.c 855157d97aa28cf84233847548bfacda21807436
|
F src/test_autoext.c 855157d97aa28cf84233847548bfacda21807436
|
||||||
F src/test_btree.c 882d59acad48bab3b1fe3daf3645059b590cfc79
|
F src/test_btree.c c1308ba0b88ab577fa56c9e493a09829dfcded9c
|
||||||
F src/test_config.c 26389b032216e0fb2b544ff48a5e9101bd7b1fb4
|
F src/test_config.c 26389b032216e0fb2b544ff48a5e9101bd7b1fb4
|
||||||
F src/test_hexio.c 82916f918687502658f02533b519c38cb180db6d
|
F src/test_hexio.c 82916f918687502658f02533b519c38cb180db6d
|
||||||
F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
|
F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
|
||||||
@@ -152,7 +152,7 @@ F src/vdbeaux.c c6d50887e8f29706ae35b965298e58fa6ba0e9bf
|
|||||||
F src/vdbeblob.c cf9ee3c7d9977cbd896f8b118da4fb4268637f4f
|
F src/vdbeblob.c cf9ee3c7d9977cbd896f8b118da4fb4268637f4f
|
||||||
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
|
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
|
||||||
F src/vdbemem.c 019952d44066a24aef70ca8c284cfd2d1073c398
|
F src/vdbemem.c 019952d44066a24aef70ca8c284cfd2d1073c398
|
||||||
F src/vtab.c 8d65679ab4ef3efce5d946d7f2d2dac5a33313b4
|
F src/vtab.c ee29237ecc9b310dc43c0c2ac5caa6c6a20787be
|
||||||
F src/where.c 2776a0caf8cbbfd6ec79cfb1cd9bc25074055e5e
|
F src/where.c 2776a0caf8cbbfd6ec79cfb1cd9bc25074055e5e
|
||||||
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
@@ -529,7 +529,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 3d60c14a32955b69e714a73372924d421899f83b
|
P 160593dcc5690af715b775c81137c6e09cca6454
|
||||||
R 79bf1accc56116075f09cd253592694c
|
R 5d5493a8682338889467b44d542e4cdc
|
||||||
U drh
|
U drh
|
||||||
Z e40cc1b0395242393945aa35a1600f4d
|
Z d35e1fbff49f629248bfcae9f72cc56d
|
||||||
|
@@ -1 +1 @@
|
|||||||
160593dcc5690af715b775c81137c6e09cca6454
|
4c1e9ffebe7c611a8b6a89153ae97ab9bca19ea3
|
433
src/btree.c
433
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.398 2007/08/16 10:09:02 danielk1977 Exp $
|
** $Id: btree.c,v 1.399 2007/08/17 01:14:38 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.
|
||||||
@@ -32,6 +32,36 @@ static const char zMagicHeader[] = SQLITE_FILE_HEADER;
|
|||||||
int sqlite3_btree_trace=0; /* True to enable tracing */
|
int sqlite3_btree_trace=0; /* True to enable tracing */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||||
|
/*
|
||||||
|
** A flag to indicate whether or not shared cache is enabled. Also,
|
||||||
|
** a list of BtShared objects that are eligible for participation
|
||||||
|
** in shared cache.
|
||||||
|
*/
|
||||||
|
#ifdef SQLITE_TEST
|
||||||
|
BtShared *sqlite3SharedCacheList = 0;
|
||||||
|
int sqlite3SharedCacheEnabled = 0;
|
||||||
|
#else
|
||||||
|
static BtShared *sqlite3SharedCacheList = 0;
|
||||||
|
static int sqlite3SharedCacheEnabled = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SQLITE_OMIT_SHARED_CACHE */
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||||
|
/*
|
||||||
|
** Enable or disable the shared pager and schema features.
|
||||||
|
**
|
||||||
|
** This routine has no effect on existing database connections.
|
||||||
|
** The shared cache setting effects only future calls to
|
||||||
|
** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2().
|
||||||
|
*/
|
||||||
|
int sqlite3_enable_shared_cache(int enable){
|
||||||
|
sqlite3SharedCacheEnabled = enable;
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Forward declaration
|
** Forward declaration
|
||||||
*/
|
*/
|
||||||
@@ -50,8 +80,9 @@ static int checkReadLocks(Btree*,Pgno,BtCursor*);
|
|||||||
#define queryTableLock(a,b,c) SQLITE_OK
|
#define queryTableLock(a,b,c) SQLITE_OK
|
||||||
#define lockTable(a,b,c) SQLITE_OK
|
#define lockTable(a,b,c) SQLITE_OK
|
||||||
#define unlockAllTables(a)
|
#define unlockAllTables(a)
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||||
/*
|
/*
|
||||||
** Query to see if btree handle p may obtain a lock of type eLock
|
** Query to see if btree handle p may obtain a lock of type eLock
|
||||||
** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return
|
** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return
|
||||||
@@ -63,7 +94,7 @@ static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){
|
|||||||
BtLock *pIter;
|
BtLock *pIter;
|
||||||
|
|
||||||
/* 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( 0==sqlite3ThreadDataReadOnly()->useSharedData ){
|
if( !p->sharable ){
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +127,9 @@ static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){
|
|||||||
}
|
}
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
#endif /* !SQLITE_OMIT_SHARED_CACHE */
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||||
/*
|
/*
|
||||||
** Add a lock on the table with root-page iTable to the shared-btree used
|
** Add a lock on the table with root-page iTable to the shared-btree used
|
||||||
** by Btree handle p. Parameter eLock must be either READ_LOCK or
|
** by Btree handle p. Parameter eLock must be either READ_LOCK or
|
||||||
@@ -111,7 +144,7 @@ static int lockTable(Btree *p, Pgno iTable, u8 eLock){
|
|||||||
BtLock *pIter;
|
BtLock *pIter;
|
||||||
|
|
||||||
/* 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( 0==sqlite3ThreadDataReadOnly()->useSharedData ){
|
if( !p->sharable ){
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +197,9 @@ static int lockTable(Btree *p, Pgno iTable, u8 eLock){
|
|||||||
|
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
#endif /* !SQLITE_OMIT_SHARED_CACHE */
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||||
/*
|
/*
|
||||||
** Release all the table locks (locks obtained via calls to the lockTable()
|
** Release all the table locks (locks obtained via calls to the lockTable()
|
||||||
** procedure) held by Btree handle p.
|
** procedure) held by Btree handle p.
|
||||||
@@ -172,11 +207,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;
|
||||||
|
|
||||||
/* If the shared-cache extension is not enabled, there should be no
|
assert( p->sharable || 0==*ppIter );
|
||||||
** locks in the BtShared.pLock list, making this procedure a no-op. Assert
|
|
||||||
** that this is the case.
|
|
||||||
*/
|
|
||||||
assert( sqlite3ThreadDataReadOnly()->useSharedData || 0==*ppIter );
|
|
||||||
|
|
||||||
while( *ppIter ){
|
while( *ppIter ){
|
||||||
BtLock *pLock = *ppIter;
|
BtLock *pLock = *ppIter;
|
||||||
@@ -1023,6 +1054,8 @@ static void pageReinit(DbPage *pData, int pageSize){
|
|||||||
** zFilename is the name of the database file. If zFilename is NULL
|
** zFilename is the name of the database file. If zFilename is NULL
|
||||||
** a new database with a random name is created. This randomly named
|
** a new database with a random name is created. This randomly named
|
||||||
** database file will be deleted when sqlite3BtreeClose() is called.
|
** database file will be deleted when sqlite3BtreeClose() is called.
|
||||||
|
** If zFilename is ":memory:" then an in-memory database is created
|
||||||
|
** that is automatically destroyed when it is closed.
|
||||||
*/
|
*/
|
||||||
int sqlite3BtreeOpen(
|
int sqlite3BtreeOpen(
|
||||||
const char *zFilename, /* Name of the file containing the BTree database */
|
const char *zFilename, /* Name of the file containing the BTree database */
|
||||||
@@ -1030,14 +1063,11 @@ int sqlite3BtreeOpen(
|
|||||||
Btree **ppBtree, /* Pointer to new Btree object written here */
|
Btree **ppBtree, /* Pointer to new Btree object written here */
|
||||||
int flags /* Options */
|
int flags /* Options */
|
||||||
){
|
){
|
||||||
BtShared *pBt; /* Shared part of btree structure */
|
BtShared *pBt = 0; /* Shared part of btree structure */
|
||||||
Btree *p; /* Handle to return */
|
Btree *p; /* Handle to return */
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
int nReserve;
|
int nReserve;
|
||||||
unsigned char zDbHeader[100];
|
unsigned char zDbHeader[100];
|
||||||
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
|
|
||||||
const ThreadData *pTsdro;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Set the variable isMemdb to true for an in-memory database, or
|
/* Set the variable isMemdb to true for an in-memory database, or
|
||||||
** false for a file-based database. This symbol is only required if
|
** false for a file-based database. This symbol is only required if
|
||||||
@@ -1059,106 +1089,150 @@ int sqlite3BtreeOpen(
|
|||||||
p->inTrans = TRANS_NONE;
|
p->inTrans = TRANS_NONE;
|
||||||
p->pSqlite = pSqlite;
|
p->pSqlite = pSqlite;
|
||||||
|
|
||||||
/* Try to find an existing Btree structure opened on zFilename. */
|
|
||||||
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
|
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
|
||||||
pTsdro = sqlite3ThreadDataReadOnly();
|
/*
|
||||||
if( pTsdro->useSharedData && zFilename && !isMemdb ){
|
** If this Btree is a candidate for shared cache, try to find an
|
||||||
|
** existing BtShared object that we can share with
|
||||||
|
*/
|
||||||
|
if( (flags & BTREE_PRIVATE)==0
|
||||||
|
&& isMemdb==0
|
||||||
|
&& zFilename && zFilename[0]
|
||||||
|
&& sqlite3SharedCacheEnabled
|
||||||
|
){
|
||||||
char *zFullPathname = sqlite3OsFullPathname(zFilename);
|
char *zFullPathname = sqlite3OsFullPathname(zFilename);
|
||||||
|
sqlite3_mutex *mutexShared;
|
||||||
|
p->sharable = 1;
|
||||||
if( !zFullPathname ){
|
if( !zFullPathname ){
|
||||||
sqlite3_free(p);
|
sqlite3_free(p);
|
||||||
return SQLITE_NOMEM;
|
return SQLITE_NOMEM;
|
||||||
}
|
}
|
||||||
for(pBt=pTsdro->pBtree; pBt; pBt=pBt->pNext){
|
mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
|
||||||
|
sqlite3_mutex_enter(mutexShared);
|
||||||
|
for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){
|
||||||
assert( pBt->nRef>0 );
|
assert( pBt->nRef>0 );
|
||||||
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager)) ){
|
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager)) ){
|
||||||
p->pBt = pBt;
|
p->pBt = pBt;
|
||||||
*ppBtree = p;
|
|
||||||
pBt->nRef++;
|
pBt->nRef++;
|
||||||
sqlite3_free(zFullPathname);
|
break;
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sqlite3_mutex_leave(mutexShared);
|
||||||
sqlite3_free(zFullPathname);
|
sqlite3_free(zFullPathname);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
** The following asserts make sure that structures used by the btree are
|
|
||||||
** the right size. This is to guard against size changes that result
|
|
||||||
** when compiling on a different architecture.
|
|
||||||
*/
|
|
||||||
assert( sizeof(i64)==8 || sizeof(i64)==4 );
|
|
||||||
assert( sizeof(u64)==8 || sizeof(u64)==4 );
|
|
||||||
assert( sizeof(u32)==4 );
|
|
||||||
assert( sizeof(u16)==2 );
|
|
||||||
assert( sizeof(Pgno)==4 );
|
|
||||||
|
|
||||||
pBt = sqlite3MallocZero( sizeof(*pBt) );
|
|
||||||
if( pBt==0 ){
|
if( pBt==0 ){
|
||||||
rc = SQLITE_NOMEM;
|
/*
|
||||||
goto btree_open_out;
|
** The following asserts make sure that structures used by the btree are
|
||||||
}
|
** the right size. This is to guard against size changes that result
|
||||||
rc = sqlite3PagerOpen(&pBt->pPager, zFilename, EXTRA_SIZE, flags);
|
** when compiling on a different architecture.
|
||||||
if( rc==SQLITE_OK ){
|
|
||||||
rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
|
|
||||||
}
|
|
||||||
if( rc!=SQLITE_OK ){
|
|
||||||
goto btree_open_out;
|
|
||||||
}
|
|
||||||
p->pBt = pBt;
|
|
||||||
|
|
||||||
sqlite3PagerSetDestructor(pBt->pPager, pageDestructor);
|
|
||||||
sqlite3PagerSetReiniter(pBt->pPager, pageReinit);
|
|
||||||
pBt->pCursor = 0;
|
|
||||||
pBt->pPage1 = 0;
|
|
||||||
pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager);
|
|
||||||
pBt->pageSize = get2byte(&zDbHeader[16]);
|
|
||||||
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
|
|
||||||
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
|
|
||||||
pBt->pageSize = SQLITE_DEFAULT_PAGE_SIZE;
|
|
||||||
pBt->maxEmbedFrac = 64; /* 25% */
|
|
||||||
pBt->minEmbedFrac = 32; /* 12.5% */
|
|
||||||
pBt->minLeafFrac = 32; /* 12.5% */
|
|
||||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
|
||||||
/* If the magic name ":memory:" will create an in-memory database, then
|
|
||||||
** leave the autoVacuum mode at 0 (do not auto-vacuum), even if
|
|
||||||
** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if
|
|
||||||
** SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a
|
|
||||||
** regular file-name. In this case the auto-vacuum applies as per normal.
|
|
||||||
*/
|
*/
|
||||||
if( zFilename && !isMemdb ){
|
assert( sizeof(i64)==8 || sizeof(i64)==4 );
|
||||||
pBt->autoVacuum = (SQLITE_DEFAULT_AUTOVACUUM ? 1 : 0);
|
assert( sizeof(u64)==8 || sizeof(u64)==4 );
|
||||||
pBt->incrVacuum = (SQLITE_DEFAULT_AUTOVACUUM==2 ? 1 : 0);
|
assert( sizeof(u32)==4 );
|
||||||
|
assert( sizeof(u16)==2 );
|
||||||
|
assert( sizeof(Pgno)==4 );
|
||||||
|
|
||||||
|
pBt = sqlite3MallocZero( sizeof(*pBt) );
|
||||||
|
if( pBt==0 ){
|
||||||
|
rc = SQLITE_NOMEM;
|
||||||
|
goto btree_open_out;
|
||||||
|
}
|
||||||
|
rc = sqlite3PagerOpen(&pBt->pPager, zFilename, EXTRA_SIZE, flags);
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
|
||||||
|
}
|
||||||
|
if( rc!=SQLITE_OK ){
|
||||||
|
goto btree_open_out;
|
||||||
|
}
|
||||||
|
p->pBt = pBt;
|
||||||
|
|
||||||
|
sqlite3PagerSetDestructor(pBt->pPager, pageDestructor);
|
||||||
|
sqlite3PagerSetReiniter(pBt->pPager, pageReinit);
|
||||||
|
pBt->pCursor = 0;
|
||||||
|
pBt->pPage1 = 0;
|
||||||
|
pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager);
|
||||||
|
pBt->pageSize = get2byte(&zDbHeader[16]);
|
||||||
|
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
|
||||||
|
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
|
||||||
|
pBt->pageSize = SQLITE_DEFAULT_PAGE_SIZE;
|
||||||
|
pBt->maxEmbedFrac = 64; /* 25% */
|
||||||
|
pBt->minEmbedFrac = 32; /* 12.5% */
|
||||||
|
pBt->minLeafFrac = 32; /* 12.5% */
|
||||||
|
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||||
|
/* If the magic name ":memory:" will create an in-memory database, then
|
||||||
|
** leave the autoVacuum mode at 0 (do not auto-vacuum), even if
|
||||||
|
** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if
|
||||||
|
** SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a
|
||||||
|
** regular file-name. In this case the auto-vacuum applies as per normal.
|
||||||
|
*/
|
||||||
|
if( zFilename && !isMemdb ){
|
||||||
|
pBt->autoVacuum = (SQLITE_DEFAULT_AUTOVACUUM ? 1 : 0);
|
||||||
|
pBt->incrVacuum = (SQLITE_DEFAULT_AUTOVACUUM==2 ? 1 : 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
nReserve = 0;
|
||||||
|
}else{
|
||||||
|
nReserve = zDbHeader[20];
|
||||||
|
pBt->maxEmbedFrac = zDbHeader[21];
|
||||||
|
pBt->minEmbedFrac = zDbHeader[22];
|
||||||
|
pBt->minLeafFrac = zDbHeader[23];
|
||||||
|
pBt->pageSizeFixed = 1;
|
||||||
|
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||||
|
pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0);
|
||||||
|
pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
pBt->usableSize = pBt->pageSize - nReserve;
|
||||||
|
assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */
|
||||||
|
sqlite3PagerSetPagesize(pBt->pPager, pBt->pageSize);
|
||||||
|
|
||||||
|
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
|
||||||
|
/* Add the new BtShared object to the linked list sharable BtShareds.
|
||||||
|
*/
|
||||||
|
if( p->sharable ){
|
||||||
|
sqlite3_mutex *mutexShared;
|
||||||
|
pBt->nRef = 1;
|
||||||
|
mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
|
||||||
|
pBt->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
||||||
|
sqlite3_mutex_enter(mutexShared);
|
||||||
|
pBt->pNext = sqlite3SharedCacheList;
|
||||||
|
sqlite3SharedCacheList = pBt;
|
||||||
|
sqlite3_mutex_leave(mutexShared);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
nReserve = 0;
|
|
||||||
}else{
|
|
||||||
nReserve = zDbHeader[20];
|
|
||||||
pBt->maxEmbedFrac = zDbHeader[21];
|
|
||||||
pBt->minEmbedFrac = zDbHeader[22];
|
|
||||||
pBt->minLeafFrac = zDbHeader[23];
|
|
||||||
pBt->pageSizeFixed = 1;
|
|
||||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
|
||||||
pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0);
|
|
||||||
pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
pBt->usableSize = pBt->pageSize - nReserve;
|
|
||||||
assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */
|
|
||||||
sqlite3PagerSetPagesize(pBt->pPager, pBt->pageSize);
|
|
||||||
|
|
||||||
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
|
#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO)
|
||||||
/* Add the new btree to the linked list starting at ThreadData.pBtree.
|
/* If the new Btree uses a sharable pBtShared, then link the new
|
||||||
** There is no chance that a malloc() may fail inside of the
|
** Btree into the list of all sharable Btrees for the same connection.
|
||||||
** sqlite3ThreadData() call, as the ThreadData structure must have already
|
** The list is kept in ascending order by pBtShared address.
|
||||||
** been allocated for pTsdro->useSharedData to be non-zero.
|
|
||||||
*/
|
*/
|
||||||
if( pTsdro->useSharedData && zFilename && !isMemdb ){
|
if( p->sharable ){
|
||||||
pBt->pNext = pTsdro->pBtree;
|
int i;
|
||||||
sqlite3ThreadData()->pBtree = pBt;
|
Btree *pSib;
|
||||||
|
for(i=0; i<pSqlite->nDb; i++){
|
||||||
|
if( (pSib = pSqlite->aDb[i].pBt)!=0 && pSib->sharable ){
|
||||||
|
while( pSib->pPrev ){ pSib = pSib->pPrev; }
|
||||||
|
if( p->pBt<pSib->pBt ){
|
||||||
|
p->pNext = pSib;
|
||||||
|
p->pPrev = 0;
|
||||||
|
pSib->pPrev = p;
|
||||||
|
}else{
|
||||||
|
while( pSib->pNext && pSib->pNext->pBt>p->pBt ){
|
||||||
|
pSib = pSib->pNext;
|
||||||
|
}
|
||||||
|
p->pNext = pSib->pNext;
|
||||||
|
p->pPrev = pSib;
|
||||||
|
if( p->pNext ){
|
||||||
|
p->pNext->pPrev = p;
|
||||||
|
}
|
||||||
|
pSib->pNext = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
pBt->nRef = 1;
|
|
||||||
*ppBtree = p;
|
*ppBtree = p;
|
||||||
|
|
||||||
btree_open_out:
|
btree_open_out:
|
||||||
@@ -1173,6 +1247,43 @@ btree_open_out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Decrement the BtShared.nRef counter. When it reaches zero,
|
||||||
|
** remove the BtShared structure from the sharing list. Return
|
||||||
|
** true if the BtShared.nRef counter reaches zero and return
|
||||||
|
** false if it is still positive.
|
||||||
|
*/
|
||||||
|
static int removeFromSharingList(BtShared *pBt){
|
||||||
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||||
|
sqlite3_mutex *pMaster;
|
||||||
|
BtShared *pList;
|
||||||
|
int removed = 0;
|
||||||
|
|
||||||
|
pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
|
||||||
|
sqlite3_mutex_enter(pMaster);
|
||||||
|
pBt->nRef--;
|
||||||
|
if( pBt->nRef<=0 ){
|
||||||
|
if( sqlite3SharedCacheList==pBt ){
|
||||||
|
sqlite3SharedCacheList = pBt->pNext;
|
||||||
|
}else{
|
||||||
|
pList = sqlite3SharedCacheList;
|
||||||
|
while( pList && pList->pNext!=pBt ){
|
||||||
|
pList=pList->pNext;
|
||||||
|
}
|
||||||
|
if( pList ){
|
||||||
|
pList->pNext = pBt->pNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_mutex_free(pBt->mutex);
|
||||||
|
removed = 1;
|
||||||
|
}
|
||||||
|
sqlite3_mutex_leave(pMaster);
|
||||||
|
return removed;
|
||||||
|
#else
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Close an open database and invalidate all cursors.
|
** Close an open database and invalidate all cursors.
|
||||||
*/
|
*/
|
||||||
@@ -1180,11 +1291,8 @@ int sqlite3BtreeClose(Btree *p){
|
|||||||
BtShared *pBt = p->pBt;
|
BtShared *pBt = p->pBt;
|
||||||
BtCursor *pCur;
|
BtCursor *pCur;
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
|
||||||
ThreadData *pTsd;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Close all cursors opened via this handle. */
|
/* Close all cursors opened via this handle. */
|
||||||
|
sqlite3BtreeEnter(p);
|
||||||
pCur = pBt->pCursor;
|
pCur = pBt->pCursor;
|
||||||
while( pCur ){
|
while( pCur ){
|
||||||
BtCursor *pTmp = pCur;
|
BtCursor *pTmp = pCur;
|
||||||
@@ -1199,48 +1307,131 @@ int sqlite3BtreeClose(Btree *p){
|
|||||||
** this handle.
|
** this handle.
|
||||||
*/
|
*/
|
||||||
sqlite3BtreeRollback(p);
|
sqlite3BtreeRollback(p);
|
||||||
sqlite3_free(p);
|
sqlite3BtreeLeave(p);
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
|
||||||
/* If there are still other outstanding references to the shared-btree
|
/* If there are still other outstanding references to the shared-btree
|
||||||
** structure, return now. The remainder of this procedure cleans
|
** structure, return now. The remainder of this procedure cleans
|
||||||
** up the shared-btree.
|
** up the shared-btree.
|
||||||
*/
|
*/
|
||||||
assert( pBt->nRef>0 );
|
assert( p->wantToLock==0 && p->locked==0 );
|
||||||
pBt->nRef--;
|
if( !p->sharable || removeFromSharingList(pBt) ){
|
||||||
if( pBt->nRef ){
|
/* The pBt is no longer on the sharing list, so we can access
|
||||||
return SQLITE_OK;
|
** it without having to hold the mutex.
|
||||||
|
**
|
||||||
|
** Clean out and delete the BtShared object.
|
||||||
|
*/
|
||||||
|
assert( !pBt->pCursor );
|
||||||
|
assert( pBt->nRef==0 );
|
||||||
|
sqlite3PagerClose(pBt->pPager);
|
||||||
|
if( pBt->xFreeSchema && pBt->pSchema ){
|
||||||
|
pBt->xFreeSchema(pBt->pSchema);
|
||||||
|
}
|
||||||
|
sqlite3_free(pBt->pSchema);
|
||||||
|
sqlite3_free(pBt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove the shared-btree from the thread wide list. Call
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||||
** ThreadDataReadOnly() and then cast away the const property of the
|
else{
|
||||||
** pointer to avoid allocating thread data if it is not really required.
|
assert( p->wantToLock==0 );
|
||||||
*/
|
assert( p->locked==0 );
|
||||||
pTsd = (ThreadData *)sqlite3ThreadDataReadOnly();
|
assert( p->sharable );
|
||||||
if( pTsd->pBtree==pBt ){
|
if( p->pPrev ) p->pPrev->pNext = p->pNext;
|
||||||
assert( pTsd==sqlite3ThreadData() );
|
if( p->pNext ) p->pNext->pPrev = p->pPrev;
|
||||||
pTsd->pBtree = pBt->pNext;
|
|
||||||
}else{
|
|
||||||
BtShared *pPrev;
|
|
||||||
for(pPrev=pTsd->pBtree; pPrev && pPrev->pNext!=pBt; pPrev=pPrev->pNext){}
|
|
||||||
if( pPrev ){
|
|
||||||
assert( pTsd==sqlite3ThreadData() );
|
|
||||||
pPrev->pNext = pBt->pNext;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Close the pager and free the shared-btree structure */
|
sqlite3_free(p);
|
||||||
assert( !pBt->pCursor );
|
|
||||||
sqlite3PagerClose(pBt->pPager);
|
|
||||||
if( pBt->xFreeSchema && pBt->pSchema ){
|
|
||||||
pBt->xFreeSchema(pBt->pSchema);
|
|
||||||
}
|
|
||||||
sqlite3_free(pBt->pSchema);
|
|
||||||
sqlite3_free(pBt);
|
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||||
|
/*
|
||||||
|
** Enter a mutex on the given BTree object.
|
||||||
|
**
|
||||||
|
** If the object is not sharable, then no mutex is ever required
|
||||||
|
** and this routine is a no-op. The underlying mutex is non-recursive.
|
||||||
|
** But we keep a reference count in Btree.wantToLock so the behavior
|
||||||
|
** of this interface is recursive.
|
||||||
|
**
|
||||||
|
** To avoid deadlocks, multiple Btrees are locked in the same order
|
||||||
|
** by all database connections. The p->pNext is a list of other
|
||||||
|
** Btrees belonging to the same database connection as the p Btree
|
||||||
|
** which need to be locked after p. If we cannot get a lock on
|
||||||
|
** p, then first unlock all of the others on p->pNext, then wait
|
||||||
|
** for the lock to become available on p, then relock all of the
|
||||||
|
** subsequent Btrees that desire a lock.
|
||||||
|
*/
|
||||||
|
void sqlite3BtreeEnter(Btree *p){
|
||||||
|
Btree *pLater;
|
||||||
|
|
||||||
|
/* Some basic sanity checking on the Btree. The list of Btrees
|
||||||
|
** connected by pNext and pPrev should be in sorted order by
|
||||||
|
** Btree.pBt value. All elements of the list should belong to
|
||||||
|
** the same connection. Only shared Btrees are on the list. */
|
||||||
|
assert( p->pNext==0 || p->pNext->pBt>p->pBt );
|
||||||
|
assert( p->pPrev==0 || p->pPrev->pBt<p->pBt );
|
||||||
|
assert( p->pNext==0 || p->pNext->pSqlite==p->pSqlite );
|
||||||
|
assert( p->pPrev==0 || p->pPrev->pSqlite==p->pSqlite );
|
||||||
|
assert( p->sharable || (p->pNext==0 && p->pPrev==0) );
|
||||||
|
|
||||||
|
/* Check for locking consistency */
|
||||||
|
assert( !p->locked || p->wantToLock>0 );
|
||||||
|
assert( p->sharable || p->wantToLock==0 );
|
||||||
|
|
||||||
|
if( !p->sharable ) return;
|
||||||
|
p->wantToLock++;
|
||||||
|
if( p->locked ) return;
|
||||||
|
|
||||||
|
/* In most cases, we should be able to acquire the lock we
|
||||||
|
** want without having to go throught the ascending lock
|
||||||
|
** procedure that follows. Just be sure not to block.
|
||||||
|
*/
|
||||||
|
if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){
|
||||||
|
p->locked = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To avoid deadlock, first release all locks with a larger
|
||||||
|
** BtShared address. Then acquire our lock. Then reacquire
|
||||||
|
** the other BtShared locks that we used to hold in ascending
|
||||||
|
** order.
|
||||||
|
*/
|
||||||
|
for(pLater=p->pNext; pLater; pLater=pLater->pNext){
|
||||||
|
assert( pLater->sharable );
|
||||||
|
assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt );
|
||||||
|
assert( !pLater->locked || pLater->wantToLock>0 );
|
||||||
|
if( pLater->locked ){
|
||||||
|
sqlite3_mutex_leave(pLater->pBt->mutex);
|
||||||
|
pLater->locked = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_mutex_enter(p->pBt->mutex);
|
||||||
|
for(pLater=p->pNext; pLater; pLater=pLater->pNext){
|
||||||
|
if( pLater->wantToLock ){
|
||||||
|
sqlite3_mutex_enter(pLater->pBt->mutex);
|
||||||
|
pLater->locked = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* !SQLITE_OMIT_SHARED_CACHE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Exit the recursive mutex on a Btree.
|
||||||
|
*/
|
||||||
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||||
|
void sqlite3BtreeLeave(Btree *p){
|
||||||
|
if( p->sharable ){
|
||||||
|
assert( p->wantToLock>0 );
|
||||||
|
p->wantToLock--;
|
||||||
|
if( p->wantToLock==0 ){
|
||||||
|
assert( p->locked );
|
||||||
|
sqlite3_mutex_leave(p->pBt->mutex);
|
||||||
|
p->locked = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* !SQLITE_OMIT_SHARED_CACHE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Change the busy handler callback function.
|
** Change the busy handler callback function.
|
||||||
*/
|
*/
|
||||||
|
23
src/btree.h
23
src/btree.h
@@ -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.82 2007/05/08 21:45:27 drh Exp $
|
** @(#) $Id: btree.h,v 1.83 2007/08/17 01:14:38 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _BTREE_H_
|
#ifndef _BTREE_H_
|
||||||
#define _BTREE_H_
|
#define _BTREE_H_
|
||||||
@@ -59,6 +59,14 @@ int sqlite3BtreeOpen(
|
|||||||
#define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */
|
#define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */
|
||||||
#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
|
#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
|
||||||
#define BTREE_MEMORY 4 /* In-memory DB. No argument */
|
#define BTREE_MEMORY 4 /* In-memory DB. No argument */
|
||||||
|
#define BTREE_READONLY 8 /* Open the database in read-only mode */
|
||||||
|
#define BTREE_READWRITE 16 /* Open for both reading and writing */
|
||||||
|
#define BTREE_CREATE 32 /* Create the database if it does not exist */
|
||||||
|
|
||||||
|
/* Additional values for the 4th argument of sqlite3BtreeOpen that
|
||||||
|
** are not associated with PAGER_ values.
|
||||||
|
*/
|
||||||
|
#define BTREE_PRIVATE 64 /* Never share with other connections */
|
||||||
|
|
||||||
int sqlite3BtreeClose(Btree*);
|
int sqlite3BtreeClose(Btree*);
|
||||||
int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*);
|
int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*);
|
||||||
@@ -87,6 +95,19 @@ void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
|
|||||||
int sqlite3BtreeSchemaLocked(Btree *);
|
int sqlite3BtreeSchemaLocked(Btree *);
|
||||||
int sqlite3BtreeLockTable(Btree *, int, u8);
|
int sqlite3BtreeLockTable(Btree *, int, u8);
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If we are not using shared cache, then there is no need to
|
||||||
|
** use mutexes to access the BtShared structures. So make the
|
||||||
|
** Enter and Leave procedures no-ops.
|
||||||
|
*/
|
||||||
|
#ifdef SQLITE_OMIT_SHARED_CACHE
|
||||||
|
# define sqlite3BtreeEnter(X)
|
||||||
|
# define sqlite3BtreeLeave(X)
|
||||||
|
#else
|
||||||
|
void sqlite3BtreeEnter(Btree*);
|
||||||
|
void sqlite3BtreeLeave(Btree*);
|
||||||
|
#endif
|
||||||
|
|
||||||
const char *sqlite3BtreeGetFilename(Btree *);
|
const char *sqlite3BtreeGetFilename(Btree *);
|
||||||
const char *sqlite3BtreeGetDirname(Btree *);
|
const char *sqlite3BtreeGetDirname(Btree *);
|
||||||
const char *sqlite3BtreeGetJournalname(Btree *);
|
const char *sqlite3BtreeGetJournalname(Btree *);
|
||||||
|
@@ -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: btreeInt.h,v 1.5 2007/06/15 12:06:59 drh Exp $
|
** $Id: btreeInt.h,v 1.6 2007/08/17 01:14:38 drh Exp $
|
||||||
**
|
**
|
||||||
** This file implements a external (disk-based) database using BTrees.
|
** This file implements a external (disk-based) database using BTrees.
|
||||||
** For a detailed discussion of BTrees, refer to
|
** For a detailed discussion of BTrees, refer to
|
||||||
@@ -248,7 +248,7 @@ typedef struct BtLock BtLock;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Page type flags. An ORed combination of these flags appear as the
|
** Page type flags. An ORed combination of these flags appear as the
|
||||||
** first byte of every BTree page.
|
** first byte of on-disk image of every BTree page.
|
||||||
*/
|
*/
|
||||||
#define PTF_INTKEY 0x01
|
#define PTF_INTKEY 0x01
|
||||||
#define PTF_ZERODATA 0x02
|
#define PTF_ZERODATA 0x02
|
||||||
@@ -276,8 +276,8 @@ struct MemPage {
|
|||||||
u8 hasData; /* True if this page stores data */
|
u8 hasData; /* True if this page stores data */
|
||||||
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
|
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
|
||||||
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
|
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
|
||||||
u16 maxLocal; /* Copy of Btree.maxLocal or Btree.maxLeaf */
|
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
|
||||||
u16 minLocal; /* Copy of Btree.minLocal or Btree.minLeaf */
|
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
|
||||||
u16 cellOffset; /* Index in aData of first cell pointer */
|
u16 cellOffset; /* Index in aData of first cell pointer */
|
||||||
u16 idxParent; /* Index in parent of this node */
|
u16 idxParent; /* Index in parent of this node */
|
||||||
u16 nFree; /* Number of free bytes on the page */
|
u16 nFree; /* Number of free bytes on the page */
|
||||||
@@ -286,8 +286,8 @@ struct MemPage {
|
|||||||
u8 *pCell; /* Pointers to the body of the overflow cell */
|
u8 *pCell; /* Pointers to the body of the overflow cell */
|
||||||
u16 idx; /* Insert this cell before idx-th non-overflow cell */
|
u16 idx; /* Insert this cell before idx-th non-overflow cell */
|
||||||
} aOvfl[5];
|
} aOvfl[5];
|
||||||
BtShared *pBt; /* Pointer back to BTree structure */
|
BtShared *pBt; /* Pointer to BtShared that this page is part of */
|
||||||
u8 *aData; /* Pointer back to the start of the page */
|
u8 *aData; /* Pointer to disk image of the page data */
|
||||||
DbPage *pDbPage; /* Pager page handle */
|
DbPage *pDbPage; /* Pager page handle */
|
||||||
Pgno pgno; /* Page number for this page */
|
Pgno pgno; /* Page number for this page */
|
||||||
MemPage *pParent; /* The parent of this page. NULL for root */
|
MemPage *pParent; /* The parent of this page. NULL for root */
|
||||||
@@ -300,11 +300,30 @@ struct MemPage {
|
|||||||
*/
|
*/
|
||||||
#define EXTRA_SIZE sizeof(MemPage)
|
#define EXTRA_SIZE sizeof(MemPage)
|
||||||
|
|
||||||
/* Btree handle */
|
/* A Btree handle
|
||||||
|
**
|
||||||
|
** A database connection contains a pointer to an instance of
|
||||||
|
** this object for every database file that it has open. This structure
|
||||||
|
** is opaque to the database connection. The database connection cannot
|
||||||
|
** see the internals of this structure and only deals with pointers to
|
||||||
|
** this structure.
|
||||||
|
**
|
||||||
|
** For some database files, the same underlying database cache might be
|
||||||
|
** shared between multiple connections. In that case, each contection
|
||||||
|
** has it own pointer to this object. But each instance of this object
|
||||||
|
** points to the same BtShared object. The database cache and the
|
||||||
|
** schema associated with the database file are all contained within
|
||||||
|
** the BtShared object.
|
||||||
|
*/
|
||||||
struct Btree {
|
struct Btree {
|
||||||
sqlite3 *pSqlite;
|
sqlite3 *pSqlite; /* The database connection holding this btree */
|
||||||
BtShared *pBt;
|
BtShared *pBt; /* Sharable content of this btree */
|
||||||
u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
|
u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
|
||||||
|
u8 sharable; /* True if we can share pBt with other pSqlite */
|
||||||
|
u8 locked; /* True if pSqlite currently has pBt locked */
|
||||||
|
int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
|
||||||
|
Btree *pNext; /* List of Btrees with the same pSqlite value */
|
||||||
|
Btree *pPrev; /* Back pointer of the same list */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -312,15 +331,21 @@ struct Btree {
|
|||||||
**
|
**
|
||||||
** If the shared-data extension is enabled, there may be multiple users
|
** If the shared-data extension is enabled, there may be multiple users
|
||||||
** of the Btree structure. At most one of these may open a write transaction,
|
** of the Btree structure. At most one of these may open a write transaction,
|
||||||
** but any number may have active read transactions. Variable Btree.pDb
|
** but any number may have active read transactions.
|
||||||
** points to the handle that owns any current write-transaction.
|
|
||||||
*/
|
*/
|
||||||
#define TRANS_NONE 0
|
#define TRANS_NONE 0
|
||||||
#define TRANS_READ 1
|
#define TRANS_READ 1
|
||||||
#define TRANS_WRITE 2
|
#define TRANS_WRITE 2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Everything we need to know about an open database
|
** An instance of this object represents a single database file.
|
||||||
|
**
|
||||||
|
** A single database file can be in use as the same time by two
|
||||||
|
** or more database connections. When two or more connections are
|
||||||
|
** sharing the same database file, each connection has it own
|
||||||
|
** private Btree object for the file and each of those Btrees points
|
||||||
|
** to this one BtShared object. BtShared.nRef is the number of
|
||||||
|
** connections currently sharing this database file.
|
||||||
*/
|
*/
|
||||||
struct BtShared {
|
struct BtShared {
|
||||||
Pager *pPager; /* The page cache */
|
Pager *pPager; /* The page cache */
|
||||||
@@ -350,6 +375,7 @@ struct BtShared {
|
|||||||
void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
|
void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
|
||||||
void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
|
void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
|
||||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||||
|
sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */
|
||||||
BtLock *pLock; /* List of locks held on this shared-btree struct */
|
BtLock *pLock; /* List of locks held on this shared-btree struct */
|
||||||
BtShared *pNext; /* Next in ThreadData.pBtree linked list */
|
BtShared *pNext; /* Next in ThreadData.pBtree linked list */
|
||||||
#endif
|
#endif
|
||||||
@@ -373,9 +399,15 @@ struct CellInfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** A cursor is a pointer to a particular entry in the BTree.
|
** A cursor is a pointer to a particular entry within a particular
|
||||||
|
** b-tree within a database file.
|
||||||
|
**
|
||||||
** The entry is identified by its MemPage and the index in
|
** The entry is identified by its MemPage and the index in
|
||||||
** MemPage.aCell[] of the entry.
|
** MemPage.aCell[] of the entry.
|
||||||
|
**
|
||||||
|
** When a single database file can shared by two more database connections,
|
||||||
|
** but cursors cannot be shared. Each cursor is associated with a
|
||||||
|
** particular database connection identified BtCursor.pBtree.pSqlite.
|
||||||
*/
|
*/
|
||||||
struct BtCursor {
|
struct BtCursor {
|
||||||
Btree *pBtree; /* The Btree to which this cursor belongs */
|
Btree *pBtree; /* The Btree to which this cursor belongs */
|
||||||
@@ -530,8 +562,6 @@ struct BtLock {
|
|||||||
** of handle p (type Btree*) are internally consistent.
|
** of handle p (type Btree*) are internally consistent.
|
||||||
*/
|
*/
|
||||||
#define btreeIntegrity(p) \
|
#define btreeIntegrity(p) \
|
||||||
assert( p->inTrans!=TRANS_NONE || p->pBt->nTransaction<p->pBt->nRef ); \
|
|
||||||
assert( p->pBt->nTransaction<=p->pBt->nRef ); \
|
|
||||||
assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \
|
assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \
|
||||||
assert( p->pBt->inTransaction>=p->inTrans );
|
assert( p->pBt->inTransaction>=p->inTrans );
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
** COMMIT
|
** COMMIT
|
||||||
** ROLLBACK
|
** ROLLBACK
|
||||||
**
|
**
|
||||||
** $Id: build.c,v 1.435 2007/08/16 10:09:02 danielk1977 Exp $
|
** $Id: build.c,v 1.436 2007/08/17 01:14:38 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -69,7 +69,7 @@ void sqlite3TableLock(
|
|||||||
int nBytes;
|
int nBytes;
|
||||||
TableLock *p;
|
TableLock *p;
|
||||||
|
|
||||||
if( 0==sqlite3ThreadDataReadOnly()->useSharedData || iDb<0 ){
|
if( iDb<0 ){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +100,6 @@ void sqlite3TableLock(
|
|||||||
static void codeTableLocks(Parse *pParse){
|
static void codeTableLocks(Parse *pParse){
|
||||||
int i;
|
int i;
|
||||||
Vdbe *pVdbe;
|
Vdbe *pVdbe;
|
||||||
assert( sqlite3ThreadDataReadOnly()->useSharedData || pParse->nTableLock==0 );
|
|
||||||
|
|
||||||
if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){
|
if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){
|
||||||
return;
|
return;
|
||||||
|
31
src/main.c
31
src/main.c
@@ -14,7 +14,7 @@
|
|||||||
** other files are for internal use by SQLite and should not be
|
** other files are for internal use by SQLite and should not be
|
||||||
** accessed by users of the library.
|
** accessed by users of the library.
|
||||||
**
|
**
|
||||||
** $Id: main.c,v 1.382 2007/08/16 13:01:45 drh Exp $
|
** $Id: main.c,v 1.383 2007/08/17 01:14:38 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
@@ -1235,35 +1235,6 @@ int sqlite3Corrupt(void){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
|
||||||
/*
|
|
||||||
** Enable or disable the shared pager and schema features for the
|
|
||||||
** current thread.
|
|
||||||
**
|
|
||||||
** This routine should only be called when there are no open
|
|
||||||
** database connections.
|
|
||||||
*/
|
|
||||||
int sqlite3_enable_shared_cache(int enable){
|
|
||||||
ThreadData *pTd = sqlite3ThreadData();
|
|
||||||
if( pTd ){
|
|
||||||
/* It is only legal to call sqlite3_enable_shared_cache() when there
|
|
||||||
** are no currently open b-trees that were opened by the calling thread.
|
|
||||||
** This condition is only easy to detect if the shared-cache were
|
|
||||||
** previously enabled (and is being disabled).
|
|
||||||
*/
|
|
||||||
if( pTd->pBtree && !enable ){
|
|
||||||
assert( pTd->useSharedData );
|
|
||||||
return SQLITE_MISUSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pTd->useSharedData = enable;
|
|
||||||
/* sqlite3ReleaseThreadData(); */
|
|
||||||
}
|
|
||||||
return sqlite3ApiExit(0, SQLITE_OK);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This is a convenience routine that makes sure that all thread-specific
|
** This is a convenience routine that makes sure that all thread-specific
|
||||||
** data for this thread has been deallocated.
|
** data for this thread has been deallocated.
|
||||||
|
26
src/mutex.c
26
src/mutex.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains the C functions that implement mutexes for
|
** This file contains the C functions that implement mutexes for
|
||||||
** use by the SQLite core.
|
** use by the SQLite core.
|
||||||
**
|
**
|
||||||
** $Id: mutex.c,v 1.3 2007/08/16 19:40:17 drh Exp $
|
** $Id: mutex.c,v 1.4 2007/08/17 01:14:38 drh Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -228,17 +228,19 @@ void sqlite3_mutex_enter(sqlite3_mutex *pMutex){
|
|||||||
pthread_mutex_lock(&p->mutex);
|
pthread_mutex_lock(&p->mutex);
|
||||||
}else{
|
}else{
|
||||||
struct RMutex *p = (struct RMutex*)pMutex;
|
struct RMutex *p = (struct RMutex*)pMutex;
|
||||||
pthread_mutex_lock(&p->auxMutex);
|
while(1){
|
||||||
if( p->nRef==0 ){
|
pthread_mutex_lock(&p->auxMutex);
|
||||||
p->nRef++;
|
if( p->nRef==0 ){
|
||||||
p->owner = pthread_self();
|
p->nRef++;
|
||||||
pthread_mutex_lock(&p->mainMutex);
|
p->owner = pthread_self();
|
||||||
pthread_mutex_unlock(&p->auxMutex);
|
pthread_mutex_lock(&p->mainMutex);
|
||||||
}else if( pthread_equal(p->owner, pthread_self()) ){
|
pthread_mutex_unlock(&p->auxMutex);
|
||||||
p->nRef++;
|
break;
|
||||||
pthread_mutex_unlock(&p->auxMutex);
|
}else if( pthread_equal(p->owner, pthread_self()) ){
|
||||||
}else{
|
p->nRef++;
|
||||||
while( p->nRef ){
|
pthread_mutex_unlock(&p->auxMutex);
|
||||||
|
break;
|
||||||
|
}else{
|
||||||
pthread_mutex_unlock(&p->auxMutex);
|
pthread_mutex_unlock(&p->auxMutex);
|
||||||
pthread_mutex_lock(&p->mainMutex);
|
pthread_mutex_lock(&p->mainMutex);
|
||||||
pthread_mutex_unlock(&p->mainMutex);
|
pthread_mutex_unlock(&p->mainMutex);
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
** the version number) and changes its name to "sqlite3.h" as
|
** the version number) and changes its name to "sqlite3.h" as
|
||||||
** part of the build process.
|
** part of the build process.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqlite.h.in,v 1.226 2007/08/16 19:40:17 drh Exp $
|
** @(#) $Id: sqlite.h.in,v 1.227 2007/08/17 01:14:38 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITE3_H_
|
#ifndef _SQLITE3_H_
|
||||||
#define _SQLITE3_H_
|
#define _SQLITE3_H_
|
||||||
@@ -2175,6 +2175,9 @@ int sqlite3_global_recover(void);
|
|||||||
** [sqlite3_value_text16()] can be invalidated by a subsequent call to
|
** [sqlite3_value_text16()] can be invalidated by a subsequent call to
|
||||||
** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()],
|
** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()],
|
||||||
** or [sqlite3_value_text16()].
|
** or [sqlite3_value_text16()].
|
||||||
|
**
|
||||||
|
** These routines must be called from the same thread as
|
||||||
|
** the SQL function that supplied the sqlite3_value* parameters.
|
||||||
*/
|
*/
|
||||||
const void *sqlite3_value_blob(sqlite3_value*);
|
const void *sqlite3_value_blob(sqlite3_value*);
|
||||||
int sqlite3_value_bytes(sqlite3_value*);
|
int sqlite3_value_bytes(sqlite3_value*);
|
||||||
@@ -2206,6 +2209,9 @@ int sqlite3_value_numeric_type(sqlite3_value*);
|
|||||||
** [sqlite3_context | SQL function context] that is the first
|
** [sqlite3_context | SQL function context] that is the first
|
||||||
** parameter to the callback routine that implements the aggregate
|
** parameter to the callback routine that implements the aggregate
|
||||||
** function.
|
** function.
|
||||||
|
**
|
||||||
|
** This routine must be called from the same thread in which
|
||||||
|
** the aggregate SQL function was originally invoked.
|
||||||
*/
|
*/
|
||||||
void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
|
void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
|
||||||
|
|
||||||
@@ -2216,6 +2222,9 @@ void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
|
|||||||
** and [sqlite3_create_function16()] routines
|
** and [sqlite3_create_function16()] routines
|
||||||
** used to register user functions is available to
|
** used to register user functions is available to
|
||||||
** the implementation of the function using this call.
|
** the implementation of the function using this call.
|
||||||
|
**
|
||||||
|
** This routine must be called from the same thread in which
|
||||||
|
** the SQL function was originally invoked.
|
||||||
*/
|
*/
|
||||||
void *sqlite3_user_data(sqlite3_context*);
|
void *sqlite3_user_data(sqlite3_context*);
|
||||||
|
|
||||||
@@ -2248,6 +2257,9 @@ void *sqlite3_user_data(sqlite3_context*);
|
|||||||
** In practice, meta-data is preserved between function calls for
|
** In practice, meta-data is preserved between function calls for
|
||||||
** expressions that are constant at compile time. This includes literal
|
** expressions that are constant at compile time. This includes literal
|
||||||
** values and SQL variables.
|
** values and SQL variables.
|
||||||
|
**
|
||||||
|
** These routine must be called from the same thread in which
|
||||||
|
** the SQL function was originally invoked.
|
||||||
*/
|
*/
|
||||||
void *sqlite3_get_auxdata(sqlite3_context*, int);
|
void *sqlite3_get_auxdata(sqlite3_context*, int);
|
||||||
void sqlite3_set_auxdata(sqlite3_context*, int, void*, void (*)(void*));
|
void sqlite3_set_auxdata(sqlite3_context*, int, void*, void (*)(void*));
|
||||||
@@ -2294,6 +2306,9 @@ typedef void (*sqlite3_destructor_type)(void*);
|
|||||||
** The sqlite3_result_toobig() cause the function implementation
|
** The sqlite3_result_toobig() cause the function implementation
|
||||||
** to throw and error indicating that a string or BLOB is to long
|
** to throw and error indicating that a string or BLOB is to long
|
||||||
** to represent.
|
** to represent.
|
||||||
|
**
|
||||||
|
** These routines must be called from within the same thread as
|
||||||
|
** the SQL function associated with the [sqlite3_context] pointer.
|
||||||
*/
|
*/
|
||||||
void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
|
void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
|
||||||
void sqlite3_result_double(sqlite3_context*, double);
|
void sqlite3_result_double(sqlite3_context*, double);
|
||||||
@@ -3234,8 +3249,9 @@ int sqlite3_unregister_vfs(sqlite3_vfs*);
|
|||||||
** The sqlite3_mutex_free() routine deallocates a previously
|
** The sqlite3_mutex_free() routine deallocates a previously
|
||||||
** allocated dynamic mutex. SQLite is careful to deallocate every
|
** allocated dynamic mutex. SQLite is careful to deallocate every
|
||||||
** dynamic mutex that it allocates. The dynamic mutexes must not be in
|
** dynamic mutex that it allocates. The dynamic mutexes must not be in
|
||||||
** use when they are deallocated. Static mutexes do not need to be
|
** use when they are deallocated. Attempting to deallocate a static
|
||||||
** deallocated and SQLite never bothers to do so.
|
** mutex results in undefined behavior. SQLite never deallocates
|
||||||
|
** a static mutex.
|
||||||
**
|
**
|
||||||
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
|
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
|
||||||
** to enter a mutex. If another thread is already within the mutex,
|
** to enter a mutex. If another thread is already within the mutex,
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.589 2007/08/16 13:01:45 drh Exp $
|
** @(#) $Id: sqliteInt.h,v 1.590 2007/08/17 01:14:38 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITEINT_H_
|
#ifndef _SQLITEINT_H_
|
||||||
#define _SQLITEINT_H_
|
#define _SQLITEINT_H_
|
||||||
@@ -399,6 +399,7 @@ struct sqlite3 {
|
|||||||
int magic; /* Magic number for detect library misuse */
|
int magic; /* Magic number for detect library misuse */
|
||||||
int nChange; /* Value returned by sqlite3_changes() */
|
int nChange; /* Value returned by sqlite3_changes() */
|
||||||
int nTotalChange; /* Value returned by sqlite3_total_changes() */
|
int nTotalChange; /* Value returned by sqlite3_total_changes() */
|
||||||
|
sqlite3_mutex *pMutex; /* Connection mutex */
|
||||||
struct sqlite3InitInfo { /* Information used during initialization */
|
struct sqlite3InitInfo { /* Information used during initialization */
|
||||||
int iDb; /* When back is being initialized */
|
int iDb; /* When back is being initialized */
|
||||||
int newTnum; /* Rootpage of table being initialized */
|
int newTnum; /* Rootpage of table being initialized */
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
** is not included in the SQLite library. It is used for automated
|
** is not included in the SQLite library. It is used for automated
|
||||||
** testing of the SQLite library.
|
** testing of the SQLite library.
|
||||||
**
|
**
|
||||||
** $Id: test1.c,v 1.262 2007/08/16 13:01:45 drh Exp $
|
** $Id: test1.c,v 1.263 2007/08/17 01:14:38 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "tcl.h"
|
#include "tcl.h"
|
||||||
@@ -1312,6 +1312,7 @@ static int test_enable_shared(
|
|||||||
int rc;
|
int rc;
|
||||||
int enable;
|
int enable;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
extern int sqlite3SharedCacheEnabled;
|
||||||
|
|
||||||
if( objc!=2 ){
|
if( objc!=2 ){
|
||||||
Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
|
Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
|
||||||
@@ -1320,7 +1321,7 @@ static int test_enable_shared(
|
|||||||
if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
|
if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
ret = sqlite3ThreadDataReadOnly()->useSharedData;
|
ret = sqlite3SharedCacheEnabled;
|
||||||
rc = sqlite3_enable_shared_cache(enable);
|
rc = sqlite3_enable_shared_cache(enable);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
|
Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
** is not included in the SQLite library. It is used for automated
|
** is not included in the SQLite library. It is used for automated
|
||||||
** testing of the SQLite library.
|
** testing of the SQLite library.
|
||||||
**
|
**
|
||||||
** $Id: test_btree.c,v 1.2 2007/05/08 11:27:16 drh Exp $
|
** $Id: test_btree.c,v 1.3 2007/08/17 01:14:39 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "btreeInt.h"
|
#include "btreeInt.h"
|
||||||
#include <tcl.h>
|
#include <tcl.h>
|
||||||
@@ -140,17 +140,15 @@ int sqlite3BtreeSharedCacheReport(
|
|||||||
Tcl_Obj *CONST objv[]
|
Tcl_Obj *CONST objv[]
|
||||||
){
|
){
|
||||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||||
const ThreadData *pTd = sqlite3ThreadDataReadOnly();
|
extern BtShared *sqlite3SharedCacheList;
|
||||||
if( pTd->useSharedData ){
|
BtShared *pBt;
|
||||||
BtShared *pBt;
|
Tcl_Obj *pRet = Tcl_NewObj();
|
||||||
Tcl_Obj *pRet = Tcl_NewObj();
|
for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){
|
||||||
for(pBt=pTd->pBtree; pBt; pBt=pBt->pNext){
|
const char *zFile = sqlite3PagerFilename(pBt->pPager);
|
||||||
const char *zFile = sqlite3PagerFilename(pBt->pPager);
|
Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zFile, -1));
|
||||||
Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(zFile, -1));
|
Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(pBt->nRef));
|
||||||
Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(pBt->nRef));
|
|
||||||
}
|
|
||||||
Tcl_SetObjResult(interp, pRet);
|
|
||||||
}
|
}
|
||||||
|
Tcl_SetObjResult(interp, pRet);
|
||||||
#endif
|
#endif
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** This file contains code used to help implement virtual tables.
|
** This file contains code used to help implement virtual tables.
|
||||||
**
|
**
|
||||||
** $Id: vtab.c,v 1.50 2007/08/16 10:09:03 danielk1977 Exp $
|
** $Id: vtab.c,v 1.51 2007/08/17 01:14:39 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
@@ -162,7 +162,7 @@ void sqlite3VtabBeginParse(
|
|||||||
Table *pTable; /* The new virtual table */
|
Table *pTable; /* The new virtual table */
|
||||||
sqlite3 *db; /* Database connection */
|
sqlite3 *db; /* Database connection */
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
#if 0 /* FIX ME */
|
||||||
if( sqlite3ThreadDataReadOnly()->useSharedData ){
|
if( sqlite3ThreadDataReadOnly()->useSharedData ){
|
||||||
sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode");
|
sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode");
|
||||||
return;
|
return;
|
||||||
|
Reference in New Issue
Block a user