File:
[LON-CAPA] /
loncom /
debugging_tools /
rebuild_db_from_hist.pl
Revision
1.4:
download - view:
text,
annotated -
select for diffs
Thu Dec 9 22:25:47 2004 UTC (19 years, 9 months ago) by
matthew
Branches:
MAIN
CVS tags:
version_2_1_X,
version_2_1_99_2,
version_2_1_99_1,
version_2_1_99_0,
version_2_1_3,
version_2_1_2,
version_2_1_1,
version_2_1_0,
version_2_0_X,
version_2_0_99_1,
version_2_0_2,
version_2_0_1,
version_2_0_0,
version_1_99_3,
version_1_99_2,
version_1_99_1_tmcc,
version_1_99_1,
version_1_99_0_tmcc,
version_1_99_0,
version_1_3_X,
version_1_3_3,
version_1_3_2,
version_1_3_1,
version_1_3_0,
version_1_2_99_1,
HEAD
Added handling of 'S' storage.
Made error messages a little more specific.
#!/usr/bin/perl -w
#
# The LearningOnline Network
#
# rebuild_db_from_hist.pl Rebuild a *.db file from a *.hist file
#
# $Id: rebuild_db_from_hist.pl,v 1.4 2004/12/09 22:25:47 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
#################################################
use strict;
use Getopt::Long;
use GDBM_File;
#
# Options
my ($help,$debug,$test,$p_is_s);
GetOptions("help" => \$help,
"debug" => \$debug,
"test" => \$test,
"p_is_s" => \$p_is_s);
if (! defined($debug)) { $debug = 0; }
if (! defined($test)) { $test = 0; }
#
# Help them out if they ask for it
if ($help) {
print <<'END';
rebuild_db_from_hist.pl - recreate a db file from a hist file.
Options:
-help Display this help.
-debug Output debugging code (not much is output yet)
-test Verify the given *.hist file will reconstruct the current db file
Sends error messages to STDERR.
-p_is_s Treat 'P' lines as 'S' lines.
Examples:
rebuild_db_from_hist.pl -t $file.hist # Perform a test rebuild
rebuild_db_from_hist.pl $file.hist
END
exit;
}
#
# Loop through ARGV getting files.
while (my $fname = shift) {
my $db_filename = $fname;
$db_filename =~ s/\.hist$/\.db/;
if (-e $db_filename && ! $test) {
print STDERR "Aborting: The target file $db_filename exists.".$/;
next;
}
my ($error,$constructed_hash) = &process_file($fname,$db_filename,$debug);
if (! defined($error) || ! $test) {
$error = &write_hash($db_filename,$constructed_hash);
}
if ($test) {
my $error = &test_hash($db_filename,$constructed_hash);
if (defined($error)) {
print "Error processing ".$fname.$/;
print STDERR $error;
} else {
print "Everything looks good for ".$fname.$/;
}
}
if (defined($error)) {
print $error.$/;
}
}
exit;
######################################################
######################################################
sub process_file {
my ($fname,$db_filename,$debug) = @_;
#
open(HISTFILE,$fname);
my %db_to_store;
my $no_action_count = 0;
while (my $command = <HISTFILE>) {
chomp($command);
my $error = undef;
# Each line can begin with:
# P:put
# D:delete
my ($action,$time,$concatenated_data) = split(':',$command,3);
if ($fname eq 'roles.hist' && $concatenated_data =~ /^.*:.*:/) {
(undef,undef,$concatenated_data) = split(':',$concatenated_data,3);
}
next if (! defined($action));
if ($action eq 'P' && $p_is_s) { $action = 'S'; }
my ($rid,$allkeys,$version);
if ($action eq 'S') {
($rid,$concatenated_data) = split(':',$concatenated_data,2);
$version = ++$db_to_store{"version:$rid"};
# print $version.$/;
}
next if (! defined($concatenated_data));
my @data = split('&',$concatenated_data);
foreach my $k_v_pair (@data) {
my ($key,$value) = split('=',$k_v_pair,2);
if (defined($action) && $action eq 'P') {
if (defined($value)) {
$db_to_store{$key}=$value;
} else {
$no_action_count++;
}
} elsif ($action eq 'S') {
# Versioning of data, so we update the old ata
$allkeys.=$key.':';
$db_to_store{"$version:$rid:$key"}=$value;
} elsif ($action eq 'D') {
delete($db_to_store{$key});
} else {
$error = "Unable to understand action '".$action."'";
}
}
if ($action eq 'S') {
$db_to_store{"$version:$rid:timestamp"}=$time;
$allkeys.='timestamp';
$db_to_store{"$version:keys:$rid"}=$allkeys;
}
if (defined($error)) {
return ('Error:'.$error.$/,undef);
}
}
if ($no_action_count) {
print $no_action_count.' lines did not require action.'.$/;
}
close(HISTFILE);
return (undef,\%db_to_store);
}
sub write_hash {
my ($db_filename,$db_to_store) = @_;
#
# Write the gdbm file
my %db;
if (! tie(%db,'GDBM_File',$db_filename,&GDBM_WRCREAT(),0640)) {
warn "Unable to tie to $db_filename";
return "Unable to tie to $db_filename";
}
#
while (my ($k,$v) = each(%$db_to_store)) {
$db{$k}=$v;
}
#
untie(%db);
return undef;
}
sub test_hash {
my ($db_filename,$my_db) = @_;
#
my %db;
if (! tie(%db,'GDBM_File',$db_filename,&GDBM_READER(),0640)) {
return "Unable to tie to $db_filename";;
}
my (%key_errors,%value_errors);
while (my ($k,$v) = each(%db)) {
if (exists($my_db->{$k})) {
if ($my_db->{$k} eq $v) {
delete($my_db->{$k});
} else {
$value_errors{$k}=$v;
}
} else {
$key_errors{$k}=$v;
}
}
untie(%db);
#
my $error;
my $extra_count = scalar(keys(%$my_db));
if ($extra_count) {
$error.=$extra_count.' extra key/value pairs found in hist: '.$/;
while (my ($k,$v) = each(%$my_db)) {
$error .= ' "'.$k.'" => "'.$v.'"'.$/;
}
}
my $key_count = scalar(keys(%key_errors));
if ($key_count) {
$error.=$key_count.' missing keys found in db but not in hist: '.$/;
while (my ($k,$v) = each(%key_errors)) {
$error .= ' "'.$k.'" => "'.$v.'"'.$/;
}
}
my $value_count = scalar(keys(%value_errors));
if ($value_count) {
$error.=$value_count.' mismatched values found: '.$/;
while (my ($k,$v) = each(%value_errors)) {
$error .= ' "'.$k.'" => "'.$v.'"'.$/;
}
}
#
return $error;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>