cmap.c 31 KB

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