/ Check-in [cb3cbe00]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Ensure master journal file is deleted when a transaction is committed. (CVS 1586)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cb3cbe00be9a42e974688016a056053cedb55eef
User & Date: danielk1977 2004-06-14 09:35:17
Context
2004-06-14
09:41
Bugfix for previous checkin. (CVS 1587) check-in: 2737505f user: danielk1977 tags: trunk
09:35
Ensure master journal file is deleted when a transaction is committed. (CVS 1586) check-in: cb3cbe00 user: danielk1977 tags: trunk
08:26
Check the value of the schema cookie before reading the sqlite_master table. (CVS 1585) check-in: 80c299f8 user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/main.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Main file for the SQLite library.  The routines in this file
    13     13   ** implement the programmer interface to the library.  Routines in
    14     14   ** other files are for internal use by SQLite and should not be
    15     15   ** accessed by users of the library.
    16     16   **
    17         -** $Id: main.c,v 1.219 2004/06/13 23:07:04 drh Exp $
           17  +** $Id: main.c,v 1.220 2004/06/14 09:35:17 danielk1977 Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include "os.h"
    21     21   #include <ctype.h>
    22     22   
    23     23   /*
    24     24   ** A pointer to this structure is used to communicate information
................................................................................
   221    221     ** Meta values are as follows:
   222    222     **    meta[0]   Schema cookie.  Changes with each schema change.
   223    223     **    meta[1]   File format of schema layer.
   224    224     **    meta[2]   Size of the page cache.
   225    225     **    meta[3]   Synchronous setting.  1:off, 2:normal, 3:full
   226    226     **    meta[4]   Db text encoding. 1:UTF-8 3:UTF-16 LE 4:UTF-16 BE
   227    227     **    meta[5]   Pragma temp_store value.  See comments on BtreeFactory
   228         -  **    meta[6]
          228  +  **    meta[6]   
   229    229     **    meta[7]
   230    230     **    meta[8]
   231    231     **    meta[9]
   232    232     **
   233    233     ** Note: The hash defined SQLITE_UTF* symbols in sqliteInt.h correspond to
   234    234     ** the possible values of meta[4].
   235    235     */

Changes to src/os.h.

   144    144   int sqlite3OsDelete(const char*);
   145    145   int sqlite3OsFileExists(const char*);
   146    146   int sqliteOsFileRename(const char*, const char*);
   147    147   int sqlite3OsOpenReadWrite(const char*, OsFile*, int*);
   148    148   int sqlite3OsOpenExclusive(const char*, OsFile*, int);
   149    149   int sqlite3OsOpenReadOnly(const char*, OsFile*);
   150    150   int sqlite3OsOpenDirectory(const char*, OsFile*);
          151  +int sqlite3OsSyncDirectory(const char*);
   151    152   int sqlite3OsTempFileName(char*);
   152    153   int sqlite3OsClose(OsFile*);
   153    154   int sqlite3OsRead(OsFile*, void*, int amt);
   154    155   int sqlite3OsWrite(OsFile*, const void*, int amt);
   155    156   int sqlite3OsSeek(OsFile*, off_t offset);
   156    157   int sqlite3OsSync(OsFile*);
   157    158   int sqlite3OsTruncate(OsFile*, off_t size);

