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

On a ROLLBACK, if there page cache entries which are dirty but not in the

rollback journal, make sure they get reinitialized in the btree layer. (CVS 5936)

FossilOrigin-Name: faded96f36229ee85039276db693391d0f10648c
This commit is contained in:
drh
2008-11-21 03:23:43 +00:00
parent 41022645ee
commit c047b9f74d
4 changed files with 68 additions and 32 deletions

View File

@@ -18,7 +18,7 @@
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.506 2008/11/19 18:30:29 drh Exp $
** @(#) $Id: pager.c,v 1.507 2008/11/21 03:23:43 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
@@ -1061,9 +1061,6 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){
return cksum;
}
/* Forward declaration */
static void makeClean(PgHdr*);
/*
** Read a single page from the journal file opened on file descriptor
** jfd. Playback this one page.
@@ -1173,7 +1170,9 @@ static int pager_playback_one_page(
if( pPager->xReiniter ){
pPager->xReiniter(pPg);
}
if( isMainJrnl ) makeClean(pPg);
if( isMainJrnl ){
sqlite3PcacheMakeClean(pPg);
}
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
@@ -1518,6 +1517,20 @@ static int pager_playback(Pager *pPager, int isHot){
assert( 0 );
end_playback:
/* There may be pages in cache that are dirty but which were not in
** the rollback journal. Such pages would have been taken out of the
** freelist (and hence marked as DontRollback). All such pages must
** be reinitialized.
*/
if( rc==SQLITE_OK && pPager->xReiniter ){
PgHdr *pDirty; /* List of page that are still dirty */
pDirty = sqlite3PcacheDirtyList(pPager->pPCache);
while( pDirty ){
pPager->xReiniter(pDirty);
sqlite3PcacheMakeClean(pDirty);
pDirty = pDirty->pDirty;
}
}
if( rc==SQLITE_OK ){
zMaster = pPager->pTmpSpace;
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
@@ -3094,23 +3107,6 @@ int sqlite3PagerBegin(DbPage *pPg, int exFlag){
return rc;
}
/*
** Make a page dirty. Set its dirty flag and add it to the dirty
** page list.
*/
static void makeDirty(PgHdr *pPg){
sqlite3PcacheMakeDirty(pPg);
}
/*
** Make a page clean. Clear its dirty bit and remove it from the
** dirty page list.
*/
static void makeClean(PgHdr *pPg){
sqlite3PcacheMakeClean(pPg);
}
/*
** Mark a data page as writeable. The page is written into the journal
** if it is not there already. This routine must be called before making
@@ -3162,7 +3158,7 @@ static int pager_write(PgHdr *pPg){
/* Mark the page as dirty. If the page has already been written
** to the journal then we can return right away.
*/
makeDirty(pPg);
sqlite3PcacheMakeDirty(pPg);
if( pageInJournal(pPg) && (pageInStatement(pPg) || pPager->stmtInUse==0) ){
pPager->dirtyCache = 1;
pPager->dbModified = 1;
@@ -4091,7 +4087,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
sqlite3PcacheDrop(pPgOld);
}
makeDirty(pPg);
sqlite3PcacheMakeDirty(pPg);
pPager->dirtyCache = 1;
pPager->dbModified = 1;
@@ -4126,7 +4122,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
pPager->needSync = 1;
assert( pPager->noSync==0 && !MEMDB );
pPgHdr->flags |= PGHDR_NEED_SYNC;
makeDirty(pPgHdr);
sqlite3PcacheMakeDirty(pPgHdr);
sqlite3PagerUnref(pPgHdr);
}