# This file was automatically generated by SWIG (http://www.swig.org).
# Version 1.3.35
#
# Don't modify this file, modify the SWIG interface instead.

package Amanda::Xfer;
require Exporter;
require DynaLoader;
@ISA = qw(Exporter DynaLoader);
require Amanda::MainLoop;
require Amanda::Device;
require Amanda::Types;
package Amanda::Xferc;
bootstrap Amanda::Xfer;
package Amanda::Xfer;
@EXPORT = qw( );

# ---------- BASE METHODS -------------

package Amanda::Xfer;

sub TIEHASH {
    my ($classname,$obj) = @_;
    return bless $obj, $classname;
}

sub CLEAR { }

sub FIRSTKEY { }

sub NEXTKEY { }

sub FETCH {
    my ($self,$field) = @_;
    my $member_func = "swig_${field}_get";
    $self->$member_func();
}

sub STORE {
    my ($self,$field,$newval) = @_;
    my $member_func = "swig_${field}_set";
    $self->$member_func($newval);
}

sub this {
    my $ptr = shift;
    return tied(%$ptr);
}


# ------- FUNCTION WRAPPERS --------

package Amanda::Xfer;

*xfer_new = *Amanda::Xferc::xfer_new;
*xfer_unref = *Amanda::Xferc::xfer_unref;
*xfer_get_status = *Amanda::Xferc::xfer_get_status;
*xfer_repr = *Amanda::Xferc::xfer_repr;
*xfer_start = *Amanda::Xferc::xfer_start;
*xfer_cancel = *Amanda::Xferc::xfer_cancel;
*xfer_element_unref = *Amanda::Xferc::xfer_element_unref;
*xfer_element_repr = *Amanda::Xferc::xfer_element_repr;
*xfer_source_device = *Amanda::Xferc::xfer_source_device;
*xfer_source_random = *Amanda::Xferc::xfer_source_random;
*xfer_source_pattern = *Amanda::Xferc::xfer_source_pattern;
*xfer_source_fd = *Amanda::Xferc::xfer_source_fd;
*xfer_filter_xor = *Amanda::Xferc::xfer_filter_xor;
*xfer_dest_device = *Amanda::Xferc::xfer_dest_device;
*xfer_dest_null = *Amanda::Xferc::xfer_dest_null;
*xfer_dest_fd = *Amanda::Xferc::xfer_dest_fd;
*xfer_get_amglue_source = *Amanda::Xferc::xfer_get_amglue_source;

# ------- VARIABLE STUBS --------

package Amanda::Xfer;

*XFER_INIT = *Amanda::Xferc::XFER_INIT;
*XFER_START = *Amanda::Xferc::XFER_START;
*XFER_RUNNING = *Amanda::Xferc::XFER_RUNNING;
*XFER_DONE = *Amanda::Xferc::XFER_DONE;
*XMSG_INFO = *Amanda::Xferc::XMSG_INFO;
*XMSG_ERROR = *Amanda::Xferc::XMSG_ERROR;
*XMSG_DONE = *Amanda::Xferc::XMSG_DONE;
*XMSG_CANCEL = *Amanda::Xferc::XMSG_CANCEL;

@EXPORT_OK = ();
%EXPORT_TAGS = ();

=head1 NAME

Amanda::Xfer - the transfer architecture

=head1 SYNOPSIS

  use Amanda::MainLoop;
  use Amanda::Xfer qw( :constants );
  use POSIX;

  my $infd = POSIX::open("input", POSIX::O_RDONLY, 0);
  my $outfd = POSIX::open("output", POSIX::O_CREAT|POSIX::O_WRONLY, 0640);
  my $xfer = Amanda::Xfer->new([
    Amanda::Xfer::Source::Fd->new($infd),
    Amanda::Xfer::Dest::Fd->new($outfd)
  ]);
  $xfer->get_source()->set_callback(sub {
      my ($src, $xmsg, $xfer) = @_;
      print "Message from $xfer: $xmsg\n"; # use stringify operations
      if ($xfer->get_status() == $XFER_DONE) {
	  $src->remove();
	  Amanda::MainLoop::quit();
      }
  });
  $xfer->start();
  Amanda::MainLoop::run();
  
