mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Avoid parsing the structure of b-tree pages (in sqlite3BtreeInitPage) more than is necessary. (CVS 5720)
FossilOrigin-Name: 6b998f3066754e219c266501327e5578c9406b63
This commit is contained in:
24
manifest
24
manifest
@@ -1,5 +1,5 @@
|
||||
C Update\sthe\sversion\snumber\sto\s3.6.3.\s(CVS\s5719)
|
||||
D 2008-09-18T13:49:13
|
||||
C Avoid\sparsing\sthe\sstructure\sof\sb-tree\spages\s(in\ssqlite3BtreeInitPage)\smore\sthan\sis\snecessary.\s(CVS\s5720)
|
||||
D 2008-09-18T17:34:44
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in d15a7ebfe5e057a72a49805ffb302dbb601c8329
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@@ -99,9 +99,9 @@ F src/attach.c db3f4a60538733c1e4dcb9d0217a6e0d6ccd615b
|
||||
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
|
||||
F src/bitvec.c 95c86bd18d8fedf0533f5af196192546e10a7e7d
|
||||
F src/btmutex.c 709cad2cdca0afd013f0f612363810e53f59ec53
|
||||
F src/btree.c 5db7b54e9d39dddb06e066e993901fc8630c6e49
|
||||
F src/btree.c e8484887722a3a84f2aab5663a0dc93e0c7806c7
|
||||
F src/btree.h 6371c5e599fab391a150c96afbc10062b276d107
|
||||
F src/btreeInt.h ab18c7b4980314e9e4b402e5dcde09f3c2545576
|
||||
F src/btreeInt.h e36f77e6621d671beb19ae581af1eba116cdfdc4
|
||||
F src/build.c 160c71acca8f643f436ed6c1ee2f684c88df4dfe
|
||||
F src/callback.c 7a40fd44da3eb89e7f6eff30aa6f940c45d73a97
|
||||
F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
|
||||
@@ -137,11 +137,11 @@ F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60
|
||||
F src/os_os2.c e391fc95adc744bbdcefd4d11e3066998185a0a0
|
||||
F src/os_unix.c 8f4def6a92681735908fa1b87b5cc0291ebafde6
|
||||
F src/os_win.c 3209dc0ed734291764393ea8d534ba0d8696a540
|
||||
F src/pager.c 34318b85cead25e179a6ff83092c79d6dcecb2fd
|
||||
F src/pager.h c45380ca9d0933ea5bc4ecb3a43958b6d2ec5a9c
|
||||
F src/pager.c bcfa1c4034414a247c1583fd97c9c561afae53f9
|
||||
F src/pager.h 1ef5a3f8e0b4c8b30f19c8e01d4fca2db9bb5797
|
||||
F src/parse.y d0f76d2cb8d6883d5600dc20beb961a6022b94b8
|
||||
F src/pcache.c c799d753a5d4b913961a4fe66c8a7c706b04d28d
|
||||
F src/pcache.h deddea69babf3e0931b11eea3bf5c9e33a654389
|
||||
F src/pcache.c e025e5380d75ffc25ef069fee8d128b595513ece
|
||||
F src/pcache.h 0b6871e820159629915e8688b5c67a81a203773f
|
||||
F src/pragma.c e633b6b7dabc110e2abfed4e35ba34a4039cb65c
|
||||
F src/prepare.c c7e00ed1b0bdcf699b1aad651247d4dc3d281b0b
|
||||
F src/printf.c 785f87120589c1db672e37c6eb1087c456e6f84d
|
||||
@@ -637,7 +637,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
P 0889b22a2949160c3f2d06beaa05a867b4c228b3
|
||||
R ac300755102001ce1aa8c09d26102ac6
|
||||
U drh
|
||||
Z c0568459c1b6c869285e59f30eb43c51
|
||||
P 419764b35c96a1b08aefc0d6093c19fdf2aef517
|
||||
R abfec31e169b70fffcf581f021d6269e
|
||||
U danielk1977
|
||||
Z fbad4f393b6c492a76554e62ab4e7b3d
|
||||
|
@@ -1 +1 @@
|
||||
419764b35c96a1b08aefc0d6093c19fdf2aef517
|
||||
6b998f3066754e219c266501327e5578c9406b63
|
102
src/btree.c
102
src/btree.c
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.512 2008/09/18 01:08:16 drh Exp $
|
||||
** $Id: btree.c,v 1.513 2008/09/18 17:34:44 danielk1977 Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** See the header comment on "btreeInt.h" for additional information.
|
||||
@@ -941,15 +941,17 @@ int sqlite3BtreeInitPage(
|
||||
if( pPage==pParent ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){
|
||||
if( (pPage->pParent!=pParent)
|
||||
&& (pPage->pParent!=0 || pPage->isInit==PAGE_ISINIT_FULL) ){
|
||||
/* The parent page should never change unless the file is corrupt */
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
if( pPage->isInit ) return SQLITE_OK;
|
||||
if( pPage->pParent==0 && pParent!=0 ){
|
||||
if( pPage->isInit==PAGE_ISINIT_FULL ) return SQLITE_OK;
|
||||
if( pParent!=0 ){
|
||||
pPage->pParent = pParent;
|
||||
sqlite3PagerRef(pParent->pDbPage);
|
||||
}
|
||||
if( pPage->isInit==PAGE_ISINIT_NONE ){
|
||||
hdr = pPage->hdrOffset;
|
||||
data = pPage->aData;
|
||||
if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
|
||||
@@ -993,6 +995,7 @@ int sqlite3BtreeInitPage(
|
||||
/* Free space cannot exceed total page size */
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Check that all the offsets in the cell offset array are within range.
|
||||
@@ -1014,7 +1017,7 @@ int sqlite3BtreeInitPage(
|
||||
}
|
||||
#endif
|
||||
|
||||
pPage->isInit = 1;
|
||||
pPage->isInit = PAGE_ISINIT_FULL;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -1048,7 +1051,7 @@ static void zeroPage(MemPage *pPage, int flags){
|
||||
pPage->maskPage = pBt->pageSize - 1;
|
||||
pPage->idxShift = 0;
|
||||
pPage->nCell = 0;
|
||||
pPage->isInit = 1;
|
||||
pPage->isInit = PAGE_ISINIT_FULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1120,7 +1123,7 @@ static int getAndInitPage(
|
||||
MemPage *pPage;
|
||||
|
||||
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||
assert( !pParent || pParent->isInit );
|
||||
assert( !pParent || pParent->isInit==PAGE_ISINIT_FULL );
|
||||
if( pgno==0 ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
@@ -1144,7 +1147,7 @@ static int getAndInitPage(
|
||||
if( rc ) return rc;
|
||||
pPage = *ppPage;
|
||||
}
|
||||
if( pPage->isInit==0 ){
|
||||
if( pPage->isInit!=PAGE_ISINIT_FULL ){
|
||||
rc = sqlite3BtreeInitPage(pPage, pParent);
|
||||
}else if( pParent && (pPage==pParent || pPage->pParent!=pParent) ){
|
||||
/* This condition indicates a loop in the b-tree structure (the scenario
|
||||
@@ -1184,14 +1187,18 @@ static void pageDestructor(DbPage *pData){
|
||||
MemPage *pPage;
|
||||
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
|
||||
if( pPage ){
|
||||
assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||
assert( pPage->isInit!=PAGE_ISINIT_FULL
|
||||
|| sqlite3_mutex_held(pPage->pBt->mutex)
|
||||
);
|
||||
if( pPage->pParent ){
|
||||
MemPage *pParent = pPage->pParent;
|
||||
assert( pParent->pBt==pPage->pBt );
|
||||
pPage->pParent = 0;
|
||||
releasePage(pParent);
|
||||
}
|
||||
pPage->isInit = 0;
|
||||
if( pPage->isInit==PAGE_ISINIT_FULL ){
|
||||
pPage->isInit = PAGE_ISINIT_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1203,14 +1210,15 @@ static void pageDestructor(DbPage *pData){
|
||||
** This routine needs to reset the extra data section at the end of the
|
||||
** page to agree with the restored data.
|
||||
*/
|
||||
static void pageReinit(DbPage *pData, int pageSize){
|
||||
static void pageReinit(DbPage *pData){
|
||||
MemPage *pPage;
|
||||
assert( (pageSize & 7)==0 );
|
||||
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
|
||||
if( pPage->isInit ){
|
||||
if( pPage->isInit==PAGE_ISINIT_FULL ){
|
||||
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||
pPage->isInit = 0;
|
||||
sqlite3BtreeInitPage(pPage, pPage->pParent);
|
||||
}else if( pPage->isInit==PAGE_ISINIT_DATA ){
|
||||
pPage->isInit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3557,7 +3565,7 @@ static int moveToRoot(BtCursor *pCur){
|
||||
}
|
||||
pRoot = pCur->pPage;
|
||||
if( pRoot && pRoot->pgno==pCur->pgnoRoot ){
|
||||
assert( pRoot->isInit );
|
||||
assert( pRoot->isInit==PAGE_ISINIT_FULL );
|
||||
}else{
|
||||
if(
|
||||
SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0))
|
||||
@@ -3743,7 +3751,7 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
return rc;
|
||||
}
|
||||
assert( pCur->pPage );
|
||||
assert( pCur->pPage->isInit );
|
||||
assert( pCur->pPage->isInit==PAGE_ISINIT_FULL );
|
||||
if( pCur->eState==CURSOR_INVALID ){
|
||||
*pRes = -1;
|
||||
assert( pCur->pPage->nCell==0 );
|
||||
@@ -3829,7 +3837,7 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
pCur->idx = (lwr+upr)/2;
|
||||
}
|
||||
assert( lwr==upr+1 );
|
||||
assert( pPage->isInit );
|
||||
assert( pPage->isInit==PAGE_ISINIT_FULL );
|
||||
if( pPage->leaf ){
|
||||
chldPg = 0;
|
||||
}else if( lwr>=pPage->nCell ){
|
||||
@@ -3935,7 +3943,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
|
||||
}
|
||||
pCur->skip = 0;
|
||||
|
||||
assert( pPage->isInit );
|
||||
assert( pPage->isInit==PAGE_ISINIT_FULL );
|
||||
assert( pCur->idx<pPage->nCell );
|
||||
|
||||
pCur->idx++;
|
||||
@@ -4004,7 +4012,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
|
||||
pCur->skip = 0;
|
||||
|
||||
pPage = pCur->pPage;
|
||||
assert( pPage->isInit );
|
||||
assert( pPage->isInit==PAGE_ISINIT_FULL );
|
||||
assert( pCur->idx>=0 );
|
||||
if( !pPage->leaf ){
|
||||
pgno = get4byte( findCell(pPage, pCur->idx) );
|
||||
@@ -4295,6 +4303,13 @@ static int allocateBtreePage(
|
||||
end_allocate_page:
|
||||
releasePage(pTrunk);
|
||||
releasePage(pPrevTrunk);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( (*ppPage)->isInit==PAGE_ISINIT_FULL ){
|
||||
releasePage(*ppPage);
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
(*ppPage)->isInit = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -4594,7 +4609,7 @@ static int reparentPage(
|
||||
pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
|
||||
if( pDbPage ){
|
||||
pThis = (MemPage *)sqlite3PagerGetExtra(pDbPage);
|
||||
if( pThis->isInit ){
|
||||
if( pThis->isInit==PAGE_ISINIT_FULL ){
|
||||
assert( pThis->aData==sqlite3PagerGetData(pDbPage) );
|
||||
if( pThis->pParent!=pNewParent ){
|
||||
if( pThis->pParent ) sqlite3PagerUnref(pThis->pParent->pDbPage);
|
||||
@@ -4877,7 +4892,7 @@ static int balance(MemPage*, int);
|
||||
*/
|
||||
static int balance_quick(MemPage *pPage, MemPage *pParent){
|
||||
int rc;
|
||||
MemPage *pNew;
|
||||
MemPage *pNew = 0;
|
||||
Pgno pgnoNew;
|
||||
u8 *pCell;
|
||||
u16 szCell;
|
||||
@@ -4893,9 +4908,7 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){
|
||||
** into it. Then remove the overflow cell from pPage.
|
||||
*/
|
||||
rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pCell = pPage->aOvfl[0].pCell;
|
||||
szCell = cellSizePtr(pPage, pCell);
|
||||
zeroPage(pNew, pPage->aData[0]);
|
||||
@@ -4939,17 +4952,34 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = ptrmapPutOvfl(pNew, 0);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
releasePage(pNew);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point the pPage->nFree variable is not set correctly with
|
||||
** respect to the content of the page (because it was set to 0 by
|
||||
** insertCell). So call sqlite3BtreeInitPage() to make sure it is
|
||||
** correct.
|
||||
**
|
||||
** This has to be done even if an error will be returned. Normally, if
|
||||
** an error occurs during tree balancing, the contents of MemPage are
|
||||
** not important, as they will be recalculated when the page is rolled
|
||||
** back. But here, in balance_quick(), it is possible that pPage has
|
||||
** not yet been marked dirty or written into the journal file. Therefore
|
||||
** it will not be rolled back and so it is important to make sure that
|
||||
** the page data and contents of MemPage are consistent.
|
||||
*/
|
||||
pPage->isInit = 0;
|
||||
sqlite3BtreeInitPage(pPage, pPage->pParent);
|
||||
sqlite3PagerUnref(pPage->pParent->pDbPage);
|
||||
|
||||
/* Release the reference to the new page and balance the parent page,
|
||||
** in case the divider cell inserted caused it to become overfull.
|
||||
*/
|
||||
releasePage(pNew);
|
||||
return balance(pParent, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = balance(pParent, 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_QUICKBALANCE */
|
||||
|
||||
@@ -5022,7 +5052,7 @@ static int balance_nonroot(MemPage *pPage){
|
||||
/*
|
||||
** Find the parent page.
|
||||
*/
|
||||
assert( pPage->isInit );
|
||||
assert( pPage->isInit==PAGE_ISINIT_FULL );
|
||||
assert( sqlite3PagerIswriteable(pPage->pDbPage) || pPage->nOverflow==1 );
|
||||
pBt = pPage->pBt;
|
||||
pParent = pPage->pParent;
|
||||
@@ -5554,7 +5584,7 @@ static int balance_nonroot(MemPage *pPage){
|
||||
** have been added to the freelist so it might no longer be initialized.
|
||||
** But the parent page will always be initialized.
|
||||
*/
|
||||
assert( pParent->isInit );
|
||||
assert( pParent->isInit==PAGE_ISINIT_FULL );
|
||||
sqlite3ScratchFree(apCell);
|
||||
apCell = 0;
|
||||
rc = balance(pParent, 0);
|
||||
@@ -5571,9 +5601,11 @@ balance_cleanup:
|
||||
for(i=0; i<nNew; i++){
|
||||
releasePage(apNew[i]);
|
||||
}
|
||||
|
||||
releasePage(pParent);
|
||||
TRACE(("BALANCE: finished with %d: old=%d new=%d cells=%d\n",
|
||||
pPage->pgno, nOld, nNew, nCell));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -5707,7 +5739,7 @@ static int balance_deeper(MemPage *pPage){
|
||||
cdata = pChild->aData;
|
||||
memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr);
|
||||
memcpy(&cdata[cbrk], &data[cbrk], usableSize-cbrk);
|
||||
if( pChild->isInit ) return SQLITE_CORRUPT;
|
||||
if( pChild->isInit==PAGE_ISINIT_FULL ) return SQLITE_CORRUPT;
|
||||
rc = sqlite3BtreeInitPage(pChild, pPage);
|
||||
if( rc ) goto balancedeeper_out;
|
||||
memcpy(pChild->aOvfl, pPage->aOvfl, pPage->nOverflow*sizeof(pPage->aOvfl[0]));
|
||||
@@ -5890,7 +5922,7 @@ int sqlite3BtreeInsert(
|
||||
TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
|
||||
pCur->pgnoRoot, nKey, nData, pPage->pgno,
|
||||
loc==0 ? "overwrite" : "new entry"));
|
||||
assert( pPage->isInit );
|
||||
assert( pPage->isInit==PAGE_ISINIT_FULL );
|
||||
allocateTempSpace(pBt);
|
||||
newCell = pBt->pTmpSpace;
|
||||
if( newCell==0 ) return SQLITE_NOMEM;
|
||||
@@ -5944,7 +5976,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
|
||||
BtShared *pBt = p->pBt;
|
||||
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( pPage->isInit );
|
||||
assert( pPage->isInit==PAGE_ISINIT_FULL );
|
||||
if( pBt->inTransaction!=TRANS_WRITE ){
|
||||
/* Must start a transaction before doing a delete */
|
||||
rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
|
||||
@@ -7124,7 +7156,11 @@ static int btreeCopyFile(Btree *pTo, Btree *pFrom){
|
||||
}
|
||||
}
|
||||
|
||||
if( pToPage ) sqlite3PagerUnref(pToPage);
|
||||
if( pToPage ){
|
||||
MemPage *p = (MemPage *)sqlite3PagerGetExtra(pToPage);
|
||||
p->isInit = 0;
|
||||
sqlite3PagerUnref(pToPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btreeInt.h,v 1.30 2008/08/01 20:10:08 drh Exp $
|
||||
** $Id: btreeInt.h,v 1.31 2008/09/18 17:34:44 danielk1977 Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
@@ -296,6 +296,18 @@ struct MemPage {
|
||||
MemPage *pParent; /* The parent of this page. NULL for root */
|
||||
};
|
||||
|
||||
/*
|
||||
** Possible values for the MemPage.isInit variable. When a page is first
|
||||
** loaded or if the data stored in the MemPage struct is invalidated,
|
||||
** MemPage.isInit is set to PAGE_ISINIT_NONE. If the MemPage structure
|
||||
** is fully initialized, then MemPage.isInit is set to PAGE_ISINIT_FULL.
|
||||
** MemPage.isInit is set to PAGE_ISINIT_DATA when the MemPage struct is
|
||||
** populated, but the MemPage.pParent variable is not necessarily correct.
|
||||
*/
|
||||
#define PAGE_ISINIT_NONE 0
|
||||
#define PAGE_ISINIT_DATA 1
|
||||
#define PAGE_ISINIT_FULL 2
|
||||
|
||||
/*
|
||||
** The in-memory image of a disk page has the auxiliary information appended
|
||||
** to the end. EXTRA_SIZE is the number of bytes of space needed to hold
|
||||
|
15
src/pager.c
15
src/pager.c
@@ -18,7 +18,7 @@
|
||||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.491 2008/09/17 20:06:26 drh Exp $
|
||||
** @(#) $Id: pager.c,v 1.492 2008/09/18 17:34:44 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
#include "sqliteInt.h"
|
||||
@@ -208,8 +208,7 @@ struct Pager {
|
||||
int nHit, nMiss; /* Cache hits and missing */
|
||||
int nRead, nWrite; /* Database pages read/written */
|
||||
#endif
|
||||
void (*xDestructor)(DbPage*,int); /* Call this routine when freeing pages */
|
||||
void (*xReiniter)(DbPage*,int); /* Call this routine when reloading pages */
|
||||
void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
|
||||
#ifdef SQLITE_HAS_CODEC
|
||||
void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
|
||||
void *pCodecArg; /* First argument to xCodec() */
|
||||
@@ -1159,7 +1158,7 @@ static int pager_playback_one_page(
|
||||
pData = pPg->pData;
|
||||
memcpy(pData, aData, pPager->pageSize);
|
||||
if( pPager->xReiniter ){
|
||||
pPager->xReiniter(pPg, pPager->pageSize);
|
||||
pPager->xReiniter(pPg);
|
||||
}
|
||||
if( isMainJrnl ) makeClean(pPg);
|
||||
#ifdef SQLITE_CHECK_PAGES
|
||||
@@ -1941,7 +1940,7 @@ void sqlite3PagerSetBusyhandler(Pager *pPager, BusyHandler *pBusyHandler){
|
||||
** an opportunity to restore the EXTRA section to agree with the restored
|
||||
** page data.
|
||||
*/
|
||||
void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*,int)){
|
||||
void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*)){
|
||||
pPager->xReiniter = xReinit;
|
||||
}
|
||||
|
||||
@@ -3830,8 +3829,8 @@ int sqlite3PagerRollback(Pager *pPager){
|
||||
int rc = SQLITE_OK;
|
||||
PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
|
||||
if( MEMDB ){
|
||||
sqlite3PcacheRollback(pPager->pPCache, 1);
|
||||
sqlite3PcacheRollback(pPager->pPCache, 0);
|
||||
sqlite3PcacheRollback(pPager->pPCache, 1, pPager->xReiniter);
|
||||
sqlite3PcacheRollback(pPager->pPCache, 0, pPager->xReiniter);
|
||||
sqlite3PcacheCleanAll(pPager->pPCache);
|
||||
sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
|
||||
pPager->dbSize = pPager->origDbSize;
|
||||
@@ -3991,7 +3990,7 @@ int sqlite3PagerStmtRollback(Pager *pPager){
|
||||
if( pPager->stmtInUse ){
|
||||
PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
|
||||
if( MEMDB ){
|
||||
sqlite3PcacheRollback(pPager->pPCache, 1);
|
||||
sqlite3PcacheRollback(pPager->pPCache, 1, pPager->xReiniter);
|
||||
pPager->dbSize = pPager->stmtSize;
|
||||
pager_truncate_cache(pPager);
|
||||
rc = SQLITE_OK;
|
||||
|
@@ -13,7 +13,7 @@
|
||||
** subsystem. The page cache subsystem reads and writes a file a page
|
||||
** at a time and provides a journal for rollback.
|
||||
**
|
||||
** @(#) $Id: pager.h,v 1.82 2008/09/01 17:23:29 drh Exp $
|
||||
** @(#) $Id: pager.h,v 1.83 2008/09/18 17:34:44 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#ifndef _PAGER_H_
|
||||
@@ -72,7 +72,7 @@ typedef struct PgHdr DbPage;
|
||||
*/
|
||||
int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, void(*)(DbPage*), int,int,int);
|
||||
void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler);
|
||||
void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int));
|
||||
void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*));
|
||||
int sqlite3PagerSetPagesize(Pager*, u16*);
|
||||
int sqlite3PagerMaxPageCount(Pager*, int);
|
||||
int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
|
||||
|
11
src/pcache.c
11
src/pcache.c
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file implements that page cache.
|
||||
**
|
||||
** @(#) $Id: pcache.c,v 1.29 2008/09/17 20:06:26 drh Exp $
|
||||
** @(#) $Id: pcache.c,v 1.30 2008/09/18 17:34:44 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@@ -1019,7 +1019,11 @@ void sqlite3PcacheCommit(PCache *pCache, int idJournal){
|
||||
/*
|
||||
** Rollback a change previously preserved.
|
||||
*/
|
||||
void sqlite3PcacheRollback(PCache *pCache, int idJournal){
|
||||
void sqlite3PcacheRollback(
|
||||
PCache *pCache, /* Pager cache */
|
||||
int idJournal, /* Which copy to rollback to */
|
||||
void (*xReiniter)(PgHdr*) /* Called on each rolled back page */
|
||||
){
|
||||
PgHdr *p;
|
||||
int sz;
|
||||
int mask = idJournal==0 ? ~PGHDR_IN_JOURNAL : 0xffffff;
|
||||
@@ -1030,6 +1034,9 @@ void sqlite3PcacheRollback(PCache *pCache, int idJournal){
|
||||
memcpy(p->pData, p->apSave[idJournal], sz);
|
||||
pcacheFree(p->apSave[idJournal]);
|
||||
p->apSave[idJournal] = 0;
|
||||
if( xReiniter ){
|
||||
xReiniter(p);
|
||||
}
|
||||
}
|
||||
p->flags &= mask;
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@
|
||||
** This header file defines the interface that the sqlite page cache
|
||||
** subsystem.
|
||||
**
|
||||
** @(#) $Id: pcache.h,v 1.10 2008/09/17 20:06:26 drh Exp $
|
||||
** @(#) $Id: pcache.h,v 1.11 2008/09/18 17:34:44 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#ifndef _PCACHE_H_
|
||||
@@ -113,7 +113,7 @@ void sqlite3PcacheTruncate(PCache*, Pgno x);
|
||||
/* Routines used to implement transactions on memory-only databases. */
|
||||
int sqlite3PcachePreserve(PgHdr*, int); /* Preserve current page content */
|
||||
void sqlite3PcacheCommit(PCache*, int); /* Drop preserved copy */
|
||||
void sqlite3PcacheRollback(PCache*, int); /* Rollback to preserved copy */
|
||||
void sqlite3PcacheRollback(PCache*, int, void (*xReiniter)(PgHdr*));
|
||||
|
||||
/* Get a list of all dirty pages in the cache, sorted by page number */
|
||||
PgHdr *sqlite3PcacheDirtyList(PCache*);
|
||||
|
Reference in New Issue
Block a user