1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Big change to make pager.c easier to follow. Unused variables removed, comments improved, etc. (CVS 6197)

FossilOrigin-Name: 12f7346c13c180ed73d7a2e3b590be457360254a
This commit is contained in:
danielk1977
2009-01-20 17:06:27 +00:00
parent 78ca0e7eb4
commit bea2a94850
13 changed files with 2358 additions and 1631 deletions

View File

@@ -1,5 +1,5 @@
C When\snot\scompiling\sfor\san\sEBCDIC\ssystem,\suse\sbuilt-in\salternatives\sto\sthe\stolowe\nr(),\stoupper()\sand\sother\sctype.h\slibrary\sfunctions.\sTicket\s#3597.\s(CVS\s6196) C Big\schange\sto\smake\spager.c\seasier\sto\sfollow.\sUnused\svariables\sremoved,\scomments\simproved,\setc.\s(CVS\s6197)
D 2009-01-20T16:53:40 D 2009-01-20T17:06:27
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 6619a1b72de7ada2bb7be97862913e27c6f5e339 F Makefile.in 6619a1b72de7ada2bb7be97862913e27c6f5e339
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -101,11 +101,11 @@ F src/alter.c 0ec29744c36c6e976596ce38c16289ebc5dc94db
F src/analyze.c c86fd6a1425b22b3a46ce72ad403e4280026364f F src/analyze.c c86fd6a1425b22b3a46ce72ad403e4280026364f
F src/attach.c 1c35f95da3c62d19de75b44cfefd12c81c1791b3 F src/attach.c 1c35f95da3c62d19de75b44cfefd12c81c1791b3
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/bitvec.c 1da48f915129b476cae0cfd7a6ed0eb0d03a9bdb F src/bitvec.c 44f7059ac1f874d364b34af31b9617e52223ba75
F src/btmutex.c 63c5cc4ad5715690767ffcb741e185d7bc35ec1a F src/btmutex.c 63c5cc4ad5715690767ffcb741e185d7bc35ec1a
F src/btree.c e183a4357e8f5081fd04c757e006ef6fdaaa79a1 F src/btree.c 01b3af74d9e756901f21401ca1a3d0bb8b2b9368
F src/btree.h 4f141cf748d2ee7c6d7fc175f64f87a45cd44113 F src/btree.h 4f141cf748d2ee7c6d7fc175f64f87a45cd44113
F src/btreeInt.h 790482376263bbc5862ae7124354a26c70695369 F src/btreeInt.h 44bcbfe387ba99a3a9f2527bd12fa1bb8bc574b3
F src/build.c c8bf5dcef4d5889bc57eecdb8b3dba178e5e06a8 F src/build.c c8bf5dcef4d5889bc57eecdb8b3dba178e5e06a8
F src/callback.c bee8949d619b1b7b1e4dfac8a19c5116ae1dd12a F src/callback.c bee8949d619b1b7b1e4dfac8a19c5116ae1dd12a
F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
@@ -119,7 +119,7 @@ F src/hash.c 5824e6ff7ba78cd34c8d6cd724367713583e5b55
F src/hash.h 28f38ebb1006a5beedcb013bcdfe31befe7437ae F src/hash.h 28f38ebb1006a5beedcb013bcdfe31befe7437ae
F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb
F src/insert.c f6db1e6f43aae337e64a755208abb6ff124edc19 F src/insert.c f6db1e6f43aae337e64a755208abb6ff124edc19
F src/journal.c cffd2cd214e58c0e99c3ff632b3bee6c7cbb260e F src/journal.c e00df0c0da8413ab6e1bb7d7cab5665d4a9000d0
F src/legacy.c 8b3b95d48d202614946d7ce7256e7ba898905c3b F src/legacy.c 8b3b95d48d202614946d7ce7256e7ba898905c3b
F src/loadext.c 3f96631089fc4f3871a67f02f2e4fc7ea4d51edc F src/loadext.c 3f96631089fc4f3871a67f02f2e4fc7ea4d51edc
F src/main.c da5ff4dfbb59896af5f7b4afaef48d2fb7d08a7d F src/main.c da5ff4dfbb59896af5f7b4afaef48d2fb7d08a7d
@@ -142,11 +142,11 @@ F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60
F src/os_os2.c bed77dc26e3a95ce4a204936b9a1ca6fe612fcc5 F src/os_os2.c bed77dc26e3a95ce4a204936b9a1ca6fe612fcc5
F src/os_unix.c c74255cc1fcddc38fc3cc1dcf70c2325d3c2948e F src/os_unix.c c74255cc1fcddc38fc3cc1dcf70c2325d3c2948e
F src/os_win.c 496e3ceb499aedc63622a89ef76f7af2dd902709 F src/os_win.c 496e3ceb499aedc63622a89ef76f7af2dd902709
F src/pager.c bf917e869ef44b8e277e87f5b5ac980a1ee727ef F src/pager.c 52fdfe6d6326a646152a26f1db94f4563fd6db39
F src/pager.h 3345547d4b5b4db323f50d855d91a01837c7f2de F src/pager.h 95b9802f6a014cc55523006f2b893a37b2dc16e3
F src/parse.y b214295a91e985c42adb6bfd3ad1c56c47828e8d F src/parse.y b214295a91e985c42adb6bfd3ad1c56c47828e8d
F src/pcache.c a3c729f4bb3464fab27617ab7411916e0cded2bf F src/pcache.c 48fbfc2208a2734c578b3223fcd4fea7d84f442b
F src/pcache.h 00adba50e5b90414a40f2c63e5272c152c523373 F src/pcache.h 9b927ccc5a538e31b4c3bc7eec4f976db42a1324
F src/pcache1.c c0aa84ff69ea759fa944dbee9167a2463ab7c322 F src/pcache1.c c0aa84ff69ea759fa944dbee9167a2463ab7c322
F src/pragma.c 04c13c79fd559d769f5bcb3aa661b32d484b1e7b F src/pragma.c 04c13c79fd559d769f5bcb3aa661b32d484b1e7b
F src/prepare.c 9ec504ddd4a8e34e5fb502033312da6a78f5f76a F src/prepare.c 9ec504ddd4a8e34e5fb502033312da6a78f5f76a
@@ -158,13 +158,13 @@ F src/select.c ae72b604e47092521c4d9ae54e1b1cbeb872a747
F src/shell.c 0d801ef653fd73d17161afebaab898a58ec3524b F src/shell.c 0d801ef653fd73d17161afebaab898a58ec3524b
F src/sqlite.h.in 6cd2489e40fe97ba58c60044a4ced377e08b6d09 F src/sqlite.h.in 6cd2489e40fe97ba58c60044a4ced377e08b6d09
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
F src/sqliteInt.h 8ddded6a804d2055ae860e8f514c545a49840006 F src/sqliteInt.h 086886697368982dd7469689cd6e96c94d091008
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76 F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
F src/table.c 332ab0ea691e63862e2a8bdfe2c0617ee61062a3 F src/table.c 332ab0ea691e63862e2a8bdfe2c0617ee61062a3
F src/tclsqlite.c 7d77c3899d0244804d2773c9157e783788627762 F src/tclsqlite.c 7d77c3899d0244804d2773c9157e783788627762
F src/test1.c 58c0026d8764635efe8e7e7cea61e41faecef597 F src/test1.c 58c0026d8764635efe8e7e7cea61e41faecef597
F src/test2.c b0e977810ea3df8adaa2a2898ef4f6813875e840 F src/test2.c 9689e7d3b7791da8c03f9acd1ea801802cb83c17
F src/test3.c 88a246b56b824275300e6c899634fbac1dc94b14 F src/test3.c 88a246b56b824275300e6c899634fbac1dc94b14
F src/test4.c f79ab52d27ff49b784b631a42e2ccd52cfd5c84c F src/test4.c f79ab52d27ff49b784b631a42e2ccd52cfd5c84c
F src/test5.c 162a1cea2105a2c460a3f39fa6919617b562a288 F src/test5.c 162a1cea2105a2c460a3f39fa6919617b562a288
@@ -202,7 +202,7 @@ F src/vdbe.c e14b330e7b9b27dd9eb1595f47aedea30acfd521
F src/vdbe.h 03516f28bf5aca00a53c4dccd6c313f96adb94f6 F src/vdbe.h 03516f28bf5aca00a53c4dccd6c313f96adb94f6
F src/vdbeInt.h 5530e45fc64c1572f123aca384096e1b84cf834b F src/vdbeInt.h 5530e45fc64c1572f123aca384096e1b84cf834b
F src/vdbeapi.c 85c33cfbfa56249cbe627831610afafba754477d F src/vdbeapi.c 85c33cfbfa56249cbe627831610afafba754477d
F src/vdbeaux.c a5db2fe6da4a49848f123af681888ba4cee6e7b4 F src/vdbeaux.c 30c1bbc1d2876c5bbe84d52dab9980ed032bca98
F src/vdbeblob.c b0dcebfafedcf9c0addc7901ad98f6f986c08935 F src/vdbeblob.c b0dcebfafedcf9c0addc7901ad98f6f986c08935
F src/vdbemem.c 06311d5c46fd703fe95ff81bd0a1b72ba0341311 F src/vdbemem.c 06311d5c46fd703fe95ff81bd0a1b72ba0341311
F src/vtab.c e39e011d7443a8d574b1b9cde207a35522e6df43 F src/vtab.c e39e011d7443a8d574b1b9cde207a35522e6df43
@@ -697,7 +697,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
P 7035c35dbef72b7b4d00201a65734a6d93dd0d3e P 1041abd6784d283bebf646c54e93599522f7889d
R 290a11e6c2265b9e59ca104eb003d6fa R 4bde501bdb15fe167fc73edd2c133657
U danielk1977 U danielk1977
Z 3b48670f3dab91065d2f211cd03723d9 Z e2751323f1f34d69687246315d80831a

