/ Check-in [08c545f0]
Login

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

Overview
Comment:Added option to restore_jrnl.tcl utility to hex dump journal pages.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 08c545f03082421166a21274b39e07bb348c17e6
User & Date: shaneh 2010-01-08 04:50:22
Original Comment: Added option to dump pages.
Context
2010-01-08
23:01
Update comments in fts3.c to more accurately describe the doclist format. check-in: e424a030 user: drh tags: trunk
04:50
Added option to restore_jrnl.tcl utility to hex dump journal pages. check-in: 08c545f0 user: shaneh tags: trunk
2010-01-07
22:02
Minor tweaks to restore_jrnl.tcl utility script. check-in: b97aca12 user: shaneh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to tool/restore_jrnl.tcl.

    10     10   #***********************************************************************
    11     11   # This file implements utility functions for SQLite library.
    12     12   #
    13     13   # This file attempts to restore the header of a journal.
    14     14   # This may be useful for rolling-back the last committed 
    15     15   # transaction from a recovered journal.
    16     16   #
    17         -# $Id: restore_jrnl.tcl,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $
    18     17   
    19     18   package require sqlite3
    20     19   
    21         -if { $argc != 2 } {
    22         -  puts "USAGE: restore_jrnl.tcl db_name jrnl_name"
    23         -  puts "Example: restore_jrnl.tcl foo.sqlite foo.sqlite-journal"
           20  +set parm_error 0
           21  +set fix_chksums 0
           22  +set dump_pages 0
           23  +set db_name ""
           24  +
           25  +for {set i 0} {$i<$argc} {incr i} {
           26  +  if {[lindex $argv $i] == "-fix_chksums"} {
           27  +    set fix_chksums -1
           28  +  } elseif {[lindex $argv $i] == "-dump_pages"} {
           29  +    set dump_pages -1
           30  +  } elseif {$db_name == ""} {
           31  +    set db_name [lindex $argv $i]
           32  +    set jrnl_name $db_name-journal
           33  +  } else {
           34  +    set parm_error -1
           35  +  }
           36  +}
           37  +if {$parm_error || $db_name == ""} {
           38  +  puts "USAGE: restore_jrnl.tcl \[-fix_chksums\] \[-dump_pages\] db_name"
           39  +  puts "Example: restore_jrnl.tcl foo.sqlite"
    24     40     return
    25         -} else {
    26         -  set db_name [lindex $argv 0]
    27         -  set jrnl_name [lindex $argv 1]
    28     41   }
    29     42   
    30     43   # is there a way to determine this?
    31     44   set sectsz 512
    32     45   
    33     46   # Copy file $from into $to
    34     47   #
................................................................................
    52     65       puts Ok
    53     66     } else {
    54     67       puts Error
    55     68       puts "  Got: $res"
    56     69       puts "  Expected: $expected"
    57     70     }
    58     71   }
           72  +
           73  +# Calc checksum nonce from journal page data.
           74  +#
           75  +proc calc_nonce {jrnl_pgno} {
           76  +  global sectsz
           77  +  global db_pgsz
           78  +  global jrnl_name
           79  +  set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$jrnl_pgno)]
           80  +  set nonce [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] 4]]
           81  +  for {set i [expr $db_pgsz-200]} {$i>0} {set i [expr $i-200]} {
           82  +    set byte [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$i] 1]]
           83  +    set nonce [expr $nonce-$byte]
           84  +  }
           85  +  return $nonce
           86  +}
           87  +
           88  +# Calc checksum from journal page data.
           89  +#
           90  +proc calc_chksum {jrnl_pgno} {
           91  +  global sectsz
           92  +  global db_pgsz
           93  +  global jrnl_name
           94  +  global nonce
           95  +  set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$jrnl_pgno)]
           96  +  set chksum $nonce
           97  +  for {set i [expr $db_pgsz-200]} {$i>0} {set i [expr $i-200]} {
           98  +    set byte [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$i] 1]]
           99  +    set chksum [expr $chksum+$byte]
          100  +  }
          101  +  return $chksum
          102  +}
          103  +
          104  +# Print journal page data in hex dump form
          105  +#
          106  +proc dump_jrnl_page {jrnl_pgno} {
          107  +  global sectsz
          108  +  global db_pgsz
          109  +  global jrnl_name
          110  +
          111  +  # print a header block for the page
          112  +  puts [string repeat "-" 79]
          113  +  set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$jrnl_pgno)]
          114  +  set db_pgno [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset] 4]]
          115  +  set chksum [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] 4]]
          116  +  set nonce [calc_nonce $jrnl_pgno]
          117  +  puts [ format {jrnl_pg_offset: %08x (%d)  jrnl_pgno: %d  db_pgno: %d} \
          118  +      $jrnl_pg_offset $jrnl_pg_offset \
          119  +      $jrnl_pgno $db_pgno]
          120  +  puts [ format {nonce: %08x chksum: %08x} \
          121  +      $nonce $chksum]
          122  +
          123  +  # now hex dump the data
          124  +  # This is derived from the Tcler's WIKI
          125  +  set fid [open $jrnl_name r]
          126  +  fconfigure $fid -translation binary -encoding binary
          127  +  seek $fid [expr $jrnl_pg_offset+4]
          128  +  set data [read $fid $db_pgsz]
          129  +  close $fid
          130  +  for {set addr 0} {$addr<$db_pgsz} {set addr [expr $addr+16]} {
          131  +    # get 16 bytes of data
          132  +    set s [string range $data $addr [expr $addr+16]]
          133  +    
          134  +    # Convert the data to hex and to characters.
          135  +    binary scan $s H*@0a* hex ascii
          136  +
          137  +    # Replace non-printing characters in the data.
          138  +    regsub -all -- {[^[:graph:] ]} $ascii {.} ascii
          139  +
          140  +    # Split the 16 bytes into two 8-byte chunks
          141  +    regexp -- {(.{16})(.{0,16})} $hex -> hex1 hex2
          142  +
          143  +    # Convert the hex to pairs of hex digits
          144  +    regsub -all -- {..} $hex1 {& } hex1
          145  +    regsub -all -- {..} $hex2 {& } hex2
          146  +
          147  +    # Print the hex and ascii data
          148  +    puts [ format {%08x %-24s %-24s %-16s} \
          149  +        $addr $hex1 $hex2 $ascii ]
          150  +  }
          151  +}
    59    152   
    60    153   # Setup for the tests.  Make a backup copy of the files.
    61    154   #
    62    155   if [file exist $db_name.org] {
    63    156     puts "ERROR: during back-up: $db_name.org exists already."
    64    157     return;
    65    158   }
