3.1.3

Amanda::Taper::Scribe


NAME

Amanda::Taper::Scribe


SYNOPSIS

  my $scribe = Amanda::Taper::Scribe->new(
        taperscan => $taperscan_algo,
        feedback => $feedback_obj);
  $subs{'start_scribe'} = make_cb(start_scribe => sub {
    $scribe->start($datestamp, finished_cb => $subs{'start_xfer'});
  });
  $subs{'start_xfer'} = make_cb(start_xfer => sub {
    my ($err) = @_;
    my $xfer_dest = $scribe->get_xfer_dest(
        max_memory => 64 * 1024,
        split_method => 'disk',
        part_size => 150 * 1024**2,
        disk_cache_dirname => "$tmpdir/splitbuffer");
    # .. set up the rest of the transfer ..
    $xfer->start(sub {
        my ($src, $msg, $xfer) = @_;
        $scribe->handle_xmsg($src, $msg, $xfer);
        # .. any other processing ..
    });
    # tell the scribe to start dumping via this transfer
    $scribe->start_dump(
        xfer => $xfer,
        dump_header => $hdr,
        dump_cb => $subs{'dump_cb'});
  });
  $subs{'dump_cb'} = make_cb(dump_cb => sub {
      my %params = @_;
      # .. handle dump results ..
      print "DONE\n";
      Amanda::MainLoop::quit();
  });
  $subs{'start_scribe'}->();
  Amanda::MainLoop::run();


OVERVIEW

This package provides a high-level abstraction of Amanda's procedure for writing dumpfiles to tape.

Amanda writes a sequence of dumpfiles to a sequence of volumes. The volumes are supplied by a taperscan algorithm, which operates a changer to find and load each volume. As dumpfiles are written to volumes and those volumes fill up, the taperscan algorithm supplies additional volumes.

In order to reduce internal fragmentation within volumes, Amanda can "split" dumpfiles into smaller pieces, so that the overall dumpfile can span multiple volumes. Each "part" is written to the volume in sequence. If a device encounters an error while writing a part, then that part is considered "partial", and is rewritten from its beginning on the next volume. Some devices can reliably indicate that they are full (EOM), and for these devices parts are simply truncated, and the Scribe starts the next part on the next volume.

To facilitate rewriting parts on devices which cannot indicate EOM, Amanda must retain all of the data in a part, even after that data is written to the volume. The Scribe provides several methods to support this: caching the part in memory, caching the part in a special on-disk file, or relying on pre-existing on-disk storage. The latter method is used when reading from holding disks.

The details of efficiently splitting dumpfiles and rewriting parts are handled by the low-level Amanda::Xfer::Dest::Taper subclasses. The Scribe creates an instance of the appropriate subclass and supplies it with volumes from an Amanda::Taper::Scan object. It calls a number of Amanda::Taper::Scribe::Feedback methods to indicate the status of the dump process and to request permission for each additional volume.


OPERATING A SCRIBE

The Amanda::Taper::Scribe constructor takes two arguments: taperscan and feedback. The first specifies the taper scan algorithm that the Scribe should use, and the second specifies the Feedback object that will receive notifications from the Scribe (see below).

  my $scribe = Amanda::Taper::Scribe->new(
        taperscan => $my_taperscan,
        feedback => $my_feedback);

Once the object is in place, call its start method.

START THE SCRIBE

Start the scribe's operation by calling its start method. This will invoke the taperscan algorithm and scan for a volume. The method takes two parameters:

  $scribe->start(
        dump_timestamp => $ts,
        finished_cb => $start_finished_cb);

The timestamp will be written to each volume written by the Scribe. The finished_cb will be called with a single argument - undef or an error message - when the Scribe is ready to start its first dump. The Scribe is "ready" when it has found a device to which it can write, although it does not request permission to overwrite that volume, nor start overwriting it, until the first dump begins (that is, until the first call to start_dump).

SET UP A TRANSFER

Once the Scribe is started, begin transferring a dumpfile. This is a three-step process: first, get an Amanda::Xfer::Dest::Taper object from the Scribe, then start the transfer, and finally let the Scribe know that the transfer has started. Note that the Scribe supplies and manages the transfer destination, but the transfer itself remains the responsibility of the caller.

Get device

Call get_device to get the first device the xfer will be working with.

  $device = $scribe->get_device();

This method must be called after start has completed.

Check device compatibily for the data path

Call check_data_path, supplying the data_path requested by the user.

  if (my $err = $scribe->check_data_path($data_path)) {
      # handle error message
  }

This method must be called after start has completed and before get_xfer_dest is called, it return undef on success or an error message if the supplied data_path is incompatible with the device.

Get a Transfer Destination

Call get_xfer_dest to get the transfer element, supplying information on how the dump should be split:

  $xdest = $scribe->get_xfer_dest(
        max_memory => $max_memory,
        # .. split parameters
        );

This method must be called after start has completed, and will always return a transfer element immediately.

The underlying Amanda::Xfer::Dest::Taper handles device streaming properly. It uses max_memory bytes of memory for this purpose.

