-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
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
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
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
** 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"
** 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(),
#define PAGER_SHARED 1
#define PAGER_RESERVED 2
#define PAGER_EXCLUSIVE 3
+#define PAGER_SYNCED 4
/*
}
/*
-** 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;
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
}
}
- 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,
** 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);
}
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;
}
PgHdr *pPg, *pNext;
switch( pPager->state ){
case PAGER_RESERVED:
+ case PAGER_SYNCED:
case PAGER_EXCLUSIVE: {
sqlite3pager_rollback(pPager);
if( !pPager->memDb ){
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
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;
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: