validate and faster pass through
authorHeiko Schlittermann (JUMPER) <hs@schlittermann.de>
Mon, 16 Dec 2013 21:05:22 +0100
changeset 11 9ad262d8c301
parent 10 8231f7b00052
child 12 9e30f40ffb34
validate and faster pass through
bin/amdumpext
--- a/bin/amdumpext	Mon Dec 16 16:36:15 2013 +0100
+++ b/bin/amdumpext	Mon Dec 16 21:05:22 2013 +0100
@@ -37,6 +37,8 @@
 use constant FD3       => 3;
 use constant FD4       => 4;
 
+my $BS = 64 * 2**20;    # 64 MB read size
+
 $SIG{__DIE__} = sub { die $^S ? '' : "$ME: ", @_ };
 
 my %SUPPORT = (
@@ -58,6 +60,7 @@
 sub exec_selfcheck;
 sub exec_estimate;
 sub exec_backup;
+sub exec_validate;
 
 # some helper functions
 
@@ -92,19 +95,23 @@
     ) or pod2usage;
 
     given ($command) {
-        when ("support") { exec_support }
-        when ("selfcheck") {
+        when ('support') { exec_support }
+        when ('selfcheck') {
             pod2usage if undef ~~ $opt_device;
             exec_selfcheck
         }
-        when ("estimate") {
+        when ('estimate') {
             pod2usage if undef ~~ [$opt_device, $opt_level[0]];
             exec_estimate
         }
-        when ("backup") {
+        when ('backup') {
             pod2usage if undef ~~ [$opt_device, $opt_level[0]];
             exec_backup
         }
+        when ('validate') {
+            exec_validate
+        }
+
         default { pod2usage }
     }
 }
@@ -133,11 +140,19 @@
         "@gids (@groups)";
     };
 
-    foreach my $tool (qw(dump restore)) {
-        if ($_ = (grep { -x ($_ .= "/$tool") } split /:/ => $ENV{PATH})[0]) {
-            my ($version, undef) = `$_ 2>&1`;
-	    chomp $version;
-            OK "$tool is $version";
+    foreach my $tool (qw(dump restore cat)) {
+        if (my $path =
+            (grep { -x ($_ .= "/$tool") } split /:/ => $ENV{PATH})[0])
+        {
+
+            # not all tools understand --version, but fortunately they
+            # all output a line starting with the name of the tool and
+            # the version information
+            my ($version, undef) =
+              map  { /^.*?\s+(.*)/ }
+              grep { /\A(?:$path|$tool)\s/ } `$path --version 2>&1`;
+            chomp $version;
+            OK "$tool is $path $version";
         }
         else {
             ERROR "$tool not found in $ENV{PATH}";
@@ -257,18 +272,27 @@
                     die "Can't exec `restore -tvf -`: $!";
                 };
 
-                # the restore may close it's input, we'll get
-                # a SIG{PIPE} because of this
+                # The restore may close it's input, we'll get
+                # a SIG{PIPE} because of this.
+                # But how can we be sure that it was the restore
+                # that just sent us the signal? Currently we write
+                # to two processes only, writing to STDOUT (the data
+                # stream up down to the server). If this fails we die.
+                # The other stream we write to is the 'restore'.
+                # If we got this SIGPIPE, we 'switch' to cat, since
+                # it's faster then our perl script.
                 local $SIG{PIPE} = sub {
                     close $restore;
                     $restore = undef;
                     $SIG{PIPE} = 'default';
+                    exec 'cat';
+                    die "Can't exec `cat': $!\n";
                 };
 
-                local $/ = \(my $x = 64 * 1024);
+                local $/ = \$BS;
                 while (<STDIN>) {
-                    print $_;
-                    print $restore $_ if $restore;
+                    print $_ or die "Can't send data to `dump': $!\n";
+                    print $restore $_;
                 }
                 close($restore) if $restore;
                 exit 0;
@@ -397,6 +421,27 @@
 
 }
 
+sub exec_validate {
+
+    my $pid = fork // die "Can't fork: $!\n";
+
+    # the first part goes into restore
+    # but restore stops reading after the directory
+    if (not $pid) {
+        exec 'restore', '-tf', '-';
+        die "Can't exec restore: $!\n";
+    }
+    waitpid($pid, 0);
+    die $? if $?;
+
+    # read the remaining dump via cat, I think,
+    # nobody is fast than cat
+    open(STDOUT, '>', '/dev/null')
+      or die "Can't redirect STDOUT to >/dev/null: $!\n";
+    exec 'cat';
+    die "Can't exec `cat': $!\n";
+}
+
 sub device {
     my $_ = shift;
     return $_ if /^\//;
@@ -419,8 +464,10 @@
 =head1 SYNOPSIS
 
   amdumpext support
-  amdumpext selfcheck [options] [--level <level>]    --device <device> 
-  amdumpext estimate [options]  [--level <level>]... --device <device> 
+  amdumpext selfcheck [options] [--level <level>] --device <device> 
+  amdumpext backup    [options] [--level <level>] --device <device> 
+  amdumpext estimate  [options] [--level <level>]... --device <device> 
+  amdumpext validate 
 
 =head1 DESCRIPTION
 
@@ -489,6 +536,12 @@
 
 mandatory options: device, level, ...
 
+=head2 validate
+
+This checks if the data stream is readable and looks like a dump.
+Actually it does not try to completly validate the stream, as B<restore>
+does not have such an option.
+
 =head1 PROPERTIES
 
 The properties may be set on the server side to tune the behaviour