The arguments to get_xfer_dest differ for the various split methods. For no splitting:

  $scribe->get_xfer_dest(
        # ...
        split_method => 'none');

For buffering the split parts in memory:

  $scribe->get_xfer_dest(
        # ...
        split_method => 'memory',
        part_size => $part_size);

For buffering the split parts on disk:

  $scribe->get_xfer_dest(
        # ...
        split_method => 'disk',
        part_size => $part_size,
        disk_cache_dirname => $disk_cache_dirname);

Finally, if the transfer source is capable of calling Amanda::Xfer::Dest::Taper's cache_inform method:

  $scribe->get_xfer_dest(
        # ...
        split_method => 'cache_inform',
        part_size => $part_size);

An Amanda::Taper::Scribe object can only run one transfer at a time, so do not call get_xfer_dest until the dump_cb for the previous start_dump has been called.

Start the Transfer

Armed with the element returned by get_xfer_dest, the caller should create a source element and a transfer object and start the transfer. In order to manage the splitting process, the Scribe needs to be informed, via its handle_xmsg method, of all transfer messages . This is usually accomplished with something like:

  $xfer->start(sub {
      my ($src, $msg, $xfer) = @_;
      $scribe->handle_xmsg($src, $msg, $xfer);
  });

Inform the Scribe

Once the transfer has started, the Scribe is ready to begin writing parts to the volume. This is the first moment at which the Scribe needs a header, too. All of this is supplied to the start_dump method:

  $scribe->start_dump(
      xfer => $xfer,
      dump_header => $hdr,
      dump_cb => $dump_cb);

The c<dump_header> here is the header that will be applied to all parts of the dumpfile. The only field in the header that the Scribe controls is the part number. The dump_cb callback passed to start_dump is called when the dump is completely finished - either successfully or with a fatal error. Unlike most callbacks, this one takes keyword arguments, since it has so many parameters.

  $dump_cb->(
        result => $result,
        device_errors => $device_errors,
        size => $size,
        duration => $duration,
        total_duration => $total_duration);

All parameters will be present on every call.

The result is one of "FAILED", "PARTIAL", or "DONE". Even when dump_cb reports a fatal error, result may be "PARTIAL" if some data was written successfully.

The final parameters, size (in bytes), duration, and total_duration (in seconds) describe the total transfer, and are a sum of all of the parts written to the device. Note that duration does not include time spent operating the changer, while total_duration reflects the time from the start_dump call to the invocation of the dump_cb.

TODO: cancel_dump

QUIT

When all of the dumpfiles are transferred, call the quit method to release any resources and clean up. This method takes a typical finished_cb.

  $scribe->quit(finished_cb => sub {
    print "ALL DONE!\n";
  });

GET_BYTES_WRITTEN

The get_bytes_written returns the number of bytes written to the device at the time of the call, and is meant to be used for status reporting. This value is updated at least as each part is finished; for some modes of operation, it is updated continuously. Notably, DirectTCP transfers do not update continuously.


FEEDBACK

The Amanda::Taper::Scribe::Feedback class is intended to be subclassed by the user. It provides a number of notification methods that enable the historical logging and driver/taper interactions required by Amanda. The parent class does nothing of interest, but allows subclasses to omit methods they do not need.

The request_volume_permission method provides a means for the caller to limit the number of volumes the Scribe consumes. It is called as

  $fb->request_volume_permission(perm_cb => $cb);

where the perm_cb is a callback which expects a single argument: undef if permission is granted, or reason (as a string) if permission is denied. The default implementation always calls perm_cb->(undef).

All of the remaining methods are notifications, and do not take a callback.

  $fb->notif_new_tape(
        error => $error,
        volume_label => $volume_label);

The Scribe calls notif_new_tape when a new volume is started. If the volume_label is undefined, then the volume was not successfully relabled, and its previous contents may still be available. If error is defined, then no useful data was written to the volume. Note that error and volume_label may both be defined if the previous contents of the volume were erased, but no useful, new data was written to the volume.

This method will be called exactly once for every call to request_volume_permission that calls perm_cb->(undef).

  $fb->notif_part_done(
        partnum => $partnum,
        fileno => $fileno,
        successful => $successful,
        size => $size,
        duration => $duration);

The Scribe calls notif_part_done for each part written to the volume, including partial parts. If the part was not written successfully, then successful is false. The size is in bytes, and the duration is a floating-point number of seconds. If a part fails before a new device file is created, then fileno may be zero.

Finally, the Scribe sends a few historically significant trace log messages via notif_log_info:

  $fb->notif_log_info(
        message => $message);

A typical Feedback subclass might begin like this:

  package main::Feedback;
  use base 'Amanda::Taper::Scribe::Feedback';
  sub request_volume_permission {
    my $self = shift;
    my %params = @_;
    $params{'perm_cb'}->("NO VOLUMES FOR YOU!");
  }


ABOUT THIS PAGE

This page was automatically generated Tue Nov 19 20:05:35 2013 from the Amanda source tree, and documents the most recent development version of Amanda. For documentation specific to the version of Amanda on your system, use the 'perldoc' command.


3.1.3