2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 2008 Zmanda Inc.
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.
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.
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
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.
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.
29 #ifndef XFER_ELEMENT_H
30 #define XFER_ELEMENT_H
33 #include <glib-object.h>
39 /* sources have no input mechanisms and destinations have no output
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
49 /* upstream element will write() to elt->downstream->input_fd. EOF
50 * is indicated by closing the file descriptor. */
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,
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,
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.
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;
74 /***********************
77 * The virtual base class for all transfer elements
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)
89 * Main object structure
92 typedef struct XferElement {
95 /* The transfer to which this element is attached */
96 Xfer *xfer; /* set by xfer_new */
98 /* assigned input and output mechanisms */
100 xfer_mech output_mech;
102 /* neighboring xfer elements */
103 struct XferElement *upstream;
104 struct XferElement *downstream;
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 */
111 gboolean can_generate_eof;
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. */
119 /* cache for repr() */
128 GObjectClass __parent__;
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().
136 * @param elt: the XferElement
137 * @return: statically allocated string
139 char *(*repr)(XferElement *elt);
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().
146 * elt->input_mech and elt->output_mech are already set when this function
147 * is called, but upstream and downstream are not.
149 * @param elt: the XferElement
151 void (*setup)(XferElement *elt);
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
157 * @param elt: the XferElement
158 * @return: TRUE if this element will send XMSG_DONE
160 gboolean (*start)(XferElement *elt);
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
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.
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.
181 * If this element can generate an EOF, it should return TRUE, otherwise
184 * The default implementation sets self->expect_eof and self->cancelled
185 * appropriately and returns self->can_generate_eof.
187 * This method is always called from the main thread. It must not block.
189 * @param elt: the XferElement
191 gboolean (*cancel)(XferElement *elt, gboolean generate_eof);
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
198 * @param elt: the XferElement
199 * @param size (output): size of resulting buffer
201 gpointer (*pull_buffer)(XferElement *elt, size_t *size);
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.
209 * @param elt: the XferElement
211 * @param size: size of buffer
213 void (*push_buffer)(XferElement *elt, gpointer buf, size_t size);
215 /* class variables */
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.
221 const char *perl_class;
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;
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);
244 * These are utilities for subclasses
247 /* Drain UPSTREAM by pulling buffers until EOF
249 * @param upstream: the element to drain
251 void xfer_element_drain_by_pulling(XferElement *upstream);
253 /* Drain UPSTREAM by reading until EOF. This does not close
254 * the file descriptor.
256 * @param fd: the file descriptor to drain
258 void xfer_element_drain_by_reading(int fd);
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.
265 * @param xfer: the transfer object
266 * @returns: the new status (XFER_CANCELLED or XFER_DONE)
268 xfer_status wait_until_xfer_cancelled(Xfer *xfer);
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.
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
280 void xfer_element_handle_error(XferElement *elt, const char *fmt, ...)
283 /***********************
284 * XferElement subclasses
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.
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.
296 * Implemented in source-device.c
298 * @param device: Device object to read from
299 * @return: new element
301 XferElement *xfer_source_device(
304 /* A transfer source that produces LENGTH bytes of random data, for testing
307 * Implemented in source-random.c
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
313 XferElement *xfer_source_random(guint64 length, guint32 prng_seed);
315 /* A transfer source that produces LENGTH bytes containing repeated
316 * copies of the provided pattern, for testing purposes.
318 * Implemented in source-pattern.c
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
325 XferElement *xfer_source_pattern(guint64 length, void * pattern,
326 size_t pattern_length);
328 /* A transfer source that provides bytes read from a file descriptor.
329 * Reading continues until EOF, but the file descriptor is not closed.
331 * Implemented in source-fd.c
333 * @param fd: the file descriptor from which to read
334 * @return: new element
336 XferElement * xfer_source_fd(
339 /* A transfer filter that just applies a bytewise XOR transformation to the data
340 * that passes through it.
342 * Implemented in filter-xor.c
344 * @param xor_key: key for xor operations
345 * @return: new element
347 XferElement *xfer_filter_xor(
348 unsigned char xor_key);
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.
354 * Implemented in dest-device.c
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
367 /* A transfer destination that consumes all bytes it is given, optionally
368 * validating that they match those produced by source_random
370 * Implemented in dest-null.c
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
377 XferElement *xfer_dest_null(
380 /* A transfer destination that writes bytes to a file descriptor. The file
381 * descriptor is not closed when the transfer is complete.
383 * Implemented in dest-fd.c
385 * @param fd: file descriptor to which to write
386 * @return: new element
388 XferElement *xfer_dest_fd(