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-mem-port-source.h"
26 struct _TaperMemPortSourcePrivate {
27 /* Actual size of this buffer is given by max_part_size in TaperSource. */
29 guint64 buffer_offset; /* Bytes read from buffer. */
30 guint64 buffer_len; /* Bytes written to buffer. */
33 /* here are local prototypes */
34 static void taper_mem_port_source_init (TaperMemPortSource * o);
35 static void taper_mem_port_source_class_init (TaperMemPortSourceClass * c);
36 static ssize_t taper_mem_port_source_read (TaperSource * pself, void * buf,
38 static gboolean taper_mem_port_source_seek_to_part_start (TaperSource * pself);
39 static void taper_mem_port_source_start_new_part (TaperSource * pself);
40 static int taper_mem_port_source_predict_parts(TaperSource * pself);
42 /* pointer to the class of our parent */
43 static TaperSourceClass * source_parent_class = NULL;
44 static TaperPortSourceClass *parent_class = NULL;
47 taper_mem_port_source_get_type (void)
49 static GType type = 0;
51 if G_UNLIKELY(type == 0) {
52 static const GTypeInfo info = {
53 sizeof (TaperMemPortSourceClass),
55 (GBaseFinalizeFunc) NULL,
56 (GClassInitFunc) taper_mem_port_source_class_init,
57 (GClassFinalizeFunc) NULL,
58 NULL /* class_data */,
59 sizeof (TaperMemPortSource),
61 (GInstanceInitFunc) taper_mem_port_source_init,
65 type = g_type_register_static (TAPER_TYPE_PORT_SOURCE,
66 "TaperMemPortSource", &info,
74 taper_mem_port_source_finalize(GObject *obj_self) {
75 TaperMemPortSource *self = TAPER_MEM_PORT_SOURCE (obj_self);
76 if(G_OBJECT_CLASS(parent_class)->finalize)
77 (* G_OBJECT_CLASS(parent_class)->finalize)(obj_self);
78 amfree (self->_priv->retry_buffer);
83 taper_mem_port_source_init (TaperMemPortSource * o) {
84 o->_priv = malloc(sizeof(TaperMemPortSourcePrivate));
85 o->_priv->retry_buffer = NULL;
86 o->_priv->retry_mode = FALSE;
87 o->_priv->buffer_offset = o->_priv->buffer_len = 0;
91 taper_mem_port_source_class_init (TaperMemPortSourceClass * c) {
92 GObjectClass *g_object_class = (GObjectClass*) c;
93 TaperSourceClass *taper_source_class = (TaperSourceClass *)c;
95 parent_class = g_type_class_ref (TAPER_TYPE_PORT_SOURCE);
96 source_parent_class = (TaperSourceClass*)parent_class;
98 taper_source_class->read = taper_mem_port_source_read;
99 taper_source_class->seek_to_part_start =
100 taper_mem_port_source_seek_to_part_start;
101 taper_source_class->start_new_part = taper_mem_port_source_start_new_part;
102 taper_source_class->predict_parts = taper_mem_port_source_predict_parts;
104 g_object_class->finalize = taper_mem_port_source_finalize;
107 static int taper_mem_port_source_predict_parts(TaperSource * pself) {
108 TaperMemPortSource * self = TAPER_MEM_PORT_SOURCE(pself);
109 g_return_val_if_fail(self != NULL, -1);
114 /* Allocate buffer space, if it hasn't been done yet. */
115 static void setup_retry_buffer(TaperMemPortSource * self) {
118 if (selfp->retry_buffer != NULL)
121 alloc_size = TAPER_SOURCE(self)->max_part_size;
122 if (alloc_size > SIZE_MAX) {
123 g_fprintf(stderr, "Fallback split size of %lld is greater that system maximum of %lld.\n",
124 (long long)alloc_size, (long long)SIZE_MAX);
125 alloc_size = SIZE_MAX;
128 max_usage = physmem_available() * .95;
129 if (alloc_size > max_usage) {
130 g_fprintf(stderr, "Fallback split size of %lld is greater than 95%% of available memory (%lld bytes).\n", (long long)alloc_size, (long long)max_usage);
131 alloc_size = max_usage;
134 if (alloc_size < DISK_BLOCK_BYTES * 10) {
135 g_fprintf(stderr, "Fallback split size of %ju is smaller than 10 blocks (%u bytes).\n",
136 (uintmax_t)alloc_size, DISK_BLOCK_BYTES * 10);
137 alloc_size = DISK_BLOCK_BYTES * 10;
140 TAPER_SOURCE(self)->max_part_size = alloc_size;
141 selfp->retry_buffer = malloc(alloc_size);
145 taper_mem_port_source_read (TaperSource * pself, void * buf, size_t count) {
146 TaperMemPortSource * self = (TaperMemPortSource*)pself;
147 g_return_val_if_fail (self != NULL, -1);
148 g_return_val_if_fail (TAPER_IS_MEM_PORT_SOURCE (self), -1);
149 g_return_val_if_fail (buf != NULL, -1);
150 g_return_val_if_fail (count > 0, -1);
152 if (selfp->retry_mode) {
153 g_assert(selfp->retry_buffer != NULL && selfp->buffer_len > 0);
154 count = MIN(count, selfp->buffer_len - selfp->buffer_offset);
157 /* It was not before. */
158 pself->end_of_part = TRUE;
162 memcpy(buf, selfp->retry_buffer + selfp->buffer_offset, count);
163 selfp->buffer_offset += count;
167 if (selfp->retry_buffer == NULL) {
168 setup_retry_buffer(self);
171 count = MIN(count, pself->max_part_size - selfp->buffer_len);
172 if (count == 0) /* it was nonzero before */ {
173 pself->end_of_part = TRUE;
177 read_result = source_parent_class->read(pself, buf, count);
178 /* TaperPortSource handles EOF and other goodness. */
179 if (read_result <= 0) {
183 /* All's well in the world. */
184 memcpy(selfp->retry_buffer + selfp->buffer_len,
186 selfp->buffer_len += read_result;
191 g_assert_not_reached();
195 taper_mem_port_source_seek_to_part_start (TaperSource * pself) {
196 TaperMemPortSource * self = (TaperMemPortSource*)pself;
197 g_return_val_if_fail (self != NULL, FALSE);
198 g_return_val_if_fail (TAPER_IS_MEM_PORT_SOURCE (self), FALSE);
199 g_return_val_if_fail (selfp->buffer_len > 0, FALSE);
201 selfp->retry_mode = TRUE;
202 selfp->buffer_offset = 0;
204 if (source_parent_class->seek_to_part_start)
205 return source_parent_class->seek_to_part_start(pself);
211 taper_mem_port_source_start_new_part (TaperSource * pself) {
212 TaperMemPortSource * self = (TaperMemPortSource*)pself;
213 g_return_if_fail (self != NULL);
214 g_return_if_fail (TAPER_IS_MEM_PORT_SOURCE (self));
216 selfp->buffer_offset = selfp->buffer_len = 0;
217 selfp->retry_mode = FALSE;
219 if (source_parent_class->start_new_part)
220 source_parent_class->start_new_part(pself);