diff --git a/manifest b/manifest index 7ccd8bcfc8..7aa1fa9809 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthat\swhen\sa\sCREATE\sINDEX\sfails,\sit\sdoes\snot\sleave\sa\sresidue\sbehind\nthat\scan\scorrupt\sthe\sdatabase.\s\sTicket\s#1115.\s(CVS\s2330) -D 2005-02-14T20:48:19 +C Check\sthat\sread-only\spages\sare\snot\sbeing\smodified\s(disabled\sby\sdefault).\s(CVS\s2331) +D 2005-02-15T02:54:15 F Makefile.in d928187101fa3d78426cf48ca30e39d0fb714e57 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 @@ -51,7 +51,7 @@ F src/os_unix.c 68d3d32937eee90fe1f50d500d1a4ee826cbe790 F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13 F src/os_win.c bddeae1c3299be0fbe47077dd4e98b786a067f71 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c d0c1f41b41d2b56a6fd0e1308a66518872f68ed5 +F src/pager.c 69efe972d6034d8d5603f5b2a768e43e25dad0c0 F src/pager.h 70d496f372163abb6340f474288c4bb9ea962cf7 F src/parse.y 450fc9c4d5a737be6fdba6e4b2e3de5800d4d750 F src/pragma.c 7e65c5545d83909238adf231e2a6eee6eb43e0d5 @@ -271,7 +271,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl 3e522a06ad41992023c80ca29a048ae2331ca5bd -P 41d2214b83dd52acdda64a50d0c1ef16009d06d0 -R 9e0bcb38fd98e646a6dce64083f59531 -U drh -Z b1359ca9d31266c1dc27ad6e9e05dbe4 +P cbed92f397ec13b57771ab8b5be74c0cacf35dfd +R f5e0bf334bc8ca4771ae6f5140466932 +U danielk1977 +Z 79138fc5bf3ab18977a8db63dd8b495b diff --git a/manifest.uuid b/manifest.uuid index 36f4e8f326..d68eba3a8c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cbed92f397ec13b57771ab8b5be74c0cacf35dfd \ No newline at end of file +8514a4feb2a86e93c4251c491d394e861bb65edb \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 53c2b84143..ab6490fb9d 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.188 2005/02/06 02:45:42 drh Exp $ +** @(#) $Id: pager.c,v 1.189 2005/02/15 02:54:15 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -168,6 +168,9 @@ struct PgHdr { u8 alwaysRollback; /* Disable dont_rollback() for this page */ short int nRef; /* Number of users of this page */ PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */ +#ifdef SQLITE_CHECK_PAGES + u32 pageHash; +#endif /* pPager->psAligned bytes of page data follow this header */ /* Pager.nExtra bytes of local data follow the page data */ }; @@ -451,6 +454,36 @@ static int pager_errcode(Pager *pPager){ return rc; } +#ifdef SQLITE_CHECK_PAGES +/* +** Return a 32-bit hash of the page data for pPage. +*/ +static u32 pager_pagehash(PgHdr *pPage){ + u32 hash = 0; + int i; + unsigned char *pData = (unsigned char *)PGHDR_TO_DATA(pPage); + for(i=0; ipPager->pageSize; i++){ + hash = (hash+i)^pData[i]; + } + return hash; +} + +/* +** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES +** is defined, and NDEBUG is not defined, an assert() statement checks +** that the page is either dirty or still matches the calculated page-hash. +*/ +#define CHECK_PAGE(x) checkPage(x) +static void checkPage(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + assert( !pPg->pageHash || pPager->errMask || MEMDB || pPg->dirty || + pPg->pageHash==pager_pagehash(pPg) ); +} + +#else +#define CHECK_PAGE(x) +#endif + /* ** When this is called the journal file for pager pPager must be open. ** The master journal file name is read from the end of the file and @@ -841,6 +874,9 @@ static int pager_unwritelock(Pager *pPager){ pPg->inJournal = 0; pPg->dirty = 0; pPg->needSync = 0; +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif } pPager->dirtyCache = 0; pPager->nRec = 0; @@ -958,6 +994,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ if( pPager->state>=PAGER_EXCLUSIVE ){ pPg->dirty = 0; pPg->needSync = 0; +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif } CODEC(pPager, pData, pPg->pgno, 3); } @@ -1086,6 +1125,9 @@ static int pager_reload_cache(Pager *pPager){ } pPg->needSync = 0; pPg->dirty = 0; +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif } return rc; } @@ -2101,6 +2143,9 @@ static int pager_write_pagelist(PgHdr *pList){ #endif if( rc ) return rc; pList->dirty = 0; +#ifdef SQLITE_CHECK_PAGES + pList->pageHash = pager_pagehash(pList); +#endif pList = pList->pDirty; } return SQLITE_OK; @@ -2388,6 +2433,9 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ pPager->nRead++; } } +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif }else{ /* The requested page is in the page cache. */ pPager->nHit++; @@ -2440,6 +2488,8 @@ int sqlite3pager_unref(void *pData){ pPg->nRef--; REFINFO(pPg); + CHECK_PAGE(pPg); + /* When the number of references to a page reach 0, call the ** destructor and add the page to the freelist. */ @@ -2628,6 +2678,8 @@ int sqlite3pager_write(void *pData){ assert( !pPager->setMaster ); + CHECK_PAGE(pPg); + /* Mark the page as dirty. If the page has already been written ** to the journal then we can return right away. */ @@ -2831,6 +2883,9 @@ void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){ }else{ TRACE3("DONT_WRITE page %d of %d\n", pgno, PAGERID(pPager)); pPg->dirty = 0; +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif } } }