Imported Upstream version 3.3.3
[debian/amanda] / device-src / property.c
1 /*
2  * Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
3  *
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.
8  *
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
12  * for more details.
13  *
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
17  *
18  * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19  * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
20  */
21
22 #include "amanda.h"
23
24 #include "property.h"
25 #include "glib-util.h"
26
27 /*****
28  * Property-specific Types, etc.
29  */
30
31 static const GEnumValue _concurrency_paradigm_values[] = {
32         { CONCURRENCY_PARADIGM_EXCLUSIVE,
33           "CONCURRENCY_PARADIGM_EXCLUSIVE",
34           "exclusive" },
35         { CONCURRENCY_PARADIGM_SHARED_READ,
36           "CONCURRENCY_PARADIGM_SHARED_READ",
37           "shared-read" },
38         { CONCURRENCY_PARADIGM_RANDOM_ACCESS,
39           "CONCURRENCY_PARADIGM_RANDOM_ACCESS",
40           "random-access" },
41         { 0, NULL, NULL }
42 };
43
44 GType concurrency_paradigm_get_type (void) {
45     static GType type = 0;
46     if (G_UNLIKELY(type == 0)) {
47         type = g_enum_register_static ("ConcurrencyParadigm",
48                                        _concurrency_paradigm_values);
49     }
50     return type;
51 }
52
53 static const GEnumValue _streaming_requirement_values[] = {
54         { STREAMING_REQUIREMENT_NONE,
55           "STREAMING_REQUIREMENT_NONE",
56           "none" },
57         { STREAMING_REQUIREMENT_DESIRED,
58           "STREAMING_REQUIREMENT_DESIRED",
59           "desired" },
60         { STREAMING_REQUIREMENT_REQUIRED,
61           "STREAMING_REQUIREMENT_REQUIRED",
62           "required" },
63         { 0, NULL, NULL }
64 };
65
66 GType streaming_requirement_get_type (void) {
67     static GType type = 0;
68     if (G_UNLIKELY(type == 0)) {
69         type = g_enum_register_static ("StreamingRequirement",
70                                        _streaming_requirement_values);
71     }
72     return type;
73 }
74
75 static const GEnumValue _media_access_mode_values[] = {
76         { MEDIA_ACCESS_MODE_READ_ONLY,
77           "MEDIA_ACCESS_MODE_READ_ONLY",
78           (char *)"read-only" },
79         { MEDIA_ACCESS_MODE_WORM,
80           "MEDIA_ACCESS_MODE_WORM",
81           (char *)"write-once-read-many" },
82         { MEDIA_ACCESS_MODE_READ_WRITE,
83           "MEDIA_ACCESS_MODE_READ_WRITE",
84           (char *)"read-write" },
85         { MEDIA_ACCESS_MODE_WRITE_ONLY,
86           "MEDIA_ACCESS_MODE_WRITE_ONLY",
87           (char *)"write-many-read-never" },
88         { 0, NULL, NULL }
89 };
90
91 GType media_access_mode_get_type (void) {
92     static GType type = 0;
93     if (G_UNLIKELY(type == 0)) {
94         type = g_enum_register_static ("MediaAccessMode",
95                                        _media_access_mode_values);
96     }
97     return type;
98 }
99
100 /******
101  * Property registration and lookup
102  */
103
104 static GPtrArray *device_property_bases = NULL;
105 static GHashTable *device_property_bases_by_name = NULL;
106
107 DevicePropertyBase* device_property_get_by_id(DevicePropertyId id) {
108     if (!device_property_bases || id >= device_property_bases->len)
109         return NULL;
110
111     return g_ptr_array_index(device_property_bases, id);
112 }
113
114 DevicePropertyBase* device_property_get_by_name(const char *name) {
115     gpointer rv;
116
117     if (!device_property_bases_by_name)
118         return NULL;
119
120     rv = g_hash_table_lookup(device_property_bases_by_name, name);
121     if (rv)
122         return (DevicePropertyBase *)rv;
123
124     return NULL;
125 }
126
127 #define toupper_and_underscore(c) (((c)=='-')? '_' : g_ascii_toupper((c)))
128 static guint
129 device_property_hash(
130         gconstpointer key)
131 {
132     /* modified version of glib's hash function, copyright
133      * GLib Team and others 1997-2000. */
134     const char *p = key;
135     guint h = toupper_and_underscore(*p);
136
137     if (h)
138         for (p += 1; *p != '\0'; p++)
139             h = (h << 5) - h + toupper_and_underscore(*p);
140
141     return h;
142 }
143
144 static gboolean
145 device_property_equal(
146         gconstpointer v1,
147         gconstpointer v2)
148 {
149     const char *s1 = v1, *s2 = v2;
150
151     while (*s1 && *s2) {
152         if (toupper_and_underscore(*s1) != toupper_and_underscore(*s2))
153             return FALSE;
154         s1++, s2++;
155     }
156     if (*s1 || *s2)
157         return FALSE;
158
159     return TRUE;
160 }
161
162 void
163 device_property_fill_and_register(DevicePropertyBase *base,
164                     GType type, const char * name, const char * desc) {
165
166     /* create the hash table and array if necessary */
167     if (!device_property_bases) {
168         device_property_bases = g_ptr_array_new();
169         device_property_bases_by_name = g_hash_table_new(device_property_hash, device_property_equal);
170     }
171
172     /* check for a duplicate */
173     if (device_property_get_by_name(name)) {
174         g_critical("A property named '%s' already exists!", name);
175     }
176
177     /* allocate space for this DPB and fill it in */
178     base->ID = device_property_bases->len;
179     base->type = type;
180     base->name = name; /* no strdup -- it's statically allocated */
181     base->description = desc; /* ditto */
182
183     /* add it to the array and hash table; note that its array index and its
184      * ID are the same. */
185     g_ptr_array_add(device_property_bases, base);
186     g_hash_table_insert(device_property_bases_by_name, (gpointer)name, (gpointer)base);
187 }
188
189 /******
190  * Initialization
191  */
192
193 void device_property_init(void) {
194     device_property_fill_and_register(&device_property_concurrency,
195                                       CONCURRENCY_PARADIGM_TYPE, "concurrency",
196       "Supported concurrency mode (none, multiple readers, multiple writers)");
197     device_property_fill_and_register(&device_property_streaming,
198                                       STREAMING_REQUIREMENT_TYPE, "streaming",
199       "Streaming desirability (unnecessary, desired, required)");
200     device_property_fill_and_register(&device_property_compression,
201                                       G_TYPE_BOOLEAN, "compression",
202       "Is device performing data compression?");
203     device_property_fill_and_register(&device_property_compression_rate,
204                                       G_TYPE_DOUBLE, "compression_rate",
205       "Compression rate, "
206           "averaged for some (currently undefined) period of time)");
207     device_property_fill_and_register(&device_property_block_size,
208                                       G_TYPE_INT, "block_size",
209                                       "Block size to use while writing.");
210     device_property_fill_and_register(&device_property_min_block_size,
211                                       G_TYPE_UINT, "min_block_size",
212       "Minimum supported blocking factor.");
213     device_property_fill_and_register(&device_property_max_block_size,
214                                       G_TYPE_UINT, "max_block_size",
215       "Maximum supported blocking factor.");
216     device_property_fill_and_register(&device_property_read_block_size,
217                                       G_TYPE_UINT, "read_block_size",
218       "Minimum size of a read for this device (maximum expected block size)");
219     device_property_fill_and_register(&device_property_appendable,
220                                       G_TYPE_BOOLEAN, "appendable",
221       "Does device support appending to previously-written media?");
222     device_property_fill_and_register(&device_property_canonical_name,
223                                       G_TYPE_STRING, "canonical_name",
224       "The most reliable device name to use to refer to this device.");
225     device_property_fill_and_register(&device_property_medium_access_type,
226                                       MEDIA_ACCESS_MODE_TYPE,
227                                       "medium_access_type",
228       "What kind of media (RO/WORM/RW/WORN) do we have here?");
229     device_property_fill_and_register(&device_property_partial_deletion,
230                                      G_TYPE_BOOLEAN, "partial_deletion",
231       "Does this device support recycling just part of a volume?" );
232     device_property_fill_and_register(&device_property_full_deletion,
233                                      G_TYPE_BOOLEAN, "full_deletion",
234       "Does this device support recycling the entire volume?" );
235     device_property_fill_and_register(&device_property_max_volume_usage,
236                                       G_TYPE_UINT64, "max_volume_usage",
237       "Artificial limit to data written to volume.");
238     device_property_fill_and_register(&device_property_enforce_max_volume_usage,
239                                       G_TYPE_BOOLEAN, "enforce_max_volume_usage",
240       "Does max_volume_usage enabled?");
241     device_property_fill_and_register(&device_property_verbose,
242                                      G_TYPE_BOOLEAN, "verbose",
243        "Should the device produce verbose output?");
244     device_property_fill_and_register(&device_property_comment,
245                                      G_TYPE_STRING, "comment",
246        "User-specified comment for the device");
247     device_property_fill_and_register(&device_property_leom,
248                                      G_TYPE_BOOLEAN, "leom",
249        "Does this device support LEOM?");
250 }
251
252 DevicePropertyBase device_property_concurrency;
253 DevicePropertyBase device_property_streaming;
254 DevicePropertyBase device_property_compression;
255 DevicePropertyBase device_property_compression_rate;
256 DevicePropertyBase device_property_block_size;
257 DevicePropertyBase device_property_min_block_size;
258 DevicePropertyBase device_property_max_block_size;
259 DevicePropertyBase device_property_read_block_size;
260 DevicePropertyBase device_property_appendable;
261 DevicePropertyBase device_property_canonical_name;
262 DevicePropertyBase device_property_medium_access_type;
263 DevicePropertyBase device_property_partial_deletion;
264 DevicePropertyBase device_property_full_deletion;
265 DevicePropertyBase device_property_max_volume_usage;
266 DevicePropertyBase device_property_enforce_max_volume_usage;
267 DevicePropertyBase device_property_comment;
268 DevicePropertyBase device_property_leom;
269 DevicePropertyBase device_property_verbose;