From: dan Date: Fri, 6 Aug 2010 17:18:00 +0000 (+0000) Subject: Further enhancements to comments in pager.c. X-Git-Tag: version-3.7.2~53^2~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=85d14ed238f9c60333148062f28390092e3de68a;p=thirdparty%2Fsqlite.git Further enhancements to comments in pager.c. FossilOrigin-Name: 876162c7e036af1cb447409b685afc72c0061a32 --- diff --git a/manifest b/manifest index f3b4bb44fc..e52daaa123 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\ssome\sproblems\swith\srunning\stest\sscripts\swith\sthe\sinmemory_journal\spermutation. -D 2010-08-06T14:37:13 +C Further\senhancements\sto\scomments\sin\spager.c. +D 2010-08-06T17:18:01 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -156,7 +156,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e F src/os_unix.c ae5ca8a6031380708f3fec7be325233d49944914 F src/os_win.c 51cb62f76262d961ea4249489383d714501315a7 -F src/pager.c c905bca55b0d507a2c5c9ee97895ba0aaff2a969 +F src/pager.c 2dffe4d468c7665cceaa43eb56e4b5c2f0d28396 F src/pager.h 80726162dc3942f59ab27b738fb667b9ba0a89d5 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58 F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07 @@ -843,7 +843,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P aef6698c732f3f9e46986f53e63ca2bdf5f7d208 -R d400d2e52912473cf6c4aca53a46678c +P 7bd8ba084e75bcd5c744e1d4a1812df3a4d91887 +R 8a9a6e1ca5d584d1153bedf7c51336b6 U dan -Z e0e135b259997ce301d4de7d751dee90 +Z 9aa10a3fe3170bea3315ad90ad87b34f diff --git a/manifest.uuid b/manifest.uuid index 9840d1e499..4ff4fab4ca 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7bd8ba084e75bcd5c744e1d4a1812df3a4d91887 \ No newline at end of file +876162c7e036af1cb447409b685afc72c0061a32 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 6383beb8e5..767426fefa 100644 --- a/src/pager.c +++ b/src/pager.c @@ -497,13 +497,21 @@ struct PagerSavepoint { ** ** doNotSpill, doNotSyncSpill ** -** When enabled, cache spills are prohibited. The doNotSpill variable -** inhibits all cache spill and doNotSyncSpill inhibits those spills that -** would require a journal sync. The doNotSyncSpill 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. The -** doNotSpill value set to prevent pagerStress() from trying to use -** the journal during a rollback. +** These two boolean variables control the behaviour of cache-spills +** (calls made by the pcache module to the pagerStress() routine to +** write cached data to the file-system in order to free up memory). +** +** When doNotSpill is non-zero, writing to the database from pagerStress() +** is disabled altogether. This is done in a very obscure case that +** comes up during savepoint rollback that requires the pcache module +** to allocate a new page to prevent the journal file from being written +** while it is being traversed by code in pager_playback(). +** +** If doNotSyncSpill is non-zero, writing to the database from pagerStress() +** is permitted, but syncing the journal file is not. This flag is set +** by sqlite3PagerWrite() when the file-system sector-size is larger than +** the database page-size in order to prevent a journal sync from happening +** in between the journalling of two pages on the same sector. ** ** subjInMemory ** @@ -1750,8 +1758,9 @@ static int pager_error(Pager *pPager, int rc){ ** the journal file or writing the very first journal-header of a ** database transaction. ** -** If the pager is in PAGER_SHARED or PAGER_UNLOCK state when this -** routine is called, it is a no-op (returns SQLITE_OK). +** This routine is never called in PAGER_ERROR state. If it is called +** in PAGER_NONE or PAGER_SHARED state and the lock held is less +** exclusive than a RESERVED lock, it is a no-op. ** ** Otherwise, any active savepoints are released. ** @@ -1782,13 +1791,9 @@ static int pager_error(Pager *pPager, int rc){ ** DELETE and the pager is in exclusive mode, the method described under ** journalMode==PERSIST is used instead. ** -** After the journal is finalized, if running in non-exclusive mode, the -** pager moves to PAGER_SHARED state (and downgrades the lock on the -** database file accordingly). -** -** If the pager is running in exclusive mode and is in PAGER_SYNCED state, -** it moves to PAGER_EXCLUSIVE. No locks are downgraded when running in -** exclusive mode. +** After the journal is finalized, the pager moves to PAGER_READER state. +** If running in non-exclusive rollback mode, the lock on the file is +** downgraded to a SHARED_LOCK. ** ** SQLITE_OK is returned if no error occurs. If an error occurs during ** any of the IO operations to finalize the journal file or unlock the @@ -1803,7 +1808,19 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){ int rc = SQLITE_OK; /* Error code from journal finalization operation */ int rc2 = SQLITE_OK; /* Error code from db file unlock operation */ - /* Do nothing if the pager does not have an open write transaction. */ + /* Do nothing if the pager does not have an open write transaction + ** or at least a RESERVED lock. This function may be called when there + ** is no write-transaction active but a RESERVED or greater lock is + ** held under two circumstances: + ** + ** 1. After a successful hot-journal rollback, it is called with + ** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK. + ** + ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE + ** lock switches back to locking_mode=normal and then executes a + ** read-transaction, this function is called with eState==PAGER_READER + ** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed. + */ assert( assert_pager_state(pPager) ); assert( pPager->eState!=PAGER_ERROR ); if( pPager->eStateeLockeLock>=RESERVED_LOCK && !pPager->exclusiveMode ){ + }else if( !pPager->exclusiveMode ){ assert( pPager->eState==PAGER_READER ); pager_end_transaction(pPager, 0); } @@ -1959,9 +1976,8 @@ static void pagerReportSize(Pager *pPager){ ** The page begins at offset *pOffset into the file. The *pOffset ** value is increased to the start of the next page in the journal. ** -** The isMainJrnl flag is true if this is the main rollback journal and -** false for the statement journal. The main rollback journal uses -** checksums - the statement journal does not. +** The main rollback journal uses checksums - the statement journal does +** not. ** ** If the page number of the page record read from the (sub-)journal file ** is greater than the current value of Pager.dbSize, then playback is @@ -2015,6 +2031,17 @@ static int pager_playback_one_page( assert( aData ); /* Temp storage must have already been allocated */ assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) ); + /* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction + ** or savepoint rollback done at the request of the caller) or this is + ** a hot-journal rollback. If it is a hot-journal rollback, the pager + ** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback + ** only reads from the main journal, not the sub-journal. + */ + assert( pPager->eState>=PAGER_WRITER_CACHEMOD + || (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK) + ); + assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl ); + /* Read the page number and page data from the journal or sub-journal ** file. Return an error code to the caller if an IO error occurs. */ @@ -2051,9 +2078,6 @@ static int pager_playback_one_page( if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){ return rc; } - assert( pPager->eState>=PAGER_WRITER_CACHEMOD - || (pPager->eState==PAGER_OPEN && isMainJrnl) - ); /* When playing back page 1, restore the nReserve setting */ @@ -2863,15 +2887,34 @@ static int pagerBeginReadTransaction(Pager *pPager){ return rc; } - /* -** TODO: Description here. +** This function is called as part of the transition from PAGER_OPEN +** to PAGER_READER state to determine the size of the database file +** in pages (assuming the page size currently stored in Pager.pageSize). +** +** If no error occurs, SQLITE_OK is returned and the size of the database +** in pages is stored in *pnPage. Otherwise, an error code (perhaps +** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified. */ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ Pgno nPage; /* Value to return via *pnPage */ + /* Query the WAL sub-system for the database size. The WalDbsize() + ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or + ** if the database size is not available. The database size is not + ** available from the WAL sub-system if the log file is empty or + ** contains no valid committed transactions. + */ assert( pPager->eState==PAGER_OPEN ); + assert( pPager->eLock>=SHARED_LOCK || pPager->noReadlock ); nPage = sqlite3WalDbsize(pPager->pWal); + + /* If the database size was not available from the WAL sub-system, + ** determine it based on the size of the database file. If the size + ** of the database file is not an integer multiple of the page-size, + ** round down to the nearest page. Except, any file larger than 0 + ** bytes in size is considered to contain at least one page. + */ if( nPage==0 ){ i64 n = 0; /* Size of db file in bytes */ assert( isOpen(pPager->fd) || pPager->tempFile ); @@ -2887,7 +2930,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ } } - /* If the current number of pages in the file is greater than the + /* If the current number of pages in the file is greater than the ** configured maximum pager number, increase the allowed limit so ** that the file can be read. */ @@ -2912,8 +2955,6 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ ** ** Return SQLITE_OK or an error code. ** -** If the WAL file is opened, also open a snapshot (read transaction). -** ** The caller must hold a SHARED lock on the database file to call this ** function. Because an EXCLUSIVE lock on the db file is required to delete ** a WAL on a none-empty database, this ensures there is no race condition @@ -2922,12 +2963,13 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ */ static int pagerOpenWalIfPresent(Pager *pPager){ int rc = SQLITE_OK; + assert( pPager->eState==PAGER_OPEN ); + assert( pPager->eLock>=SHARED_LOCK || pPager->noReadlock ); + if( !pPager->tempFile ){ int isWal; /* True if WAL file exists */ Pgno nPage; /* Size of the database file */ - assert( pPager->eState==PAGER_OPEN ); - assert( pPager->eLock>=SHARED_LOCK || pPager->noReadlock ); rc = pagerPagecount(pPager, &nPage); if( rc ) return rc; if( nPage==0 ){ @@ -2942,9 +2984,6 @@ static int pagerOpenWalIfPresent(Pager *pPager){ if( isWal ){ testcase( sqlite3PcachePagecount(pPager->pPCache)==0 ); rc = sqlite3PagerOpenWal(pPager, 0); - if( rc==SQLITE_OK ){ - rc = pagerBeginReadTransaction(pPager); - } }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){ pPager->journalMode = PAGER_JOURNALMODE_DELETE; } @@ -4994,14 +5033,6 @@ static int pager_open_journal(Pager *pPager){ ** an EXCLUSIVE lock. If such a lock is already held, no locking ** functions need be called. ** -** If this is not a temporary or in-memory file and, the journal file is -** opened if it has not been already. For a temporary file, the opening -** of the journal file is deferred until there is an actual need to -** write to the journal. TODO: Why handle temporary files differently? -** -** If the journal file is opened (or if it is already open), then a -** journal-header is written to the start of it. -** ** If the subjInMemory argument is non-zero, then any sub-journal opened ** within this transaction will be opened as an in-memory file. This ** has no effect if the sub-journal is already opened (as it may be when @@ -5048,7 +5079,6 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){ } } - if( rc==SQLITE_OK ){ /* Change to WRITER_LOCKED state. **