2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 2005-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 #define selfp (self->_priv)
22 #include "taper-source.h"
23 #include "taper-file-source.h"
24 #include "taper-port-source.h"
25 #include "taper-disk-port-source.h"
26 #include "taper-mem-port-source.h"
28 /* here are local prototypes */
29 static void taper_source_init (TaperSource * o);
30 static void taper_source_class_init (TaperSourceClass * c);
31 static void default_taper_source_start_new_part(TaperSource * self);
32 static gboolean default_taper_source_is_partial(TaperSource * self);
33 static gboolean default_taper_source_seek_to_part_start(TaperSource * self);
34 static gboolean default_taper_source_get_end_of_data(TaperSource * self);
35 static gboolean default_taper_source_get_end_of_part(TaperSource * self);
36 static dumpfile_t * default_taper_source_get_first_header(TaperSource * self);
37 static char* default_taper_source_get_errmsg(TaperSource * self);
39 /* pointer to the class of our parent */
40 static GObjectClass *parent_class = NULL;
43 taper_source_get_type (void)
45 static GType type = 0;
47 if G_UNLIKELY(type == 0) {
48 static const GTypeInfo info = {
49 sizeof (TaperSourceClass),
51 (GBaseFinalizeFunc) NULL,
52 (GClassInitFunc) taper_source_class_init,
53 (GClassFinalizeFunc) NULL,
54 NULL /* class_data */,
57 (GInstanceInitFunc) taper_source_init,
61 type = g_type_register_static (G_TYPE_OBJECT, "TaperSource", &info,
62 (GTypeFlags)G_TYPE_FLAG_ABSTRACT);
68 static void taper_source_finalize(GObject * obj_self) {
69 TaperSource * self = TAPER_SOURCE(obj_self);
71 if (G_OBJECT_CLASS(parent_class)->finalize)
72 G_OBJECT_CLASS(parent_class)->finalize(obj_self);
74 dumpfile_free(self->first_header);
75 amfree(self->driver_handle);
80 taper_source_init (TaperSource * o) {
81 o->end_of_data = FALSE;
82 o->end_of_part = FALSE;
83 o->max_part_size = G_MAXUINT64;
84 o->first_header = NULL;
89 taper_source_class_init (TaperSourceClass * c) {
90 GObjectClass *g_object_class = (GObjectClass*) c;
92 parent_class = g_type_class_ref (G_TYPE_OBJECT);
95 c->seek_to_part_start = default_taper_source_seek_to_part_start;
96 c->start_new_part = default_taper_source_start_new_part;
97 c->is_partial = default_taper_source_is_partial;
98 c->get_end_of_data = default_taper_source_get_end_of_data;
99 c->get_end_of_part = default_taper_source_get_end_of_part;
100 c->get_first_header = default_taper_source_get_first_header;
101 c->get_errmsg = default_taper_source_get_errmsg;
102 c->predict_parts = NULL;
104 g_object_class->finalize = taper_source_finalize;
107 TaperSource * taper_source_new(char * handle,
108 cmd_t mode, char * holding_disk_file,
110 char * split_disk_buffer,
112 guint64 fallback_splitsize) {
113 TaperSource * source_rval;
114 g_return_val_if_fail(mode == FILE_WRITE || mode == PORT_WRITE, NULL);
115 if (mode == FILE_WRITE) {
116 TaperFileSource * file_rval;
117 g_return_val_if_fail(holding_disk_file != NULL, NULL);
118 g_return_val_if_fail(holding_disk_file[0] != '\0', NULL);
120 /* Return a TaperFileSource. */
122 source_rval = (TaperSource*)
123 g_object_new(TAPER_TYPE_FILE_SOURCE, NULL);
124 file_rval = (TaperFileSource*) source_rval;
126 if (file_rval == NULL)
129 file_rval->holding_disk_file = g_strdup(holding_disk_file);
130 source_rval->max_part_size = splitsize;
132 TaperPortSource * port_rval;
133 g_return_val_if_fail(socket_fd >= 0, NULL);
135 if (split_disk_buffer != NULL) {
136 TaperDiskPortSource * disk_rval;
137 g_return_val_if_fail(split_disk_buffer[0] != '\0', NULL);
138 g_return_val_if_fail(splitsize > 0, NULL);
140 /* Return a TaperDiskPortSource. */
141 source_rval = (TaperSource*)
142 g_object_new(TAPER_TYPE_DISK_PORT_SOURCE, NULL);
143 disk_rval = (TaperDiskPortSource*) source_rval;
144 port_rval = (TaperPortSource*) source_rval;
146 if (disk_rval == NULL)
149 disk_rval->buffer_dir_name = g_strdup(split_disk_buffer);
150 disk_rval->fallback_buffer_size = fallback_splitsize;
151 source_rval->max_part_size = splitsize;
153 if (splitsize != 0) {
154 TaperMemPortSource * mem_rval;
155 /* Return a TaperMemPortSource. */
156 if (fallback_splitsize == 0)
157 fallback_splitsize = splitsize;
158 source_rval = (TaperSource*)
159 g_object_new(TAPER_TYPE_MEM_PORT_SOURCE, NULL);
160 mem_rval = (TaperMemPortSource*) source_rval;
161 port_rval = (TaperPortSource*) source_rval;
163 if (mem_rval == NULL)
166 source_rval->max_part_size = fallback_splitsize;
168 /* Return a TaperPortSource. */
169 source_rval = (TaperSource*)
170 g_object_new(TAPER_TYPE_PORT_SOURCE, NULL);
171 port_rval = (TaperPortSource*) source_rval;
173 if (source_rval == NULL)
178 port_rval->socket_fd = socket_fd;
181 /* If we got here, we have a return value. */
182 source_rval->driver_handle = strdup(handle);
186 /* Default implementations of virtual functions. */
188 default_taper_source_start_new_part(TaperSource * self) {
189 self->end_of_part = FALSE;
193 default_taper_source_seek_to_part_start(TaperSource * self) {
194 self->end_of_data = self->end_of_part = FALSE;
196 return self->max_part_size > 0;
200 default_taper_source_is_partial(TaperSource * self) {
201 return self->first_header->is_partial;
204 static gboolean default_taper_source_get_end_of_data(TaperSource * self) {
205 return self->end_of_data;
207 static gboolean default_taper_source_get_end_of_part(TaperSource * self) {
208 return self->end_of_part;
210 static dumpfile_t* default_taper_source_get_first_header(TaperSource * self) {
211 if (self->first_header == NULL)
213 return dumpfile_copy(self->first_header);
216 static char* default_taper_source_get_errmsg(TaperSource * self) {
220 /* The rest of these functions are vtable dispatch stubs. */
223 taper_source_read (TaperSource * self, void * buf, size_t count)
225 TaperSourceClass *klass;
226 g_return_val_if_fail (self != NULL, (ssize_t )-1);
227 g_return_val_if_fail (IS_TAPER_SOURCE (self), (ssize_t )-1);
228 g_return_val_if_fail (buf != NULL, (ssize_t )-1);
229 g_return_val_if_fail (count > 0, (ssize_t )-1);
231 if (self->end_of_data || self->end_of_part) {
235 klass = TAPER_SOURCE_GET_CLASS(self);
238 return (*klass->read)(self,buf,count);
240 return (ssize_t )(-1);
244 taper_source_get_end_of_data (TaperSource * self)
246 TaperSourceClass *klass;
247 g_return_val_if_fail (self != NULL, TRUE);
248 g_return_val_if_fail (IS_TAPER_SOURCE (self), TRUE);
250 klass = TAPER_SOURCE_GET_CLASS(self);
252 g_return_val_if_fail(klass->get_end_of_data != NULL, TRUE);
254 return (*klass->get_end_of_data)(self);
258 taper_source_get_end_of_part (TaperSource * self)
260 TaperSourceClass *klass;
261 g_return_val_if_fail (self != NULL, TRUE);
262 g_return_val_if_fail (IS_TAPER_SOURCE (self), TRUE);
264 klass = TAPER_SOURCE_GET_CLASS(self);
266 g_return_val_if_fail(klass->get_end_of_part != NULL, TRUE);
268 return (*klass->get_end_of_part)(self);
272 taper_source_get_first_header (TaperSource * self)
274 TaperSourceClass *klass;
275 g_return_val_if_fail (self != NULL, NULL);
276 g_return_val_if_fail (IS_TAPER_SOURCE (self), NULL);
278 klass = TAPER_SOURCE_GET_CLASS(self);
280 g_return_val_if_fail(klass->get_first_header != NULL, NULL);
282 return (*klass->get_first_header)(self);
286 taper_source_get_errmsg (TaperSource * self)
288 TaperSourceClass *klass;
289 g_return_val_if_fail (self != NULL, NULL);
290 g_return_val_if_fail (IS_TAPER_SOURCE (self), NULL);
292 klass = TAPER_SOURCE_GET_CLASS(self);
294 g_return_val_if_fail(klass->get_errmsg != NULL, NULL);
296 return (*klass->get_errmsg)(self);
299 int taper_source_predict_parts(TaperSource * self) {
300 TaperSourceClass *klass;
301 g_return_val_if_fail (self != NULL, -1);
302 g_return_val_if_fail (IS_TAPER_SOURCE (self), -1);
304 klass = TAPER_SOURCE_GET_CLASS(self);
306 if (klass->predict_parts != NULL) {
307 return (*klass->predict_parts)(self);
314 taper_source_seek_to_part_start (TaperSource * self)
316 TaperSourceClass *klass;
317 g_return_val_if_fail (self != NULL, (gboolean )0);
318 g_return_val_if_fail (IS_TAPER_SOURCE (self), (gboolean )0);
319 klass = TAPER_SOURCE_GET_CLASS(self);
321 if(klass->seek_to_part_start)
322 return (*klass->seek_to_part_start)(self);
324 return (gboolean )(0);
328 taper_source_start_new_part (TaperSource * self)
330 TaperSourceClass *klass;
331 g_return_if_fail (self != NULL);
332 g_return_if_fail (IS_TAPER_SOURCE (self));
333 klass = TAPER_SOURCE_GET_CLASS(self);
335 if(klass->start_new_part)
336 (*klass->start_new_part)(self);
340 taper_source_is_partial (TaperSource * self)
342 TaperSourceClass *klass;
343 g_return_val_if_fail (self != NULL, FALSE);
344 g_return_val_if_fail (IS_TAPER_SOURCE (self), FALSE);
345 g_return_val_if_fail (taper_source_get_end_of_data(self), FALSE);
346 klass = TAPER_SOURCE_GET_CLASS(self);
348 if(klass->is_partial)
349 return (*klass->is_partial)(self);
354 producer_result_t taper_source_producer(gpointer data,
355 queue_buffer_t * buffer,
357 TaperSource * source;
361 g_assert(IS_TAPER_SOURCE(source));
364 if (buffer->data == NULL) {
365 buffer->data = malloc(hint_size);
366 /* This allocation is more likely than most to fail. */
367 g_return_val_if_fail(buffer->data != NULL, PRODUCER_ERROR);
368 buffer->alloc_size = hint_size;
371 result = taper_source_read(source, buffer->data, buffer->alloc_size);
373 buffer->data_size = result;
374 return PRODUCER_MORE;
375 } else if (result == 0) {
376 /* EOF or EOC? We are done here either way. */
377 return PRODUCER_FINISHED;
379 return PRODUCER_ERROR;
382 g_assert_not_reached();