tizen 2.3 release
[external/buxton.git] / src / db / memory.c
1 /*
2  * This file is part of buxton.
3  *
4  * Copyright (C) 2013 Intel Corporation
5  *
6  * buxton is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1
9  * of the License, or (at your option) any later version.
10  */
11
12 #ifdef HAVE_CONFIG_H
13         #include "config.h"
14 #endif
15
16 #include <assert.h>
17 #include <errno.h>
18
19 #include "hashmap.h"
20 #include "log.h"
21 #include "buxton.h"
22 #include "backend.h"
23 #include "util.h"
24
25 /**
26  * Memory Database Module
27  *
28  * Used for quick testing and debugging of Buxton, to ensure protocol
29  * and direct access are working as intended.
30  * Note this is not persistent.
31  */
32
33
34 static Hashmap *_resources;
35
36 /* Return existing hashmap or create new hashmap on the fly */
37 static Hashmap *_db_for_resource(BuxtonLayer *layer)
38 {
39         Hashmap *db;
40         char *name = NULL;
41         int r;
42
43         assert(layer);
44         assert(_resources);
45
46         if (layer->type == LAYER_USER) {
47                 r = asprintf(&name, "%s-%d", layer->name.value, layer->uid);
48         } else {
49                 r = asprintf(&name, "%s", layer->name.value);
50         }
51         if (r == -1) {
52                 return NULL;
53         }
54
55         db = hashmap_get(_resources, name);
56         if (!db) {
57                 db = hashmap_new(string_hash_func, string_compare_func);
58                 hashmap_put(_resources, name, db);
59         } else {
60                 free(name);
61         }
62
63         return db;
64 }
65
66 static int set_value(BuxtonLayer *layer, _BuxtonKey *key, BuxtonData *data,
67                       BuxtonString *label)
68 {
69         Hashmap *db;
70         BuxtonArray *array = NULL;
71         BuxtonArray *stored;
72         BuxtonData *data_copy = NULL;
73         BuxtonData *d;
74         BuxtonString *label_copy = NULL;
75         BuxtonString *l;
76         char *full_key = NULL;
77         char *k;
78         int ret;
79
80         assert(layer);
81         assert(key);
82         assert(label);
83
84         db = _db_for_resource(layer);
85         if (!db) {
86                 ret = ENOENT;
87                 goto end;
88         }
89
90         if (key->name.value) {
91                 if (asprintf(&full_key, "%s%s", key->group.value, key->name.value) == -1) {
92                         abort();
93                 }
94         } else {
95                 full_key = strdup(key->group.value);
96                 if (!full_key) {
97                         abort();
98                 }
99         }
100
101         if (!data) {
102                 stored = (BuxtonArray *)hashmap_get(db, full_key);
103                 if (!stored) {
104                         ret = ENOENT;
105                         free(full_key);
106                         goto end;
107                 }
108                 data = buxton_array_get(stored, 0);
109         }
110
111         array = buxton_array_new();
112         if (!array) {
113                 abort();
114         }
115         data_copy = malloc0(sizeof(BuxtonData));
116         if (!data_copy) {
117                 abort();
118         }
119         label_copy = malloc0(sizeof(BuxtonString));
120         if (!label_copy) {
121                 abort();
122         }
123
124         if (!buxton_data_copy(data, data_copy)) {
125                 abort();
126         }
127         if (!buxton_string_copy(label, label_copy)) {
128                 abort();
129         }
130         if (!buxton_array_add(array, data_copy)) {
131                 abort();
132         }
133         if (!buxton_array_add(array, label_copy)) {
134                 abort();
135         }
136         if (!buxton_array_add(array, full_key)) {
137                 abort();
138         }
139
140         ret = hashmap_put(db, full_key, array);
141         if (ret != 1) {
142                 if (ret == -ENOMEM) {
143                         abort();
144                 }
145                 /* remove the old value */
146                 stored = (BuxtonArray *)hashmap_remove(db, full_key);
147                 assert(stored);
148
149                 /* free the data */
150                 d = buxton_array_get(stored, 0);
151                 data_free(d);
152                 l = buxton_array_get(stored, 1);
153                 string_free(l);
154                 k = buxton_array_get(stored, 2);
155                 free(k);
156                 buxton_array_free(&stored, NULL);
157                 ret = hashmap_put(db, full_key, array);
158                 if (ret != 1) {
159                         abort();
160                 }
161         }
162
163         ret = 0;
164
165 end:
166         return ret;
167 }
168
169 static int get_value(BuxtonLayer *layer, _BuxtonKey *key, BuxtonData *data,
170                       BuxtonString *label)
171 {
172         Hashmap *db;
173         BuxtonArray *stored;
174         BuxtonData *d;
175         BuxtonString *l;
176         char *full_key = NULL;
177         int ret;
178
179         assert(layer);
180         assert(key);
181         assert(label);
182         assert(data);
183
184         db = _db_for_resource(layer);
185         if (!db) {
186                 /*
187                  * Set negative here to indicate layer not found
188                  * rather than key not found, optimization for
189                  * set value
190                  */
191                 ret = -ENOENT;
192                 goto end;
193         }
194
195         if (key->name.value) {
196                 if (asprintf(&full_key, "%s%s", key->group.value, key->name.value) == -1) {
197                         abort();
198                 }
199         } else {
200                 full_key = strdup(key->group.value);
201                 if (!full_key) {
202                         abort();
203                 }
204         }
205
206         stored = (BuxtonArray *)hashmap_get(db, full_key);
207         if (!stored) {
208                 ret = ENOENT;
209                 goto end;
210         }
211         d = buxton_array_get(stored, 0);
212         if (d->type != key->type) {
213                 ret = EINVAL;
214                 goto end;
215         }
216
217         if (!buxton_data_copy(d, data)) {
218                 abort();
219         }
220
221         l = buxton_array_get(stored, 1);
222         if (!buxton_string_copy(l, label)) {
223                 abort();
224         }
225
226         ret = 0;
227
228 end:
229         free(full_key);
230         return ret;
231 }
232
233 static int unset_value(BuxtonLayer *layer,
234                         _BuxtonKey *key,
235                         __attribute__((unused)) BuxtonData *data,
236                         __attribute__((unused)) BuxtonString *label)
237 {
238         Hashmap *db;
239         BuxtonArray *stored;
240         BuxtonData *d;
241         BuxtonString *l;
242         char *full_key = NULL;
243         char *k;
244         int ret;
245
246         assert(layer);
247         assert(key);
248
249         db = _db_for_resource(layer);
250         if (!db) {
251                 ret = ENOENT;
252                 goto end;
253         }
254
255         if (key->name.value) {
256                 if (asprintf(&full_key, "%s%s", key->group.value, key->name.value) == -1) {
257                         abort();
258                 }
259         } else {
260                 full_key = strdup(key->group.value);
261                 if (!full_key) {
262                         abort();
263                 }
264         }
265
266         /* test if the value exists */
267         stored = (BuxtonArray *)hashmap_remove(db, full_key);
268         if (!stored) {
269                 ret = ENOENT;
270                 goto end;
271         }
272
273         /* free the data */
274         d = buxton_array_get(stored, 0);
275         data_free(d);
276         l = buxton_array_get(stored, 1);
277         string_free(l);
278         k = buxton_array_get(stored, 2);
279         free(k);
280         buxton_array_free(&stored, NULL);
281
282         ret = 0;
283
284 end:
285         free(full_key);
286         return ret;
287 }
288
289 _bx_export_ void buxton_module_destroy(void)
290 {
291         const char *key1, *key2;
292         Iterator iteratori, iteratoro;
293         Hashmap *map;
294         BuxtonArray *array;
295         BuxtonData *d;
296         BuxtonString *l;
297
298         /* free all hashmaps */
299         HASHMAP_FOREACH_KEY(map, key1, _resources, iteratoro) {
300                 HASHMAP_FOREACH_KEY(array, key2, map, iteratori) {
301                         hashmap_remove(map, key2);
302                         d = buxton_array_get(array, 0);
303                         data_free(d);
304                         l = buxton_array_get(array, 1);
305                         string_free(l);
306                         buxton_array_free(&array, NULL);
307                 }
308                 hashmap_remove(_resources, key1);
309                 hashmap_free(map);
310                 free((void *)key1);
311                 map = NULL;
312         }
313         hashmap_free(_resources);
314         _resources = NULL;
315 }
316
317 _bx_export_ bool buxton_module_init(BuxtonBackend *backend)
318 {
319
320         assert(backend);
321
322         /* Point the struct methods back to our own */
323         backend->set_value = &set_value;
324         backend->get_value = &get_value;
325         backend->unset_value = &unset_value;
326         backend->list_keys = NULL;
327         backend->create_db = NULL;
328
329         _resources = hashmap_new(string_hash_func, string_compare_func);
330         if (!_resources) {
331                 abort();
332         }
333         return true;
334 }
335
336 /*
337  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
338  *
339  * Local variables:
340  * c-basic-offset: 8
341  * tab-width: 8
342  * indent-tabs-mode: t
343  * End:
344  *
345  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
346  * :indentSize=8:tabSize=8:noTabs=false:
347  */