cmap.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. /*
  2. * Copyright (c) 2011-2012 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 <sys/types.h>
  36. #include <unistd.h>
  37. #include <fcntl.h>
  38. #include <stdlib.h>
  39. #include <errno.h>
  40. #include <poll.h>
  41. #include <assert.h>
  42. #include <qb/qbloop.h>
  43. #include <qb/qbipc_common.h>
  44. #include <corosync/corotypes.h>
  45. #include <corosync/corodefs.h>
  46. #include <corosync/mar_gen.h>
  47. #include <corosync/ipc_cmap.h>
  48. #include <corosync/logsys.h>
  49. #include <corosync/coroapi.h>
  50. #include <corosync/icmap.h>
  51. #include "service.h"
  52. LOGSYS_DECLARE_SUBSYS ("CMAP");
  53. #define MAX_REQ_EXEC_CMAP_MCAST_ITEMS 32
  54. #define ICMAP_VALUETYPE_NOT_EXIST 0
  55. struct cmap_conn_info {
  56. struct hdb_handle_database iter_db;
  57. struct hdb_handle_database track_db;
  58. };
  59. typedef uint64_t cmap_iter_handle_t;
  60. typedef uint64_t cmap_track_handle_t;
  61. struct cmap_track_user_data {
  62. void *conn;
  63. cmap_track_handle_t track_handle;
  64. uint64_t track_inst_handle;
  65. };
  66. enum cmap_message_req_types {
  67. MESSAGE_REQ_EXEC_CMAP_MCAST = 0,
  68. };
  69. enum cmap_mcast_reason {
  70. CMAP_MCAST_REASON_SYNC = 0,
  71. CMAP_MCAST_REASON_NEW_CONFIG_VERSION = 1,
  72. };
  73. static struct corosync_api_v1 *api;
  74. static char *cmap_exec_init_fn (struct corosync_api_v1 *corosync_api);
  75. static int cmap_exec_exit_fn(void);
  76. static int cmap_lib_init_fn (void *conn);
  77. static int cmap_lib_exit_fn (void *conn);
  78. static void message_handler_req_lib_cmap_set(void *conn, const void *message);
  79. static void message_handler_req_lib_cmap_delete(void *conn, const void *message);
  80. static void message_handler_req_lib_cmap_get(void *conn, const void *message);
  81. static void message_handler_req_lib_cmap_adjust_int(void *conn, const void *message);
  82. static void message_handler_req_lib_cmap_iter_init(void *conn, const void *message);
  83. static void message_handler_req_lib_cmap_iter_next(void *conn, const void *message);
  84. static void message_handler_req_lib_cmap_iter_finalize(void *conn, const void *message);
  85. static void message_handler_req_lib_cmap_track_add(void *conn, const void *message);
  86. static void message_handler_req_lib_cmap_track_delete(void *conn, const void *message);
  87. static void cmap_notify_fn(int32_t event,
  88. const char *key_name,
  89. struct icmap_notify_value new_val,
  90. struct icmap_notify_value old_val,
  91. void *user_data);
  92. static void message_handler_req_exec_cmap_mcast(
  93. const void *message,
  94. unsigned int nodeid);
  95. static void exec_cmap_mcast_endian_convert(void *message);
  96. /*
  97. * Reson is subtype of message. argc is number of items in argv array. Argv is array
  98. * of strings (key names) which will be send to wire. There can be maximum
  99. * MAX_REQ_EXEC_CMAP_MCAST_ITEMS items (for more items, CS_ERR_TOO_MANY_GROUPS
  100. * error is returned). If key is not found, item has type ICMAP_VALUETYPE_NOT_EXIST
  101. * and length zero.
  102. */
  103. static cs_error_t cmap_mcast_send(enum cmap_mcast_reason reason, int argc, char *argv[]);
  104. static void cmap_sync_init (
  105. const unsigned int *trans_list,
  106. size_t trans_list_entries,
  107. const unsigned int *member_list,
  108. size_t member_list_entries,
  109. const struct memb_ring_id *ring_id);
  110. static int cmap_sync_process (void);
  111. static void cmap_sync_activate (void);
  112. static void cmap_sync_abort (void);
  113. static void cmap_config_version_track_cb(
  114. int32_t event,
  115. const char *key_name,
  116. struct icmap_notify_value new_value,
  117. struct icmap_notify_value old_value,
  118. void *user_data);
  119. /*
  120. * Library Handler Definition
  121. */
  122. static struct corosync_lib_handler cmap_lib_engine[] =
  123. {
  124. { /* 0 */
  125. .lib_handler_fn = message_handler_req_lib_cmap_set,
  126. .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
  127. },
  128. { /* 1 */
  129. .lib_handler_fn = message_handler_req_lib_cmap_delete,
  130. .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
  131. },
  132. { /* 2 */
  133. .lib_handler_fn = message_handler_req_lib_cmap_get,
  134. .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
  135. },
  136. { /* 3 */
  137. .lib_handler_fn = message_handler_req_lib_cmap_adjust_int,
  138. .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
  139. },
  140. { /* 4 */
  141. .lib_handler_fn = message_handler_req_lib_cmap_iter_init,
  142. .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
  143. },
  144. { /* 5 */
  145. .lib_handler_fn = message_handler_req_lib_cmap_iter_next,
  146. .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
  147. },
  148. { /* 6 */
  149. .lib_handler_fn = message_handler_req_lib_cmap_iter_finalize,
  150. .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
  151. },
  152. { /* 7 */
  153. .lib_handler_fn = message_handler_req_lib_cmap_track_add,
  154. .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
  155. },
  156. { /* 8 */
  157. .lib_handler_fn = message_handler_req_lib_cmap_track_delete,
  158. .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED
  159. },
  160. };
  161. static struct corosync_exec_handler cmap_exec_engine[] =
  162. {
  163. { /* 0 - MESSAGE_REQ_EXEC_CMAP_MCAST */
  164. .exec_handler_fn = message_handler_req_exec_cmap_mcast,
  165. .exec_endian_convert_fn = exec_cmap_mcast_endian_convert
  166. },
  167. };
  168. struct corosync_service_engine cmap_service_engine = {
  169. .name = "corosync configuration map access",
  170. .id = CMAP_SERVICE,
  171. .priority = 1,
  172. .private_data_size = sizeof(struct cmap_conn_info),
  173. .flow_control = CS_LIB_FLOW_CONTROL_NOT_REQUIRED,
  174. .allow_inquorate = CS_LIB_ALLOW_INQUORATE,
  175. .lib_init_fn = cmap_lib_init_fn,
  176. .lib_exit_fn = cmap_lib_exit_fn,
  177. .lib_engine = cmap_lib_engine,
  178. .lib_engine_count = sizeof (cmap_lib_engine) / sizeof (struct corosync_lib_handler),
  179. .exec_init_fn = cmap_exec_init_fn,
  180. .exec_exit_fn = cmap_exec_exit_fn,
  181. .exec_engine = cmap_exec_engine,
  182. .exec_engine_count = sizeof (cmap_exec_engine) / sizeof (struct corosync_exec_handler),
  183. .sync_init = cmap_sync_init,
  184. .sync_process = cmap_sync_process,
  185. .sync_activate = cmap_sync_activate,
  186. .sync_abort = cmap_sync_abort
  187. };
  188. struct corosync_service_engine *cmap_get_service_engine_ver0 (void)
  189. {
  190. return (&cmap_service_engine);
  191. }
  192. struct req_exec_cmap_mcast_item {
  193. mar_name_t key_name __attribute__((aligned(8)));
  194. mar_uint8_t value_type __attribute__((aligned(8)));
  195. mar_size_t value_len __attribute__((aligned(8)));
  196. uint8_t value[] __attribute__((aligned(8)));
  197. };
  198. struct req_exec_cmap_mcast {
  199. struct qb_ipc_request_header header __attribute__((aligned(8)));
  200. mar_uint8_t reason __attribute__((aligned(8)));
  201. mar_uint8_t no_items __attribute__((aligned(8)));
  202. mar_uint8_t reserved1 __attribute__((aligned(8)));
  203. mar_uint8_t reserver2 __attribute__((aligned(8)));
  204. /*
  205. * Following are array of req_exec_cmap_mcast_item alligned to 8 bytes
  206. */
  207. };
  208. static size_t cmap_sync_trans_list_entries = 0;
  209. static size_t cmap_sync_member_list_entries = 0;
  210. static uint64_t cmap_highest_config_version_received = 0;
  211. static uint64_t cmap_my_config_version = 0;
  212. static int cmap_first_sync = 1;
  213. static icmap_track_t cmap_config_version_track;
  214. static void cmap_config_version_track_cb(
  215. int32_t event,
  216. const char *key_name,
  217. struct icmap_notify_value new_value,
  218. struct icmap_notify_value old_value,
  219. void *user_data)
  220. {
  221. const char *key = "totem.config_version";
  222. cs_error_t ret;
  223. ENTER();
  224. if (icmap_get_uint64("totem.config_version", &cmap_my_config_version) != CS_OK) {
  225. cmap_my_config_version = 0;
  226. }
  227. ret = cmap_mcast_send(CMAP_MCAST_REASON_NEW_CONFIG_VERSION, 1, (char **)&key);
  228. if (ret != CS_OK) {
  229. log_printf(LOGSYS_LEVEL_ERROR, "Can't inform other nodes about new config version");
  230. }
  231. LEAVE();
  232. }
  233. static int cmap_exec_exit_fn(void)
  234. {
  235. if (icmap_track_delete(cmap_config_version_track) != CS_OK) {
  236. log_printf(LOGSYS_LEVEL_ERROR, "Can't delete config_version icmap tracker");
  237. }
  238. return 0;
  239. }
  240. static char *cmap_exec_init_fn (
  241. struct corosync_api_v1 *corosync_api)
  242. {
  243. cs_error_t ret;
  244. api = corosync_api;
  245. ret = icmap_track_add("totem.config_version",
  246. ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY,
  247. cmap_config_version_track_cb,
  248. NULL,
  249. &cmap_config_version_track);
  250. if (ret != CS_OK) {
  251. return ((char *)"Can't add config_version icmap tracker");
  252. }
  253. return (NULL);
  254. }
  255. static int cmap_lib_init_fn (void *conn)
  256. {
  257. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  258. log_printf(LOGSYS_LEVEL_DEBUG, "lib_init_fn: conn=%p", conn);
  259. api->ipc_refcnt_inc(conn);
  260. memset(conn_info, 0, sizeof(*conn_info));
  261. hdb_create(&conn_info->iter_db);
  262. hdb_create(&conn_info->track_db);
  263. return (0);
  264. }
  265. static int cmap_lib_exit_fn (void *conn)
  266. {
  267. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  268. hdb_handle_t iter_handle = 0;
  269. icmap_iter_t *iter;
  270. hdb_handle_t track_handle = 0;
  271. icmap_track_t *track;
  272. log_printf(LOGSYS_LEVEL_DEBUG, "exit_fn for conn=%p", conn);
  273. hdb_iterator_reset(&conn_info->iter_db);
  274. while (hdb_iterator_next(&conn_info->iter_db,
  275. (void*)&iter, &iter_handle) == 0) {
  276. icmap_iter_finalize(*iter);
  277. (void)hdb_handle_put (&conn_info->iter_db, iter_handle);
  278. }
  279. hdb_destroy(&conn_info->iter_db);
  280. hdb_iterator_reset(&conn_info->track_db);
  281. while (hdb_iterator_next(&conn_info->track_db,
  282. (void*)&track, &track_handle) == 0) {
  283. free(icmap_track_get_user_data(*track));
  284. icmap_track_delete(*track);
  285. (void)hdb_handle_put (&conn_info->track_db, track_handle);
  286. }
  287. hdb_destroy(&conn_info->track_db);
  288. api->ipc_refcnt_dec(conn);
  289. return (0);
  290. }
  291. static void cmap_sync_init (
  292. const unsigned int *trans_list,
  293. size_t trans_list_entries,
  294. const unsigned int *member_list,
  295. size_t member_list_entries,
  296. const struct memb_ring_id *ring_id)
  297. {
  298. cmap_sync_trans_list_entries = trans_list_entries;
  299. cmap_sync_member_list_entries = member_list_entries;
  300. cmap_highest_config_version_received = 0;
  301. if (icmap_get_uint64("totem.config_version", &cmap_my_config_version) != CS_OK) {
  302. cmap_my_config_version = 0;
  303. }
  304. }
  305. static int cmap_sync_process (void)
  306. {
  307. const char *key = "totem.config_version";
  308. cs_error_t ret;
  309. ret = cmap_mcast_send(CMAP_MCAST_REASON_SYNC, 1, (char **)&key);
  310. return (ret == CS_OK ? 0 : -1);
  311. }
  312. static void cmap_sync_activate (void)
  313. {
  314. if (cmap_sync_trans_list_entries == 0) {
  315. log_printf(LOGSYS_LEVEL_DEBUG, "Single node sync -> no action");
  316. return ;
  317. }
  318. if (cmap_first_sync == 1) {
  319. cmap_first_sync = 0;
  320. } else {
  321. log_printf(LOGSYS_LEVEL_DEBUG, "Not first sync -> no action");
  322. return ;
  323. }
  324. if (cmap_my_config_version == 0) {
  325. log_printf(LOGSYS_LEVEL_DEBUG, "My config version is 0 -> no action");
  326. return ;
  327. }
  328. if (cmap_highest_config_version_received == 0) {
  329. log_printf(LOGSYS_LEVEL_DEBUG, "Other nodes version is 0 -> no action");
  330. return ;
  331. }
  332. if (cmap_highest_config_version_received != cmap_my_config_version) {
  333. log_printf(LOGSYS_LEVEL_ERROR,
  334. "Received config version (%"PRIu64") is different than my config version (%"PRIu64")! Exiting",
  335. cmap_highest_config_version_received, cmap_my_config_version);
  336. api->shutdown_request();
  337. return ;
  338. }
  339. }
  340. static void cmap_sync_abort (void)
  341. {
  342. }
  343. static void message_handler_req_lib_cmap_set(void *conn, const void *message)
  344. {
  345. const struct req_lib_cmap_set *req_lib_cmap_set = message;
  346. struct res_lib_cmap_set res_lib_cmap_set;
  347. cs_error_t ret;
  348. if (icmap_is_key_ro((char *)req_lib_cmap_set->key_name.value)) {
  349. ret = CS_ERR_ACCESS;
  350. } else {
  351. ret = icmap_set((char *)req_lib_cmap_set->key_name.value, &req_lib_cmap_set->value,
  352. req_lib_cmap_set->value_len, req_lib_cmap_set->type);
  353. }
  354. memset(&res_lib_cmap_set, 0, sizeof(res_lib_cmap_set));
  355. res_lib_cmap_set.header.size = sizeof(res_lib_cmap_set);
  356. res_lib_cmap_set.header.id = MESSAGE_RES_CMAP_SET;
  357. res_lib_cmap_set.header.error = ret;
  358. api->ipc_response_send(conn, &res_lib_cmap_set, sizeof(res_lib_cmap_set));
  359. }
  360. static void message_handler_req_lib_cmap_delete(void *conn, const void *message)
  361. {
  362. const struct req_lib_cmap_set *req_lib_cmap_set = message;
  363. struct res_lib_cmap_delete res_lib_cmap_delete;
  364. cs_error_t ret;
  365. if (icmap_is_key_ro((char *)req_lib_cmap_set->key_name.value)) {
  366. ret = CS_ERR_ACCESS;
  367. } else {
  368. ret = icmap_delete((char *)req_lib_cmap_set->key_name.value);
  369. }
  370. memset(&res_lib_cmap_delete, 0, sizeof(res_lib_cmap_delete));
  371. res_lib_cmap_delete.header.size = sizeof(res_lib_cmap_delete);
  372. res_lib_cmap_delete.header.id = MESSAGE_RES_CMAP_DELETE;
  373. res_lib_cmap_delete.header.error = ret;
  374. api->ipc_response_send(conn, &res_lib_cmap_delete, sizeof(res_lib_cmap_delete));
  375. }
  376. static void message_handler_req_lib_cmap_get(void *conn, const void *message)
  377. {
  378. const struct req_lib_cmap_get *req_lib_cmap_get = message;
  379. struct res_lib_cmap_get *res_lib_cmap_get;
  380. struct res_lib_cmap_get error_res_lib_cmap_get;
  381. cs_error_t ret;
  382. size_t value_len;
  383. size_t res_lib_cmap_get_size;
  384. icmap_value_types_t type;
  385. void *value;
  386. value_len = req_lib_cmap_get->value_len;
  387. res_lib_cmap_get_size = sizeof(*res_lib_cmap_get) + value_len;
  388. res_lib_cmap_get = malloc(res_lib_cmap_get_size);
  389. if (res_lib_cmap_get == NULL) {
  390. ret = CS_ERR_NO_MEMORY;
  391. goto error_exit;
  392. }
  393. memset(res_lib_cmap_get, 0, res_lib_cmap_get_size);
  394. if (value_len > 0) {
  395. value = res_lib_cmap_get->value;
  396. } else {
  397. value = NULL;
  398. }
  399. ret = icmap_get((char *)req_lib_cmap_get->key_name.value,
  400. value,
  401. &value_len,
  402. &type);
  403. if (ret != CS_OK) {
  404. free(res_lib_cmap_get);
  405. goto error_exit;
  406. }
  407. res_lib_cmap_get->header.size = res_lib_cmap_get_size;
  408. res_lib_cmap_get->header.id = MESSAGE_RES_CMAP_GET;
  409. res_lib_cmap_get->header.error = ret;
  410. res_lib_cmap_get->type = type;
  411. res_lib_cmap_get->value_len = value_len;
  412. api->ipc_response_send(conn, res_lib_cmap_get, res_lib_cmap_get_size);
  413. free(res_lib_cmap_get);
  414. return ;
  415. error_exit:
  416. memset(&error_res_lib_cmap_get, 0, sizeof(error_res_lib_cmap_get));
  417. error_res_lib_cmap_get.header.size = sizeof(error_res_lib_cmap_get);
  418. error_res_lib_cmap_get.header.id = MESSAGE_RES_CMAP_GET;
  419. error_res_lib_cmap_get.header.error = ret;
  420. api->ipc_response_send(conn, &error_res_lib_cmap_get, sizeof(error_res_lib_cmap_get));
  421. }
  422. static void message_handler_req_lib_cmap_adjust_int(void *conn, const void *message)
  423. {
  424. const struct req_lib_cmap_adjust_int *req_lib_cmap_adjust_int = message;
  425. struct res_lib_cmap_adjust_int res_lib_cmap_adjust_int;
  426. cs_error_t ret;
  427. if (icmap_is_key_ro((char *)req_lib_cmap_adjust_int->key_name.value)) {
  428. ret = CS_ERR_ACCESS;
  429. } else {
  430. ret = icmap_adjust_int((char *)req_lib_cmap_adjust_int->key_name.value,
  431. req_lib_cmap_adjust_int->step);
  432. }
  433. memset(&res_lib_cmap_adjust_int, 0, sizeof(res_lib_cmap_adjust_int));
  434. res_lib_cmap_adjust_int.header.size = sizeof(res_lib_cmap_adjust_int);
  435. res_lib_cmap_adjust_int.header.id = MESSAGE_RES_CMAP_ADJUST_INT;
  436. res_lib_cmap_adjust_int.header.error = ret;
  437. api->ipc_response_send(conn, &res_lib_cmap_adjust_int, sizeof(res_lib_cmap_adjust_int));
  438. }
  439. static void message_handler_req_lib_cmap_iter_init(void *conn, const void *message)
  440. {
  441. const struct req_lib_cmap_iter_init *req_lib_cmap_iter_init = message;
  442. struct res_lib_cmap_iter_init res_lib_cmap_iter_init;
  443. cs_error_t ret;
  444. icmap_iter_t iter;
  445. icmap_iter_t *hdb_iter;
  446. cmap_iter_handle_t handle = 0ULL;
  447. const char *prefix;
  448. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  449. if (req_lib_cmap_iter_init->prefix.length > 0) {
  450. prefix = (char *)req_lib_cmap_iter_init->prefix.value;
  451. } else {
  452. prefix = NULL;
  453. }
  454. iter = icmap_iter_init(prefix);
  455. if (iter == NULL) {
  456. ret = CS_ERR_NO_SECTIONS;
  457. goto reply_send;
  458. }
  459. ret = hdb_error_to_cs(hdb_handle_create(&conn_info->iter_db, sizeof(iter), &handle));
  460. if (ret != CS_OK) {
  461. goto reply_send;
  462. }
  463. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->iter_db, handle, (void *)&hdb_iter));
  464. if (ret != CS_OK) {
  465. goto reply_send;
  466. }
  467. *hdb_iter = iter;
  468. (void)hdb_handle_put (&conn_info->iter_db, handle);
  469. reply_send:
  470. memset(&res_lib_cmap_iter_init, 0, sizeof(res_lib_cmap_iter_init));
  471. res_lib_cmap_iter_init.header.size = sizeof(res_lib_cmap_iter_init);
  472. res_lib_cmap_iter_init.header.id = MESSAGE_RES_CMAP_ITER_INIT;
  473. res_lib_cmap_iter_init.header.error = ret;
  474. res_lib_cmap_iter_init.iter_handle = handle;
  475. api->ipc_response_send(conn, &res_lib_cmap_iter_init, sizeof(res_lib_cmap_iter_init));
  476. }
  477. static void message_handler_req_lib_cmap_iter_next(void *conn, const void *message)
  478. {
  479. const struct req_lib_cmap_iter_next *req_lib_cmap_iter_next = message;
  480. struct res_lib_cmap_iter_next res_lib_cmap_iter_next;
  481. cs_error_t ret;
  482. icmap_iter_t *iter;
  483. size_t value_len = 0;
  484. icmap_value_types_t type = 0;
  485. const char *res = NULL;
  486. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  487. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->iter_db,
  488. req_lib_cmap_iter_next->iter_handle, (void *)&iter));
  489. if (ret != CS_OK) {
  490. goto reply_send;
  491. }
  492. res = icmap_iter_next(*iter, &value_len, &type);
  493. if (res == NULL) {
  494. ret = CS_ERR_NO_SECTIONS;
  495. }
  496. (void)hdb_handle_put (&conn_info->iter_db, req_lib_cmap_iter_next->iter_handle);
  497. reply_send:
  498. memset(&res_lib_cmap_iter_next, 0, sizeof(res_lib_cmap_iter_next));
  499. res_lib_cmap_iter_next.header.size = sizeof(res_lib_cmap_iter_next);
  500. res_lib_cmap_iter_next.header.id = MESSAGE_RES_CMAP_ITER_NEXT;
  501. res_lib_cmap_iter_next.header.error = ret;
  502. if (res != NULL) {
  503. res_lib_cmap_iter_next.value_len = value_len;
  504. res_lib_cmap_iter_next.type = type;
  505. memcpy(res_lib_cmap_iter_next.key_name.value, res, strlen(res));
  506. res_lib_cmap_iter_next.key_name.length = strlen(res);
  507. }
  508. api->ipc_response_send(conn, &res_lib_cmap_iter_next, sizeof(res_lib_cmap_iter_next));
  509. }
  510. static void message_handler_req_lib_cmap_iter_finalize(void *conn, const void *message)
  511. {
  512. const struct req_lib_cmap_iter_finalize *req_lib_cmap_iter_finalize = message;
  513. struct res_lib_cmap_iter_finalize res_lib_cmap_iter_finalize;
  514. cs_error_t ret;
  515. icmap_iter_t *iter;
  516. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  517. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->iter_db,
  518. req_lib_cmap_iter_finalize->iter_handle, (void *)&iter));
  519. if (ret != CS_OK) {
  520. goto reply_send;
  521. }
  522. icmap_iter_finalize(*iter);
  523. (void)hdb_handle_destroy(&conn_info->iter_db, req_lib_cmap_iter_finalize->iter_handle);
  524. (void)hdb_handle_put (&conn_info->iter_db, req_lib_cmap_iter_finalize->iter_handle);
  525. reply_send:
  526. memset(&res_lib_cmap_iter_finalize, 0, sizeof(res_lib_cmap_iter_finalize));
  527. res_lib_cmap_iter_finalize.header.size = sizeof(res_lib_cmap_iter_finalize);
  528. res_lib_cmap_iter_finalize.header.id = MESSAGE_RES_CMAP_ITER_FINALIZE;
  529. res_lib_cmap_iter_finalize.header.error = ret;
  530. api->ipc_response_send(conn, &res_lib_cmap_iter_finalize, sizeof(res_lib_cmap_iter_finalize));
  531. }
  532. static void cmap_notify_fn(int32_t event,
  533. const char *key_name,
  534. struct icmap_notify_value new_val,
  535. struct icmap_notify_value old_val,
  536. void *user_data)
  537. {
  538. struct cmap_track_user_data *cmap_track_user_data = (struct cmap_track_user_data *)user_data;
  539. struct res_lib_cmap_notify_callback res_lib_cmap_notify_callback;
  540. struct iovec iov[3];
  541. memset(&res_lib_cmap_notify_callback, 0, sizeof(res_lib_cmap_notify_callback));
  542. res_lib_cmap_notify_callback.header.size = sizeof(res_lib_cmap_notify_callback) + new_val.len + old_val.len;
  543. res_lib_cmap_notify_callback.header.id = MESSAGE_RES_CMAP_NOTIFY_CALLBACK;
  544. res_lib_cmap_notify_callback.header.error = CS_OK;
  545. res_lib_cmap_notify_callback.new_value_type = new_val.type;
  546. res_lib_cmap_notify_callback.old_value_type = old_val.type;
  547. res_lib_cmap_notify_callback.new_value_len = new_val.len;
  548. res_lib_cmap_notify_callback.old_value_len = old_val.len;
  549. res_lib_cmap_notify_callback.event = event;
  550. res_lib_cmap_notify_callback.key_name.length = strlen(key_name);
  551. res_lib_cmap_notify_callback.track_inst_handle = cmap_track_user_data->track_inst_handle;
  552. memcpy(res_lib_cmap_notify_callback.key_name.value, key_name, strlen(key_name));
  553. iov[0].iov_base = (char *)&res_lib_cmap_notify_callback;
  554. iov[0].iov_len = sizeof(res_lib_cmap_notify_callback);
  555. iov[1].iov_base = (char *)new_val.data;
  556. iov[1].iov_len = new_val.len;
  557. iov[2].iov_base = (char *)old_val.data;
  558. iov[2].iov_len = old_val.len;
  559. api->ipc_dispatch_iov_send(cmap_track_user_data->conn, iov, 3);
  560. }
  561. static void message_handler_req_lib_cmap_track_add(void *conn, const void *message)
  562. {
  563. const struct req_lib_cmap_track_add *req_lib_cmap_track_add = message;
  564. struct res_lib_cmap_track_add res_lib_cmap_track_add;
  565. cs_error_t ret;
  566. cmap_track_handle_t handle = 0;
  567. icmap_track_t track = NULL;
  568. icmap_track_t *hdb_track;
  569. struct cmap_track_user_data *cmap_track_user_data;
  570. const char *key_name;
  571. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  572. cmap_track_user_data = malloc(sizeof(*cmap_track_user_data));
  573. if (cmap_track_user_data == NULL) {
  574. ret = CS_ERR_NO_MEMORY;
  575. goto reply_send;
  576. }
  577. memset(cmap_track_user_data, 0, sizeof(*cmap_track_user_data));
  578. if (req_lib_cmap_track_add->key_name.length > 0) {
  579. key_name = (char *)req_lib_cmap_track_add->key_name.value;
  580. } else {
  581. key_name = NULL;
  582. }
  583. ret = icmap_track_add(key_name,
  584. req_lib_cmap_track_add->track_type,
  585. cmap_notify_fn,
  586. cmap_track_user_data,
  587. &track);
  588. if (ret != CS_OK) {
  589. free(cmap_track_user_data);
  590. goto reply_send;
  591. }
  592. ret = hdb_error_to_cs(hdb_handle_create(&conn_info->track_db, sizeof(track), &handle));
  593. if (ret != CS_OK) {
  594. free(cmap_track_user_data);
  595. goto reply_send;
  596. }
  597. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->track_db, handle, (void *)&hdb_track));
  598. if (ret != CS_OK) {
  599. free(cmap_track_user_data);
  600. goto reply_send;
  601. }
  602. *hdb_track = track;
  603. cmap_track_user_data->conn = conn;
  604. cmap_track_user_data->track_handle = handle;
  605. cmap_track_user_data->track_inst_handle = req_lib_cmap_track_add->track_inst_handle;
  606. (void)hdb_handle_put (&conn_info->track_db, handle);
  607. reply_send:
  608. memset(&res_lib_cmap_track_add, 0, sizeof(res_lib_cmap_track_add));
  609. res_lib_cmap_track_add.header.size = sizeof(res_lib_cmap_track_add);
  610. res_lib_cmap_track_add.header.id = MESSAGE_RES_CMAP_TRACK_ADD;
  611. res_lib_cmap_track_add.header.error = ret;
  612. res_lib_cmap_track_add.track_handle = handle;
  613. api->ipc_response_send(conn, &res_lib_cmap_track_add, sizeof(res_lib_cmap_track_add));
  614. }
  615. static void message_handler_req_lib_cmap_track_delete(void *conn, const void *message)
  616. {
  617. const struct req_lib_cmap_track_delete *req_lib_cmap_track_delete = message;
  618. struct res_lib_cmap_track_delete res_lib_cmap_track_delete;
  619. cs_error_t ret;
  620. icmap_track_t *track;
  621. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  622. uint64_t track_inst_handle = 0;
  623. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->track_db,
  624. req_lib_cmap_track_delete->track_handle, (void *)&track));
  625. if (ret != CS_OK) {
  626. goto reply_send;
  627. }
  628. track_inst_handle = ((struct cmap_track_user_data *)icmap_track_get_user_data(*track))->track_inst_handle;
  629. free(icmap_track_get_user_data(*track));
  630. ret = icmap_track_delete(*track);
  631. (void)hdb_handle_put (&conn_info->track_db, req_lib_cmap_track_delete->track_handle);
  632. (void)hdb_handle_destroy(&conn_info->track_db, req_lib_cmap_track_delete->track_handle);
  633. reply_send:
  634. memset(&res_lib_cmap_track_delete, 0, sizeof(res_lib_cmap_track_delete));
  635. res_lib_cmap_track_delete.header.size = sizeof(res_lib_cmap_track_delete);
  636. res_lib_cmap_track_delete.header.id = MESSAGE_RES_CMAP_TRACK_DELETE;
  637. res_lib_cmap_track_delete.header.error = ret;
  638. res_lib_cmap_track_delete.track_inst_handle = track_inst_handle;
  639. api->ipc_response_send(conn, &res_lib_cmap_track_delete, sizeof(res_lib_cmap_track_delete));
  640. }
  641. static cs_error_t cmap_mcast_send(enum cmap_mcast_reason reason, int argc, char *argv[])
  642. {
  643. int i;
  644. size_t value_len;
  645. icmap_value_types_t value_type;
  646. cs_error_t err;
  647. size_t item_len;
  648. size_t msg_len = 0;
  649. struct req_exec_cmap_mcast req_exec_cmap_mcast;
  650. struct req_exec_cmap_mcast_item *item = NULL;
  651. struct iovec req_exec_cmap_iovec[MAX_REQ_EXEC_CMAP_MCAST_ITEMS + 1];
  652. ENTER();
  653. if (argc > MAX_REQ_EXEC_CMAP_MCAST_ITEMS) {
  654. return (CS_ERR_TOO_MANY_GROUPS);
  655. }
  656. memset(req_exec_cmap_iovec, 0, sizeof(req_exec_cmap_iovec));
  657. for (i = 0; i < argc; i++) {
  658. err = icmap_get(argv[i], NULL, &value_len, &value_type);
  659. if (err != CS_OK && err != CS_ERR_NOT_EXIST) {
  660. goto free_mem;
  661. }
  662. if (err == CS_ERR_NOT_EXIST) {
  663. value_type = ICMAP_VALUETYPE_NOT_EXIST;
  664. value_len = 0;
  665. }
  666. item_len = MAR_ALIGN_UP(sizeof(*item) + value_len, 8);
  667. item = malloc(item_len);
  668. if (item == NULL) {
  669. goto free_mem;
  670. }
  671. memset(item, 0, item_len);
  672. item->value_type = value_type;
  673. item->value_len = value_len;
  674. item->key_name.length = strlen(argv[i]);
  675. strcpy((char *)item->key_name.value, argv[i]);
  676. if (value_type != ICMAP_VALUETYPE_NOT_EXIST) {
  677. err = icmap_get(argv[i], item->value, &value_len, &value_type);
  678. if (err != CS_OK) {
  679. goto free_mem;
  680. }
  681. }
  682. req_exec_cmap_iovec[i + 1].iov_base = item;
  683. req_exec_cmap_iovec[i + 1].iov_len = item_len;
  684. msg_len += item_len;
  685. qb_log(LOG_TRACE, "Item %u - type %u, len %zu", i, item->value_type, item->value_len);
  686. item = NULL;
  687. }
  688. memset(&req_exec_cmap_mcast, 0, sizeof(req_exec_cmap_mcast));
  689. req_exec_cmap_mcast.header.size = sizeof(req_exec_cmap_mcast) + msg_len;
  690. req_exec_cmap_mcast.reason = reason;
  691. req_exec_cmap_mcast.no_items = argc;
  692. req_exec_cmap_iovec[0].iov_base = &req_exec_cmap_mcast;
  693. req_exec_cmap_iovec[0].iov_len = sizeof(req_exec_cmap_mcast);
  694. qb_log(LOG_TRACE, "Sending %u items (%u iovec) for reason %u", argc, argc + 1, reason);
  695. err = (api->totem_mcast(req_exec_cmap_iovec, argc + 1, TOTEM_AGREED) == 0 ? CS_OK : CS_ERR_MESSAGE_ERROR);
  696. free_mem:
  697. for (i = 0; i < argc; i++) {
  698. free(req_exec_cmap_iovec[i + 1].iov_base);
  699. }
  700. free(item);
  701. LEAVE();
  702. return (err);
  703. }
  704. static struct req_exec_cmap_mcast_item *cmap_mcast_item_find(
  705. const void *message,
  706. char *key)
  707. {
  708. const struct req_exec_cmap_mcast *req_exec_cmap_mcast = message;
  709. int i;
  710. const char *p;
  711. struct req_exec_cmap_mcast_item *item;
  712. mar_uint16_t key_name_len;
  713. p = (const char *)message + sizeof(*req_exec_cmap_mcast);
  714. for (i = 0; i < req_exec_cmap_mcast->no_items; i++) {
  715. item = (struct req_exec_cmap_mcast_item *)p;
  716. key_name_len = item->key_name.length;
  717. if (strlen(key) == key_name_len && strcmp((char *)item->key_name.value, key) == 0) {
  718. return (item);
  719. }
  720. p += MAR_ALIGN_UP(sizeof(*item) + item->value_len, 8);
  721. }
  722. return (NULL);
  723. }
  724. static void message_handler_req_exec_cmap_mcast_reason_sync_nv(
  725. enum cmap_mcast_reason reason,
  726. const void *message,
  727. unsigned int nodeid)
  728. {
  729. char member_config_version[ICMAP_KEYNAME_MAXLEN];
  730. uint64_t config_version = 0;
  731. struct req_exec_cmap_mcast_item *item;
  732. mar_size_t value_len;
  733. ENTER();
  734. item = cmap_mcast_item_find(message, (char *)"totem.config_version");
  735. if (item != NULL) {
  736. value_len = item->value_len;
  737. if (item->value_type == ICMAP_VALUETYPE_NOT_EXIST) {
  738. config_version = 0;
  739. }
  740. if (item->value_type == ICMAP_VALUETYPE_UINT64) {
  741. memcpy(&config_version, item->value, value_len);
  742. }
  743. }
  744. qb_log(LOG_TRACE, "Received config version %"PRIu64" from node %x", config_version, nodeid);
  745. if (nodeid != api->totem_nodeid_get() &&
  746. config_version > cmap_highest_config_version_received) {
  747. cmap_highest_config_version_received = config_version;
  748. }
  749. snprintf(member_config_version, ICMAP_KEYNAME_MAXLEN,
  750. "runtime.totem.pg.mrp.srp.members.%u.config_version", nodeid);
  751. icmap_set_uint64(member_config_version, config_version);
  752. LEAVE();
  753. }
  754. static void message_handler_req_exec_cmap_mcast(
  755. const void *message,
  756. unsigned int nodeid)
  757. {
  758. const struct req_exec_cmap_mcast *req_exec_cmap_mcast = message;
  759. ENTER();
  760. switch (req_exec_cmap_mcast->reason) {
  761. case CMAP_MCAST_REASON_SYNC:
  762. message_handler_req_exec_cmap_mcast_reason_sync_nv(req_exec_cmap_mcast->reason,
  763. message, nodeid);
  764. break;
  765. case CMAP_MCAST_REASON_NEW_CONFIG_VERSION:
  766. message_handler_req_exec_cmap_mcast_reason_sync_nv(req_exec_cmap_mcast->reason,
  767. message, nodeid);
  768. break;
  769. default:
  770. qb_log(LOG_TRACE, "Received mcast with unknown reason %u", req_exec_cmap_mcast->reason);
  771. };
  772. LEAVE();
  773. }
  774. static void exec_cmap_mcast_endian_convert(void *message)
  775. {
  776. struct req_exec_cmap_mcast *req_exec_cmap_mcast = message;
  777. const char *p;
  778. int i;
  779. struct req_exec_cmap_mcast_item *item;
  780. uint16_t u16;
  781. uint32_t u32;
  782. uint64_t u64;
  783. float flt;
  784. double dbl;
  785. swab_coroipc_request_header_t(&req_exec_cmap_mcast->header);
  786. p = (const char *)message + sizeof(*req_exec_cmap_mcast);
  787. for (i = 0; i < req_exec_cmap_mcast->no_items; i++) {
  788. item = (struct req_exec_cmap_mcast_item *)p;
  789. swab_mar_uint16_t(&item->key_name.length);
  790. swab_mar_size_t(&item->value_len);
  791. switch (item->value_type) {
  792. case ICMAP_VALUETYPE_INT16:
  793. case ICMAP_VALUETYPE_UINT16:
  794. memcpy(&u16, item->value, sizeof(u16));
  795. u16 = swab16(u16);
  796. memcpy(item->value, &u16, sizeof(u16));
  797. break;
  798. case ICMAP_VALUETYPE_INT32:
  799. case ICMAP_VALUETYPE_UINT32:
  800. memcpy(&u32, item->value, sizeof(u32));
  801. u32 = swab32(u32);
  802. memcpy(item->value, &u32, sizeof(u32));
  803. break;
  804. case ICMAP_VALUETYPE_INT64:
  805. case ICMAP_VALUETYPE_UINT64:
  806. memcpy(&u64, item->value, sizeof(u64));
  807. u64 = swab64(u64);
  808. memcpy(item->value, &u64, sizeof(u64));
  809. break;
  810. case ICMAP_VALUETYPE_FLOAT:
  811. memcpy(&flt, item->value, sizeof(flt));
  812. swabflt(&flt);
  813. memcpy(item->value, &flt, sizeof(flt));
  814. break;
  815. case ICMAP_VALUETYPE_DOUBLE:
  816. memcpy(&dbl, item->value, sizeof(dbl));
  817. swabdbl(&dbl);
  818. memcpy(item->value, &dbl, sizeof(dbl));
  819. break;
  820. }
  821. p += MAR_ALIGN_UP(sizeof(*item) + item->value_len, 8);
  822. }
  823. }