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:
46
src/pager.c
46
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.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);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user