diff --git a/manifest b/manifest index 1ae29a1ab6..ec3deff973 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\snew\sOS\sfile\smethod\sto\sreturn\sthe\ssector-size\sof\sthe\sunderlying\sstorage:\ssqlite3OsSectorSize()\s(CVS\s3700) -D 2007-03-19T05:54:49 +C Changes\sto\ssupport\smedium\ssector\ssizes\slarger\sthan\sthe\sdatabase\spage\ssize.\s(CVS\s3701) +D 2007-03-19T11:25:20 F Makefile.in 1fe3d0b46e40fd684e1e61f8e8056cefed16de9f F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -58,7 +58,7 @@ F src/alter.c 2c79ec40f65e33deaf90ca493422c74586e481a3 F src/analyze.c 7d2b7ab9a9c2fd6e55700f69064dfdd3e36d7a8a F src/attach.c fd286a9140a2df84b1482f052b67ff5fad9569a1 F src/auth.c 902f4722661c796b97f007d9606bd7529c02597f -F src/btree.c f5c1b3d88ad62ab4682de37229168a00b87fc948 +F src/btree.c 4336ada77332acb947af6d382f0f3648ea9d8b6c F src/btree.h 066444ee25bd6e6accb997bfd2cf5ace14dbcd00 F src/build.c f2edc786b5bf165a7d0949ed3a5872455a610c0e F src/callback.c 31d22b4919c7645cbcbb1591ce2453e8c677c558 @@ -86,7 +86,7 @@ F src/os_unix.c 33ee7c1483fbd4d67cf5638c87622c277442b744 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e F src/os_win.c f3ca3e08167eb3382781b840e787809eccb626dc F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c 097923484be9edfb238920ad61583ad98ef3bbb3 +F src/pager.c c276e9de4e77d1c3d72367a7e207fa82e0e74af3 F src/pager.h 8881591ca23d1e5fd83c95fa8317245fbcf64227 F src/parse.y bcfe366c1fd61cfc40e5344eb69a31997a821af0 F src/pragma.c b52dcf2fbb46f3266f9d00b88054c684df3af2e7 @@ -437,7 +437,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P d42c9636205a1a649cffcaeabff2b9b32016db31 -R aace24c3ad1a66792ced6daa5ca6df05 +P 5752d84d374205e011d49b0221d6237967fe0743 +R 35e0cdc81bf64a560c8bcc30c7e3b7e8 U danielk1977 -Z a82901bb045246e4e447c22d214c62f4 +Z 835c96473334a1bbc531e7fce3e63932 diff --git a/manifest.uuid b/manifest.uuid index 66f0c8e970..4a1553172f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5752d84d374205e011d49b0221d6237967fe0743 \ No newline at end of file +3a3e8eb25d8e04cfccc5c0513ed04efcc25d3dbf \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index f99277402a..fe04ddc9ac 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.338 2007/03/06 15:53:44 drh Exp $ +** $Id: btree.c,v 1.339 2007/03/19 11:25:20 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -4031,8 +4031,8 @@ static int reparentPage(BtShared *pBt, Pgno pgno, MemPage *pNewParent, int idx){ aData = sqlite3pager_lookup(pBt->pPager, pgno); if( aData ){ pThis = (MemPage*)&aData[pBt->pageSize]; - assert( pThis->aData==aData ); if( pThis->isInit ){ + assert( pThis->aData==aData ); if( pThis->pParent!=pNewParent ){ if( pThis->pParent ) sqlite3pager_unref(pThis->pParent->aData); pThis->pParent = pNewParent; diff --git a/src/pager.c b/src/pager.c index 0565898c83..b2ada00419 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.289 2007/03/19 05:54:49 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.290 2007/03/19 11:25:20 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -285,6 +285,7 @@ struct Pager { Pager *pNext; /* Linked list of pagers in this thread */ #endif char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ + int doNotSync; }; /* @@ -628,14 +629,16 @@ static int seekJournalHdr(Pager *pPager){ */ static int writeJournalHdr(Pager *pPager){ char zHeader[sizeof(aJournalMagic)+16]; + int rc; - int rc = seekJournalHdr(pPager); + if( pPager->stmtHdrOff==0 ){ + pPager->stmtHdrOff = pPager->journalOff; + } + + rc = seekJournalHdr(pPager); if( rc ) return rc; pPager->journalHdr = pPager->journalOff; - if( pPager->stmtHdrOff==0 ){ - pPager->stmtHdrOff = pPager->journalHdr; - } pPager->journalOff += JOURNAL_HDR_SZ(pPager); /* FIX ME: @@ -1422,8 +1425,9 @@ static int pager_stmt_playback(Pager *pPager){ } #endif - /* Set hdrOff to be the offset to the first journal header written - ** this statement transaction, or the end of the file if no journal + /* Set hdrOff to be the offset just after the end of the last journal + ** page written before the first journal-header for this statement + ** transaction was written, or the end of the file if no journal ** header was written. */ hdrOff = pPager->stmtHdrOff; @@ -1471,8 +1475,7 @@ static int pager_stmt_playback(Pager *pPager){ } pPager->journalOff = pPager->stmtJSize; pPager->cksumInit = pPager->stmtCksum; - assert( JOURNAL_HDR_SZ(pPager)<(pPager->pageSize+8) ); - while( pPager->journalOff <= (hdrOff-(pPager->pageSize+8)) ){ + while( pPager->journalOff < hdrOff ){ rc = pager_playback_one_page(pPager, pPager->jfd, 1); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK ) goto end_stmt_playback; @@ -2479,6 +2482,7 @@ static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){ */ pPager->nRec = 0; assert( pPager->journalOff > 0 ); + assert( pPager->doNotSync==0 ); rc = writeJournalHdr(pPager); if( rc!=0 ){ return rc; @@ -2731,7 +2735,9 @@ int sqlite3pager_acquire(Pager *pPager, Pgno pgno, void **ppPage, int clrFlag){ /* The requested page is not in the page cache. */ int h; TEST_INCR(pPager->nMiss); - if( pPager->nPagemxPage || pPager->pFirst==0 || MEMDB ){ + if( pPager->nPagemxPage || pPager->pFirst==0 || MEMDB || + (pPager->pFirstSynced==0 && pPager->doNotSync) + ){ /* Create a new page */ if( pPager->nPage>=pPager->nHash ){ pager_resize_hash_table(pPager, @@ -3104,7 +3110,7 @@ static void makeClean(PgHdr *pPg){ ** is a call to sqlite3pager_commit() or sqlite3pager_rollback() to ** reset. */ -int sqlite3pager_write(void *pData){ +static int pager_write(void *pData){ PgHdr *pPg = DATA_TO_PGHDR(pData); Pager *pPager = pPg->pPager; int rc = SQLITE_OK; @@ -3258,6 +3264,77 @@ int sqlite3pager_write(void *pData){ return rc; } +/* +** This function is used to mark a data-page as writable. It uses +** pager_write() to open a journal file (if it is not already open) +** and write the page *pData to the journal. +** +** The difference between this function and pager_write() is that this +** function also deals with the special case where 2 or more pages +** fit on a single disk sector. In this case all co-resident pages +** must have been written to the journal file before returning. +*/ +int sqlite3pager_write(void *pData){ + int rc = SQLITE_OK; + + PgHdr *pPg = DATA_TO_PGHDR(pData); + Pager *pPager = pPg->pPager; + Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); + + if( !MEMDB && nPagePerSector>1 ){ + Pgno nPageCount; /* Total number of pages in database file */ + Pgno pg1; /* First page of the sector pPg is located on. */ + int nPage; /* Number of pages starting at pg1 to journal */ + int ii; + + /* Set the doNotSync flag to 1. This is because we cannot allow a journal + ** header to be written between the pages journaled by this function. + */ + assert( pPager->doNotSync==0 ); + pPager->doNotSync = 1; + + /* 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 = sqlite3pager_pagecount(pPager); + 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; iiaInJournal || pg==pPg->pgno || + pg>pPager->origDbSize || !(pPager->aInJournal[pg/8]&(1<<(pg&7))) + ) { + if( pg!=PAGER_MJ_PGNO(pPager) ){ + void *pPage; + rc = sqlite3pager_get(pPager, pg, &pPage); + if( rc==SQLITE_OK ){ + rc = pager_write(pPage); + sqlite3pager_unref(pPage); + } + } + } + } + + assert( pPager->doNotSync==1 ); + pPager->doNotSync = 0; + }else{ + rc = pager_write(pData); + } + return rc; +} + /* ** Return TRUE if the page given in the argument was previously passed ** to sqlite3pager_write(). In other words, return TRUE if it is ok