X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=device-src%2Fnull-device.c;h=3f1bf3473e07c30a59772b4da19cc08e9c59100b;hb=ca9fbb570498b74f4c6adaebd629bff20f146a14;hp=a6b1a0256af0e1d8884e0479bc4eeba890bf858b;hpb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;p=debian%2Famanda diff --git a/device-src/null-device.c b/device-src/null-device.c index a6b1a02..3f1bf34 100644 --- a/device-src/null-device.c +++ b/device-src/null-device.c @@ -1,39 +1,74 @@ /* - * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License version 2.1 as - * published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, but + * Copyright (c) 2007, 2008, 2009, 2010 Zmanda, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * Contact information: Zmanda Inc., 505 N Mathlida Ave, Suite 120 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com */ #include "amanda.h" #include "device.h" -#include "null-device.h" #define NULL_DEVICE_MIN_BLOCK_SIZE (1) -#define NULL_DEVICE_MAX_BLOCK_SIZE SHRT_MAX +#define NULL_DEVICE_MAX_BLOCK_SIZE (INT_MAX) +#define NULL_DEVICE_DEFAULT_BLOCK_SIZE DISK_BLOCK_BYTES + +/* + * Type checking and casting macros + */ +#define TYPE_NULL_DEVICE (null_device_get_type()) +#define NULL_DEVICE(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), null_device_get_type(), NullDevice) +#define NULL_DEVICE_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), null_device_get_type(), NullDevice const) +#define NULL_DEVICE_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), null_device_get_type(), NullDeviceClass) +#define IS_NULL_DEVICE(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), null_device_get_type ()) +#define NULL_DEVICE_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), null_device_get_type(), NullDeviceClass) +static GType null_device_get_type (void); + +/* + * Main object structure + */ +typedef struct _NullDevice NullDevice; +struct _NullDevice { + Device __parent__; +}; + +/* + * Class definition + */ +typedef struct _NullDeviceClass NullDeviceClass; +struct _NullDeviceClass { + DeviceClass __parent__; + gboolean in_file; +}; + +void null_device_register(void); /* here are local prototypes */ static void null_device_init (NullDevice * o); static void null_device_class_init (NullDeviceClass * c); +static void null_device_base_init (NullDeviceClass * c); +static DeviceStatusFlags null_device_read_label(Device * dself); +static void null_device_open_device(Device * self, char *device_name, + char * device_type, char * device_node); static gboolean null_device_start (Device * self, DeviceAccessMode mode, char * label, char * timestamp); -static gboolean null_device_write_block (Device * self, guint size, - gpointer data, gboolean last); -static Device* null_device_factory(char * device_type, - char * device_name); +static gboolean null_device_finish (Device * pself); +static gboolean null_device_start_file(Device * self, dumpfile_t * jobInfo); +static gboolean null_device_write_block (Device * self, guint size, gpointer data); +static gboolean null_device_finish_file(Device * self); +static Device* null_device_factory(char * device_name, char * device_type, char * device_node); /* pointer to the class of our parent */ static DeviceClass *parent_class = NULL; @@ -43,15 +78,15 @@ void null_device_register(void) { register_device(null_device_factory, device_prefix_list); } -GType +static GType null_device_get_type (void) { static GType type = 0; - + if G_UNLIKELY(type == 0) { static const GTypeInfo info = { sizeof (NullDeviceClass), - (GBaseInitFunc) NULL, + (GBaseInitFunc) null_device_base_init, (GBaseFinalizeFunc) NULL, (GClassInitFunc) null_device_class_init, (GClassFinalizeFunc) NULL, @@ -61,7 +96,7 @@ null_device_get_type (void) (GInstanceInitFunc) null_device_init, NULL }; - + type = g_type_register_static (TYPE_DEVICE, "NullDevice", &info, (GTypeFlags)0); } @@ -69,127 +104,196 @@ null_device_get_type (void) return type; } -static void +static void null_device_init (NullDevice * self) { - Device * o; - DeviceProperty prop; + Device * dself; GValue response; - o = (Device*)(self); + dself = (Device*)(self); bzero(&response, sizeof(response)); /* Register properties */ - prop.base = &device_property_concurrency; - prop.access = PROPERTY_ACCESS_GET_MASK; g_value_init(&response, CONCURRENCY_PARADIGM_TYPE); g_value_set_enum(&response, CONCURRENCY_PARADIGM_RANDOM_ACCESS); - device_add_property(o, &prop, &response); + device_set_simple_property(dself, PROPERTY_CONCURRENCY, + &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED); g_value_unset(&response); - - prop.base = &device_property_streaming; g_value_init(&response, STREAMING_REQUIREMENT_TYPE); g_value_set_enum(&response, STREAMING_REQUIREMENT_NONE); - device_add_property(o, &prop, &response); + device_set_simple_property(dself, PROPERTY_STREAMING, + &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED); g_value_unset(&response); - - prop.base = &device_property_block_size; - g_value_init(&response, G_TYPE_INT); - g_value_set_int(&response, -1); - device_add_property(o, &prop, &response); + + g_value_init(&response, G_TYPE_BOOLEAN); + g_value_set_boolean(&response, FALSE); + device_set_simple_property(dself, PROPERTY_APPENDABLE, + &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED); g_value_unset(&response); - - prop.base = &device_property_min_block_size; - g_value_init(&response, G_TYPE_UINT); - g_value_set_uint(&response, NULL_DEVICE_MIN_BLOCK_SIZE); - device_add_property(o, &prop, &response); - - prop.base = &device_property_max_block_size; - g_value_set_uint(&response, NULL_DEVICE_MAX_BLOCK_SIZE); - device_add_property(o, &prop, &response); + + g_value_init(&response, G_TYPE_BOOLEAN); + g_value_set_boolean(&response, FALSE); + device_set_simple_property(dself, PROPERTY_PARTIAL_DELETION, + &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED); g_value_unset(&response); - prop.base = &device_property_appendable; g_value_init(&response, G_TYPE_BOOLEAN); g_value_set_boolean(&response, FALSE); - device_add_property(o, &prop, &response); + device_set_simple_property(dself, PROPERTY_FULL_DELETION, + &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED); + g_value_unset(&response); - prop.base = &device_property_partial_deletion; - device_add_property(o, &prop, &response); + g_value_init(&response, G_TYPE_BOOLEAN); + g_value_set_boolean(&response, FALSE); + device_set_simple_property(dself, PROPERTY_LEOM, + &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED); g_value_unset(&response); - prop.base = &device_property_canonical_name; + /* this device's canonical name is always "null:", regardless of + * the name the user supplies; note that we install the simple + * getter in null_device_class_init. */ g_value_init(&response, G_TYPE_STRING); g_value_set_static_string(&response, "null:"); - device_add_property(o, &prop, &response); + device_set_simple_property(dself, PROPERTY_CANONICAL_NAME, + &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DEFAULT); g_value_unset(&response); - prop.base = &device_property_medium_access_type; g_value_init(&response, MEDIA_ACCESS_MODE_TYPE); g_value_set_enum(&response, MEDIA_ACCESS_MODE_WRITE_ONLY); - device_add_property(o, &prop, &response); + device_set_simple_property(dself, PROPERTY_MEDIUM_ACCESS_TYPE, + &response, PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_DETECTED); g_value_unset(&response); } -static void -null_device_class_init (NullDeviceClass * c G_GNUC_UNUSED) +static void +null_device_class_init (NullDeviceClass * c) { DeviceClass *device_class = (DeviceClass *)c; parent_class = g_type_class_ref (TYPE_DEVICE); + device_class->read_label = null_device_read_label; + device_class->open_device = null_device_open_device; device_class->start = null_device_start; + device_class->finish = null_device_finish; + device_class->start_file = null_device_start_file; device_class->write_block = null_device_write_block; + device_class->finish_file = null_device_finish_file; } +static void +null_device_base_init (NullDeviceClass * c) +{ + DeviceClass *device_class = (DeviceClass *)c; + + /* Our canonical name is simpler than most devices' */ + device_class_register_property(device_class, PROPERTY_CANONICAL_NAME, + PROPERTY_ACCESS_GET_MASK, + device_simple_property_get_fn, + device_simple_property_set_fn); +} -static Device* null_device_factory(char * device_type, - char * device_name G_GNUC_UNUSED) { + +static Device* null_device_factory(char * device_name, char * device_type, char * device_node) { + Device * device; g_assert(0 == strcmp(device_type, "null")); - return DEVICE(g_object_new(TYPE_NULL_DEVICE, NULL)); - + device = DEVICE(g_object_new(TYPE_NULL_DEVICE, NULL)); + device_open_device(device, device_name, device_type, device_node); + return device; } /* Begin virtual function overrides */ -static gboolean +static DeviceStatusFlags +null_device_read_label(Device * dself) { + if (device_in_error(dself)) return FALSE; + + device_set_error(dself, + stralloc(_("Can't open NULL device for reading or appending.")), + DEVICE_STATUS_DEVICE_ERROR); + return FALSE; +} + +static void +null_device_open_device(Device * pself, char *device_name, + char * device_type, char * device_node) +{ + pself->min_block_size = NULL_DEVICE_MIN_BLOCK_SIZE; + pself->max_block_size = NULL_DEVICE_MAX_BLOCK_SIZE; + pself->block_size = NULL_DEVICE_DEFAULT_BLOCK_SIZE; + + if (parent_class->open_device) { + parent_class->open_device(pself, device_name, device_type, device_node); + } +} + +static gboolean null_device_start (Device * pself, DeviceAccessMode mode, char * label, char * timestamp) { NullDevice * self; self = NULL_DEVICE(pself); - g_return_val_if_fail (self != NULL, FALSE); + + if (device_in_error(self)) return FALSE; + + pself->access_mode = mode; + pself->in_file = FALSE; if (mode == ACCESS_WRITE) { - if (parent_class->start) { - return parent_class->start((Device*)self, mode, label, timestamp); - } else { - return TRUE; - } + pself->volume_label = newstralloc(pself->volume_label, label); + pself->volume_time = newstralloc(pself->volume_time, timestamp); + pself->header_block_size = 32768; + return TRUE; } else { - g_fprintf(stderr, "Can't open NULL device for reading or appending.\n"); + device_set_error(pself, + stralloc(_("Can't open NULL device for reading or appending.")), + DEVICE_STATUS_DEVICE_ERROR); return FALSE; } } +/* This default implementation does very little. */ +static gboolean +null_device_finish (Device * pself) { + pself->access_mode = ACCESS_NULL; + + if (device_in_error(pself)) return FALSE; + + return TRUE; +} + static gboolean -null_device_write_block (Device * pself, guint size, gpointer data, - gboolean last_block) { +null_device_start_file(Device * d_self, + dumpfile_t * jobInfo G_GNUC_UNUSED) +{ + d_self->in_file = TRUE; + d_self->is_eom = FALSE; + d_self->block = 0; + if (d_self->file <= 0) + d_self->file = 1; + else + d_self->file ++; + + return TRUE; +} + +static gboolean +null_device_write_block (Device * pself, guint size G_GNUC_UNUSED, + gpointer data G_GNUC_UNUSED) { NullDevice * self; self = NULL_DEVICE(pself); - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (data != NULL, FALSE); - - if ((size < NULL_DEVICE_MIN_BLOCK_SIZE && !last_block) || - size > NULL_DEVICE_MAX_BLOCK_SIZE) { - return FALSE; - } else { - if (parent_class->write_block) { - /* Calls device_finish_file(). */ - parent_class->write_block((Device*)self, size, data, last_block); - } - return TRUE; - } - g_assert_not_reached(); + if (device_in_error(self)) return FALSE; + + pself->block++; + + return TRUE; +} + +static gboolean +null_device_finish_file(Device * pself) { + if (device_in_error(pself)) return FALSE; + + pself->in_file = FALSE; + return TRUE; }