View File

@@ -1 +1 @@
1041abd6784d283bebf646c54e93599522f7889d 12f7346c13c180ed73d7a2e3b590be457360254a

View File

@@ -34,7 +34,7 @@
** start of a transaction, and is thus usually less than a few thousand, ** start of a transaction, and is thus usually less than a few thousand,
** but can be as large as 2 billion for a really big database. ** but can be as large as 2 billion for a really big database.
** **
** @(#) $Id: bitvec.c,v 1.12 2009/01/16 16:23:38 danielk1977 Exp $ ** @(#) $Id: bitvec.c,v 1.13 2009/01/20 17:06:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -275,6 +275,14 @@ void sqlite3BitvecDestroy(Bitvec *p){
sqlite3_free(p); sqlite3_free(p);
} }
/*
** Return the value of the iSize parameter specified when Bitvec *p
** was created.
*/
u32 sqlite3BitvecSize(Bitvec *p){
return p->iSize;
}
#ifndef SQLITE_OMIT_BUILTIN_TEST #ifndef SQLITE_OMIT_BUILTIN_TEST
/* /*
** Let V[] be an array of unsigned characters sufficient to hold ** Let V[] be an array of unsigned characters sufficient to hold

View File

@@ -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.560 2009/01/16 16:23:38 danielk1977 Exp $ ** $Id: btree.c,v 1.561 2009/01/20 17:06:27 danielk1977 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.
@@ -282,6 +282,80 @@ static void invalidateAllOverflowCache(BtShared *pBt){
#define invalidateAllOverflowCache(x) #define invalidateAllOverflowCache(x)
#endif #endif
/*
** Set bit pgno of the BtShared.pHasContent bitvec. This is called
** when a page that previously contained data becomes a free-list leaf
** page.
**
** The BtShared.pHasContent bitvec exists to work around an obscure
** bug caused by the interaction of two useful IO optimizations surrounding
** free-list leaf pages:
**
** 1) When all data is deleted from a page and the page becomes
** a free-list leaf page, the page is not written to the database
** (as free-list leaf pages contain no meaningful data). Sometimes
** such a page is not even journalled (as it will not be modified,
** why bother journalling it?).
**
** 2) When a free-list leaf page is reused, its content is not read
** from the database or written to the journal file (why should it
** be, if it is not at all meaningful?).
**
** By themselves, these optimizations work fine and provide a handy
** performance boost to bulk delete or insert operations. However, if
** a page is moved to the free-list and then reused within the same
** transaction, a problem comes up. If the page is not journalled when
** it is moved to the free-list and it is also not journalled when it
** is extracted from the free-list and reused, then the original data
** may be lost. In the event of a rollback, it may not be possible
** to restore the database to its original configuration.
**
** The solution is the BtShared.pHasContent bitvec. Whenever a page is
** moved to become a free-list leaf page, the corresponding bit is
** set in the bitvec. Whenever a leaf page is extracted from the free-list,
** optimization 2 above is ommitted if the corresponding bit is already
** set in BtShared.pHasContent. The contents of the bitvec are cleared
** at the end of every transaction.
*/
static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
int rc = SQLITE_OK;
if( !pBt->pHasContent ){
int nPage;
rc = sqlite3PagerPagecount(pBt->pPager, &nPage);
if( rc==SQLITE_OK ){
pBt->pHasContent = sqlite3BitvecCreate((u32)nPage);
if( !pBt->pHasContent ){
rc = SQLITE_NOMEM;
}
}
}
if( rc==SQLITE_OK && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){
rc = sqlite3BitvecSet(pBt->pHasContent, pgno);
}
return rc;
}
/*
** Query the BtShared.pHasContent vector.
**
** This function is called when a free-list leaf page is removed from the
** free-list for reuse. It returns false if it is safe to retrieve the
** page from the pager layer with the 'no-content' flag set. True otherwise.
*/
static int btreeGetHasContent(BtShared *pBt, Pgno pgno){
Bitvec *p = pBt->pHasContent;
return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno)));
}
/*
** Clear (destroy) the BtShared.pHasContent bitvec. This should be
** invoked at the conclusion of each write-transaction.
*/
static void btreeClearHasContent(BtShared *pBt){
sqlite3BitvecDestroy(pBt->pHasContent);
pBt->pHasContent = 0;
}
/* /*
** Save the current cursor position in the variables BtCursor.nKey ** Save the current cursor position in the variables BtCursor.nKey
** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
@@ -1100,6 +1174,21 @@ int sqlite3BtreeGetPage(
return SQLITE_OK; return SQLITE_OK;
} }
/*
** Retrieve a page from the pager cache. If the requested page is not
** already in the pager cache return NULL. Initialize the MemPage.pBt and
** MemPage.aData elements if needed.
*/
static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){
DbPage *pDbPage;
assert( sqlite3_mutex_held(pBt->mutex) );
pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
if( pDbPage ){
return btreePageFromDbPage(pDbPage, pgno, pBt);
}
return 0;
}
/* /*
** Return the size of the database file in pages. If there is any kind of ** Return the size of the database file in pages. If there is any kind of
** error, return ((unsigned int)-1). ** error, return ((unsigned int)-1).
@@ -1124,7 +1213,6 @@ static int getAndInitPage(
MemPage **ppPage /* Write the page pointer here */ MemPage **ppPage /* Write the page pointer here */
){ ){
int rc; int rc;
DbPage *pDbPage;
MemPage *pPage; MemPage *pPage;
assert( sqlite3_mutex_held(pBt->mutex) ); assert( sqlite3_mutex_held(pBt->mutex) );
@@ -1137,10 +1225,9 @@ static int getAndInitPage(
** pagerPagecount() to make sure pgno is within limits, which results ** pagerPagecount() to make sure pgno is within limits, which results
** in a measureable performance improvements. ** in a measureable performance improvements.
*/ */
pDbPage = sqlite3PagerLookup(pBt->pPager, pgno); *ppPage = pPage = btreePageLookup(pBt, pgno);
if( pDbPage ){ if( pPage ){
/* Page is already in cache */ /* Page is already in cache */
*ppPage = pPage = btreePageFromDbPage(pDbPage, pgno, pBt);
rc = SQLITE_OK; rc = SQLITE_OK;
}else{ }else{
/* Page not in cache. Acquire it. */ /* Page not in cache. Acquire it. */
@@ -2013,7 +2100,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
if( pBt->readOnly ){ if( pBt->readOnly ){
rc = SQLITE_READONLY; rc = SQLITE_READONLY;
}else{ }else{
rc = sqlite3PagerBegin(pBt->pPage1->pDbPage, wrflag>1); rc = sqlite3PagerBegin(pBt->pPager, wrflag>1);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = newDatabase(pBt); rc = newDatabase(pBt);
} }
@@ -2372,7 +2459,7 @@ int sqlite3BtreeIncrVacuum(Btree *p){
rc = SQLITE_DONE; rc = SQLITE_DONE;
}else{ }else{
invalidateAllOverflowCache(pBt); invalidateAllOverflowCache(pBt);
rc = incrVacuumStep(pBt, 0, sqlite3PagerImageSize(pBt->pPager)); rc = incrVacuumStep(pBt, 0, pagerPagecount(pBt));
} }
sqlite3BtreeLeave(p); sqlite3BtreeLeave(p);
return rc; return rc;
@@ -2540,6 +2627,7 @@ int sqlite3BtreeCommitPhaseTwo(Btree *p){
/* Set the handles current transaction state to TRANS_NONE and unlock /* Set the handles current transaction state to TRANS_NONE and unlock
** the pager if this call closed the only read or write transaction. ** the pager if this call closed the only read or write transaction.
*/ */
btreeClearHasContent(pBt);
p->inTrans = TRANS_NONE; p->inTrans = TRANS_NONE;
unlockBtreeIfUnused(pBt); unlockBtreeIfUnused(pBt);
@@ -2675,6 +2763,7 @@ int sqlite3BtreeRollback(Btree *p){
} }
} }
btreeClearHasContent(pBt);
p->inTrans = TRANS_NONE; p->inTrans = TRANS_NONE;
pBt->inStmt = 0; pBt->inStmt = 0;
unlockBtreeIfUnused(pBt); unlockBtreeIfUnused(pBt);
@@ -3082,34 +3171,29 @@ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
** **
** If an error occurs an SQLite error code is returned. Otherwise: ** If an error occurs an SQLite error code is returned. Otherwise:
** **
** Unless pPgnoNext is NULL, the page number of the next overflow ** The page number of the next overflow page in the linked list is
** page in the linked list is written to *pPgnoNext. If page ovfl ** written to *pPgnoNext. If page ovfl is the last page in its linked
** is the last page in its linked list, *pPgnoNext is set to zero. ** list, *pPgnoNext is set to zero.
** **
** If ppPage is not NULL, *ppPage is set to the MemPage* handle ** If ppPage is not NULL, and a reference to the MemPage object corresponding
** for page ovfl. The underlying pager page may have been requested ** to page number pOvfl was obtained, then *ppPage is set to point to that
** with the noContent flag set, so the page data accessable via ** reference. It is the responsibility of the caller to call releasePage()
** this handle may not be trusted. ** on *ppPage to free the reference. In no reference was obtained (because
** the pointer-map was used to obtain the value for *pPgnoNext), then
** *ppPage is set to zero.
*/ */
static int getOverflowPage( static int getOverflowPage(
BtShared *pBt, BtShared *pBt,
Pgno ovfl, /* Overflow page */ Pgno ovfl, /* Overflow page */
MemPage **ppPage, /* OUT: MemPage handle */ MemPage **ppPage, /* OUT: MemPage handle (may be NULL) */
Pgno *pPgnoNext /* OUT: Next overflow page number */ Pgno *pPgnoNext /* OUT: Next overflow page number */
){ ){
Pgno next = 0; Pgno next = 0;
MemPage *pPage = 0;
int rc = SQLITE_OK; int rc = SQLITE_OK;
assert( sqlite3_mutex_held(pBt->mutex) ); assert( sqlite3_mutex_held(pBt->mutex) );
/* One of these must not be NULL. Otherwise, why call this function? */ assert(pPgnoNext);
assert(ppPage || pPgnoNext);
/* If pPgnoNext is NULL, then this function is being called to obtain
** a MemPage* reference only. No page-data is required in this case.
*/
if( !pPgnoNext ){
return sqlite3BtreeGetPage(pBt, ovfl, ppPage, 1);
}
#ifndef SQLITE_OMIT_AUTOVACUUM #ifndef SQLITE_OMIT_AUTOVACUUM
/* Try to find the next page in the overflow list using the /* Try to find the next page in the overflow list using the
@@ -3129,34 +3213,29 @@ static int getOverflowPage(
if( iGuess<=pagerPagecount(pBt) ){ if( iGuess<=pagerPagecount(pBt) ){
rc = ptrmapGet(pBt, iGuess, &eType, &pgno); rc = ptrmapGet(pBt, iGuess, &eType, &pgno);
if( rc!=SQLITE_OK ){ if( rc==SQLITE_OK && eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){
return rc;
}
if( eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){
next = iGuess; next = iGuess;
rc = SQLITE_DONE;
} }
} }
} }
#endif #endif
if( next==0 || ppPage ){ if( rc==SQLITE_OK ){
MemPage *pPage = 0; rc = sqlite3BtreeGetPage(pBt, ovfl, &pPage, 0);
rc = sqlite3BtreeGetPage(pBt, ovfl, &pPage, next!=0);
assert(rc==SQLITE_OK || pPage==0); assert(rc==SQLITE_OK || pPage==0);
if( next==0 && rc==SQLITE_OK ){ if( next==0 && rc==SQLITE_OK ){
next = get4byte(pPage->aData); next = get4byte(pPage->aData);
} }
if( ppPage ){
*ppPage = pPage;
}else{
releasePage(pPage);
}
} }
*pPgnoNext = next;
return rc; *pPgnoNext = next;
if( ppPage ){
*ppPage = pPage;
}else{
releasePage(pPage);
}
return (rc==SQLITE_DONE ? SQLITE_OK : rc);
} }
/* /*
@@ -4265,6 +4344,7 @@ static int allocateBtreePage(
iPage = get4byte(&aData[8+closest*4]); iPage = get4byte(&aData[8+closest*4]);
if( !searchList || iPage==nearby ){ if( !searchList || iPage==nearby ){
int noContent;
Pgno nPage; Pgno nPage;
*pPgno = iPage; *pPgno = iPage;
nPage = pagerPagecount(pBt); nPage = pagerPagecount(pBt);
@@ -4281,9 +4361,9 @@ static int allocateBtreePage(
} }
put4byte(&aData[4], k-1); put4byte(&aData[4], k-1);
assert( sqlite3PagerIswriteable(pTrunk->pDbPage) ); assert( sqlite3PagerIswriteable(pTrunk->pDbPage) );
rc = sqlite3BtreeGetPage(pBt, *pPgno, ppPage, 1); noContent = !btreeGetHasContent(pBt, *pPgno);
rc = sqlite3BtreeGetPage(pBt, *pPgno, ppPage, noContent);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
sqlite3PagerDontRollback((*ppPage)->pDbPage);
rc = sqlite3PagerWrite((*ppPage)->pDbPage); rc = sqlite3PagerWrite((*ppPage)->pDbPage);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
releasePage(*ppPage); releasePage(*ppPage);
@@ -4301,6 +4381,10 @@ static int allocateBtreePage(
int nPage = pagerPagecount(pBt); int nPage = pagerPagecount(pBt);
*pPgno = nPage + 1; *pPgno = nPage + 1;
if( *pPgno==PENDING_BYTE_PAGE(pBt) ){
(*pPgno)++;
}
#ifndef SQLITE_OMIT_AUTOVACUUM #ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, *pPgno) ){ if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, *pPgno) ){
/* If *pPgno refers to a pointer-map page, allocate two new pages /* If *pPgno refers to a pointer-map page, allocate two new pages
@@ -4340,32 +4424,51 @@ end_allocate_page:
} }
/* /*
** Add a page of the database file to the freelist. ** This function is used to add page iPage to the database file free-list.
** It is assumed that the page is not already a part of the free-list.
** **
** sqlite3PagerUnref() is NOT called for pPage. ** The value passed as the second argument to this function is optional.
** If the caller happens to have a pointer to the MemPage object
** corresponding to page iPage handy, it may pass it as the second value.
** Otherwise, it may pass NULL.
**
** If a pointer to a MemPage object is passed as the second argument,
** its reference count is not altered by this function.
*/ */
static int freePage(MemPage *pPage){ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
BtShared *pBt = pPage->pBt; MemPage *pTrunk = 0; /* Free-list trunk page */
MemPage *pPage1 = pBt->pPage1; Pgno iTrunk = 0; /* Page number of free-list trunk page */
int rc, n, k; MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */
MemPage *pPage; /* Page being freed. May be NULL. */
int rc; /* Return Code */
int nFree; /* Initial number of pages on free-list */
/* Prepare the page for freeing */ assert( sqlite3_mutex_held(pBt->mutex) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( iPage>1 );
assert( pPage->pgno>1 ); assert( !pMemPage || pMemPage->pgno==iPage );
pPage->isInit = 0;
if( pMemPage ){
pPage = pMemPage;
sqlite3PagerRef(pPage->pDbPage);
}else{
pPage = btreePageLookup(pBt, iPage);
}
/* Increment the free page count on pPage1 */ /* Increment the free page count on pPage1 */
rc = sqlite3PagerWrite(pPage1->pDbPage); rc = sqlite3PagerWrite(pPage1->pDbPage);
if( rc ) return rc; if( rc ) goto freepage_out;
n = get4byte(&pPage1->aData[36]); nFree = get4byte(&pPage1->aData[36]);
put4byte(&pPage1->aData[36], n+1); put4byte(&pPage1->aData[36], nFree+1);
#ifdef SQLITE_SECURE_DELETE #ifdef SQLITE_SECURE_DELETE
/* If the SQLITE_SECURE_DELETE compile-time option is enabled, then /* If the SQLITE_SECURE_DELETE compile-time option is enabled, then
** always fully overwrite deleted information with zeros. ** always fully overwrite deleted information with zeros.
*/ */
rc = sqlite3PagerWrite(pPage->pDbPage); if( (!pPage && (rc = sqlite3BtreeGetPage(pBt, iPage, &pPage, 0)))
if( rc ) return rc; || (rc = sqlite3PagerWrite(pPage->pDbPage))
){
goto freepage_out;
}
memset(pPage->aData, 0, pPage->pBt->pageSize); memset(pPage->aData, 0, pPage->pBt->pageSize);
#endif #endif
@@ -4373,27 +4476,34 @@ static int freePage(MemPage *pPage){
** to indicate that the page is free. ** to indicate that the page is free.
*/ */
if( ISAUTOVACUUM ){ if( ISAUTOVACUUM ){
rc = ptrmapPut(pBt, pPage->pgno, PTRMAP_FREEPAGE, 0); rc = ptrmapPut(pBt, iPage, PTRMAP_FREEPAGE, 0);
if( rc ) return rc; if( rc ) goto freepage_out;
} }
if( n==0 ){ /* Now manipulate the actual database free-list structure. There are two
/* This is the first free page */ ** possibilities. If the free-list is currently empty, or if the first
rc = sqlite3PagerWrite(pPage->pDbPage); ** trunk page in the free-list is full, then this page will become a
if( rc ) return rc; ** new free-list trunk page. Otherwise, it will become a leaf of the
memset(pPage->aData, 0, 8); ** first trunk page in the current free-list. This block tests if it
put4byte(&pPage1->aData[32], pPage->pgno); ** is possible to add the page as a new free-list leaf.
TRACE(("FREE-PAGE: %d first\n", pPage->pgno)); */
}else{ if( nFree!=0 ){
/* Other free pages already exist. Retrive the first trunk page int nLeaf; /* Initial number of leaf cells on trunk page */
** of the freelist and find out how many leaves it has. */
MemPage *pTrunk; iTrunk = get4byte(&pPage1->aData[32]);
rc = sqlite3BtreeGetPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk, 0); rc = sqlite3BtreeGetPage(pBt, iTrunk, &pTrunk, 0);
if( rc ) return rc; if( rc!=SQLITE_OK ){
k = get4byte(&pTrunk->aData[4]); goto freepage_out;
if( k>=pBt->usableSize/4 - 8 ){ }
/* The trunk is full. Turn the page being freed into a new
** trunk page with no leaves. nLeaf = get4byte(&pTrunk->aData[4]);
if( nLeaf<0 ){
rc = SQLITE_CORRUPT_BKPT;
goto freepage_out;
}
if( nLeaf<pBt->usableSize/4 - 8 ){
/* In this case there is room on the trunk page to insert the page
** being freed as a new leaf.
** **
** Note that the trunk page is not really full until it contains ** Note that the trunk page is not really full until it contains
** usableSize/4 - 2 entries, not usableSize/4 - 8 entries as we have ** usableSize/4 - 2 entries, not usableSize/4 - 8 entries as we have
@@ -4406,32 +4516,49 @@ static int freePage(MemPage *pPage){
** to 3.6.0 or later) we should consider fixing the conditional above ** to 3.6.0 or later) we should consider fixing the conditional above
** to read "usableSize/4-2" instead of "usableSize/4-8". ** to read "usableSize/4-2" instead of "usableSize/4-8".
*/ */
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc==SQLITE_OK ){
put4byte(pPage->aData, pTrunk->pgno);
put4byte(&pPage->aData[4], 0);
put4byte(&pPage1->aData[32], pPage->pgno);
TRACE(("FREE-PAGE: %d new trunk page replacing %d\n",
pPage->pgno, pTrunk->pgno));
}
}else if( k<0 ){
rc = SQLITE_CORRUPT;
}else{
/* Add the newly freed page as a leaf on the current trunk */
rc = sqlite3PagerWrite(pTrunk->pDbPage); rc = sqlite3PagerWrite(pTrunk->pDbPage);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
put4byte(&pTrunk->aData[4], k+1); put4byte(&pTrunk->aData[4], nLeaf+1);
put4byte(&pTrunk->aData[8+k*4], pPage->pgno); put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
#ifndef SQLITE_SECURE_DELETE #ifndef SQLITE_SECURE_DELETE
rc = sqlite3PagerDontWrite(pPage->pDbPage); if( pPage ){
sqlite3PagerDontWrite(pPage->pDbPage);
}
#endif #endif
rc = btreeSetHasContent(pBt, iPage);
} }
TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno));
goto freepage_out;
} }
releasePage(pTrunk);
} }
/* If control flows to this point, then it was not possible to add the
** the page being freed as a leaf page of the first trunk in the free-list.
** Possibly because the free-list is empty, or possibly because the
** first trunk in the free-list is full. Either way, the page being freed
** will become the new first trunk page in the free-list.
*/
if( (!pPage && (rc = sqlite3BtreeGetPage(pBt, iPage, &pPage, 0)))
|| (rc = sqlite3PagerWrite(pPage->pDbPage))
){
goto freepage_out;
}
put4byte(pPage->aData, iTrunk);
put4byte(&pPage->aData[4], 0);
put4byte(&pPage1->aData[32], iPage);
TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, iTrunk));
freepage_out:
if( pPage ){
pPage->isInit = 0;
}
releasePage(pPage);
releasePage(pTrunk);
return rc; return rc;
} }
static int freePage(MemPage *pPage){
return freePage2(pPage->pBt, pPage, pPage->pgno);
}
/* /*
** Free any overflow pages associated with the given Cell. ** Free any overflow pages associated with the given Cell.
@@ -4454,16 +4581,21 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
assert( ovflPgno==0 || nOvfl>0 ); assert( ovflPgno==0 || nOvfl>0 );
while( nOvfl-- ){ while( nOvfl-- ){
MemPage *pOvfl; Pgno iNext;
MemPage *pOvfl = 0;
if( ovflPgno==0 || ovflPgno>pagerPagecount(pBt) ){ if( ovflPgno==0 || ovflPgno>pagerPagecount(pBt) ){
return SQLITE_CORRUPT_BKPT; return SQLITE_CORRUPT_BKPT;
} }
if( nOvfl ){
rc = getOverflowPage(pBt, ovflPgno, &pOvfl, (nOvfl==0)?0:&ovflPgno); rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext);
if( rc ) return rc; if( rc ) return rc;
rc = freePage(pOvfl); }
sqlite3PagerUnref(pOvfl->pDbPage); rc = freePage2(pBt, pOvfl, ovflPgno);
if( pOvfl ){
sqlite3PagerUnref(pOvfl->pDbPage);
}
if( rc ) return rc; if( rc ) return rc;
ovflPgno = iNext;
} }
return SQLITE_OK; return SQLITE_OK;
} }
@@ -6229,11 +6361,6 @@ static int btreeCreateTable(Btree *p, int *piTable, int flags){
} }
assert( eType!=PTRMAP_ROOTPAGE ); assert( eType!=PTRMAP_ROOTPAGE );
assert( eType!=PTRMAP_FREEPAGE ); assert( eType!=PTRMAP_FREEPAGE );
rc = sqlite3PagerWrite(pRoot->pDbPage);
if( rc!=SQLITE_OK ){
releasePage(pRoot);
return rc;
}
rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0); rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0);
releasePage(pRoot); releasePage(pRoot);
@@ -7094,17 +7221,6 @@ const char *sqlite3BtreeGetFilename(Btree *p){
return sqlite3PagerFilename(p->pBt->pPager); return sqlite3PagerFilename(p->pBt->pPager);
} }
/*
** Return the pathname of the directory that contains the database file.
**
** The pager directory name is invariant as long as the pager is
** open so it is safe to access without the BtShared mutex.
*/
const char *sqlite3BtreeGetDirname(Btree *p){
assert( p->pBt->pPager!=0 );
return sqlite3PagerDirname(p->pBt->pPager);
}
/* /*
** Return the pathname of the journal file for this database. The return ** Return the pathname of the journal file for this database. The return
** value of this routine is the same regardless of whether the journal file ** value of this routine is the same regardless of whether the journal file
@@ -7190,7 +7306,7 @@ static int btreeCopyFile(Btree *pTo, Btree *pFrom){
** page is still on the rollback journal, though. And that is the ** page is still on the rollback journal, though. And that is the
** whole point of this block: to put pages on the rollback journal. ** whole point of this block: to put pages on the rollback journal.
*/ */
rc = sqlite3PagerDontWrite(pDbPage); sqlite3PagerDontWrite(pDbPage);
} }
sqlite3PagerUnref(pDbPage); sqlite3PagerUnref(pDbPage);
} }

