/ Check-in [79f573cc]
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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:79f573cc7be89b3dd5540c45ef132b5cedc98e9b
User & Date: danielk1977 2008-03-20 04:45:49
Context
2008-03-20
10:44
stick everything that sqlite links against into Libs.private (CVS 4895) check-in: 8b198617 user: vapier tags: trunk
04:45
Write the page-size into the first journal-header of each journal file. (CVS 4894) check-in: 79f573cc user: danielk1977 tags: trunk
02:25
Make out-of-tree builds work as expected when using configure script (CVS 4893) check-in: e2d05ea3 user: mlcreech tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
967
968
969
970
971
972
973

974
975
976
977
978
979
980
981
982
983
984
985
....
1019
1020
1021
1022
1023
1024
1025




1026
1027
1028
1029
1030
1031
1032
....
1058
1059
1060
1061
1062
1063
1064

1065
1066
1067
1068
1069
1070
1071
....
1081
1082
1083
1084
1085
1086
1087











1088
1089
1090
1091
1092
1093
1094
** 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>

/*
................................................................................
**
** 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);
................................................................................
  /* 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.
  */
................................................................................
  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;

................................................................................
  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.
  */







|







 







>

|


|







 







>
>
>
>







 







>







 







>
>
>
>
>
>
>
>
>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
....
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
....
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
....
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
** 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>

/*
................................................................................
**
** 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);
................................................................................
  /* 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.
  */
................................................................................
  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;

................................................................................
  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.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
..
45
46
47
48
49
50
51

52
53
54
55
56
57
58
#    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
}
................................................................................
  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







|







 







>







2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
..
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#    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
}
................................................................................
  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