Imported Upstream version 3.3.3
[debian/amanda] / perl / Amanda / Changer / multi.pm
index 53921e6708fcd33fc9d09ad8d67ef43bdcca0391..7a087b5d1af96fcc72b621efdcdd3f1ed2252ba2 100644 (file)
@@ -1,8 +1,9 @@
-# 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
-# by the Free Software Foundation.
+# This program 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.
 #
 # This program is distributed in the hope that it will be useful, but
 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -56,6 +57,7 @@ See the amanda-changers(7) manpage for usage information.
 #   pid           - the pid that reserved that slot.
 #   state         - SLOT_FULL/SLOT_EMPTY/SLOT_UNKNOWN
 #   device_status - the status of the device after the open or read_label
+#   device_error  - error message from the device
 #   f_type        - the F_TYPE of the fileheader.
 #   label         - the label, if known, of the volume in this slot
 
@@ -110,6 +112,8 @@ sub new {
     }
 
     my $state_filename = Amanda::Config::config_dir_relative($config->{'changerfile'});
+    my $lock_timeout = $config->{'lock-timeout'};
+    Amanda::Debug::debug("Using state file: $state_filename");
 
     my $self = {
        slots => \@slots,
@@ -120,6 +124,7 @@ sub new {
        state_filename => $state_filename,
        first_slot => $first_slot,
        last_slot => $last_slot,
+       'lock-timeout' => $lock_timeout,
     };
 
     bless ($self, $class);
@@ -362,10 +367,14 @@ sub update {
 
        my $slot = $res->{'this_slot'};
        my $dev = $res->{device};
-       $dev->read_label();
-       my $label = $dev->volume_label;
        $self->_update_slot_state(state => $state, dev => $dev, slot =>$slot);
-       $user_msg_fn->("recording volume '$label' in slot $slot");
+       if ($dev->status() == $DEVICE_STATUS_SUCCESS) {
+           my $label = $dev->volume_label;
+           $user_msg_fn->("recording volume '$label' in slot $slot");
+       } else {
+           my $status = $dev->error_or_status;
+           $user_msg_fn->("recording device error '" . $status . "' in slot $slot");
+       }
        $res->release(
            finished_cb => $steps->{'released'},
            unlocked => 1,
@@ -404,13 +413,21 @@ sub inventory {
            my $s = { slot => $slot,
                      state => $state->{slots}->{$unaliased}->{state} || Amanda::Changer::SLOT_UNKNOWN,
                      reserved => $self->_is_slot_in_use($state, $slot) };
-           if (defined $state->{slots}->{$unaliased}) {
+           if (defined $state->{slots}->{$unaliased} and
+               exists $state->{slots}->{$unaliased}->{device_status}) {
                $s->{'device_status'} =
                              $state->{slots}->{$unaliased}->{device_status};
+               if ($s->{'device_status'} != $DEVICE_STATUS_SUCCESS) {
+                   $s->{'device_error'} =
+                             $state->{slots}->{$unaliased}->{device_error};
+               } else {
+                   $s->{'device_error'} = undef;
+               }
                $s->{'f_type'} = $state->{slots}->{$unaliased}->{f_type};
                $s->{'label'} = $state->{slots}->{$unaliased}->{label};
            } else {
                $s->{'device_status'} = undef;
+               $s->{'device_error'} = undef;
                $s->{'f_type'} = undef;
                $s->{'label'} = undef;
            }
@@ -552,6 +569,11 @@ sub _update_slot_state {
     my $slot = $params{slot};
     my $unaliased = $self->{unaliased}->{$slot};
     $state->{slots}->{$unaliased}->{device_status} = "".scalar($dev->status);
+    if ($dev->status != $DEVICE_STATUS_SUCCESS) {
+       $state->{slots}->{$unaliased}->{device_error} = $dev->error;
+    } else {
+       $state->{slots}->{$unaliased}->{device_error} = undef;
+    }
     my $label = $dev->volume_label;
     $state->{slots}->{$unaliased}->{state} = Amanda::Changer::SLOT_FULL;
     $state->{slots}->{$unaliased}->{label} = $label;
@@ -604,7 +626,9 @@ sub _get_current {
     if (defined $state->{current_slot}) {
        my $slot = $self->{number}->{$state->{current_slot}};
        # return the slot if it exist.
-       return $slot if $slot >= $self->{'first_slot'} && $slot < $self->{'last_slot'};
+       return $slot if defined $slot and
+                               $slot >= $self->{'first_slot'} and
+                               $slot < $self->{'last_slot'};
        Amanda::Debug::debug("statefile current_slot is not configured");
     }
     # return the first slot
@@ -647,12 +671,23 @@ sub set_label {
        my $label = $params{'label'};
        my $slot = $self->{'this_slot'};
        my $unaliased = $chg->{unaliased}->{$slot};
+       my $dev = $self->{'device'};
 
        $state->{slots}->{$unaliased}->{label} =  $label;
        $state->{slots}->{$unaliased}->{device_status} =
-                               "".$DEVICE_STATUS_SUCCESS;
-       $state->{slots}->{$unaliased}->{f_type} =
-                               "".scalar($Amanda::Header::F_TAPESTART);
+                               "".$dev->status;
+       if ($dev->status != $DEVICE_STATUS_SUCCESS) {
+           $state->{slots}->{$unaliased}->{device_error} = $dev->error;
+       } else {
+           $state->{slots}->{$unaliased}->{device_error} = undef;
+       }
+       my $volume_header = $dev->volume_header;
+       if (defined $volume_header) {
+           $state->{slots}->{$unaliased}->{f_type} =
+                               "".$volume_header->{type};
+       } else {
+           $state->{slots}->{$unaliased}->{f_type} = undef;
+       }
        $finished_cb->();
     });
 }
@@ -665,6 +700,10 @@ sub do_release {
     # then never mind
     return unless $self->{'chg'};
 
+    $self->{'device'}->eject() if (exists $self->{'device'} and
+                                  exists $params{'eject'} and
+                                  $params{'eject'});
+
     # unref the device, for good measure
     $self->{'device'} = undef;