View File

@@ -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.40 2009/01/16 16:23:38 danielk1977 Exp $ ** $Id: btreeInt.h,v 1.41 2009/01/20 17:06:27 danielk1977 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
@@ -204,10 +204,6 @@
** * zero or more pages numbers of leaves ** * zero or more pages numbers of leaves
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "pager.h"
#include "btree.h"
#include "os.h"
#include <assert.h>
/* Round up a number to the next larger multiple of 8. This is used /* Round up a number to the next larger multiple of 8. This is used
** to force 8-byte alignment on 64-bit architectures. ** to force 8-byte alignment on 64-bit architectures.
@@ -383,6 +379,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 */
sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */ sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */
Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */
#ifndef SQLITE_OMIT_SHARED_CACHE #ifndef SQLITE_OMIT_SHARED_CACHE
int nRef; /* Number of references to this structure */ int nRef; /* Number of references to this structure */
BtShared *pNext; /* Next on a list of sharable BtShared structs */ BtShared *pNext; /* Next on a list of sharable BtShared structs */
@@ -490,18 +487,10 @@ struct BtCursor {
#define CURSOR_REQUIRESEEK 2 #define CURSOR_REQUIRESEEK 2
#define CURSOR_FAULT 3 #define CURSOR_FAULT 3
/* The database page the PENDING_BYTE occupies. This page is never used. /*
** TODO: This macro is very similary to PAGER_MJ_PGNO() in pager.c. They ** The database page the PENDING_BYTE occupies. This page is never used.
** should possibly be consolidated (presumably in pager.h).
**
** If disk I/O is omitted (meaning that the database is stored purely
** in memory) then there is no pending byte.
*/ */
#ifdef SQLITE_OMIT_DISKIO # define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)
# define PENDING_BYTE_PAGE(pBt) 0x7fffffff
#else
# define PENDING_BYTE_PAGE(pBt) ((Pgno)((PENDING_BYTE/(pBt)->pageSize)+1))
#endif
/* /*
** A linked list of the following structures is stored at BtShared.pLock. ** A linked list of the following structures is stored at BtShared.pLock.

View File

@@ -10,7 +10,7 @@
** **
************************************************************************* *************************************************************************
** **
** @(#) $Id: journal.c,v 1.8 2008/05/01 18:01:47 drh Exp $ ** @(#) $Id: journal.c,v 1.9 2009/01/20 17:06:27 danielk1977 Exp $
*/ */
#ifdef SQLITE_ENABLE_ATOMIC_WRITE #ifdef SQLITE_ENABLE_ATOMIC_WRITE
@@ -28,7 +28,7 @@
** **
** 1) The in-memory representation grows too large for the allocated ** 1) The in-memory representation grows too large for the allocated
** buffer, or ** buffer, or
** 2) The xSync() method is called. ** 2) The sqlite3JournalCreate() function is called.
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -95,8 +95,9 @@ static int jrnlRead(
JournalFile *p = (JournalFile *)pJfd; JournalFile *p = (JournalFile *)pJfd;
if( p->pReal ){ if( p->pReal ){
rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
}else if( (iAmt+iOfst)>p->iSize ){
rc = SQLITE_IOERR_SHORT_READ;
}else{ }else{
assert( iAmt+iOfst<=p->iSize );
memcpy(zBuf, &p->zBuf[iOfst], iAmt); memcpy(zBuf, &p->zBuf[iOfst], iAmt);
} }
return rc; return rc;

File diff suppressed because it is too large Load Diff

View File

@@ -13,15 +13,16 @@
** subsystem. The page cache subsystem reads and writes a file a page ** subsystem. The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback. ** at a time and provides a journal for rollback.
** **
** @(#) $Id: pager.h,v 1.95 2009/01/16 16:23:38 danielk1977 Exp $ ** @(#) $Id: pager.h,v 1.96 2009/01/20 17:06:27 danielk1977 Exp $
*/ */
#ifndef _PAGER_H_ #ifndef _PAGER_H_
#define _PAGER_H_ #define _PAGER_H_
/* /*
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise ** Default maximum size for persistent journal files. A negative
** it must be turned on for each database using "PRAGMA auto_vacuum = 1". ** value means no limit. This value may be overridden using the
** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit".
*/ */
#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT #ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
#define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1 #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1
@@ -43,10 +44,20 @@ typedef struct Pager Pager;
*/ */
typedef struct PgHdr DbPage; typedef struct PgHdr DbPage;
/*
** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
** reserved for working around a windows/posix incompatibility). It is
** used in the journal to signify that the remainder of the journal file
** is devoted to storing a master journal name - there are no more pages to
** roll back. See comments for function writeMasterJournal() in pager.c
** for details.
*/
#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
/* /*
** Allowed values for the flags parameter to sqlite3PagerOpen(). ** Allowed values for the flags parameter to sqlite3PagerOpen().
** **
** NOTE: This values must match the corresponding BTREE_ values in btree.h. ** NOTE: These values must match the corresponding BTREE_ values in btree.h.
*/ */
#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ #define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */ #define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
@@ -69,75 +80,84 @@ typedef struct PgHdr DbPage;
#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */ #define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
/* /*
** See source code comments for a detailed description of the following ** The remainder of this file contains the declarations of the functions
** routines: ** that make up the Pager sub-system API. See source code comments for
** a detailed description of each routine.
*/ */
/* Open and close a Pager connection. */
int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int); int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int);
int sqlite3PagerClose(Pager *pPager);
/* Functions used to configure a Pager object. */
void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*)); void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*));
int sqlite3PagerSetPagesize(Pager*, u16*); int sqlite3PagerSetPagesize(Pager*, u16*);
int sqlite3PagerMaxPageCount(Pager*, int); int sqlite3PagerMaxPageCount(Pager*, int);
int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
void sqlite3PagerSetCachesize(Pager*, int); void sqlite3PagerSetCachesize(Pager*, int);
int sqlite3PagerClose(Pager *pPager); void sqlite3PagerSetSafetyLevel(Pager*,int,int);
int sqlite3PagerLockingMode(Pager *, int);
int sqlite3PagerJournalMode(Pager *, int);
i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
/* Functions used to obtain and release page references. */
int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) #define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0)
DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
int sqlite3PagerPageRefcount(DbPage*); void sqlite3PagerRef(DbPage*);
int sqlite3PagerRef(DbPage*); void sqlite3PagerUnref(DbPage*);
int sqlite3PagerUnref(DbPage*);
/* Operations on page references. */
int sqlite3PagerWrite(DbPage*); int sqlite3PagerWrite(DbPage*);
void sqlite3PagerDontWrite(DbPage*);
int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int);
int sqlite3PagerPageRefcount(DbPage*);
void *sqlite3PagerGetData(DbPage *);
void *sqlite3PagerGetExtra(DbPage *);
/* Functions used to manage pager transactions and savepoints. */
int sqlite3PagerPagecount(Pager*, int*); int sqlite3PagerPagecount(Pager*, int*);
int sqlite3PagerBegin(DbPage*, int exFlag); int sqlite3PagerBegin(Pager*, int exFlag);
int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int); int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
int sqlite3PagerSync(Pager *pPager);
int sqlite3PagerCommitPhaseTwo(Pager*); int sqlite3PagerCommitPhaseTwo(Pager*);
int sqlite3PagerRollback(Pager*); int sqlite3PagerRollback(Pager*);
int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
/* Functions used to query pager state and configuration. */
u8 sqlite3PagerIsreadonly(Pager*); u8 sqlite3PagerIsreadonly(Pager*);
void sqlite3PagerDontRollback(DbPage*);
int sqlite3PagerDontWrite(DbPage*);
int sqlite3PagerRefcount(Pager*); int sqlite3PagerRefcount(Pager*);
void sqlite3PagerSetSafetyLevel(Pager*,int,int);
const char *sqlite3PagerFilename(Pager*); const char *sqlite3PagerFilename(Pager*);
const sqlite3_vfs *sqlite3PagerVfs(Pager*); const sqlite3_vfs *sqlite3PagerVfs(Pager*);
sqlite3_file *sqlite3PagerFile(Pager*); sqlite3_file *sqlite3PagerFile(Pager*);
const char *sqlite3PagerDirname(Pager*); const char *sqlite3PagerDirname(Pager*);
const char *sqlite3PagerJournalname(Pager*); const char *sqlite3PagerJournalname(Pager*);
int sqlite3PagerNosync(Pager*); int sqlite3PagerNosync(Pager*);
int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int);
void *sqlite3PagerGetData(DbPage *);
void *sqlite3PagerGetExtra(DbPage *);
int sqlite3PagerLockingMode(Pager *, int);
int sqlite3PagerJournalMode(Pager *, int);
i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
void *sqlite3PagerTempSpace(Pager*); void *sqlite3PagerTempSpace(Pager*);
int sqlite3PagerSync(Pager *pPager);
int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
/* Functions used in auto-vacuum mode to truncate the database file. */
#ifndef SQLITE_OMIT_AUTOVACUUM #ifndef SQLITE_OMIT_AUTOVACUUM
void sqlite3PagerTruncateImage(Pager*,Pgno); void sqlite3PagerTruncateImage(Pager*,Pgno);
Pgno sqlite3PagerImageSize(Pager *);
#endif #endif
/* Used by encryption extensions. */
#ifdef SQLITE_HAS_CODEC #ifdef SQLITE_HAS_CODEC
void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*); void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
#endif #endif
/* Functions to support testing and debugging. */
#if !defined(NDEBUG) || defined(SQLITE_TEST) #if !defined(NDEBUG) || defined(SQLITE_TEST)
Pgno sqlite3PagerPagenumber(DbPage*); Pgno sqlite3PagerPagenumber(DbPage*);
int sqlite3PagerIswriteable(DbPage*); int sqlite3PagerIswriteable(DbPage*);
#endif #endif
#ifdef SQLITE_TEST #ifdef SQLITE_TEST
int *sqlite3PagerStats(Pager*); int *sqlite3PagerStats(Pager*);
void sqlite3PagerRefdump(Pager*); void sqlite3PagerRefdump(Pager*);
int sqlite3PagerIsMemdb(Pager*); int sqlite3PagerIsMemdb(Pager*);
#endif void disable_simulated_io_errors(void);
void enable_simulated_io_errors(void);
#ifdef SQLITE_TEST
void disable_simulated_io_errors(void);
void enable_simulated_io_errors(void);
#else #else
# define disable_simulated_io_errors() # define disable_simulated_io_errors()
# define enable_simulated_io_errors() # define enable_simulated_io_errors()

