/ Check-in [73cd0aab]
Login

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

Overview
Comment:Ensure the master journal directory is synced. Also, change the master journal format to store journal file names. (CVS 1583)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 73cd0aabb24f7b663c8b55cf5e8fcb34fd48c032
User & Date: danielk1977 2004-06-14 06:03:57
Context
2004-06-14
06:13
Change tests in pager.test to account for the extra cache hit in the code that updates file change counter. (CVS 1584) check-in: 76ac9a78 user: danielk1977 tags: trunk
06:03
Ensure the master journal directory is synced. Also, change the master journal format to store journal file names. (CVS 1583) check-in: 73cd0aab user: danielk1977 tags: trunk
05:10
Update the file change counter just before each transaction is committed. (CVS 1582) check-in: 4649abcb user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** $Id: btree.c,v 1.165 2004/06/13 23:07:04 drh Exp $
           12  +** $Id: btree.c,v 1.166 2004/06/14 06:03:57 danielk1977 Exp $
    13     13   **
    14     14   ** This file implements a external (disk-based) database using BTrees.
    15     15   ** For a detailed discussion of BTrees, refer to
    16     16   **
    17     17   **     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
    18     18   **     "Sorting And Searching", pages 473-480. Addison-Wesley
    19     19   **     Publishing Company, Reading, Massachusetts.
................................................................................
  4191   4191   /*
  4192   4192   ** Return the full pathname of the underlying database file.
  4193   4193   */
  4194   4194   const char *sqlite3BtreeGetFilename(Btree *pBt){
  4195   4195     assert( pBt->pPager!=0 );
  4196   4196     return sqlite3pager_filename(pBt->pPager);
  4197   4197   }
         4198  +
         4199  +/*
         4200  +** Return the pathname of the directory that contains the database file.
         4201  +*/
         4202  +const char *sqlite3BtreeGetDirname(Btree *pBt){
         4203  +  assert( pBt->pPager!=0 );
         4204  +  return sqlite3pager_dirname(pBt->pPager);
         4205  +}
         4206  +
         4207  +/*
         4208  +** Return the pathname of the journal file for this database. The return
         4209  +** value of this routine is the same regardless of whether the journal file
         4210  +** has been created or not.
         4211  +*/
         4212  +const char *sqlite3BtreeGetJournalname(Btree *pBt){
         4213  +  assert( pBt->pPager!=0 );
         4214  +  return sqlite3pager_journalname(pBt->pPager);
         4215  +}
  4198   4216   
  4199   4217   /*
  4200   4218   ** Copy the complete content of pBtFrom into pBtTo.  A transaction
  4201   4219   ** must be active for both files.
  4202   4220   **
  4203   4221   ** The size of file pBtFrom may be reduced by this operation.
  4204   4222   ** If anything goes wrong, the transaction on pBtFrom is rolled back.

Changes to src/btree.h.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This header file defines the interface that the sqlite B-Tree file
    13     13   ** subsystem.  See comments in the source code for a detailed description
    14     14   ** of what each interface routine does.
    15     15   **
    16         -** @(#) $Id: btree.h,v 1.53 2004/06/04 06:22:01 danielk1977 Exp $
           16  +** @(#) $Id: btree.h,v 1.54 2004/06/14 06:03:57 danielk1977 Exp $
    17     17   */
    18     18   #ifndef _BTREE_H_
    19     19   #define _BTREE_H_
    20     20   
    21     21   /* TODO: This definition is just included so other modules compile. It
    22     22   ** needs to be revisited.
    23     23   */
................................................................................
    55     55   int sqlite3BtreeRollbackStmt(Btree*);
    56     56   int sqlite3BtreeCreateTable(Btree*, int*, int flags);
    57     57   int sqlite3BtreeIsInTrans(Btree*);
    58     58   int sqlite3BtreeIsInStmt(Btree*);
    59     59   int sqlite3BtreeSync(Btree*, const char *zMaster);
    60     60   
    61     61   const char *sqlite3BtreeGetFilename(Btree *);
           62  +const char *sqlite3BtreeGetDirname(Btree *);
           63  +const char *sqlite3BtreeGetJournalname(Btree *);
    62     64   int sqlite3BtreeCopyFile(Btree *, Btree *);
    63     65   
    64     66   /* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR
    65     67   ** of the following flags:
    66     68   */
    67     69   #define BTREE_INTKEY     1    /* Table has only 64-bit signed integer keys */
    68     70   #define BTREE_ZERODATA   2    /* Table has keys only - no data */