See L<http://wiki.zmanda.com/index.php/XFA> for background on the transfer
architecture.

=head1 API STATUS

Fluid.

=head1 Amanda::Xfer Objects

A new transfer is created with C<< Amanda::Xfer->new() >>, which takes an arrayref
giving the transfer elements which should compose the transfer.

The resulting object has the following methods:

=over

=item get_source()

Get the L<Amanda::MainLoop> event source through which messages will be
delivered for this transfer.  Use its C<set_callback> method to connect a perl
sub for processing events.  You I<must> C<release> the source when the
transfer is complete!

The callback from this event source receives three arguments: the event source,
the message, and a reference to the controlling transfer.  See the description of
C<Amanda::Xfer::Msg>, below, for details.

=item start()

Start this transfer.  Processing takes place asynchronously, and messages will
begin queueing up immediately.

=item cancel()

Stop transferring data.  The transfer will send an C<XMSG_CANCEL>, "drain" any
buffered data as best it can, and then complete normally with an C<XMSG_DONE>.

=item get_status()

Get the transfer's status.  The result will be one of C<$XFER_INIT>,
C<$XFER_START>, C<$XFER_RUNNING>, or C<$XFER_DONE>.  These symbols are
available for import with the tag C<:constants>.

=item repr()

Return a string representation of this transfer, suitable for use in debugging
messages.  This method is automatically invoked when a transfer is interpolated
into a string:
  print "Starting $xfer\n";

=back

=head1 Amanda::Xfer::Element objects

The individual transfer elements that compose a transfer are instances of
subclasses of Amanda::Xfer::Element.  All such objects have a C<repr()> method,
similar to that for transfers, and support a similar kind of string
interpolation.

Note that the names of these classes contain the words "Source", "Filter", and
"Dest".  This is merely suggestive of their intended purpose -- there are no
such abstract classes.

=head2 Transfer Sources

=head3 Amanda::Xfer::Source::Device

  Amanda::Xfer::Source::Device->new($device);

This source reads data from a device.  The device should already be queued up
for reading (C<$device->seek_file(..)>).  The element will read until the end
of the device file.

=head3 Amanda::Xfer::Source::Fd

  Amanda::Xfer::Source::Fd->new(fileno($fh));

This source reads data from a file descriptor.  It reads until EOF, but does
not close the descriptor.  Be careful not to let Perl close the file for you!

=head3 Amanda::Xfer::Source::Random

  Amanda::Xfer::Source::Random->new($length, $seed);

This source provides I<length> bytes of random data (or an unlimited amount
of data if I<length> is zero).  C<$seed> is the seed used
to generate the random numbers; this seed can be used in a destination to
check for correct output.

=head3 Amanda::Xfer::Source::Pattern

  Amanda::Xfer::Source::Pattern->new($length, $pattern);

This source provides I<length> bytes containing copies of
I<pattern>. If I<length> is zero, the source provides an unlimited
number of bytes.

=head2 Transfer Filters

=head3 Amanda::Xfer::Filter:Xor

  Amanda::Xfer::Filter::Xor->new($key);

This filter applies a bytewise XOR operation to the data flowing through it.

=head2 Transfer Destinations

=head3 Amanda::Xfer::Dest::Device

  Amanda::Xfer::Dest::Device->new($device, $max_memory);

This source writes data to a device.  The device should already be queued up
for writing (C<$device->start_file(..)>).  No more than C<$max_memory> will be
used for buffers.  Use zero for the default buffer size.  On completion of the
transfer, the file will be finished.

=head3 Amanda::Xfer::Dest::Fd

  Amanda::Xfer::Dest::Fd->new(fileno($fh));

This destination writes data to a file descriptor.  The file is not closed
after the transfer is completed.  Be careful not to let Perl close the file
for you!

=head3 Amanda::Xfer::Dest::Null

  Amanda::Xfer::Dest::Null->new($seed);

