Imported Upstream version 2.6.1
[debian/amanda] / device-src / property.c
index 3980a3f6c2326b5f3e84a6b02a95ab6c3d0db38f..275cc8088bf0871a2324945466e9fae6b2db9467 100644 (file)
@@ -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 
  * 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 "property.h"
+#include "glib-util.h"
+
+/*****
+ * Property-specific Types, etc.
+ */
 
 static const GEnumValue _concurrency_paradigm_values[] = {
         { CONCURRENCY_PARADIGM_EXCLUSIVE,
@@ -93,7 +98,7 @@ GType media_access_mode_get_type (void) {
 
 /* Copy function for GBoxed QualifiedSize. */
 static gpointer qualified_size_copy(gpointer source) {
-    gpointer rval = malloc(sizeof(QualifiedSize));
+    gpointer rval = g_new(QualifiedSize, 1);
     memcpy(rval, source, sizeof(QualifiedSize));
     return rval;
 }
@@ -108,122 +113,98 @@ GType qualified_size_get_type (void) {
     return type;
 }
 
-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 }
-};
+/******
+ * Property registration and lookup
+ */
 
-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;
-}
+static GPtrArray *device_property_bases = NULL;
+static GHashTable *device_property_bases_by_name = NULL;
 
-gboolean feature_support_flags_is_valid(FeatureSupportFlags f) {
-    int status = 0, surety = 0, source = 0;
-
-    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 ++;
-
-    return (!(f & ~FEATURE_SUPPORT_FLAGS_MASK) &&
-            status == 1  &&  surety == 1  &&  source == 1);
+DevicePropertyBase* device_property_get_by_id(DevicePropertyId id) {
+    if (!device_property_bases || id >= device_property_bases->len)
+       return NULL;
+
+    return g_ptr_array_index(device_property_bases, id);
 }
 
-static GSList* device_property_base_list = NULL;
+DevicePropertyBase* device_property_get_by_name(const char *name) {
+    gpointer rv;
 
-const DevicePropertyBase* device_property_get_by_id(DevicePropertyId id) {
-    GSList *iter;
+    if (!device_property_bases_by_name)
+       return NULL;
 
-    iter = device_property_base_list;
-    while (iter != NULL) {
-        DevicePropertyBase* rval = (DevicePropertyBase*)(iter->data);
-        if (rval->ID == id) {
-            return rval;
-        }
-        iter = g_slist_next(iter);
-    }
+    rv = g_hash_table_lookup(device_property_bases_by_name, name);
+    if (rv)
+       return (DevicePropertyBase *)rv;
 
     return NULL;
 }
 
-const DevicePropertyBase* device_property_get_by_name(const char *name) {
-    GSList *iter = device_property_base_list;
+#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);
+
+    if (h)
+       for (p += 1; *p != '\0'; p++)
+           h = (h << 5) - h + toupper_and_underscore(*p);
+
+    return h;
+}
 
-    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++;
-
-    device_property_base_list = g_slist_prepend(device_property_base_list,
-                                                base);
-    return id;
-}
+void
+device_property_fill_and_register(DevicePropertyBase *base,
+                   GType type, const char * name, const char * desc) {
+
+    /* 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);
+    }
 
-/* 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) {
+    /* check for a duplicate */
+    if (device_property_get_by_name(name)) {
+       g_critical("A property named '%s' already exists!", name);
+    }
+
+    /* 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 +222,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_buffer_size,
+                                      G_TYPE_UINT, "read_buffer_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?");
@@ -267,43 +251,6 @@ void device_property_init(void) {
     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_verbose,
                                      G_TYPE_BOOLEAN, "verbose",
        "Should the device produce verbose output?");
@@ -316,21 +263,11 @@ 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_buffer_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_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_verbose;