View File

@@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** This file implements that page cache. ** This file implements that page cache.
** **
** @(#) $Id: pcache.c,v 1.41 2009/01/16 16:23:38 danielk1977 Exp $ ** @(#) $Id: pcache.c,v 1.42 2009/01/20 17:06:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -23,14 +23,13 @@ struct PCache {
PgHdr *pSynced; /* Last synced page in dirty page list */ PgHdr *pSynced; /* Last synced page in dirty page list */
int nRef; /* Number of referenced pages */ int nRef; /* Number of referenced pages */
int nMax; /* Configured cache size */ int nMax; /* Configured cache size */
int nMin; /* Configured minimum cache size */
int szPage; /* Size of every page in this cache */ int szPage; /* Size of every page in this cache */
int szExtra; /* Size of extra space for each page */ int szExtra; /* Size of extra space for each page */
int bPurgeable; /* True if pages are on backing store */ int bPurgeable; /* True if pages are on backing store */
int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */ int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
void *pStress; /* Argument to xStress */ void *pStress; /* Argument to xStress */
sqlite3_pcache *pCache; /* Pluggable cache module */ sqlite3_pcache *pCache; /* Pluggable cache module */
PgHdr *pPage1; PgHdr *pPage1; /* Reference to page 1 */
}; };
/* /*
@@ -181,7 +180,6 @@ void sqlite3PcacheOpen(
p->xStress = xStress; p->xStress = xStress;
p->pStress = pStress; p->pStress = pStress;
p->nMax = 100; p->nMax = 100;
p->nMin = 10;
} }
/* /*
@@ -431,9 +429,8 @@ void sqlite3PcacheClose(PCache *pCache){
/* /*
** Discard the contents of the cache. ** Discard the contents of the cache.
*/ */
int sqlite3PcacheClear(PCache *pCache){ void sqlite3PcacheClear(PCache *pCache){
sqlite3PcacheTruncate(pCache, 0); sqlite3PcacheTruncate(pCache, 0);
return SQLITE_OK;
} }
/* /*

View File

@@ -12,7 +12,7 @@
** This header file defines the interface that the sqlite page cache ** This header file defines the interface that the sqlite page cache
** subsystem. ** subsystem.
** **
** @(#) $Id: pcache.h,v 1.18 2009/01/16 16:23:38 danielk1977 Exp $ ** @(#) $Id: pcache.h,v 1.19 2009/01/20 17:06:27 danielk1977 Exp $
*/ */
#ifndef _PCACHE_H_ #ifndef _PCACHE_H_
@@ -111,7 +111,7 @@ void sqlite3PcacheClose(PCache*);
void sqlite3PcacheClearSyncFlags(PCache *); void sqlite3PcacheClearSyncFlags(PCache *);
/* Discard the contents of the cache */ /* Discard the contents of the cache */
int sqlite3PcacheClear(PCache*); void sqlite3PcacheClear(PCache*);
/* Return the total number of outstanding page references */ /* Return the total number of outstanding page references */
int sqlite3PcacheRefCount(PCache*); int sqlite3PcacheRefCount(PCache*);

