Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Set the Pager.eState variable to PAGER_ERROR whenever the pager enters the error state. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | experimental |
Files: | files | file ages | folders |
SHA1: |
4d384761d27425b71555f4f326277827 |
User & Date: | dan 2010-08-03 18:18:42.000 |
Context
2010-08-03
| ||
18:29 | Merge trunk changes into experimental branch. (check-in: 15368a9f85 user: dan tags: experimental) | |
18:18 | Set the Pager.eState variable to PAGER_ERROR whenever the pager enters the error state. (check-in: 4d384761d2 user: dan tags: experimental) | |
15:57 | Add comments to clarify the purpose of the pager "error state". (check-in: fde4c59782 user: dan tags: experimental) | |
Changes
Changes to src/pager.c.
︙ | ︙ | |||
287 288 289 290 291 292 293 294 295 296 297 298 299 300 | */ #define PAGER_NONE 0 #define PAGER_READER 1 #define PAGER_WRITER_INITIAL 2 #define PAGER_WRITER_CACHEMOD 3 #define PAGER_WRITER_DBMOD 4 #define PAGER_WRITER_FINISHED 5 /* ** The page cache as a whole is always in one of the following ** states: ** ** PAGER_UNLOCK The page cache is not currently reading or | > | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | */ #define PAGER_NONE 0 #define PAGER_READER 1 #define PAGER_WRITER_INITIAL 2 #define PAGER_WRITER_CACHEMOD 3 #define PAGER_WRITER_DBMOD 4 #define PAGER_WRITER_FINISHED 5 #define PAGER_ERROR 6 /* ** The page cache as a whole is always in one of the following ** states: ** ** PAGER_UNLOCK The page cache is not currently reading or |
︙ | ︙ | |||
692 693 694 695 696 697 698 699 700 701 702 703 704 705 | /* State must be valid. */ assert( p->eState==PAGER_NONE || p->eState==PAGER_READER || p->eState==PAGER_WRITER_INITIAL || p->eState==PAGER_WRITER_CACHEMOD || p->eState==PAGER_WRITER_DBMOD || p->eState==PAGER_WRITER_FINISHED ); /* Regardless of the current state, a temp-file connection always behaves ** as if it has an exclusive lock on the database file. It never updates ** the change-counter field, so the changeCountDone flag is always set. */ assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK ); | > | 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 | /* State must be valid. */ assert( p->eState==PAGER_NONE || p->eState==PAGER_READER || p->eState==PAGER_WRITER_INITIAL || p->eState==PAGER_WRITER_CACHEMOD || p->eState==PAGER_WRITER_DBMOD || p->eState==PAGER_WRITER_FINISHED || p->eState==PAGER_ERROR ); /* Regardless of the current state, a temp-file connection always behaves ** as if it has an exclusive lock on the database file. It never updates ** the change-counter field, so the changeCountDone flag is always set. */ assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK ); |
︙ | ︙ | |||
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 | /* Check that MEMDB implies noSync. */ assert( !MEMDB || p->noSync ); switch( p->eState ){ case PAGER_NONE: assert( !MEMDB ); assert( !p->tempFile ); break; case PAGER_READER: assert( p->eLock>=SHARED_LOCK || p->noReadlock ); break; case PAGER_WRITER_INITIAL: if( !pagerUseWal(pPager) ){ assert( p->eLock>=RESERVED_LOCK ); } assert( pPager->dbSize==pPager->dbOrigSize ); assert( pPager->dbOrigSize==pPager->dbFileSize ); break; case PAGER_WRITER_CACHEMOD: if( !pagerUseWal(pPager) ){ /* It is possible that if journal_mode=wal here that neither the ** journal file nor the WAL file are open. This happens during ** a rollback transaction that switches from journal_mode=off ** to journal_mode=wal. */ assert( p->eLock>=RESERVED_LOCK ); assert( isOpen(p->jfd) || p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_WAL ); } assert( pPager->dbOrigSize==pPager->dbFileSize ); break; case PAGER_WRITER_DBMOD: assert( !pagerUseWal(pPager) ); assert( p->eLock>=EXCLUSIVE_LOCK || pagerUseWal(pPager) ); assert( isOpen(p->jfd) || p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_WAL ); break; case PAGER_WRITER_FINISHED: assert( !pagerUseWal(pPager) ); assert( p->eLock>=EXCLUSIVE_LOCK || pagerUseWal(pPager) ); assert( isOpen(p->jfd) || p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_WAL ); break; } return 1; } /* ** (gdb) printf "%s", print_pager_state(pPager) | > > > > > > > > > > > > > > > > > | 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 | /* Check that MEMDB implies noSync. */ assert( !MEMDB || p->noSync ); switch( p->eState ){ case PAGER_NONE: assert( !MEMDB ); assert( !p->tempFile ); assert( pPager->errCode==SQLITE_OK ); assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); break; case PAGER_READER: assert( pPager->errCode==SQLITE_OK ); assert( p->eLock>=SHARED_LOCK || p->noReadlock ); break; case PAGER_WRITER_INITIAL: assert( pPager->errCode==SQLITE_OK ); if( !pagerUseWal(pPager) ){ assert( p->eLock>=RESERVED_LOCK ); } assert( pPager->dbSize==pPager->dbOrigSize ); assert( pPager->dbOrigSize==pPager->dbFileSize ); assert( pPager->setMaster==0 ); break; case PAGER_WRITER_CACHEMOD: assert( pPager->errCode==SQLITE_OK ); if( !pagerUseWal(pPager) ){ /* It is possible that if journal_mode=wal here that neither the ** journal file nor the WAL file are open. This happens during ** a rollback transaction that switches from journal_mode=off ** to journal_mode=wal. */ assert( p->eLock>=RESERVED_LOCK ); assert( isOpen(p->jfd) || p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_WAL ); } assert( pPager->dbOrigSize==pPager->dbFileSize ); break; case PAGER_WRITER_DBMOD: assert( pPager->errCode==SQLITE_OK ); assert( !pagerUseWal(pPager) ); assert( p->eLock>=EXCLUSIVE_LOCK || pagerUseWal(pPager) ); assert( isOpen(p->jfd) || p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_WAL ); break; case PAGER_WRITER_FINISHED: assert( pPager->errCode==SQLITE_OK ); assert( !pagerUseWal(pPager) ); assert( p->eLock>=EXCLUSIVE_LOCK || pagerUseWal(pPager) ); assert( isOpen(p->jfd) || p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_WAL ); break; case PAGER_ERROR: /* There must be at least one outstanding reference to the pager if ** in ERROR state. Otherwise the pager should have already dropped ** back to NONE state. */ assert( pPager->errCode!=SQLITE_OK ); assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); break; } return 1; } /* ** (gdb) printf "%s", print_pager_state(pPager) |
︙ | ︙ | |||
783 784 785 786 787 788 789 | "Journal mode: journal_mode=%s\n" "Backing store: tempFile=%d memDb=%d useJournal=%d\n" , p->eState==PAGER_NONE ? "NONE" : p->eState==PAGER_READER ? "READER" : p->eState==PAGER_WRITER_INITIAL ? "WRITER_INITIAL" : p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" : p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" : | | > | 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 | "Journal mode: journal_mode=%s\n" "Backing store: tempFile=%d memDb=%d useJournal=%d\n" , p->eState==PAGER_NONE ? "NONE" : p->eState==PAGER_READER ? "READER" : p->eState==PAGER_WRITER_INITIAL ? "WRITER_INITIAL" : p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" : p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" : p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" : p->eState==PAGER_ERROR ? "ERROR" : "?error?" , p->eLock==NO_LOCK ? "NONE" : p->eLock==RESERVED_LOCK ? "RESERVED" : p->eLock==EXCLUSIVE_LOCK ? "EXCLUSIVE" : p->eLock==SHARED_LOCK ? "SHARED" : "?error?" , p->exclusiveMode ? "exclusive" : "normal" , p->journalMode==PAGER_JOURNALMODE_MEMORY ? "memory" : p->journalMode==PAGER_JOURNALMODE_OFF ? "off" : |
︙ | ︙ | |||
1439 1440 1441 1442 1443 1444 1445 | ** fail, since no attempt to allocate dynamic memory will be made. */ (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p); return p; } /* | | < < < < | | < | 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 | ** fail, since no attempt to allocate dynamic memory will be made. */ (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p); return p; } /* ** Discard the entire contents of the in-memory page-cache. */ static void pager_reset(Pager *pPager){ sqlite3BackupRestart(pPager->pBackup); sqlite3PcacheClear(pPager->pPCache); } /* ** Free all structures in the Pager.aSavepoint[] array and set both ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal ** if it is open and the pager is not in exclusive mode. */ |
︙ | ︙ | |||
1501 1502 1503 1504 1505 1506 1507 | ** If the pager is currently in error state, discard the contents of ** the cache and reset the Pager structure internal state. If there is ** an open journal-file, then the next time a shared-lock is obtained ** on the pager file (by this or any other process), it will be ** treated as a hot-journal and rolled back. */ static void pager_unlock(Pager *pPager){ | > > > > > > > > > | < < < < < < < < < < | | < > > > > | < > > | > | | | > | | < < < | < < > | 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 | ** If the pager is currently in error state, discard the contents of ** the cache and reset the Pager structure internal state. If there is ** an open journal-file, then the next time a shared-lock is obtained ** on the pager file (by this or any other process), it will be ** treated as a hot-journal and rolled back. */ static void pager_unlock(Pager *pPager){ sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; releaseAllSavepoints(pPager); if( pagerUseWal(pPager) ){ assert( !isOpen(pPager->jfd) ); sqlite3WalEndReadTransaction(pPager->pWal); pPager->eState = PAGER_NONE; }else if( !pPager->exclusiveMode ){ int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0; /* If the operating system support deletion of open files, then ** close the journal file when dropping the database lock. Otherwise ** another connection with journal_mode=delete might delete the file ** out from under us. */ assert( (PAGER_JOURNALMODE_MEMORY & 5)!=1 ); assert( (PAGER_JOURNALMODE_OFF & 5)!=1 ); assert( (PAGER_JOURNALMODE_WAL & 5)!=1 ); assert( (PAGER_JOURNALMODE_DELETE & 5)!=1 ); assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 ); assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 ); if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN) || 1!=(pPager->journalMode & 5) ){ sqlite3OsClose(pPager->jfd); } osUnlock(pPager, NO_LOCK); /* The pager state may be changed from PAGER_ERROR to PAGER_NONE here ** without clearing the error code. This is intentional - the error ** code is cleared and the cache reset in the block below. */ assert( pPager->errCode || pPager->eState!=PAGER_ERROR ); pPager->changeCountDone = 0; pPager->eState = PAGER_NONE; IOTRACE(("UNLOCK %p\n", pPager)) } /* If Pager.errCode is set, the contents of the pager cache cannot be ** trusted. Now that there are no outstanding references to the pager, ** it can safely move back to PAGER_NONE state. This happens in both ** normal and exclusive-locking mode. */ if( pPager->errCode ){ pager_reset(pPager); pPager->changeCountDone = 0; pPager->eState = PAGER_NONE; pPager->errCode = SQLITE_OK; } } /* ** This function should be called when an IOERR, CORRUPT or FULL error ** may have occurred. The first argument is a pointer to the pager ** structure, the second the error-code about to be returned by a pager |
︙ | ︙ | |||
1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 | assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK || (pPager->errCode & 0xff)==SQLITE_IOERR ); if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ pPager->errCode = rc; } return rc; } /* ** This routine ends a transaction. A transaction is usually ended by ** either a COMMIT or a ROLLBACK operation. This routine may be called | > | 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 | assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK || (pPager->errCode & 0xff)==SQLITE_IOERR ); if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ pPager->errCode = rc; pPager->eState = PAGER_ERROR; } return rc; } /* ** This routine ends a transaction. A transaction is usually ended by ** either a COMMIT or a ROLLBACK operation. This routine may be called |
︙ | ︙ | |||
1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 | */ 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. */ assert( assert_pager_state(pPager) ); if( pPager->eState<PAGER_WRITER_INITIAL && pPager->eLock<RESERVED_LOCK ){ return SQLITE_OK; } releaseAllSavepoints(pPager); assert( isOpen(pPager->jfd) || pPager->pInJournal==0 ); if( isOpen(pPager->jfd) ){ | > | 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 | */ 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. */ assert( assert_pager_state(pPager) ); assert( pPager->eState!=PAGER_ERROR ); if( pPager->eState<PAGER_WRITER_INITIAL && pPager->eLock<RESERVED_LOCK ){ return SQLITE_OK; } releaseAllSavepoints(pPager); assert( isOpen(pPager->jfd) || pPager->pInJournal==0 ); if( isOpen(pPager->jfd) ){ |
︙ | ︙ | |||
1737 1738 1739 1740 1741 1742 1743 | ** ** If the pager has not already entered the error state, but an IO or ** malloc error occurs during a rollback, then this will itself cause ** the pager to enter the error state. Which will be cleared by the ** call to pager_unlock(), as described above. */ static void pagerUnlockAndRollback(Pager *pPager){ | | > | 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 | ** ** If the pager has not already entered the error state, but an IO or ** malloc error occurs during a rollback, then this will itself cause ** the pager to enter the error state. Which will be cleared by the ** call to pager_unlock(), as described above. */ static void pagerUnlockAndRollback(Pager *pPager){ if( pPager->eState!=PAGER_ERROR ){ assert( assert_pager_state(pPager) ); if( pPager->eState>=PAGER_WRITER_INITIAL ){ sqlite3BeginBenignMalloc(); sqlite3PagerRollback(pPager); sqlite3EndBenignMalloc(); }else if( pPager->eLock>=RESERVED_LOCK && !pPager->exclusiveMode ){ pager_end_transaction(pPager, 0); } |
︙ | ︙ | |||
2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 | ** the end of the new file instead. ** ** If successful, return SQLITE_OK. If an IO error occurs while modifying ** the database file, return the error code to the caller. */ static int pager_truncate(Pager *pPager, Pgno nPage){ int rc = SQLITE_OK; if( pPager->eState>=PAGER_WRITER_DBMOD && isOpen(pPager->fd) ){ i64 currentSize, newSize; /* TODO: Is it safe to use Pager.dbFileSize here? */ rc = sqlite3OsFileSize(pPager->fd, ¤tSize); newSize = pPager->pageSize*(i64)nPage; if( rc==SQLITE_OK && currentSize!=newSize ){ if( currentSize>newSize ){ | > | 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 | ** the end of the new file instead. ** ** If successful, return SQLITE_OK. If an IO error occurs while modifying ** the database file, return the error code to the caller. */ static int pager_truncate(Pager *pPager, Pgno nPage){ int rc = SQLITE_OK; assert( pPager->eState!=PAGER_ERROR ); if( pPager->eState>=PAGER_WRITER_DBMOD && isOpen(pPager->fd) ){ i64 currentSize, newSize; /* TODO: Is it safe to use Pager.dbFileSize here? */ rc = sqlite3OsFileSize(pPager->fd, ¤tSize); newSize = pPager->pageSize*(i64)nPage; if( rc==SQLITE_OK && currentSize!=newSize ){ if( currentSize>newSize ){ |
︙ | ︙ | |||
2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 | */ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){ i64 szJ; /* Effective size of the main journal */ i64 iHdrOff; /* End of first segment of main-journal records */ int rc = SQLITE_OK; /* Return code */ Bitvec *pDone = 0; /* Bitvec to ensure pages played back only once */ assert( pPager->eState>=PAGER_WRITER_INITIAL ); /* Allocate a bitvec to use to store the set of pages rolled back */ if( pSavepoint ){ pDone = sqlite3BitvecCreate(pSavepoint->nOrig); if( !pDone ){ return SQLITE_NOMEM; | > | 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 | */ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){ i64 szJ; /* Effective size of the main journal */ i64 iHdrOff; /* End of first segment of main-journal records */ int rc = SQLITE_OK; /* Return code */ Bitvec *pDone = 0; /* Bitvec to ensure pages played back only once */ assert( pPager->eState!=PAGER_ERROR ); assert( pPager->eState>=PAGER_WRITER_INITIAL ); /* Allocate a bitvec to use to store the set of pages rolled back */ if( pSavepoint ){ pDone = sqlite3BitvecCreate(pSavepoint->nOrig); if( !pDone ){ return SQLITE_NOMEM; |
︙ | ︙ | |||
3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 | ** If the page size is not changed, either because one of the enumerated ** conditions above is not true, the pager was in error state when this ** function was called, or because the memory allocation attempt failed, ** then *pPageSize is set to the old, retained page size before returning. */ int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize, int nReserve){ int rc = pPager->errCode; if( rc==SQLITE_OK ){ u16 pageSize = *pPageSize; assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); if( (pPager->memDb==0 || pPager->dbSize==0) && sqlite3PcacheRefCount(pPager->pPCache)==0 && pageSize && pageSize!=pPager->pageSize | > > > > > > | 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 | ** If the page size is not changed, either because one of the enumerated ** conditions above is not true, the pager was in error state when this ** function was called, or because the memory allocation attempt failed, ** then *pPageSize is set to the old, retained page size before returning. */ int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize, int nReserve){ int rc = pPager->errCode; /* It is not possible to do a full assert_pager_state() here, as this ** function may be called from within PagerOpen(), before the state ** of the Pager object is internally consistent. */ assert( rc==SQLITE_OK || pPager->eState==PAGER_ERROR ); if( rc==SQLITE_OK ){ u16 pageSize = *pPageSize; assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); if( (pPager->memDb==0 || pPager->dbSize==0) && sqlite3PcacheRefCount(pPager->pPCache)==0 && pageSize && pageSize!=pPager->pageSize |
︙ | ︙ | |||
3366 3367 3368 3369 3370 3371 3372 | ** to the caller. */ int sqlite3PagerClose(Pager *pPager){ u8 *pTmp = (u8 *)pPager->pTmpSpace; disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); | | < | | | | > > > > > > | | 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 | ** to the caller. */ int sqlite3PagerClose(Pager *pPager){ u8 *pTmp = (u8 *)pPager->pTmpSpace; disable_simulated_io_errors(); sqlite3BeginBenignMalloc(); /* pPager->errCode = 0; */ pPager->exclusiveMode = 0; #ifndef SQLITE_OMIT_WAL sqlite3WalClose(pPager->pWal, (pPager->noSync ? 0 : pPager->sync_flags), pPager->pageSize, pTmp ); pPager->pWal = 0; #endif pager_reset(pPager); if( MEMDB ){ pager_unlock(pPager); }else{ /* If it is open, sync the journal file before calling UnlockAndRollback. ** If this is not done, then an unsynced portion of the open journal ** file may be played back into the database. If a power failure occurs ** while this is happening, the database could become corrupt. ** ** If an error occurs while trying to sync the journal, shift the pager ** into the ERROR state. This causes UnlockAndRollback to unlock the ** database and close the journal file without attempting to roll it ** back or finalize it. The next database user will have to do hot-journal ** rollback before accessing the database file. */ if( isOpen(pPager->jfd) ){ pager_error(pPager, pagerSyncHotJournal(pPager)); } pagerUnlockAndRollback(pPager); } sqlite3EndBenignMalloc(); enable_simulated_io_errors(); PAGERTRACE(("CLOSE %d\n", PAGERID(pPager))); IOTRACE(("CLOSE %p\n", pPager)) |
︙ | ︙ | |||
4355 4356 4357 4358 4359 4360 4361 | ** exclusive access mode. */ assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_READER ); assert( assert_pager_state(pPager) ); if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; } | < < < < < < < < < < < < < < | 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 | ** exclusive access mode. */ assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_READER ); assert( assert_pager_state(pPager) ); if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; } if( !pagerUseWal(pPager) && pPager->eState==PAGER_NONE ){ sqlite3_vfs * const pVfs = pPager->pVfs; assert( !MEMDB && !pPager->tempFile ); assert( pPager->noReadlock==0 || pPager->readOnly ); if( pPager->noReadlock==0 ){ rc = pager_wait_on_lock(pPager, SHARED_LOCK); if( rc!=SQLITE_OK ){ assert( pPager->eLock==PAGER_UNLOCK ); goto failed; |
︙ | ︙ | |||
4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 | ** 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) ){ rc = pagerSyncHotJournal(pPager); if( rc==SQLITE_OK ){ pPager->eState = PAGER_WRITER_FINISHED; rc = pager_playback(pPager, 1); pPager->eState = PAGER_NONE; } if( rc!=SQLITE_OK ){ goto failed; } | > | 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 | ** 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) ){ rc = pagerSyncHotJournal(pPager); if( rc==SQLITE_OK ){ assert( pPager->eState==PAGER_NONE ); pPager->eState = PAGER_WRITER_FINISHED; rc = pager_playback(pPager, 1); pPager->eState = PAGER_NONE; } if( rc!=SQLITE_OK ){ goto failed; } |
︙ | ︙ | |||
4536 4537 4538 4539 4540 4541 4542 | } if( pagerUseWal(pPager) && rc==SQLITE_OK ){ rc = pagerBeginReadTransaction(pPager); } if( pPager->eState==PAGER_NONE && rc==SQLITE_OK ){ | < | < < | 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 | } if( pagerUseWal(pPager) && rc==SQLITE_OK ){ rc = pagerBeginReadTransaction(pPager); } if( pPager->eState==PAGER_NONE && rc==SQLITE_OK ){ rc = pagerPagecount(pPager, &pPager->dbSize); } failed: if( rc!=SQLITE_OK ){ pager_unlock(pPager); assert( pPager->eState==PAGER_NONE ); }else{ pPager->eState = PAGER_READER; } return rc; } /* |
︙ | ︙ | |||
4958 4959 4960 4961 4962 4963 4964 4965 | static int pager_write(PgHdr *pPg){ void *pData = pPg->pData; Pager *pPager = pPg->pPager; int rc = SQLITE_OK; /* This routine is not called unless a write-transaction has already ** been started. The journal file may or may not be open at this point. */ | > | > | > | < | 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 | static int pager_write(PgHdr *pPg){ void *pData = pPg->pData; Pager *pPager = pPg->pPager; int rc = SQLITE_OK; /* This routine is not called unless a write-transaction has already ** been started. The journal file may or may not be open at this point. ** It is never called in the ERROR state. */ assert( pPager->eState==PAGER_WRITER_INITIAL || pPager->eState==PAGER_WRITER_CACHEMOD || pPager->eState==PAGER_WRITER_DBMOD ); assert( assert_pager_state(pPager) ); /* If an error has been previously detected, report the same error ** again. This should not happen, but the check provides robustness. */ if( NEVER(pPager->errCode) ) return pPager->errCode; /* Higher-level routines never call this function if database is not ** writable. But check anyway, just for robustness. */ if( NEVER(pPager->readOnly) ) return SQLITE_PERM; CHECK_PAGE(pPg); |
︙ | ︙ | |||
5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 | int rc = SQLITE_OK; PgHdr *pPg = pDbPage; Pager *pPager = pPg->pPager; Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); assert( pPager->eState>=PAGER_WRITER_INITIAL ); assert( assert_pager_state(pPager) ); if( nPagePerSector>1 ){ Pgno nPageCount; /* Total number of pages in database file */ Pgno pg1; /* First page of the sector pPg is located on. */ int nPage = 0; /* Number of pages starting at pg1 to journal */ int ii; /* Loop counter */ | > | 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 | int rc = SQLITE_OK; PgHdr *pPg = pDbPage; Pager *pPager = pPg->pPager; Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); assert( pPager->eState>=PAGER_WRITER_INITIAL ); assert( pPager->eState!=PAGER_ERROR ); assert( assert_pager_state(pPager) ); if( nPagePerSector>1 ){ Pgno nPageCount; /* Total number of pages in database file */ Pgno pg1; /* First page of the sector pPg is located on. */ int nPage = 0; /* Number of pages starting at pg1 to journal */ int ii; /* Loop counter */ |
︙ | ︙ | |||
5404 5405 5406 5407 5408 5409 5410 | assert( pPager->eState==PAGER_WRITER_INITIAL || pPager->eState==PAGER_WRITER_CACHEMOD || pPager->eState==PAGER_WRITER_DBMOD ); assert( assert_pager_state(pPager) ); | < < < < < | 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 | assert( pPager->eState==PAGER_WRITER_INITIAL || pPager->eState==PAGER_WRITER_CACHEMOD || pPager->eState==PAGER_WRITER_DBMOD ); assert( assert_pager_state(pPager) ); /* If a prior error occurred, report that error again. */ if( pPager->errCode ) return pPager->errCode; PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", pPager->zFilename, zMaster, pPager->dbSize)); /* If no database changes have been made, return early. */ |
︙ | ︙ | |||
5678 5679 5680 5681 5682 5683 5684 | ** some other process can use it to restore the database state (by ** hot-journal rollback). */ int sqlite3PagerRollback(Pager *pPager){ int rc = SQLITE_OK; /* Return code */ PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager))); | | > > > > | < < < < < < < | < < < | < | < < > | 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 | ** some other process can use it to restore the database state (by ** hot-journal rollback). */ int sqlite3PagerRollback(Pager *pPager){ int rc = SQLITE_OK; /* Return code */ PAGERTRACE(("ROLLBACK %d\n", PAGERID(pPager))); /* PagerRollback() is a no-op if called in READER or NONE state. If ** the pager is already in the ERROR state, the rollback is not ** attempted here. Instead, the error code is returned to the caller. */ assert( assert_pager_state(pPager) ); if( pPager->eState==PAGER_ERROR ) return pPager->errCode; if( pPager->eState<=PAGER_READER ) return SQLITE_OK; if( pagerUseWal(pPager) ){ int rc2; rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1); rc2 = pager_end_transaction(pPager, pPager->setMaster); if( rc==SQLITE_OK ) rc = rc2; }else if( !isOpen(pPager->jfd) ){ rc = pager_end_transaction(pPager, 0); }else{ rc = pager_playback(pPager, 0); } assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK ); assert( rc==SQLITE_OK || rc==SQLITE_FULL || (rc&0xFF)==SQLITE_IOERR ); /* 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); } |
︙ | ︙ |