Imported Upstream version 3.2.0
[debian/amanda] / xfer-src / xfer-element.h
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 2008, 2009, 2010 Zmanda, Inc.  All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published
7  * by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17  *
18  * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19  * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
20  */
21
22 /* Base classes for transfer elements.
23  */
24
25 #ifndef XFER_ELEMENT_H
26 #define XFER_ELEMENT_H
27
28 #include <glib.h>
29 #include <glib-object.h>
30 #include "xfer.h"
31 #include "directtcp.h"
32
33 typedef enum {
34     /* sources have no input mechanisms and destinations have no output
35      * mechansisms. */
36     XFER_MECH_NONE,
37
38     /* downstream element will read() from elt->upstream's output_fd; EOF
39      * is indicated by the usual OS mechanism resulting in a zero-length
40      * read, in response to which the downstream element must close
41      * the fd. */
42     XFER_MECH_READFD,
43
44     /* upstream element will write() to elt->downstream's input_fd.  EOF
45      * is indicated by closing the file descriptor. */
46     XFER_MECH_WRITEFD,
47
48     /* downstream element will call elt->upstream->pull_buffer() to
49      * pull a buffer.  EOF is indicated by returning a NULL buffer */
50     XFER_MECH_PULL_BUFFER,
51
52     /* upstream element will call elt->downstream->push_buffer(buf) to push
53      * a buffer.  EOF is indicated by passing a NULL buffer. */
54     XFER_MECH_PUSH_BUFFER,
55
56     /* DirectTCP: downstream sends an array of IP:PORT addresses to which a TCP
57      * connection should be made, then upstream connects to one of the addreses
58      * and sends the data over that connection */
59     XFER_MECH_DIRECTTCP_LISTEN,
60
61     /* DirectTCP: downstream gets IP:PORT addresses from upstream to which a
62      * TCP connection should be made, then connects to one of the addreses and
63      * receives the data over that connection */
64     XFER_MECH_DIRECTTCP_CONNECT,
65
66     /* (sentinel value) */
67     XFER_MECH_MAX,
68 } xfer_mech;
69
70 /* Description of a pair (input, output) of xfer mechanisms that an
71  * element can support, along with the associated costs.  An array of these
72  * pairs is stored in the class-level variable 'mech_pairs', describing
73  * all of the mechanisms that an element supports.
74  */
75 typedef struct {
76     xfer_mech input_mech;
77     xfer_mech output_mech;
78     guint8 ops_per_byte;        /* number of byte copies or other operations */
79     guint8 nthreads;            /* number of additional threads created */
80 } xfer_element_mech_pair_t;
81
82 /***********************
83  * XferElement
84  *
85  * The virtual base class for all transfer elements
86  */
87
88 GType xfer_element_get_type(void);
89 #define XFER_ELEMENT_TYPE (xfer_element_get_type())
90 #define XFER_ELEMENT(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), xfer_element_get_type(), XferElement)
91 #define XFER_ELEMENT_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), xfer_element_get_type(), XferElement const)
92 #define XFER_ELEMENT_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), xfer_element_get_type(), XferElementClass)
93 #define IS_XFER_ELEMENT(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), xfer_element_get_type ())
94 #define XFER_ELEMENT_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), xfer_element_get_type(), XferElementClass)
95
96 /*
97  * Main object structure
98  */
99
100 typedef struct XferElement {
101     GObject __parent__;
102
103     /* The transfer to which this element is attached */
104     Xfer *xfer; /* set by xfer_new */
105
106     /* assigned input and output mechanisms */
107     xfer_mech input_mech;
108     xfer_mech output_mech;
109
110     /* neighboring xfer elements */
111     struct XferElement *upstream;
112     struct XferElement *downstream;
113
114     /* Information regarding cancellation.  Cancelled and expect_eof are set by
115      * the default cancel() method.  Can_generate_eof should be set during
116      * initialization, and is returned by the default cancel implementation */
117     gboolean cancelled;
118     gboolean expect_eof;
119     gboolean can_generate_eof;
120
121     /* file descriptors for XFER_MECH_READFD and XFER_MECH_WRITEFD.  These
122      * should be set during setup(), and can be accessed by neighboring
123      * elements during start().  These values are shared among multiple
124      * elements, and thus must be accessed with xfer_element_swap_input_fd and
125      * xfer_element_swap_output_fd.  Any file descriptors remaining here at
126      * finalize time will be closed. */
127     gint _input_fd;
128     gint _output_fd;
129
130     /* array of IP:PORT pairs that can be used to connect to this element,
131      * terminated by a 0.0.0.0:0.  The first is set by elements with an input
132      * mech of XFER_MECH_DIRECTTCP_LISTEN and accessed by their upstream
133      * neighbor; the second is set by elements with an output mech of
134      * XFER_MECH_DIRECTTCP_CONNECT and accessed by their downstream neighbor.
135      * */
136
137     DirectTCPAddr *input_listen_addrs;
138     DirectTCPAddr *output_listen_addrs;
139
140     /* cache for repr() */
141     char *repr;
142 } XferElement;
143
144 /*
145  * Class definition
146  */
147
148 typedef struct {
149     GObjectClass __parent__;
150
151     /* Get a string representation of this element.  The returned string will be freed
152      * when the element is finalized, and is static until that time.  This method is
153      * implemented by XferElement, but can be overridden by classes that can provide
154      * additional useful information about themselves.  Overriding methods can use
155      * the 'repr' instance variable as a cache -- it will be freed on finalize().
156      *
157      * @param elt: the XferElement
158      * @return: statically allocated string
159      */
160     char *(*repr)(XferElement *elt);
161
162     /* Set up this element.  This function is called for all elements in a
163      * transfer before start() is called for any elements.  For mechanisms
164      * where this element supplies a file descriptor, it should set its
165      * input_fd and/or output_fd appropriately; neighboring elements will use
166      * that value in start().  Elements which supply IP:PORT pairs should set
167      * their input_addrs, for neighboring elements to use in start().
168      *
169      * elt->input_mech and elt->output_mech are already set when this function
170      * is called, but upstream and downstream are not.
171      *
172      * If the setup operation fails, the method should send an XMSG_ERROR and
173      * call XMSG_CANCEL, and return False.  In this situation, the start method
174      * will not be called.  The Xfer will appear to the user to start and
175      * immediately fail.
176      *
177      * Note that this method may never be called if other elements' setup methods
178      * fail first.
179      *
180      * @param elt: the XferElement
181      * @return: false on failure, true on success
182      */
183     gboolean (*setup)(XferElement *elt);
184
185     /* Start transferring data.  The element downstream of this one will
186      * already be started, while the upstream element will not, so data will
187      * not begin flowing immediately.  It is safe to access attributes of
188      * neighboring elements during this call.
189      *
190      * This method will *not* be called if all elements do not set up
191      * correctly.
192      *
193      * @param elt: the XferElement
194      * @return: TRUE if this element will send XMSG_DONE
195      */
196     gboolean (*start)(XferElement *elt);
197
198     /* Stop transferring data.  The upstream element's cancel method will
199      * already have been called, but due to buffering and synchronization
200      * issues, data may yet arrive.  The element may discard any such data, but
201      * must not fail.  This method is only called for abnormal terminations;
202      * elements should normally stop processing on receiving an EOF indication
203      * from upstream.
204      *
205      * If expect_eof is TRUE, then this element should expect an EOF from its
206      * upstream element, and should drain any remaining data until that EOF
207      * arrives and generate an EOF to the downstream element.  The utility
208      * functions xfer_element_drain_by_reading and
209      * xfer_element_drain_by_pulling may be useful for this purpose. This
210      * draining is important in order to avoid hung threads or unexpected
211      * SIGPIPEs.
212      *
213      * If expect_eof is FALSE, then the upstream elements are unable to
214      * generate an early EOF, so this element should *not* attempt to drain any
215      * remaining data.  As an example, an FdSource is not active and thus
216      * cannot generate an EOF on request.
217      *
218      * If this element can generate an EOF, it should return TRUE, otherwise
219      * FALSE.
220      *
221      * This method may be called before start or setup if an error is
222      * encountered during setup.
223      *
224      * The default implementation sets self->expect_eof and self->cancelled
225      * appropriately and returns self->can_generate_eof.
226      *
227      * This method is always called from the main thread.  It must not block.
228      *
229      * @param elt: the XferElement
230      * @param expect_eof: element should expect an EOF
231      * @returns: true if this element can return EOF
232      */
233     gboolean (*cancel)(XferElement *elt, gboolean expect_eof);
234
235     /* Get a buffer full of data from this element.  This function is called by
236      * the downstream element under XFER_MECH_PULL_CALL.  It can block indefinitely,
237      * and must only return NULL on EOF.  Responsibility to free the buffer transfers
238      * to the caller.
239      *
240      * @param elt: the XferElement
241      * @param size (output): size of resulting buffer
242      * @returns: buffer pointer
243      */
244     gpointer (*pull_buffer)(XferElement *elt, size_t *size);
245
246     /* A buffer full of data is being sent to this element for processing; this
247      * function is called by the upstream element under XFER_MECH_PUSH_CALL.
248      * It can block indefinitely if the data cannot be processed immediately.
249      * An EOF condition is signaled by call with a NULL buffer.  Responsibility to
250      * free the buffer transfers to the callee.
251      *
252      * @param elt: the XferElement
253      * @param buf: buffer
254      * @param size: size of buffer
255      */
256     void (*push_buffer)(XferElement *elt, gpointer buf, size_t size);
257
258     /* Returns the mech_pairs that this element supports.  The default
259      * implementation just returns the class attribute 'mech_pairs', but
260      * subclasses can dynamically select the available mechanisms by overriding
261      * this method.  Note that the method is called before the setup() method.
262      *
263      * @param elt: the XferElement
264      * @returns: array of mech pairs, terminated by <NONE,NONE>
265      */
266     xfer_element_mech_pair_t *(*get_mech_pairs)(XferElement *elt);
267
268     /* class variables */
269
270     /* This is used by the perl bindings -- it is a class variable giving the
271      * appropriate perl class to wrap this XferElement.  It should be set by
272      * each class's class_init.
273      */
274     const char *perl_class;
275
276     /* Statically allocated array of input/output mechanisms supported by this
277      * class (terminated by <XFER_MECH_NONE,XFER_MECH_NONE>).  The default
278      * get_mech_pairs method returns this. */
279     xfer_element_mech_pair_t *mech_pairs;
280 } XferElementClass;
281
282 /*
283  * Method stubs
284  */
285
286 void xfer_element_unref(XferElement *elt);
287 gboolean xfer_element_link_to(XferElement *elt, XferElement *successor);
288 char *xfer_element_repr(XferElement *elt);
289 gboolean xfer_element_setup(XferElement *elt);
290 gboolean xfer_element_start(XferElement *elt);
291 void xfer_element_push_buffer(XferElement *elt, gpointer buf, size_t size);
292 gpointer xfer_element_pull_buffer(XferElement *elt, size_t *size);
293 gboolean xfer_element_cancel(XferElement *elt, gboolean expect_eof);
294 xfer_element_mech_pair_t *xfer_element_get_mech_pairs(XferElement *elt);
295
296 /****
297  * Subclass utilities
298  *
299  * These are utilities for subclasses
300  */
301
302 /* Drain UPSTREAM by pulling buffers until EOF
303  *
304  * @param upstream: the element to drain
305  */
306 void xfer_element_drain_by_pulling(XferElement *upstream);
307
308 /* Drain UPSTREAM by reading until EOF.  This does not close
309  * the file descriptor.
310  *
311  * @param fd: the file descriptor to drain
312  */
313 void xfer_element_drain_by_reading(int fd);
314
315 /* Atomically swap a value into elt->_input_fd and _output_fd, respectively.
316  * Always use these methods to access the field.
317  *
318  * @param elt: xfer element
319  * @param newfd: new value for the fd field
320  * @returns: old value of the fd field
321  */
322 #define xfer_element_swap_input_fd(elt, newfd) \
323     xfer_atomic_swap_fd((elt)->xfer, &(elt)->_input_fd, newfd)
324 #define xfer_element_swap_output_fd(elt, newfd) \
325     xfer_atomic_swap_fd((elt)->xfer, &(elt)->_output_fd, newfd)
326
327 /***********************
328  * XferElement subclasses
329  *
330  * These simple subclasses do not introduce any additional public members or
331  * methods, so they do not have their own header file.  The functions here
332  * provide their only public interface.  The implementation of these elements
333  * can also provide a good prototype for new elements.
334  */
335
336 /* A transfer source that produces LENGTH bytes of random data, for testing
337  * purposes.
338  *
339  * Implemented in source-random.c
340  *
341  * @param length: bytes to produce, or zero for no limit
342  * @param prng_seed: initial value for random number generator
343  * @return: new element
344  */
345 XferElement *xfer_source_random(guint64 length, guint32 prng_seed);
346
347 /* Get the ending random seed for the xfer_source_random.  Call this after a
348  * transfer has finished, and construct a new xfer_source_random with the seed.
349  * The new source will continue the same random sequence at the next byte.  This
350  * is useful for constructing spanned dumps in testing.
351  *
352  * @param src: XferSourceRandom object
353  * @returns: seed
354  */
355 guint32 xfer_source_random_get_seed(XferElement *src);
356
357 /* A transfer source that produces LENGTH bytes containing repeated
358  * copies of the provided pattern, for testing purposes.
359  *
360  * Implemented in source-pattern.c
361  *
362  * @param length: bytes to produce, or zero for no limit
363  * @param pattern: Pointer to memory containing the desired byte pattern.
364  * @param pattern_length: Size of pattern to repeat.
365  * @return: new element
366  */
367 XferElement *xfer_source_pattern(guint64 length, void * pattern,
368                                  size_t pattern_length);
369
370 /* A transfer source that provides bytes read from a file descriptor.
371  * Reading continues until EOF, but the file descriptor is not closed.
372  *
373  * Implemented in source-fd.c
374  *
375  * @param fd: the file descriptor from which to read
376  * @return: new element
377  */
378 XferElement * xfer_source_fd(
379     int fd);
380
381 /* A transfer source that exposes its listening DirectTCPAddrs (via
382  * elt->input_listen_addrs) for external use
383  *
384  * Implemented in source-directtcp-listen.c
385  *
386  * @return: new element
387  */
388 XferElement * xfer_source_directtcp_listen(void);
389
390 /* A transfer source that connects to a DirectTCP address and pulls data
391  * from it into the transfer.
392  *
393  * Implemented in source-directtcp-listen.c
394  *
395  * @param addrs: DirectTCP addresses to connect to
396  * @return: new element
397  */
398 XferElement * xfer_source_directtcp_connect(DirectTCPAddr *addrs);
399
400 /* A transfer filter that executes an external application, feeding it data on
401  * stdin and taking the results on stdout.
402  *
403  * The memory for ARGV becomes the property of the transfer element and will be
404  * g_strfreev'd when the xfer is destroyed.
405  *
406  * Implemented in filter-process.c
407  *
408  * @param argv: NULL-terminated command-line arguments
409  * @param need_root: become root before exec'ing the subprocess
410  * @param log_stderr: if true, send stderr to the debug log; otherwise, send it
411  * to the stderr of the current process
412  * @return: new element
413  */
414 XferElement *xfer_filter_process(gchar **argv,
415     gboolean need_root,
416     gboolean log_stderr);
417
418 /* A transfer filter that just applies a bytewise XOR transformation to the data
419  * that passes through it.
420  *
421  * Implemented in filter-xor.c
422  *
423  * @param xor_key: key for xor operations
424  * @return: new element
425  */
426 XferElement *xfer_filter_xor(
427     unsigned char xor_key);
428
429 /* A transfer destination that consumes all bytes it is given, optionally
430  * validating that they match those produced by source_random
431  *
432  * Implemented in dest-null.c
433  *
434  * @param prng_seed: if nonzero, validate that the datastream matches
435  *      that produced by a random source with this random seed.  If zero,
436  *      no validation is performed.
437  * @return: new element
438  */
439 XferElement *xfer_dest_null(
440     guint32 prng_seed);
441
442 /* A transfer destination that writes bytes to a file descriptor.  The file
443  * descriptor is not closed when the transfer is complete.
444  *
445  * Implemented in dest-fd.c
446  *
447  * @param fd: file descriptor to which to write
448  * @return: new element
449  */
450 XferElement *xfer_dest_fd(
451     int fd);
452
453 /* A transfer destination that writes bytes to an in-memory buffer.
454  *
455  * Implemented in dest-buffer.c
456  *
457  * @param max_size: maximum size for the buffer, or zero for no limit
458  * @return: new element
459  */
460 XferElement *xfer_dest_buffer(
461     gsize max_size);
462
463 /* Get the buffer and size from an XferDestBuffer.  The resulting buffer
464  * will remain allocated until the XDB itself is freed.
465  *
466  * Implemented in dest-buffer.c
467  *
468  * @param elt: the element
469  * @param buf (output): buffer pointer
470  * @param size (output): buffer size
471  */
472 void xfer_dest_buffer_get(
473     XferElement *elt,
474     gpointer *buf,
475     gsize *size);
476
477 /* A transfer dest that connects to a DirectTCPAddr and sends data to
478  * it
479  *
480  * Implemented in dest-directtcp-connect.c
481  *
482  * @param addrs: DirectTCP addresses to connect to
483  * @return: new element
484  */
485 XferElement * xfer_dest_directtcp_connect(DirectTCPAddr *addrs);
486
487 /* A transfer dest that listens for a DirecTCP connection and sends data to it
488  * when connected.  Listening addresses are exposed at
489  * elt->output_listen_addrs.
490  *
491  * Implemented in dest-directtcp-listen.c
492  *
493  * @return: new element
494  */
495 XferElement * xfer_dest_directtcp_listen(void);
496
497 #endif