/*
- * Copyright (c) 2007, 2008, 2009, 2010 Zmanda, Inc. All Rights Reserved.
+ * Copyright (c) 2007-2012 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 free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
#include <regex.h>
#include "device.h"
-#include "queueing.h"
-#include "device-queueing.h"
#include "property.h"
#include "timestamp.h"
static void default_device_open_device(Device * self, char * device_name,
char * device_type, char * device_node);
static gboolean default_device_configure(Device *self, gboolean use_global_config);
-static gboolean default_device_write_from_fd(Device *self,
- queue_fd_t *queue_fd);
-static gboolean default_device_read_to_fd(Device *self, queue_fd_t *queue_fd);
static gboolean default_device_property_get_ex(Device * self, DevicePropertyId id,
GValue * val,
PropertySurety *surety,
device_class->open_device = default_device_open_device;
device_class->configure = default_device_configure;
- device_class->write_from_fd = default_device_write_from_fd;
- device_class->read_to_fd = default_device_read_to_fd;
device_class->property_get_ex = default_device_property_get_ex;
device_class->property_set_ex = default_device_property_set_ex;
g_object_class->finalize = device_finalize;
PROPERTY_ACCESS_GET_MASK|PROPERTY_ACCESS_SET_MASK,
device_simple_property_get_fn,
device_simple_property_set_fn);
+
+ device_class_register_property(device_class, PROPERTY_LEOM,
+ PROPERTY_ACCESS_GET_MASK,
+ device_simple_property_get_fn,
+ device_simple_property_set_fn);
}
static void simple_property_free(SimpleProperty * resp) {
*driver_name = stralloc("tape");
*device = stralloc(user_name);
#else /* !WANT_TAPE_DEVICE */
- errmsg = newvstrallocf(errmsg, "\"%s\" is not a valid device name.\n", user_name);
+ *errmsg = newvstrallocf(*errmsg, "\"%s\" is not a valid device name.\n", user_name);
regfree(®ex);
return FALSE;
#endif /* WANT_TAPE_DEVICE */
device = factory(device_name, device_type, device_node);
g_assert(device != NULL); /* factories must always return a device */
+ device->device_mutex = g_mutex_new();
amfree(device_type);
amfree(device_node);
} else {
self->volume_time = g_strdup(timestamp);
}
- strncpy(rval->datestamp, self->volume_time, sizeof(rval->datestamp));
- strncpy(rval->name, label, sizeof(rval->name));
+ g_strlcpy(rval->datestamp, self->volume_time, sizeof(rval->datestamp));
+ g_strlcpy(rval->name, label, sizeof(rval->name));
return rval;
}
rval = malloc(sizeof(*rval));
rval->type = F_TAPEEND;
timestamp = get_timestamp_from_time(time(NULL));
- strncpy(rval->datestamp, timestamp, sizeof(rval->datestamp));
+ g_strlcpy(rval->datestamp, timestamp, sizeof(rval->datestamp));
amfree(timestamp);
return rval;
}
g_assert(block_size >= 0); /* int -> gsize (unsigned) */
if ((gsize)block_size < self->min_block_size
- || (gsize)block_size > self->max_block_size)
+ || (gsize)block_size > self->max_block_size) {
+ device_set_error(self,
+ g_strdup_printf("Error setting BLOCK-SIZE property to '%zu', it must be between %zu and %zu", (gsize)block_size, self->min_block_size, self->max_block_size),
+ DEVICE_STATUS_DEVICE_ERROR);
return FALSE;
+ }
self->block_size = block_size;
self->block_size_surety = surety;
return DEVICE_GET_CLASS(self)->class_properties_list;
}
-static gboolean
-default_device_read_to_fd(Device *self, queue_fd_t *queue_fd) {
- GValue val;
- StreamingRequirement streaming_mode;
-
- if (device_in_error(self)) return FALSE;
-
- /* Get the device's parameters */
- bzero(&val, sizeof(val));
- if (!device_property_get(self, PROPERTY_STREAMING, &val)
- || !G_VALUE_HOLDS(&val, STREAMING_REQUIREMENT_TYPE)) {
- streaming_mode = STREAMING_REQUIREMENT_REQUIRED;
- } else {
- streaming_mode = g_value_get_enum(&val);
- }
-
- return QUEUE_SUCCESS ==
- do_consumer_producer_queue_full(
- device_read_producer,
- self,
- fd_write_consumer,
- queue_fd,
- self->block_size,
- DEFAULT_MAX_BUFFER_MEMORY,
- streaming_mode);
-}
-
-static gboolean
-default_device_write_from_fd(Device *self, queue_fd_t *queue_fd) {
- GValue val;
- StreamingRequirement streaming_mode;
-
- if (device_in_error(self)) return FALSE;
-
- /* Get the device's parameters */
- bzero(&val, sizeof(val));
- if (!device_property_get(self, PROPERTY_STREAMING, &val)
- || !G_VALUE_HOLDS(&val, STREAMING_REQUIREMENT_TYPE)) {
- streaming_mode = STREAMING_REQUIREMENT_REQUIRED;
- } else {
- streaming_mode = g_value_get_enum(&val);
- }
-
- return QUEUE_SUCCESS ==
- do_consumer_producer_queue_full(
- fd_read_producer,
- queue_fd,
- device_write_consumer,
- self,
- self->block_size,
- DEFAULT_MAX_BUFFER_MEMORY,
- streaming_mode);
-}
-
/* XXX WARNING XXX
* All the functions below this comment are stub functions that do nothing
* but implement the virtual function table. Call these functions and they
return (klass->finish)(self);
}
+guint64
+device_get_bytes_read (Device * self) {
+ DeviceClass *klass;
+ guint64 bytes = 0;
+
+ g_assert(IS_DEVICE (self));
+
+ g_mutex_lock(self->device_mutex);
+ if (self->in_file) {
+ klass = DEVICE_GET_CLASS(self);
+ if (klass->get_bytes_read) {
+ bytes = (klass->get_bytes_read)(self);
+ } else {
+ bytes = self->bytes_read;
+ }
+ }
+ g_mutex_unlock(self->device_mutex);
+ return bytes;
+}
+
+guint64
+device_get_bytes_written (Device * self) {
+ DeviceClass *klass;
+ guint64 bytes = 0;
+
+ g_assert(IS_DEVICE (self));
+
+ g_mutex_lock(self->device_mutex);
+ if (self->in_file) {
+ klass = DEVICE_GET_CLASS(self);
+ if (klass->get_bytes_written) {
+ bytes = (klass->get_bytes_written)(self);
+ } else {
+ bytes = self->bytes_written;
+ }
+ }
+ g_mutex_unlock(self->device_mutex);
+ return bytes;
+}
+
gboolean
device_configure (Device * self, gboolean use_global_config)
{
return (*klass->write_block)(self,size, block);
}
-gboolean
-device_write_from_fd (Device * self, queue_fd_t * queue_fd)
-{
- DeviceClass *klass;
-
- g_assert(IS_DEVICE (self));
- g_assert(queue_fd->fd >= 0);
- g_assert(IS_WRITABLE_ACCESS_MODE(self->access_mode));
-
- klass = DEVICE_GET_CLASS(self);
- g_assert(klass->write_from_fd);
- return (klass->write_from_fd)(self,queue_fd);
-}
-
gboolean
device_start_file (Device * self, dumpfile_t * jobInfo) {
DeviceClass * klass;
return (klass->read_block)(self,buffer,size);
}
-gboolean
-device_read_to_fd (Device * self, queue_fd_t *queue_fd)
-{
- DeviceClass *klass;
-
- g_assert(IS_DEVICE (self));
- g_assert(queue_fd->fd >= 0);
- g_assert(self->access_mode == ACCESS_READ);
-
- klass = DEVICE_GET_CLASS(self);
- g_assert(klass->read_to_fd);
- return (klass->read_to_fd)(self,queue_fd);
-}
-
-
gboolean
device_property_get_ex(
Device * self,
}
}
-gboolean
+int
device_accept(
Device *self,
DirectTCPConnection **conn,
- ProlongProc prolong,
- gpointer prolong_data)
+ int *cancelled,
+ GMutex *abort_mutex,
+ GCond *abort_cond)
{
DeviceClass *klass;
klass = DEVICE_GET_CLASS(self);
if(klass->accept) {
- return (klass->accept)(self, conn, prolong, prolong_data);
+ return (klass->accept)(self, conn, cancelled, abort_mutex, abort_cond);
} else {
device_set_error(self,
- stralloc(_("Unimplemented method")),
+ g_strdup(_("Unimplemented method")),
DEVICE_STATUS_DEVICE_ERROR);
- return FALSE;
+ return 1;
}
}
-gboolean
+
+int
+device_connect(
+ Device *self,
+ gboolean for_writing,
+ DirectTCPAddr *addrs,
+ DirectTCPConnection **conn,
+ int *cancelled,
+ GMutex *abort_mutex,
+ GCond *abort_cond)
+{
+ DeviceClass *klass;
+
+ klass = DEVICE_GET_CLASS(self);
+ if(klass->connect) {
+ return (klass->connect)(self, for_writing, addrs, conn, cancelled,
+ abort_mutex, abort_cond);
+ } else {
+ device_set_error(self,
+ g_strdup(_("Unimplemented method")),
+ DEVICE_STATUS_DEVICE_ERROR);
+ return 1;
+ }
+}
+
+int
device_write_from_connection(
Device *self,
guint64 size,
- guint64 *actual_size)
+ guint64 *actual_size,
+ int *cancelled,
+ GMutex *abort_mutex,
+ GCond *abort_cond)
{
DeviceClass *klass;
g_assert(IS_WRITABLE_ACCESS_MODE(self->access_mode));
if(klass->write_from_connection) {
- return (klass->write_from_connection)(self, size, actual_size);
+ return (klass->write_from_connection)(self, size, actual_size,
+ cancelled,
+ abort_mutex, abort_cond);
} else {
device_set_error(self,
stralloc(_("Unimplemented method")),
DEVICE_STATUS_DEVICE_ERROR);
- return FALSE;
+ return 1;
}
}
-gboolean
+int
device_read_to_connection(
Device *self,
guint64 size,
- guint64 *actual_size)
+ guint64 *actual_size,
+ int *cancelled,
+ GMutex *abort_mutex,
+ GCond *abort_cond)
{
DeviceClass *klass;
klass = DEVICE_GET_CLASS(self);
if(klass->read_to_connection) {
- return (klass->read_to_connection)(self, size, actual_size);
+ return (klass->read_to_connection)(self, size, actual_size,
+ cancelled, abort_mutex, abort_cond);
} else {
device_set_error(self,
stralloc(_("Unimplemented method")),
DEVICE_STATUS_DEVICE_ERROR);
- return FALSE;
+ return 1;
}
}