42 #include <qb/qbdefs.h>
46 #define ICMAP_MAX_VALUE_LEN (16*1024)
85 static int icmap_check_key_name(
const char *key_name);
101 static int32_t icmap_tt_to_qbtt(int32_t track_type);
106 static int32_t icmap_qbtt_to_tt(int32_t track_type);
116 static int icmap_is_valid_name_char(
char c);
123 const char *key_name,
134 const char *key_name,
142 static int32_t icmap_tt_to_qbtt(int32_t track_type)
147 res |= QB_MAP_NOTIFY_DELETED;
151 res |= QB_MAP_NOTIFY_REPLACED;
155 res |= QB_MAP_NOTIFY_INSERTED;
159 res |= QB_MAP_NOTIFY_RECURSIVE;
165 static int32_t icmap_qbtt_to_tt(int32_t track_type)
169 if (track_type & QB_MAP_NOTIFY_DELETED) {
173 if (track_type & QB_MAP_NOTIFY_REPLACED) {
177 if (track_type & QB_MAP_NOTIFY_INSERTED) {
181 if (track_type & QB_MAP_NOTIFY_RECURSIVE) {
188 static void icmap_map_free_cb(uint32_t event,
189 char* key,
void* old_value,
197 if (item != NULL && value != old_value) {
207 *result = malloc(
sizeof(
struct icmap_map));
208 if (*result == NULL) {
212 (*result)->qb_map = qb_trie_create();
213 if ((*result)->qb_map == NULL) {
218 err = qb_map_notify_add((*result)->qb_map, NULL, icmap_map_free_cb, QB_MAP_NOTIFY_FREE, NULL);
228 static void icmap_set_ro_access_free(
void)
230 struct list_head *iter = icmap_ro_access_item_list_head.
next;
233 while (iter != &icmap_ro_access_item_list_head) {
235 list_del(&icmap_ro_ai->
list);
238 iter = icmap_ro_access_item_list_head.
next;
242 static void icmap_del_all_track(
void)
247 while (iter != &icmap_track_list_head) {
250 iter = icmap_track_list_head.
next;
257 qb_map_destroy(map->
qb_map);
266 icmap_del_all_track();
275 icmap_set_ro_access_free();
283 return (icmap_global_map);
286 static int icmap_is_valid_name_char(
char c)
288 return ((c >=
'a' && c <=
'z') ||
289 (c >=
'A' && c <=
'Z') ||
290 (c >=
'0' && c <=
'9') ||
291 c ==
'.' || c ==
'_' || c ==
'-' || c ==
'/' || c ==
':');
298 for (i = 0; i < strlen(key_name); i++) {
299 if (!icmap_is_valid_name_char(key_name[i])) {
305 static int icmap_check_key_name(
const char *
key_name)
313 for (i = 0; i < strlen(key_name); i++) {
314 if (!icmap_is_valid_name_char(key_name[i])) {
346 static int icmap_check_value_len(
const void *value,
size_t value_len,
icmap_value_types_t type)
354 if (icmap_get_valuetype_len(type) == value_len) {
366 if (value_len > strlen((
const char *)value) + 1) {
380 if (item->
type != type) {
385 ptr_len = strlen((
const char *)value);
386 if (ptr_len > value_len) {
395 return (memcmp(item->
value, value, value_len) == 0);
403 const char *key_name1,
405 const char *key_name2)
409 if (map1 == NULL || key_name1 == NULL || map2 == NULL || key_name2 == NULL) {
413 item1 = qb_map_get(map1->
qb_map, key_name1);
414 item2 = qb_map_get(map2->
qb_map, key_name2);
416 if (item1 == NULL || item2 == NULL) {
425 const char *key_name,
432 size_t new_value_len;
433 size_t new_item_size;
435 if (value == NULL || key_name == NULL) {
439 if (icmap_check_value_len(value, value_len, type) != 0) {
443 item = qb_map_get(map->
qb_map, key_name);
448 if (icmap_item_eq(item, value, value_len, type)) {
452 if (icmap_check_key_name(key_name) != 0) {
459 new_value_len = strlen((
const char *)value);
460 if (new_value_len > value_len) {
468 new_value_len = icmap_get_valuetype_len(type);
471 new_item_size =
sizeof(
struct icmap_item) + new_value_len;
472 new_item = malloc(new_item_size);
473 if (new_item == NULL) {
476 memset(new_item, 0, new_item_size);
479 new_item->key_name = strdup(key_name);
480 if (new_item->key_name == NULL) {
485 new_item->key_name = item->
key_name;
489 new_item->type =
type;
490 new_item->value_len = new_value_len;
492 memcpy(new_item->value, value, new_value_len);
495 ((
char *)new_item->value)[new_value_len - 1] = 0;
498 qb_map_put(map->
qb_map, new_item->key_name, new_item);
504 const char *key_name,
510 return (
icmap_set_r(icmap_global_map, key_name, value, value_len, type));
653 if (key_name == NULL) {
657 item = qb_map_get(map->
qb_map, key_name);
677 const char *key_name,
684 if (key_name == NULL) {
688 item = qb_map_get(map->
qb_map, key_name);
697 if (value_len != NULL) {
702 *value = item->
value;
710 const char *key_name,
717 size_t tmp_value_len;
719 res = icmap_get_ref_r(map, key_name, &tmp_value, &tmp_value_len, type);
725 if (value_len != NULL) {
726 *value_len = tmp_value_len;
729 if (value_len == NULL || *value_len < tmp_value_len) {
733 *value_len = tmp_value_len;
735 memcpy(value, tmp_value, tmp_value_len);
742 const char *key_name,
748 return (
icmap_get_r(icmap_global_map, key_name, value, value_len, type));
757 res =
icmap_get_r(map, key_name, NULL, &str_len, &type);
766 *str = malloc(str_len);
773 res =
icmap_get_r(map, key_name, *str, &str_len, &type);
787 const char *key_name,
796 key_size =
sizeof(key_value);
797 memset(key_value, 0, key_size);
799 err =
icmap_get_r(map, key_name, key_value, &key_size, &key_type);
803 if (key_type != type) {
807 memcpy(value, key_value, icmap_get_valuetype_len(key_type));
940 const char *key_name,
950 if (key_name == NULL) {
954 item = qb_map_get(map->
qb_map, key_name);
959 switch (item->
type) {
962 memcpy(&u8, item->
value,
sizeof(u8));
968 memcpy(&u16, item->
value,
sizeof(u16));
974 memcpy(&u32, item->
value,
sizeof(u32));
980 memcpy(&u64, item->
value,
sizeof(u64));
996 const char *key_name,
1005 const char *key_name,
1011 if (key_name == NULL) {
1015 item = qb_map_get(map->
qb_map, key_name);
1020 switch (item->
type) {
1023 *(uint8_t *)item->
value += step;
1027 *(uint16_t *)item->
value += step;
1031 *(uint32_t *)item->
value += step;
1035 *(uint64_t *)item->
value += step;
1053 const char *key_name,
1102 return (qb_map_pref_iter_create(map->
qb_map, prefix));
1116 res = qb_map_iter_next(iter, (
void **)&item);
1121 if (value_len != NULL) {
1134 qb_map_iter_free(iter);
1137 static void icmap_notify_fn(uint32_t event,
char *key,
void *old_value,
void *value,
void *user_data)
1145 if (value == NULL && old_value == NULL) {
1149 if (new_item != NULL) {
1152 new_val.data = new_item->
value;
1154 memset(&new_val, 0,
sizeof(new_val));
1160 if (old_item != NULL && old_item != new_item) {
1161 old_val.type = old_item->
type;
1163 old_val.data = old_item->
value;
1165 memset(&old_val, 0,
sizeof(old_val));
1168 icmap_track->
notify_fn(icmap_qbtt_to_tt(event),
1176 const char *key_name,
1184 if (notify_fn == NULL || icmap_track == NULL) {
1188 if ((track_type & ~(ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX)) != 0) {
1192 *icmap_track = malloc(
sizeof(**icmap_track));
1193 if (*icmap_track == NULL) {
1196 memset(*icmap_track, 0,
sizeof(**icmap_track));
1198 if (key_name != NULL) {
1199 (*icmap_track)->key_name = strdup(key_name);
1202 (*icmap_track)->track_type = track_type;
1203 (*icmap_track)->notify_fn = notify_fn;
1206 if ((err = qb_map_notify_add(icmap_global_map->
qb_map, (*icmap_track)->key_name, icmap_notify_fn,
1207 icmap_tt_to_qbtt(track_type), *icmap_track)) != 0) {
1208 free((*icmap_track)->key_name);
1214 list_init(&(*icmap_track)->list);
1215 list_add (&(*icmap_track)->list, &icmap_track_list_head);
1224 if ((err = qb_map_notify_del_2(icmap_global_map->
qb_map, icmap_track->
key_name,
1225 icmap_notify_fn, icmap_tt_to_qbtt(icmap_track->
track_type), icmap_track)) != 0) {
1229 list_del(&icmap_track->
list);
1246 for (iter = icmap_ro_access_item_list_head.
next; iter != &icmap_ro_access_item_list_head; iter = iter->
next) {
1249 if (icmap_ro_ai->
prefix == prefix && strcmp(key_name, icmap_ro_ai->
key_name) == 0) {
1256 list_del(&icmap_ro_ai->
list);
1269 icmap_ro_ai = malloc(
sizeof(*icmap_ro_ai));
1270 if (icmap_ro_ai == NULL) {
1274 memset(icmap_ro_ai, 0,
sizeof(*icmap_ro_ai));
1275 icmap_ro_ai->
key_name = strdup(key_name);
1276 if (icmap_ro_ai->
key_name == NULL) {
1282 list_init(&icmap_ro_ai->
list);
1283 list_add (&icmap_ro_ai->
list, &icmap_ro_access_item_list_head);
1293 for (iter = icmap_ro_access_item_list_head.
next; iter != &icmap_ro_access_item_list_head; iter = iter->
next) {
1296 if (icmap_ro_ai->
prefix) {
1297 if (strlen(icmap_ro_ai->
key_name) > strlen(key_name))
1300 if (strncmp(icmap_ro_ai->
key_name, key_name, strlen(icmap_ro_ai->
key_name)) == 0) {
1304 if (strcmp(icmap_ro_ai->
key_name, key_name) == 0) {
1330 while ((key_name =
icmap_iter_next(iter, &value_len, &value_type)) != NULL) {
1331 err = icmap_get_ref_r(src_map, key_name, &value, &value_len, &value_type);
1333 goto exit_iter_finalize;
1336 err =
icmap_set_r(dst_map, key_name, value, value_len, value_type);
1338 goto exit_iter_finalize;
cs_error_t icmap_set_float(const char *key_name, float value)
cs_error_t icmap_set_r(const icmap_map_t map, const char *key_name, const void *value, size_t value_len, icmap_value_types_t type)
Reentrant version of icmap_set.
cs_error_t icmap_get_double(const char *key_name, double *dbl)
icmap_notify_fn_t notify_fn
cs_error_t icmap_get_uint64(const char *key_name, uint64_t *u64)
cs_error_t icmap_set_int16_r(const icmap_map_t map, const char *key_name, int16_t value)
cs_error_t icmap_get_r(const icmap_map_t map, const char *key_name, void *value, size_t *value_len, icmap_value_types_t *type)
Same as icmap_get but it's reentrant and operates on given icmap_map.
cs_error_t icmap_dec_r(const icmap_map_t map, const char *key_name)
icmap_dec_r
cs_error_t icmap_get_int16(const char *key_name, int16_t *i16)
cs_error_t icmap_get_uint8(const char *key_name, uint8_t *u8)
cs_error_t icmap_set_double(const char *key_name, double value)
cs_error_t icmap_track_add(const char *key_name, int32_t track_type, icmap_notify_fn_t notify_fn, void *user_data, icmap_track_t *icmap_track)
Add tracking function for given key_name.
cs_error_t icmap_set_uint64_r(const icmap_map_t map, const char *key_name, uint64_t value)
cs_error_t icmap_set_uint32(const char *key_name, uint32_t value)
cs_error_t icmap_set_uint16_r(const icmap_map_t map, const char *key_name, uint16_t value)
cs_error_t icmap_fast_inc(const char *key_name)
Increase stored value by one.
cs_error_t icmap_get_string_r(icmap_map_t map, const char *key_name, char **str)
cs_error_t icmap_set_int8_r(const icmap_map_t map, const char *key_name, int8_t value)
#define ICMAP_MAX_VALUE_LEN
const char * icmap_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
Return next item in iterator iter.
cs_error_t icmap_adjust_int(const char *key_name, int32_t step)
icmap_adjust_int
void icmap_convert_name_to_valid_name(char *key_name)
Converts given key_name to valid key name (replacing all prohibited characters by _) ...
cs_error_t icmap_get_int32(const char *key_name, int32_t *i32)
cs_error_t icmap_track_delete(icmap_track_t icmap_track)
Remove previously added track.
icmap_iter_t icmap_iter_init_r(const icmap_map_t map, const char *prefix)
icmap_iter_init_r
cs_error_t icmap_get_uint32_r(const icmap_map_t map, const char *key_name, uint32_t *u32)
DECLARE_LIST_INIT(icmap_ro_access_item_list_head)
cs_error_t icmap_get_float_r(const icmap_map_t map, const char *key_name, float *flt)
cs_error_t icmap_inc(const char *key_name)
Increase stored value by one.
cs_error_t icmap_get_uint32(const char *key_name, uint32_t *u32)
cs_error_t icmap_init_r(icmap_map_t *result)
Initialize additional (local, reentrant) icmap_map.
cs_error_t icmap_set_int8(const char *key_name, int8_t value)
#define ICMAP_TRACK_DELETE
#define ICMAP_KEYNAME_MAXLEN
Maximum length of key in icmap.
cs_error_t icmap_fast_inc_r(const icmap_map_t map, const char *key_name)
icmap_fast_inc_r
cs_error_t icmap_get_int8_r(const icmap_map_t map, const char *key_name, int8_t *i8)
cs_error_t icmap_set_string_r(const icmap_map_t map, const char *key_name, const char *value)
cs_error_t icmap_set_int64_r(const icmap_map_t map, const char *key_name, int64_t value)
cs_error_t icmap_set_double_r(const icmap_map_t map, const char *key_name, double value)
#define ICMAP_TRACK_MODIFY
icmap_map_t icmap_get_global_map(void)
Return global icmap.
void(* icmap_notify_fn_t)(int32_t event, const char *key_name, struct icmap_notify_value new_value, struct icmap_notify_value old_value, void *user_data)
Prototype for notify callback function.
cs_error_t icmap_set_uint8_r(const icmap_map_t map, const char *key_name, uint8_t value)
cs_error_t icmap_get_int8(const char *key_name, int8_t *i8)
cs_error_t icmap_set_uint64(const char *key_name, uint64_t value)
int icmap_is_key_ro(const char *key_name)
Check in given key is read only.
cs_error_t icmap_fast_adjust_int_r(const icmap_map_t map, const char *key_name, int32_t step)
icmap_fast_adjust_int_r
cs_error_t icmap_set_uint16(const char *key_name, uint16_t value)
cs_error_t icmap_set_int16(const char *key_name, int16_t value)
cs_error_t
The cs_error_t enum.
cs_error_t icmap_get_uint8_r(const icmap_map_t map, const char *key_name, uint8_t *u8)
cs_error_t icmap_delete(const char *key_name)
Delete key from map.
cs_error_t icmap_get_int16_r(const icmap_map_t map, const char *key_name, int16_t *i16)
cs_error_t icmap_set_float_r(const icmap_map_t map, const char *key_name, float value)
cs_error_t icmap_get_int64_r(const icmap_map_t map, const char *key_name, int64_t *i64)
cs_error_t icmap_fast_adjust_int(const char *key_name, int32_t step)
icmap_fast_adjust_int
cs_error_t icmap_copy_map(icmap_map_t dst_map, const icmap_map_t src_map)
Copy content of src_map icmap to dst_map icmap.
icmap_iter_t icmap_iter_init(const char *prefix)
Initialize iterator with given prefix.
cs_error_t icmap_init(void)
Initialize global icmap.
void icmap_iter_finalize(icmap_iter_t iter)
Finalize iterator.
cs_error_t icmap_set_int64(const char *key_name, int64_t value)
cs_error_t icmap_get(const char *key_name, void *value, size_t *value_len, icmap_value_types_t *type)
Retrieve value of key key_name and store it in user preallocated value pointer.
cs_error_t icmap_fast_dec_r(const icmap_map_t map, const char *key_name)
icmap_fast_dec_r
cs_error_t icmap_delete_r(const icmap_map_t map, const char *key_name)
icmap_delete_r
cs_error_t icmap_get_int64(const char *key_name, int64_t *i64)
cs_error_t icmap_set_int32(const char *key_name, int32_t value)
int icmap_key_value_eq(const icmap_map_t map1, const char *key_name1, const icmap_map_t map2, const char *key_name2)
Compare value of key with name key_name1 in map1 with key with name key_name2 in map2.
cs_error_t icmap_set_int32_r(const icmap_map_t map, const char *key_name, int32_t value)
cs_error_t icmap_dec(const char *key_name)
Decrease stored value by one.
cs_error_t icmap_set_uint8(const char *key_name, uint8_t value)
struct icmap_track * icmap_track_t
Track type.
cs_error_t icmap_get_uint16_r(const icmap_map_t map, const char *key_name, uint16_t *u16)
cs_error_t icmap_set_string(const char *key_name, const char *value)
#define ICMAP_KEYNAME_MINLEN
Minimum lenght of key in icmap.
cs_error_t icmap_set_uint32_r(const icmap_map_t map, const char *key_name, uint32_t value)
cs_error_t icmap_adjust_int_r(const icmap_map_t map, const char *key_name, int32_t step)
icmap_adjust_int_r
cs_error_t icmap_inc_r(const icmap_map_t map, const char *key_name)
icmap_inc_r
#define list_entry(ptr, type, member)
cs_error_t icmap_set(const char *key_name, const void *value, size_t value_len, icmap_value_types_t type)
Store value with value_len length and type as key_name name in global icmap.
cs_error_t icmap_get_int32_r(const icmap_map_t map, const char *key_name, int32_t *i32)
void icmap_fini(void)
Finalize global icmap.
cs_error_t icmap_get_string(const char *key_name, char **str)
Shortcut for icmap_get for string type.
cs_error_t icmap_get_uint64_r(const icmap_map_t map, const char *key_name, uint64_t *u64)
cs_error_t icmap_fast_dec(const char *key_name)
Decrease stored value by one.
cs_error_t icmap_get_uint16(const char *key_name, uint16_t *u16)
cs_error_t icmap_set_ro_access(const char *key_name, int prefix, int ro_access)
Set read-only access for given key (key_name) or prefix, If prefix is set.
cs_error_t qb_to_cs_error(int result)
qb_to_cs_error
icmap_value_types_t
Possible types of value.
cs_error_t icmap_get_double_r(const icmap_map_t map, const char *key_name, double *dbl)
void icmap_fini_r(const icmap_map_t map)
Finalize local, reentrant icmap.
cs_error_t icmap_get_float(const char *key_name, float *flt)
qb_map_iter_t * icmap_iter_t
Itterator type.
Structure passed as new_value and old_value in change callback.
#define ICMAP_TRACK_PREFIX
Whole prefix is tracked, instead of key only (so "totem." tracking means that "totem.nodeid", "totem.version", ...
void * icmap_track_get_user_data(icmap_track_t icmap_track)
Return user data associated with given track.