icmap.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243
  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. #include <config.h>
  35. #include <string.h>
  36. #include <stdio.h>
  37. #include <corosync/corotypes.h>
  38. #include <qb/qbdefs.h>
  39. #include <corosync/list.h>
  40. #include <corosync/icmap.h>
  41. #define ICMAP_MAX_VALUE_LEN (16*1024)
  42. struct icmap_item {
  43. char *key_name;
  44. icmap_value_types_t type;
  45. size_t value_len;
  46. char value[];
  47. };
  48. struct icmap_map {
  49. qb_map_t *qb_map;
  50. };
  51. static icmap_map_t icmap_global_map;
  52. struct icmap_track {
  53. char *key_name;
  54. int32_t track_type;
  55. icmap_notify_fn_t notify_fn;
  56. void *user_data;
  57. struct list_head list;
  58. };
  59. struct icmap_ro_access_item {
  60. char *key_name;
  61. int prefix;
  62. struct list_head list;
  63. };
  64. DECLARE_LIST_INIT(icmap_ro_access_item_list_head);
  65. DECLARE_LIST_INIT(icmap_track_list_head);
  66. /*
  67. * Static functions declarations
  68. */
  69. /*
  70. * Check if key_name is valid icmap key name. Returns 0 on success, and -1 on fail
  71. */
  72. static int icmap_check_key_name(const char *key_name);
  73. /*
  74. * Check that value with given type has correct length value_len. Returns 0 on success,
  75. * and -1 on fail
  76. */
  77. static int icmap_check_value_len(const void *value, size_t value_len, icmap_value_types_t type);
  78. /*
  79. * Returns length of value of given type, or 0 for string and binary data type
  80. */
  81. static size_t icmap_get_valuetype_len(icmap_value_types_t type);
  82. /*
  83. * Converts track type of icmap to qb
  84. */
  85. static int32_t icmap_tt_to_qbtt(int32_t track_type);
  86. /*
  87. * Convert track type of qb to icmap
  88. */
  89. static int32_t icmap_qbtt_to_tt(int32_t track_type);
  90. /*
  91. * Checks if item has same value as value with value_len and given type. Returns 0 if not, otherwise !0.
  92. */
  93. static int icmap_item_eq(const struct icmap_item *item, const void *value, size_t value_len, icmap_value_types_t type);
  94. /*
  95. * Checks if given character is valid in key name. Returns 0 if not, otherwise !0.
  96. */
  97. static int icmap_is_valid_name_char(char c);
  98. /*
  99. * Helper for getting integer and float value with given type for key key_name and store it in value.
  100. */
  101. static cs_error_t icmap_get_int_r(
  102. const icmap_map_t map,
  103. const char *key_name,
  104. void *value,
  105. icmap_value_types_t type);
  106. /*
  107. * Function implementation
  108. */
  109. static int32_t icmap_tt_to_qbtt(int32_t track_type)
  110. {
  111. int32_t res = 0;
  112. if (track_type & ICMAP_TRACK_DELETE) {
  113. res |= QB_MAP_NOTIFY_DELETED;
  114. }
  115. if (track_type & ICMAP_TRACK_MODIFY) {
  116. res |= QB_MAP_NOTIFY_REPLACED;
  117. }
  118. if (track_type & ICMAP_TRACK_ADD) {
  119. res |= QB_MAP_NOTIFY_INSERTED;
  120. }
  121. if (track_type & ICMAP_TRACK_PREFIX) {
  122. res |= QB_MAP_NOTIFY_RECURSIVE;
  123. }
  124. return (res);
  125. }
  126. static int32_t icmap_qbtt_to_tt(int32_t track_type)
  127. {
  128. int32_t res = 0;
  129. if (track_type & QB_MAP_NOTIFY_DELETED) {
  130. res |= ICMAP_TRACK_DELETE;
  131. }
  132. if (track_type & QB_MAP_NOTIFY_REPLACED) {
  133. res |= ICMAP_TRACK_MODIFY;
  134. }
  135. if (track_type & QB_MAP_NOTIFY_INSERTED) {
  136. res |= ICMAP_TRACK_ADD;
  137. }
  138. if (track_type & QB_MAP_NOTIFY_RECURSIVE) {
  139. res |= ICMAP_TRACK_PREFIX;
  140. }
  141. return (res);
  142. }
  143. static void icmap_map_free_cb(uint32_t event,
  144. char* key, void* old_value,
  145. void* value, void* user_data)
  146. {
  147. struct icmap_item *item = (struct icmap_item *)old_value;
  148. /*
  149. * value == old_value -> fast_adjust_int was used, don't free data
  150. */
  151. if (item != NULL && value != old_value) {
  152. free(item->key_name);
  153. free(item);
  154. }
  155. }
  156. cs_error_t icmap_init_r(icmap_map_t *result)
  157. {
  158. int32_t err;
  159. *result = malloc(sizeof(struct icmap_map));
  160. if (*result == NULL) {
  161. return (CS_ERR_NO_MEMORY);
  162. }
  163. (*result)->qb_map = qb_trie_create();
  164. if ((*result)->qb_map == NULL)
  165. return (CS_ERR_INIT);
  166. err = qb_map_notify_add((*result)->qb_map, NULL, icmap_map_free_cb, QB_MAP_NOTIFY_FREE, NULL);
  167. return (qb_to_cs_error(err));
  168. }
  169. cs_error_t icmap_init(void)
  170. {
  171. return (icmap_init_r(&icmap_global_map));
  172. }
  173. static void icmap_set_ro_access_free(void)
  174. {
  175. struct list_head *iter = icmap_ro_access_item_list_head.next;
  176. struct icmap_ro_access_item *icmap_ro_ai;
  177. while (iter != &icmap_ro_access_item_list_head) {
  178. icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
  179. list_del(&icmap_ro_ai->list);
  180. free(icmap_ro_ai->key_name);
  181. free(icmap_ro_ai);
  182. iter = icmap_ro_access_item_list_head.next;
  183. }
  184. }
  185. static void icmap_del_all_track(void)
  186. {
  187. struct list_head *iter = icmap_track_list_head.next;
  188. struct icmap_track *icmap_track;
  189. while (iter != &icmap_track_list_head) {
  190. icmap_track = list_entry(iter, struct icmap_track, list);
  191. icmap_track_delete(icmap_track);
  192. iter = icmap_track_list_head.next;
  193. }
  194. }
  195. void icmap_fini_r(const icmap_map_t map)
  196. {
  197. qb_map_destroy(map->qb_map);
  198. free(map);
  199. return;
  200. }
  201. void icmap_fini(void)
  202. {
  203. icmap_del_all_track();
  204. /*
  205. * catch 22 warning:
  206. * We need to drop this notify but we can't because it calls icmap_map_free_cb
  207. * while destroying the tree to free icmap_item(s).
  208. * -> qb_map_notify_del_2(icmap_map, NULL, icmap_map_free_cb, QB_MAP_NOTIFY_FREE, NULL);
  209. * and we cannot call it after map_destroy. joy! :)
  210. */
  211. icmap_fini_r(icmap_global_map);
  212. icmap_set_ro_access_free();
  213. return ;
  214. }
  215. icmap_map_t icmap_get_global_map(void)
  216. {
  217. return (icmap_global_map);
  218. }
  219. static int icmap_is_valid_name_char(char c)
  220. {
  221. return ((c >= 'a' && c <= 'z') ||
  222. (c >= 'A' && c <= 'Z') ||
  223. (c >= '0' && c <= '9') ||
  224. c == '.' || c == '_' || c == '-' || c == '/' || c == ':');
  225. }
  226. void icmap_convert_name_to_valid_name(char *key_name)
  227. {
  228. int i;
  229. for (i = 0; i < strlen(key_name); i++) {
  230. if (!icmap_is_valid_name_char(key_name[i])) {
  231. key_name[i] = '_';
  232. }
  233. }
  234. }
  235. static int icmap_check_key_name(const char *key_name)
  236. {
  237. int i;
  238. if ((strlen(key_name) < ICMAP_KEYNAME_MINLEN) || strlen(key_name) > ICMAP_KEYNAME_MAXLEN) {
  239. return (-1);
  240. }
  241. for (i = 0; i < strlen(key_name); i++) {
  242. if (!icmap_is_valid_name_char(key_name[i])) {
  243. return (-1);
  244. }
  245. }
  246. return (0);
  247. }
  248. static size_t icmap_get_valuetype_len(icmap_value_types_t type)
  249. {
  250. size_t res = 0;
  251. switch (type) {
  252. case ICMAP_VALUETYPE_INT8: res = sizeof(int8_t); break;
  253. case ICMAP_VALUETYPE_UINT8: res = sizeof(uint8_t); break;
  254. case ICMAP_VALUETYPE_INT16: res = sizeof(int16_t); break;
  255. case ICMAP_VALUETYPE_UINT16: res = sizeof(uint16_t); break;
  256. case ICMAP_VALUETYPE_INT32: res = sizeof(int32_t); break;
  257. case ICMAP_VALUETYPE_UINT32: res = sizeof(uint32_t); break;
  258. case ICMAP_VALUETYPE_INT64: res = sizeof(int64_t); break;
  259. case ICMAP_VALUETYPE_UINT64: res = sizeof(uint64_t); break;
  260. case ICMAP_VALUETYPE_FLOAT: res = sizeof(float); break;
  261. case ICMAP_VALUETYPE_DOUBLE: res = sizeof(double); break;
  262. case ICMAP_VALUETYPE_STRING:
  263. case ICMAP_VALUETYPE_BINARY:
  264. res = 0;
  265. break;
  266. }
  267. return (res);
  268. }
  269. static int icmap_check_value_len(const void *value, size_t value_len, icmap_value_types_t type)
  270. {
  271. if (value_len > ICMAP_MAX_VALUE_LEN) {
  272. return (-1);
  273. }
  274. if (type != ICMAP_VALUETYPE_STRING && type != ICMAP_VALUETYPE_BINARY) {
  275. if (icmap_get_valuetype_len(type) == value_len) {
  276. return (0);
  277. } else {
  278. return (-1);
  279. }
  280. }
  281. if (type == ICMAP_VALUETYPE_STRING) {
  282. /*
  283. * value_len can be shorter then real string length, but never
  284. * longer (+ 1 is because of 0 at the end of string)
  285. */
  286. if (value_len > strlen((const char *)value) + 1) {
  287. return (-1);
  288. } else {
  289. return (0);
  290. }
  291. }
  292. return (0);
  293. }
  294. static int icmap_item_eq(const struct icmap_item *item, const void *value, size_t value_len, icmap_value_types_t type)
  295. {
  296. size_t ptr_len;
  297. if (item->type != type) {
  298. return (0);
  299. }
  300. if (item->type == ICMAP_VALUETYPE_STRING) {
  301. ptr_len = strlen((const char *)value);
  302. if (ptr_len > value_len) {
  303. ptr_len = value_len;
  304. }
  305. ptr_len++;
  306. } else {
  307. ptr_len = value_len;
  308. }
  309. if (item->value_len == ptr_len) {
  310. return (memcmp(item->value, value, value_len) == 0);
  311. };
  312. return (0);
  313. }
  314. cs_error_t icmap_set_r(
  315. const icmap_map_t map,
  316. const char *key_name,
  317. const void *value,
  318. size_t value_len,
  319. icmap_value_types_t type)
  320. {
  321. struct icmap_item *item;
  322. struct icmap_item *new_item;
  323. size_t new_value_len;
  324. size_t new_item_size;
  325. if (value == NULL || key_name == NULL) {
  326. return (CS_ERR_INVALID_PARAM);
  327. }
  328. if (icmap_check_value_len(value, value_len, type) != 0) {
  329. return (CS_ERR_INVALID_PARAM);
  330. }
  331. item = qb_map_get(map->qb_map, key_name);
  332. if (item != NULL) {
  333. /*
  334. * Check that key is really changed
  335. */
  336. if (icmap_item_eq(item, value, value_len, type)) {
  337. return (CS_OK);
  338. }
  339. } else {
  340. if (icmap_check_key_name(key_name) != 0) {
  341. return (CS_ERR_NAME_TOO_LONG);
  342. }
  343. }
  344. if (type == ICMAP_VALUETYPE_BINARY || type == ICMAP_VALUETYPE_STRING) {
  345. if (type == ICMAP_VALUETYPE_STRING) {
  346. new_value_len = strlen((const char *)value);
  347. if (new_value_len > value_len) {
  348. new_value_len = value_len;
  349. }
  350. new_value_len++;
  351. } else {
  352. new_value_len = value_len;
  353. }
  354. } else {
  355. new_value_len = icmap_get_valuetype_len(type);
  356. }
  357. new_item_size = sizeof(struct icmap_item) + new_value_len;
  358. new_item = malloc(new_item_size);
  359. if (new_item == NULL) {
  360. return (CS_ERR_NO_MEMORY);
  361. }
  362. memset(new_item, 0, new_item_size);
  363. if (item == NULL) {
  364. new_item->key_name = strdup(key_name);
  365. if (new_item->key_name == NULL) {
  366. free(new_item);
  367. return (CS_ERR_NO_MEMORY);
  368. }
  369. } else {
  370. new_item->key_name = item->key_name;
  371. item->key_name = NULL;
  372. }
  373. new_item->type = type;
  374. new_item->value_len = new_value_len;
  375. memcpy(new_item->value, value, new_value_len);
  376. if (new_item->type == ICMAP_VALUETYPE_STRING) {
  377. ((char *)new_item->value)[new_value_len - 1] = 0;
  378. }
  379. qb_map_put(map->qb_map, new_item->key_name, new_item);
  380. return (CS_OK);
  381. }
  382. cs_error_t icmap_set(
  383. const char *key_name,
  384. const void *value,
  385. size_t value_len,
  386. icmap_value_types_t type)
  387. {
  388. return (icmap_set_r(icmap_global_map, key_name, value, value_len, type));
  389. }
  390. cs_error_t icmap_set_int8_r(const icmap_map_t map, const char *key_name, int8_t value)
  391. {
  392. return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT8));
  393. }
  394. cs_error_t icmap_set_uint8_r(const icmap_map_t map, const char *key_name, uint8_t value)
  395. {
  396. return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT8));
  397. }
  398. cs_error_t icmap_set_int16_r(const icmap_map_t map, const char *key_name, int16_t value)
  399. {
  400. return (icmap_set_r(map,key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT16));
  401. }
  402. cs_error_t icmap_set_uint16_r(const icmap_map_t map, const char *key_name, uint16_t value)
  403. {
  404. return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT16));
  405. }
  406. cs_error_t icmap_set_int32_r(const icmap_map_t map, const char *key_name, int32_t value)
  407. {
  408. return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT32));
  409. }
  410. cs_error_t icmap_set_uint32_r(const icmap_map_t map, const char *key_name, uint32_t value)
  411. {
  412. return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT32));
  413. }
  414. cs_error_t icmap_set_int64_r(const icmap_map_t map, const char *key_name, int64_t value)
  415. {
  416. return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT64));
  417. }
  418. cs_error_t icmap_set_uint64_r(const icmap_map_t map, const char *key_name, uint64_t value)
  419. {
  420. return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT64));
  421. }
  422. cs_error_t icmap_set_float_r(const icmap_map_t map, const char *key_name, float value)
  423. {
  424. return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_FLOAT));
  425. }
  426. cs_error_t icmap_set_double_r(const icmap_map_t map, const char *key_name, double value)
  427. {
  428. return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_DOUBLE));
  429. }
  430. cs_error_t icmap_set_string_r(const icmap_map_t map, const char *key_name, const char *value)
  431. {
  432. if (value == NULL) {
  433. return (CS_ERR_INVALID_PARAM);
  434. }
  435. return (icmap_set_r(map, key_name, value, strlen(value), ICMAP_VALUETYPE_STRING));
  436. }
  437. cs_error_t icmap_set_int8(const char *key_name, int8_t value)
  438. {
  439. return (icmap_set_int8_r(icmap_global_map, key_name, value));
  440. }
  441. cs_error_t icmap_set_uint8(const char *key_name, uint8_t value)
  442. {
  443. return (icmap_set_uint8_r(icmap_global_map, key_name, value));
  444. }
  445. cs_error_t icmap_set_int16(const char *key_name, int16_t value)
  446. {
  447. return (icmap_set_int16_r(icmap_global_map, key_name, value));
  448. }
  449. cs_error_t icmap_set_uint16(const char *key_name, uint16_t value)
  450. {
  451. return (icmap_set_uint16_r(icmap_global_map, key_name, value));
  452. }
  453. cs_error_t icmap_set_int32(const char *key_name, int32_t value)
  454. {
  455. return (icmap_set_int32_r(icmap_global_map, key_name, value));
  456. }
  457. cs_error_t icmap_set_uint32(const char *key_name, uint32_t value)
  458. {
  459. return (icmap_set_uint32_r(icmap_global_map, key_name, value));
  460. }
  461. cs_error_t icmap_set_int64(const char *key_name, int64_t value)
  462. {
  463. return (icmap_set_int64_r(icmap_global_map, key_name, value));
  464. }
  465. cs_error_t icmap_set_uint64(const char *key_name, uint64_t value)
  466. {
  467. return (icmap_set_uint64_r(icmap_global_map, key_name, value));
  468. }
  469. cs_error_t icmap_set_float(const char *key_name, float value)
  470. {
  471. return (icmap_set_float_r(icmap_global_map, key_name, value));
  472. }
  473. cs_error_t icmap_set_double(const char *key_name, double value)
  474. {
  475. return (icmap_set_double_r(icmap_global_map, key_name, value));
  476. }
  477. cs_error_t icmap_set_string(const char *key_name, const char *value)
  478. {
  479. return (icmap_set_string_r(icmap_global_map, key_name, value));
  480. }
  481. cs_error_t icmap_delete_r(const icmap_map_t map, const char *key_name)
  482. {
  483. struct icmap_item *item;
  484. if (key_name == NULL) {
  485. return (CS_ERR_INVALID_PARAM);
  486. }
  487. item = qb_map_get(map->qb_map, key_name);
  488. if (item == NULL) {
  489. return (CS_ERR_NOT_EXIST);
  490. }
  491. if (qb_map_rm(map->qb_map, item->key_name) != QB_TRUE) {
  492. return (CS_ERR_NOT_EXIST);
  493. }
  494. return (CS_OK);
  495. }
  496. cs_error_t icmap_delete(const char *key_name)
  497. {
  498. return (icmap_delete_r(icmap_global_map, key_name));
  499. }
  500. cs_error_t icmap_get_r(
  501. const icmap_map_t map,
  502. const char *key_name,
  503. void *value,
  504. size_t *value_len,
  505. icmap_value_types_t *type)
  506. {
  507. struct icmap_item *item;
  508. if (key_name == NULL) {
  509. return (CS_ERR_INVALID_PARAM);
  510. }
  511. item = qb_map_get(map->qb_map, key_name);
  512. if (item == NULL) {
  513. return (CS_ERR_NOT_EXIST);
  514. }
  515. if (type != NULL) {
  516. *type = item->type;
  517. }
  518. if (value == NULL) {
  519. if (value_len != NULL) {
  520. *value_len = item->value_len;
  521. }
  522. } else {
  523. if (value_len == NULL || *value_len < item->value_len) {
  524. return (CS_ERR_INVALID_PARAM);
  525. }
  526. *value_len = item->value_len;
  527. memcpy(value, item->value, item->value_len);
  528. }
  529. return (CS_OK);
  530. }
  531. cs_error_t icmap_get(
  532. const char *key_name,
  533. void *value,
  534. size_t *value_len,
  535. icmap_value_types_t *type)
  536. {
  537. return (icmap_get_r(icmap_global_map, key_name, value, value_len, type));
  538. }
  539. static cs_error_t icmap_get_int_r(
  540. const icmap_map_t map,
  541. const char *key_name,
  542. void *value,
  543. icmap_value_types_t type)
  544. {
  545. char key_value[16];
  546. size_t key_size;
  547. cs_error_t err;
  548. icmap_value_types_t key_type;
  549. key_size = sizeof(key_value);
  550. memset(key_value, 0, key_size);
  551. err = icmap_get(key_name, key_value, &key_size, &key_type);
  552. if (err != CS_OK)
  553. return (err);
  554. if (key_type != type) {
  555. return (CS_ERR_INVALID_PARAM);
  556. }
  557. memcpy(value, key_value, icmap_get_valuetype_len(key_type));
  558. return (CS_OK);
  559. }
  560. cs_error_t icmap_get_int8_r(const icmap_map_t map, const char *key_name, int8_t *i8)
  561. {
  562. return (icmap_get_int_r(map, key_name, i8, ICMAP_VALUETYPE_INT8));
  563. }
  564. cs_error_t icmap_get_uint8_r(const icmap_map_t map, const char *key_name, uint8_t *u8)
  565. {
  566. return (icmap_get_int_r(map, key_name, u8, ICMAP_VALUETYPE_UINT8));
  567. }
  568. cs_error_t icmap_get_int16_r(const icmap_map_t map, const char *key_name, int16_t *i16)
  569. {
  570. return (icmap_get_int_r(map, key_name, i16, ICMAP_VALUETYPE_INT16));
  571. }
  572. cs_error_t icmap_get_uint16_r(const icmap_map_t map, const char *key_name, uint16_t *u16)
  573. {
  574. return (icmap_get_int_r(map, key_name, u16, ICMAP_VALUETYPE_UINT16));
  575. }
  576. cs_error_t icmap_get_int32_r(const icmap_map_t map, const char *key_name, int32_t *i32)
  577. {
  578. return (icmap_get_int_r(map, key_name, i32, ICMAP_VALUETYPE_INT32));
  579. }
  580. cs_error_t icmap_get_uint32_r(const icmap_map_t map, const char *key_name, uint32_t *u32)
  581. {
  582. return (icmap_get_int_r(map, key_name, u32, ICMAP_VALUETYPE_UINT32));
  583. }
  584. cs_error_t icmap_get_int64_r(const icmap_map_t map, const char *key_name, int64_t *i64)
  585. {
  586. return(icmap_get_int_r(map, key_name, i64, ICMAP_VALUETYPE_INT64));
  587. }
  588. cs_error_t icmap_get_uint64_r(const icmap_map_t map, const char *key_name, uint64_t *u64)
  589. {
  590. return (icmap_get_int_r(map, key_name, u64, ICMAP_VALUETYPE_UINT64));
  591. }
  592. cs_error_t icmap_get_float_r(const icmap_map_t map, const char *key_name, float *flt)
  593. {
  594. return (icmap_get_int_r(map, key_name, flt, ICMAP_VALUETYPE_FLOAT));
  595. }
  596. cs_error_t icmap_get_double_r(const icmap_map_t map, const char *key_name, double *dbl)
  597. {
  598. return (icmap_get_int_r(map, key_name, dbl, ICMAP_VALUETYPE_DOUBLE));
  599. }
  600. cs_error_t icmap_get_int8(const char *key_name, int8_t *i8)
  601. {
  602. return (icmap_get_int8_r(icmap_global_map, key_name, i8));
  603. }
  604. cs_error_t icmap_get_uint8(const char *key_name, uint8_t *u8)
  605. {
  606. return (icmap_get_uint8_r(icmap_global_map, key_name, u8));
  607. }
  608. cs_error_t icmap_get_int16(const char *key_name, int16_t *i16)
  609. {
  610. return (icmap_get_int16_r(icmap_global_map, key_name, i16));
  611. }
  612. cs_error_t icmap_get_uint16(const char *key_name, uint16_t *u16)
  613. {
  614. return (icmap_get_uint16_r(icmap_global_map, key_name, u16));
  615. }
  616. cs_error_t icmap_get_int32(const char *key_name, int32_t *i32)
  617. {
  618. return (icmap_get_int32_r(icmap_global_map, key_name, i32));
  619. }
  620. cs_error_t icmap_get_uint32(const char *key_name, uint32_t *u32)
  621. {
  622. return (icmap_get_uint32_r(icmap_global_map, key_name, u32));
  623. }
  624. cs_error_t icmap_get_int64(const char *key_name, int64_t *i64)
  625. {
  626. return(icmap_get_int64_r(icmap_global_map, key_name, i64));
  627. }
  628. cs_error_t icmap_get_uint64(const char *key_name, uint64_t *u64)
  629. {
  630. return (icmap_get_uint64_r(icmap_global_map, key_name, u64));
  631. }
  632. cs_error_t icmap_get_float(const char *key_name, float *flt)
  633. {
  634. return (icmap_get_float_r(icmap_global_map, key_name, flt));
  635. }
  636. cs_error_t icmap_get_double(const char *key_name, double *dbl)
  637. {
  638. return (icmap_get_double_r(icmap_global_map, key_name, dbl));
  639. }
  640. cs_error_t icmap_get_string(const char *key_name, char **str)
  641. {
  642. cs_error_t res;
  643. size_t str_len;
  644. icmap_value_types_t type;
  645. res = icmap_get(key_name, NULL, &str_len, &type);
  646. if (res != CS_OK || type != ICMAP_VALUETYPE_STRING) {
  647. if (res == CS_OK) {
  648. res = CS_ERR_INVALID_PARAM;
  649. }
  650. goto return_error;
  651. }
  652. *str = malloc(str_len);
  653. if (*str == NULL) {
  654. res = CS_ERR_NO_MEMORY;
  655. goto return_error;
  656. }
  657. res = icmap_get(key_name, *str, &str_len, &type);
  658. if (res != CS_OK) {
  659. free(*str);
  660. goto return_error;
  661. }
  662. return (CS_OK);
  663. return_error:
  664. return (res);
  665. }
  666. cs_error_t icmap_adjust_int_r(
  667. const icmap_map_t map,
  668. const char *key_name,
  669. int32_t step)
  670. {
  671. struct icmap_item *item;
  672. uint8_t u8;
  673. uint16_t u16;
  674. uint32_t u32;
  675. uint64_t u64;
  676. cs_error_t err = CS_OK;
  677. if (key_name == NULL) {
  678. return (CS_ERR_INVALID_PARAM);
  679. }
  680. item = qb_map_get(map->qb_map, key_name);
  681. if (item == NULL) {
  682. return (CS_ERR_NOT_EXIST);
  683. }
  684. switch (item->type) {
  685. case ICMAP_VALUETYPE_INT8:
  686. case ICMAP_VALUETYPE_UINT8:
  687. memcpy(&u8, item->value, sizeof(u8));
  688. u8 += step;
  689. err = icmap_set(key_name, &u8, sizeof(u8), item->type);
  690. break;
  691. case ICMAP_VALUETYPE_INT16:
  692. case ICMAP_VALUETYPE_UINT16:
  693. memcpy(&u16, item->value, sizeof(u16));
  694. u16 += step;
  695. err = icmap_set(key_name, &u16, sizeof(u16), item->type);
  696. break;
  697. case ICMAP_VALUETYPE_INT32:
  698. case ICMAP_VALUETYPE_UINT32:
  699. memcpy(&u32, item->value, sizeof(u32));
  700. u32 += step;
  701. err = icmap_set(key_name, &u32, sizeof(u32), item->type);
  702. break;
  703. case ICMAP_VALUETYPE_INT64:
  704. case ICMAP_VALUETYPE_UINT64:
  705. memcpy(&u64, item->value, sizeof(u64));
  706. u64 += step;
  707. err = icmap_set(key_name, &u64, sizeof(u64), item->type);
  708. break;
  709. case ICMAP_VALUETYPE_FLOAT:
  710. case ICMAP_VALUETYPE_DOUBLE:
  711. case ICMAP_VALUETYPE_STRING:
  712. case ICMAP_VALUETYPE_BINARY:
  713. err = CS_ERR_INVALID_PARAM;
  714. break;
  715. }
  716. return (err);
  717. }
  718. cs_error_t icmap_adjust_int(
  719. const char *key_name,
  720. int32_t step)
  721. {
  722. return (icmap_adjust_int_r(icmap_global_map, key_name, step));
  723. }
  724. cs_error_t icmap_fast_adjust_int_r(
  725. const icmap_map_t map,
  726. const char *key_name,
  727. int32_t step)
  728. {
  729. struct icmap_item *item;
  730. cs_error_t err = CS_OK;
  731. if (key_name == NULL) {
  732. return (CS_ERR_INVALID_PARAM);
  733. }
  734. item = qb_map_get(map->qb_map, key_name);
  735. if (item == NULL) {
  736. return (CS_ERR_NOT_EXIST);
  737. }
  738. switch (item->type) {
  739. case ICMAP_VALUETYPE_INT8:
  740. case ICMAP_VALUETYPE_UINT8:
  741. *(uint8_t *)item->value += step;
  742. break;
  743. case ICMAP_VALUETYPE_INT16:
  744. case ICMAP_VALUETYPE_UINT16:
  745. *(uint16_t *)item->value += step;
  746. break;
  747. case ICMAP_VALUETYPE_INT32:
  748. case ICMAP_VALUETYPE_UINT32:
  749. *(uint32_t *)item->value += step;
  750. break;
  751. case ICMAP_VALUETYPE_INT64:
  752. case ICMAP_VALUETYPE_UINT64:
  753. *(uint64_t *)item->value += step;
  754. break;
  755. case ICMAP_VALUETYPE_FLOAT:
  756. case ICMAP_VALUETYPE_DOUBLE:
  757. case ICMAP_VALUETYPE_STRING:
  758. case ICMAP_VALUETYPE_BINARY:
  759. err = CS_ERR_INVALID_PARAM;
  760. break;
  761. }
  762. if (err == CS_OK) {
  763. qb_map_put(map->qb_map, item->key_name, item);
  764. }
  765. return (err);
  766. }
  767. cs_error_t icmap_fast_adjust_int(
  768. const char *key_name,
  769. int32_t step)
  770. {
  771. return (icmap_fast_adjust_int_r(icmap_global_map, key_name, step));
  772. }
  773. cs_error_t icmap_inc_r(const icmap_map_t map, const char *key_name)
  774. {
  775. return (icmap_adjust_int_r(map, key_name, 1));
  776. }
  777. cs_error_t icmap_inc(const char *key_name)
  778. {
  779. return (icmap_inc_r(icmap_global_map, key_name));
  780. }
  781. cs_error_t icmap_dec_r(const icmap_map_t map, const char *key_name)
  782. {
  783. return (icmap_adjust_int_r(map, key_name, -1));
  784. }
  785. cs_error_t icmap_dec(const char *key_name)
  786. {
  787. return (icmap_dec_r(icmap_global_map, key_name));
  788. }
  789. cs_error_t icmap_fast_inc_r(const icmap_map_t map, const char *key_name)
  790. {
  791. return (icmap_fast_adjust_int_r(map, key_name, 1));
  792. }
  793. cs_error_t icmap_fast_inc(const char *key_name)
  794. {
  795. return (icmap_fast_inc_r(icmap_global_map, key_name));
  796. }
  797. cs_error_t icmap_fast_dec_r(const icmap_map_t map, const char *key_name)
  798. {
  799. return (icmap_fast_adjust_int_r(map, key_name, -1));
  800. }
  801. cs_error_t icmap_fast_dec(const char *key_name)
  802. {
  803. return (icmap_fast_dec_r(icmap_global_map, key_name));
  804. }
  805. icmap_iter_t icmap_iter_init_r(const icmap_map_t map, const char *prefix)
  806. {
  807. return (qb_map_pref_iter_create(map->qb_map, prefix));
  808. }
  809. icmap_iter_t icmap_iter_init(const char *prefix)
  810. {
  811. return (icmap_iter_init_r(icmap_global_map, prefix));
  812. }
  813. const char *icmap_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
  814. {
  815. struct icmap_item *item;
  816. const char *res;
  817. res = qb_map_iter_next(iter, (void **)&item);
  818. if (res == NULL) {
  819. return (res);
  820. }
  821. if (value_len != NULL) {
  822. *value_len = item->value_len;
  823. }
  824. if (type != NULL) {
  825. *type = item->type;
  826. }
  827. return (res);
  828. }
  829. void icmap_iter_finalize(icmap_iter_t iter)
  830. {
  831. qb_map_iter_free(iter);
  832. }
  833. static void icmap_notify_fn(uint32_t event, char *key, void *old_value, void *value, void *user_data)
  834. {
  835. icmap_track_t icmap_track = (icmap_track_t)user_data;
  836. struct icmap_item *new_item = (struct icmap_item *)value;
  837. struct icmap_item *old_item = (struct icmap_item *)old_value;
  838. struct icmap_notify_value new_val;
  839. struct icmap_notify_value old_val;
  840. if (value == NULL && old_value == NULL) {
  841. return ;
  842. }
  843. if (new_item != NULL) {
  844. new_val.type = new_item->type;
  845. new_val.len = new_item->value_len;
  846. new_val.data = new_item->value;
  847. } else {
  848. memset(&new_val, 0, sizeof(new_val));
  849. }
  850. /*
  851. * old_item == new_item if fast functions are used -> don't fill old value
  852. */
  853. if (old_item != NULL && old_item != new_item) {
  854. old_val.type = old_item->type;
  855. old_val.len = old_item->value_len;
  856. old_val.data = old_item->value;
  857. } else {
  858. memset(&old_val, 0, sizeof(old_val));
  859. }
  860. icmap_track->notify_fn(icmap_qbtt_to_tt(event),
  861. key,
  862. new_val,
  863. old_val,
  864. icmap_track->user_data);
  865. }
  866. cs_error_t icmap_track_add(
  867. const char *key_name,
  868. int32_t track_type,
  869. icmap_notify_fn_t notify_fn,
  870. void *user_data,
  871. icmap_track_t *icmap_track)
  872. {
  873. int32_t err;
  874. if (notify_fn == NULL || icmap_track == NULL) {
  875. return (CS_ERR_INVALID_PARAM);
  876. }
  877. if ((track_type & ~(ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX)) != 0) {
  878. return (CS_ERR_INVALID_PARAM);
  879. }
  880. *icmap_track = malloc(sizeof(**icmap_track));
  881. if (*icmap_track == NULL) {
  882. return (CS_ERR_NO_MEMORY);
  883. }
  884. memset(*icmap_track, 0, sizeof(**icmap_track));
  885. if (key_name != NULL) {
  886. (*icmap_track)->key_name = strdup(key_name);
  887. };
  888. (*icmap_track)->track_type = track_type;
  889. (*icmap_track)->notify_fn = notify_fn;
  890. (*icmap_track)->user_data = user_data;
  891. if ((err = qb_map_notify_add(icmap_global_map->qb_map, (*icmap_track)->key_name, icmap_notify_fn,
  892. icmap_tt_to_qbtt(track_type), *icmap_track)) != 0) {
  893. free((*icmap_track)->key_name);
  894. free(*icmap_track);
  895. return (qb_to_cs_error(err));
  896. }
  897. list_init(&(*icmap_track)->list);
  898. list_add (&(*icmap_track)->list, &icmap_track_list_head);
  899. return (CS_OK);
  900. }
  901. cs_error_t icmap_track_delete(icmap_track_t icmap_track)
  902. {
  903. int32_t err;
  904. if ((err = qb_map_notify_del_2(icmap_global_map->qb_map, icmap_track->key_name,
  905. icmap_notify_fn, icmap_tt_to_qbtt(icmap_track->track_type), icmap_track)) != 0) {
  906. return (qb_to_cs_error(err));
  907. }
  908. list_del(&icmap_track->list);
  909. free(icmap_track->key_name);
  910. free(icmap_track);
  911. return (CS_OK);
  912. }
  913. void *icmap_track_get_user_data(icmap_track_t icmap_track)
  914. {
  915. return (icmap_track->user_data);
  916. }
  917. cs_error_t icmap_set_ro_access(const char *key_name, int prefix, int ro_access)
  918. {
  919. struct list_head *iter;
  920. struct icmap_ro_access_item *icmap_ro_ai;
  921. for (iter = icmap_ro_access_item_list_head.next; iter != &icmap_ro_access_item_list_head; iter = iter->next) {
  922. icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
  923. if (icmap_ro_ai->prefix == prefix && strcmp(key_name, icmap_ro_ai->key_name) == 0) {
  924. /*
  925. * We found item
  926. */
  927. if (ro_access) {
  928. return (CS_ERR_EXIST);
  929. } else {
  930. list_del(&icmap_ro_ai->list);
  931. free(icmap_ro_ai->key_name);
  932. free(icmap_ro_ai);
  933. return (CS_OK);
  934. }
  935. }
  936. }
  937. if (!ro_access) {
  938. return (CS_ERR_NOT_EXIST);
  939. }
  940. icmap_ro_ai = malloc(sizeof(*icmap_ro_ai));
  941. if (icmap_ro_ai == NULL) {
  942. return (CS_ERR_NO_MEMORY);
  943. }
  944. memset(icmap_ro_ai, 0, sizeof(*icmap_ro_ai));
  945. icmap_ro_ai->key_name = strdup(key_name);
  946. if (icmap_ro_ai->key_name == NULL) {
  947. free(icmap_ro_ai);
  948. return (CS_ERR_NO_MEMORY);
  949. }
  950. icmap_ro_ai->prefix = prefix;
  951. list_init(&icmap_ro_ai->list);
  952. list_add (&icmap_ro_ai->list, &icmap_ro_access_item_list_head);
  953. return (CS_OK);
  954. }
  955. int icmap_is_key_ro(const char *key_name)
  956. {
  957. struct list_head *iter;
  958. struct icmap_ro_access_item *icmap_ro_ai;
  959. for (iter = icmap_ro_access_item_list_head.next; iter != &icmap_ro_access_item_list_head; iter = iter->next) {
  960. icmap_ro_ai = list_entry(iter, struct icmap_ro_access_item, list);
  961. if (icmap_ro_ai->prefix) {
  962. if (strlen(icmap_ro_ai->key_name) > strlen(key_name))
  963. continue;
  964. if (strncmp(icmap_ro_ai->key_name, key_name, strlen(icmap_ro_ai->key_name)) == 0) {
  965. return (CS_TRUE);
  966. }
  967. } else {
  968. if (strcmp(icmap_ro_ai->key_name, key_name) == 0) {
  969. return (CS_TRUE);
  970. }
  971. }
  972. }
  973. return (CS_FALSE);
  974. }