2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 2006 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);
38 /* pointer to the class of our parent */
39 static GObjectClass *parent_class = NULL;
42 taper_source_get_type (void)
44 static GType type = 0;
46 if G_UNLIKELY(type == 0) {
47 static const GTypeInfo info = {
48 sizeof (TaperSourceClass),
50 (GBaseFinalizeFunc) NULL,
51 (GClassInitFunc) taper_source_class_init,
52 (GClassFinalizeFunc) NULL,
53 NULL /* class_data */,
56 (GInstanceInitFunc) taper_source_init,
60 type = g_type_register_static (G_TYPE_OBJECT, "TaperSource", &info,
61 (GTypeFlags)G_TYPE_FLAG_ABSTRACT);
67 static void taper_source_finalize(GObject * obj_self) {
68 TaperSource * self = TAPER_SOURCE(obj_self);
70 if (G_OBJECT_CLASS(parent_class)->finalize)
71 G_OBJECT_CLASS(parent_class)->finalize(obj_self);
73 if (self->first_header)
74 amfree(self->first_header);
76 if (self->driver_handle)
77 amfree(self->driver_handle);
81 taper_source_init (TaperSource * o) {
82 o->end_of_data = FALSE;
83 o->end_of_part = FALSE;
84 o->max_part_size = G_MAXUINT64;
85 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->predict_parts = NULL;
103 g_object_class->finalize = taper_source_finalize;
106 TaperSource * taper_source_new(char * handle,
107 cmd_t mode, char * holding_disk_file,
109 char * split_disk_buffer,
111 guint64 fallback_splitsize) {
112 TaperSource * source_rval;
113 g_return_val_if_fail(mode == FILE_WRITE || mode == PORT_WRITE, NULL);
114 if (mode == FILE_WRITE) {
115 TaperFileSource * file_rval;
116 g_return_val_if_fail(holding_disk_file != NULL, NULL);
117 g_return_val_if_fail(holding_disk_file[0] != '\0', NULL);
119 /* Return a TaperFileSource. */
121 source_rval = (TaperSource*)
122 g_object_new(TAPER_TYPE_FILE_SOURCE, NULL);
123 file_rval = (TaperFileSource*) source_rval;
125 if (file_rval == NULL)
128 file_rval->holding_disk_file = g_strdup(holding_disk_file);
129 source_rval->max_part_size = splitsize;
131 TaperPortSource * port_rval;
132 g_return_val_if_fail(socket_fd >= 0, NULL);
134 if (split_disk_buffer != NULL) {
135 TaperDiskPortSource * disk_rval;
136 g_return_val_if_fail(split_disk_buffer[0] != '\0', NULL);
137 g_return_val_if_fail(splitsize > 0, NULL);
139 /* Return a TaperDiskPortSource. */
140 source_rval = (TaperSource*)
141 g_object_new(TAPER_TYPE_DISK_PORT_SOURCE, NULL);
142 disk_rval = (TaperDiskPortSource*) source_rval;
143 port_rval = (TaperPortSource*) source_rval;
145 if (disk_rval == NULL)
148 disk_rval->buffer_dir_name = g_strdup(split_disk_buffer);
149 disk_rval->fallback_buffer_size = fallback_splitsize;
150 source_rval->max_part_size = splitsize;
152 if (splitsize != 0) {
153 TaperMemPortSource * mem_rval;
154 /* Return a TaperMemPortSource. */
155 if (fallback_splitsize == 0)
156 fallback_splitsize = splitsize;
157 source_rval = (TaperSource*)
158 g_object_new(TAPER_TYPE_MEM_PORT_SOURCE, NULL);
159 mem_rval = (TaperMemPortSource*) source_rval;
160 port_rval = (TaperPortSource*) source_rval;
162 if (mem_rval == NULL)
165 source_rval->max_part_size = fallback_splitsize;
167 /* Return a TaperPortSource. */
168 source_rval = (TaperSource*)
169 g_object_new(TAPER_TYPE_PORT_SOURCE, NULL);
170 port_rval = (TaperPortSource*) source_rval;
172 if (source_rval == NULL)
177 port_rval->socket_fd = socket_fd;
180 /* If we got here, we have a return value. */
181 source_rval->driver_handle = strdup(handle);
185 /* Default implementations of virtual functions. */
187 default_taper_source_start_new_part(TaperSource * self) {
188 self->end_of_part = FALSE;
192 default_taper_source_seek_to_part_start(TaperSource * self) {
193 self->end_of_data = self->end_of_part = FALSE;
199 default_taper_source_is_partial(TaperSource * self) {
200 return self->first_header->is_partial;
203 static gboolean default_taper_source_get_end_of_data(TaperSource * self) {
204 return self->end_of_data;
206 static gboolean default_taper_source_get_end_of_part(TaperSource * self) {
207 return self->end_of_part;
209 static dumpfile_t* default_taper_source_get_first_header(TaperSource * self) {
210 if (self->first_header == NULL)
212 return dumpfile_copy(self->first_header);
215 /* The rest of these functions are vtable dispatch stubs. */
218 taper_source_read (TaperSource * self, void * buf, size_t count)
220 TaperSourceClass *klass;
221 g_return_val_if_fail (self != NULL, (ssize_t )-1);
222 g_return_val_if_fail (TAPER_IS_SOURCE (self), (ssize_t )-1);
223 g_return_val_if_fail (buf != NULL, (ssize_t )-1);
224 g_return_val_if_fail (count > 0, (ssize_t )-1);
226 if (self->end_of_data || self->end_of_part) {
230 klass = TAPER_SOURCE_GET_CLASS(self);
233 return (*klass->read)(self,buf,count);
235 return (ssize_t )(-1);
239 taper_source_get_end_of_data (TaperSource * self)
241 TaperSourceClass *klass;
242 g_return_val_if_fail (self != NULL, TRUE);
243 g_return_val_if_fail (TAPER_IS_SOURCE (self), TRUE);
245 klass = TAPER_SOURCE_GET_CLASS(self);
247 g_return_val_if_fail(klass->get_end_of_data != NULL, TRUE);
249 return (*klass->get_end_of_data)(self);
253 taper_source_get_end_of_part (TaperSource * self)
255 TaperSourceClass *klass;
256 g_return_val_if_fail (self != NULL, TRUE);
257 g_return_val_if_fail (TAPER_IS_SOURCE (self), TRUE);
259 klass = TAPER_SOURCE_GET_CLASS(self);
261 g_return_val_if_fail(klass->get_end_of_part != NULL, TRUE);
263 return (*klass->get_end_of_part)(self);
267 taper_source_get_first_header (TaperSource * self)
269 TaperSourceClass *klass;
270 g_return_val_if_fail (self != NULL, NULL);
271 g_return_val_if_fail (TAPER_IS_SOURCE (self), NULL);
273 klass = TAPER_SOURCE_GET_CLASS(self);
275 g_return_val_if_fail(klass->get_first_header != NULL, NULL);
277 return (*klass->get_first_header)(self);
280 int taper_source_predict_parts(TaperSource * self) {
281 TaperSourceClass *klass;
282 g_return_val_if_fail (self != NULL, -1);
283 g_return_val_if_fail (TAPER_IS_SOURCE (self), -1);
285 klass = TAPER_SOURCE_GET_CLASS(self);
287 if (klass->predict_parts != NULL) {
288 return (*klass->predict_parts)(self);
295 taper_source_seek_to_part_start (TaperSource * self)
297 TaperSourceClass *klass;
298 g_return_val_if_fail (self != NULL, (gboolean )0);
299 g_return_val_if_fail (TAPER_IS_SOURCE (self), (gboolean )0);
300 klass = TAPER_SOURCE_GET_CLASS(self);
302 if(klass->seek_to_part_start)
303 return (*klass->seek_to_part_start)(self);
305 return (gboolean )(0);
309 taper_source_start_new_part (TaperSource * self)
311 TaperSourceClass *klass;
312 g_return_if_fail (self != NULL);
313 g_return_if_fail (TAPER_IS_SOURCE (self));
314 klass = TAPER_SOURCE_GET_CLASS(self);
316 if(klass->start_new_part)
317 (*klass->start_new_part)(self);
321 taper_source_is_partial (TaperSource * self)
323 TaperSourceClass *klass;
324 g_return_val_if_fail (self != NULL, FALSE);
325 g_return_val_if_fail (TAPER_IS_SOURCE (self), FALSE);
326 g_return_val_if_fail (taper_source_get_end_of_data(self), FALSE);
327 klass = TAPER_SOURCE_GET_CLASS(self);
329 if(klass->is_partial)
330 return (*klass->is_partial)(self);
335 producer_result_t taper_source_producer(gpointer data,
336 queue_buffer_t * buffer,
338 TaperSource * source;
342 g_assert(TAPER_IS_SOURCE(source));
345 if (buffer->data == NULL) {
346 buffer->data = malloc(hint_size);
347 /* This allocation is more likely than most to fail. */
348 g_return_val_if_fail(buffer->data != NULL, PRODUCER_ERROR);
349 buffer->alloc_size = hint_size;
352 result = taper_source_read(source, buffer->data, buffer->alloc_size);
354 buffer->data_size = result;
355 return PRODUCER_MORE;
356 } else if (result == 0) {
357 /* EOF or EOC? We are done here either way. */
358 return PRODUCER_FINISHED;
360 return PRODUCER_ERROR;
363 g_assert_not_reached();