Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -7,11 +7,11 @@ ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.162 2004/06/09 17:37:23 drh Exp $ +** $Id: btree.c,v 1.163 2004/06/09 20:03:09 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: @@ -1248,11 +1248,11 @@ if( pBt->pPage1==0 ){ rc = lockBtree(pBt); } if( rc==SQLITE_OK && wrflag ){ - rc = sqlite3pager_begin(pBt->pPage1->aData, 0); + rc = sqlite3pager_begin(pBt->pPage1->aData, nMaster); if( rc==SQLITE_OK ){ rc = newDatabase(pBt); } } Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -12,11 +12,11 @@ ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.209 2004/06/09 12:30:06 danielk1977 Exp $ +** $Id: main.c,v 1.210 2004/06/09 20:03:09 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include @@ -1031,10 +1031,13 @@ sqlite3_create_collation(db, "NOCASE", 0, 0, nocaseCollatingFunc); /* Open the backend database driver */ if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){ db->temp_store = 2; + db->nMaster = 0; /* Disable atomic multi-file commit for :memory: */ + }else{ + db->nMaster = -1; /* Size of master journal filename initially unknown */ } rc = sqlite3BtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt); if( rc!=SQLITE_OK ){ /* FIX ME: sqlite3BtreeFactory() should call sqlite3Error(). */ sqlite3Error(db, rc, 0); @@ -1159,6 +1162,5 @@ char *zName8 = sqlite3utf16to8(zName, -1, SQLITE_BIGENDIAN); rc = sqlite3_create_collation(db, zName8, pref16, pCtx, xCompare); sqliteFree(zName8); return rc; } - Index: src/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -16,11 +16,11 @@ ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.116 2004/06/09 19:03:55 drh Exp $ +** @(#) $Id: pager.c,v 1.117 2004/06/09 20:03:09 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" #include "pager.h" #include @@ -1932,11 +1932,12 @@ } if( rc==SQLITE_OK ){ rc = write32bits(&pPager->jfd, pPager->nMaster); } if( rc==SQLITE_OK ){ - rc = sqlite3OsSeek(&pPager->jfd, 24 + pPager->nMaster); + sqlite3OsSeek(&pPager->jfd, 24 + pPager->nMaster - 1); + rc = sqlite3OsWrite(&pPager->jfd, "\000", 1); } if( pPager->stmtAutoopen && rc==SQLITE_OK ){ rc = sqlite3pager_stmt_begin(pPager); } if( rc!=SQLITE_OK ){ Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.275 2004/06/09 14:01:51 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.276 2004/06/09 20:03:09 drh Exp $ */ #include "config.h" #include "sqlite3.h" #include "hash.h" #include "parse.h" @@ -420,10 +420,11 @@ int errCode; /* Most recent error code (SQLITE_*) */ char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ void *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ u8 enc; /* Text encoding for this database. */ u8 autoCommit; /* The auto-commit flag. */ + int nMaster; /* Length of master journal name. -1=unknown */ }; /* ** Possible values for the sqlite.flags and or Db.flags fields. ** Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -41,11 +41,11 @@ ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** 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.361 2004/06/09 09:55:19 danielk1977 Exp $ +** $Id: vdbe.c,v 1.362 2004/06/09 20:03:10 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include #include "vdbeInt.h" @@ -2317,12 +2317,14 @@ assert( i>=0 && inDb ); pBt = db->aDb[i].pBt; if( pBt ){ - int nMaster = strlen(sqlite3BtreeGetFilename(db->aDb[0].pBt))+11; - rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, nMaster); + if( db->nMaster<0 ){ + db->nMaster = strlen(sqlite3BtreeGetFilename(db->aDb[0].pBt))+20; + } + rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, db->nMaster); if( rc==SQLITE_BUSY ){ if( db->busyHandler.xFunc==0 ){ p->pc = pc; p->rc = SQLITE_BUSY; p->pTos = pTos; Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -931,12 +931,16 @@ } /* The simple case - no more than one database file (not counting the TEMP ** database) has a transaction active. There is no need for the ** master-journal. + ** + ** if db->nMaster==0, it means the main database is :memory:. In that case + ** we do not support atomic multi-file commits, so use the simple case then + ** too. */ - if( nTrans<=100 ){ /**** FIX ME ****/ + if( db->nMaster<=0 || nTrans<=1 ){ for(i=0; rc==SQLITE_OK && inDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ rc = sqlite3BtreeSync(pBt, 0); } @@ -972,10 +976,11 @@ return SQLITE_NOMEM; } }while( sqlite3OsFileExists(zMaster) ); /* Open the master journal. */ + assert( strlen(zMaster)nMaster ); rc = sqlite3OsOpenExclusive(zMaster, &master, 0); if( rc!=SQLITE_OK ){ sqliteFree(zMaster); return rc; } @@ -986,20 +991,15 @@ ** still have 'null' as the master journal pointer, so they will roll ** back independantly if a failure occurs. */ for(i=0; inDb; i++){ Btree *pBt = db->aDb[i].pBt; + if( i==1 ) continue; /* Ignore the TEMP database */ if( pBt && sqlite3BtreeIsInTrans(pBt) ){ char const *zFile = sqlite3BtreeGetFilename(pBt); - rc = sqlite3OsWrite(&master, zFile, strlen(zFile)); - if( rc!=SQLITE_OK ){ - sqlite3OsClose(&master); - sqlite3OsDelete(zMaster); - sqliteFree(zMaster); - return rc; - } - rc = sqlite3OsWrite(&master, "\0", 1); + if( zFile[0]==0 ) continue; /* Ignore :memory: databases */ + rc = sqlite3OsWrite(&master, zFile, strlen(zFile)+1); if( rc!=SQLITE_OK ){ sqlite3OsClose(&master); sqlite3OsDelete(zMaster); sqliteFree(zMaster); return rc; @@ -1008,10 +1008,13 @@ } /* Sync the master journal file */ rc = sqlite3OsSync(&master); sqlite3OsClose(&master); + + /* FIXME: Sync the directory that contains the master journal to + ** make sure the i-node is up to date. */ /* Sync all the db files involved in the transaction. The same call ** sets the master journal pointer in each individual journal. If ** an error occurs here, do not delete the master journal file. ** Index: test/pager2.test ================================================================== --- test/pager2.test +++ test/pager2.test @@ -9,11 +9,11 @@ # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is page cache subsystem. # -# $Id: pager2.test,v 1.1 2004/05/12 13:30:09 drh Exp $ +# $Id: pager2.test,v 1.2 2004/06/09 20:03:10 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -120,11 +120,11 @@ } msg] lappend v $msg } {0 {}} do_test pager2-2.15 { pager_stats $::p1 -} {ref 1 page 1 max 10 size 1 state 2 err 0 hit 1 miss 1 ovfl 0} +} {ref 1 page 1 max 10 size 1 state 3 err 0 hit 1 miss 1 ovfl 0} do_test pager2-2.16 { page_read $::g1 } {Page-One} do_test pager2-2.17 { set v [catch { @@ -293,11 +293,11 @@ set res } {} do_test pager2-4.5.$i.1 { page_write $g1 "Page-1 v$i" lrange [pager_stats $p1] 8 9 - } {state 2} + } {state 3} do_test pager2-4.5.$i.2 { for {set j 2} {$j<=20} {incr j} { set gx [page_get $p1 $j] page_write $gx "Page-$j v$i" page_unref $gx @@ -334,11 +334,11 @@ set res } {} do_test pager2-4.5.$i.5 { page_write $g1 "Page-1 v$i" lrange [pager_stats $p1] 8 9 - } {state 2} + } {state 3} do_test pager2-4.5.$i.6 { for {set j 2} {$j<=20} {incr j} { set gx [page_get $p1 $j] page_write $gx "Page-$j v$i" page_unref $gx