SQLite

Check-in [79f573cc7b]
Login

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

Overview
Comment:Write the page-size into the first journal-header of each journal file. (CVS 4894)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 79f573cc7be89b3dd5540c45ef132b5cedc98e9b
User & Date: danielk1977 2008-03-20 04:45:49.000
Context
2008-03-20
10:44
stick everything that sqlite links against into Libs.private (CVS 4895) (check-in: 8b198617f5 user: vapier tags: trunk)
04:45
Write the page-size into the first journal-header of each journal file. (CVS 4894) (check-in: 79f573cc7b user: danielk1977 tags: trunk)
02:25
Make out-of-tree builds work as expected when using configure script (CVS 4893) (check-in: e2d05ea3c3 user: mlcreech tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/pager.c.
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.418 2008/03/19 14:15:35 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*







|







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.419 2008/03/20 04:45:49 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*
967
968
969
970
971
972
973

974
975
976
977
978
979
980
981
982
983
984
985
**
** The format for the journal header is as follows:
** - 8 bytes: Magic identifying journal format.
** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
** - 4 bytes: Random number used for page hash.
** - 4 bytes: Initial database page count.
** - 4 bytes: Sector size used by the process that wrote this journal.

** 
** Followed by (JOURNAL_HDR_SZ - 24) bytes of unused space.
*/
static int writeJournalHdr(Pager *pPager){
  char zHeader[sizeof(aJournalMagic)+16];
  int rc;

  if( pPager->stmtHdrOff==0 ){
    pPager->stmtHdrOff = pPager->journalOff;
  }

  seekJournalHdr(pPager);







>

|


|







967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
**
** The format for the journal header is as follows:
** - 8 bytes: Magic identifying journal format.
** - 4 bytes: Number of records in journal, or -1 no-sync mode is on.
** - 4 bytes: Random number used for page hash.
** - 4 bytes: Initial database page count.
** - 4 bytes: Sector size used by the process that wrote this journal.
** - 4 bytes: Database page size.
** 
** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
*/
static int writeJournalHdr(Pager *pPager){
  char zHeader[sizeof(aJournalMagic)+20];
  int rc;

  if( pPager->stmtHdrOff==0 ){
    pPager->stmtHdrOff = pPager->journalOff;
  }

  seekJournalHdr(pPager);
1019
1020
1021
1022
1023
1024
1025




1026
1027
1028
1029
1030
1031
1032
  /* The random check-hash initialiser */ 
  sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
  put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
  /* The initial database size */
  put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize);
  /* The assumed sector size for this process */
  put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);




  IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, sizeof(zHeader)))
  rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader),pPager->journalOff);
  pPager->journalOff += JOURNAL_HDR_SZ(pPager);

  /* The journal header has been written successfully. Seek the journal
  ** file descriptor to the end of the journal header sector.
  */







>
>
>
>







1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
  /* The random check-hash initialiser */ 
  sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
  put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
  /* The initial database size */
  put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize);
  /* The assumed sector size for this process */
  put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
  if( pPager->journalHdr==0 ){
    /* The page size */
    put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);
  }
  IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, sizeof(zHeader)))
  rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader),pPager->journalOff);
  pPager->journalOff += JOURNAL_HDR_SZ(pPager);

  /* The journal header has been written successfully. Seek the journal
  ** file descriptor to the end of the journal header sector.
  */
1058
1059
1060
1061
1062
1063
1064

1065
1066
1067
1068
1069
1070
1071
  i64 journalSize,
  u32 *pNRec, 
  u32 *pDbSize
){
  int rc;
  unsigned char aMagic[8]; /* A buffer to hold the magic header */
  i64 jrnlOff;


  seekJournalHdr(pPager);
  if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
    return SQLITE_DONE;
  }
  jrnlOff = pPager->journalOff;








>







1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
  i64 journalSize,
  u32 *pNRec, 
  u32 *pDbSize
){
  int rc;
  unsigned char aMagic[8]; /* A buffer to hold the magic header */
  i64 jrnlOff;
  int iPageSize;

  seekJournalHdr(pPager);
  if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
    return SQLITE_DONE;
  }
  jrnlOff = pPager->journalOff;

1081
1082
1083
1084
1085
1086
1087











1088
1089
1090
1091
1092
1093
1094
  if( rc ) return rc;

  rc = read32bits(pPager->jfd, jrnlOff+4, &pPager->cksumInit);
  if( rc ) return rc;

  rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize);
  if( rc ) return rc;












  /* Update the assumed sector-size to match the value used by 
  ** the process that created this journal. If this journal was
  ** created by a process other than this one, then this routine
  ** is being called from within pager_playback(). The local value
  ** of Pager.sectorSize is restored at the end of that routine.
  */







>
>
>
>
>
>
>
>
>
>
>







