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.165 2004/06/13 23:07:04 drh Exp $ +** $Id: btree.c,v 1.166 2004/06/14 06:03:57 danielk1977 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: @@ -4193,10 +4193,28 @@ */ const char *sqlite3BtreeGetFilename(Btree *pBt){ assert( pBt->pPager!=0 ); return sqlite3pager_filename(pBt->pPager); } + +/* +** Return the pathname of the directory that contains the database file. +*/ +const char *sqlite3BtreeGetDirname(Btree *pBt){ + assert( pBt->pPager!=0 ); + return sqlite3pager_dirname(pBt->pPager); +} + +/* +** Return the pathname of the journal file for this database. The return +** value of this routine is the same regardless of whether the journal file +** has been created or not. +*/ +const char *sqlite3BtreeGetJournalname(Btree *pBt){ + assert( pBt->pPager!=0 ); + return sqlite3pager_journalname(pBt->pPager); +} /* ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. ** Index: src/btree.h ================================================================== --- src/btree.h +++ src/btree.h @@ -11,11 +11,11 @@ ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.53 2004/06/04 06:22:01 danielk1977 Exp $ +** @(#) $Id: btree.h,v 1.54 2004/06/14 06:03:57 danielk1977 Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It @@ -57,10 +57,12 @@ int sqlite3BtreeIsInTrans(Btree*); int sqlite3BtreeIsInStmt(Btree*); int sqlite3BtreeSync(Btree*, const char *zMaster); const char *sqlite3BtreeGetFilename(Btree *); +const char *sqlite3BtreeGetDirname(Btree *); +const char *sqlite3BtreeGetJournalname(Btree *); int sqlite3BtreeCopyFile(Btree *, Btree *); /* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR ** of the following flags: */ 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.125 2004/06/14 05:10:43 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.126 2004/06/14 06:03:57 danielk1977 Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" #include "pager.h" #include @@ -613,34 +613,37 @@ ** is running this routine also. Not that it makes too much difference. */ rc = sqlite3OsOpenExclusive(zMaster, &master, 0); if( rc!=SQLITE_OK ) goto delmaster_out; master_open = 1; - rc = sqlite3OsFileSize(&master, &nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; if( nMasterJournal>0 ){ - char *zDb; - zMasterJournal = (char *)sqliteMalloc(nMasterJournal); + char *zJournal; + char *zMasterPtr; + int nMasterPtr; /* Number of bytes allocated at zMasterPtr */ + + /* Load the entire master journal file into space obtained from + ** sqliteMalloc() and pointed to by zMasterJournal. + ** + ** Also allocate an extra (strlen(zMaster)+1) bytes. This space is used + ** to load a master-journal filename from some other journal file to + ** check if it points at this master journal file. + */ + nMasterPtr = strlen(zMaster) + 1; + zMasterJournal = (char *)sqliteMalloc(nMasterJournal) + nMasterPtr; if( !zMasterJournal ){ rc = SQLITE_NOMEM; goto delmaster_out; } + zMasterPtr = &zMasterJournal[nMasterJournal]; rc = sqlite3OsRead(&master, zMasterJournal, nMasterJournal); if( rc!=SQLITE_OK ) goto delmaster_out; - zDb = zMasterJournal; - while( (zDb-zMasterJournal)0 && nMaster>=strlen(zMaster)+1 ){ - /*** FIX ME: Consider allocating this space at the same time - **** space is allocated for holding the text of the master journal */ - char *zMasterPtr = (char *)sqliteMalloc(nMaster); - if( !zMasterPtr ){ - rc = SQLITE_NOMEM; - } - rc = sqlite3OsRead(&journal, zMasterPtr, nMaster); + if( nMaster>=nMasterPtr ){ + rc = sqlite3OsRead(&journal, zMasterPtr, nMasterPtr); if( rc!=SQLITE_OK ){ - sqliteFree(zMasterPtr); goto delmaster_out; } - if( 0==strncmp(zMasterPtr, zMaster, nMaster) ){ + if( zMasterPtr[nMasterPtr-1]=='\0' && !strcmp(zMasterPtr, zMaster) ){ /* We have a match. Do not delete the master journal file. */ - sqliteFree(zMasterPtr); goto delmaster_out; } } } - zDb += (strlen(zDb)+1); + zJournal += (strlen(zJournal)+1); } } sqlite3OsDelete(zMaster); @@ -2631,10 +2625,24 @@ ** Return the full pathname of the database file. */ const char *sqlite3pager_filename(Pager *pPager){ return pPager->zFilename; } + +/* +** Return the directory of the database file. +*/ +const char *sqlite3pager_dirname(Pager *pPager){ + return pPager->zDirectory; +} + +/* +** Return the full pathname of the journal file. +*/ +const char *sqlite3pager_journalname(Pager *pPager){ + return pPager->zJournal; +} /* ** Set the codec for this pager */ void sqlite3pager_set_codec( Index: src/pager.h ================================================================== --- src/pager.h +++ src/pager.h @@ -11,11 +11,11 @@ ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.33 2004/06/09 17:37:28 drh Exp $ +** @(#) $Id: pager.h,v 1.34 2004/06/14 06:03:57 danielk1977 Exp $ */ /* ** The size of a page. ** @@ -97,10 +97,12 @@ void sqlite3pager_dont_rollback(void*); void sqlite3pager_dont_write(Pager*, Pgno); int *sqlite3pager_stats(Pager*); void sqlite3pager_set_safety_level(Pager*,int); const char *sqlite3pager_filename(Pager*); +const char *sqlite3pager_dirname(Pager*); +const char *sqlite3pager_journalname(Pager*); int sqlite3pager_rename(Pager*, const char *zNewName); void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*); #ifdef SQLITE_DEBUG int sqlite3pager_lockstate(Pager*); Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -1059,11 +1059,11 @@ */ 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); + char const *zFile = sqlite3BtreeGetJournalname(pBt); if( zFile[0]==0 ) continue; /* Ignore :memory: databases */ rc = sqlite3OsWrite(&master, zFile, strlen(zFile)+1); if( rc!=SQLITE_OK ){ sqlite3OsClose(&master); sqlite3OsDelete(zMaster); @@ -1071,17 +1071,29 @@ return rc; } } } - /* Sync the master journal file */ + + /* Sync the master journal file. Before doing this, open the directory + ** the master journal file is store in so that it gets synced too. + */ + zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt); + rc = sqlite3OsOpenDirectory(zMainFile, &master); + if( rc!=SQLITE_OK ){ + sqlite3OsClose(&master); + sqlite3OsDelete(zMaster); + sqliteFree(zMaster); + return rc; + } rc = sqlite3OsSync(&master); + if( rc!=SQLITE_OK ){ + sqliteFree(zMaster); + return rc; + } 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. ** ** If the error occurs during the first call to sqlite3BtreeSync(),