Imported Upstream version 3.3.2
[debian/amanda] / server-src / amvault.pl
index 8b2c87a66e6b4fbd20112190c1d521f104d981e6..88111f7c9728b3324ce4e4d9911f450c235fd474 100644 (file)
@@ -1,5 +1,5 @@
 #! @PERL@
-# Copyright (c) 2008, 2009, 2010 Zmanda, Inc.  All Rights Reserved.
+# Copyright (c) 2008-2012 Zmanda, Inc.  All Rights Reserved.
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License version 2 as published
@@ -93,7 +93,7 @@ sub user_request {
 package Amvault;
 
 use Amanda::Config qw( :getconf config_dir_relative );
-use Amanda::Debug qw( :logging );
+use Amanda::Debug qw( :logging debug );
 use Amanda::Xfer qw( :constants );
 use Amanda::Header qw( :constants );
 use Amanda::MainLoop;
@@ -108,8 +108,8 @@ use Amanda::Changer qw( :constants );
 use Amanda::Cmdline;
 use Amanda::Paths;
 use Amanda::Logfile qw( :logtype_t log_add log_add_full
-                       log_rename $amanda_log_trace_log make_stats
-                       match_datestamp match_level );
+                       log_rename $amanda_log_trace_log make_stats );
+use Amanda::Util qw ( match_datestamp match_level );
 
 use base qw(
     Amanda::Recovery::Clerk::Feedback
@@ -141,6 +141,7 @@ sub new {
        exporting => 0, # is an export in progress?
        call_after_export => undef, # call this when export complete
        config_overrides_opts => $params{'config_overrides_opts'},
+       trace_log_filename => getconf($CNF_LOGDIR) . "/log",
 
        # called when the operation is complete, with the exit
        # status
@@ -148,6 +149,47 @@ sub new {
     }, $class;
 }
 
+sub run_subprocess {
+    my ($proc, @args) = @_;
+
+    my $pid = POSIX::fork();
+    if ($pid == 0) {
+       my $null = POSIX::open("/dev/null", POSIX::O_RDWR);
+       POSIX::dup2($null, 0);
+       POSIX::dup2($null, 1);
+       POSIX::dup2($null, 2);
+       exec $proc, @args;
+       die "Could not exec $proc: $!";
+    }
+    waitpid($pid, 0);
+    my $s = $? >> 8;
+    debug("$proc exited with code $s: $!");
+}
+
+sub do_amcleanup {
+    my $self = shift;
+
+    return 1 unless -f $self->{'trace_log_filename'};
+
+    # logfiles are still around.  First, try an amcleanup -p to see if
+    # the actual processes are already dead
+    debug("runing amcleanup -p");
+    run_subprocess("$sbindir/amcleanup", '-p', $self->{'config_name'},
+                  $self->{'config_overrides_opts'});
+
+    return 1 unless -f $self->{'trace_log_filename'};
+
+    return 0;
+}
+
+sub bail_already_running() {
+    my $self = shift;
+    my $msg = "An Amanda process is already running - please run amcleanup manually";
+    print "$msg\n";
+    debug($msg);
+    $self->{'exit_cb'}->(1);
+}
+
 sub run {
     my $self = shift;
     my ($exit_cb) = @_;
@@ -163,7 +205,20 @@ sub run {
 
     # open up a trace log file and put our imprimatur on it, unless dry_runing
     if (!$self->{'opt_dry_run'}) {
+       if (!$self->do_amcleanup()) {
+           return $self->bail_already_running();
+       }
        log_add($L_INFO, "amvault pid $$");
+
+       # Check we own the log file
+       open(my $tl, "<", $self->{'trace_log_filename'})
+           or die("could not open trace log file '$self->{'trace_log_filename'}': $!");
+       if (<$tl> !~ /^INFO amvault amvault pid $$/) {
+           debug("another amdump raced with this one, and won");
+           close($tl);
+           return $self->bail_already_running();
+       }
+       close($tl);
        log_add($L_START, "date " . $self->{'dst_write_timestamp'});
        Amanda::Debug::add_amanda_log_handler($amanda_log_trace_log);
        $self->{'cleanup'}{'roll_trace_log'} = 1;
@@ -249,7 +304,7 @@ sub setup_src {
        # convert the timestamp and level to a dumpspec
        my $level = $self->{'fulls_only'}? "0" : undef;
        push @dumpspecs, Amanda::Cmdline::dumpspec_t->new(
-               undef, undef, $self->{'src_write_timestamp'}, $level, undef);
+               undef, undef, undef, $level, $self->{'src_write_timestamp'});
     }
 
     # if we ignored all of the dumpspecs and didn't create any, then dump
@@ -313,7 +368,7 @@ sub plan_cb {
                      $dump->{'dump_timestamp'} . " " .
                      $dump->{'level'} . "\n";
            }
-           $total_kb += $dump->{'kb'};
+           $total_kb += int $dump->{'kb'};
        }
 
        print STDOUT "Total Size: $total_kb KB\n";
@@ -630,6 +685,14 @@ sub quit {
     };
 
     step roll_log => sub {
+       if (defined $self->{'src'}->{'chg'}) {
+           $self->{'src'}->{'chg'}->quit();
+           $self->{'src'}->{'chg'} = undef;
+       }
+       if (defined $self->{'dst'}->{'chg'}) {
+           $self->{'dst'}->{'chg'}->quit();
+           $self->{'dst'}->{'chg'} = undef;
+       }
        if ($self->{'cleanup'}{'roll_trace_log'}) {
            log_add_full($L_FINISH, "driver", "fake driver finish");
            log_add($L_INFO, "pid-done $$");
@@ -740,6 +803,7 @@ sub scribe_notif_log_info {
     my $self = shift;
     my %params = @_;
 
+    debug("$params{'message'}");
     log_add_full($L_INFO, "taper", $params{'message'});
 }
 
@@ -942,6 +1006,7 @@ sub add_autolabel {
     usage("unknown --autolabel value '$val'");
 }
 
+debug("Arguments: " . join(' ', @ARGV));
 Getopt::Long::Configure(qw{ bundling });
 GetOptions(
     'o=s' => sub {