From aa5ccdf5b8cff54960c533aab7eb627e92855c37 Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Mon, 14 Jun 2004 05:10:42 +0000 Subject: [PATCH] Update the file change counter just before each transaction is committed. (CVS 1582) FossilOrigin-Name: 4649abcbfd032836b196b5d690ef66e4aa494c45 --- manifest | 16 +++++------ manifest.uuid | 2 +- src/pager.c | 77 +++++++++++++++++++++++++++++++++++++++++++-------- src/vdbe.c | 4 +-- 4 files changed, 76 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 045040dcd4..0e6418374d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C os_win.c\sis\snow\sworking\swith\sthe\snew\slocking\sprotocol.\s(CVS\s1581) -D 2004-06-13T23:07:04 +C Update\sthe\sfile\schange\scounter\sjust\sbefore\seach\stransaction\sis\scommitted.\s(CVS\s1582) +D 2004-06-14T05:10:43 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -48,7 +48,7 @@ F src/os_unix.c 7ece785e36c4ecb57c73db8d374b56912d742c4a F src/os_unix.h 1cd6133cf66dea704b8646b70b2dfdcbdd9b3738 F src/os_win.c d4009586dfd0543ca8956ff0be30f9d23e2cbbdd F src/os_win.h 004eec47b1780fcaf07420ddc2072294b698d48c -F src/pager.c 4a2d3c871169385f7fe65c37919ced82cb3d34ed +F src/pager.c feb44bd0279f77319079c1fddf9be927b052d028 F src/pager.h ca8f293e1d623a7c628a1c5e0c6cf43d5bbb80bf F src/parse.y 097438674976355a10cf177bd97326c548820b86 F src/pragma.c e288bd122d3ca41ec2032475abde1ff5fa3095f4 @@ -71,7 +71,7 @@ F src/update.c 6133c876aa126e1771cda165fd992bb0d2f8eb38 F src/utf.c e16737b3fc4201bf7ce9bd8ced5250596aa31b76 F src/util.c 90375fa253137562d536ccdd40b297f0fd7413fc F src/vacuum.c b921eb778842592e1fb48a9d4cef7e861103878f -F src/vdbe.c c71e47262d3d3539a20a489a03b9cde15ef3acb7 +F src/vdbe.c e6b6702fb2c2e2702e312f52c2cc08353c580736 F src/vdbe.h 46f74444a213129bc4b5ce40124dd8ed613b0cde F src/vdbeInt.h ffc7b8ed911c5bf804796a768fdb6f0568010fa2 F src/vdbeapi.c ee350b552fc4c1c695b760f914f69e9c5556e829 @@ -223,7 +223,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248 F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P c5ebc1c05eccc2c0697b6047a504954e11960f73 -R 4b53e920198647f93177549edf4e8baf -U drh -Z 362250ddf90f1c6b39b6cc80b805170c +P 77c5eaa10a9d2e2bb8f89b7434d6e6efbacf35e9 +R 728fa94fee79e66b965ca32e2cd56d1b +U danielk1977 +Z 982942d9d284a3b9c20e3e9aaf713011 diff --git a/manifest.uuid b/manifest.uuid index 809d329572..8aed1a27f6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -77c5eaa10a9d2e2bb8f89b7434d6e6efbacf35e9 \ No newline at end of file +4649abcbfd032836b196b5d690ef66e4aa494c45 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index add2e80b46..94f9954466 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.124 2004/06/12 01:43:26 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.125 2004/06/14 05:10:43 danielk1977 Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" @@ -71,6 +71,13 @@ static Pager *mainPager = 0; ** threads can be reading or writing while one ** process is writing. ** +** PAGER_SYNCED The pager moves to this state from PAGER_EXCLUSIVE +** after all dirty pages have been written to the +** database file and the file has been synced to +** disk. All that remains to do is to remove the +** journal file and the transaction will be +** committed. +** ** The page cache comes up in PAGER_UNLOCK. The first time a ** sqlite3pager_get() occurs, the state transitions to PAGER_SHARED. ** After all pages have been released using sqlite_page_unref(), @@ -87,6 +94,7 @@ static Pager *mainPager = 0; #define PAGER_SHARED 1 #define PAGER_RESERVED 2 #define PAGER_EXCLUSIVE 3 +#define PAGER_SYNCED 4 /* @@ -323,8 +331,8 @@ static int write32bits(OsFile *fd, u32 val){ } /* -** Write a 32-bit integer into a page header right before the -** page data. This will overwrite the PgHdr.pDirty pointer. +** Write the 32-bit integer 'val' into the page identified by page header +** 'p' at offset 'offset'. */ static void store32bits(u32 val, PgHdr *p, int offset){ unsigned char *ac; @@ -335,6 +343,16 @@ static void store32bits(u32 val, PgHdr *p, int offset){ ac[3] = val & 0xff; } +/* +** Read a 32-bit integer at offset 'offset' from the page identified by +** page header 'p'. +*/ +static u32 retrieve32bits(PgHdr *p, int offset){ + unsigned char *ac; + ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset]; + return (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3]; +} + /* ** Convert the bits in the pPager->errMask into an approprate @@ -532,7 +550,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ } } - assert( pPager->state==PAGER_RESERVED || pPager->state==PAGER_EXCLUSIVE ); + assert( pPager->state==PAGER_RESERVED || pPager->state>=PAGER_EXCLUSIVE ); /* If the pager is in RESERVED state, then there must be a copy of this ** page in the pager cache. In this case just update the pager cache, @@ -546,9 +564,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ ** and the main file. The page is then marked not dirty. */ pPg = pager_lookup(pPager, pgno); - assert( pPager->state==PAGER_EXCLUSIVE || pPg ); + assert( pPager->state>=PAGER_EXCLUSIVE || pPg ); TRACE2("PLAYBACK page %d\n", pgno); - if( pPager->state==PAGER_EXCLUSIVE ){ + if( pPager->state>=PAGER_EXCLUSIVE ){ sqlite3OsSeek(&pPager->fd, (pgno-1)*(off_t)SQLITE_PAGE_SIZE); rc = sqlite3OsWrite(&pPager->fd, aData, SQLITE_PAGE_SIZE); } @@ -564,7 +582,7 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ if( pPager->xDestructor ){ /*** FIX ME: Should this be xReinit? ***/ pPager->xDestructor(pData, pPager->pageSize); } - if( pPager->state==PAGER_EXCLUSIVE ){ + if( pPager->state>=PAGER_EXCLUSIVE ){ pPg->dirty = 0; pPg->needSync = 0; } @@ -1315,6 +1333,7 @@ int sqlite3pager_close(Pager *pPager){ PgHdr *pPg, *pNext; switch( pPager->state ){ case PAGER_RESERVED: + case PAGER_SYNCED: case PAGER_EXCLUSIVE: { sqlite3pager_rollback(pPager); if( !pPager->memDb ){ @@ -2627,6 +2646,35 @@ void sqlite3pager_set_codec( pPager->pCodecArg = pCodecArg; } +/* +** This routine is called to increment the database file change-counter, +** stored at byte 24 of the pager file. +*/ +static int pager_incr_changecounter(Pager *pPager){ + void *pPage; + PgHdr *pPgHdr; + u32 change_counter; + int rc; + + /* Open page 1 of the file for writing. */ + rc = sqlite3pager_get(pPager, 1, &pPage); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3pager_write(pPage); + if( rc!=SQLITE_OK ) return rc; + + /* Read the current value at byte 24. */ + pPgHdr = DATA_TO_PGHDR(pPage); + change_counter = retrieve32bits(pPgHdr, 24); + + /* Increment the value just read and write it back to byte 24. */ + change_counter++; + store32bits(change_counter, pPgHdr, 24); + + /* Release the page reference. */ + sqlite3pager_unref(pPage); + return SQLITE_OK; +} + /* ** Sync the database file for the pager pPager. zMaster points to the name ** of a master journal file that should be written into the individual @@ -2644,13 +2692,16 @@ void sqlite3pager_set_codec( int sqlite3pager_sync(Pager *pPager, const char *zMaster){ int rc = SQLITE_OK; - /* If this is an in-memory db, or no pages have been written to, this - ** function is a no-op. + /* If this is an in-memory db, or no pages have been written to, or this + ** function has already been called, it is a no-op. */ - if( !pPager->memDb && pPager->dirtyCache ){ + if( pPager->state!=PAGER_SYNCED && !pPager->memDb && pPager->dirtyCache ){ PgHdr *pPg; assert( pPager->journalOpen ); + rc = pager_incr_changecounter(pPager); + if( rc!=SQLITE_OK ) goto sync_exit; + /* Sync the journal file */ rc = syncJournal(pPager, zMaster); if( rc!=SQLITE_OK ) goto sync_exit; @@ -2660,10 +2711,12 @@ int sqlite3pager_sync(Pager *pPager, const char *zMaster){ rc = pager_write_pagelist(pPg); if( rc!=SQLITE_OK ) goto sync_exit; - /* If any pages were actually written, sync the database file */ - if( pPg && !pPager->noSync ){ + /* Sync the database file. */ + if( !pPager->noSync ){ rc = sqlite3OsSync(&pPager->fd); } + + pPager->state = PAGER_SYNCED; } sync_exit: diff --git a/src/vdbe.c b/src/vdbe.c index 9057e0de4e..9cba200776 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.370 2004/06/12 20:12:51 drh Exp $ +** $Id: vdbe.c,v 1.371 2004/06/14 05:10:43 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -2136,7 +2136,7 @@ case OP_Column: { ** 't' TEXT ** 'o' NONE ** -** If P3 is NULL then datatype coercion occurs. +** If P3 is NULL then no datatype coercion occurs. */ /* Opcode MakeRecord P1 * P3 **