mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Add comments to clarify the purpose of the pager "error state".
FossilOrigin-Name: fde4c59782e98366792e1552fd122e7d80a277ff
This commit is contained in:
12
manifest
12
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Add\sstate\sdiagram\sto\scomments\sin\sexperimental\sversion\sof\spager.c.
|
C Add\scomments\sto\sclarify\sthe\spurpose\sof\sthe\spager\s"error\sstate".
|
||||||
D 2010-08-03T12:48:46
|
D 2010-08-03T15:57:10
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e
|
F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -156,7 +156,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
|||||||
F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e
|
F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e
|
||||||
F src/os_unix.c ae5ca8a6031380708f3fec7be325233d49944914
|
F src/os_unix.c ae5ca8a6031380708f3fec7be325233d49944914
|
||||||
F src/os_win.c 51cb62f76262d961ea4249489383d714501315a7
|
F src/os_win.c 51cb62f76262d961ea4249489383d714501315a7
|
||||||
F src/pager.c 24f978063ff3f18f1632b05b695717cc9818538a
|
F src/pager.c 809f4dfbca43fd64ef27855e193d8544a5054668
|
||||||
F src/pager.h 80726162dc3942f59ab27b738fb667b9ba0a89d5
|
F src/pager.h 80726162dc3942f59ab27b738fb667b9ba0a89d5
|
||||||
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
|
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
|
||||||
F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07
|
F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07
|
||||||
@@ -841,7 +841,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
|||||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||||
P 0a636798bdb6961a47327091715b254f79add823
|
P 16dcf5a6d3ebff9a734705693b5ac740f4ff2cc1
|
||||||
R b916884b782901df5d25760d516d1243
|
R f5f08ae2bf16feac4ddffb2e7526923b
|
||||||
U dan
|
U dan
|
||||||
Z a547af01cff05efb8820775070ecaafe
|
Z 158c2b787243a4910abe77703b2eb315
|
||||||
|
@@ -1 +1 @@
|
|||||||
16dcf5a6d3ebff9a734705693b5ac740f4ff2cc1
|
fde4c59782e98366792e1552fd122e7d80a277ff
|
103
src/pager.c
103
src/pager.c
@@ -140,6 +140,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
|
|||||||
** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted.
|
** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted.
|
||||||
**
|
**
|
||||||
** READER:
|
** READER:
|
||||||
|
**
|
||||||
** In this state all the requirements for reading the database in
|
** In this state all the requirements for reading the database in
|
||||||
** rollback (non-WAL) mode are met. Unless the pager is (or recently
|
** rollback (non-WAL) mode are met. Unless the pager is (or recently
|
||||||
** was) in exclusive-locking mode, a user-level read transaction is
|
** was) in exclusive-locking mode, a user-level read transaction is
|
||||||
@@ -152,12 +153,16 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
|
|||||||
** may not be trusted at this point.
|
** may not be trusted at this point.
|
||||||
**
|
**
|
||||||
** WRITER_INITIAL:
|
** WRITER_INITIAL:
|
||||||
|
**
|
||||||
** * A write transaction is active.
|
** * A write transaction is active.
|
||||||
** * A RESERVED or greater lock is held on the database file.
|
** * A RESERVED or greater lock is held on the database file.
|
||||||
** * The dbSize, dbOrigSize and dbFileSize variables are all valid.
|
** * The dbSize, dbOrigSize and dbFileSize variables are all valid.
|
||||||
** * The contents of the pager cache have not been modified.
|
** * The contents of the pager cache have not been modified.
|
||||||
|
** * The journal file may or may not be open.
|
||||||
|
** * Nothing (not even the first header) has been written to the journal.
|
||||||
**
|
**
|
||||||
** WRITER_CACHEMOD:
|
** WRITER_CACHEMOD:
|
||||||
|
**
|
||||||
** * A write transaction is active.
|
** * A write transaction is active.
|
||||||
** * A RESERVED or greater lock is held on the database file.
|
** * A RESERVED or greater lock is held on the database file.
|
||||||
** * The journal file is open and the first header has been written
|
** * The journal file is open and the first header has been written
|
||||||
@@ -165,6 +170,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
|
|||||||
** * The contents of the page cache have been modified.
|
** * The contents of the page cache have been modified.
|
||||||
**
|
**
|
||||||
** WRITER_DBMOD:
|
** WRITER_DBMOD:
|
||||||
|
**
|
||||||
** * A write transaction is active.
|
** * A write transaction is active.
|
||||||
** * An EXCLUSIVE or greater lock is held on the database file.
|
** * An EXCLUSIVE or greater lock is held on the database file.
|
||||||
** * The journal file is open and the first header has been written
|
** * The journal file is open and the first header has been written
|
||||||
@@ -173,6 +179,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
|
|||||||
** written to disk).
|
** written to disk).
|
||||||
**
|
**
|
||||||
** WRITER_FINISHED:
|
** WRITER_FINISHED:
|
||||||
|
**
|
||||||
** * A write transaction is active.
|
** * A write transaction is active.
|
||||||
** * An EXCLUSIVE or greater lock is held on the database file.
|
** * An EXCLUSIVE or greater lock is held on the database file.
|
||||||
** * All writing and syncing of journal and database data has finished.
|
** * All writing and syncing of journal and database data has finished.
|
||||||
@@ -180,12 +187,62 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
|
|||||||
** commit the transaction. If an error did occur, the caller will need
|
** commit the transaction. If an error did occur, the caller will need
|
||||||
** to rollback the transaction.
|
** to rollback the transaction.
|
||||||
**
|
**
|
||||||
|
** ERROR:
|
||||||
|
**
|
||||||
|
** The ERROR state is entered when an IO, OOM or disk-full error
|
||||||
|
** occurs at a point in the code that makes it difficult to be sure
|
||||||
|
** that the in-memory pager state (cache contents, db size etc.) are
|
||||||
|
** consistent with the contents of the file-system.
|
||||||
|
**
|
||||||
|
** For example, if an IO error occurs while performing a rollback,
|
||||||
|
** the contents of the page-cache may be left in an inconsistent state.
|
||||||
|
** At this point it would be dangerous to change back to READER state
|
||||||
|
** (as usually happens after a rollback). Any subsequent readers might
|
||||||
|
** report database corruption (due to the inconsistent cache), and if
|
||||||
|
** they upgrade to writers, they may inadvertently corrupt the database
|
||||||
|
** file. To avoid this hazard, the pager switches into the ERROR state
|
||||||
|
** instead of READER following such an error.
|
||||||
|
**
|
||||||
|
** Once it has entered the ERROR state, any attempt to use the pager
|
||||||
|
** to read or write data returns an error. Eventually, once all
|
||||||
|
** outstanding transactions have been abandoned, the pager is able to
|
||||||
|
** transition back to NONE state, discarding the contents of the
|
||||||
|
** page-cache and any other in-memory state at the same time. Everything
|
||||||
|
** is reloaded from disk (and, if necessary, hot-journal rollback peformed)
|
||||||
|
** when a read-transaction is next opened on the pager (transitioning
|
||||||
|
** the pager into READER state). At that point the system has recovered
|
||||||
|
** from the error.
|
||||||
|
**
|
||||||
|
** Specifically, the pager jumps into the ERROR state if:
|
||||||
|
**
|
||||||
|
** 1. An error occurs while attempting a rollback. This happens in
|
||||||
|
** function sqlite3PagerRollback().
|
||||||
|
**
|
||||||
|
** 2. An error occurs while attempting to finalize a journal file
|
||||||
|
** following a commit in function sqlite3PagerCommitPhaseTwo().
|
||||||
|
**
|
||||||
|
** 3. An error occurs while attempting to write to the journal or
|
||||||
|
** database file in function pagerStress() in order to free up
|
||||||
|
** memory.
|
||||||
|
**
|
||||||
|
** In other cases, the error is returned to the b-tree layer. The b-tree
|
||||||
|
** layer then attempts a rollback operation. If the error condition
|
||||||
|
** persists, the pager enters the ERROR state via condition (1) above.
|
||||||
|
**
|
||||||
|
** Condition (3) is necessary because it can be triggered by a read-only
|
||||||
|
** statement executed within a transaction. In this case, if the error
|
||||||
|
** code were simply returned to the user, the b-tree layer would not
|
||||||
|
** automatically attempt a rollback, as it assumes that an error in a
|
||||||
|
** read-only statement cannot leave the pager in an internally inconsistent
|
||||||
|
** state.
|
||||||
|
**
|
||||||
|
**
|
||||||
** State diagram:
|
** State diagram:
|
||||||
**
|
**
|
||||||
** NONE <-------------+
|
** NONE <------+------+
|
||||||
** | |
|
** | | |
|
||||||
** V |
|
** V | |
|
||||||
** +---------> READER------------->|
|
** +---------> READER-------+ |
|
||||||
** | | |
|
** | | |
|
||||||
** | V |
|
** | V |
|
||||||
** |<-------WRITER_INITIAL-----> ERROR
|
** |<-------WRITER_INITIAL-----> ERROR
|
||||||
@@ -1619,7 +1676,6 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
|
|||||||
|| (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
|
|| (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
|
||||||
){
|
){
|
||||||
rc = zeroJournalHdr(pPager, hasMaster);
|
rc = zeroJournalHdr(pPager, hasMaster);
|
||||||
pager_error(pPager, rc);
|
|
||||||
pPager->journalOff = 0;
|
pPager->journalOff = 0;
|
||||||
}else{
|
}else{
|
||||||
/* This branch may be executed with Pager.journalMode==MEMORY if
|
/* This branch may be executed with Pager.journalMode==MEMORY if
|
||||||
@@ -4327,7 +4383,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
|||||||
rc = pager_wait_on_lock(pPager, SHARED_LOCK);
|
rc = pager_wait_on_lock(pPager, SHARED_LOCK);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
assert( pPager->eLock==PAGER_UNLOCK );
|
assert( pPager->eLock==PAGER_UNLOCK );
|
||||||
return pager_error(pPager, rc);
|
goto failed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4358,7 +4414,6 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
|||||||
*/
|
*/
|
||||||
rc = pagerLock(pPager, EXCLUSIVE_LOCK);
|
rc = pagerLock(pPager, EXCLUSIVE_LOCK);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
rc = pager_error(pPager, rc);
|
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4411,6 +4466,10 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
|||||||
** it back since the process that crashed and left the hot journal
|
** it back since the process that crashed and left the hot journal
|
||||||
** probably did not sync it and we are required to always sync
|
** probably did not sync it and we are required to always sync
|
||||||
** the journal before playing it back.
|
** the journal before playing it back.
|
||||||
|
**
|
||||||
|
** Even if an error occurs while syncing or rolling back the
|
||||||
|
** hot-journal, there is no need to enter the ERROR state here, as
|
||||||
|
** the pager never left state NONE anyhow.
|
||||||
*/
|
*/
|
||||||
if( isOpen(pPager->jfd) ){
|
if( isOpen(pPager->jfd) ){
|
||||||
rc = pagerSyncHotJournal(pPager);
|
rc = pagerSyncHotJournal(pPager);
|
||||||
@@ -4420,7 +4479,6 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
|||||||
pPager->eState = PAGER_NONE;
|
pPager->eState = PAGER_NONE;
|
||||||
}
|
}
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
rc = pager_error(pPager, rc);
|
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@@ -4488,8 +4546,10 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
|||||||
|
|
||||||
failed:
|
failed:
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
/* pager_unlock() is a no-op for exclusive mode and in-memory databases. */
|
|
||||||
pager_unlock(pPager);
|
pager_unlock(pPager);
|
||||||
|
assert( (pPager->eState==PAGER_NONE)
|
||||||
|
|| (pPager->exclusiveMode && pagerUseWal(pPager))
|
||||||
|
);
|
||||||
}else{
|
}else{
|
||||||
pPager->eState = PAGER_READER;
|
pPager->eState = PAGER_READER;
|
||||||
}
|
}
|
||||||
@@ -5544,21 +5604,12 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
|
|||||||
** called, just return the same error code without doing anything. */
|
** called, just return the same error code without doing anything. */
|
||||||
if( NEVER(pPager->errCode) ) return pPager->errCode;
|
if( NEVER(pPager->errCode) ) return pPager->errCode;
|
||||||
|
|
||||||
/* This function should not be called if the pager is not in at least
|
|
||||||
** PAGER_RESERVED state. **FIXME**: Make it so that this test always
|
|
||||||
** fails - make it so that we never reach this point if we do not hold
|
|
||||||
** all necessary locks.
|
|
||||||
*/
|
|
||||||
assert( pPager->eState==PAGER_WRITER_INITIAL
|
assert( pPager->eState==PAGER_WRITER_INITIAL
|
||||||
|| pPager->eState==PAGER_WRITER_FINISHED
|
|| pPager->eState==PAGER_WRITER_FINISHED
|
||||||
|| (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD)
|
|| (pagerUseWal(pPager) && pPager->eState==PAGER_WRITER_CACHEMOD)
|
||||||
);
|
);
|
||||||
assert( assert_pager_state(pPager) );
|
assert( assert_pager_state(pPager) );
|
||||||
|
|
||||||
#if 0
|
|
||||||
if( NEVER(pPager->state<PAGER_RESERVED) ) return SQLITE_ERROR;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* An optimization. If the database was not actually modified during
|
/* An optimization. If the database was not actually modified during
|
||||||
** this transaction, the pager is running in exclusive-mode and is
|
** this transaction, the pager is running in exclusive-mode and is
|
||||||
** using persistent journals, then this function is a no-op.
|
** using persistent journals, then this function is a no-op.
|
||||||
@@ -5637,13 +5688,11 @@ int sqlite3PagerRollback(Pager *pPager){
|
|||||||
|
|
||||||
if( pagerUseWal(pPager) ){
|
if( pagerUseWal(pPager) ){
|
||||||
int rc2;
|
int rc2;
|
||||||
|
|
||||||
rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
|
rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
|
||||||
rc2 = pager_end_transaction(pPager, pPager->setMaster);
|
rc2 = pager_end_transaction(pPager, pPager->setMaster);
|
||||||
if( rc==SQLITE_OK ) rc = rc2;
|
if( rc==SQLITE_OK ) rc = rc2;
|
||||||
rc = pager_error(pPager, rc);
|
|
||||||
}else if( pPager->eState==PAGER_WRITER_INITIAL ){
|
}else if( pPager->eState==PAGER_WRITER_INITIAL ){
|
||||||
rc = pager_end_transaction(pPager, pPager->setMaster);
|
rc = pager_end_transaction(pPager, 0);
|
||||||
}else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
|
}else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
|
||||||
if( pPager->eState>=PAGER_WRITER_DBMOD ){
|
if( pPager->eState>=PAGER_WRITER_DBMOD ){
|
||||||
pager_playback(pPager, 0);
|
pager_playback(pPager, 0);
|
||||||
@@ -5660,14 +5709,12 @@ int sqlite3PagerRollback(Pager *pPager){
|
|||||||
}else{
|
}else{
|
||||||
rc = pager_playback(pPager, 0);
|
rc = pager_playback(pPager, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If an error occurs during a ROLLBACK, we can no longer trust the pager
|
|
||||||
** cache. So call pager_error() on the way out to make any error
|
|
||||||
** persistent.
|
|
||||||
*/
|
|
||||||
rc = pager_error(pPager, rc);
|
|
||||||
}
|
}
|
||||||
return rc;
|
|
||||||
|
/* If an error occurs during a ROLLBACK, we can no longer trust the pager
|
||||||
|
** cache. So call pager_error() on the way out to make any error persistent.
|
||||||
|
*/
|
||||||
|
return pager_error(pPager, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user