Changes to src/os_mac.c.

   387    387     if( PBFlushFileSync(&params) != noErr ){
   388    388   # endif
   389    389       return SQLITE_IOERR;
   390    390     }else{
   391    391       return SQLITE_OK;
   392    392     }
   393    393   }
          394  +
          395  +/*
          396  +** Sync the directory zDirname. This is a no-op on operating systems other
          397  +** than UNIX.
          398  +*/
          399  +int sqlite3OsSyncDirectory(const char *zDirname){
          400  +  return SQLITE_OK;
          401  +}
   394    402   
   395    403   /*
   396    404   ** Truncate an open file to a specified size
   397    405   */
   398    406   int sqlite3OsTruncate(OsFile *id, off_t nByte){
   399    407     SimulateIOError(SQLITE_IOERR);
   400    408   # ifdef _LARGE_FILE

Changes to src/os_unix.c.

   615    615         fsync(id->dirfd);
   616    616         close(id->dirfd);  /* Only need to sync once, so close the directory */
   617    617         id->dirfd = -1;    /* when we are done. */
   618    618       }
   619    619       return SQLITE_OK;
   620    620     }
   621    621   }
          622  +
          623  +/*
          624  +** Sync the directory zDirname. This is a no-op on operating systems other
          625  +** than UNIX.
          626  +*/
          627  +int sqlite3OsSyncDirectory(const char *zDirname){
          628  +  int fd;
          629  +  int r;
          630  +  fd = open(zDirname, O_RDONLY|O_BINARY, 0644);
          631  +  if( fd<0 ){
          632  +    return SQLITE_CANTOPEN; 
          633  +  }
          634  +  r = fsync(fd);
          635  +  close(fd);
          636  +  return ((r==0)?SQLITE_OK:SQLITE_IOERR);
          637  +}
   622    638   
   623    639   /*
   624    640   ** Truncate an open file to a specified size
   625    641   */
   626    642   int sqlite3OsTruncate(OsFile *id, off_t nByte){
   627    643     SimulateIOError(SQLITE_IOERR);
   628    644     return ftruncate(id->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;

Changes to src/os_win.c.

   285    285     TRACE3("SYNC %d lock=%d\n", id->h, id->locktype);
   286    286     if( FlushFileBuffers(id->h) ){
   287    287       return SQLITE_OK;
   288    288     }else{
   289    289       return SQLITE_IOERR;
   290    290     }
   291    291   }
          292  +
          293  +/*
          294  +** Sync the directory zDirname. This is a no-op on operating systems other
          295  +** than UNIX.
          296  +*/
          297  +int sqlite3OsSyncDirectory(const char *zDirname){
          298  +  return SQLITE_OK;
          299  +}
   292    300   
   293    301   /*
   294    302   ** Truncate an open file to a specified size
   295    303   */
   296    304   int sqlite3OsTruncate(OsFile *id, off_t nByte){
   297    305     LONG upperBits = nByte>>32;
   298    306     TRACE3("TRUNCATE %d %lld\n", id->h, nByte);

Changes to src/vdbeaux.c.

  1083   1083         sqlite3OsClose(&master);
  1084   1084         sqlite3OsDelete(zMaster);
  1085   1085         sqliteFree(zMaster);
  1086   1086         return rc;
  1087   1087       }
  1088   1088       rc = sqlite3OsSync(&master);
  1089   1089       if( rc!=SQLITE_OK ){
         1090  +      sqlite3OsClose(&master);
  1090   1091         sqliteFree(zMaster);
  1091   1092         return rc;
  1092   1093       }
  1093         -    sqlite3OsClose(&master);
  1094   1094   
  1095   1095       /* Sync all the db files involved in the transaction. The same call
  1096   1096       ** sets the master journal pointer in each individual journal. If
  1097   1097       ** an error occurs here, do not delete the master journal file.
  1098   1098       **
  1099   1099       ** If the error occurs during the first call to sqlite3BtreeSync(),
  1100   1100       ** then there is a chance that the master journal file will be
................................................................................
  1103   1103       ** occured.
  1104   1104       */
  1105   1105       for(i=0; i<db->nDb; i++){ 
  1106   1106         Btree *pBt = db->aDb[i].pBt;
  1107   1107         if( pBt && sqlite3BtreeIsInTrans(pBt) ){
  1108   1108           rc = sqlite3BtreeSync(pBt, zMaster);
  1109   1109           if( rc!=SQLITE_OK ){
         1110  +          sqlite3OsClose(&master);
  1110   1111             sqliteFree(zMaster);
  1111   1112             return rc;
  1112   1113           }
  1113   1114         }
  1114   1115       }
         1116  +    sqlite3OsClose(&master);
  1115   1117       sqliteFree(zMaster);
  1116   1118       zMaster = 0;
  1117   1119   
  1118         -    /* Delete the master journal file. This commits the transaction. */
         1120  +    /* Delete the master journal file. This commits the transaction. After
         1121  +    ** doing this the directory is synced again before any individual
         1122  +    ** transaction files are deleted.
         1123  +    */
  1119   1124       rc = sqlite3OsDelete(zMaster);
  1120   1125       assert( rc==SQLITE_OK );
         1126  +    rc = sqlite3OsSyncDirectory(zMainFile);
         1127  +    if( rc!=SQLITE_OK ){
         1128  +      /* This is not good. The master journal file has been deleted, but
         1129  +      ** the directory sync failed. There is no completely safe course of
         1130  +      ** action from here. The individual journals contain the name of the
         1131  +      ** master journal file, but there is no way of knowing if that
         1132  +      ** master journal exists now or if it will exist after the operating
         1133  +      ** system crash that may follow the fsync() failure.
         1134  +      */
         1135  +      assert(0);
         1136  +      sqliteFree(zMaster);
         1137  +      return rc;
         1138  +    }
  1121   1139   
  1122   1140       /* All files and directories have already been synced, so the following
  1123   1141       ** calls to sqlite3BtreeCommit() are only closing files and deleting
  1124   1142       ** journals. If something goes wrong while this is happening we don't
  1125         -    ** really care. The integrity of the transaction is already guarenteed,
         1143  +    ** really care. The integrity of the transaction is already guaranteed,
  1126   1144       ** but some stray 'cold' journals may be lying around. Returning an
  1127   1145       ** error code won't help matters.
  1128   1146       */
  1129   1147       for(i=0; i<db->nDb; i++){ 
  1130   1148         Btree *pBt = db->aDb[i].pBt;
  1131   1149         if( pBt ){
  1132   1150           sqlite3BtreeCommit(pBt);

Changes to test/attach2.test.

     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this script is testing the ATTACH and DETACH commands
    13     13   # and related functionality.
    14     14   #
    15         -# $Id: attach2.test,v 1.16 2004/06/12 02:17:15 drh Exp $
           15  +# $Id: attach2.test,v 1.17 2004/06/14 09:35:17 danielk1977 Exp $
    16     16   #
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   
    21     21   
    22     22   # Ticket #354
................................................................................
   299    299   do_test attach2-4.15 {
   300    300     execsql {SELECT * FROM t1} db2
   301    301   } {1 2 1 2}
   302    302   
   303    303   db close
   304    304   db2 close
   305    305   file delete -force test2.db
          306  +
          307  +if 0 {
          308  +
          309  +# These tests - attach2-5.* - check that the master journal file is deleted
          310  +# correctly when a multi-file transaction is committed or rolled back.
          311  +#
          312  +# Update: It's not actually created if a rollback occurs, so that test
          313  +# doesn't really prove too much.
          314  +foreach f [glob test.db*] {file delete -force $f}
          315  +do_test attach2-5.1 {
          316  +  sqlite db test.db
          317  +  execsql {
          318  +    ATTACH 'test.db2' AS aux;
          319  +  }
          320  +} {}
          321  +do_test attach2-5.2 {
          322  +  execsql {
          323  +    BEGIN;
          324  +    CREATE TABLE tbl(a, b, c);
          325  +    CREATE TABLE aux.tbl(a, b, c);
          326  +    COMMIT;
          327  +  }
          328  +} {}
          329  +do_test attach2-5.3 {
          330  +  glob test.db*
          331  +} {test.db test.db2}
          332  +do_test attach2-5.4 {
          333  +  execsql {
          334  +    BEGIN;
          335  +    DROP TABLE aux.tbl;
          336  +    DROP TABLE tbl;
          337  +    ROLLBACK;
          338  +  }
          339  +} {}
          340  +do_test attach2-5.5 {
          341  +  glob test.db*
          342  +} {test.db test.db2}
          343  +
          344  +db close
          345  +
          346  +}
          347  +
   306    348   
   307    349   finish_test
          350  +
          351  +
          352  +
          353  +
          354  +
          355  +