1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
  if( rc ) return rc;

  rc = read32bits(pPager->jfd, jrnlOff+4, &pPager->cksumInit);
  if( rc ) return rc;

  rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize);
  if( rc ) return rc;

  rc = read32bits(pPager->jfd, jrnlOff+16, (u32 *)&iPageSize);
  if( rc==SQLITE_OK 
   && iPageSize>=512 
   && iPageSize<=SQLITE_MAX_PAGE_SIZE 
   && ((iPageSize-1)&iPageSize)==0 
  ){
    u16 pagesize = iPageSize;
    rc = sqlite3PagerSetPagesize(pPager, &pagesize);
  }
  if( rc ) return rc;

  /* Update the assumed sector-size to match the value used by 
  ** the process that created this journal. If this journal was
  ** created by a process other than this one, then this routine
  ** is being called from within pager_playback(). The local value
  ** of Pager.sectorSize is restored at the end of that routine.
  */
Added test/crash6.test.






































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# 2001 September 15
#
# 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.
#
#***********************************************************************
# This file tests that rollback journals for databases that use a 
# page-size other than the default page-size can be rolled back Ok.
#
# $Id: crash6.test,v 1.1 2008/03/20 04:45:49 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !crashtest {
  finish_test
  return
}

for {set ii 0} {$ii < 10} {incr ii} {
  catch {db close}
  file delete -force test.db test.db-journal
  crashsql -delay 2 -file test.db {
    PRAGMA auto_vacuum=OFF;
    PRAGMA page_size=4096;
    BEGIN;
    CREATE TABLE abc AS SELECT 1 AS a, 2 AS b, 3 AS c;
    COMMIT;
    BEGIN;
    CREATE TABLE def AS SELECT 1 AS d, 2 AS e, 3 AS f;
    COMMIT;
  }
  sqlite3 db test.db
  integrity_check crash6-1.$ii
}

for {set ii 0} {$ii < 10} {incr ii} {
  catch {db close}
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  execsql {
    PRAGMA auto_vacuum=OFF;
    PRAGMA page_size=2048;
    BEGIN;
    CREATE TABLE abc AS SELECT 1 AS a, 2 AS b, 3 AS c;
    COMMIT;
  }
  db close
  crashsql -delay 1 -file test.db {
    INSERT INTO abc VALUES(5, 6, 7);
  }
  sqlite3 db test.db
  integrity_check crash6-2.$ii
}

proc signature {} {
  return [db eval {SELECT count(*), md5sum(a), md5sum(b), md5sum(c) FROM abc}]
}

# Test case for crashing during database sync with page-size values 
# from 1024 to 8192.
#
for {set ii 0} {$ii < 30} {incr ii} {
  db close
  file delete -force test.db
  sqlite3 db test.db

  set pagesize [expr 1024 << ($ii % 4)]
  do_test crash6-3.$ii.0 {
    execsql "pragma page_size = $pagesize"
    execsql "pragma page_size"
  } $pagesize

  do_test crash6-3.$ii.1 {
  
    execsql BEGIN
    execsql {CREATE TABLE abc(a, b, c)}
    for {set n 0} {$n < 1000} {incr n} {
      execsql "INSERT INTO abc VALUES($n, [expr 2*$n], [expr 3*$n])"
    }
    execsql {
      INSERT INTO abc SELECT * FROM abc;
      INSERT INTO abc SELECT * FROM abc;
      INSERT INTO abc SELECT * FROM abc;
      INSERT INTO abc SELECT * FROM abc;
      INSERT INTO abc SELECT * FROM abc;
    }
    execsql COMMIT
    expr ([file size test.db] / 1024) > 450
  } {1}

  set sig [signature]
  db close

  do_test crash6-3.$ii.2 {
     crashsql -file test.db "
       BEGIN;
       SELECT random() FROM abc LIMIT $ii;
       INSERT INTO abc SELECT randstr(10,10), 0, 0 FROM abc WHERE random()%2==0;
       DELETE FROM abc WHERE random()%2!=0;
       COMMIT;
     "
  } {1 {child process exited abnormally}}

  do_test crash6-3.$ii.3 {
    sqlite3 db test.db
    signature
  } $sig
} 

finish_test
Changes to test/quick.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#
#    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.
#
#***********************************************************************
# This file runs all tests.
#
# $Id: quick.test,v 1.69 2008/01/16 18:20:42 danielk1977 Exp $

proc lshift {lvar} {
  upvar $lvar l
  set ret [lindex $l 0]
  set l [lrange $l 1 end]
  return $ret
}








|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#
#    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.
#
#***********************************************************************
# This file runs all tests.
#
# $Id: quick.test,v 1.70 2008/03/20 04:45:49 danielk1977 Exp $

proc lshift {lvar} {
  upvar $lvar l
  set ret [lindex $l 0]
  set l [lrange $l 1 end]
  return $ret
}
45
46
47
48
49
50
51

52
53
54
55
56
57
58
  btree5.test
  btree6.test
  corrupt.test
  crash.test
  crash2.test
  crash3.test
  crash4.test

  exclusive3.test
  fts3.test
  fuzz.test
  fuzz_malloc.test
  in2.test
  loadext.test
  mallocAll.test







>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  btree5.test
  btree6.test
  corrupt.test
  crash.test
  crash2.test
  crash3.test
  crash4.test
  crash6.test
  exclusive3.test
  fts3.test
  fuzz.test
  fuzz_malloc.test
  in2.test
  loadext.test
  mallocAll.test