Index: src/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -303,16 +303,17 @@ ** may attempt to commit the transaction again later (calling ** CommitPhaseOne() again). This flag is used to ensure that the ** master journal name is only written to the journal file the first ** time CommitPhaseOne() is called. ** -** doNotSync +** doNotSpill ** ** When enabled, cache spills are prohibited and the journal file cannot ** be synced. This variable is set and cleared by sqlite3PagerWrite() ** in order to prevent a journal sync from happening in between the -** journalling of two pages on the same sector. +** journalling of two pages on the same sector. It is also set to prevent +** pagerStress() from trying to use the journal during a rollback. ** ** needSync ** ** TODO: It might be easier to set this variable in writeJournalHdr() ** and writeMasterJournal() only. Change its meaning to "unsynced data @@ -352,11 +353,11 @@ u8 dbModified; /* True if there are any changes to the Db */ u8 needSync; /* True if an fsync() is needed on the journal */ u8 journalStarted; /* True if header of journal is synced */ u8 changeCountDone; /* Set after incrementing the change-counter */ u8 setMaster; /* True if a m-j name has been written to jrnl */ - u8 doNotSync; /* Boolean. While true, do not spill the cache */ + u8 doNotSpill; /* Do not spill the cache when non-zero */ u8 dbSizeValid; /* Set when dbSize is correct */ u8 subjInMemory; /* True to use in-memory sub-journals */ Pgno dbSize; /* Number of pages in the database */ Pgno dbOrigSize; /* dbSize before the current transaction */ Pgno dbFileSize; /* Number of pages in the database file */ @@ -1688,13 +1689,16 @@ ** the data just read from the sub-journal. Mark the page as dirty ** and if the pager requires a journal-sync, then mark the page as ** requiring a journal-sync before it is written. */ assert( isSavepnt ); - if( (rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1))!=SQLITE_OK ){ - return rc; - } + assert( pPager->doNotSpill==0 ); + pPager->doNotSpill++; + rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1); + assert( pPager->doNotSpill==1 ); + pPager->doNotSpill--; + if( rc!=SQLITE_OK ) return rc; pPg->flags &= ~PGHDR_NEED_READ; sqlite3PcacheMakeDirty(pPg); } if( pPg ){ /* No page should ever be explicitly rolled back that is in use, except @@ -3511,10 +3515,22 @@ Pager *pPager = (Pager *)p; int rc = SQLITE_OK; assert( pPg->pPager==pPager ); assert( pPg->flags&PGHDR_DIRTY ); + + /* The doNotSpill flag is set during times when writing to the journal + ** is disallowed: (1) during calls to sqlite3PagerWrite() while it + ** is journalling a set of two or more database pages that are stored + ** on the same disk sector, and (2) while performing a rollback. + ** + ** Similarly, if the pager has already entered the error state, do not + ** try to write the contents of pPg to disk. + */ + if( pPager->errCode || pPager->doNotSpill ){ + return SQLITE_OK; + } pPg->pDirty = 0; if( pagerUseWal(pPager) ){ /* Write a single frame for this page to the log. */ if( subjRequiresPage(pPg) ){ @@ -3522,26 +3538,10 @@ } if( rc==SQLITE_OK ){ rc = pagerWalFrames(pPager, pPg, 0, 0, 0); } }else{ - /* The doNotSync flag is set by the sqlite3PagerWrite() function while it - ** is journalling a set of two or more database pages that are stored - ** on the same disk sector. Syncing the journal is not allowed while - ** this is happening as it is important that all members of such a - ** set of pages are synced to disk together. So, if the page this function - ** is trying to make clean will require a journal sync and the doNotSync - ** flag is set, return without doing anything. The pcache layer will - ** just have to go ahead and allocate a new page buffer instead of - ** reusing pPg. - ** - ** Similarly, if the pager has already entered the error state, do not - ** try to write the contents of pPg to disk. - */ - if( pPager->errCode || (pPager->doNotSync && pPg->flags&PGHDR_NEED_SYNC) ){ - return SQLITE_OK; - } /* Sync the journal file if required. */ if( pPg->flags&PGHDR_NEED_SYNC ){ rc = syncJournal(pPager); if( rc==SQLITE_OK && pPager->fullSync && @@ -4832,16 +4832,16 @@ Pgno pg1; /* First page of the sector pPg is located on. */ int nPage; /* Number of pages starting at pg1 to journal */ int ii; /* Loop counter */ int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ - /* Set the doNotSync flag to 1. This is because we cannot allow a journal + /* Set the doNotSpill flag to 1. This is because we cannot allow a journal ** header to be written between the pages journaled by this function. */ assert( !MEMDB ); - assert( pPager->doNotSync==0 ); - pPager->doNotSync = 1; + assert( pPager->doNotSpill==0 ); + pPager->doNotSpill++; /* This trick assumes that both the page-size and sector-size are ** an integer power of 2. It sets variable pg1 to the identifier ** of the first page of the sector pPg is located on. */ @@ -4899,12 +4899,12 @@ } } assert(pPager->needSync); } - assert( pPager->doNotSync==1 ); - pPager->doNotSync = 0; + assert( pPager->doNotSpill==1 ); + pPager->doNotSpill--; }else{ rc = pager_write(pDbPage); } return rc; }