diff --git a/manifest b/manifest index 370ebbaa8d..c01d4989ca 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C fix\sa\stypo\son\sthe\squickstart.html\spage.\s(CVS\s843) -D 2003-01-21T23:06:58 +C Minor\srefinements\sto\sthe\spager.\s(CVS\s844) +D 2003-01-22T01:26:44 F Makefile.in 6606854b1512f185b8e8c779b8d7fc2750463d64 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -33,7 +33,7 @@ F src/main.c ad3193c56da5acd31bc6cd48aa50dae1962d7c78 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565 F src/os.c ed27e178e0c4b71f2807da81b8851f0fadc50778 F src/os.h afa3e096213bad86845f8bdca81a9e917505e401 -F src/pager.c f35799e6c5d9dbb9701f3a8945a557a34b8e4850 +F src/pager.c 82148bde7a080caab5f1c9ccec921275a14306dc F src/pager.h 540833e8cb826b80ce2e39aa917deee5e12db626 F src/parse.y a4fbfbe3c4254c96dae8c33264fb54af755a3770 F src/printf.c e8e9a0605602cb1a3a2dc754e0978fa9064ecee7 @@ -154,7 +154,7 @@ F www/speed.tcl 52759968401d81760fc01f9d3ab6242f6d2a7066 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 00f08fc0b5b6b9c5efbf15a62f9a1cc1cfa71283 -R 62a55b3f1eb6c2e886fabe1e2c0c925a +P 61869bb51b981a47d783cc8739833cc0c4733b0a +R c183df5a3160c5a0bd4aa1d31253edd6 U drh -Z 0e6e33b12aee37e6d243a0b7bc8099cc +Z fa8ef383d1b8461b08c239cde8f9cd63 diff --git a/manifest.uuid b/manifest.uuid index d9298db45b..b430c6e74d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -61869bb51b981a47d783cc8739833cc0c4733b0a \ No newline at end of file +19221dee5fee4c8800cbae309f009964c8d646a2 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 0d18bd2eed..03be78c565 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.69 2003/01/21 02:39:37 drh Exp $ +** @(#) $Id: pager.c,v 1.70 2003/01/22 01:26:44 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" @@ -99,6 +99,7 @@ struct PgHdr { u8 dirty; /* TRUE if we need to write back changes */ u8 needSync; /* Sync journal before writing this page */ u8 alwaysRollback; /* Disable dont_rollback() for this page */ + PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */ /* SQLITE_PAGE_SIZE bytes of page data follow this header */ /* Pager.nExtra bytes of local data follow the page data */ }; @@ -268,6 +269,24 @@ static int write32bits(OsFile *fd, u32 val){ return sqliteOsWrite(fd, ac, 4); } +/* +** Write a 32-bit integer into a page header right before the +** page data. This will overwrite the PgHdr.pDirty pointer. +*/ +static void storePageNumber(PgHdr *p){ + u32 val = p->pgno; + unsigned char *ac; + ac = &((char*)PGHDR_TO_DATA(p))[-4]; + if( pager_old_format ){ + memcpy(ac, &val, 4); + }else{ + ac[0] = (val>>24) & 0xff; + ac[1] = (val>>16) & 0xff; + ac[2] = (val>>8) & 0xff; + ac[3] = val & 0xff; + } +} + /* ** Convert the bits in the pPager->errMask into an approprate @@ -930,12 +949,49 @@ static int syncAllPages(Pager *pPager){ assert( pPager->pFirstSynced==pPager->pFirst ); } #endif - - return rc; } +/* +** Given a list of pages (connected by the PgHdr.pDirty pointer) write +** every one of those pages out to the database file and mark them all +** as clean. +*/ +static int pager_write_pagelist(PgHdr *pList){ + Pager *pPager; + int rc; + + if( pList==0 ) return SQLITE_OK; + pPager = pList->pPager; + while( pList ){ + assert( pList->dirty ); + sqliteOsSeek(&pPager->fd, (pList->pgno-1)*(off_t)SQLITE_PAGE_SIZE); + rc = sqliteOsWrite(&pPager->fd, PGHDR_TO_DATA(pList), SQLITE_PAGE_SIZE); + if( rc ) return rc; + pList->dirty = 0; + pList = pList->pDirty; + } + return SQLITE_OK; +} + +/* +** Collect every dirty page into a dirty list and +** return a pointer to the head of that list. All pages are +** collected even if they are still in use. +*/ +static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ + PgHdr *p, *pList; + pList = 0; + for(p=pPager->pAll; p; p=p->pNextAll){ + if( p->dirty ){ + p->pDirty = pList; + pList = p; + } + } + return pList; +} + /* ** Acquire a page. ** @@ -1078,15 +1134,13 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ */ if( pPg->dirty ){ assert( pPg->needSync==0 ); - TRACE2("SAVE %d\n", pPg->pgno); - sqliteOsSeek(&pPager->fd, (pPg->pgno-1)*(off_t)SQLITE_PAGE_SIZE); - rc = sqliteOsWrite(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE); + pPg->pDirty = 0; + rc = pager_write_pagelist( pPg ); if( rc!=SQLITE_OK ){ sqlitepager_rollback(pPager); *ppPage = 0; return SQLITE_IOERR; } - pPg->dirty = 0; } assert( pPg->dirty==0 ); @@ -1435,10 +1489,8 @@ int sqlitepager_write(void *pData){ */ if( !pPg->inJournal && pPager->useJournal ){ if( (int)pPg->pgno <= pPager->origDbSize ){ - rc = write32bits(&pPager->jfd, pPg->pgno); - if( rc==SQLITE_OK ){ - rc = sqliteOsWrite(&pPager->jfd, pData, SQLITE_PAGE_SIZE); - } + storePageNumber(pPg); + rc = sqliteOsWrite(&pPager->jfd, &((char*)pData)[-4], SQLITE_PAGE_SIZE+4); if( rc!=SQLITE_OK ){ sqlitepager_rollback(pPager); pPager->errMask |= PAGER_ERR_FULL; @@ -1467,10 +1519,8 @@ int sqlitepager_write(void *pData){ */ if( pPager->ckptInUse && !pPg->inCkpt && (int)pPg->pgno<=pPager->ckptSize ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); - rc = write32bits(&pPager->cpfd, pPg->pgno); - if( rc==SQLITE_OK ){ - rc = sqliteOsWrite(&pPager->cpfd, pData, SQLITE_PAGE_SIZE); - } + storePageNumber(pPg); + rc = sqliteOsWrite(&pPager->cpfd, &((char*)pData)[-4], SQLITE_PAGE_SIZE+4); if( rc!=SQLITE_OK ){ sqlitepager_rollback(pPager); pPager->errMask |= PAGER_ERR_FULL; @@ -1586,7 +1636,6 @@ void sqlitepager_dont_rollback(void *pData){ int sqlitepager_commit(Pager *pPager){ int rc; PgHdr *pPg; - int dbChanged; if( pPager->errMask==PAGER_ERR_FULL ){ rc = sqlitepager_rollback(pPager); @@ -1615,17 +1664,12 @@ int sqlitepager_commit(Pager *pPager){ if( pPager->needSync && sqliteOsSync(&pPager->jfd)!=SQLITE_OK ){ goto commit_abort; } - dbChanged = 0; - for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ - if( pPg->dirty==0 ) continue; - TRACE2("COMMIT-PAGE %d\n", pPg->pgno); - sqliteOsSeek(&pPager->fd, (pPg->pgno-1)*(off_t)SQLITE_PAGE_SIZE); - rc = sqliteOsWrite(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE); - if( rc!=SQLITE_OK ) goto commit_abort; - dbChanged = 1; - } - if( dbChanged && !pPager->noSync && sqliteOsSync(&pPager->fd)!=SQLITE_OK ){ - goto commit_abort; + pPg = pager_get_all_dirty_pages(pPager); + if( pPg ){ + rc = pager_write_pagelist(pPg); + if( rc || (!pPager->noSync && sqliteOsSync(&pPager->fd)!=SQLITE_OK) ){ + goto commit_abort; + } } rc = pager_unwritelock(pPager); pPager->dbSize = -1;