]> git.proxmox.com Git - mirror_corosync.git/blob - exec/icmap.c
icmap: Add function to return global icmap
[mirror_corosync.git] / exec / icmap.c
1 /*
2 * Copyright (c) 2011 Red Hat, Inc.
3 *
4 * All rights reserved.
5 *
6 * Author: Jan Friesse (jfriesse@redhat.com)
7 *
8 * This software licensed under BSD license, the text of which follows:
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 *
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * - Neither the name of the Red Hat, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <config.h>
36
37 #include <string.h>
38 #include <stdio.h>
39
40 #include <corosync/corotypes.h>
41
42 #include <qb/qbdefs.h>
43 #include <corosync/list.h>
44 #include <corosync/icmap.h>
45
46 #define ICMAP_MAX_VALUE_LEN (16*1024)
47
48 struct icmap_item {
49 char *key_name;
50 icmap_value_types_t type;
51 size_t value_len;
52 char value[];
53 };
54
55 struct icmap_map {
56 qb_map_t *qb_map;
57 };
58
59 static icmap_map_t icmap_global_map;
60
61 struct icmap_track {
62 char *key_name;
63 int32_t track_type;
64 icmap_notify_fn_t notify_fn;
65 void *user_data;
66 struct list_head list;
67 };
68
69 struct icmap_ro_access_item {
70 char *key_name;
71 int prefix;
72 struct list_head list;
73 };
74
75 DECLARE_LIST_INIT(icmap_ro_access_item_list_head);
76 DECLARE_LIST_INIT(icmap_track_list_head);
77
78 /*
79 * Static functions declarations
80 */
81
82 /*
83 * Check if key_name is valid icmap key name. Returns 0 on success, and -1 on fail
84 */
85 static int icmap_check_key_name(const char *key_name);
86
87 /*
88 * Check that value with given type has correct length value_len. Returns 0 on success,
89 * and -1 on fail
90 */
91 static int icmap_check_value_len(const void *value, size_t value_len, icmap_value_types_t type);
92
93 /*
94 * Returns length of value of given type, or 0 for string and binary data type
95 */
96 static size_t icmap_get_valuetype_len(icmap_value_types_t type);
97
98 /*
99 * Converts track type of icmap to qb
100 */
101 static int32_t icmap_tt_to_qbtt(int32_t track_type);
102
103 /*
104 * Convert track type of qb to icmap
105 */
106 static int32_t icmap_qbtt_to_tt(int32_t track_type);
107
108 /*
109 * Checks if item has same value as value with value_len and given type. Returns 0 if not, otherwise !0.
110 */
111 static int icmap_item_eq(const struct icmap_item *item, const void *value, size_t value_len, icmap_value_types_t type);
112
113 /*
114 * Checks if given character is valid in key name. Returns 0 if not, otherwise !0.
115 */
116 static int icmap_is_valid_name_char(char c);
117
118 /*
119 * Helper for getting integer and float value with given type for key key_name and store it in value.
120 */
121 static cs_error_t icmap_get_int_r(
122 const icmap_map_t map,
123 const char *key_name,
124 void *value,
125 icmap_value_types_t type);
126
127 /*
128 * Function implementation
129 */
130 static int32_t icmap_tt_to_qbtt(int32_t track_type)
131 {
132 int32_t res = 0;
133
134 if (track_type & ICMAP_TRACK_DELETE) {
135 res |= QB_MAP_NOTIFY_DELETED;
136 }
137
138 if (track_type & ICMAP_TRACK_MODIFY) {
139 res |= QB_MAP_NOTIFY_REPLACED;
140 }
141
142 if (track_type & ICMAP_TRACK_ADD) {
143 res |= QB_MAP_NOTIFY_INSERTED;
144 }
145
146 if (track_type & ICMAP_TRACK_PREFIX) {
147 res |= QB_MAP_NOTIFY_RECURSIVE;
148 }
149
150 return (res);
151 }
152
153 static int32_t icmap_qbtt_to_tt(int32_t track_type)
154 {
155 int32_t res = 0;
156
157 if (track_type & QB_MAP_NOTIFY_DELETED) {
158 res |= ICMAP_TRACK_DELETE;
159 }
160
161 if (track_type & QB_MAP_NOTIFY_REPLACED) {
162 res |= ICMAP_TRACK_MODIFY;
163 }
164
165 if (track_type & QB_MAP_NOTIFY_INSERTED) {
166 res |= ICMAP_TRACK_ADD;
167 }
168
169 if (track_type & QB_MAP_NOTIFY_RECURSIVE) {
170 res |= ICMAP_TRACK_PREFIX;
171 }
172
173 return (res);
174 }
175
176 static void icmap_map_free_cb(uint32_t event,
177 char* key, void* old_value,
178 void* value, void* user_data)
179 {
180 struct icmap_item *item = (struct icmap_item *)old_value;
181
182 /*
183 * value == old_value -> fast_adjust_int was used, don't free data
184 */
185 if (item != NULL && value != old_value) {
186 free(item->key_name);
187 free(item);
188 }
189 }
190
191 cs_error_t icmap_init_r(icmap_map_t *result)
192 {
193 int32_t err;
194
195 *result = malloc(sizeof(struct icmap_map));
196 if (*result == NULL) {
197 return (CS_ERR_NO_MEMORY);
198 }
199
200 (*result)->qb_map = qb_trie_create();
201 if ((*result)->qb_map == NULL)
202 return (CS_ERR_INIT);
203
204 err = qb_map_notify_add((*result)->qb_map, NULL, icmap_map_free_cb, QB_MAP_NOTIFY_FREE, NULL);
205
206 return (qb_to_cs_error(err));
207 }
208
209 cs_error_t icmap_init(void)
210 {
211 return (icmap_init_r(&icmap_global_map));
212 }
213
214 static void icmap_set_ro_access_free(void)
215 {
216 struct list_head *iter = icmap_ro_access_item_list_head.next;
217 struct icmap_ro_access_item *icmap_ro_ai;
218
219 while (iter != &icmap_ro_access_item_list_head) {
220 icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
221 list_del(&icmap_ro_ai->list);
222 free(icmap_ro_ai->key_name);
223 free(icmap_ro_ai);
224 iter = icmap_ro_access_item_list_head.next;
225 }
226 }
227
228 static void icmap_del_all_track(void)
229 {
230 struct list_head *iter = icmap_track_list_head.next;
231 struct icmap_track *icmap_track;
232
233 while (iter != &icmap_track_list_head) {
234 icmap_track = list_entry(iter, struct icmap_track, list);
235 icmap_track_delete(icmap_track);
236 iter = icmap_track_list_head.next;
237 }
238 }
239
240 void icmap_fini_r(const icmap_map_t map)
241 {
242
243 qb_map_destroy(map->qb_map);
244 free(map);
245
246 return;
247 }
248
249 void icmap_fini(void)
250 {
251
252 icmap_del_all_track();
253 /*
254 * catch 22 warning:
255 * We need to drop this notify but we can't because it calls icmap_map_free_cb
256 * while destroying the tree to free icmap_item(s).
257 * -> qb_map_notify_del_2(icmap_map, NULL, icmap_map_free_cb, QB_MAP_NOTIFY_FREE, NULL);
258 * and we cannot call it after map_destroy. joy! :)
259 */
260 icmap_fini_r(icmap_global_map);
261 icmap_set_ro_access_free();
262
263 return ;
264 }
265
266 icmap_map_t icmap_get_global_map(void)
267 {
268
269 return (icmap_global_map);
270 }
271
272 static int icmap_is_valid_name_char(char c)
273 {
274 return ((c >= 'a' && c <= 'z') ||
275 (c >= 'A' && c <= 'Z') ||
276 (c >= '0' && c <= '9') ||
277 c == '.' || c == '_' || c == '-' || c == '/' || c == ':');
278 }
279
280 void icmap_convert_name_to_valid_name(char *key_name)
281 {
282 int i;
283
284 for (i = 0; i < strlen(key_name); i++) {
285 if (!icmap_is_valid_name_char(key_name[i])) {
286 key_name[i] = '_';
287 }
288 }
289 }
290
291 static int icmap_check_key_name(const char *key_name)
292 {
293 int i;
294
295 if ((strlen(key_name) < ICMAP_KEYNAME_MINLEN) || strlen(key_name) > ICMAP_KEYNAME_MAXLEN) {
296 return (-1);
297 }
298
299 for (i = 0; i < strlen(key_name); i++) {
300 if (!icmap_is_valid_name_char(key_name[i])) {
301 return (-1);
302 }
303 }
304
305 return (0);
306 }
307
308 static size_t icmap_get_valuetype_len(icmap_value_types_t type)
309 {
310 size_t res = 0;
311
312 switch (type) {
313 case ICMAP_VALUETYPE_INT8: res = sizeof(int8_t); break;
314 case ICMAP_VALUETYPE_UINT8: res = sizeof(uint8_t); break;
315 case ICMAP_VALUETYPE_INT16: res = sizeof(int16_t); break;
316 case ICMAP_VALUETYPE_UINT16: res = sizeof(uint16_t); break;
317 case ICMAP_VALUETYPE_INT32: res = sizeof(int32_t); break;
318 case ICMAP_VALUETYPE_UINT32: res = sizeof(uint32_t); break;
319 case ICMAP_VALUETYPE_INT64: res = sizeof(int64_t); break;
320 case ICMAP_VALUETYPE_UINT64: res = sizeof(uint64_t); break;
321 case ICMAP_VALUETYPE_FLOAT: res = sizeof(float); break;
322 case ICMAP_VALUETYPE_DOUBLE: res = sizeof(double); break;
323 case ICMAP_VALUETYPE_STRING:
324 case ICMAP_VALUETYPE_BINARY:
325 res = 0;
326 break;
327 }
328
329 return (res);
330 }
331
332 static int icmap_check_value_len(const void *value, size_t value_len, icmap_value_types_t type)
333 {
334
335 if (value_len > ICMAP_MAX_VALUE_LEN) {
336 return (-1);
337 }
338
339 if (type != ICMAP_VALUETYPE_STRING && type != ICMAP_VALUETYPE_BINARY) {
340 if (icmap_get_valuetype_len(type) == value_len) {
341 return (0);
342 } else {
343 return (-1);
344 }
345 }
346
347 if (type == ICMAP_VALUETYPE_STRING) {
348 if (value_len > strlen((const char *)value)) {
349 return (-1);
350 } else {
351 return (0);
352 }
353 }
354
355 return (0);
356 }
357
358 static int icmap_item_eq(const struct icmap_item *item, const void *value, size_t value_len, icmap_value_types_t type)
359 {
360 size_t ptr_len;
361
362 if (item->type != type) {
363 return (0);
364 }
365
366 if (item->type == ICMAP_VALUETYPE_STRING) {
367 ptr_len = strlen((const char *)value);
368 if (ptr_len > value_len) {
369 ptr_len = value_len;
370 }
371 ptr_len++;
372 } else {
373 ptr_len = value_len;
374 }
375
376 if (item->value_len == ptr_len) {
377 return (memcmp(item->value, value, value_len) == 0);
378 };
379
380 return (0);
381 }
382
383 cs_error_t icmap_set_r(
384 const icmap_map_t map,
385 const char *key_name,
386 const void *value,
387 size_t value_len,
388 icmap_value_types_t type)
389 {
390 struct icmap_item *item;
391 struct icmap_item *new_item;
392 size_t new_value_len;
393 size_t new_item_size;
394
395 if (value == NULL || key_name == NULL) {
396 return (CS_ERR_INVALID_PARAM);
397 }
398
399 if (icmap_check_value_len(value, value_len, type) != 0) {
400 return (CS_ERR_INVALID_PARAM);
401 }
402
403 item = qb_map_get(map->qb_map, key_name);
404 if (item != NULL) {
405 /*
406 * Check that key is really changed
407 */
408 if (icmap_item_eq(item, value, value_len, type)) {
409 return (CS_OK);
410 }
411 } else {
412 if (icmap_check_key_name(key_name) != 0) {
413 return (CS_ERR_NAME_TOO_LONG);
414 }
415 }
416
417 if (type == ICMAP_VALUETYPE_BINARY || type == ICMAP_VALUETYPE_STRING) {
418 if (type == ICMAP_VALUETYPE_STRING) {
419 new_value_len = strlen((const char *)value);
420 if (new_value_len > value_len) {
421 new_value_len = value_len;
422 }
423 new_value_len++;
424 } else {
425 new_value_len = value_len;
426 }
427 } else {
428 new_value_len = icmap_get_valuetype_len(type);
429 }
430
431 new_item_size = sizeof(struct icmap_item) + new_value_len;
432 new_item = malloc(new_item_size);
433 if (new_item == NULL) {
434 return (CS_ERR_NO_MEMORY);
435 }
436 memset(new_item, 0, new_item_size);
437
438 if (item == NULL) {
439 new_item->key_name = strdup(key_name);
440 if (new_item->key_name == NULL) {
441 free(new_item);
442 return (CS_ERR_NO_MEMORY);
443 }
444 } else {
445 new_item->key_name = item->key_name;
446 item->key_name = NULL;
447 }
448
449 new_item->type = type;
450 new_item->value_len = new_value_len;
451
452 memcpy(new_item->value, value, new_value_len);
453
454 if (new_item->type == ICMAP_VALUETYPE_STRING) {
455 ((char *)new_item->value)[new_value_len - 1] = 0;
456 }
457
458 qb_map_put(map->qb_map, new_item->key_name, new_item);
459
460 return (CS_OK);
461 }
462
463 cs_error_t icmap_set(
464 const char *key_name,
465 const void *value,
466 size_t value_len,
467 icmap_value_types_t type)
468 {
469
470 return (icmap_set_r(icmap_global_map, key_name, value, value_len, type));
471 }
472
473 cs_error_t icmap_set_int8_r(const icmap_map_t map, const char *key_name, int8_t value)
474 {
475
476 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT8));
477 }
478
479 cs_error_t icmap_set_uint8_r(const icmap_map_t map, const char *key_name, uint8_t value)
480 {
481
482 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT8));
483 }
484
485 cs_error_t icmap_set_int16_r(const icmap_map_t map, const char *key_name, int16_t value)
486 {
487
488 return (icmap_set_r(map,key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT16));
489 }
490
491 cs_error_t icmap_set_uint16_r(const icmap_map_t map, const char *key_name, uint16_t value)
492 {
493
494 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT16));
495 }
496
497 cs_error_t icmap_set_int32_r(const icmap_map_t map, const char *key_name, int32_t value)
498 {
499
500 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT32));
501 }
502
503 cs_error_t icmap_set_uint32_r(const icmap_map_t map, const char *key_name, uint32_t value)
504 {
505
506 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT32));
507 }
508
509 cs_error_t icmap_set_int64_r(const icmap_map_t map, const char *key_name, int64_t value)
510 {
511
512 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT64));
513 }
514
515 cs_error_t icmap_set_uint64_r(const icmap_map_t map, const char *key_name, uint64_t value)
516 {
517
518 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT64));
519 }
520
521 cs_error_t icmap_set_float_r(const icmap_map_t map, const char *key_name, float value)
522 {
523
524 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_FLOAT));
525 }
526
527 cs_error_t icmap_set_double_r(const icmap_map_t map, const char *key_name, double value)
528 {
529
530 return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_DOUBLE));
531 }
532
533 cs_error_t icmap_set_string_r(const icmap_map_t map, const char *key_name, const char *value)
534 {
535
536 if (value == NULL) {
537 return (CS_ERR_INVALID_PARAM);
538 }
539
540 return (icmap_set_r(map, key_name, value, strlen(value), ICMAP_VALUETYPE_STRING));
541 }
542
543 cs_error_t icmap_set_int8(const char *key_name, int8_t value)
544 {
545
546 return (icmap_set_int8_r(icmap_global_map, key_name, value));
547 }
548
549 cs_error_t icmap_set_uint8(const char *key_name, uint8_t value)
550 {
551
552 return (icmap_set_uint8_r(icmap_global_map, key_name, value));
553 }
554
555 cs_error_t icmap_set_int16(const char *key_name, int16_t value)
556 {
557
558 return (icmap_set_int16_r(icmap_global_map, key_name, value));
559 }
560
561 cs_error_t icmap_set_uint16(const char *key_name, uint16_t value)
562 {
563
564 return (icmap_set_uint16_r(icmap_global_map, key_name, value));
565 }
566
567 cs_error_t icmap_set_int32(const char *key_name, int32_t value)
568 {
569
570 return (icmap_set_int32_r(icmap_global_map, key_name, value));
571 }
572
573 cs_error_t icmap_set_uint32(const char *key_name, uint32_t value)
574 {
575
576 return (icmap_set_uint32_r(icmap_global_map, key_name, value));
577 }
578
579 cs_error_t icmap_set_int64(const char *key_name, int64_t value)
580 {
581
582 return (icmap_set_int64_r(icmap_global_map, key_name, value));
583 }
584
585 cs_error_t icmap_set_uint64(const char *key_name, uint64_t value)
586 {
587
588 return (icmap_set_uint64_r(icmap_global_map, key_name, value));
589 }
590
591 cs_error_t icmap_set_float(const char *key_name, float value)
592 {
593
594 return (icmap_set_float_r(icmap_global_map, key_name, value));
595 }
596
597 cs_error_t icmap_set_double(const char *key_name, double value)
598 {
599
600 return (icmap_set_double_r(icmap_global_map, key_name, value));
601 }
602
603 cs_error_t icmap_set_string(const char *key_name, const char *value)
604 {
605
606 return (icmap_set_string_r(icmap_global_map, key_name, value));
607 }
608
609 cs_error_t icmap_delete_r(const icmap_map_t map, const char *key_name)
610 {
611 struct icmap_item *item;
612
613 if (key_name == NULL) {
614 return (CS_ERR_INVALID_PARAM);
615 }
616
617 item = qb_map_get(map->qb_map, key_name);
618 if (item == NULL) {
619 return (CS_ERR_NOT_EXIST);
620 }
621
622 if (qb_map_rm(map->qb_map, item->key_name) != QB_TRUE) {
623 return (CS_ERR_NOT_EXIST);
624 }
625
626 return (CS_OK);
627 }
628
629 cs_error_t icmap_delete(const char *key_name)
630 {
631
632 return (icmap_delete_r(icmap_global_map, key_name));
633 }
634
635 cs_error_t icmap_get_r(
636 const icmap_map_t map,
637 const char *key_name,
638 void *value,
639 size_t *value_len,
640 icmap_value_types_t *type)
641 {
642 struct icmap_item *item;
643
644 if (key_name == NULL) {
645 return (CS_ERR_INVALID_PARAM);
646 }
647
648 item = qb_map_get(map->qb_map, key_name);
649 if (item == NULL) {
650 return (CS_ERR_NOT_EXIST);
651 }
652
653 if (type != NULL) {
654 *type = item->type;
655 }
656
657 if (value == NULL) {
658 if (value_len != NULL) {
659 *value_len = item->value_len;
660 }
661 } else {
662 if (value_len == NULL || *value_len < item->value_len) {
663 return (CS_ERR_INVALID_PARAM);
664 }
665
666 *value_len = item->value_len;
667
668 memcpy(value, item->value, item->value_len);
669 }
670
671 return (CS_OK);
672 }
673
674 cs_error_t icmap_get(
675 const char *key_name,
676 void *value,
677 size_t *value_len,
678 icmap_value_types_t *type)
679 {
680
681 return (icmap_get_r(icmap_global_map, key_name, value, value_len, type));
682 }
683
684 static cs_error_t icmap_get_int_r(
685 const icmap_map_t map,
686 const char *key_name,
687 void *value,
688 icmap_value_types_t type)
689 {
690 char key_value[16];
691 size_t key_size;
692 cs_error_t err;
693 icmap_value_types_t key_type;
694
695 key_size = sizeof(key_value);
696 memset(key_value, 0, key_size);
697
698 err = icmap_get(key_name, key_value, &key_size, &key_type);
699 if (err != CS_OK)
700 return (err);
701
702 if (key_type != type) {
703 return (CS_ERR_INVALID_PARAM);
704 }
705
706 memcpy(value, key_value, icmap_get_valuetype_len(key_type));
707
708 return (CS_OK);
709 }
710
711 cs_error_t icmap_get_int8_r(const icmap_map_t map, const char *key_name, int8_t *i8)
712 {
713
714 return (icmap_get_int_r(map, key_name, i8, ICMAP_VALUETYPE_INT8));
715 }
716
717 cs_error_t icmap_get_uint8_r(const icmap_map_t map, const char *key_name, uint8_t *u8)
718 {
719
720 return (icmap_get_int_r(map, key_name, u8, ICMAP_VALUETYPE_UINT8));
721 }
722
723 cs_error_t icmap_get_int16_r(const icmap_map_t map, const char *key_name, int16_t *i16)
724 {
725
726 return (icmap_get_int_r(map, key_name, i16, ICMAP_VALUETYPE_INT16));
727 }
728
729 cs_error_t icmap_get_uint16_r(const icmap_map_t map, const char *key_name, uint16_t *u16)
730 {
731
732 return (icmap_get_int_r(map, key_name, u16, ICMAP_VALUETYPE_UINT16));
733 }
734
735 cs_error_t icmap_get_int32_r(const icmap_map_t map, const char *key_name, int32_t *i32)
736 {
737
738 return (icmap_get_int_r(map, key_name, i32, ICMAP_VALUETYPE_INT32));
739 }
740
741 cs_error_t icmap_get_uint32_r(const icmap_map_t map, const char *key_name, uint32_t *u32)
742 {
743
744 return (icmap_get_int_r(map, key_name, u32, ICMAP_VALUETYPE_UINT32));
745 }
746
747 cs_error_t icmap_get_int64_r(const icmap_map_t map, const char *key_name, int64_t *i64)
748 {
749
750 return(icmap_get_int_r(map, key_name, i64, ICMAP_VALUETYPE_INT64));
751 }
752
753 cs_error_t icmap_get_uint64_r(const icmap_map_t map, const char *key_name, uint64_t *u64)
754 {
755
756 return (icmap_get_int_r(map, key_name, u64, ICMAP_VALUETYPE_UINT64));
757 }
758
759 cs_error_t icmap_get_float_r(const icmap_map_t map, const char *key_name, float *flt)
760 {
761
762 return (icmap_get_int_r(map, key_name, flt, ICMAP_VALUETYPE_FLOAT));
763 }
764
765 cs_error_t icmap_get_double_r(const icmap_map_t map, const char *key_name, double *dbl)
766 {
767
768 return (icmap_get_int_r(map, key_name, dbl, ICMAP_VALUETYPE_DOUBLE));
769 }
770
771 cs_error_t icmap_get_int8(const char *key_name, int8_t *i8)
772 {
773
774 return (icmap_get_int8_r(icmap_global_map, key_name, i8));
775 }
776
777 cs_error_t icmap_get_uint8(const char *key_name, uint8_t *u8)
778 {
779
780 return (icmap_get_uint8_r(icmap_global_map, key_name, u8));
781 }
782
783 cs_error_t icmap_get_int16(const char *key_name, int16_t *i16)
784 {
785
786 return (icmap_get_int16_r(icmap_global_map, key_name, i16));
787 }
788
789 cs_error_t icmap_get_uint16(const char *key_name, uint16_t *u16)
790 {
791
792 return (icmap_get_uint16_r(icmap_global_map, key_name, u16));
793 }
794
795 cs_error_t icmap_get_int32(const char *key_name, int32_t *i32)
796 {
797
798 return (icmap_get_int32_r(icmap_global_map, key_name, i32));
799 }
800
801 cs_error_t icmap_get_uint32(const char *key_name, uint32_t *u32)
802 {
803
804 return (icmap_get_uint32_r(icmap_global_map, key_name, u32));
805 }
806
807 cs_error_t icmap_get_int64(const char *key_name, int64_t *i64)
808 {
809
810 return(icmap_get_int64_r(icmap_global_map, key_name, i64));
811 }
812
813 cs_error_t icmap_get_uint64(const char *key_name, uint64_t *u64)
814 {
815
816 return (icmap_get_uint64_r(icmap_global_map, key_name, u64));
817 }
818
819 cs_error_t icmap_get_float(const char *key_name, float *flt)
820 {
821
822 return (icmap_get_float_r(icmap_global_map, key_name, flt));
823 }
824
825 cs_error_t icmap_get_double(const char *key_name, double *dbl)
826 {
827
828 return (icmap_get_double_r(icmap_global_map, key_name, dbl));
829 }
830
831 cs_error_t icmap_get_string(const char *key_name, char **str)
832 {
833 cs_error_t res;
834 size_t str_len;
835 icmap_value_types_t type;
836
837 res = icmap_get(key_name, NULL, &str_len, &type);
838 if (res != CS_OK || type != ICMAP_VALUETYPE_STRING) {
839 if (res == CS_OK) {
840 res = CS_ERR_INVALID_PARAM;
841 }
842
843 goto return_error;
844 }
845
846 *str = malloc(str_len);
847 if (*str == NULL) {
848 res = CS_ERR_NO_MEMORY;
849
850 goto return_error;
851 }
852
853 res = icmap_get(key_name, *str, &str_len, &type);
854 if (res != CS_OK) {
855 free(*str);
856 goto return_error;
857 }
858
859 return (CS_OK);
860
861 return_error:
862 return (res);
863 }
864
865 cs_error_t icmap_adjust_int_r(
866 const icmap_map_t map,
867 const char *key_name,
868 int32_t step)
869 {
870 struct icmap_item *item;
871 uint8_t u8;
872 uint16_t u16;
873 uint32_t u32;
874 uint64_t u64;
875 cs_error_t err = CS_OK;
876
877 if (key_name == NULL) {
878 return (CS_ERR_INVALID_PARAM);
879 }
880
881 item = qb_map_get(map->qb_map, key_name);
882 if (item == NULL) {
883 return (CS_ERR_NOT_EXIST);
884 }
885
886 switch (item->type) {
887 case ICMAP_VALUETYPE_INT8:
888 case ICMAP_VALUETYPE_UINT8:
889 memcpy(&u8, item->value, sizeof(u8));
890 u8 += step;
891 err = icmap_set(key_name, &u8, sizeof(u8), item->type);
892 break;
893 case ICMAP_VALUETYPE_INT16:
894 case ICMAP_VALUETYPE_UINT16:
895 memcpy(&u16, item->value, sizeof(u16));
896 u16 += step;
897 err = icmap_set(key_name, &u16, sizeof(u16), item->type);
898 break;
899 case ICMAP_VALUETYPE_INT32:
900 case ICMAP_VALUETYPE_UINT32:
901 memcpy(&u32, item->value, sizeof(u32));
902 u32 += step;
903 err = icmap_set(key_name, &u32, sizeof(u32), item->type);
904 break;
905 case ICMAP_VALUETYPE_INT64:
906 case ICMAP_VALUETYPE_UINT64:
907 memcpy(&u64, item->value, sizeof(u64));
908 u64 += step;
909 err = icmap_set(key_name, &u64, sizeof(u64), item->type);
910 break;
911 case ICMAP_VALUETYPE_FLOAT:
912 case ICMAP_VALUETYPE_DOUBLE:
913 case ICMAP_VALUETYPE_STRING:
914 case ICMAP_VALUETYPE_BINARY:
915 err = CS_ERR_INVALID_PARAM;
916 break;
917 }
918
919 return (err);
920 }
921
922 cs_error_t icmap_adjust_int(
923 const char *key_name,
924 int32_t step)
925 {
926
927 return (icmap_adjust_int_r(icmap_global_map, key_name, step));
928 }
929
930 cs_error_t icmap_fast_adjust_int_r(
931 const icmap_map_t map,
932 const char *key_name,
933 int32_t step)
934 {
935 struct icmap_item *item;
936 cs_error_t err = CS_OK;
937
938 if (key_name == NULL) {
939 return (CS_ERR_INVALID_PARAM);
940 }
941
942 item = qb_map_get(map->qb_map, key_name);
943 if (item == NULL) {
944 return (CS_ERR_NOT_EXIST);
945 }
946
947 switch (item->type) {
948 case ICMAP_VALUETYPE_INT8:
949 case ICMAP_VALUETYPE_UINT8:
950 *(uint8_t *)item->value += step;
951 break;
952 case ICMAP_VALUETYPE_INT16:
953 case ICMAP_VALUETYPE_UINT16:
954 *(uint16_t *)item->value += step;
955 break;
956 case ICMAP_VALUETYPE_INT32:
957 case ICMAP_VALUETYPE_UINT32:
958 *(uint32_t *)item->value += step;
959 break;
960 case ICMAP_VALUETYPE_INT64:
961 case ICMAP_VALUETYPE_UINT64:
962 *(uint64_t *)item->value += step;
963 break;
964 case ICMAP_VALUETYPE_FLOAT:
965 case ICMAP_VALUETYPE_DOUBLE:
966 case ICMAP_VALUETYPE_STRING:
967 case ICMAP_VALUETYPE_BINARY:
968 err = CS_ERR_INVALID_PARAM;
969 break;
970 }
971
972 if (err == CS_OK) {
973 qb_map_put(map->qb_map, item->key_name, item);
974 }
975
976 return (err);
977 }
978
979 cs_error_t icmap_fast_adjust_int(
980 const char *key_name,
981 int32_t step)
982 {
983
984 return (icmap_fast_adjust_int_r(icmap_global_map, key_name, step));
985 }
986
987 cs_error_t icmap_inc_r(const icmap_map_t map, const char *key_name)
988 {
989 return (icmap_adjust_int_r(map, key_name, 1));
990 }
991
992 cs_error_t icmap_inc(const char *key_name)
993 {
994 return (icmap_inc_r(icmap_global_map, key_name));
995 }
996
997 cs_error_t icmap_dec_r(const icmap_map_t map, const char *key_name)
998 {
999 return (icmap_adjust_int_r(map, key_name, -1));
1000 }
1001
1002 cs_error_t icmap_dec(const char *key_name)
1003 {
1004 return (icmap_dec_r(icmap_global_map, key_name));
1005 }
1006
1007 cs_error_t icmap_fast_inc_r(const icmap_map_t map, const char *key_name)
1008 {
1009 return (icmap_fast_adjust_int_r(map, key_name, 1));
1010 }
1011
1012 cs_error_t icmap_fast_inc(const char *key_name)
1013 {
1014 return (icmap_fast_inc_r(icmap_global_map, key_name));
1015 }
1016
1017 cs_error_t icmap_fast_dec_r(const icmap_map_t map, const char *key_name)
1018 {
1019 return (icmap_fast_adjust_int_r(map, key_name, -1));
1020 }
1021
1022 cs_error_t icmap_fast_dec(const char *key_name)
1023 {
1024 return (icmap_fast_dec_r(icmap_global_map, key_name));
1025 }
1026
1027 icmap_iter_t icmap_iter_init_r(const icmap_map_t map, const char *prefix)
1028 {
1029 return (qb_map_pref_iter_create(map->qb_map, prefix));
1030 }
1031
1032 icmap_iter_t icmap_iter_init(const char *prefix)
1033 {
1034 return (icmap_iter_init_r(icmap_global_map, prefix));
1035 }
1036
1037
1038 const char *icmap_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
1039 {
1040 struct icmap_item *item;
1041 const char *res;
1042
1043 res = qb_map_iter_next(iter, (void **)&item);
1044 if (res == NULL) {
1045 return (res);
1046 }
1047
1048 if (value_len != NULL) {
1049 *value_len = item->value_len;
1050 }
1051
1052 if (type != NULL) {
1053 *type = item->type;
1054 }
1055
1056 return (res);
1057 }
1058
1059 void icmap_iter_finalize(icmap_iter_t iter)
1060 {
1061 qb_map_iter_free(iter);
1062 }
1063
1064 static void icmap_notify_fn(uint32_t event, char *key, void *old_value, void *value, void *user_data)
1065 {
1066 icmap_track_t icmap_track = (icmap_track_t)user_data;
1067 struct icmap_item *new_item = (struct icmap_item *)value;
1068 struct icmap_item *old_item = (struct icmap_item *)old_value;
1069 struct icmap_notify_value new_val;
1070 struct icmap_notify_value old_val;
1071
1072 if (value == NULL && old_value == NULL) {
1073 return ;
1074 }
1075
1076 if (new_item != NULL) {
1077 new_val.type = new_item->type;
1078 new_val.len = new_item->value_len;
1079 new_val.data = new_item->value;
1080 } else {
1081 memset(&new_val, 0, sizeof(new_val));
1082 }
1083
1084 /*
1085 * old_item == new_item if fast functions are used -> don't fill old value
1086 */
1087 if (old_item != NULL && old_item != new_item) {
1088 old_val.type = old_item->type;
1089 old_val.len = old_item->value_len;
1090 old_val.data = old_item->value;
1091 } else {
1092 memset(&old_val, 0, sizeof(old_val));
1093 }
1094
1095 icmap_track->notify_fn(icmap_qbtt_to_tt(event),
1096 key,
1097 new_val,
1098 old_val,
1099 icmap_track->user_data);
1100 }
1101
1102 cs_error_t icmap_track_add(
1103 const char *key_name,
1104 int32_t track_type,
1105 icmap_notify_fn_t notify_fn,
1106 void *user_data,
1107 icmap_track_t *icmap_track)
1108 {
1109 int32_t err;
1110
1111 if (notify_fn == NULL || icmap_track == NULL) {
1112 return (CS_ERR_INVALID_PARAM);
1113 }
1114
1115 if ((track_type & ~(ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX)) != 0) {
1116 return (CS_ERR_INVALID_PARAM);
1117 }
1118
1119 *icmap_track = malloc(sizeof(**icmap_track));
1120 if (*icmap_track == NULL) {
1121 return (CS_ERR_NO_MEMORY);
1122 }
1123 memset(*icmap_track, 0, sizeof(**icmap_track));
1124
1125 if (key_name != NULL) {
1126 (*icmap_track)->key_name = strdup(key_name);
1127 };
1128
1129 (*icmap_track)->track_type = track_type;
1130 (*icmap_track)->notify_fn = notify_fn;
1131 (*icmap_track)->user_data = user_data;
1132
1133 if ((err = qb_map_notify_add(icmap_global_map->qb_map, (*icmap_track)->key_name, icmap_notify_fn,
1134 icmap_tt_to_qbtt(track_type), *icmap_track)) != 0) {
1135 free((*icmap_track)->key_name);
1136 free(*icmap_track);
1137
1138 return (qb_to_cs_error(err));
1139 }
1140
1141 list_init(&(*icmap_track)->list);
1142 list_add (&(*icmap_track)->list, &icmap_track_list_head);
1143
1144 return (CS_OK);
1145 }
1146
1147 cs_error_t icmap_track_delete(icmap_track_t icmap_track)
1148 {
1149 int32_t err;
1150
1151 if ((err = qb_map_notify_del_2(icmap_global_map->qb_map, icmap_track->key_name,
1152 icmap_notify_fn, icmap_tt_to_qbtt(icmap_track->track_type), icmap_track)) != 0) {
1153 return (qb_to_cs_error(err));
1154 }
1155
1156 list_del(&icmap_track->list);
1157 free(icmap_track->key_name);
1158 free(icmap_track);
1159
1160 return (CS_OK);
1161 }
1162
1163 void *icmap_track_get_user_data(icmap_track_t icmap_track)
1164 {
1165 return (icmap_track->user_data);
1166 }
1167
1168 cs_error_t icmap_set_ro_access(const char *key_name, int prefix, int ro_access)
1169 {
1170 struct list_head *iter;
1171 struct icmap_ro_access_item *icmap_ro_ai;
1172
1173 for (iter = icmap_ro_access_item_list_head.next; iter != &icmap_ro_access_item_list_head; iter = iter->next) {
1174 icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
1175
1176 if (icmap_ro_ai->prefix == prefix && strcmp(key_name, icmap_ro_ai->key_name) == 0) {
1177 /*
1178 * We found item
1179 */
1180 if (ro_access) {
1181 return (CS_ERR_EXIST);
1182 } else {
1183 list_del(&icmap_ro_ai->list);
1184 free(icmap_ro_ai->key_name);
1185 free(icmap_ro_ai);
1186
1187 return (CS_OK);
1188 }
1189 }
1190 }
1191
1192 if (!ro_access) {
1193 return (CS_ERR_NOT_EXIST);
1194 }
1195
1196 icmap_ro_ai = malloc(sizeof(*icmap_ro_ai));
1197 if (icmap_ro_ai == NULL) {
1198 return (CS_ERR_NO_MEMORY);
1199 }
1200
1201 memset(icmap_ro_ai, 0, sizeof(*icmap_ro_ai));
1202 icmap_ro_ai->key_name = strdup(key_name);
1203 if (icmap_ro_ai->key_name == NULL) {
1204 free(icmap_ro_ai);
1205 return (CS_ERR_NO_MEMORY);
1206 }
1207
1208 icmap_ro_ai->prefix = prefix;
1209 list_init(&icmap_ro_ai->list);
1210 list_add (&icmap_ro_ai->list, &icmap_ro_access_item_list_head);
1211
1212 return (CS_OK);
1213 }
1214
1215 int icmap_is_key_ro(const char *key_name)
1216 {
1217 struct list_head *iter;
1218 struct icmap_ro_access_item *icmap_ro_ai;
1219
1220 for (iter = icmap_ro_access_item_list_head.next; iter != &icmap_ro_access_item_list_head; iter = iter->next) {
1221 icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
1222
1223 if (icmap_ro_ai->prefix) {
1224 if (strlen(icmap_ro_ai->key_name) > strlen(key_name))
1225 continue;
1226
1227 if (strncmp(icmap_ro_ai->key_name, key_name, strlen(icmap_ro_ai->key_name)) == 0) {
1228 return (CS_TRUE);
1229 }
1230 } else {
1231 if (strcmp(icmap_ro_ai->key_name, key_name) == 0) {
1232 return (CS_TRUE);
1233 }
1234 }
1235 }
1236
1237 return (CS_FALSE);
1238
1239 }