From: drh Date: Sun, 20 Feb 2011 03:32:54 +0000 (+0000) Subject: Make sure the change-counter and SQLite-version fields of the header are X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bb250298e691b8c0efc42876368927c645cd8a88;p=thirdparty%2Fsqlite.git Make sure the change-counter and SQLite-version fields of the header are set correctly even after vacuuming. This is a backport of changes [0be92a7576] and [04fa1e1690] to address ticket [5de63f876cc]. FossilOrigin-Name: 442be1358e7dff17548718c0c7c031ec320d135d --- diff --git a/manifest b/manifest index c83c67403a..aabe5693ce 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 -C Do\snot\sraise\san\sSQLITE_CORRUPT\serror\sin\sRecoverymode\sif\sthe\sdatabase\ssize\nin\sthe\sheader\sis\slarger\sthan\sthe\sphysical\sfile\ssize.\s\sThis\sis\sa\scherrypick\nof\scheckin\s[114640d920e16c8] -D 2011-02-20T03:27:52.324 +C Make\ssure\sthe\schange-counter\sand\sSQLite-version\sfields\sof\sthe\sheader\sare\nset\scorrectly\seven\safter\svacuuming.\s\sThis\sis\sa\sbackport\sof\schanges\n[0be92a7576]\sand\s[04fa1e1690]\sto\saddress\sticket\s[5de63f876cc]. +D 2011-02-20T03:32:54.731 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 4547616ad2286053af6ccccefa242dc925e49bf0 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -165,7 +165,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e F src/os_unix.c 0240c5b547b4cf585c8cac351a95c3e85ce00772 F src/os_win.c 2f90f7bdec714fad51cd31b4ecad3cc1b4bb5aad -F src/pager.c c0aca5c733c15a16fe158c3215d857841a4e5381 +F src/pager.c 5b2210b4307c626a3b3ed7312161ec533958c094 F src/pager.h 0ea59db2a33bc6c2c02cae34de33367e1effdf76 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58 F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa @@ -376,7 +376,7 @@ F test/enc4.test 4b575ef09e0eff896e73bd24076f96c2aa6a42de F test/eqp.test 69670e7919030f21de29fb99bf1d68f97aedcbdb F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3 F test/exclusive.test 53e1841b422e554cecf0160f937c473d6d0e3062 -F test/exclusive2.test 76e63c05349cb70d09d60b99d2ae625525ff5155 +F test/exclusive2.test c2f2b2242dc436a12df8dd531e06843053bd3b9a F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7 F test/expr.test 620a636cf7b7d4e5834a0b9d83a4da372e24a7b7 F test/fallocate.test 43dc34b8c24be6baffadc3b4401ee15710ce83c6 @@ -897,14 +897,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 29597a71d0848cd5faeb68b606a9127910c8dc57 -R 4765ab892066a2cf596b52ac188daaa7 +P 7701b07759d63537408a68bac85cb1b8b27160b7 +R 1af9cda1d47f108dd79a57e892ab3d60 U drh -Z 0fd913631bd65c1d6b88eece64aed780 +Z d17b6d73dc0e258c19674947beb8c07b -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) -iD8DBQFNYIo8oxKgR168RlERAtxOAJ0W2UlkzgKSsQgJHB8/MuaurrnAOACeIEqH -2d5x+c+4cCHEyAOLiV5KRVk= -=mpQI +iD8DBQFNYItqoxKgR168RlERAkvGAJ456/IGVD5IaXa+SVUvWNJiAFQjWwCdEmc5 +sY0984PvfU6Cksq4hCEZCN0= +=PbW4 -----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index f75cc684ef..0a7ea22276 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7701b07759d63537408a68bac85cb1b8b27160b7 \ No newline at end of file +442be1358e7dff17548718c0c7c031ec320d135d \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 5fcee322bc..2b267b1895 100644 --- a/src/pager.c +++ b/src/pager.c @@ -2915,11 +2915,37 @@ static int pagerRollbackWal(Pager *pPager){ return rc; } + +/* +** Update the value of the change-counter at offsets 24 and 92 in +** the header and the sqlite version number at offset 96. +** +** This is an unconditional update. See also the pager_incr_changecounter() +** routine which only updates the change-counter if the update is actually +** needed, as determined by the pPager->changeCountDone state variable. +*/ +static void pager_write_changecounter(PgHdr *pPg){ + u32 change_counter; + + /* Increment the value just read and write it back to byte 24. */ + change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1; + put32bits(((char*)pPg->pData)+24, change_counter); + + /* Also store the SQLite version number in bytes 96..99 and in + ** bytes 92..95 store the change counter for which the version number + ** is valid. */ + put32bits(((char*)pPg->pData)+92, change_counter); + put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER); +} + /* ** This function is a wrapper around sqlite3WalFrames(). As well as logging ** the contents of the list of pages headed by pList (connected by pDirty), ** this function notifies any active backup processes that the pages have -** changed. +** changed. +** +** The list of pages passed into this routine is always sorted by page number. +** Hence, if page 1 appears anywhere on the list, it will be the first page. */ static int pagerWalFrames( Pager *pPager, /* Pager object */ @@ -2929,8 +2955,19 @@ static int pagerWalFrames( int syncFlags /* Flags to pass to OsSync() (or 0) */ ){ int rc; /* Return code */ +#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES) + PgHdr *p; /* For looping over pages */ +#endif assert( pPager->pWal ); +#ifdef SQLITE_DEBUG + /* Verify that the page list is in accending order */ + for(p=pList; p && p->pDirty; p=p->pDirty){ + assert( p->pgno < p->pDirty->pgno ); + } +#endif + + if( pList->pgno==1 ) pager_write_changecounter(pList); rc = sqlite3WalFrames(pPager->pWal, pPager->pageSize, pList, nTruncate, isCommit, syncFlags ); @@ -2942,9 +2979,8 @@ static int pagerWalFrames( } #ifdef SQLITE_CHECK_PAGES - { - PgHdr *p; - for(p=pList; p; p=p->pDirty) pager_set_pagehash(p); + for(p=pList; p; p=p->pDirty){ + pager_set_pagehash(p); } #endif @@ -3969,6 +4005,7 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ char *pData; /* Data to write */ assert( (pList->flags&PGHDR_NEED_SYNC)==0 ); + if( pList->pgno==1 ) pager_write_changecounter(pList); /* Encode the database */ CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData); @@ -5489,7 +5526,13 @@ void sqlite3PagerDontWrite(PgHdr *pPg){ /* ** This routine is called to increment the value of the database file ** change-counter, stored as a 4-byte big-endian integer starting at -** byte offset 24 of the pager file. +** byte offset 24 of the pager file. The secondary change counter at +** 92 is also updated, as is the SQLite version number at offset 96. +** +** But this only happens if the pPager->changeCountDone flag is false. +** To avoid excess churning of page 1, the update only happens once. +** See also the pager_write_changecounter() routine that does an +** unconditional update of the change counters. ** ** If the isDirectMode flag is zero, then this is done by calling ** sqlite3PagerWrite() on page 1, then modifying the contents of the @@ -5530,7 +5573,6 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ if( !pPager->changeCountDone && pPager->dbSize>0 ){ PgHdr *pPgHdr; /* Reference to page 1 */ - u32 change_counter; /* Initial value of change-counter field */ assert( !pPager->tempFile && isOpen(pPager->fd) ); @@ -5543,21 +5585,13 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ ** direct mode, page 1 is always held in cache and hence the PagerGet() ** above is always successful - hence the ALWAYS on rc==SQLITE_OK. */ - if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){ + if( !DIRECT_MODE && rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPgHdr); } if( rc==SQLITE_OK ){ - /* Increment the value just read and write it back to byte 24. */ - change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers); - change_counter++; - put32bits(((char*)pPgHdr->pData)+24, change_counter); - - /* Also store the SQLite version number in bytes 96..99 and in - ** bytes 92..95 store the change counter for which the version number - ** is valid. */ - put32bits(((char*)pPgHdr->pData)+92, change_counter); - put32bits(((char*)pPgHdr->pData)+96, SQLITE_VERSION_NUMBER); + /* Actually do the update of the change counter */ + pager_write_changecounter(pPgHdr); /* If running in direct mode, write the contents of page 1 to the file. */ if( DIRECT_MODE ){ diff --git a/test/exclusive2.test b/test/exclusive2.test index 6c3571d23b..4a167c7f42 100644 --- a/test/exclusive2.test +++ b/test/exclusive2.test @@ -299,13 +299,13 @@ do_test exclusive2-3.5 { INSERT INTO t1 VALUES(randstr(10, 400)); } readPagerChangeCounter test.db -} {4} +} {5} do_test exclusive2-3.6 { execsql { INSERT INTO t1 VALUES(randstr(10, 400)); } readPagerChangeCounter test.db -} {5} +} {6} sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit) finish_test