Imported Upstream version 3.3.2
[debian/amanda] / device-src / property.c
index 3980a3f6c2326b5f3e84a6b02a95ab6c3d0db38f..c951724e51d2a2fb3ae8344a4f8b900ec8f81183 100644 (file)
@@ -1,32 +1,37 @@
 /*
- * 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-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 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 "property.h"
+#include "glib-util.h"
+
+/*****
+ * Property-specific Types, etc.
+ */
 
 static const GEnumValue _concurrency_paradigm_values[] = {
         { CONCURRENCY_PARADIGM_EXCLUSIVE,
           "CONCURRENCY_PARADIGM_EXCLUSIVE",
           "exclusive" },
-        { CONCURRENCY_PARADIGM_SHARED_READ, 
+        { CONCURRENCY_PARADIGM_SHARED_READ,
           "CONCURRENCY_PARADIGM_SHARED_READ",
           "shared-read" },
         { CONCURRENCY_PARADIGM_RANDOM_ACCESS,
@@ -91,139 +96,98 @@ GType media_access_mode_get_type (void) {
     return type;
 }
 
-/* Copy function for GBoxed QualifiedSize. */
-static gpointer qualified_size_copy(gpointer source) {
-    gpointer rval = malloc(sizeof(QualifiedSize));
-    memcpy(rval, source, sizeof(QualifiedSize));
-    return rval;
-}
+/******
+ * Property registration and lookup
+ */
 
-GType qualified_size_get_type (void) {
-    static GType type = 0;
-    if (G_UNLIKELY(type == 0)) {
-        type = g_boxed_type_register_static ("QualifiedSize",
-                                             qualified_size_copy,
-                                             free);
-    }
-    return type;
-}
+static GPtrArray *device_property_bases = NULL;
+static GHashTable *device_property_bases_by_name = NULL;
 
-static const GFlagsValue _feature_support_flags_values[] = {
-    { FEATURE_STATUS_ENABLED,
-      "FEATURE_STATUS_ENABLED",
-      "enabled" },
-    { FEATURE_STATUS_DISABLED,
-      "FEATURE_STATUS_DISABLED",
-      "disabled" },
-    { FEATURE_SURETY_BAD,
-      "FEATURE_SURETY_BAD",
-      "bad" },
-    { FEATURE_SURETY_GOOD,
-      "FEATURE_SURETY_GOOD",
-      "good" },
-    { FEATURE_SOURCE_DEFAULT,
-      "FEATURE_SOURCE_DEFAULT",
-      "default" },
-    { FEATURE_SOURCE_DETECTED,
-      "FEATURE_SOURCE_DETECTED",
-      "detected" },
-    { FEATURE_SOURCE_USER,
-      "FEATURE_SOURCE_USER",
-      "user"},
-    { 0, NULL, NULL }
-};
+DevicePropertyBase* device_property_get_by_id(DevicePropertyId id) {
+    if (!device_property_bases || id >= device_property_bases->len)
+       return NULL;
 
-GType feature_support_get_type (void) {
-    static GType type = 0;
-    if (G_UNLIKELY(type == 0)) {
-        type = g_flags_register_static ("FeatureSupportFlags",
-                                        _feature_support_flags_values);
-    }
-    return type;
+    return g_ptr_array_index(device_property_bases, id);
 }
 
-gboolean feature_support_flags_is_valid(FeatureSupportFlags f) {
-    int status = 0, surety = 0, source = 0;
+DevicePropertyBase* device_property_get_by_name(const char *name) {
+    gpointer rv;
 
-    if (f & FEATURE_STATUS_ENABLED)
-        status ++;
-    if (f & FEATURE_STATUS_DISABLED)
-        status ++;
-    if (f & FEATURE_SURETY_BAD)
-        surety ++;
-    if (f & FEATURE_SURETY_GOOD)
-        surety ++;
-    if (f & FEATURE_SOURCE_DEFAULT)
-        source ++;
-    if (f & FEATURE_SOURCE_DETECTED)
-        source ++;
-    if (f & FEATURE_SOURCE_USER)
-        source ++;
+    if (!device_property_bases_by_name)
+       return NULL;
 
-    return (!(f & ~FEATURE_SUPPORT_FLAGS_MASK) &&
-            status == 1  &&  surety == 1  &&  source == 1);
-}
+    rv = g_hash_table_lookup(device_property_bases_by_name, name);
+    if (rv)
+       return (DevicePropertyBase *)rv;
 
-static GSList* device_property_base_list = NULL;
+    return NULL;
+}
 
-const DevicePropertyBase* device_property_get_by_id(DevicePropertyId id) {
-    GSList *iter;
+#define toupper_and_underscore(c) (((c)=='-')? '_' : g_ascii_toupper((c)))
+static guint
+device_property_hash(
+       gconstpointer key)
+{
+    /* modified version of glib's hash function, copyright
+     * GLib Team and others 1997-2000. */
+    const char *p = key;
+    guint h = toupper_and_underscore(*p);
 
-    iter = device_property_base_list;
-    while (iter != NULL) {
-        DevicePropertyBase* rval = (DevicePropertyBase*)(iter->data);
-        if (rval->ID == id) {
-            return rval;
-        }
-        iter = g_slist_next(iter);
-    }
+    if (h)
+       for (p += 1; *p != '\0'; p++)
+           h = (h << 5) - h + toupper_and_underscore(*p);
 
-    return NULL;
+    return h;
 }
 
-const DevicePropertyBase* device_property_get_by_name(const char *name) {
-    GSList *iter = device_property_base_list;
-
-    g_return_val_if_fail(name != NULL, NULL);
+static gboolean
+device_property_equal(
+       gconstpointer v1,
+       gconstpointer v2)
+{
+    const char *s1 = v1, *s2 = v2;
 
-    while (iter != NULL) {
-        DevicePropertyBase* rval = (DevicePropertyBase*)(iter->data);
-        if (strcasecmp(rval->name, name) == 0) {
-            return rval;
-        }
-        iter = g_slist_next(iter);
+    while (*s1 && *s2) {
+       if (toupper_and_underscore(*s1) != toupper_and_underscore(*s2))
+           return FALSE;
+       s1++, s2++;
     }
+    if (*s1 || *s2)
+       return FALSE;
 
-    return NULL;
+    return TRUE;
 }
 
-DevicePropertyId device_property_register(DevicePropertyBase* base) {
-    static guint id = 0;
-    g_assert(base != NULL);
-    g_assert(base->ID == -1);
-    g_assert(base->name != NULL);
-    g_assert(base->description != NULL);
-    
-    base->ID = id++;
+void
+device_property_fill_and_register(DevicePropertyBase *base,
+                   GType type, const char * name, const char * desc) {
 
-    device_property_base_list = g_slist_prepend(device_property_base_list,
-                                                base);
-    return id;
-}
+    /* create the hash table and array if necessary */
+    if (!device_property_bases) {
+       device_property_bases = g_ptr_array_new();
+       device_property_bases_by_name = g_hash_table_new(device_property_hash, device_property_equal);
+    }
+
+    /* check for a duplicate */
+    if (device_property_get_by_name(name)) {
+       g_critical("A property named '%s' already exists!", name);
+    }
 
-/* Does the same thing, but fills in a new DevicePropertyBase. */
-static void
-device_property_fill_and_register(DevicePropertyBase * base,
-                                  GType type,
-                                  const char * name,
-                                  const char * desc) {
+    /* allocate space for this DPB and fill it in */
+    base->ID = device_property_bases->len;
     base->type = type;
-    base->name = name;
-    base->description = desc;
-    base->ID = -1;
-    device_property_register(base);
+    base->name = name; /* no strdup -- it's statically allocated */
+    base->description = desc; /* ditto */
+
+    /* add it to the array and hash table; note that its array index and its
+     * ID are the same. */
+    g_ptr_array_add(device_property_bases, base);
+    g_hash_table_insert(device_property_bases_by_name, (gpointer)name, (gpointer)base);
 }
 
+/******
+ * Initialization
+ */
 
 void device_property_init(void) {
     device_property_fill_and_register(&device_property_concurrency,
@@ -241,13 +205,16 @@ void device_property_init(void) {
           "averaged for some (currently undefined) period of time)");
     device_property_fill_and_register(&device_property_block_size,
                                       G_TYPE_INT, "block_size",
-                                      "Device blocking factor in bytes.");
+                                      "Block size to use while writing.");
     device_property_fill_and_register(&device_property_min_block_size,
                                       G_TYPE_UINT, "min_block_size",
       "Minimum supported blocking factor.");
     device_property_fill_and_register(&device_property_max_block_size,
                                       G_TYPE_UINT, "max_block_size",
       "Maximum supported blocking factor.");
+    device_property_fill_and_register(&device_property_read_block_size,
+                                      G_TYPE_UINT, "read_block_size",
+      "Minimum size of a read for this device (maximum expected block size)");
     device_property_fill_and_register(&device_property_appendable,
                                       G_TYPE_BOOLEAN, "appendable",
       "Does device support appending to previously-written media?");
@@ -261,52 +228,24 @@ void device_property_init(void) {
     device_property_fill_and_register(&device_property_partial_deletion,
                                      G_TYPE_BOOLEAN, "partial_deletion",
       "Does this device support recycling just part of a volume?" );
-    device_property_fill_and_register(&device_property_free_space,
-                                      QUALIFIED_SIZE_TYPE, "free_space",
-      "Remaining capacity of the device.");
+    device_property_fill_and_register(&device_property_full_deletion,
+                                     G_TYPE_BOOLEAN, "full_deletion",
+      "Does this device support recycling the entire volume?" );
     device_property_fill_and_register(&device_property_max_volume_usage,
                                       G_TYPE_UINT64, "max_volume_usage",
       "Artificial limit to data written to volume.");
-    device_property_fill_and_register(&device_property_fsf,
-                                      FEATURE_SUPPORT_FLAGS_TYPE, "fsf",
-      "Does this drive support the MTFSF command?");
-    device_property_fill_and_register(&device_property_bsf,
-                                      FEATURE_SUPPORT_FLAGS_TYPE, "bsf",
-      "Does this drive support the MTBSF command?" );
-    device_property_fill_and_register(&device_property_fsr,
-                                      FEATURE_SUPPORT_FLAGS_TYPE, "fsr",
-      "Does this drive support the MTFSR command?");
-    device_property_fill_and_register(&device_property_bsr,
-                                      FEATURE_SUPPORT_FLAGS_TYPE, "bsr",
-      "Does this drive support the MTBSR command?");
-    /* FIXME: Is this feature even useful? */
-    device_property_fill_and_register(&device_property_eom,
-                                      FEATURE_SUPPORT_FLAGS_TYPE, "eom",
-      "Does this drive support the MTEOM command?");
-    device_property_fill_and_register(&device_property_bsf_after_eom,
-                                      FEATURE_SUPPORT_FLAGS_TYPE,
-                                      "bsf_after_eom",
-      "Does this drive require an MTBSF after MTEOM in order to append?" );
-    device_property_fill_and_register(&device_property_final_filemarks,
-                                      G_TYPE_UINT, "final_filemarks",
-      "How many filemarks to write after the last tape file?" );
-    device_property_fill_and_register(&device_property_read_buffer_size,
-                                      G_TYPE_UINT, "read_buffer_size",
-      "What buffer size should be used for reading?");
-    device_property_fill_and_register(&device_property_s3_secret_key,
-                                      G_TYPE_STRING, "s3_secret_key",
-       "Secret access key to authenticate with Amazon S3");
-    device_property_fill_and_register(&device_property_s3_access_key,
-                                      G_TYPE_STRING, "s3_access_key",
-       "Access key ID to authenticate with Amazon S3");
-#ifdef WANT_DEVPAY
-    device_property_fill_and_register(&device_property_s3_user_token,
-                                      G_TYPE_STRING, "s3_user_token",
-       "User token for authentication Amazon devpay requests");
-#endif
+    device_property_fill_and_register(&device_property_enforce_max_volume_usage,
+                                      G_TYPE_BOOLEAN, "enforce_max_volume_usage",
+      "Does max_volume_usage enabled?");
     device_property_fill_and_register(&device_property_verbose,
                                      G_TYPE_BOOLEAN, "verbose",
        "Should the device produce verbose output?");
+    device_property_fill_and_register(&device_property_comment,
+                                     G_TYPE_STRING, "comment",
+       "User-specified comment for the device");
+    device_property_fill_and_register(&device_property_leom,
+                                     G_TYPE_BOOLEAN, "leom",
+       "Does this device support LEOM?");
 }
 
 DevicePropertyBase device_property_concurrency;
@@ -316,21 +255,14 @@ DevicePropertyBase device_property_compression_rate;
 DevicePropertyBase device_property_block_size;
 DevicePropertyBase device_property_min_block_size;
 DevicePropertyBase device_property_max_block_size;
+DevicePropertyBase device_property_read_block_size;
 DevicePropertyBase device_property_appendable;
 DevicePropertyBase device_property_canonical_name;
 DevicePropertyBase device_property_medium_access_type;
 DevicePropertyBase device_property_partial_deletion;
-DevicePropertyBase device_property_free_space;
+DevicePropertyBase device_property_full_deletion;
 DevicePropertyBase device_property_max_volume_usage;
-DevicePropertyBase device_property_fsf;
-DevicePropertyBase device_property_bsf;
-DevicePropertyBase device_property_fsr;
-DevicePropertyBase device_property_bsr;
-DevicePropertyBase device_property_eom;
-DevicePropertyBase device_property_bsf_after_eom;
-DevicePropertyBase device_property_final_filemarks;
-DevicePropertyBase device_property_read_buffer_size;
-DevicePropertyBase device_property_s3_access_key;
-DevicePropertyBase device_property_s3_secret_key;
-DevicePropertyBase device_property_s3_user_token;
+DevicePropertyBase device_property_enforce_max_volume_usage;
+DevicePropertyBase device_property_comment;
+DevicePropertyBase device_property_leom;
 DevicePropertyBase device_property_verbose;