-# 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
step start_xfer => sub {
my ($err) = @_;
my $xfer_dest = $scribe->get_xfer_dest(
+ allow_split => 1,
max_memory => 64 * 1024,
can_cache_inform => 0,
part_size => 150 * 1024**2,
the dump should be split:
$xdest = $scribe->get_xfer_dest(
+ allow_split => $allow_split,
max_memory => $max_memory,
# .. splitting parameters
);
=over 4
+=item C<allow_split>
+
+this dle is allowed or not to split
+
=item C<part_size>
the split part size to use, or 0 for no splitting
use Amanda::Taper::Scribe qw( get_splitting_args_from_config );
my %splitting_args = get_splitting_args_from_config(
# Amanda dumptype configuration parameters,
+ dle_allow_split => ..,
dle_tape_splitsize => ..,
dle_split_diskbuffer => ..,
dle_fallback_splitsize => ..,
my %params = @_;
my $decide_debug = $Amanda::Config::debug_taper || $params{'debug'};
- for my $rq_param qw(taperscan feedback) {
+ for my $rq_param (qw(taperscan feedback)) {
croak "required parameter '$rq_param' mising"
unless exists $params{$rq_param};
}
taperscan => $params{'taperscan'},
feedback => $params{'feedback'},
debug => $decide_debug,
+ eject_volume => $params{'eject_volume'},
write_timestamp => undef,
started => 0,
device => undef,
device_size => undef,
device_at_eom => undef, # device still exists, but is full
+ close_volume => undef,
# callback passed to start_dump
dump_cb => undef,
# information for the current dumpfile
dump_header => undef,
retry_part_on_peom => undef,
+ allow_split => undef,
xfer => undef,
xdt => undef,
xdt_ready => undef,
my $self = shift;
my %params = @_;
- for my $rq_param qw(write_timestamp finished_cb) {
+ for my $rq_param (qw(write_timestamp finished_cb)) {
croak "required parameter '$rq_param' missing"
unless exists $params{$rq_param};
}
- die "scribe already started" if $self->{'started'};
+ confess "scribe already started" if $self->{'started'};
$self->dbg("starting");
$self->{'write_timestamp'} = $params{'write_timestamp'};
$self->dbg("quitting");
if ($self->{'xfer'}) {
- die "Scribe cannot quit while a transfer is active";
+ confess "Scribe cannot quit while a transfer is active";
# Supporting this would be complicated:
# - cancel the xfer and wait for it to complete
# - ensure that the taperscan not be started afterward
my $device = $self->get_device();
if (!defined $device) {
- die "no device is available to check the datapath";
+ confess "no device is available to check the datapath";
}
my $use_directtcp = $device->directtcp_supported();
my $self = shift;
my %params = @_;
- for my $rq_param qw(max_memory) {
+ for my $rq_param (qw(max_memory)) {
croak "required parameter '$rq_param' missing"
unless exists $params{$rq_param};
}
- die "not yet started"
+ confess "not yet started"
unless $self->{'write_timestamp'} and $self->{'started'};
- die "xfer element already returned"
+ confess "xfer element already returned"
if ($self->{'xdt'});
- die "xfer already running"
+ confess "xfer already running"
if ($self->{'xfer'});
$self->{'xfer'} = undef;
# set the callback
$self->{'dump_cb'} = undef;
$self->{'retry_part_on_peom'} = 1;
+ $self->{'allow_split'} = 0;
$self->{'start_part_on_xdt_ready'} = 0;
# start getting parameters together to determine what kind of splitting
my ($use_mem_cache, $disk_cache_dirname) = (0, undef);
my $can_cache_inform = $params{'can_cache_inform'};
my $part_cache_type = $params{'part_cache_type'} || 'none';
+ my $allow_split = $params{'allow_split'};
my $xdt_first_dev = $self->get_device();
if (!defined $xdt_first_dev) {
- die "no device is available to create an xfer_dest";
+ confess "no device is available to create an xfer_dest";
}
my $leom_supported = $xdt_first_dev->property_get("leom");
my $use_directtcp = $xdt_first_dev->directtcp_supported();
$self->{'retry_part_on_peom'} = 0;
}
+ if ($allow_split &&
+ ($can_cache_inform ||
+ !defined($part_cache_type) ||
+ $part_cache_type eq 'disk' ||
+ $part_cache_type eq 'memory' ||
+ $leom_supported)) {
+ $self->{'allow_split'} = 1;
+ } else {
+ $self->{'allow_split'} = 0;
+ }
+
+ $self->{'retry_part_on_peom'} = 0 if !$self->{'allow_split'};
+
debug("Amanda::Taper::Scribe preparing to write, part size $part_size, "
. "$dest_text ($dest_type) "
. ($leom_supported? " (LEOM supported)" : " (no LEOM)"));
my $self = shift;
my %params = @_;
- die "no xfer dest set up; call get_xfer_dest first"
+ confess "no xfer dest set up; call get_xfer_dest first"
unless defined $self->{'xdt'};
# get the header ready for writing (totalparts was set by the caller)
my $self = shift;
my %params = @_;
- die "no xfer dest set up; call get_xfer_dest first"
+ confess "no xfer dest set up; call get_xfer_dest first"
unless defined $self->{'xdt'};
# set up the dump_cb for when this dump is done, and keep the xfer
$self->{'dump_cb'} = $params{'dump_cb'};
$self->{'xfer'} = $params{'xfer'};
- # XXX The cancel should call dump_cb, but right now the xfer stays hung in
- # accept. So we leave the xfer to its hang, and dump_cb is called and xdt
- # and xfer are set to undef. This should be fixed in 3.2.
+ # The cancel will can dump_cb.
$self->{'xfer'}->cancel();
- $self->{'dump_cb'}->(
- result => "FAILED",
- device_errors => [],
- config_denial_message => undef,
- size => 0,
- duration => 0.0,
- total_duration => 0,
- nparts => 0);
- $self->{'xdt'} = undef;
- $self->{'xfer'} = undef;
+}
+
+sub close_volume {
+ my $self = shift;
+
+ $self->{'close_volume'} = 1;
}
sub get_bytes_written {
return
}
+ if ($self->{'close_volume'}) {
+ $self->{'close_volume'} = undef;
+ return $self->_get_new_volume();
+ }
+
# we need an actual, permitted device at this point, so if we don't have
# one, then defer this start_part call until we do. The device may still
# exist, but be at EOM, if the last dump failed at EOM and was not retried
$self->dbg("not notifying for empty, successful part");
} else {
# double-check partnum
- die "Part numbers do not match!"
+ confess "Part numbers do not match!"
unless ($self->{'dump_header'}->{'partnum'} == $msg->{'partnum'});
# notify
}
# if the part failed..
- if (!$msg->{'successful'}) {
+ if (!$msg->{'successful'} || !$self->{'allow_split'}) {
# if no caching was going on, then the dump has failed
if (!$self->{'retry_part_on_peom'}) {
# mark this device as at EOM, since we are not going to look
if ($self->{'device'}->status() != $DEVICE_STATUS_SUCCESS) {
$msg = $self->{'device'}->error_or_status();
}
- $self->_operation_failed(device_error => $msg);
+ $self->_operation_failed(device_error => "$msg, splitting not enabled");
return;
}
# if the part was unsuccessful, but the xfer dest has reason to believe
# this is not due to EOM, then the dump is done
if (!$msg->{'successful'}) {
- my $msg = "unknown error while dumping";
if ($self->{'device'}->status() != $DEVICE_STATUS_SUCCESS) {
$msg = $self->{'device'}->error_or_status();
+ $self->_operation_failed(device_error => $msg);
+ } else {
+ $self->_operation_failed();
}
- $self->_operation_failed(device_error => $msg);
return;
}
# determine the correct final status - DONE if we're done, PARTIAL
# if we've started writing to the volume, otherwise FAILED
- if (@{$self->{'device_errors'}} or $self->{'config_denial_message'}) {
+ if (@{$self->{'device_errors'}} or $self->{'config_denial_message'} or
+ !$self->{'last_part_successful'}) {
$result = $self->{'started_writing'}? 'PARTIAL' : 'FAILED';
} else {
$result = 'DONE';
my $error_message = $params{'device_error'}
|| $params{'config_denial_message'}
- || 'no reason';
+ || 'input error';
$self->dbg("operation failed: $error_message");
# tuck the message away as desired
# _dump_done constructs the dump_cb from $self parameters
$self->_dump_done();
} else {
- die "error with no callback to handle it: $error_message";
+ confess "error with no callback to handle it: $error_message";
}
}
}
my $self = shift;
my %params = @_;
my @errors;
+ my $do_eject = 0;
my ($label, $fm, $kb);
# if we've already written a volume, log it
if ($self->{'device'} and defined $self->{'device'}->volume_label) {
+ $do_eject = 1 if $self->{'eject_volume'};
$label = $self->{'device'}->volume_label();
$fm = $self->{'device'}->file();
$kb = $self->{'device_size'} / 1024;
$self->{'device'} = undef;
$self->{'device_at_eom'} = 0;
- $self->{'reservation'}->release(finished_cb => sub {
+ $self->{'reservation'}->release(eject => $do_eject, finished_cb => sub {
my ($err) = @_;
push @errors, "$err" if $err;
# notify the feedback that we've finished and released a tape
if ($label) {
- $self->{'feedback'}->scribe_notif_tape_done(
+ return $self->{'feedback'}->scribe_notif_tape_done(
volume_label => $label,
size => $kb * 1024,
- num_files => $fm);
+ num_files => $fm,
+ finished_cb => sub {
+ $params{'finished_cb'}->(@errors? join("; ", @errors) : undef);
+ });
}
$params{'finished_cb'}->(@errors? join("; ", @errors) : undef);
$new_scribe->{'dump_cb'} = $self->{'dump_cb'};
$new_scribe->{'dump_header'} = $self->{'dump_header'};
$new_scribe->{'retry_part_on_peom'} = $self->{'retry_part_on_peom'};
+ $new_scribe->{'allow_split'} = $self->{'allow_split'};
$new_scribe->{'split_method'} = $self->{'split_method'};
$new_scribe->{'xfer'} = $self->{'xfer'};
$new_scribe->{'xdt'} = $self->{'xdt'};
# inform the xdt about this new device before starting it
$self->{'xdt'}->use_device($device);
- my $result = $self->_device_start($reservation, $access_mode, $new_label, $is_new);
- if ($result == 0) {
- # try reading the label to see whether we erased the tape
- my $erased = 0;
- CHECK_READ_LABEL: {
+ my $cbX = sub {};
+ my $steps = define_steps
+ cb_ref => \$cbX;
+
+ step device_start => sub {
+ $self->_device_start($reservation, $access_mode, $new_label, $is_new,
+ $steps->{'device_started'});
+ };
+
+ step device_started => sub {
+ my $result = shift;
+
+ if ($result == 0) {
+ # try reading the label to see whether we erased the tape
+ my $erased = 0;
+ CHECK_READ_LABEL: {
# don't worry about erasing new tapes
- if ($is_new) {
- last CHECK_READ_LABEL;
- }
+ if ($is_new) {
+ last CHECK_READ_LABEL;
+ }
- $device->read_label();
+ $device->finish();
+ $device->read_label();
- # does the device think something is broken now?
- if (($device->status & ~$DEVICE_STATUS_VOLUME_UNLABELED)
- and !($device->status & $DEVICE_STATUS_VOLUME_UNLABELED)) {
- $erased = 1;
- last CHECK_READ_LABEL;
- }
+ # does the device think something is broken now?
+ if (($device->status & ~$DEVICE_STATUS_VOLUME_UNLABELED)
+ and !($device->status & $DEVICE_STATUS_VOLUME_UNLABELED)) {
+ $erased = 1;
+ last CHECK_READ_LABEL;
+ }
- # has the label changed?
- my $vol_label = $device->volume_label;
- if ((!defined $old_label and defined $vol_label)
- or (defined $old_label and !defined $vol_label)
- or (defined $old_label and $old_label ne $vol_label)) {
- $erased = 1;
- last CHECK_READ_LABEL;
- }
+ # has the label changed?
+ my $vol_label = $device->volume_label;
+ if ((!defined $old_label and defined $vol_label)
+ or (defined $old_label and !defined $vol_label)
+ or (defined $old_label and $old_label ne $vol_label)) {
+ $erased = 1;
+ last CHECK_READ_LABEL;
+ }
- # has the timestamp changed?
- my $vol_timestamp = $device->volume_time;
- if ((!defined $old_timestamp and defined $vol_timestamp)
- or (defined $old_timestamp and !defined $vol_timestamp)
- or (defined $old_timestamp and $old_timestamp ne $vol_timestamp)) {
- $erased = 1;
- last CHECK_READ_LABEL;
+ # has the timestamp changed?
+ my $vol_timestamp = $device->volume_time;
+ if ((!defined $old_timestamp and defined $vol_timestamp)
+ or (defined $old_timestamp and !defined $vol_timestamp)
+ or (defined $old_timestamp and $old_timestamp ne $vol_timestamp)) {
+ $erased = 1;
+ last CHECK_READ_LABEL;
+ }
}
+
+ $self->{'feedback'}->scribe_notif_new_tape(
+ error => "while labeling new volume: " . $device->error_or_status(),
+ volume_label => $erased? $new_label : undef);
+
+ $self->_get_new_volume();
+ return $cbX->();
+ } elsif ($result != 1) {
+ $self->{'feedback'}->scribe_notif_new_tape(
+ error => $result,
+ volume_label => undef);
+ $self->_get_new_volume();
+ return $cbX->();
}
- $self->{'feedback'}->scribe_notif_new_tape(
- error => "while labeling new volume: " . $device->error_or_status(),
- volume_label => $erased? $new_label : undef);
+ $new_label = $device->volume_label;
- return $self->_get_new_volume();
- } elsif ($result != 1) {
+ # success!
$self->{'feedback'}->scribe_notif_new_tape(
- error => $result,
- volume_label => undef);
- return $self->_get_new_volume();
- }
-
- $new_label = $device->volume_label;
+ error => undef,
+ volume_label => $new_label);
- # success!
- $self->{'feedback'}->scribe_notif_new_tape(
- error => undef,
- volume_label => $new_label);
+ $self->{'reservation'}->set_label(label => $new_label,
+ finished_cb => $steps->{'set_labelled'});
+ };
- # notify the changer that we've labeled the tape, and start the part.
- my $label_set_cb = make_cb(label_set_cb => sub {
+ step set_labelled => sub {
my ($err) = @_;
if ($err) {
$self->{'feedback'}->scribe_notif_log_info(
message => "Error from set_label: $err");
# fall through to start_part anyway...
}
- return $self->_start_part();
- });
- $self->{'reservation'}->set_label(label => $new_label,
- finished_cb => $label_set_cb);
+ $self->_start_part();
+ return $cbX->();
+ }
}
# return 0 for device->start error
# return a message for others error
sub _device_start {
my $self = shift;
- my ($reservation, $access_mode, $new_label, $is_new) = @_;
+ my ($reservation, $access_mode, $new_label, $is_new, $finished_cb) = @_;
my $device = $reservation->{'device'};
my $tl = $self->{'taperscan'}->{'tapelist'};
+ my $meta;
if (!defined $tl) { # For Mock::Taperscan in installcheck
if (!$device->start($access_mode, $new_label, $self->{'write_timestamp'})) {
- return 0;
+ return $finished_cb->(0);
} else {
- return 1;
+ return $finished_cb->(1);
}
}
- if ($is_new) {
- # generate the new label and write it to the tapelist file
- $tl->reload(1);
- ($new_label, my $err) = $self->{'taperscan'}->make_new_tape_label();
- if (!defined $new_label) {
- $tl->unlock();
- return $err;
- } else {
- $tl->add_tapelabel('0', $new_label, undef, 0, undef, $reservation->{'barcode'});
- $tl->write();
- }
- $self->dbg("generate new label '$new_label'");
- }
+ my $steps = define_steps
+ cb_ref => \$finished_cb;
+
+ step setup => sub {
+ return $reservation->get_meta_label(
+ finished_cb => $steps->{'got_meta_label'});
+ };
+
+ step got_meta_label => sub {
+ my ($err, $meta) = @_;
- # write the label to the device
- if (!$device->start($access_mode, $new_label, $self->{'write_timestamp'})) {
if ($is_new) {
- # remove the generated label from the tapelist file
+ # generate the new label and write it to the tapelist file
$tl->reload(1);
- $tl->remove_tapelabel($new_label);
+ if (!$meta) {
+ ($meta, $err) = $reservation->make_new_meta_label();
+ if (defined $err) {
+ $tl->unlock();
+ return $finished_cb->($err);
+ }
+ }
+ ($new_label, my $err) = $reservation->make_new_tape_label(
+ meta => $meta);
+ if (!defined $new_label) {
+ $tl->unlock();
+ return $finished_cb->($err);
+ }
+ $tl->add_tapelabel('0', $new_label, undef, 1, $meta,
+ $reservation->{'barcode'});
$tl->write();
- }
- return 0;
- }
+ $self->dbg("generate new label '$new_label'");
+ } else {
+ $tl->reload(0);
+ my $tle = $tl->lookup_tapelabel($new_label);
+ $meta = $tle->{'meta'} if !defined $meta && $tle->{'meta'};
+ my $barcode = $tle->{'barcode'};
+ if (defined $barcode and $barcode ne $reservation->{'barcode'}) {
+ return $finished_cb->("tapelist for label '$new_label' have barcode '$barcode' but changer report '" . $reservation->{'barcode'} . "'");
+ }
+ }
- # rewrite the tapelist file
- $tl->reload(1);
- my $tle = $tl->lookup_tapelabel($new_label);
- $tl->remove_tapelabel($new_label);
- $tl->add_tapelabel($self->{'write_timestamp'}, $new_label,
- $tle? $tle->{'comment'} : undef, 1);
- $tl->write();
+ # write the label to the device
+ if (!$device->start($access_mode, $new_label, $self->{'write_timestamp'})) {
+ if ($is_new) {
+ # remove the generated label from the tapelist file
+ $tl->reload(1);
+ $tl->remove_tapelabel($new_label);
+ $tl->write();
+ }
+ return $finished_cb->(0);
+ }
+
+ # rewrite the tapelist file
+ $tl->reload(1);
+ my $tle = $tl->lookup_tapelabel($new_label);
+ $meta = $tle->{'meta'} if !$meta && $tle->{'meta'};
+ $tl->remove_tapelabel($new_label);
+ $tl->add_tapelabel($self->{'write_timestamp'}, $new_label,
+ $tle? $tle->{'comment'} : undef, 1, $meta,
+ $reservation->{'barcode'}, $device->block_size/1024);
+ $tl->write();
+
+ $reservation->set_meta_label(meta => $meta,
+ finished_cb => $steps->{'set_meta_label'});
+ };
- return 1;
+ step set_meta_label => sub {
+ return $finished_cb->(1);
+ }
}
sub dbg {
sub get_splitting_args_from_config {
my %params = @_;
- use Data::Dumper;
my %splitting_args;
+ $splitting_args{'allow_split'} = 0;
# if dle_splitting is false, then we don't split - easy.
if (defined $params{'dle_allow_split'} and !$params{'dle_allow_split'}) {
- return ();
+ return %splitting_args;
}
# utility for below
my $fsusage = Amanda::Util::get_fs_usage($dirname);
confess "$dirname" if (!$fsusage);
- my $avail = $fsusage->{'blocks'} * $fsusage->{'bavail'};
+ my $avail = $fsusage->{'blocksize'} * $fsusage->{'bavail'};
if ($avail < $part_size) {
Amanda::Debug::debug("disk cache has $avail bytes available on $dirname, but " .
"needs $part_size");
# part cache type is memory unless we have a split_diskbuffer that fits the bill
if ($params{'part_size'}) {
+ $splitting_args{'allow_split'} = 1;
$params{'part_cache_type'} = 'memory';
if (defined $params{'dle_split_diskbuffer'}
and -d $params{'dle_split_diskbuffer'}) {
my $ps = $params{'part_size'};
my $pcms = $params{'part_cache_max_size'};
$ps = $pcms if (!defined $ps or (defined $pcms and $pcms < $ps));
+ $splitting_args{'allow_split'} = 1 if ((defined $ps and $ps > 0) or
+ $params{'leom_supported'});
# fail back from 'disk' to 'none' if the disk isn't set up correctly
if (defined $params{'part_cache_type'} and
}
sub scribe_notif_new_tape { }
-sub scribe_notif_tape_done { }
sub scribe_notif_part_done { }
sub scribe_notif_log_info { }
+sub scribe_notif_tape_done {
+ my $self = shift;
+ my %params = @_;
+
+ $params{'finished_cb'}->();
+}
##
## Device Handling
package Amanda::Taper::Scribe::DevHandling;
use Amanda::MainLoop;
use Carp;
+use Amanda::Debug qw( :logging );
# This class handles scanning for volumes, requesting permission for those
# volumes (the driver likes to feel like it's in control), and providing those
my $self = shift;
my %params = @_;
- for my $rq_param qw(finished_cb) {
+ for my $rq_param (qw(finished_cb)) {
croak "required parameter '$rq_param' mising"
unless exists $params{$rq_param};
}
my $self = shift;
my (%params) = @_;
- die "already processing a volume request"
+ confess "already processing a volume request"
if ($self->{'volume_cb'});
$self->{'volume_cb'} = $params{'volume_cb'};
$self->{'scan_running'} = 1;
- $self->{'taperscan'}->scan(result_cb => sub {
+ my $_user_msg_fn = sub {
+ my %params = @_;
+ if (exists($params{'slot_result'})) {
+ if ($params{'does_not_match_labelstr'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} with label $params{'label'} do not match labelstr");
+ } elsif ($params{'not_in_tapelist'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} with label $params{'label'} is not in the tapelist");
+ } elsif ($params{'active'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} with label $params{'label'} is not reusable");
+ } elsif ($params{'not_autolabel'}) {
+ if ($params{'label'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} with label $params{'label'} is not labelable ");
+ } elsif ($params{'empty'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} is empty, autolabel not set");
+ } elsif ($params{'non_amanda'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} is a non-amanda volume, autolabel not set");
+ } elsif ($params{'volume_error'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} is a volume in error: $params{'err'}, autolabel not set");
+ } elsif ($params{'not_success'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} is a device in error: $params{'err'}, autolabel not set");
+ } elsif ($params{'err'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "$params{'err'}");
+ } else {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} without label is not labelable ");
+ }
+ } elsif ($params{'empty'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} is empty, autolabel disabled");
+ } elsif ($params{'non_amanda'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} is a non-amanda volume, autolabel disabled");
+ } elsif ($params{'volume_error'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} is a volume in error: $params{'err'}, autolabel disabled");
+ } elsif ($params{'not_success'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} is a device in error: $params{'err'}, autolabel disabled");
+ } elsif ($params{'err'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "$params{'err'}");
+ } elsif ($params{'not_labelable'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} without label can't be labeled");
+ } elsif (!defined $params{'label'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} without label can be labeled");
+ } elsif ($params{'relabeled'}) {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} with label $params{'label'} will be relabeled");
+ } else {
+ $self->{'feedback'}->scribe_notif_log_info(
+ message => "Slot $params{'slot'} with label $params{'label'} is usable");
+ }
+ }
+ };
+
+ $self->{'taperscan'}->scan(
+ user_msg_fn => $_user_msg_fn,
+ result_cb => sub {
my ($error, $reservation, $volume_label, $access_mode, $is_new) = @_;
$self->{'scan_running'} = 0;
$self->{'scan_finished'} = 1;
- if ($error) {
- $self->{'scan_error'} = $error;
- } else {
- $self->{'reservation'} = $reservation;
- $self->{'device'} = $reservation->{'device'};
- $self->{'volume_label'} = $volume_label;
- $self->{'access_mode'} = $access_mode;
- $self->{'is_new'} = $is_new;
- }
+ $self->{'scan_error'} = $error;
+ $self->{'reservation'} = $reservation;
+ $self->{'device'} = $reservation->{'device'} if $reservation;
+ $self->{'volume_label'} = $volume_label;
+ $self->{'access_mode'} = $access_mode;
+ $self->{'is_new'} = $is_new;
$self->_maybe_callback();
});
} elsif ($params{'cause'} eq 'error') {
$self->{'error_denial_message'} = $params{'message'};
} else {
- die "bad cause '" . $params{'cause'} . "'";
+ confess "bad cause '" . $params{'cause'} . "'";
}
} elsif (!defined $params{'allow'}) {
- die "no allow or cause defined";
+ confess "no allow or cause defined";
}
$self->_maybe_callback();