2 * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
22 /* The Device API abstracts device workings, interaction, properties, and
23 * capabilities from the rest of the Amanda code base. It supports
24 * pluggable modules for different kinds of devices. */
30 #include <glib-object.h>
33 #include "fileheader.h"
34 #include "directtcp.h"
35 #include "directtcp-connection.h"
37 /* Device API version. */
38 #define DEVICE_API_VERSION 0
40 extern void device_api_init(void);
42 /* Different access modes */
44 ACCESS_NULL, /* Device is not yet opened. */
50 #define IS_WRITABLE_ACCESS_MODE(mode) ((mode) == ACCESS_WRITE || \
51 (mode) == ACCESS_APPEND)
53 /* Device object definition follows. */
56 * Type checking and casting macros
58 GType device_get_type (void);
59 #define TYPE_DEVICE (device_get_type())
60 #define DEVICE(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), device_get_type(), Device)
61 #define DEVICE_CONST(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), device_get_type(), Device const)
62 #define DEVICE_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), device_get_type(), DeviceClass)
63 #define IS_DEVICE(obj) G_TYPE_CHECK_INSTANCE_TYPE((obj), device_get_type ())
64 #define DEVICE_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), device_get_type(), DeviceClass)
66 typedef struct DevicePrivate_s DevicePrivate;
68 /* See Amanda::Device POD for a description of these constants */
70 DEVICE_STATUS_SUCCESS = 0,
71 DEVICE_STATUS_DEVICE_ERROR = (1 << 0),
72 DEVICE_STATUS_DEVICE_BUSY = (1 << 1),
73 DEVICE_STATUS_VOLUME_MISSING = (1 << 2),
74 DEVICE_STATUS_VOLUME_UNLABELED = (1 << 3),
75 DEVICE_STATUS_VOLUME_ERROR = (1 << 4),
76 DEVICE_STATUS_FLAGS_MAX = (1 << 5)
79 #define DEVICE_STATUS_FLAGS_MASK (DEVICE_STATUS_MAX-1)
80 #define DEVICE_STATUS_FLAGS_TYPE (device_status_flags_get_type())
81 GType device_status_flags_get_type(void);
83 /* a callback to prolong an operation */
84 typedef gboolean (* ProlongProc)(gpointer data);
87 * Main object structure
89 typedef struct Device {
92 /* You can peek at the stuff below, but only subclasses should
93 change these values.*/
95 /* A mutex to protect field accessed from another thread.
96 * Only get_bytes_read and get_bytes_written are allowed from another
97 * Only in_file, bytes_read and bytes_written are protected */
100 /* What file, block are we at? (and are we in the middle of a file?) */
105 /* Holds the user-specified device name, which may be an alias */
108 /* Holds the user-specified access-mode, or ACCESS_NULL if the device
109 * has not yet been started*/
110 DeviceAccessMode access_mode;
112 /* In reading mode, FALSE unless all the data from the current file
113 * was successfully read. In writing mode, TRUE if the last byte
114 * of a file has been written by write_from_connection. */
117 /* In writing mode, indicates that the volume is at (or near, if possible)
121 /* Holds the label and time of the currently-inserted volume,
122 * or NULL if it has not been read/written yet. */
126 /* The most recently read volume header, or NULL if no header was
127 * read from this device. Callers can use this to glean information
128 * about the volume beyond volume_label and volume_time. */
129 dumpfile_t *volume_header;
131 /* The latest status for the device */
132 DeviceStatusFlags status;
134 /* device block-size ranges. These are also available as properties,
135 * and by default users can set block_size via property BLOCK_SIZE.
136 * Writers should use block_size, and readers should initially use
137 * block_size, and expand buffers as directed by read_block. */
138 gsize min_block_size;
139 gsize max_block_size;
141 gsize header_block_size;
144 guint64 bytes_written;
146 /* surety and source for the block size; if you set block_size directly,
148 PropertySurety block_size_surety;
149 PropertySource block_size_source;
151 DevicePrivate * private;
154 /* Pointer to factory function for device types.
156 * device_name is the full name ("tape:/dev/nst0")
157 * device_prefix is the prefix ("tape")
158 * device_node is what follows the prefix ("/dev/nst0")
160 * The caller retains responsibility to free or otherwise handle
161 * the passed strings.
163 typedef Device* (*DeviceFactory)(char *device_name,
164 char * device_prefix,
167 /* This function registers a new device with the allocation system.
168 * Call it after you register your type with the GLib type system.
169 * This function assumes that the strings in device_prefix_list are
170 * statically allocated. */
171 extern void register_device(DeviceFactory factory,
172 const char ** device_prefix_list);
177 typedef struct _DeviceClass DeviceClass;
178 struct _DeviceClass {
179 GObjectClass __parent__;
180 void (* open_device) (Device * self, char * device_name,
181 char * device_prefix, char * device_node);
182 gboolean (* configure) (Device * self, gboolean use_global_config);
183 DeviceStatusFlags (* read_label)(Device * self);
184 gboolean (* start) (Device * self, DeviceAccessMode mode,
185 char * label, char * timestamp);
186 gboolean (* start_file) (Device * self, dumpfile_t * info);
187 gboolean (* write_block) (Device * self, guint size, gpointer data);
188 gboolean (* finish_file) (Device * self);
189 dumpfile_t* (* seek_file) (Device * self, guint file);
190 gboolean (* seek_block) (Device * self, guint64 block);
191 int (* read_block) (Device * self, gpointer buf, int * size);
192 gboolean (* property_get_ex) (Device * self, DevicePropertyId id,
194 PropertySurety *surety,
195 PropertySource *source);
196 gboolean (* property_set_ex) (Device * self,
199 PropertySurety surety,
200 PropertySource source);
201 gboolean (* recycle_file) (Device * self, guint filenum);
202 gboolean (* erase) (Device * self);
203 gboolean (* eject) (Device * self);
204 gboolean (* finish) (Device * self);
205 guint64 (* get_bytes_read) (Device * self);
206 guint64 (* get_bytes_written) (Device * self);
208 gboolean (* listen)(Device *self, gboolean for_writing, DirectTCPAddr **addrs);
209 /* The MainLoop must be running, but the following 4 methods must not be
210 * called from an event. they must be called from a different thread.
216 int (* accept)(Device *self, DirectTCPConnection **conn,
217 int *cancelled, GMutex *abort_mutex, GCond *abort_cond);
218 int (* connect)(Device *self, gboolean for_writing,
219 DirectTCPAddr *addrs, DirectTCPConnection **conn,
221 GMutex *abort_mutex, GCond *abort_cond);
222 int (* write_from_connection)(Device *self, guint64 size,
223 guint64 *actual_size, int *cancelled,
224 GMutex *abort_mutex, GCond *abort_cond);
225 int (* read_to_connection)(Device *self, guint64 size,
226 guint64 *actual_size, int *cancelled,
227 GMutex *abort_mutex, GCond *abort_cond);
229 gboolean (* use_connection)(Device *self, DirectTCPConnection *conn);
231 /* array of DeviceProperty objects for this class, keyed by ID */
232 GArray *class_properties;
234 /* The return value of device_property_get_list */
235 GSList * class_properties_list;
237 /* TRUE if the directtcp methods are implemented by this device class */
238 gboolean directtcp_supported;
242 * Device Instantiation
245 /* Return the unaliased device name of a device.
246 * The returned string must not be freed by the caller.
248 char* device_unaliased_name(char * device_name);
250 /* This is how you get a new Device. Pass in a device name or alias.
252 * A Device is *always* returned, even for an invalid device name. You
253 * must check the resulting device->status to know if the device is valid
254 * to be used. If device->status is not DEVICE_STATUS_SUCCESS, then there
255 * was an error opening the device.
257 * Note that the Amanda configuration must be initialized, as this function
258 * looks for device definitions and other configuration information.
260 Device* device_open (char * device_name);
262 /* As a special case, a RAIT device can be created from a collection of child
263 * devices. This is used by the RAIT changer, for example. This function is
264 * implemented in rait-device.c. */
265 Device* rait_device_open_from_children(GSList *child_devices);
267 /* Once you have a new device, you should configure it. This sets properties
268 * on the device based on the user's configuation. If USE_GLOBAL_CONFIG is
269 * true, then any global device_property parameters are processed, along with
270 * tapetype and othe relevant parameters.
272 gboolean device_configure(Device *self, gboolean use_global_config);
278 /* return the error message or the string "Unknown Device error". The
279 * string remains the responsibility of the Device, and should not
280 * be freed by the caller. */
281 char *device_error(Device * self);
283 /* return a string version of the status. The string remains the
284 * responsibility of the Device, and should not be freed by the
286 char *device_status_error(Device * self);
288 /* Return errmsg if it is set or a string version of the status. The
289 * string remains the responsibility of the Device, and should not
290 * be freed by the caller. */
291 char *device_error_or_status(Device * self);
293 /* Set the error message for this device; for use internally to the
294 * API. The string becomes the responsibility of the Device. If
295 * ERRMSG is NULL, the message is cleared. Note that the given flags
296 * are OR'd with any existing status flags. */
297 void device_set_error(Device * self, char *errmsg, DeviceStatusFlags new_flags);
299 /* Mostly for internal use, this is a boolean check to see whether a given
300 * device is in an error state. If this is TRUE, most operations on the
303 * The check is for DEVICE_STATUS_DEVICE_ERROR *alone*; if any other bits
304 * (e.g., VOLUME_UNLABELED) are set, then the device may not actually be in
307 #define device_in_error(dev) \
308 ((DEVICE(dev))->status == DEVICE_STATUS_DEVICE_ERROR)
313 * See the Amanda::Device POD for more information here
316 DeviceStatusFlags device_read_label (Device * self);
317 gboolean device_start (Device * self,
318 DeviceAccessMode mode, char * label,
320 gboolean device_finish (Device * self);
321 guint64 device_get_bytes_read (Device * self);
322 guint64 device_get_bytes_written(Device * self);
323 gboolean device_start_file (Device * self,
324 dumpfile_t * jobInfo);
325 gboolean device_write_block (Device * self,
328 gboolean device_finish_file (Device * self);
329 dumpfile_t* device_seek_file (Device * self,
331 gboolean device_seek_block (Device * self,
333 int device_read_block (Device * self, gpointer buffer, int * size);
334 const GSList * device_property_get_list (Device * self);
335 gboolean device_property_get_ex (Device * self,
338 PropertySurety *surety,
339 PropertySource *source);
340 #define device_property_get(self, id, val) \
341 device_property_get_ex((self), (id), (val), NULL, NULL)
342 gboolean device_property_set_ex (Device * self,
345 PropertySurety surety,
346 PropertySource source);
347 #define device_property_set(self, id, val) \
348 device_property_set_ex((self), (id), (val), \
349 PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_USER)
350 gboolean device_recycle_file (Device * self,
353 gboolean device_erase (Device * self);
354 gboolean device_eject (Device * self);
356 #define device_directtcp_supported(self) (DEVICE_GET_CLASS((self))->directtcp_supported)
357 gboolean device_listen(Device *self, gboolean for_writing, DirectTCPAddr **addrs);
358 int device_accept(Device *self, DirectTCPConnection **conn,
359 int *cancelled, GMutex *abort_mutex, GCond *abort_cond);
360 int device_connect(Device *self, gboolean for_writing,
361 DirectTCPAddr *addrs, DirectTCPConnection **conn,
363 GMutex *abort_mutex, GCond *abort_cond);
364 int device_write_from_connection(Device *self, guint64 size,
365 guint64 *actual_size, int *cancelled,
366 GMutex *abort_mutex, GCond *abort_cond);
367 int device_read_to_connection(Device *self, guint64 size,
368 guint64 *actual_size, int *cancelled,
369 GMutex *abort_mutex, GCond *abort_cond);
370 gboolean device_use_connection(Device *self, DirectTCPConnection *conn);
372 /* Protected methods. Don't call these except in subclass implementations. */
374 /* This method provides post-construction initalization once the
375 * device name is known. It should only be used by Device
376 * factories. It is provided here as a virtual method (instead of
377 * a static function) because some devices may want to chain
378 * initilization to their parents. */
379 void device_open_device (Device * self, char *device_name, char *device_type, char *device_node);
381 /* Builds a proper header of between *size and self->block_size bytes.
382 * Returns NULL if the header does not fit in a single block. The result
383 * must be free'd. If size is NULL, the block size is used.
385 * If size is not NULL, *size is set to the actual size of the generated header.
387 char * device_build_amanda_header(Device * self, const dumpfile_t * jobinfo,
390 /* Does what you expect. You have to free the returned header. Ensures
391 that self->volume_time matches the header written to tape. */
392 dumpfile_t * make_tapestart_header(Device * self, char * label,
395 /* Does what you expect. Uses the current time. */
396 dumpfile_t * make_tapeend_header(void);
398 /* Erase any stored volume information. Use this if something happens (e.g.,
399 * a property is set) that voids previously-read volume details.
400 * This function is a NOOP unless the device is in the NULL state. */
401 void device_clear_volume_details(Device * device);
403 /* Property Handling */
405 /* Registers a property for a new device class; device drivers' GClassInitFunc
406 * should call this function for each device-specific property of the class.
407 * If either getter or setter is NULL, then the corresponding operation will
410 * Note that this will replace any existing registration (e.g., from a parent
413 void device_class_register_property(DeviceClass *klass, DevicePropertyId id,
414 PropertyAccessFlags access,
415 PropertyGetFn getter,
416 PropertySetFn setter);
418 /* Set a 'simple' property on the device. This tucks the value away in the
419 * object, to be retrieved by device_simple_property_get_fn. This is most
420 * often used in GInstanceInit functions, but can be used at any time to set or
421 * change the value of a simple property */
422 gboolean device_set_simple_property(Device *self, DevicePropertyId id,
423 GValue *val, PropertySurety surety,
424 PropertySource source);
426 /* Get a simple property set with device_set_simple_property. This is a little
427 * bit quicker than calling device_property_get_ex(), and does not affect the
428 * device's error state. Returns FALSE if the property has not been set.
429 * Surety and source are output parameters and will be ignored if they are
431 gboolean device_get_simple_property(Device *self, DevicePropertyId id,
432 GValue *val, PropertySurety *surety,
433 PropertySource *source);
435 /* A useful PropertySetFn. If your subclass also needs to intercept sets, for
436 * example to flush a cache or update a member variable, then write a stub
437 * function which "calls up" to this function. */
438 gboolean device_simple_property_set_fn(Device *self, DevicePropertyBase *base,
439 GValue *val, PropertySurety surety,
440 PropertySource source);
442 /* A useful PropertyGetFn -- returns the value, source, and surety set with
443 * device_set_simple_property */
444 gboolean device_simple_property_get_fn(Device *self, DevicePropertyBase *base,
445 GValue *val, PropertySurety *surety,
446 PropertySource *source);
448 #endif /* DEVICE_H */