Annotation of loncom/debugging_tools/rebuild_db_from_hist.pl, revision 1.4
1.1 matthew 1: #!/usr/bin/perl -w
2: #
3: # The LearningOnline Network
4: #
5: # rebuild_db_from_hist.pl Rebuild a *.db file from a *.hist file
6: #
1.4 ! matthew 7: # $Id: rebuild_db_from_hist.pl,v 1.3 2004/12/09 20:01:48 matthew Exp $
1.1 matthew 8: #
9: # Copyright Michigan State University Board of Trustees
10: #
11: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
12: #
13: # LON-CAPA is free software; you can redistribute it and/or modify
14: # it under the terms of the GNU General Public License as published by
15: # the Free Software Foundation; either version 2 of the License, or
16: # (at your option) any later version.
17: #
18: # LON-CAPA is distributed in the hope that it will be useful,
19: # but WITHOUT ANY WARRANTY; without even the implied warranty of
20: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21: # GNU General Public License for more details.
22: #
23: # You should have received a copy of the GNU General Public License
24: # along with LON-CAPA; if not, write to the Free Software
25: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26: #
27: # /home/httpd/html/adm/gpl.txt
28: #
29: # http://www.lon-capa.org/
30: #
31: #################################################
32: use strict;
33: use Getopt::Long;
34: use GDBM_File;
35:
36: #
37: # Options
1.4 ! matthew 38: my ($help,$debug,$test,$p_is_s);
1.1 matthew 39: GetOptions("help" => \$help,
40: "debug" => \$debug,
1.4 ! matthew 41: "test" => \$test,
! 42: "p_is_s" => \$p_is_s);
1.1 matthew 43:
44: if (! defined($debug)) { $debug = 0; }
45: if (! defined($test)) { $test = 0; }
46:
47: #
48: # Help them out if they ask for it
49: if ($help) {
50: print <<'END';
51: rebuild_db_from_hist.pl - recreate a db file from a hist file.
52: Options:
53: -help Display this help.
1.2 matthew 54: -debug Output debugging code (not much is output yet)
55: -test Verify the given *.hist file will reconstruct the current db file
56: Sends error messages to STDERR.
1.4 ! matthew 57: -p_is_s Treat 'P' lines as 'S' lines.
1.1 matthew 58: Examples:
1.2 matthew 59: rebuild_db_from_hist.pl -t $file.hist # Perform a test rebuild
60: rebuild_db_from_hist.pl $file.hist
1.1 matthew 61: END
62: exit;
63: }
64:
65: #
66: # Loop through ARGV getting files.
67: while (my $fname = shift) {
68: my $db_filename = $fname;
69: $db_filename =~ s/\.hist$/\.db/;
70: if (-e $db_filename && ! $test) {
71: print STDERR "Aborting: The target file $db_filename exists.".$/;
72: next;
73: }
1.3 matthew 74: my ($error,$constructed_hash) = &process_file($fname,$db_filename,$debug);
1.1 matthew 75: if (! defined($error) || ! $test) {
76: $error = &write_hash($db_filename,$constructed_hash);
77: }
78: if ($test) {
79: my $error = &test_hash($db_filename,$constructed_hash);
80: if (defined($error)) {
81: print "Error processing ".$fname.$/;
82: print STDERR $error;
83: } else {
84: print "Everything looks good for ".$fname.$/;
85: }
86: }
87: if (defined($error)) {
88: print $error.$/;
89: }
90: }
91:
92: exit;
93:
94: ######################################################
95: ######################################################
96: sub process_file {
97: my ($fname,$db_filename,$debug) = @_;
98: #
99: open(HISTFILE,$fname);
100: my %db_to_store;
101: my $no_action_count = 0;
102: while (my $command = <HISTFILE>) {
103: chomp($command);
104: my $error = undef;
105: # Each line can begin with:
106: # P:put
107: # D:delete
108: my ($action,$time,$concatenated_data) = split(':',$command,3);
1.3 matthew 109: if ($fname eq 'roles.hist' && $concatenated_data =~ /^.*:.*:/) {
110: (undef,undef,$concatenated_data) = split(':',$concatenated_data,3);
111: }
1.4 ! matthew 112: next if (! defined($action));
! 113: if ($action eq 'P' && $p_is_s) { $action = 'S'; }
! 114: my ($rid,$allkeys,$version);
! 115: if ($action eq 'S') {
! 116: ($rid,$concatenated_data) = split(':',$concatenated_data,2);
! 117: $version = ++$db_to_store{"version:$rid"};
! 118: # print $version.$/;
! 119: }
! 120: next if (! defined($concatenated_data));
1.1 matthew 121: my @data = split('&',$concatenated_data);
122: foreach my $k_v_pair (@data) {
123: my ($key,$value) = split('=',$k_v_pair,2);
124: if (defined($action) && $action eq 'P') {
125: if (defined($value)) {
126: $db_to_store{$key}=$value;
127: } else {
128: $no_action_count++;
129: }
1.4 ! matthew 130: } elsif ($action eq 'S') {
! 131: # Versioning of data, so we update the old ata
! 132: $allkeys.=$key.':';
! 133: $db_to_store{"$version:$rid:$key"}=$value;
1.1 matthew 134: } elsif ($action eq 'D') {
135: delete($db_to_store{$key});
136: } else {
137: $error = "Unable to understand action '".$action."'";
138: }
139: }
1.4 ! matthew 140: if ($action eq 'S') {
! 141: $db_to_store{"$version:$rid:timestamp"}=$time;
! 142: $allkeys.='timestamp';
! 143: $db_to_store{"$version:keys:$rid"}=$allkeys;
! 144: }
1.1 matthew 145: if (defined($error)) {
146: return ('Error:'.$error.$/,undef);
147: }
148: }
149: if ($no_action_count) {
150: print $no_action_count.' lines did not require action.'.$/;
151: }
152: close(HISTFILE);
153: return (undef,\%db_to_store);
154: }
155:
156: sub write_hash {
157: my ($db_filename,$db_to_store) = @_;
158: #
159: # Write the gdbm file
160: my %db;
161: if (! tie(%db,'GDBM_File',$db_filename,&GDBM_WRCREAT(),0640)) {
162: warn "Unable to tie to $db_filename";
163: return "Unable to tie to $db_filename";
164: }
165: #
166: while (my ($k,$v) = each(%$db_to_store)) {
167: $db{$k}=$v;
168: }
169: #
170: untie(%db);
171: return undef;
172: }
173:
174: sub test_hash {
175: my ($db_filename,$my_db) = @_;
176: #
177: my %db;
178: if (! tie(%db,'GDBM_File',$db_filename,&GDBM_READER(),0640)) {
179: return "Unable to tie to $db_filename";;
180: }
181: my (%key_errors,%value_errors);
182: while (my ($k,$v) = each(%db)) {
183: if (exists($my_db->{$k})) {
184: if ($my_db->{$k} eq $v) {
185: delete($my_db->{$k});
186: } else {
187: $value_errors{$k}=$v;
188: }
189: } else {
190: $key_errors{$k}=$v;
191: }
192: }
193: untie(%db);
194: #
195: my $error;
196: my $extra_count = scalar(keys(%$my_db));
197: if ($extra_count) {
1.4 ! matthew 198: $error.=$extra_count.' extra key/value pairs found in hist: '.$/;
1.1 matthew 199: while (my ($k,$v) = each(%$my_db)) {
200: $error .= ' "'.$k.'" => "'.$v.'"'.$/;
201: }
202: }
203: my $key_count = scalar(keys(%key_errors));
204: if ($key_count) {
1.4 ! matthew 205: $error.=$key_count.' missing keys found in db but not in hist: '.$/;
1.1 matthew 206: while (my ($k,$v) = each(%key_errors)) {
207: $error .= ' "'.$k.'" => "'.$v.'"'.$/;
208: }
209: }
210: my $value_count = scalar(keys(%value_errors));
211: if ($value_count) {
1.4 ! matthew 212: $error.=$value_count.' mismatched values found: '.$/;
1.1 matthew 213: while (my ($k,$v) = each(%value_errors)) {
214: $error .= ' "'.$k.'" => "'.$v.'"'.$/;
215: }
216: }
217: #
218: return $error;
219: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>