From: shaneh Date: Fri, 8 Jan 2010 04:50:22 +0000 (+0000) Subject: Added option to dump pages. X-Git-Tag: version-3.7.2~653 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0a7905295c0a039a17d517378e9cd2632401196f;p=thirdparty%2Fsqlite.git Added option to dump pages. FossilOrigin-Name: 08c545f03082421166a21274b39e07bb348c17e6 --- diff --git a/manifest b/manifest index 8721c80887..484deaaa1b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\stweaks\sto\srestore_jrnl.tcl\sutility\sscript. -D 2010-01-07T22:02:35 +C Added\soption\sto\sdump\spages. +D 2010-01-08T04:50:22 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -770,7 +770,7 @@ F tool/mksqlite3h.tcl eb100dce83f24b501b325b340f8b5eb8e5106b3b F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87 F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c -F tool/restore_jrnl.tcl 81dabc8951580e0983ea867631be855dc93358ce +F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a F tool/shell1.test ef08a3e738b9fee4fc228920956950bc35db0575 F tool/shell2.test 91824fff77514b6b00227744c475c09c34134a4e F tool/shell3.test ff663e83100670a295d473515c12beb8103a78b6 @@ -785,7 +785,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 05b18b5f6a38f513ff49656faada725eb44715b7 -R 99c2a9dd26b7b50e819f5bcbbba2a04f +P b97aca1200d959a1e7c08dd4e9dbce4724342119 +R 954d1ee5bc4e8dbfdb8e25f58c6f3247 U shaneh -Z 2f756cb564fe45590ccd32f9d897b68c +Z 6999a75f8e62879e0ec4ab88e2a317f7 diff --git a/manifest.uuid b/manifest.uuid index ecfbe66b43..d3a6f52e19 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b97aca1200d959a1e7c08dd4e9dbce4724342119 \ No newline at end of file +08c545f03082421166a21274b39e07bb348c17e6 \ No newline at end of file diff --git a/tool/restore_jrnl.tcl b/tool/restore_jrnl.tcl index 66ec279dab..05af4f9a2a 100644 --- a/tool/restore_jrnl.tcl +++ b/tool/restore_jrnl.tcl @@ -14,17 +14,30 @@ # This may be useful for rolling-back the last committed # transaction from a recovered journal. # -# $Id: restore_jrnl.tcl,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $ package require sqlite3 -if { $argc != 2 } { - puts "USAGE: restore_jrnl.tcl db_name jrnl_name" - puts "Example: restore_jrnl.tcl foo.sqlite foo.sqlite-journal" - return -} else { - set db_name [lindex $argv 0] - set jrnl_name [lindex $argv 1] +set parm_error 0 +set fix_chksums 0 +set dump_pages 0 +set db_name "" + +for {set i 0} {$i<$argc} {incr i} { + if {[lindex $argv $i] == "-fix_chksums"} { + set fix_chksums -1 + } elseif {[lindex $argv $i] == "-dump_pages"} { + set dump_pages -1 + } elseif {$db_name == ""} { + set db_name [lindex $argv $i] + set jrnl_name $db_name-journal + } else { + set parm_error -1 + } +} +if {$parm_error || $db_name == ""} { + puts "USAGE: restore_jrnl.tcl \[-fix_chksums\] \[-dump_pages\] db_name" + puts "Example: restore_jrnl.tcl foo.sqlite" + return } # is there a way to determine this? @@ -57,6 +70,86 @@ proc do_test {name cmd expected} { } } +# Calc checksum nonce from journal page data. +# +proc calc_nonce {jrnl_pgno} { + global sectsz + global db_pgsz + global jrnl_name + set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$jrnl_pgno)] + set nonce [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] 4]] + for {set i [expr $db_pgsz-200]} {$i>0} {set i [expr $i-200]} { + set byte [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$i] 1]] + set nonce [expr $nonce-$byte] + } + return $nonce +} + +# Calc checksum from journal page data. +# +proc calc_chksum {jrnl_pgno} { + global sectsz + global db_pgsz + global jrnl_name + global nonce + set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$jrnl_pgno)] + set chksum $nonce + for {set i [expr $db_pgsz-200]} {$i>0} {set i [expr $i-200]} { + set byte [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$i] 1]] + set chksum [expr $chksum+$byte] + } + return $chksum +} + +# Print journal page data in hex dump form +# +proc dump_jrnl_page {jrnl_pgno} { + global sectsz + global db_pgsz + global jrnl_name + + # print a header block for the page + puts [string repeat "-" 79] + set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$jrnl_pgno)] + set db_pgno [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset] 4]] + set chksum [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] 4]] + set nonce [calc_nonce $jrnl_pgno] + puts [ format {jrnl_pg_offset: %08x (%d) jrnl_pgno: %d db_pgno: %d} \ + $jrnl_pg_offset $jrnl_pg_offset \ + $jrnl_pgno $db_pgno] + puts [ format {nonce: %08x chksum: %08x} \ + $nonce $chksum] + + # now hex dump the data + # This is derived from the Tcler's WIKI + set fid [open $jrnl_name r] + fconfigure $fid -translation binary -encoding binary + seek $fid [expr $jrnl_pg_offset+4] + set data [read $fid $db_pgsz] + close $fid + for {set addr 0} {$addr<$db_pgsz} {set addr [expr $addr+16]} { + # get 16 bytes of data + set s [string range $data $addr [expr $addr+16]] + + # Convert the data to hex and to characters. + binary scan $s H*@0a* hex ascii + + # Replace non-printing characters in the data. + regsub -all -- {[^[:graph:] ]} $ascii {.} ascii + + # Split the 16 bytes into two 8-byte chunks + regexp -- {(.{16})(.{0,16})} $hex -> hex1 hex2 + + # Convert the hex to pairs of hex digits + regsub -all -- {..} $hex1 {& } hex1 + regsub -all -- {..} $hex2 {& } hex2 + + # Print the hex and ascii data + puts [ format {%08x %-24s %-24s %-16s} \ + $addr $hex1 $hex2 $ascii ] + } +} + # Setup for the tests. Make a backup copy of the files. # if [file exist $db_name.org] { @@ -71,32 +164,56 @@ copy_file $db_name $db_name.org copy_file $jrnl_name $jrnl_name.org set db_fsize [file size $db_name] -sqlite3 db $db_name -set db_pgsz [db eval {PRAGMA page_size}] -db close +set db_pgsz [hexio_get_int [hexio_read $db_name 16 2]] set db_npage [expr {$db_fsize / $db_pgsz}] -# restore in case get the page_size above changed things -copy_file $db_name.org $db_name -copy_file $jrnl_name.org $jrnl_name - -# calculate checksum nonce -set pgno 0 -set pg_offset [expr $sectsz+((4+$db_pgsz+4)*$pgno)] -set nonce [hexio_get_int [hexio_read $jrnl_name [expr $pg_offset+4+$db_pgsz] 4]] -for {set i [expr $db_pgsz-200]} {$i>0} {set i [expr $i-200]} { - set byte [hexio_get_int [hexio_read $jrnl_name [expr $pg_offset+4+$i] 1]] - set nonce [expr $nonce-$byte] +set jrnl_fsize [file size $jrnl_name] +set jrnl_npage [expr {($jrnl_fsize - $sectsz) / (4 + $db_pgsz + 4)}] + +# calculate checksum nonce for first page +set nonce [calc_nonce 0] + +# verify all the pages in the journal use the same nonce +for {set i 1} {$i<$jrnl_npage} {incr i} { + set tnonce [calc_nonce $i] + if {$tnonce != $nonce} { + puts "WARNING: different nonces: 0=$nonce $i=$tnonce" + if {$fix_chksums } { + set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$i)] + set tchksum [calc_chksum $i] + hexio_write $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] [format %08x $tchksum] + puts "INFO: fixing chksum: $i=$tchksum" + } + } +} + +# verify all the page numbers in the journal +for {set i 0} {$i<$jrnl_npage} {incr i} { + set jrnl_pg_offset [expr $sectsz+((4+$db_pgsz+4)*$i)] + set db_pgno [hexio_get_int [hexio_read $jrnl_name $jrnl_pg_offset 4]] + if {$db_pgno < 1} { + puts "WARNING: page number < 1: $i=$db_pgno" + } + if {$db_pgno >= $db_npage} { + puts "WARNING: page number >= $db_npage: $i=$db_pgno" + } +} + +# dump page data +if {$dump_pages} { + for {set i 0} {$i<$jrnl_npage} {incr i} { + dump_jrnl_page $i + } } # write the 8 byte magic string -hexio_write $jrnl_name 0 d9d505f920a163d7 - -# write -1 for number of records -hexio_write $jrnl_name 8 ffffffff - -# write 00 for checksum nonce -hexio_write $jrnl_name 12 [format %08x $nonce] +hexio_write $jrnl_name 0 d9d505f920a163d7 + +# write -1 for number of records +hexio_write $jrnl_name 8 ffffffff + +# write 00 for checksum nonce +hexio_write $jrnl_name 12 [format %08x $nonce] # write page count hexio_write $jrnl_name 16 [format %08x $db_npage] @@ -107,10 +224,10 @@ hexio_write $jrnl_name 20 [format %08x $sectsz] # write page size hexio_write $jrnl_name 24 [format %08x $db_pgsz] -# check the integrity of the database. +# check the integrity of the database with the patched journal sqlite3 db $db_name do_test restore_jrnl-1.0 { catchsql {PRAGMA integrity_check} } {0 ok} - db close +