X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=device-src%2Fnull-device.c;h=eefa4acd1c84f9c6cf379b5c6758acf51c2cf240;hb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;hp=a6b1a0256af0e1d8884e0479bc4eeba890bf858b;hpb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;p=debian%2Famanda diff --git a/device-src/null-device.c b/device-src/null-device.c index a6b1a02..eefa4ac 100644 --- a/device-src/null-device.c +++ b/device-src/null-device.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 Zmanda, Inc. All Rights Reserved. + * Copyright (c) 2005-2008 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 @@ -14,26 +14,61 @@ * 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 - * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com + * Contact information: Zmanda Inc., 465 S Mathlida Ave, Suite 300 + * Sunnyvale, CA 94086, 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,7 +78,7 @@ 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; @@ -51,7 +86,7 @@ null_device_get_type (void) 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, @@ -72,124 +107,178 @@ null_device_get_type (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); - 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_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); + device_set_simple_property(dself, PROPERTY_STREAMING, + &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_APPENDABLE, + &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_PARTIAL_DELETION, + &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) +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; -static Device* null_device_factory(char * device_type, - char * device_name G_GNUC_UNUSED) { + /* 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_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); + 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_write_block (Device * pself, guint size, gpointer data, - gboolean last_block) { +null_device_finish (Device * pself) { + if (device_in_error(pself)) return FALSE; + + pself->access_mode = ACCESS_NULL; + return TRUE; +} + +static gboolean +null_device_start_file(Device * d_self, + dumpfile_t * jobInfo G_GNUC_UNUSED) +{ + d_self->in_file = TRUE; + 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; }