SQLite

Check-in [73cd0aabb2]
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
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 73cd0aabb24f7b663c8b55cf5e8fcb34fd48c032
User & Date: danielk1977 2004-06-14 06:03:57.000
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: 76ac9a787b 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: 73cd0aabb2 user: danielk1977 tags: trunk)
05:10
Update the file change counter just before each transaction is committed. (CVS 1582) (check-in: 4649abcbfd user: danielk1977 tags: trunk)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/btree.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/*
** 2004 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    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:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.
4191
4192
4193
4194
4195
4196
4197


















4198
4199
4200
4201
4202
4203
4204
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







/*
** Return the full pathname of the underlying database file.
*/
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.
**
** The size of file pBtFrom may be reduced by this operation.
** If anything goes wrong, the transaction on pBtFrom is rolled back.
Changes to src/btree.h.
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23







-
+







**    May you share freely, never taking more than you give.
**
*************************************************************************
** 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
** needs to be revisited.
*/
55
56
57
58
59
60
61


62
63
64
65
66
67
68
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70







+
+







int sqlite3BtreeRollbackStmt(Btree*);
int sqlite3BtreeCreateTable(Btree*, int*, int flags);
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:
*/
#define BTREE_INTKEY     1    /* Table has only 64-bit signed integer keys */
#define BTREE_ZERODATA   2    /* Table has keys only - no data */
Changes to src/pager.c.
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
14
15
16
17
18
19
20

21
22
23
24
25
26
27
28







-
+







** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** 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 <assert.h>
#include <string.h>

611
612
613
614
615
616
617
618
619
620
621
622
623
624













625
626
627
628

629
630
631
632
633


634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
611
612
613
614
615
616
617

618
619
620
621


622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642


643
644








645
646
647
648
649
650
651
652
653
654

655
656
657
658
659
660
661







-




-
-
+
+
+
+
+
+
+
+
+
+
+
+
+




+



-
-
+
+
-
-
-
-
-
-
-
-










-








  /* Open the master journal file exclusively in case some other process
  ** 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)<nMasterJournal ){
    zJournal = zMasterJournal;
    while( (zJournal-zMasterJournal)<nMasterJournal ){
      char *zJournal = 0;
      /*** FIX ME:  Store the full journal name in the master journal,
      **** not just the base database name. ***/
      sqlite3SetString(&zJournal, zDb, "-journal", 0);
      if( !zJournal ){
        rc = SQLITE_NOMEM;
        goto delmaster_out;
      }
      if( sqlite3OsFileExists(zJournal) ){
        /* One of the journals pointed to by the master journal exists.
        ** Open it and check if it points at the master journal. If
        ** so, return without deleting the master journal file.
        */
        OsFile journal;
        int nMaster;
        off_t jsz;

        rc = sqlite3OsOpenReadOnly(zJournal, &journal);
        sqliteFree(zJournal);
        if( rc!=SQLITE_OK ){
          sqlite3OsClose(&journal);
          goto delmaster_out;
        }

	/* Check if the file is big enough to be a journal file
        ** with the required master journal name. If not, ignore it.
672
673
674
675
676
677
678
679
680
681
682
683

684
685
686

687
688
689
690
691

692
693
694
695
696
697
698

699
700
701
702
703
704
705
674
675
676
677
678
679
680





681



682
683

684
685

686
687

688
689
690
691

692
693
694
695
696
697
698
699







-
-
-
-
-
+
-
-
-
+

-


-
+

-




-
+







        ** is stored. Read the master journal name into memory obtained
        ** from malloc.
        */
        rc = sqlite3OsSeek(&journal, 20);
        if( rc!=SQLITE_OK ) goto delmaster_out;
        rc = read32bits(&journal, (u32*)&nMaster);
        if( rc!=SQLITE_OK ) goto delmaster_out;
        if( nMaster>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 ){
        if( nMaster>=nMasterPtr ){
            rc = SQLITE_NOMEM;
          }
          rc = sqlite3OsRead(&journal, zMasterPtr, nMaster);
          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);

delmaster_out:
  if( zMasterJournal ){
2629
2630
2631
2632
2633
2634
2635














2636
2637
2638
2639
2640
2641
2642
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650







+
+
+
+
+
+
+
+
+
+
+
+
+
+








/*
** 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(
  Pager *pPager,
  void (*xCodec)(void*,void*,Pgno,int),
Changes to src/pager.h.
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23







-
+







**    May you share freely, never taking more than you give.
**
*************************************************************************
** 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.
**
** You can change this value to another (reasonable) value you want.
** It need not be a power of two, though the interface to the disk
95
96
97
98
99
100
101


102
103
104
105
106
107
108
109
110
111
112
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114







+
+











int sqlite3pager_stmt_commit(Pager*);
int sqlite3pager_stmt_rollback(Pager*);
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*);
#endif

#ifdef SQLITE_TEST
void sqlite3pager_refdump(Pager*);
int pager3_refinfo_enable;
#endif
Changes to src/vdbeaux.c.
1057
1058
1059
1060
1061
1062
1063
1064

1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075

1076
1077
1078
1079
1080












1081
1082






1083
1084
1085
1086
1087
1088
1089
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076





1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088


1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101







-
+











+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+







    ** still have 'null' as the master journal pointer, so they will roll
    ** back independantly if a failure occurs.
    */
    for(i=0; i<db->nDb; 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);
          sqliteFree(zMaster);
          return rc;
        }
      }
    }


    /* Sync the master journal file */
    rc = sqlite3OsSync(&master);
    sqlite3OsClose(&master);

    /* FIXME:  Sync the directory that contains the master journal to
    /* 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);
    ** make sure the i-node is up to date. */

    if( rc!=SQLITE_OK ){
      sqliteFree(zMaster);
      return rc;
    }
    sqlite3OsClose(&master);

    /* 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(),
    ** then there is a chance that the master journal file will be
    ** orphaned. But we cannot delete it, in case the master journal