Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Getting ready to redo the journal file format. (CVS 210) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
42c2f3fe68c8a6bab96e035371ecd642 |
User & Date: | drh 2001-04-14 16:38:23.000 |
Context
2001-04-15
| ||
00:37 | Pager is working, mostly. (CVS 211) (check-in: f82fa7070a user: drh tags: trunk) | |
2001-04-14
| ||
16:38 | Getting ready to redo the journal file format. (CVS 210) (check-in: 42c2f3fe68 user: drh tags: trunk) | |
2001-04-12
| ||
23:21 | More testing (CVS 209) (check-in: 3bde128418 user: drh tags: trunk) | |
Changes
Changes to src/pager.c.
︙ | ︙ | |||
23 24 25 26 27 28 29 | ************************************************************************* ** This is the implementation of the page cache subsystem. ** ** The page cache is used to access a database file. The pager journals ** all writes in order to support rollback. Locking is used to limit ** access to one or more reader or on writer. ** | | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | ************************************************************************* ** This is the implementation of the page cache subsystem. ** ** The page cache is used to access a database file. The pager journals ** all writes in order to support rollback. Locking is used to limit ** access to one or more reader or on writer. ** ** @(#) $Id: pager.c,v 1.2 2001/04/14 16:38:23 drh Exp $ */ #include "pager.h" #include <fcntl.h> #include <sys/stat.h> #include <unistd.h> #include <assert.h> /* ** The page cache as a whole is always in one of the following ** states: ** ** SQLITE_UNLOCK The page cache is not currently reading or ** writing the database file. There is no ** data held in memory. This is the initial ** state. ** ** SQLITE_READLOCK The page cache is reading the database. ** Writing is not permitted. There can be ** multiple readers accessing the same database ** file at the same time. ** ** SQLITE_WRITELOCK The page cache is writing the database. ** Access is exclusive. No other processes or ** threads can be reading or writing while one ** process is writing. ** ** The page cache comes up in PCS_UNLOCK. The first time a |
︙ | ︙ | |||
68 69 70 71 72 73 74 | /* ** Each in-memory image of a page begins with the following header. */ struct PgHdr { Pager *pPager; /* The pager to which this page belongs */ Pgno pgno; /* The page number for this page */ | | | | | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | /* ** Each in-memory image of a page begins with the following header. */ struct PgHdr { Pager *pPager; /* The pager to which this page belongs */ Pgno pgno; /* The page number for this page */ PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */ int nRef; /* Number of users of this page */ PgHdr *pNext, *pPrev; /* Freelist of pages where nRef==0 */ char inJournal; /* TRUE if has been written to journal */ char dirty; /* TRUE if we need to write back changes */ /* SQLITE_PAGE_SIZE bytes of page data follow this header */ }; /* ** Convert a pointer to a PgHdr into a pointer to its data ** and back again. */ #define PGHDR_TO_DATA(P) ((void*)(&(P)[1])) #define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) /* ** The number of page numbers that will fit on one page. */ |
︙ | ︙ | |||
103 104 105 106 107 108 109 110 111 112 | */ struct Pager { char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ int fd, jfd; /* File descriptors for database and journal */ int nRef; /* Sum of PgHdr.nRef */ int dbSize; /* Number of pages in the file */ int jSize; /* Number of pages in the journal */ int nPage; /* Total number of in-memory pages */ int mxPage; /* Maximum number of pages to hold in cache */ | > > < > > | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | */ struct Pager { char *zFilename; /* Name of the database file */ char *zJournal; /* Name of the journal file */ int fd, jfd; /* File descriptors for database and journal */ int nRef; /* Sum of PgHdr.nRef */ int dbSize; /* Number of pages in the file */ int origDbSize; /* dbSize before the current change */ int jSize; /* Number of pages in the journal */ int nIdx; /* Number of entries in aIdx[] */ int nPage; /* Total number of in-memory pages */ int mxPage; /* Maximum number of pages to hold in cache */ char state; /* SQLITE_UNLOCK, _READLOCK or _WRITELOCK */ char ioErr; /* True if an I/O error has occurred */ PgHdr *pFirst, *pLast; /* List of free pages */ PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number of PgHdr */ Pgno aIdx[SQLITE_INDEX_SIZE]; /* Current journal index page */ }; /* ** Hash a page number */ #define sqlite_pager_hash(PN) ((PN)%N_PG_HASH) |
︙ | ︙ | |||
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 | ** The first time this routine is called, the pager creates a new ** journal and acquires a write lock on the database. If the write ** lock could not be acquired, this routine returns SQLITE_BUSY. The ** calling routine must check for that routine and be careful not to ** change any page data until this routine returns SQLITE_OK. */ int sqlite_pager_write(void *pData){ if( pPager->state==SQLITE_READLOCK ){ pPager->jfd = open(pPager->zJournal, O_RDWR|O_CREAT, 0644); if( pPager->jfd<0 ){ return SQLITE_CANTOPEN; } if( sqlite_pager_lock(pPager->jfd, 1) ){ close(pPager->jfd); pPager->jfd = -1; return SQLITE_BUSY; } sqlite_pager_unlock(pPager->fd); if( sqlite_pager_lock(pPager->fd, 1) ){ close(pPager->jfd); pPager->jfd = -1; pPager->state = SQLITE_UNLOCK; sqlite_pager_reset(pPager); return SQLITE_PROTOCOL; } pPager->state = SQLITE_WRITELOCK; | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > | 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 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 681 682 683 684 685 | ** The first time this routine is called, the pager creates a new ** journal and acquires a write lock on the database. If the write ** lock could not be acquired, this routine returns SQLITE_BUSY. The ** calling routine must check for that routine and be careful not to ** change any page data until this routine returns SQLITE_OK. */ int sqlite_pager_write(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); Pager *pPager = pPg->pPager; int rc; if( pPg->inJournal ){ return SQLITE_OK; } if( pPager->state==SQLITE_UNLOCK ){ return SQLITE_PROTOCOL; } if( pPager->state==SQLITE_READLOCK ){ pPager->jfd = open(pPager->zJournal, O_RDWR|O_CREAT, 0644); if( pPager->jfd<0 ){ return SQLITE_CANTOPEN; } if( sqlite_pager_lock(pPager->jfd, 1) ){ close(pPager->jfd); pPager->jfd = -1; return SQLITE_BUSY; } sqlite_pager_unlock(pPager->fd); if( sqlite_pager_lock(pPager->fd, 1) ){ close(pPager->jfd); pPager->jfd = -1; pPager->state = SQLITE_UNLOCK; sqlite_pager_reset(pPager); return SQLITE_PROTOCOL; } pPager->state = SQLITE_WRITELOCK; pPager->jSize = 1; pPager->aIdx[0] = pPager->dbSize; pPager->origDbSize = pPager->dbSize; pPager->nIdx = 1; } /* Write this page to the journal */ assert( pPager->jfd>=0 ); if( pPg->pgno >= pPager->origDbSize ){ sqlite_pager_seekpage(pPager->fd, pPg->pgno, SEEK_SET); rc = sqlite_pager_writepage(pPager->fd, pData); pPg->inJournal = 1; return rc; } pPager->aIdx[pPager->nIdx++] = pPg->pgno; sqlite_pager_seekpage(pPager->jfd, pPager->jSize++, SEEK_SET); rc = sqlite_pager_write(pPager->jfd, pData); pPg->inJournal = 1; if( pPager->nIdx==SQLITE_INDEX_SIZE ){ sqlite_pager_seekpage(pPager->jfd, pPager->idxPgno, SEEK_SET); rc = sqlite_pager_writepage(pPager->jfd, &pPager->aIdx); pPager->nIdx = 0; pPager->jSize++; } return rc; } /* ** Commit all changes to the database and release the write lock. */ int sqlite_pager_commit(Pager*){ int i, rc; PgHdr *pPg; assert( pPager->state==SQLITE_WRITELOCK ); assert( pPager->jfd>=0 ); memset(&pPager->aIdx[&pPager->nIdx], 0, (SQLITE_INDEX_SIZE - pPager->nIdx)*sizeof(Pgno)); sqlite_pager_seekpage(pPager->jfd, pPager->idxPgno, SEEK_SET); rc = sqlite_pager_writepage(pPager->jfd, &pPager->aIdx); if( fsync(pPager->jfd) ){ return SQLITE_IOERR; } for(i=0; i<N_PG_HASH; i++){ for(pPg=pPager->aHash[i]; pPg; pPg=pPg->pNextHash){ if( pPg->dirty==0 ) continue; rc = sqlite_pager_seekpage(pPager->fd, pPg->pgno, SEEK_SET); |
︙ | ︙ | |||
665 666 667 668 669 670 671 672 673 674 675 676 677 | ** Rollback all changes. The database falls back to read-only mode. ** All in-memory cache pages revert to their original data contents. ** The journal is deleted. */ int sqlite_pager_rollback(Pager *pPager){ int rc; if( pPager->state!=SQLITE_WRITELOCK ) return SQLITE_OK; rc = sqlite_pager_playback(pPager); if( rc!=SQLITE_OK ){ rc = sqlite_pager_unwritelock(pPager); } return rc; }; | > > > > | 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 | ** Rollback all changes. The database falls back to read-only mode. ** All in-memory cache pages revert to their original data contents. ** The journal is deleted. */ int sqlite_pager_rollback(Pager *pPager){ int rc; if( pPager->state!=SQLITE_WRITELOCK ) return SQLITE_OK; memset(&pPager->aIdx[&pPager->nIdx], 0, (SQLITE_INDEX_SIZE - pPager->nIdx)*sizeof(Pgno)); sqlite_pager_seekpage(pPager->jfd, pPager->idxPgno, SEEK_SET); rc = sqlite_pager_writepage(pPager->jfd, &pPager->aIdx); rc = sqlite_pager_playback(pPager); if( rc!=SQLITE_OK ){ rc = sqlite_pager_unwritelock(pPager); } return rc; }; |