Changes to src/pager.c.

    14     14   ** The pager is used to access a database disk file.  It implements
    15     15   ** atomic commit and rollback through the use of a journal file that
    16     16   ** is separate from the database file.  The pager also implements file
    17     17   ** locking to prevent two processes from writing the same database
    18     18   ** file simultaneously, or one process from reading the database while
    19     19   ** another is writing.
    20     20   **
    21         -** @(#) $Id: pager.c,v 1.125 2004/06/14 05:10:43 danielk1977 Exp $
           21  +** @(#) $Id: pager.c,v 1.126 2004/06/14 06:03:57 danielk1977 Exp $
    22     22   */
    23     23   #include "os.h"         /* Must be first to enable large file support */
    24     24   #include "sqliteInt.h"
    25     25   #include "pager.h"
    26     26   #include <assert.h>
    27     27   #include <string.h>
    28     28   
................................................................................
   611    611   
   612    612     /* Open the master journal file exclusively in case some other process
   613    613     ** is running this routine also. Not that it makes too much difference.
   614    614     */
   615    615     rc = sqlite3OsOpenExclusive(zMaster, &master, 0);
   616    616     if( rc!=SQLITE_OK ) goto delmaster_out;
   617    617     master_open = 1;
   618         -
   619    618     rc = sqlite3OsFileSize(&master, &nMasterJournal);
   620    619     if( rc!=SQLITE_OK ) goto delmaster_out;
   621    620   
   622    621     if( nMasterJournal>0 ){
   623         -    char *zDb;
   624         -    zMasterJournal = (char *)sqliteMalloc(nMasterJournal);
          622  +    char *zJournal;
          623  +    char *zMasterPtr;
          624  +    int nMasterPtr;   /* Number of bytes allocated at zMasterPtr */
          625  +
          626  +    /* Load the entire master journal file into space obtained from
          627  +    ** sqliteMalloc() and pointed to by zMasterJournal. 
          628  +    **
          629  +    ** Also allocate an extra (strlen(zMaster)+1) bytes. This space is used
          630  +    ** to load a master-journal filename from some other journal file to
          631  +    ** check if it points at this master journal file.
          632  +    */
          633  +    nMasterPtr = strlen(zMaster) + 1;
          634  +    zMasterJournal = (char *)sqliteMalloc(nMasterJournal) + nMasterPtr;
   625    635       if( !zMasterJournal ){
   626    636         rc = SQLITE_NOMEM;
   627    637         goto delmaster_out;
   628    638       }
          639  +    zMasterPtr = &zMasterJournal[nMasterJournal];
   629    640       rc = sqlite3OsRead(&master, zMasterJournal, nMasterJournal);
   630    641       if( rc!=SQLITE_OK ) goto delmaster_out;
   631    642   
   632         -    zDb = zMasterJournal;
   633         -    while( (zDb-zMasterJournal)<nMasterJournal ){
   634         -      char *zJournal = 0;
   635         -      /*** FIX ME:  Store the full journal name in the master journal,
   636         -      **** not just the base database name. ***/
   637         -      sqlite3SetString(&zJournal, zDb, "-journal", 0);
   638         -      if( !zJournal ){
   639         -        rc = SQLITE_NOMEM;
   640         -        goto delmaster_out;
   641         -      }
          643  +    zJournal = zMasterJournal;
          644  +    while( (zJournal-zMasterJournal)<nMasterJournal ){
   642    645         if( sqlite3OsFileExists(zJournal) ){
   643    646           /* One of the journals pointed to by the master journal exists.
   644    647           ** Open it and check if it points at the master journal. If
   645    648           ** so, return without deleting the master journal file.
   646    649           */
   647    650           OsFile journal;
   648    651           int nMaster;
   649    652           off_t jsz;
   650    653   
   651    654           rc = sqlite3OsOpenReadOnly(zJournal, &journal);
   652         -        sqliteFree(zJournal);
   653    655           if( rc!=SQLITE_OK ){
   654    656             sqlite3OsClose(&journal);
   655    657             goto delmaster_out;
   656    658           }
   657    659   
   658    660   	/* Check if the file is big enough to be a journal file
   659    661           ** with the required master journal name. If not, ignore it.
................................................................................
   672    674           ** is stored. Read the master journal name into memory obtained
   673    675           ** from malloc.
   674    676           */
   675    677           rc = sqlite3OsSeek(&journal, 20);
   676    678           if( rc!=SQLITE_OK ) goto delmaster_out;
   677    679           rc = read32bits(&journal, (u32*)&nMaster);
   678    680           if( rc!=SQLITE_OK ) goto delmaster_out;
   679         -        if( nMaster>0 && nMaster>=strlen(zMaster)+1 ){
   680         -          /*** FIX ME: Consider allocating this space at the same time
   681         -          **** space is allocated for holding the text of the master journal */
   682         -          char *zMasterPtr = (char *)sqliteMalloc(nMaster);
   683         -          if( !zMasterPtr ){
   684         -            rc = SQLITE_NOMEM;
   685         -          }
   686         -          rc = sqlite3OsRead(&journal, zMasterPtr, nMaster);
          681  +        if( nMaster>=nMasterPtr ){
          682  +          rc = sqlite3OsRead(&journal, zMasterPtr, nMasterPtr);
   687    683             if( rc!=SQLITE_OK ){
   688         -            sqliteFree(zMasterPtr);
   689    684               goto delmaster_out;
   690    685             }
   691         -          if( 0==strncmp(zMasterPtr, zMaster, nMaster) ){
          686  +          if( zMasterPtr[nMasterPtr-1]=='\0' && !strcmp(zMasterPtr, zMaster) ){
   692    687               /* We have a match. Do not delete the master journal file. */
   693         -            sqliteFree(zMasterPtr);
   694    688               goto delmaster_out;
   695    689             }
   696    690           }
   697    691         }
   698         -      zDb += (strlen(zDb)+1);
          692  +      zJournal += (strlen(zJournal)+1);
   699    693       }
   700    694     }
   701    695     
   702    696     sqlite3OsDelete(zMaster);
   703    697   
   704    698   delmaster_out:
   705    699     if( zMasterJournal ){
................................................................................
  2629   2623   
  2630   2624   /*
  2631   2625   ** Return the full pathname of the database file.
  2632   2626   */
  2633   2627   const char *sqlite3pager_filename(Pager *pPager){
  2634   2628     return pPager->zFilename;
  2635   2629   }
         2630  +
         2631  +/*
         2632  +** Return the directory of the database file.
         2633  +*/
         2634  +const char *sqlite3pager_dirname(Pager *pPager){
         2635  +  return pPager->zDirectory;
         2636  +}
         2637  +
         2638  +/*
         2639  +** Return the full pathname of the journal file.
         2640  +*/
         2641  +const char *sqlite3pager_journalname(Pager *pPager){
         2642  +  return pPager->zJournal;
         2643  +}
  2636   2644   
  2637   2645   /*
  2638   2646   ** Set the codec for this pager
  2639   2647   */
  2640   2648   void sqlite3pager_set_codec(
  2641   2649     Pager *pPager,
  2642   2650     void (*xCodec)(void*,void*,Pgno,int),

Changes to src/pager.h.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This header file defines the interface that the sqlite page cache
    13     13   ** subsystem.  The page cache subsystem reads and writes a file a page
    14     14   ** at a time and provides a journal for rollback.
    15     15   **
    16         -** @(#) $Id: pager.h,v 1.33 2004/06/09 17:37:28 drh Exp $
           16  +** @(#) $Id: pager.h,v 1.34 2004/06/14 06:03:57 danielk1977 Exp $
    17     17   */
    18     18   
    19     19   /*
    20     20   ** The size of a page.
    21     21   **
    22     22   ** You can change this value to another (reasonable) value you want.
    23     23   ** It need not be a power of two, though the interface to the disk
................................................................................
    95     95   int sqlite3pager_stmt_commit(Pager*);
    96     96   int sqlite3pager_stmt_rollback(Pager*);
    97     97   void sqlite3pager_dont_rollback(void*);
    98     98   void sqlite3pager_dont_write(Pager*, Pgno);
    99     99   int *sqlite3pager_stats(Pager*);
   100    100   void sqlite3pager_set_safety_level(Pager*,int);
   101    101   const char *sqlite3pager_filename(Pager*);
          102  +const char *sqlite3pager_dirname(Pager*);
          103  +const char *sqlite3pager_journalname(Pager*);
   102    104   int sqlite3pager_rename(Pager*, const char *zNewName);
   103    105   void sqlite3pager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*);
   104    106   
   105    107   #ifdef SQLITE_DEBUG
   106    108   int sqlite3pager_lockstate(Pager*);
   107    109   #endif
   108    110   
   109    111   #ifdef SQLITE_TEST
   110    112   void sqlite3pager_refdump(Pager*);
   111    113   int pager3_refinfo_enable;
   112    114   #endif

Changes to src/vdbeaux.c.

  1057   1057       ** still have 'null' as the master journal pointer, so they will roll
  1058   1058       ** back independantly if a failure occurs.
  1059   1059       */
  1060   1060       for(i=0; i<db->nDb; i++){ 
  1061   1061         Btree *pBt = db->aDb[i].pBt;
  1062   1062         if( i==1 ) continue;   /* Ignore the TEMP database */
  1063   1063         if( pBt && sqlite3BtreeIsInTrans(pBt) ){
  1064         -        char const *zFile = sqlite3BtreeGetFilename(pBt);
         1064  +        char const *zFile = sqlite3BtreeGetJournalname(pBt);
  1065   1065           if( zFile[0]==0 ) continue;  /* Ignore :memory: databases */
  1066   1066           rc = sqlite3OsWrite(&master, zFile, strlen(zFile)+1);
  1067   1067           if( rc!=SQLITE_OK ){
  1068   1068             sqlite3OsClose(&master);
  1069   1069             sqlite3OsDelete(zMaster);
  1070   1070             sqliteFree(zMaster);
  1071   1071             return rc;
  1072   1072           }
  1073   1073         }
  1074   1074       }
  1075   1075   
  1076         -    /* Sync the master journal file */
         1076  +
         1077  +    /* Sync the master journal file. Before doing this, open the directory
         1078  +    ** the master journal file is store in so that it gets synced too.
         1079  +    */
         1080  +    zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);
         1081  +    rc = sqlite3OsOpenDirectory(zMainFile, &master);
         1082  +    if( rc!=SQLITE_OK ){
         1083  +      sqlite3OsClose(&master);
         1084  +      sqlite3OsDelete(zMaster);
         1085  +      sqliteFree(zMaster);
         1086  +      return rc;
         1087  +    }
  1077   1088       rc = sqlite3OsSync(&master);
         1089  +    if( rc!=SQLITE_OK ){
         1090  +      sqliteFree(zMaster);
         1091  +      return rc;
         1092  +    }
  1078   1093       sqlite3OsClose(&master);
  1079   1094   
  1080         -    /* FIXME:  Sync the directory that contains the master journal to
  1081         -    ** make sure the i-node is up to date. */
  1082         -
  1083   1095       /* Sync all the db files involved in the transaction. The same call
  1084   1096       ** sets the master journal pointer in each individual journal. If
  1085   1097       ** an error occurs here, do not delete the master journal file.
  1086   1098       **
  1087   1099       ** If the error occurs during the first call to sqlite3BtreeSync(),
  1088   1100       ** then there is a chance that the master journal file will be
  1089   1101       ** orphaned. But we cannot delete it, in case the master journal