704177fe3b43e01eba31ce2680a67a40de864ec2
[debian/amanda] / server-src / taper-source.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 2005-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 #define selfp (self->_priv)
21
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"
27
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);
38
39 /* pointer to the class of our parent */
40 static GObjectClass *parent_class = NULL;
41
42 GType
43 taper_source_get_type (void)
44 {
45     static GType type = 0;
46     
47     if G_UNLIKELY(type == 0) {
48         static const GTypeInfo info = {
49             sizeof (TaperSourceClass),
50             (GBaseInitFunc) NULL,
51             (GBaseFinalizeFunc) NULL,
52             (GClassInitFunc) taper_source_class_init,
53             (GClassFinalizeFunc) NULL,
54             NULL /* class_data */,
55             sizeof (TaperSource),
56             0 /* n_preallocs */,
57             (GInstanceInitFunc) taper_source_init,
58             NULL
59         };
60         
61         type = g_type_register_static (G_TYPE_OBJECT, "TaperSource", &info,
62                                        (GTypeFlags)G_TYPE_FLAG_ABSTRACT);
63     }
64     
65     return type;
66 }
67
68 static void taper_source_finalize(GObject * obj_self) {
69     TaperSource * self = TAPER_SOURCE(obj_self);
70     
71     if (G_OBJECT_CLASS(parent_class)->finalize)
72         G_OBJECT_CLASS(parent_class)->finalize(obj_self);
73
74     dumpfile_free(self->first_header);
75     amfree(self->driver_handle);
76     amfree(self->errmsg);
77 }
78
79 static void 
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;
85     o->errmsg = NULL;
86 }
87
88 static void 
89 taper_source_class_init (TaperSourceClass * c) {
90     GObjectClass *g_object_class = (GObjectClass*) c;
91
92     parent_class = g_type_class_ref (G_TYPE_OBJECT);
93
94     c->read = NULL;
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;
103
104     g_object_class->finalize = taper_source_finalize;
105 }
106
107 TaperSource * taper_source_new(char * handle,
108                                cmd_t mode, char * holding_disk_file,
109                                int socket_fd,
110                                char * split_disk_buffer,
111                                guint64 splitsize,
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);
119
120         /* Return a TaperFileSource. */
121         
122         source_rval = (TaperSource*)
123             g_object_new(TAPER_TYPE_FILE_SOURCE, NULL);
124         file_rval = (TaperFileSource*) source_rval;
125
126         if (file_rval == NULL)
127             return NULL;
128
129         file_rval->holding_disk_file = g_strdup(holding_disk_file);
130         source_rval->max_part_size = splitsize;
131     } else {
132         TaperPortSource * port_rval;
133         g_return_val_if_fail(socket_fd >= 0, NULL);
134
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);
139             
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;
145
146             if (disk_rval == NULL)
147                 return NULL;
148
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;
152         } else {
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;
162
163                 if (mem_rval == NULL)
164                     return NULL;
165                 
166                 source_rval->max_part_size = fallback_splitsize;
167             } else {
168                 /* Return a TaperPortSource. */
169                 source_rval = (TaperSource*)
170                     g_object_new(TAPER_TYPE_PORT_SOURCE, NULL);
171                 port_rval = (TaperPortSource*) source_rval;
172
173                 if (source_rval == NULL)
174                     return NULL;
175             } 
176         }
177         
178         port_rval->socket_fd = socket_fd;
179     }
180
181     /* If we got here, we have a return value. */
182     source_rval->driver_handle = strdup(handle);
183     return source_rval;
184 }
185
186 /* Default implementations of virtual functions. */
187 static void
188 default_taper_source_start_new_part(TaperSource * self) {
189     self->end_of_part = FALSE;
190 }
191
192 static gboolean
193 default_taper_source_seek_to_part_start(TaperSource * self) {
194     self->end_of_data = self->end_of_part = FALSE;
195
196     return self->max_part_size > 0;
197 }
198
199 static gboolean
200 default_taper_source_is_partial(TaperSource * self) {
201     return self->first_header->is_partial;
202 }
203
204 static gboolean default_taper_source_get_end_of_data(TaperSource * self) {
205     return self->end_of_data;
206 }
207 static gboolean default_taper_source_get_end_of_part(TaperSource * self) {
208     return self->end_of_part;
209 }
210 static dumpfile_t* default_taper_source_get_first_header(TaperSource * self) {
211     if (self->first_header == NULL)
212         return NULL;
213     return dumpfile_copy(self->first_header);
214 }
215
216 static char* default_taper_source_get_errmsg(TaperSource * self) {
217     return self->errmsg;
218 }
219
220 /* The rest of these functions are vtable dispatch stubs. */
221
222 ssize_t 
223 taper_source_read (TaperSource * self, void * buf, size_t count)
224 {
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);
230
231     if (self->end_of_data || self->end_of_part) {
232         return 0;
233     }
234
235     klass = TAPER_SOURCE_GET_CLASS(self);
236     
237     if(klass->read)
238         return (*klass->read)(self,buf,count);
239     else
240         return (ssize_t )(-1);
241 }
242
243 gboolean 
244 taper_source_get_end_of_data (TaperSource * self)
245 {
246     TaperSourceClass *klass;
247     g_return_val_if_fail (self != NULL, TRUE);
248     g_return_val_if_fail (IS_TAPER_SOURCE (self), TRUE);
249
250     klass = TAPER_SOURCE_GET_CLASS(self);
251     
252     g_return_val_if_fail(klass->get_end_of_data != NULL, TRUE);
253
254     return (*klass->get_end_of_data)(self);
255 }
256
257 gboolean 
258 taper_source_get_end_of_part (TaperSource * self)
259 {
260     TaperSourceClass *klass;
261     g_return_val_if_fail (self != NULL, TRUE);
262     g_return_val_if_fail (IS_TAPER_SOURCE (self), TRUE);
263
264     klass = TAPER_SOURCE_GET_CLASS(self);
265     
266     g_return_val_if_fail(klass->get_end_of_part != NULL, TRUE);
267
268     return (*klass->get_end_of_part)(self);
269 }
270
271 dumpfile_t *
272 taper_source_get_first_header (TaperSource * self)
273 {
274     TaperSourceClass *klass;
275     g_return_val_if_fail (self != NULL, NULL);
276     g_return_val_if_fail (IS_TAPER_SOURCE (self), NULL);
277
278     klass = TAPER_SOURCE_GET_CLASS(self);
279     
280     g_return_val_if_fail(klass->get_first_header != NULL, NULL);
281
282     return (*klass->get_first_header)(self);
283 }
284
285 char *
286 taper_source_get_errmsg (TaperSource * self)
287 {
288     TaperSourceClass *klass;
289     g_return_val_if_fail (self != NULL, NULL);
290     g_return_val_if_fail (IS_TAPER_SOURCE (self), NULL);
291
292     klass = TAPER_SOURCE_GET_CLASS(self);
293     
294     g_return_val_if_fail(klass->get_errmsg != NULL, NULL);
295
296     return (*klass->get_errmsg)(self);
297 }
298
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);
303
304     klass = TAPER_SOURCE_GET_CLASS(self);
305     
306     if (klass->predict_parts != NULL) {
307         return (*klass->predict_parts)(self);
308     } else {
309         return -1;
310     }
311 }
312
313 gboolean 
314 taper_source_seek_to_part_start (TaperSource * self)
315 {
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);
320     
321     if(klass->seek_to_part_start)
322         return (*klass->seek_to_part_start)(self);
323     else
324         return (gboolean )(0);
325 }
326
327 void 
328 taper_source_start_new_part (TaperSource * self)
329 {
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);
334     
335     if(klass->start_new_part)
336         (*klass->start_new_part)(self);
337 }
338
339 gboolean
340 taper_source_is_partial (TaperSource * self)
341 {
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);
347     
348     if(klass->is_partial)
349         return (*klass->is_partial)(self);
350     else
351         return FALSE;
352 }
353
354 producer_result_t taper_source_producer(gpointer data,
355                                         queue_buffer_t * buffer,
356                                         size_t hint_size) {
357     TaperSource * source;
358     ssize_t result;
359
360     source = data;
361     g_assert(IS_TAPER_SOURCE(source));
362
363     buffer->offset = 0;
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;
369     }
370
371     result = taper_source_read(source, buffer->data, buffer->alloc_size);
372     if (result > 0) {
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;
378     } else {
379         return PRODUCER_ERROR;
380     }
381
382     g_assert_not_reached();
383 }
384