................................................................................
    67    160     puts "ERROR: during back-up: $jrnl_name.org exists already."
    68    161     return
    69    162   }
    70    163   copy_file $db_name $db_name.org
    71    164   copy_file $jrnl_name $jrnl_name.org
    72    165   
    73    166   set db_fsize [file size $db_name]
    74         -sqlite3 db $db_name
    75         -set db_pgsz [db eval {PRAGMA page_size}]
    76         -db close
          167  +set db_pgsz [hexio_get_int [hexio_read $db_name 16 2]]
    77    168   set db_npage [expr {$db_fsize / $db_pgsz}]
    78    169   
    79         -# restore in case get the page_size above changed things
    80         -copy_file $db_name.org $db_name
    81         -copy_file $jrnl_name.org $jrnl_name
          170  +set jrnl_fsize [file size $jrnl_name]
          171  +set jrnl_npage [expr {($jrnl_fsize - $sectsz) / (4 + $db_pgsz + 4)}]
          172  +
          173  +# calculate checksum nonce for first page
          174  +set nonce [calc_nonce 0]
          175  +
          176  +# verify all the pages in the journal use the same nonce
          177  +for {set i 1} {$i<$jrnl_npage} {incr i} {
          178  +  set tnonce [calc_nonce $i]
          179  +  if {$tnonce != $nonce} {
          180  +    puts "WARNING: different nonces: 0=$nonce $i=$tnonce"
          181  +    if {$fix_chksums } {
          182  +      set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$i)]
          183  +      set tchksum [calc_chksum $i]
          184  +      hexio_write $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] [format %08x $tchksum]
          185  +      puts "INFO: fixing chksum: $i=$tchksum"
          186  +    }
          187  +  }
          188  +}
          189  +
          190  +# verify all the page numbers in the journal
          191  +for {set i 0} {$i<$jrnl_npage} {incr i} {
          192  +  set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$i)]
          193  +  set db_pgno [hexio_get_int [hexio_read $jrnl_name $jrnl_pg_offset 4]]
          194  +  if {$db_pgno < 1} {
          195  +    puts "WARNING: page number < 1: $i=$db_pgno"
          196  +  }
          197  +  if {$db_pgno >= $db_npage} {
          198  +    puts "WARNING: page number >= $db_npage: $i=$db_pgno"
          199  +  }
          200  +}
    82    201   
    83         -# calculate checksum nonce
    84         -set pgno 0
    85         -set pg_offset [expr $sectsz+((4+$db_pgsz+4)*$pgno)]
    86         -set nonce [hexio_get_int [hexio_read $jrnl_name [expr $pg_offset+4+$db_pgsz] 4]]
    87         -for {set i [expr $db_pgsz-200]} {$i>0} {set i [expr $i-200]} {
    88         -  set byte [hexio_get_int [hexio_read $jrnl_name [expr $pg_offset+4+$i] 1]]
    89         -  set nonce [expr $nonce-$byte]
          202  +# dump page data
          203  +if {$dump_pages} {
          204  +  for {set i 0} {$i<$jrnl_npage} {incr i} {
          205  +    dump_jrnl_page $i
          206  +  }
    90    207   }
    91    208   
    92    209   # write the 8 byte magic string
    93    210   hexio_write $jrnl_name 0 d9d505f920a163d7
    94    211   
    95    212   # write -1 for number of records
    96    213   hexio_write $jrnl_name 8 ffffffff
................................................................................
   103    220   
   104    221   # write sector size
   105    222   hexio_write $jrnl_name 20 [format %08x $sectsz]
   106    223   
   107    224   # write page size
   108    225   hexio_write $jrnl_name 24 [format %08x $db_pgsz]
   109    226   
   110         -# check the integrity of the database.
          227  +# check the integrity of the database with the patched journal
   111    228   sqlite3 db $db_name
   112    229   do_test restore_jrnl-1.0 {
   113    230     catchsql {PRAGMA integrity_check}
   114    231   } {0 ok}
   115         -
   116    232   db close
          233  +