This destination discards the data it receives.  If C<$seed> is nonzero, then
the element will validate that it receives the data that
C<Amanda::Xfer::Source::Random> produced with the same seed.  No validation is
performed if C<$seed> is zero.

=head1 Amanda::Xfer::Msg objects

Messages are simple hashrefs, with a few convenience methods.  Like transfers,
they have a C<repr()> method that formats the message nicely, and is available
through string interpolation:
  print "Received message $msg\n";

Every message has the following keys:

=over

=item type

The message type -- one of the C<xmsg_type> constants available from the import
tag C<:constants>.

=item elt

The transfer element that sent the message.

=item version

The version of the message.  This is used to support extensibility of the protocol.

=back

The canonical description of the message types and keys is in C<xfer-src/xmsg.h>, and is
not duplicated here.

=cut

push @EXPORT_OK, qw(xfer_status_to_string);
push @{$EXPORT_TAGS{"xfer_status"}}, qw(xfer_status_to_string);

my %_xfer_status_VALUES;
#Convert an enum value to a single string
sub xfer_status_to_string {
    my ($enumval) = @_;

    for my $k (keys %_xfer_status_VALUES) {
	my $v = $_xfer_status_VALUES{$k};

	#is this a matching flag?
	if ($enumval == $v) {
	    return $k;
	}
    }

#default, just return the number
    return $enumval;
}

push @EXPORT_OK, qw($XFER_INIT);
push @{$EXPORT_TAGS{"xfer_status"}}, qw($XFER_INIT);

$_xfer_status_VALUES{"XFER_INIT"} = $XFER_INIT;

push @EXPORT_OK, qw($XFER_START);
push @{$EXPORT_TAGS{"xfer_status"}}, qw($XFER_START);

$_xfer_status_VALUES{"XFER_START"} = $XFER_START;

push @EXPORT_OK, qw($XFER_RUNNING);
push @{$EXPORT_TAGS{"xfer_status"}}, qw($XFER_RUNNING);

$_xfer_status_VALUES{"XFER_RUNNING"} = $XFER_RUNNING;

push @EXPORT_OK, qw($XFER_DONE);
push @{$EXPORT_TAGS{"xfer_status"}}, qw($XFER_DONE);

$_xfer_status_VALUES{"XFER_DONE"} = $XFER_DONE;

#copy symbols in xfer_status to constants
push @{$EXPORT_TAGS{"constants"}},  @{$EXPORT_TAGS{"xfer_status"}};

push @EXPORT_OK, qw(xmsg_type_to_string);
push @{$EXPORT_TAGS{"xmsg_type"}}, qw(xmsg_type_to_string);

my %_xmsg_type_VALUES;
#Convert an enum value to a single string
sub xmsg_type_to_string {
    my ($enumval) = @_;

    for my $k (keys %_xmsg_type_VALUES) {
	my $v = $_xmsg_type_VALUES{$k};

	#is this a matching flag?
	if ($enumval == $v) {
	    return $k;
	}
    }

#default, just return the number
    return $enumval;
}

push @EXPORT_OK, qw($XMSG_INFO);
push @{$EXPORT_TAGS{"xmsg_type"}}, qw($XMSG_INFO);

$_xmsg_type_VALUES{"XMSG_INFO"} = $XMSG_INFO;

push @EXPORT_OK, qw($XMSG_ERROR);
push @{$EXPORT_TAGS{"xmsg_type"}}, qw($XMSG_ERROR);

$_xmsg_type_VALUES{"XMSG_ERROR"} = $XMSG_ERROR;

push @EXPORT_OK, qw($XMSG_DONE);
push @{$EXPORT_TAGS{"xmsg_type"}}, qw($XMSG_DONE);

$_xmsg_type_VALUES{"XMSG_DONE"} = $XMSG_DONE;

push @EXPORT_OK, qw($XMSG_CANCEL);
push @{$EXPORT_TAGS{"xmsg_type"}}, qw($XMSG_CANCEL);

$_xmsg_type_VALUES{"XMSG_CANCEL"} = $XMSG_CANCEL;

