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-mem-port-source.h"
24 struct _TaperMemPortSourcePrivate {
25 /* Actual size of this buffer is given by max_part_size in TaperSource. */
27 guint64 buffer_offset; /* Bytes read from buffer. */
28 guint64 buffer_len; /* Bytes written to buffer. */
31 /* here are local prototypes */
32 static void taper_mem_port_source_init (TaperMemPortSource * o);
33 static void taper_mem_port_source_class_init (TaperMemPortSourceClass * c);
34 static ssize_t taper_mem_port_source_read (TaperSource * pself, void * buf,
36 static gboolean taper_mem_port_source_seek_to_part_start (TaperSource * pself);
37 static void taper_mem_port_source_start_new_part (TaperSource * pself);
38 static int taper_mem_port_source_predict_parts(TaperSource * pself);
40 /* pointer to the class of our parent */
41 static TaperSourceClass * source_parent_class = NULL;
42 static TaperPortSourceClass *parent_class = NULL;
45 taper_mem_port_source_get_type (void)
47 static GType type = 0;
49 if G_UNLIKELY(type == 0) {
50 static const GTypeInfo info = {
51 sizeof (TaperMemPortSourceClass),
53 (GBaseFinalizeFunc) NULL,
54 (GClassInitFunc) taper_mem_port_source_class_init,
55 (GClassFinalizeFunc) NULL,
56 NULL /* class_data */,
57 sizeof (TaperMemPortSource),
59 (GInstanceInitFunc) taper_mem_port_source_init,
63 type = g_type_register_static (TAPER_TYPE_PORT_SOURCE,
64 "TaperMemPortSource", &info,
72 taper_mem_port_source_finalize(GObject *obj_self) {
73 TaperMemPortSource *self = TAPER_MEM_PORT_SOURCE (obj_self);
74 if(G_OBJECT_CLASS(parent_class)->finalize)
75 (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);
76 amfree (self->_priv->retry_buffer);
81 taper_mem_port_source_init (TaperMemPortSource * o) {
82 o->_priv = malloc(sizeof(TaperMemPortSourcePrivate));
83 o->_priv->retry_buffer = NULL;
84 o->_priv->retry_mode = FALSE;
85 o->_priv->buffer_offset = o->_priv->buffer_len = 0;
89 taper_mem_port_source_class_init (TaperMemPortSourceClass * c) {
90 GObjectClass *g_object_class = (GObjectClass*) c;
91 TaperSourceClass *taper_source_class = (TaperSourceClass *)c;
93 parent_class = g_type_class_ref (TAPER_TYPE_PORT_SOURCE);
94 source_parent_class = (TaperSourceClass*)parent_class;
96 taper_source_class->read = taper_mem_port_source_read;
97 taper_source_class->seek_to_part_start =
98 taper_mem_port_source_seek_to_part_start;
99 taper_source_class->start_new_part = taper_mem_port_source_start_new_part;
100 taper_source_class->predict_parts = taper_mem_port_source_predict_parts;
102 g_object_class->finalize = taper_mem_port_source_finalize;
105 static int taper_mem_port_source_predict_parts(TaperSource * pself) {
106 TaperMemPortSource * self = TAPER_MEM_PORT_SOURCE(pself);
107 g_return_val_if_fail(self != NULL, -1);
112 /* Allocate buffer space, if it hasn't been done yet. */
114 setup_retry_buffer(TaperMemPortSource * self) {
115 TaperSource *pself = TAPER_SOURCE(self);
117 if (selfp->retry_buffer != NULL)
120 alloc_size = pself->max_part_size;
121 if (alloc_size > SIZE_MAX) {
122 g_fprintf(stderr, "Fallback split size of %lld is greater that system maximum of %lld.\n",
123 (long long)alloc_size, (long long)SIZE_MAX);
124 alloc_size = SIZE_MAX;
127 if (alloc_size < DISK_BLOCK_BYTES * 10) {
128 g_fprintf(stderr, "Fallback split size of %ju is smaller than 10 blocks (%u bytes).\n",
129 (uintmax_t)alloc_size, DISK_BLOCK_BYTES * 10);
130 alloc_size = DISK_BLOCK_BYTES * 10;
133 pself->max_part_size = alloc_size;
134 selfp->retry_buffer = malloc(alloc_size);
136 if (selfp->retry_buffer == NULL) {
137 pself->errmsg = g_strdup_printf(_("Can't allocate %ju bytes of memory for split buffer"),
138 (uintmax_t)pself->max_part_size);
146 taper_mem_port_source_read (TaperSource * pself, void * buf, size_t count) {
147 TaperMemPortSource * self = (TaperMemPortSource*)pself;
148 g_return_val_if_fail (self != NULL, -1);
149 g_return_val_if_fail (TAPER_IS_MEM_PORT_SOURCE (self), -1);
150 g_return_val_if_fail (buf != NULL, -1);
151 g_return_val_if_fail (count > 0, -1);
153 if (selfp->retry_mode) {
154 g_assert(selfp->retry_buffer != NULL && selfp->buffer_len > 0);
155 count = MIN(count, selfp->buffer_len - selfp->buffer_offset);
158 /* It was not before. */
159 pself->end_of_part = TRUE;
163 memcpy(buf, selfp->retry_buffer + selfp->buffer_offset, count);
164 selfp->buffer_offset += count;
168 if (selfp->retry_buffer == NULL) {
169 if (!setup_retry_buffer(self))
173 count = MIN(count, pself->max_part_size - selfp->buffer_len);
174 if (count == 0) /* it was nonzero before */ {
175 pself->end_of_part = TRUE;
179 read_result = source_parent_class->read(pself, buf, count);
180 /* TaperPortSource handles EOF and other goodness. */
181 if (read_result <= 0) {
185 /* All's well in the world. */
186 memcpy(selfp->retry_buffer + selfp->buffer_len,
188 selfp->buffer_len += read_result;
193 g_assert_not_reached();
197 taper_mem_port_source_seek_to_part_start (TaperSource * pself) {
198 TaperMemPortSource * self = (TaperMemPortSource*)pself;
199 g_return_val_if_fail (self != NULL, FALSE);
200 g_return_val_if_fail (TAPER_IS_MEM_PORT_SOURCE (self), FALSE);
201 g_return_val_if_fail (selfp->buffer_len > 0, FALSE);
203 selfp->retry_mode = TRUE;
204 selfp->buffer_offset = 0;
206 if (source_parent_class->seek_to_part_start)
207 return source_parent_class->seek_to_part_start(pself);
213 taper_mem_port_source_start_new_part (TaperSource * pself) {
214 TaperMemPortSource * self = (TaperMemPortSource*)pself;
215 g_return_if_fail (self != NULL);
216 g_return_if_fail (TAPER_IS_MEM_PORT_SOURCE (self));
218 selfp->buffer_offset = selfp->buffer_len = 0;
219 selfp->retry_mode = FALSE;
221 if (source_parent_class->start_new_part)
222 source_parent_class->start_new_part(pself);