Imported Upstream version 3.1.0
[debian/amanda] / device-src / device.h
index 0230970c24f316828c5787fd859948539069336c..b39a7d0b462e94598334f79ce91698ac78a71a37 100644 (file)
@@ -1,21 +1,21 @@
 /*
- * 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 
- * 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., 465 S Mathlida Ave, Suite 300
- * Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
+ * 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
  */
 
 /* The Device API abstracts device workings, interaction, properties, and
@@ -30,6 +30,8 @@
 
 #include "property.h"
 #include "fileheader.h"
+#include "directtcp.h"
+#include "directtcp-connection.h"
 
 /* Device API version. */
 #define DEVICE_API_VERSION 0
@@ -62,35 +64,14 @@ GType       device_get_type (void);
 
 typedef struct DevicePrivate_s DevicePrivate;
 
-/* This structure is a Flags (bitwise OR of values). Zero indicates success;
- * any other value indicates some kind of problem reading the label. If
- * multiple bits are set, it does not necessarily indicate that /all/ of
- * the specified issues occured, but rather that /at least one/ did. */
+/* See Amanda::Device POD for a description of these constants */
 typedef enum {
-    /* When changing, Also update device_status_flags_values in
-     * device-src/device.c and perl/Amanda/Device.swg */
     DEVICE_STATUS_SUCCESS          = 0,
-
-    /* The device is in an unresolvable error state, and
-     * further retries are unlikely to change the status */
     DEVICE_STATUS_DEVICE_ERROR     = (1 << 0),
-
-    /* The device is in use, and should be retried later */
     DEVICE_STATUS_DEVICE_BUSY      = (1 << 1),
-
-    /* The device itself is OK, but has no media loaded.  This
-     * may change if media is loaded by the user or a changer */
     DEVICE_STATUS_VOLUME_MISSING   = (1 << 2),
-
-    /* The device is OK and media is laoded, but there is
-     * no Amanda header or an invalid header on the media. */
     DEVICE_STATUS_VOLUME_UNLABELED = (1 << 3),
-
-    /* The device is OK, but there was an unresolvable error
-     * loading the header from the media, so subsequent reads
-     * or writes will probably fail. */
     DEVICE_STATUS_VOLUME_ERROR     = (1 << 4),
-
     DEVICE_STATUS_FLAGS_MAX        = (1 << 5)
 } DeviceStatusFlags;
 