View File

@@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.828 2009/01/20 16:53:41 danielk1977 Exp $ ** @(#) $Id: sqliteInt.h,v 1.829 2009/01/20 17:06:27 danielk1977 Exp $
*/ */
#ifndef _SQLITEINT_H_ #ifndef _SQLITEINT_H_
#define _SQLITEINT_H_ #define _SQLITEINT_H_
@@ -2277,6 +2277,7 @@ int sqlite3BitvecTest(Bitvec*, u32);
int sqlite3BitvecSet(Bitvec*, u32); int sqlite3BitvecSet(Bitvec*, u32);
void sqlite3BitvecClear(Bitvec*, u32); void sqlite3BitvecClear(Bitvec*, u32);
void sqlite3BitvecDestroy(Bitvec*); void sqlite3BitvecDestroy(Bitvec*);
u32 sqlite3BitvecSize(Bitvec*);
int sqlite3BitvecBuiltinTest(int,int*); int sqlite3BitvecBuiltinTest(int,int*);
RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int); RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);

View File

@@ -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: test2.c,v 1.68 2009/01/20 16:53:41 danielk1977 Exp $ ** $Id: test2.c,v 1.69 2009/01/20 17:06:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "tcl.h" #include "tcl.h"
@@ -418,18 +418,13 @@ static int page_unref(
const char **argv /* Text of each argument */ const char **argv /* Text of each argument */
){ ){
DbPage *pPage; DbPage *pPage;
int rc;
if( argc!=2 ){ if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" PAGE\"", 0); " PAGE\"", 0);
return TCL_ERROR; return TCL_ERROR;
} }
pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]);
rc = sqlite3PagerUnref(pPage); sqlite3PagerUnref(pPage);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
}
return TCL_OK; return TCL_OK;
} }

View File

@@ -14,7 +14,7 @@
** to version 2.8.7, all this code was combined into the vdbe.c source file. ** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out. ** But that file was getting too big so this subroutines were split out.
** **
** $Id: vdbeaux.c,v 1.433 2009/01/20 16:53:41 danielk1977 Exp $ ** $Id: vdbeaux.c,v 1.434 2009/01/20 17:06:27 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "vdbeInt.h" #include "vdbeInt.h"
@@ -1387,10 +1387,10 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
/* Sync the master journal file. If the IOCAP_SEQUENTIAL device /* Sync the master journal file. If the IOCAP_SEQUENTIAL device
** flag is set this is not required. ** flag is set this is not required.
*/ */
zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt); if( needSync
if( (needSync && 0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)
&& (0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL)) && SQLITE_OK!=(rc = sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))
&& (rc=sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))!=SQLITE_OK) ){ ){
sqlite3OsCloseFree(pMaster); sqlite3OsCloseFree(pMaster);
sqlite3OsDelete(pVfs, zMaster, 0); sqlite3OsDelete(pVfs, zMaster, 0);
sqlite3DbFree(db, zMaster); sqlite3DbFree(db, zMaster);