43a9323f8edb1a6c7fb4d8d431e6c024eba57f1b
[debian/amanda] / xfer-src / xfer-element.h
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 2008 Zmanda Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 /* Base classes and interfaces for transfer elements.  There are two interfaces
21  * defined here: IXferProducer and IXferConsumer.  The former is for elements
22  * which produce data, and the latter is for those which consume it.  There is
23  * a top-level XferElement base class, which all implementations subclass.
24  *
25  * Unless you're well-acquainted with GType and GObject, this file will be a
26  * difficult read.  It is really only of use to those implementing new subclasses.
27  */
28
29 #ifndef XFER_ELEMENT_H
30 #define XFER_ELEMENT_H
31
32 #include <glib.h>
33 #include <glib-object.h>
34 #include "xfer.h"
35 #include "device.h"
36 #include "queueing.h"
37
38 typedef enum {
39     /* sources have no input mechanisms and destinations have no output
40      * mechansisms. */
41     XFER_MECH_NONE,
42
43     /* downstream element will read() from elt->upstream->output_fd; EOF
44      * is indicated by the usual OS mechanism resulting in a zero-length
45      * read, in response to which the downstream element must close
46      * the fd. */
47     XFER_MECH_READFD,
48
49     /* upstream element will write() to elt->downstream->input_fd.  EOF
50      * is indicated by closing the file descriptor. */
51     XFER_MECH_WRITEFD,
52
53     /* downstream element will call elt->upstream->pull_buffer() to
54      * pull a buffer.  EOF is indicated by returning a NULL buffer */
55     XFER_MECH_PULL_BUFFER,
56
57     /* upstream element will call elt->downstream->push_buffer(buf) to push
58      * a buffer.  EOF is indicated by passing a NULL buffer. */
59     XFER_MECH_PUSH_BUFFER,
60 } xfer_mech;
61
62 /* Description of a pair (input, output) of xfer mechanisms that an
63  * element can support, along with the associated costs.  An array of these
64  * pairs is stored in the class-level variable 'mech_pairs', describing
65  * all of the mechanisms that an element supports.
66  */
67 typedef struct {
68     xfer_mech input_mech;
69     xfer_mech output_mech;
70     guint8 ops_per_byte;        /* number of byte copies or other operations */
71     guint8 nthreads;            /* number of additional threads created */
72 } xfer_element_mech_pair_t;
73
74 /***********************
75  * XferElement
76  *
77  * The virtual base class for all transfer elements
78  */
79
80 GType xfer_element_get_type(void);
81 #define XFER_ELEMENT_TYPE (xfer_element_get_type())
82 #define XFER_ELEMENT(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), xfer_element_get_type(), XferElement)
83 #define XFER_ELEMENT_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), xfer_element_get_type(), XferElement const)
84 #define XFER_ELEMENT_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), xfer_element_get_type(), XferElementClass)
85 #define IS_XFER_ELEMENT(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), xfer_element_get_type ())
86 #define XFER_ELEMENT_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), xfer_element_get_type(), XferElementClass)
87
88 /*
89  * Main object structure
90  */
91
92 typedef struct XferElement {
93     GObject __parent__;
94
95     /* The transfer to which this element is attached */
96     Xfer *xfer; /* set by xfer_new */
97
98     /* assigned input and output mechanisms */
99     xfer_mech input_mech;
100     xfer_mech output_mech;
101
102     /* neighboring xfer elements */
103     struct XferElement *upstream;
104     struct XferElement *downstream;
105
106     /* Information regarding cancellation.  Cancelled and expect_eof are set by
107      * the default cancel() method.  Can_generate_eof should be set during
108      * initialization, and is returned by the default cancel implementation */
109     gboolean cancelled;
110     gboolean expect_eof;
111     gboolean can_generate_eof;
112
113     /* file descriptors for XFER_MECH_READFD and XFER_MECH_WRITEFD.  These should be set
114      * during setup(), and can be accessed by neighboring elements during start(). It is
115      * up to subclasses to handle closing these file descriptors, if required. */
116     gint input_fd;
117     gint output_fd;
118
119     /* cache for repr() */
120     char *repr;
121 } XferElement;
122
123 /*
124  * Class definition
125  */
126
127 typedef struct {
128     GObjectClass __parent__;
129
130     /* Get a string representation of this element.  The returned string will be freed
131      * when the element is finalized, and is static until that time.  This method is
132      * implemented by XferElement, but can be overridden by classes that can provide
133      * additional useful information about themselves.  Overriding methods can use
134      * the 'repr' instance variable as a cache -- it will be freed on finalize().
135      *
136      * @param elt: the XferElement
137      * @return: statically allocated string
138      */
139     char *(*repr)(XferElement *elt);
140
141     /* Set up this element.  This function is called for all elements in a transfer
142      * before start() is called for any elements.  For mechanisms where this element
143      * supplies a file descriptor, it should set its input_fd and/or output_fd
144      * appropriately; neighboring elements will use that value in start().
145      *
146      * elt->input_mech and elt->output_mech are already set when this function
147      * is called, but upstream and downstream are not.
148      *
149      * @param elt: the XferElement
150      */
151     void (*setup)(XferElement *elt);
152
153     /* Start transferring data.  The element downstream of this one will already be
154      * started, while the upstream element will not, so data will not begin flowing
155      * immediately.
156      *
157      * @param elt: the XferElement
158      * @return: TRUE if this element will send XMSG_DONE
159      */
160     gboolean (*start)(XferElement *elt);
161
162     /* Stop transferring data.  The upstream element's cancel method will
163      * already have been called, but due to buffering and synchronization
164      * issues, data may yet arrive.  The element may discard any such data, but
165      * must not fail.  This method is only called for abnormal terminations;
166      * elements should normally stop processing on receiving an EOF indication
167      * from upstream.
168      *
169      * If expect_eof is TRUE, then this element should expect an EOF from its
170      * upstream element, and should drain any remaining data until that EOF
171      * arrives and generate an EOF to the downstream element.  The utility
172      * functions xfer_element_drain_by_reading and xfer_element_drain_by_pulling may be useful for this
173      * purpose. This draining is important in order to avoid hung threads or
174      * unexpected SIGPIPEs.
175      *
176      * If expect_eof is FALSE, then the upstream elements are unable to
177      * generate an early EOF, so this element should *not* attempt to drain any
178      * remaining data.  As an example, an FdSource is not active and thus
179      * cannot generate an EOF on request.
180      *
181      * If this element can generate an EOF, it should return TRUE, otherwise
182      * FALSE.
183      *
184      * The default implementation sets self->expect_eof and self->cancelled
185      * appropriately and returns self->can_generate_eof.
186      *
187      * This method is always called from the main thread.  It must not block.
188      *
189      * @param elt: the XferElement
190      */
191     gboolean (*cancel)(XferElement *elt, gboolean generate_eof);
192
193     /* Get a buffer full of data from this element.  This function is called by
194      * the downstream element under XFER_MECH_PULL_CALL.  It can block indefinitely,
195      * and must only return NULL on EOF.  Responsibility to free the buffer transfers
196      * to the caller.
197      *
198      * @param elt: the XferElement
199      * @param size (output): size of resulting buffer
200      */
201     gpointer (*pull_buffer)(XferElement *elt, size_t *size);
202
203     /* A buffer full of data is being sent to this element for processing; this
204      * function is called by the upstream element under XFER_MECH_PUSH_CALL.
205      * It can block indefinitely if the data cannot be processed immediately.
206      * An EOF condition is signaled by call with a NULL buffer.  Responsibility to
207      * free the buffer transfers to the callee.
208      *
209      * @param elt: the XferElement
210      * @param buf: buffer
211      * @param size: size of buffer
212      */
213     void (*push_buffer)(XferElement *elt, gpointer buf, size_t size);
214
215     /* class variables */
216
217     /* This is used by the perl bindings -- it is a class variable giving the
218      * appropriate perl class to wrap this XferElement.  It should be set by
219      * each class's class_init.
220      */
221     const char *perl_class;
222
223     /* Statically allocated array of input/output mechanisms supported by this
224      * class (terminated by <XFER_MECH_NONE,XFER_MECH_NONE>) */
225     xfer_element_mech_pair_t *mech_pairs;
226 } XferElementClass;
227
228 /*
229  * Method stubs
230  */
231
232 void xfer_element_unref(XferElement *elt);
233 gboolean xfer_element_link_to(XferElement *elt, XferElement *successor);
234 char *xfer_element_repr(XferElement *elt);
235 void xfer_element_setup(XferElement *elt);
236 gboolean xfer_element_start(XferElement *elt);
237 void xfer_element_push_buffer(XferElement *elt, gpointer buf, size_t size);
238 gpointer xfer_element_pull_buffer(XferElement *elt, size_t *size);
239 gboolean xfer_element_cancel(XferElement *elt, gboolean expect_eof);
240
241 /****
242  * Subclass utilities
243  *
244  * These are utilities for subclasses
245  */
246
247 /* Drain UPSTREAM by pulling buffers until EOF
248  *
249  * @param upstream: the element to drain
250  */
251 void xfer_element_drain_by_pulling(XferElement *upstream);
252
253 /* Drain UPSTREAM by reading until EOF.  This does not close
254  * the file descriptor.
255  *
256  * @param fd: the file descriptor to drain
257  */
258 void xfer_element_drain_by_reading(int fd);
259
260 /* Wait for the xfer's state to become CANCELLED or DONE; this is useful to
261  * wait until a cancelletion is in progress before returning an EOF or
262  * otherwise handling a failure.  If you call this in the main thread, you'll
263  * be waiting for a while.
264  *
265  * @param xfer: the transfer object
266  * @returns: the new status (XFER_CANCELLED or XFER_DONE)
267  */
268 xfer_status wait_until_xfer_cancelled(Xfer *xfer);
269
270 /* Send an XMSG_ERROR constructed with the given format and arguments, then
271  * cancel the transfer, then wait until the transfer is completely cancelled.
272  * This is the most common error-handling process for transfer elements.  All
273  * that remains to be done on return is to branch to the appropriate point in
274  * the cancellation-handling portion of the transfer.
275  *
276  * @param elt: the transfer element producing the error
277  * @param fmt: the format for the error message
278  * @param ...: arguments corresponding to the format
279  */
280 void xfer_element_handle_error(XferElement *elt, const char *fmt, ...)
281         G_GNUC_PRINTF(2,3);
282
283 /***********************
284  * XferElement subclasses
285  *
286  * These simple subclasses do not introduce any additional public members or
287  * methods, so they do not have their own header file.  The functions here
288  * provide their only public interface.  The implementation of these elements
289  * can also provide a good prototype for new elements.
290  */
291
292 /* A transfer source that reads from a Device. The device must be positioned
293  * at the start of a file before the transfer is started.  The transfer will
294  * continue until the end of the file.
295  *
296  * Implemented in source-device.c
297  *
298  * @param device: Device object to read from
299  * @return: new element
300  */
301 XferElement *xfer_source_device(
302     Device *device);
303
304 /* A transfer source that produces LENGTH bytes of random data, for testing
305  * purposes.
306  *
307  * Implemented in source-random.c
308  *
309  * @param length: bytes to produce, or zero for no limit
310  * @param prng_seed: initial value for random number generator
311  * @return: new element
312  */
313 XferElement *xfer_source_random(guint64 length, guint32 prng_seed);
314
315 /* A transfer source that produces LENGTH bytes containing repeated
316  * copies of the provided pattern, for testing purposes.
317  *
318  * Implemented in source-pattern.c
319  *
320  * @param length: bytes to produce, or zero for no limit
321  * @param pattern: Pointer to memory containing the desired byte pattern.
322  * @param pattern_length: Size of pattern to repeat.
323  * @return: new element
324  */
325 XferElement *xfer_source_pattern(guint64 length, void * pattern,
326                                  size_t pattern_length);
327
328 /* A transfer source that provides bytes read from a file descriptor.
329  * Reading continues until EOF, but the file descriptor is not closed.
330  *
331  * Implemented in source-fd.c
332  *
333  * @param fd: the file descriptor from which to read
334  * @return: new element
335  */
336 XferElement * xfer_source_fd(
337     int fd);
338
339 /* A transfer filter that just applies a bytewise XOR transformation to the data
340  * that passes through it.
341  *
342  * Implemented in filter-xor.c
343  *
344  * @param xor_key: key for xor operations
345  * @return: new element
346  */
347 XferElement *xfer_filter_xor(
348     unsigned char xor_key);
349
350 /* A transfer destination that writes bytes to a Device.  The device should have a
351  * file started, ready for a device_write_block call.  On completion of the transfer,
352  * the file will be finished.
353  *
354  * Implemented in dest-device.c
355  *
356  * @param device: the Device to write to, with a file started
357  * @param max_memory: total amount of memory to use for buffers, or zero
358  *                    for a reasonable default.
359  * @return: new element
360  */
361 XferElement *
362 xfer_dest_device(
363     Device *device,
364     size_t max_memory);
365
366
367 /* A transfer destination that consumes all bytes it is given, optionally
368  * validating that they match those produced by source_random
369  *
370  * Implemented in dest-null.c
371  *
372  * @param prng_seed: if nonzero, validate that the datastream matches
373  *      that produced by a random source with this random seed.  If zero,
374  *      no validation is performed.
375  * @return: new element
376  */
377 XferElement *xfer_dest_null(
378     guint32 prng_seed);
379
380 /* A transfer destination that writes bytes to a file descriptor.  The file
381  * descriptor is not closed when the transfer is complete.
382  *
383  * Implemented in dest-fd.c
384  *
385  * @param fd: file descriptor to which to write
386  * @return: new element
387  */
388 XferElement *xfer_dest_fd(
389     int fd);
390
391 #endif