Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add state diagram to comments in experimental version of pager.c. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | experimental |
Files: | files | file ages | folders |
SHA1: |
16dcf5a6d3ebff9a734705693b5ac740 |
User & Date: | dan 2010-08-03 12:48:46.000 |
Context
2010-08-03
| ||
15:57 | Add comments to clarify the purpose of the pager "error state". (check-in: fde4c59782 user: dan tags: experimental) | |
12:48 | Add state diagram to comments in experimental version of pager.c. (check-in: 16dcf5a6d3 user: dan tags: experimental) | |
06:42 | Incremental checkin on pager state refactoring. (check-in: 0a636798bd user: dan tags: experimental) | |
Changes
Changes to src/pager.c.
︙ | ︙ | |||
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | #define FILEHANDLEID(fd) ((int)fd) /* ** The Pager.eState variable stores the current 'state' of a pager. A ** pager may be in any one of the following six states: ** ** NONE: ** The pager starts up in this state. Nothing is guaranteed in this ** state - the file may or may not be locked and the database size is ** unknown. The database may not be read or written. ** ** * No read or write transaction is active. ** * Any lock, or no lock at all, may be held on the database file. ** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted. ** ** READER: ** In this state all the requirements for reading the database in ** rollback (non-WAL) mode are met. Unless the pager is (or recently ** was) in exclusive-locking mode, a user-level read transaction is ** open. The database size is known in this state. ** ** * A read transaction may be active. ** * A SHARED or greater lock is held on the database file. ** * The dbSize variable may be trusted (even if a user-level read | > | > | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | #define FILEHANDLEID(fd) ((int)fd) /* ** The Pager.eState variable stores the current 'state' of a pager. A ** pager may be in any one of the following six states: ** ** NONE: ** ** The pager starts up in this state. Nothing is guaranteed in this ** state - the file may or may not be locked and the database size is ** unknown. The database may not be read or written. ** ** * No read or write transaction is active. ** * Any lock, or no lock at all, may be held on the database file. ** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted. ** ** READER: ** In this state all the requirements for reading the database in ** rollback (non-WAL) mode are met. Unless the pager is (or recently ** was) in exclusive-locking mode, a user-level read transaction is ** open. The database size is known in this state. ** ** * A read transaction may be active. ** * A SHARED or greater lock is held on the database file. ** * The dbSize variable may be trusted (even if a user-level read ** transaction is not active). The dbOrigSize and dbFileSize variables ** may not be trusted at this point. ** ** WRITER_INITIAL: ** * A write transaction is active. ** * A RESERVED or greater lock is held on the database file. ** * The dbSize, dbOrigSize and dbFileSize variables are all valid. ** * The contents of the pager cache have not been modified. ** |
︙ | ︙ | |||
174 175 176 177 178 179 180 | ** * A write transaction is active. ** * An EXCLUSIVE or greater lock is held on the database file. ** * All writing and syncing of journal and database data has finished. ** If no error occured, all that remains is to finalize the journal to ** commit the transaction. If an error did occur, the caller will need ** to rollback the transaction. ** | > > > > > > > > > > > > > > > > > > > > | | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | ** * A write transaction is active. ** * An EXCLUSIVE or greater lock is held on the database file. ** * All writing and syncing of journal and database data has finished. ** If no error occured, all that remains is to finalize the journal to ** commit the transaction. If an error did occur, the caller will need ** to rollback the transaction. ** ** State diagram: ** ** NONE <-------------+ ** | | ** V | ** +---------> READER------------->| ** | | | ** | V | ** |<-------WRITER_INITIAL-----> ERROR ** | | ^ ** | V | ** |<------WRITER_CACHEMOD-------->| ** | | | ** | V | ** |<-------WRITER_DBMOD---------->| ** | | | ** | V | ** +<------WRITER_FINISHED-------->+ ** ** ** State transitions and the [function] that performs each: ** ** NONE -> READER [PagerSharedLock] ** READER -> WRITER_INITIAL [PagerBegin] ** WRITER_INITIAL -> WRITER_CACHEMOD [pager_open_journal] ** WRITER_CACHEMOD -> WRITER_DBMOD [syncJournal] ** WRITER_DBMOD -> WRITER_FINISHED [PagerCommitPhaseOne] ** |
︙ | ︙ | |||
324 325 326 327 328 329 330 | ** or SQLITE_FULL. Once one of the first three errors occurs, it persists ** and is returned as the result of every major pager API call. The ** SQLITE_FULL return code is slightly different. It persists only until the ** next successful rollback is performed on the pager cache. Also, ** SQLITE_FULL does not affect the sqlite3PagerGet() and sqlite3PagerLookup() ** APIs, they may still be used successfully. ** | | | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 | ** or SQLITE_FULL. Once one of the first three errors occurs, it persists ** and is returned as the result of every major pager API call. The ** SQLITE_FULL return code is slightly different. It persists only until the ** next successful rollback is performed on the pager cache. Also, ** SQLITE_FULL does not affect the sqlite3PagerGet() and sqlite3PagerLookup() ** APIs, they may still be used successfully. ** ** dbSize, dbOrigSize, dbFileSize ** ** Managing the size of the database file in pages is a little complicated. ** The variable Pager.dbSize contains the number of pages that the database ** image currently contains. As the database image grows or shrinks this ** variable is updated. The variable Pager.dbFileSize contains the number ** of pages in the database file. This may be different from Pager.dbSize ** if some pages have been appended to the database image but not yet written |
︙ | ︙ | |||
440 441 442 443 444 445 446 | ** operates. ** ** The 'state' variable is described in more detail along with the ** descriptions of the values it may take - PAGER_UNLOCK etc. Many of the ** other variables in this block are described in the comment directly ** above this class definition. */ | < < < < < < < | 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | ** operates. ** ** The 'state' variable is described in more detail along with the ** descriptions of the values it may take - PAGER_UNLOCK etc. Many of the ** other variables in this block are described in the comment directly ** above this class definition. */ u8 eState; /* Pager state (NONE, READER, WRITER_INITIAL..) */ u8 eLock; /* Current lock held on database file */ u8 changeCountDone; /* Set after incrementing the change-counter */ u8 setMaster; /* True if a m-j name has been written to jrnl */ u8 doNotSpill; /* Do not spill the cache when non-zero */ u8 doNotSyncSpill; /* Do not do a spill that requires jrnl sync */ u8 subjInMemory; /* True to use in-memory sub-journals */ Pgno dbSize; /* Number of pages in the database */ Pgno dbOrigSize; /* dbSize before the current transaction */ |
︙ | ︙ | |||
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 | assert( p->eLock>=SHARED_LOCK || p->noReadlock ); break; case PAGER_WRITER_INITIAL: if( !pagerUseWal(pPager) ){ assert( p->eLock>=RESERVED_LOCK ); } 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 ); } break; case PAGER_WRITER_DBMOD: assert( !pagerUseWal(pPager) ); assert( p->eLock>=EXCLUSIVE_LOCK || pagerUseWal(pPager) ); assert( isOpen(p->jfd) || p->journalMode==PAGER_JOURNALMODE_OFF | > > > | 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 | 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 |
︙ | ︙ | |||
698 699 700 701 702 703 704 | /* ** (gdb) printf "%s", print_pager_state(pPager) */ static char *print_pager_state(Pager *p){ static char zRet[1024]; sqlite3_snprintf(1024, zRet, | | | > | > > > > > > | | 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 | /* ** (gdb) printf "%s", print_pager_state(pPager) */ static char *print_pager_state(Pager *p){ static char zRet[1024]; sqlite3_snprintf(1024, zRet, "State: %s\n" "Lock: %s\n" "Locking mode: locking_mode=%s\n" "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" : "?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" : p->journalMode==PAGER_JOURNALMODE_DELETE ? "delete" : p->journalMode==PAGER_JOURNALMODE_PERSIST ? "persist" : p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" : p->journalMode==PAGER_JOURNALMODE_WAL ? "wal" : "?error?" , (int)p->tempFile, (int)p->memDb, (int)p->useJournal ); return zRet; } #endif /* |
︙ | ︙ | |||
2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 | } } nPage = (Pgno)(n / pPager->pageSize); if( nPage==0 && n>0 ){ nPage = 1; } } *pnPage = nPage; return SQLITE_OK; } /* ** Check if the *-wal file that corresponds to the database opened by pPager | > > > > > > > > > | 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 | } } nPage = (Pgno)(n / pPager->pageSize); if( nPage==0 && n>0 ){ nPage = 1; } } /* 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. */ if( nPage>pPager->mxPgno ){ pPager->mxPgno = (Pgno)nPage; } *pnPage = nPage; return SQLITE_OK; } /* ** Check if the *-wal file that corresponds to the database opened by pPager |
︙ | ︙ | |||
3041 3042 3043 3044 3045 3046 3047 | ** Attempt to set the maximum database page count if mxPage is positive. ** Make no changes if mxPage is zero or negative. And never reduce the ** maximum page count below the current size of the database. ** ** Regardless of mxPage, return the current maximum page count. */ int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ | < | < | | 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 | ** Attempt to set the maximum database page count if mxPage is positive. ** Make no changes if mxPage is zero or negative. And never reduce the ** maximum page count below the current size of the database. ** ** Regardless of mxPage, return the current maximum page count. */ int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ if( mxPage>0 ){ pPager->mxPgno = mxPage; } if( pPager->eState!=PAGER_NONE && pPager->mxPgno<pPager->dbSize ){ pPager->mxPgno = pPager->dbSize; } return pPager->mxPgno; } /* ** The following set of routines are used to disable the simulated ** I/O error mechanism. These routines are used to avoid simulated |
︙ | ︙ | |||
3112 3113 3114 3115 3116 3117 3118 | rc = SQLITE_OK; } } return rc; } /* | > | < > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 | rc = SQLITE_OK; } } return rc; } /* ** This function may only be called when a read-transaction is open on ** the pager. It returns the total number of pages in the database. ** ** However, if the file is between 1 and <page-size> bytes in size, then ** this is considered a 1 page file. */ int sqlite3PagerPagecount(Pager *pPager, int *pnPage){ assert( pPager->eState>=PAGER_SHARED ); assert( pPager->eState!=PAGER_WRITER_FINISHED ); *pnPage = (int)pPager->dbSize; return SQLITE_OK; } static int pagerLock(Pager *pPager, int eLock){ int rc; assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK ); |
︙ | ︙ | |||
3394 3395 3396 3397 3398 3399 3400 | } /* ** Sync the journal. In other words, make sure all the pages that have ** been written to the journal have actually reached the surface of the ** disk and can be restored in the event of a hot-journal rollback. ** | | | 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 | } /* ** Sync the journal. In other words, make sure all the pages that have ** been written to the journal have actually reached the surface of the ** disk and can be restored in the event of a hot-journal rollback. ** ** If the Pager.noSync flag is set, then this function is a no-op. ** Otherwise, the actions required depend on the journal-mode and the ** device characteristics of the the file-system, as follows: ** ** * If the journal file is an in-memory journal file, no action need ** be taken. ** ** * Otherwise, if the device does not support the SAFE_APPEND property, |
︙ | ︙ | |||
3424 3425 3426 3427 3428 3429 3430 | ** if( NOT SEQUENTIAL ) xSync(<journal file>); ** } ** ** If successful, this routine clears the PGHDR_NEED_SYNC flag of every ** page currently held in memory before returning SQLITE_OK. If an IO ** error is encountered, then the IO error code is returned to the caller. */ | | > | 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 | ** if( NOT SEQUENTIAL ) xSync(<journal file>); ** } ** ** If successful, this routine clears the PGHDR_NEED_SYNC flag of every ** page currently held in memory before returning SQLITE_OK. If an IO ** error is encountered, then the IO error code is returned to the caller. */ static int syncJournal(Pager *pPager, int newHdr){ int rc; /* Return code */ assert( pPager->eState==PAGER_WRITER_CACHEMOD || pPager->eState==PAGER_WRITER_DBMOD ); assert( assert_pager_state(pPager) ); assert( !pagerUseWal(pPager) ); rc = sqlite3PagerExclusiveLock(pPager); if( rc!=SQLITE_OK ) return rc; if( !pPager->noSync ){ assert( !pPager->tempFile ); if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){ |
︙ | ︙ | |||
3512 3513 3514 3515 3516 3517 3518 | PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); IOTRACE(("JSYNC %p\n", pPager)) rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags| (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) ); if( rc!=SQLITE_OK ) return rc; } | | > > > > | > | > | 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 | PAGERTRACE(("SYNC journal of %d\n", PAGERID(pPager))); IOTRACE(("JSYNC %p\n", pPager)) rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags| (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) ); if( rc!=SQLITE_OK ) return rc; } pPager->journalHdr = pPager->journalOff; if( newHdr && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ pPager->nRec = 0; rc = writeJournalHdr(pPager); } }else{ pPager->journalHdr = pPager->journalOff; } } /* Unless the pager is in noSync mode, the journal file was just ** successfully synced. Either way, clear the PGHDR_NEED_SYNC flag on ** all pages. */ sqlite3PcacheClearSyncFlags(pPager->pPCache); |
︙ | ︙ | |||
3588 3589 3590 3591 3592 3593 3594 | ** However it may be called in WRITER_CACHEMOD state if the page being ** written (and all other pages that reside on the same disk sector) was ** a free-list leaf page at the start of the transaction. In that case ** the database file is not really being modified, so it is Ok to write ** to it in CACHEMOD state. */ assert( !pagerUseWal(pPager) ); | | | | > > | 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 | ** However it may be called in WRITER_CACHEMOD state if the page being ** written (and all other pages that reside on the same disk sector) was ** a free-list leaf page at the start of the transaction. In that case ** the database file is not really being modified, so it is Ok to write ** to it in CACHEMOD state. */ assert( !pagerUseWal(pPager) ); assert( pPager->eState==PAGER_WRITER_DBMOD || pPager->eState==PAGER_WRITER_CACHEMOD ); assert( pPager->eState==PAGER_WRITER_DBMOD || (pList->pDirty==0 && pList->pgno<=pPager->dbFileSize) ); rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); /* If the file is a temp-file has not yet been opened, open it now. It ** is not possible for rc to be other than SQLITE_OK if this branch ** is taken, as pager_wait_on_lock() is a no-op for temp-files. */ |
︙ | ︙ | |||
3793 3794 3795 3796 3797 3798 3799 | if( rc==SQLITE_OK ){ rc = pagerWalFrames(pPager, pPg, 0, 0, 0); } }else{ /* Sync the journal file if required. */ if( pPg->flags&PGHDR_NEED_SYNC ){ | | < < < < < < < < | 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 | if( rc==SQLITE_OK ){ rc = pagerWalFrames(pPager, pPg, 0, 0, 0); } }else{ /* Sync the journal file if required. */ if( pPg->flags&PGHDR_NEED_SYNC ){ rc = syncJournal(pPager, 1); } /* If the page number of this page is larger than the current size of ** the database image, it may need to be written to the sub-journal. ** This is because the call to pager_write_pagelist() below will not ** actually write data to the file in this case. ** |
︙ | ︙ | |||
4620 4621 4622 4623 4624 4625 4626 | assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); PAGER_INCR(pPager->nHit); return SQLITE_OK; }else{ /* The pager cache has created a new page. Its content needs to ** be initialized. */ | < < < < < < | | 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 | assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); PAGER_INCR(pPager->nHit); return SQLITE_OK; }else{ /* The pager cache has created a new page. Its content needs to ** be initialized. */ PAGER_INCR(pPager->nMiss); pPg = *ppPage; pPg->pPager = pPager; /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page ** number greater than this, or the unused locking-page, is requested. */ if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){ rc = SQLITE_CORRUPT_BKPT; goto pager_acquire_err; } if( MEMDB || pPager->dbSize<(int)pgno || noContent || !isOpen(pPager->fd) ){ if( pgno>pPager->mxPgno ){ rc = SQLITE_FULL; goto pager_acquire_err; } if( noContent ){ /* Failure to set the bits in the InJournal bit-vectors is benign. ** It merely means that we might do some extra work to journal a |
︙ | ︙ | |||
4749 4750 4751 4752 4753 4754 4755 | ** ** Return SQLITE_OK if everything is successful. Otherwise, return ** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or ** an IO error code if opening or writing the journal file fails. */ static int pager_open_journal(Pager *pPager){ int rc = SQLITE_OK; /* Return code */ | < < < | | 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 | ** ** Return SQLITE_OK if everything is successful. Otherwise, return ** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or ** an IO error code if opening or writing the journal file fails. */ static int pager_open_journal(Pager *pPager){ int rc = SQLITE_OK; /* Return code */ sqlite3_vfs * const pVfs = pPager->pVfs; /* Local cache of vfs pointer */ assert( pPager->eState==PAGER_WRITER_INITIAL ); assert( assert_pager_state(pPager) ); assert( pPager->pInJournal==0 ); /* If already in the error state, this function is a no-op. But on ** the other hand, this routine is never called if we are already in ** an error state. */ if( NEVER(pPager->errCode) ) return pPager->errCode; if( !pagerUseWal(pPager) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize); if( pPager->pInJournal==0 ){ return SQLITE_NOMEM; } /* Open the journal file if it is not already open. */ if( !isOpen(pPager->jfd) ){ if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ |
︙ | ︙ | |||
4797 4798 4799 4800 4801 4802 4803 | /* Write the first journal header to the journal file and open ** the sub-journal if necessary. */ if( rc==SQLITE_OK ){ /* TODO: Check if all of these are really required. */ | < > | 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 | /* Write the first journal header to the journal file and open ** the sub-journal if necessary. */ if( rc==SQLITE_OK ){ /* TODO: Check if all of these are really required. */ pPager->nRec = 0; pPager->journalOff = 0; pPager->setMaster = 0; pPager->journalHdr = 0; rc = writeJournalHdr(pPager); } } if( rc!=SQLITE_OK ){ sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; }else{ assert( pPager->eState==PAGER_WRITER_INITIAL ); pPager->eState = PAGER_WRITER_CACHEMOD; } return rc; } /* |
︙ | ︙ | |||
4891 4892 4893 4894 4895 4896 4897 | ** when it has an open transaction, but never to DBMOD or FINISHED. ** This is because in those states the code to roll back savepoint ** transactions may copy data from the sub-journal into the database ** file as well as into the page cache. Which would be incorrect in ** WAL mode. */ pPager->eState = PAGER_WRITER_INITIAL; | | | 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 | ** when it has an open transaction, but never to DBMOD or FINISHED. ** This is because in those states the code to roll back savepoint ** transactions may copy data from the sub-journal into the database ** file as well as into the page cache. Which would be incorrect in ** WAL mode. */ pPager->eState = PAGER_WRITER_INITIAL; pPager->dbFileSize = pPager->dbOrigSize = pPager->dbSize; pPager->journalOff = 0; }else{ /* Ignore any IO error that occurs within pager_end_transaction(). The ** purpose of this call is to reset the internal state of the pager ** sub-system. It doesn't matter if the journal-file is not properly ** finalized at this point (since it is not a valid journal file anyway). */ |
︙ | ︙ | |||
4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 | ** yet be open. Open it now if this is the case. */ if( pPager->eState==PAGER_WRITER_INITIAL ){ rc = pager_open_journal(pPager); if( rc!=SQLITE_OK ) return rc; } assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); /* The transaction journal now exists and we have a RESERVED or an ** EXCLUSIVE lock on the main database file. Write the current page to ** the transaction journal if it is not there already. */ | > | | | | 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 | ** yet be open. Open it now if this is the case. */ if( pPager->eState==PAGER_WRITER_INITIAL ){ rc = pager_open_journal(pPager); if( rc!=SQLITE_OK ) return rc; } assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); assert( assert_pager_state(pPager) ); /* The transaction journal now exists and we have a RESERVED or an ** EXCLUSIVE lock on the main database file. Write the current page to ** the transaction journal if it is not there already. */ if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){ assert( pagerUseWal(pPager)==0 ); if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){ u32 cksum; char *pData2; /* We should never write to the journal file the page that ** contains the database locks. The following assert verifies ** that we do not. */ assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); |
︙ | ︙ | |||
5006 5007 5008 5009 5010 5011 5012 | /* Even if an IO or diskfull error occurred while journalling the ** page in the block above, set the need-sync flag for the page. ** Otherwise, when the transaction is rolled back, the logic in ** playback_one_page() will think that the page needs to be restored ** in the database file. And if an IO error occurs while doing so, ** then corruption may follow. */ | < | < | | 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 | /* Even if an IO or diskfull error occurred while journalling the ** page in the block above, set the need-sync flag for the page. ** Otherwise, when the transaction is rolled back, the logic in ** playback_one_page() will think that the page needs to be restored ** in the database file. And if an IO error occurs while doing so, ** then corruption may follow. */ pPg->flags |= PGHDR_NEED_SYNC; /* An error has occurred writing to the journal file. The ** transaction will be rolled back by the layer above. */ if( rc!=SQLITE_OK ){ return rc; } pPager->nRec++; assert( pPager->pInJournal!=0 ); rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); testcase( rc==SQLITE_NOMEM ); assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); rc |= addToSavepointBitvecs(pPager, pPg->pgno); if( rc!=SQLITE_OK ){ assert( rc==SQLITE_NOMEM ); return rc; } }else{ if( pPager->eState!=PAGER_WRITER_DBMOD ){ pPg->flags |= PGHDR_NEED_SYNC; } PAGERTRACE(("APPEND %d page %d needSync=%d\n", PAGERID(pPager), pPg->pgno, ((pPg->flags&PGHDR_NEED_SYNC)?1:0))); } } |
︙ | ︙ | |||
5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 | int sqlite3PagerWrite(DbPage *pDbPage){ int rc = SQLITE_OK; PgHdr *pPg = pDbPage; Pager *pPager = pPg->pPager; Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); 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 */ int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ | > > > | 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 | int sqlite3PagerWrite(DbPage *pDbPage){ 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 */ int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */ |
︙ | ︙ | |||
5097 5098 5099 5100 5101 5102 5103 | /* 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. */ pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; | | < | | | | | | | | | | < | 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 | /* 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. */ pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; nPageCount = pPager->dbSize; if( pPg->pgno>nPageCount ){ nPage = (pPg->pgno - pg1)+1; }else if( (pg1+nPagePerSector-1)>nPageCount ){ nPage = nPageCount+1-pg1; }else{ nPage = nPagePerSector; } assert(nPage>0); assert(pg1<=pPg->pgno); assert((pg1+nPage)>pPg->pgno); for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){ Pgno pg = pg1+ii; PgHdr *pPage; if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ if( pg!=PAGER_MJ_PGNO(pPager) ){ rc = sqlite3PagerGet(pPager, pg, &pPage); |
︙ | ︙ | |||
5508 5509 5510 5511 5512 5513 5514 | ** Because the change-counter page was just modified, unless the ** atomic-update optimization is used it is almost certain that the ** journal requires a sync here. However, in locking_mode=exclusive ** on a system under memory pressure it is just possible that this is ** not the case. In this case it is likely enough that the redundant ** xSync() call will be changed to a no-op by the OS anyhow. */ | | | 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 | ** Because the change-counter page was just modified, unless the ** atomic-update optimization is used it is almost certain that the ** journal requires a sync here. However, in locking_mode=exclusive ** on a system under memory pressure it is just possible that this is ** not the case. In this case it is likely enough that the redundant ** xSync() call will be changed to a no-op by the OS anyhow. */ rc = syncJournal(pPager, 0); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); if( rc!=SQLITE_OK ){ assert( rc!=SQLITE_IOERR_BLOCKED ); goto commit_phase_one_exit; } |
︙ | ︙ | |||
5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 | ** If a memory allocation fails, SQLITE_NOMEM is returned. If an error ** occurs while opening the sub-journal file, then an IO error code is ** returned. Otherwise, SQLITE_OK. */ int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ int rc = SQLITE_OK; /* Return code */ int nCurrent = pPager->nSavepoint; /* Current number of savepoints */ if( nSavepoint>nCurrent && pPager->useJournal ){ int ii; /* Iterator variable */ PagerSavepoint *aNew; /* New Pager.aSavepoint array */ | > > > < < < < | | | 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 | ** If a memory allocation fails, SQLITE_NOMEM is returned. If an error ** occurs while opening the sub-journal file, then an IO error code is ** returned. Otherwise, SQLITE_OK. */ int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){ int rc = SQLITE_OK; /* Return code */ int nCurrent = pPager->nSavepoint; /* Current number of savepoints */ assert( pPager->eState>=PAGER_WRITER_INITIAL ); assert( assert_pager_state(pPager) ); if( nSavepoint>nCurrent && pPager->useJournal ){ int ii; /* Iterator variable */ PagerSavepoint *aNew; /* New Pager.aSavepoint array */ /* Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM ** if the allocation fails. Otherwise, zero the new portion in case a ** malloc failure occurs while populating it in the for(...) loop below. */ aNew = (PagerSavepoint *)sqlite3Realloc( pPager->aSavepoint, sizeof(PagerSavepoint)*nSavepoint ); if( !aNew ){ return SQLITE_NOMEM; } memset(&aNew[nCurrent], 0, (nSavepoint-nCurrent) * sizeof(PagerSavepoint)); pPager->aSavepoint = aNew; /* Populate the PagerSavepoint structures just allocated. */ for(ii=nCurrent; ii<nSavepoint; ii++){ aNew[ii].nOrig = pPager->dbSize; if( isOpen(pPager->jfd) && pPager->journalOff>0 ){ aNew[ii].iOffset = pPager->journalOff; }else{ aNew[ii].iOffset = JOURNAL_HDR_SZ(pPager); } aNew[ii].iSubRec = pPager->nSubRec; aNew[ii].pInSavepoint = sqlite3BitvecCreate(pPager->dbSize); if( !aNew[ii].pInSavepoint ){ return SQLITE_NOMEM; } if( pagerUseWal(pPager) ){ sqlite3WalSavepoint(pPager->pWal, aNew[ii].aWalData); } pPager->nSavepoint = ii+1; |
︙ | ︙ |