X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=perl%2FAmanda%2FTaper%2FScan%2Ftraditional.pm;h=32fcf89f4eea51a84a0863693febad41ba60d6a9;hb=691567b16c13087b31ee4c2b6d038e57872fae82;hp=54fdf723405881583de27f7ce1cf4c93720b1516;hpb=d5853102f67d85d8e169f9dbe973ad573306c215;p=debian%2Famanda diff --git a/perl/Amanda/Taper/Scan/traditional.pm b/perl/Amanda/Taper/Scan/traditional.pm index 54fdf72..32fcf89 100644 --- a/perl/Amanda/Taper/Scan/traditional.pm +++ b/perl/Amanda/Taper/Scan/traditional.pm @@ -1,8 +1,9 @@ -# Copyright (c) 2009, 2010 Zmanda, Inc. All Rights Reserved. +# Copyright (c) 2009-2012 Zmanda, Inc. All Rights Reserved. # -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License version 2.1 as -# published by the Free Software Foundation. +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +#* License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY @@ -63,7 +64,7 @@ sub scan { $self->{'user_msg_fn'} = $params{'user_msg_fn'} || sub {}; # refresh the tapelist at every scan - $self->{'tapelist'} = $self->read_tapelist(); + $self->read_tapelist(); # count the number of scans we do, so we can only load 'current' on the # first scan @@ -75,6 +76,7 @@ sub scan { sub _user_msg { my $self = shift; my %params = @_; + $self->{'user_msg_fn'}->(%params); } @@ -180,6 +182,7 @@ sub stage_1 { step do_load => sub { $self->{'changer'}->load( label => $oldest_reusable, + set_current => 1, res_cb => $steps->{'load_done'}); }; @@ -219,98 +222,6 @@ sub stage_1 { }; } -sub try_volume { - my $self = shift; - my ($res, $result_cb) = @_; - - my $slot = $res->{'this_slot'}; - my $dev = $res->{'device'}; - my $status = $dev->status; - my $labelstr = $self->{'labelstr'}; - my $label; - my $autolabel = $self->{'autolabel'}; - - if ($status == $DEVICE_STATUS_SUCCESS) { - $label = $dev->volume_label; - - if ($label !~ /$labelstr/) { - if (!$autolabel->{'other_config'}) { - $self->_user_msg(slot_result => 1, - does_not_match_labelstr => 1, - labelstr => $labelstr, - slot => $slot, - res => $res); - return 0; - } - } else { - # verify that the label is in the tapelist - my $tle = $self->{'tapelist'}->lookup_tapelabel($label); - if (!$tle) { - $self->_user_msg(slot_result => 1, - not_in_tapelist => 1, - slot => $slot, - res => $res); - return 0; - } - - # see if it's reusable - if (!$self->is_reusable_volume(label => $label, new_label_ok => 1)) { - $self->_user_msg(slot_result => 1, - active => 1, - slot => $slot, - res => $res); - return 0; - } - $self->_user_msg(slot_result => 1, - slot => $slot, - res => $res); - $self->scan_result(res => $res, label => $label, - mode => $ACCESS_WRITE, is_new => 0, result_cb => $result_cb); - return 1; - } - } - - if (!defined $autolabel->{'template'} || - $autolabel->{'template'} eq "") { - $self->_user_msg(slot_result => 1, - slot => $slot, - res => $res); - return 0; - } - - $self->_user_msg(slot_result => 1, slot => $slot, res => $res); - - if ($status & $DEVICE_STATUS_VOLUME_UNLABELED and - $dev->volume_header and - $dev->volume_header->{'type'} == $Amanda::Header::F_EMPTY and - !$autolabel->{'empty'}) { - return 0; - } - - if ($status & $DEVICE_STATUS_VOLUME_UNLABELED and - $dev->volume_header and - $dev->volume_header->{'type'} == $Amanda::Header::F_WEIRD and - !$autolabel->{'non_amanda'}) { - return 0; - } - - if ($status & $DEVICE_STATUS_VOLUME_ERROR and - !$autolabel->{'volume_error'}) { - return 0; - } - - ($label, my $err) = $self->make_new_tape_label(); - if (!defined $label) { - # make this fatal, rather than silently skipping new tapes - $self->scan_result(error => $err, res => $res, result_cb => $result_cb); - return 1; - } - - $self->scan_result(res => $res, label => $label, mode => $ACCESS_WRITE, - is_new => 1, result_cb => $result_cb); - return 1; -} - ## # stage 2: scan for any usable volume @@ -336,6 +247,7 @@ sub stage_2 { my $load_current = ($self->{'scan_num'} == 1); my $steps = define_steps cb_ref => \$result_cb; + my $res; step load => sub { my ($err) = @_; @@ -371,12 +283,13 @@ sub stage_2 { }; step loaded => sub { - my ($err, $res) = @_; + (my $err, $res) = @_; my $loaded_current = $load_current; $load_current = 0; # don't load current a second time # bail out immediately if the scan is complete if ($err and $err->failed and $err->notfound) { + $self->_user_msg(search_result => 1, res => $res, err => $err); # no error, no reservation -> end of the scan return $self->scan_result(result_cb => $result_cb); } @@ -400,6 +313,7 @@ sub stage_2 { # or if we loaded the 'current' slot and it was invalid (this happens if # the user changes 'use-slots', for example $ignore_error = 1 if ($loaded_current && $err->invalid); + $ignore_error = 1 if ($err->empty); if ($ignore_error) { $self->_user_msg(slot_result => 1, err => $err); @@ -419,9 +333,177 @@ sub stage_2 { $self->{'seen'}->{$res->{'this_slot'}} = 1; - # we're done if try_volume calls result_cb (with success or an error) - return if ($self->try_volume($res, $result_cb)); + $steps->{'try_volume'}->(); + }; + + step try_volume => sub { + my $slot = $res->{'this_slot'}; + my $dev = $res->{'device'}; + my $status = $dev->status; + my $labelstr = $res->{'chg'}->{'labelstr'}; + my $label; + my $autolabel = $res->{'chg'}->{'autolabel'}; + + if ($status == $DEVICE_STATUS_SUCCESS) { + $label = $dev->volume_label; + + if ($label !~ /$labelstr/) { + if (!$autolabel->{'other_config'}) { + $self->_user_msg(slot_result => 1, + does_not_match_labelstr => 1, + labelstr => $labelstr, + slot => $slot, + label => $label, + res => $res); + return $steps->{'try_continue'}->(); + } + } else { + # verify that the label is in the tapelist + my $tle = $self->{'tapelist'}->lookup_tapelabel($label); + if (!$tle) { + $self->_user_msg(slot_result => 1, + not_in_tapelist => 1, + slot => $slot, + label => $label, + res => $res); + return $steps->{'try_continue'}->(); + } + + # see if it's reusable + if (!$self->is_reusable_volume(label => $label, new_label_ok => 1)) { + $self->_user_msg(slot_result => 1, + active => 1, + slot => $slot, + label => $label, + res => $res); + return $steps->{'try_continue'}->(); + } + $self->_user_msg(slot_result => 1, + slot => $slot, + label => $label, + res => $res); + $self->scan_result(res => $res, label => $label, + mode => $ACCESS_WRITE, is_new => 0, + result_cb => $result_cb); + return; + } + } + + if (!defined $autolabel->{'template'} || + $autolabel->{'template'} eq "") { + if ($status & $DEVICE_STATUS_VOLUME_UNLABELED and + $dev->volume_header and + $dev->volume_header->{'type'} == $Amanda::Header::F_EMPTY) { + $self->_user_msg(slot_result => 1, + not_autolabel => 1, + empty => 1, + slot => $slot, + res => $res); + } elsif ($status & $DEVICE_STATUS_VOLUME_UNLABELED and + $dev->volume_header and + $dev->volume_header->{'type'} == $Amanda::Header::F_WEIRD) { + $self->_user_msg(slot_result => 1, + not_autolabel => 1, + non_amanda => 1, + slot => $slot, + res => $res); + } elsif ($status & $DEVICE_STATUS_VOLUME_ERROR) { + $self->_user_msg(slot_result => 1, + not_autolabel => 1, + volume_error => 1, + err => $dev->error_or_status(), + slot => $slot, + res => $res); + } elsif ($status != $DEVICE_STATUS_SUCCESS) { + $self->_user_msg(slot_result => 1, + not_autolabel => 1, + not_success => 1, + err => $dev->error_or_status(), + slot => $slot, + res => $res); + } else { + $self->_user_msg(slot_result => 1, + not_autolabel => 1, + slot => $slot, + res => $res); + } + return $steps->{'try_continue'}->(); + } + + if ($status & $DEVICE_STATUS_VOLUME_UNLABELED and + $dev->volume_header and + $dev->volume_header->{'type'} == $Amanda::Header::F_EMPTY) { + if (!$autolabel->{'empty'}) { + $self->_user_msg(slot_result => 1, + empty => 1, + slot => $slot, + res => $res); + return $steps->{'try_continue'}->(); + } + } elsif ($status & $DEVICE_STATUS_VOLUME_UNLABELED and + $dev->volume_header and + $dev->volume_header->{'type'} == $Amanda::Header::F_WEIRD) { + if (!$autolabel->{'non_amanda'}) { + $self->_user_msg(slot_result => 1, + non_amanda => 1, + slot => $slot, + res => $res); + return $steps->{'try_continue'}->(); + } + } elsif ($status & $DEVICE_STATUS_VOLUME_ERROR) { + if (!$autolabel->{'volume_error'}) { + $self->_user_msg(slot_result => 1, + volume_error => 1, + err => $dev->error_or_status(), + slot => $slot, + res => $res); + return $steps->{'try_continue'}->(); + } + } elsif ($status != $DEVICE_STATUS_SUCCESS) { + $self->_user_msg(slot_result => 1, + not_success => 1, + err => $dev->error_or_status(), + slot => $slot, + res => $res); + return $steps->{'try_continue'}->(); + } + + $self->_user_msg(slot_result => 1, slot => $slot, res => $res); + $res->get_meta_label(finished_cb => $steps->{'got_meta_label'}); + return; + }; + + step got_meta_label => sub { + my ($err, $meta) = @_; + + if (defined $err) { + $self->scan_result(error => $err, res => $res, + result_cb => $result_cb); + return; + } + + ($meta, $err) = $res->make_new_meta_label() if !defined $meta; + if (defined $err) { + $self->scan_result(error => $err, res => $res, + result_cb => $result_cb); + return; + } + + (my $label, $err) = $res->make_new_tape_label(meta => $meta); + + + if (!defined $label) { + # make this fatal, rather than silently skipping new tapes + $self->scan_result(error => $err, res => $res, result_cb => $result_cb); + return; + } + + $self->scan_result(res => $res, label => $label, mode => $ACCESS_WRITE, + is_new => 1, result_cb => $result_cb); + return; + }; + step try_continue => sub { # no luck -- release this reservation and get the next $last_slot = $res->{'this_slot'};