X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=perl%2FAmanda%2FXfer.swg;h=6b980b1635d731d14c61858401cd51d7790ee7d9;hb=fd48f3e498442f0cbff5f3606c7c403d0566150e;hp=6140571927e83a9ed4fab8e052e4f1aff39adf68;hpb=96f35b20267e8b1a1c846d476f27fcd330e0b018;p=debian%2Famanda diff --git a/perl/Amanda/Xfer.swg b/perl/Amanda/Xfer.swg index 6140571..6b980b1 100644 --- a/perl/Amanda/Xfer.swg +++ b/perl/Amanda/Xfer.swg @@ -1,227 +1,36 @@ /* - * Copyright (c) Zmanda, Inc. All Rights Reserved. + * Copyright (c) 2008, 2009, 2010 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 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 library is distributed in the hope that it will be useful, but + * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Contact information: Zmanda Inc., 465 S Mathlida Ave, Suite 300 - * Sunnyvale, CA 94086, USA, or: http://www.zmanda.com + * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300 + * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com */ %module "Amanda::Xfer" %include "amglue/amglue.swg" %include "exception.i" +%include "cstring.i" %import "Amanda/MainLoop.swg" -%import "Amanda/Device.swg" + +%include "Xfer.pod" %{ #include "glib-util.h" #include "amxfer.h" %} -%perlcode %{ -=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 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 event source through which messages will be -delivered for this transfer. Use its C method to connect a perl -sub for processing events. You I C 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, 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, "drain" any -buffered data as best it can, and then complete normally with an C. - -=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 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 bytes of random data (or an unlimited amount -of data if I 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 bytes containing copies of -I. If I 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 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 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 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, and is -not duplicated here. - -=cut -%} - /* The SWIGging of the transfer architecture. * * The C layer of the transfer architecture exposes some structs, which are @@ -274,6 +83,8 @@ amglue_add_constant(XMSG_INFO, xmsg_type); amglue_add_constant(XMSG_ERROR, xmsg_type); amglue_add_constant(XMSG_DONE, xmsg_type); amglue_add_constant(XMSG_CANCEL, xmsg_type); +amglue_add_constant(XMSG_PART_DONE, xmsg_type); +amglue_add_constant(XMSG_READY, xmsg_type); amglue_copy_to_tag(xmsg_type, constants); /* @@ -281,118 +92,6 @@ amglue_copy_to_tag(xmsg_type, constants); */ %{ -/* Return a new SV with refcount 1 representing the given C object - * with the given class. - * - * @param c_obj: the object to represent - * @param perl_class: the perl with which to bless and tie the SV - */ -static SV * -new_sv_for_c_obj( - gpointer c_obj, - const char *perl_class) -{ - SV *sv = newSV(0); - - /* Make an SV that contains a pointer to the object, and bless it - * with the appropriate class. */ - sv_setref_pv(sv, perl_class, c_obj); - - return sv; -} - -/* Return a new SV representing a transfer. - * - * @param xfer: the transfer to represent - */ -static SV * -new_sv_for_xfer( - Xfer *xfer) -{ - if (!xfer) return &PL_sv_undef; - - xfer_ref(xfer); - return new_sv_for_c_obj(xfer, "Amanda::Xfer::Xfer"); -} - -/* Return a new SV representing a transfer element. - * - * @param xe: the transfer element to represent - */ -static SV * -new_sv_for_xfer_element( - XferElement *xe) -{ - const char *perl_class; - - if (!xe) return &PL_sv_undef; - - perl_class = XFER_ELEMENT_GET_CLASS(xe)->perl_class; - if (!perl_class) die("Attempt to wrap an XferElementClass with no perl class!"); - g_object_ref(xe); - return new_sv_for_c_obj(xe, perl_class); -} - -/* Return the C object buried in an SV, asserting that the perl SV is - * derived from derived_from. Returns NULL for undefined perl values. - * - * This function is based on SWIG's SWIG_Perl_ConvertPtr. The INT2PTR - * situation certainly looks strange, but is documented in perlxs. - * - * @param sv: the SV to convert - * @param derived_from: perl class from which the SV should be derived - * @return: underlying pointer - */ -static gpointer -c_obj_from_sv( - SV *sv, - const char *derived_from) -{ - SV *referent; - IV tmp; - - if (!sv) return NULL; - if (!SvOK(sv)) return NULL; - - /* Peel back the layers. The sv should be a blessed reference to a PV, - * and we check the class against derived_from to ensure we have the right - * stuff. */ - if (!sv_isobject(sv) || !sv_derived_from(sv, derived_from)) { - croak("Value is not an object of type %s", derived_from); - return NULL; - } - - referent = (SV *)SvRV(sv); - tmp = SvIV(referent); - return INT2PTR(gpointer, tmp); -} - -/* Convert an SV to an Xfer. The Xfer's reference count is not - * incremented -- this is a "borrowed" reference. - * - * @param sv: the perl value - * @returns: pointer to the corresponding transfer, or NULL - */ -static Xfer * -xfer_from_sv( - SV *sv) -{ - return (Xfer *)c_obj_from_sv(sv, "Amanda::Xfer::Xfer"); -} - -/* Convert an SV to an XferElement. The element's reference count is - * not incremented -- this is a "borrowed" reference. - * - * @param sv: the perl value - * @returns: pointer to the corresponding transfer element, or NULL. - */ -static XferElement * -xfer_element_from_sv( - SV *sv) -{ - return (XferElement *)c_obj_from_sv(sv, "Amanda::Xfer::Element"); -} - /* Given an XMsg, return a hashref representing the message as a pure-perl * object. The object is new, has refcount 1, and is totally independent of * the underlying XMsg. @@ -436,6 +135,27 @@ new_sv_for_xmsg( if (msg->message) hv_store(hash, "message", 7, newSVpv(msg->message, 0), 0); + /* successful */ + hv_store(hash, "successful", 10, newSViv(msg->successful), 0); + + /* eom */ + hv_store(hash, "eom", 3, newSViv(msg->eom), 0); + + /* eof */ + hv_store(hash, "eof", 3, newSViv(msg->eof), 0); + + /* size */ + hv_store(hash, "size", 4, amglue_newSVu64(msg->size), 0); + + /* duration */ + hv_store(hash, "duration", 8, newSVnv(msg->duration), 0); + + /* partnum */ + hv_store(hash, "partnum", 7, amglue_newSVu64(msg->partnum), 0); + + /* fileno */ + hv_store(hash, "fileno", 6, amglue_newSVu64(msg->fileno), 0); + return rv; } %} @@ -517,6 +237,25 @@ void xfer_cancel(Xfer *xfer); #define xfer_get_status(xfer) ((xfer)->status) %} +/* upgrade the start method to optionally take a callback, which is + * passed to the GSource's set_callback */ +%perlcode %{ +sub xfer_start_with_callback { + my ($xfer, $cb) = @_; + if (defined $cb) { + my $releasing_cb = sub { + my ($src, $msg, $xfer) = @_; + my $done = $msg->{'type'} == $XMSG_DONE; + $src->remove() if $done; + $cb->(@_); + $cb = undef if $done; # break potential reference loop + }; + $xfer->get_source()->set_callback($releasing_cb); + } + xfer_start($xfer); +} +%} + /* * XferElement functions * @@ -530,20 +269,28 @@ char *xfer_element_repr(XferElement *elt); /* xfer_element_start -- private */ /* xfer_element_cancel -- private */ +%inline %{ +static gboolean same_elements( + XferElement *a, + XferElement *b) +{ + return a == b; +} +%} + /* subclass constructors */ /* N.B. When adding new classes, ensure that the class_init function * sets perl_class to the appropriate value. */ -%newobject xfer_source_device; -XferElement *xfer_source_device( - Device *device); - %newobject xfer_source_random; XferElement *xfer_source_random( guint64 length, guint32 seed); +guint32 xfer_source_random_get_seed( + XferElement *self); + %typemap(in) (void * pattern, size_t pattern_length) { size_t len; char * pat; @@ -553,7 +300,35 @@ XferElement *xfer_source_random( $2 = len; } -%newobject xfer_source_random; +%typemap(in) (gchar **argv) { + AV *av; + unsigned int len; + unsigned int i; + + /* check that it's an arrayref */ + if (!SvROK($input) || SvTYPE(SvRV($input)) != SVt_PVAV) { + SWIG_exception(SWIG_TypeError, "Expected a non-empty arrayref"); + } + av = (AV *)SvRV($input); + + /* allocate memory for $1 */ + len = av_len(av)+1; /* av_len(av) is like $#av */ + if (!len) { + SWIG_exception(SWIG_TypeError, "Expected a non-empty arrayref"); + } + $1 = g_new0(gchar *, len+1); + + for (i = 0; i < len; i++) { + SV **sv = av_fetch(av, i, 0); + g_assert(sv != NULL); + $1[i] = g_strdup(SvPV_nolen(*sv)); + } + + /* final element is already NULL due to g_new0; xfer_filter_process takes + * care of freeing this array, so we don't have to */ +} + +%newobject xfer_source_pattern; XferElement *xfer_source_pattern( guint64 length, void * pattern, @@ -563,23 +338,59 @@ XferElement *xfer_source_pattern( XferElement *xfer_source_fd( int fd); +%newobject xfer_source_directtcp_listen; +XferElement *xfer_source_directtcp_listen(void); + +%inline %{ +static DirectTCPAddr * +xfer_source_directtcp_listen_get_addrs(XferElement *elt) { + return elt->input_listen_addrs; +} +%} + +%newobject xfer_source_directtcp_connect; +XferElement *xfer_source_directtcp_connect(DirectTCPAddr *addrs); + %newobject xfer_filter_xor; XferElement *xfer_filter_xor( unsigned char xor_key); -%newobject xfer_dest_device; -XferElement *xfer_dest_device( - Device *device, - size_t max_memory); +%newobject xfer_filter_process; +XferElement *xfer_filter_process( + gchar **argv, + gboolean need_root); %newobject xfer_dest_null; XferElement *xfer_dest_null( guint32 prng_seed); +%newobject xfer_dest_buffer; +XferElement *xfer_dest_buffer( + gsize max_size); + +%cstring_output_allocate_size(gpointer *buf, gsize *size, ); +void xfer_dest_buffer_get( + XferElement *elt, + gpointer *buf, + gsize *size); + %newobject xfer_dest_fd; XferElement *xfer_dest_fd( int fd); +%newobject xfer_dest_directtcp_listen; +XferElement *xfer_dest_directtcp_listen(void); + +%inline %{ +static DirectTCPAddr * +xfer_dest_directtcp_listen_get_addrs(XferElement *elt) { + return elt->output_listen_addrs; +} +%} + +%newobject xfer_dest_directtcp_connect; +XferElement *xfer_dest_directtcp_connect(DirectTCPAddr *addrs); + /* * Callback handling */ @@ -595,23 +406,30 @@ xmsgsource_perl_callback( dSP; amglue_Source *src = (amglue_Source *)data; SV *src_sv = NULL; + SV *msg_sv = NULL; + SV *xfer_sv = NULL; + /* keep the source around long enough for the call to finish */ + amglue_source_ref(src); g_assert(src->callback_sv != NULL); ENTER; SAVETMPS; /* create a new SV pointing to 'src', and increase its refcount - * accordingly. The SV is mortal, so FREETMPS will decrease the - * refcount, unless the callee keeps a copy of it somewhere */ + * accordingly. */ amglue_source_ref(src); src_sv = SWIG_NewPointerObj(src, SWIGTYPE_p_amglue_Source, SWIG_OWNER | SWIG_SHADOW); + SvREFCNT_inc(src_sv); + + msg_sv = new_sv_for_xmsg(msg); + xfer_sv = new_sv_for_xfer(xfer); PUSHMARK(SP); - XPUSHs(src_sv); - XPUSHs(sv_2mortal(new_sv_for_xmsg(msg))); - XPUSHs(sv_2mortal(new_sv_for_xfer(xfer))); + XPUSHs(sv_2mortal(src_sv)); + XPUSHs(sv_2mortal(msg_sv)); + XPUSHs(sv_2mortal(xfer_sv)); PUTBACK; call_sv(src->callback_sv, G_EVAL|G_DISCARD); @@ -619,10 +437,15 @@ xmsgsource_perl_callback( FREETMPS; LEAVE; - /* these may have been freed, so don't use them after this point */ - src_sv = NULL; + /* we no longer need the src */ + amglue_source_unref(src); src = NULL; + /* these may be gone, so NULL them out */ + src_sv = NULL; + msg_sv = NULL; + xfer_sv = NULL; + /* check for an uncaught 'die'. If we don't do this, then Perl will longjmp() * over the GMainLoop mechanics, leaving GMainLoop in an inconsistent (locked) * state. */ @@ -665,52 +488,60 @@ package PKG; } %enddef -%define XFER_ELEMENT_SUBCLASS() +%define XFER_ELEMENT_SUBCLASS_OF(PARENT) %perlcode { use vars qw(@ISA); -@ISA = qw( Amanda::Xfer::Element ); +@ISA = qw( PARENT ); } %enddef +%define XFER_ELEMENT_SUBCLASS() +XFER_ELEMENT_SUBCLASS_OF(Amanda::Xfer::Element) +%enddef + %define DECLARE_CONSTRUCTOR(C_CONSTRUCTOR) %perlcode { sub new { my $pkg = shift; # The C function adds the proper blessing -- this function # just gets $pkg out of the way. - Amanda::Xfer::C_CONSTRUCTOR(@_); + C_CONSTRUCTOR(@_); } } %enddef %define OVERLOAD_REPR() -%perlcode {use overload '""' => sub { $_[0]->repr(); }; +%perlcode { +use overload '""' => sub { $_[0]->repr(); }; +# overload comparison, so users can ask if one obj == another +use overload '==' => sub { Amanda::Xfer::same_elements($_[0], $_[1]); }; +use overload '!=' => sub { not Amanda::Xfer::same_elements($_[0], $_[1]); }; } %enddef %define DECLARE_METHOD(METHOD_NAME, C_FUNCTION) -%perlcode {*METHOD_NAME = *Amanda::Xfer::C_FUNCTION; +%perlcode {*METHOD_NAME = *C_FUNCTION; } %enddef /* And now define the required perl classes */ PACKAGE(Amanda::Xfer::Xfer) -DECLARE_CONSTRUCTOR(xfer_new); -DECLARE_METHOD(DESTROY, xfer_unref); +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_new); +DECLARE_METHOD(DESTROY, Amanda::Xfer::xfer_unref); OVERLOAD_REPR() -DECLARE_METHOD(repr, xfer_repr); -DECLARE_METHOD(get_status, xfer_get_status); -DECLARE_METHOD(get_source, xfer_get_amglue_source); -DECLARE_METHOD(start, xfer_start); -DECLARE_METHOD(cancel, xfer_cancel); +DECLARE_METHOD(repr, Amanda::Xfer::xfer_repr); +DECLARE_METHOD(get_status, Amanda::Xfer::xfer_get_status); +DECLARE_METHOD(get_source, Amanda::Xfer::xfer_get_amglue_source); +DECLARE_METHOD(start, Amanda::Xfer::xfer_start_with_callback); +DECLARE_METHOD(cancel, Amanda::Xfer::xfer_cancel); /* ---- */ PACKAGE(Amanda::Xfer::Element) -DECLARE_METHOD(DESTROY, xfer_element_unref); +DECLARE_METHOD(DESTROY, Amanda::Xfer::xfer_element_unref); OVERLOAD_REPR() -DECLARE_METHOD(repr, xfer_element_repr); +DECLARE_METHOD(repr, Amanda::Xfer::xfer_element_repr); /* ---- */ @@ -720,51 +551,79 @@ XFER_ELEMENT_SUBCLASS() /* ---- */ -PACKAGE(Amanda::Xfer::Source::Device) +PACKAGE(Amanda::Xfer::Source::Fd) XFER_ELEMENT_SUBCLASS() -DECLARE_CONSTRUCTOR(xfer_source_device) +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_source_fd) /* ---- */ -PACKAGE(Amanda::Xfer::Source::Fd) +PACKAGE(Amanda::Xfer::Source::Random) XFER_ELEMENT_SUBCLASS() -DECLARE_CONSTRUCTOR(xfer_source_fd) +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_source_random) +DECLARE_METHOD(get_seed, Amanda::Xfer::xfer_source_random_get_seed) /* ---- */ -PACKAGE(Amanda::Xfer::Source::Random) +PACKAGE(Amanda::Xfer::Source::DirectTCPListen) XFER_ELEMENT_SUBCLASS() -DECLARE_CONSTRUCTOR(xfer_source_random) +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_source_directtcp_listen) +DECLARE_METHOD(get_addrs, Amanda::Xfer::xfer_source_directtcp_listen_get_addrs) + +/* ---- */ + +PACKAGE(Amanda::Xfer::Source::DirectTCPConnect) +XFER_ELEMENT_SUBCLASS() +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_source_directtcp_connect) /* ---- */ PACKAGE(Amanda::Xfer::Source::Pattern) XFER_ELEMENT_SUBCLASS() -DECLARE_CONSTRUCTOR(xfer_source_pattern) +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_source_pattern) /* ---- */ PACKAGE(Amanda::Xfer::Filter::Xor) XFER_ELEMENT_SUBCLASS() -DECLARE_CONSTRUCTOR(xfer_filter_xor) +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_filter_xor) /* ---- */ -PACKAGE(Amanda::Xfer::Dest::Device) +PACKAGE(Amanda::Xfer::Filter::Process) XFER_ELEMENT_SUBCLASS() -DECLARE_CONSTRUCTOR(xfer_dest_device) +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_filter_process) /* ---- */ PACKAGE(Amanda::Xfer::Dest::Fd) XFER_ELEMENT_SUBCLASS() -DECLARE_CONSTRUCTOR(xfer_dest_fd) +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_dest_fd) /* ---- */ PACKAGE(Amanda::Xfer::Dest::Null) XFER_ELEMENT_SUBCLASS() -DECLARE_CONSTRUCTOR(xfer_dest_null) +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_dest_null) + +/* ---- */ + +PACKAGE(Amanda::Xfer::Dest::Buffer) +XFER_ELEMENT_SUBCLASS() +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_dest_buffer) +DECLARE_METHOD(get, Amanda::Xfer::xfer_dest_buffer_get) + +/* ---- */ + +PACKAGE(Amanda::Xfer::Dest::DirectTCPListen) +XFER_ELEMENT_SUBCLASS() +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_dest_directtcp_listen) +DECLARE_METHOD(get_addrs, Amanda::Xfer::xfer_dest_directtcp_listen_get_addrs) + +/* ---- */ + +PACKAGE(Amanda::Xfer::Dest::DirectTCPConnect) +XFER_ELEMENT_SUBCLASS() +DECLARE_CONSTRUCTOR(Amanda::Xfer::xfer_dest_directtcp_connect) /* ---- */ @@ -802,4 +661,10 @@ 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; + +# try to load Amanda::XferServer, which is server-only. If it's not found, then +# its classes just remain undefined. +BEGIN { + eval "use Amanda::XferServer;"; +} %}