@@ -98,6 +79,9 @@ typedef enum {
 #define DEVICE_STATUS_FLAGS_TYPE (device_status_flags_get_type())
 GType device_status_flags_get_type(void);
 
+/* a callback to prolong an operation */
+typedef gboolean (* ProlongProc)(gpointer data);
+
 /*
  * Main object structure
  */
@@ -107,7 +91,7 @@ typedef struct Device {
     /* You can peek at the stuff below, but only subclasses should
        change these values.*/
 
-    /* What file, block are we at? (and are we in the middle of a file?) */
+    /* What file, block are we at? (and are we in the middle of a file?) */
     int file;
     guint64 block;
     gboolean in_file;
@@ -120,10 +104,14 @@ typedef struct Device {
     DeviceAccessMode access_mode;
 
     /* In reading mode, FALSE unless all the data from the current file
-     * was successfully read.  In writing mode, TRUE if the end of tape
-     * has been reached. */
+     * was successfully read.  In writing mode, TRUE if the last byte
+     * of a file has been written by write_from_connection. */
     gboolean is_eof;
 
+    /* In writing mode, indicates that the volume is at (or near, if possible)
+     * EOM. */
+    gboolean is_eom;
+
     /* Holds the label and time of the currently-inserted volume,
      * or NULL if it has not been read/written yet. */
     char * volume_label;
@@ -203,19 +191,36 @@ struct _DeviceClass {
                                  PropertySurety surety,
                                  PropertySource source);
     gboolean (* recycle_file) (Device * self, guint filenum);
+    gboolean (* erase) (Device * self);
+    gboolean (* eject) (Device * self);
     gboolean (* finish) (Device * self);
 
+    gboolean (* listen)(Device *self, gboolean for_writing, DirectTCPAddr **addrs);
+    gboolean (* accept)(Device *self, DirectTCPConnection **conn,
+                       ProlongProc prolong, gpointer prolong_data);
+    gboolean (* write_from_connection)(Device *self, guint64 size, guint64 *actual_size);
+    gboolean (* read_to_connection)(Device *self, guint64 size, guint64 *actual_size);
+    gboolean (* use_connection)(Device *self, DirectTCPConnection *conn);
+
     /* array of DeviceProperty objects for this class, keyed by ID */
     GArray *class_properties;
 
     /* The return value of device_property_get_list */
     GSList * class_properties_list;
+
+    /* TRUE if the directtcp methods are implemented by this device class */
+    gboolean directtcp_supported;
 };
 
 /*
  * Device Instantiation
  */
 
+/* Return the unaliased device name of a device.
+ * The returned string must not be freed by the caller.
+ */
+char*          device_unaliased_name(char * device_name);
+
 /* This is how you get a new Device. Pass in a device name or alias.
  *
  * A Device is *always* returned, even for an invalid device name. You
@@ -228,6 +233,11 @@ struct _DeviceClass {
  */
 Device*                device_open     (char * device_name);
 
+/* As a special case, a RAIT device can be created from a collection of child
+ * devices.  This is used by the RAIT changer, for example.  This function is
+ * implemented in rait-device.c.  */
+Device*                rait_device_open_from_children(GSList *child_devices);
+
 /* Once you have a new device, you should configure it.  This sets properties
  * on the device based on the user's configuation.  If USE_GLOBAL_CONFIG is
  * true, then any global device_property parameters are processed, along with
@@ -273,140 +283,31 @@ void device_set_error(Device * self, char *errmsg, DeviceStatusFlags new_flags);
 
 /*
  * Public methods
+ *
+ * See the Amanda::Device POD for more information here
  */
 
-/* This instructs the device to read the label on the current volume.
- * device->volume_label will not be initalized until read_label or start is
- * called. You are encouraged to read the label only after setting any
- * properties that may affect the label-reading process. Also, after
- * calling this function, device->volume_label and device->volume_time
- * will be non-NULL if and only if this function returns
- * DEVICE_STATUS_SUCCESS. */
 DeviceStatusFlags        device_read_label (Device * self);
-
-/* This tells the Device that it's OK to start reading and writing
- * data. Before you call this, you can only call
- * device_property_{get, set} and device_read_label. You can only call
- * this a second time if you call device_finish() first.
- *
- * You should pass a label and timestamp if and only if you are
- * opening in WRITE mode (not READ or APPEND). The label and timestamp
- * remain the caller's responsibility in terms of memory management. The
- * passed timestamp may be NULL, in which case it will be filled in with
- * the current time.
- *
- * Note that implementations need not calculate a the current time: the
- * dispatch function does it for you. */
 gboolean       device_start    (Device * self,
                                  DeviceAccessMode mode, char * label,
                                  char * timestamp);
-
-/* This undoes device_start, returning you to the NULL state. Do this
- * if you want to (for example) change access mode.
- *
- * Note to subclass implementors: Call this function first from your
- * finalization function. */
 gboolean       device_finish   (Device * self);
-
-/* But you can't write any data until you call this function, too.  This
- * function does not take ownership of the passed dumpfile_t; you must free it
- * yourself.  Note that this function *does* set the blocksize field of the
- * header properly, based on the size of the header block.  */
 gboolean        device_start_file       (Device * self,
                                          dumpfile_t * jobInfo);
-
-/* Does what you expect. Size must be device->block_size or less.
- * If less, then this is the final block in the file, and no more blocks
- * may be written until finish_file and start_file have been called. */
 gboolean       device_write_block      (Device * self,
                                          guint size,
                                          gpointer data);
-
-/* This will drain the given fd (reading until EOF), and write the
- * resulting data out to the device using maximally-sized blocks.
- * This function does not call device_finish_file automatically.
- */
 gboolean       device_write_from_fd    (Device * self,
                                        queue_fd_t *queue_fd);
-
-/* Call this when you are finished writing a file.
- * This function will write a filemark or the local
- * equivalent, flush the buffers, and do whatever dirty work needs
- * to be done at such a point in time. */
 gboolean       device_finish_file      (Device * self);
-
-/* For reading only: Seeks to the beginning of a particular
- * filemark. Only do this when reading; opening in
- * ACCESS_WRITE will start you out at the first file, and opening in
- * ACCESS_APPEND will automatically seek to the end of the medium.
- * 
- * If the requested file doesn't exist, as might happen when a volume has
- * had files recycled, then this function will seek to the next file that
- * does exist. You can check which file this function selected by
- * examining the file field of the Device structure. If the requested
- * file number is *exactly* one more than the last valid file, this
- * function returns a TAPEEND header.
- *
- * If an error occurs or if the requested file is two or more beyond the
- * last valid file, this function returns NULL.
- *
- * Example results for a volume that has only files 1 and 3:
- * 1 -> Seeks to file 1
- * 2 -> Seeks to file 3
- * 3 -> Seeks to file 3
- * 4 -> Returns TAPEEND
- * 5 -> Returns NULL
- *
- * The returned dumpfile_t is yours to keep, at no extra charge. */
 dumpfile_t*    device_seek_file        (Device * self,
                                        guint file);
-
-/* After you have called device_seek_file (and /only/ after having
- * called device_seek_file), you can call this to seek to a particular
- * block inside the file. It works like SEEK_SET, only in blocks. */
 gboolean       device_seek_block       (Device * self,
                                        guint64 block);
-
-/* After you have called device_seek_file and/or device_seek_block,
- * you can start calling this function. It always reads exactly one whole
- * block at a time, however big that might be. You must pass in a buffer and
- * specify its size. If the buffer is big enough, the read is
- * performed, and both *size and the return value are equal to the
- * number of bytes actually read. If the buffer is not big enough, then
- * no read is performed, the function returns 0, and *size is set
- * to the minimum buffer size required to read the next block. If an
- * error occurs, the function returns -1  and *size is left unchanged.
- *
- * Note that this function may request a block size bigger than
- * dev->block_size, if it discovers an oversized block.  This allows Amanda to
- * read from volumes regardless of the block size used to write them. It is not
- * an error if buffer == NULL and *size == 0. This should be treated as a query
- * as to the possible size of the next block, although it is not an error for
- * the next read to request an even larger block size.  */
 int    device_read_block       (Device * self, gpointer buffer, int * size);
-
-/* This is the reading equivalent of device_write_from_fd(). It will
- * read from the device from the current location until end of file,
- * and drains the results out into the specified fd. Returns FALSE if
- * there is a problem writing to the fd. */
 gboolean       device_read_to_fd       (Device * self,
                                        queue_fd_t *queue_fd);
-
-/* This function tells you what properties are supported by this device, and
- * when you are allowed to get and set them. The return value is an list of
- * DeviceProperty structs.  Do not free the resulting list. */
 const GSList * device_property_get_list        (Device * self);
-
-/* These functions get or set a particular property. The val should be
- * compatible with the DevicePropertyBase associated with the given
- * DevicePropertyId, and these functions should only be called when
- * DeviceProperty.access says it is OK. Otherwise you will get an error and not
- * the tasty property action you wanted.
- *
- * All device_property_get_ex parameters but the first two are output
- * parameters, and can be left NULL if you are not interested in their value.
- * If you only need the value, use the simpler device_property_get macro. */
-
 gboolean       device_property_get_ex  (Device * self,
                                          DevicePropertyId id,
                                          GValue * val,
@@ -414,7 +315,6 @@ gboolean    device_property_get_ex  (Device * self,
                                         PropertySource *source);
 #define                device_property_get(self, id, val) \
     device_property_get_ex((self), (id), (val), NULL, NULL)
-
 gboolean       device_property_set_ex  (Device * self,
                                          DevicePropertyId id,
                                          GValue * val,
@@ -423,21 +323,20 @@ gboolean  device_property_set_ex  (Device * self,
 #define                device_property_set(self, id, val) \
     device_property_set_ex((self), (id), (val), \
            PROPERTY_SURETY_GOOD, PROPERTY_SOURCE_USER)
-
-/* On devices that support it (check PROPERTY_PARTIAL_DELETION),
- * this will free only the space associated with a particular file. 
- * This way, you can apply a different retention policy to every file
- * on the volume, appending new data at the end and recycling anywhere
- * in the middle -- even simultaneously (via different Device
- * handles)! Note that you generally can't recycle a file that is presently in
- * use (being read or written).
- *
- * To use this, open the device as DEVICE_MODE_APPEND. But you don't
- * have to call device_start_file(), unless you want to write some
- * data, too. */
 gboolean       device_recycle_file     (Device * self,
                                        guint filenum);
 
+gboolean       device_erase    (Device * self);
+gboolean       device_eject    (Device * self);
+
+#define device_directtcp_supported(self) (DEVICE_GET_CLASS((self))->directtcp_supported)
+gboolean device_listen(Device *self, gboolean for_writing, DirectTCPAddr **addrs);
+gboolean device_accept(Device *self, DirectTCPConnection **conn,
+                ProlongProc prolong, gpointer prolong_data);
+gboolean device_write_from_connection(Device *self, guint64 size, guint64 *actual_size);
+gboolean device_read_to_connection(Device *self, guint64 size, guint64 *actual_size);
+gboolean device_use_connection(Device *self, DirectTCPConnection *conn);
+
 /* Protected methods. Don't call these except in subclass implementations. */
 
 /* This method provides post-construction initalization once the
@@ -447,13 +346,14 @@ gboolean  device_recycle_file     (Device * self,
  * initilization to their parents. */
 void device_open_device (Device * self, char *device_name, char *device_type, char *device_node);
 
-/* Builds a proper header based on device block size possibilities.
- * If non-null, size is filled in with the number of bytes that should
- * be written.
- * If non-null, oneblock is filled in with TRUE if the header will fit
- * in a single Device block (FALSE otherwise). */
+/* Builds a proper header of between *size and self->block_size bytes.
+ * Returns NULL if the header does not fit in a single block.  The result
+ * must be free'd.  If size is NULL, the block size is used.
+ *
+ * If size is not NULL, *size is set to the actual size of the generated header.
+ */
 char * device_build_amanda_header(Device * self, const dumpfile_t * jobinfo,
-                                  int * size, gboolean * oneblock);
+                                  size_t *size);
 
 /* Does what you expect. You have to free the returned header. Ensures
    that self->volume_time matches the header written to tape. */