#copy symbols in xmsg_type to constants
push @{$EXPORT_TAGS{"constants"}},  @{$EXPORT_TAGS{"xmsg_type"}};

package Amanda::Xfer::Xfer;

sub new { 
    my $pkg = shift;


    Amanda::Xfer::xfer_new(@_);
}
*DESTROY = *Amanda::Xfer::xfer_unref;
use overload '""' => sub { $_[0]->repr(); };
*repr = *Amanda::Xfer::xfer_repr;
*get_status = *Amanda::Xfer::xfer_get_status;
*get_source = *Amanda::Xfer::xfer_get_amglue_source;
*start = *Amanda::Xfer::xfer_start;
*cancel = *Amanda::Xfer::xfer_cancel;

package Amanda::Xfer::Element;
*DESTROY = *Amanda::Xfer::xfer_element_unref;
use overload '""' => sub { $_[0]->repr(); };
*repr = *Amanda::Xfer::xfer_element_repr;

package Amanda::Xfer::Element::Glue;

use vars qw(@ISA);
@ISA = qw( Amanda::Xfer::Element );

package Amanda::Xfer::Source::Device;

use vars qw(@ISA);
@ISA = qw( Amanda::Xfer::Element );

sub new { 
    my $pkg = shift;


    Amanda::Xfer::xfer_source_device(@_);
}

package Amanda::Xfer::Source::Fd;

use vars qw(@ISA);
@ISA = qw( Amanda::Xfer::Element );

sub new { 
    my $pkg = shift;


    Amanda::Xfer::xfer_source_fd(@_);
}

package Amanda::Xfer::Source::Random;

use vars qw(@ISA);
@ISA = qw( Amanda::Xfer::Element );

sub new { 
    my $pkg = shift;


    Amanda::Xfer::xfer_source_random(@_);
}

package Amanda::Xfer::Source::Pattern;

use vars qw(@ISA);
@ISA = qw( Amanda::Xfer::Element );

sub new { 
    my $pkg = shift;


    Amanda::Xfer::xfer_source_pattern(@_);
}

package Amanda::Xfer::Filter::Xor;

use vars qw(@ISA);
@ISA = qw( Amanda::Xfer::Element );

sub new { 
    my $pkg = shift;


    Amanda::Xfer::xfer_filter_xor(@_);
}

package Amanda::Xfer::Dest::Device;

use vars qw(@ISA);
@ISA = qw( Amanda::Xfer::Element );

sub new { 
    my $pkg = shift;


    Amanda::Xfer::xfer_dest_device(@_);
}

package Amanda::Xfer::Dest::Fd;

use vars qw(@ISA);
@ISA = qw( Amanda::Xfer::Element );

sub new { 
    my $pkg = shift;


    Amanda::Xfer::xfer_dest_fd(@_);
}

package Amanda::Xfer::Dest::Null;

use vars qw(@ISA);
@ISA = qw( Amanda::Xfer::Element );

sub new { 
    my $pkg = shift;


    Amanda::Xfer::xfer_dest_null(@_);
}

package Amanda::Xfer::Msg;

use Data::Dumper;
use overload '""' => sub { $_[0]->repr(); };

sub repr {
    my ($self) = @_;
    local $Data::Dumper::Indent = 0;
    local $Data::Dumper::Terse = 1;
    local $Data::Dumper::Useqq = 1;

    my $typestr = Amanda::Xfer::xmsg_type_to_string($self->{'type'});
    my $str = "{ type => \$$typestr, elt => $self->{'elt'}, version => $self->{'version'},";

    my %skip = ( "type" => 1, "elt" => 1, "version" => 1 );
    for my $k (keys %$self) {
	next if $skip{$k};
	$str .= " $k => " . Dumper($self->{$k}) . ",";
    }

    # strip the trailing comma and add a closing brace
    $str =~ s/,$/ }/g;

    return $str;
}

package Amanda::Xfer;

# make Amanda::Xfer->new equivalent to Amanda::Xfer::Xfer->new (don't
# worry, the blessings work out just fine)
*new = *Amanda::Xfer::Xfer::new;
1;
