cmap.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  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. cmap_highest_config_version_received = 0;
  302. if (icmap_get_uint64("totem.config_version", &cmap_my_config_version) != CS_OK) {
  303. cmap_my_config_version = 0;
  304. }
  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 == 0) {
  330. log_printf(LOGSYS_LEVEL_DEBUG, "Other nodes version is 0 -> no action");
  331. return ;
  332. }
  333. if (cmap_highest_config_version_received != cmap_my_config_version) {
  334. log_printf(LOGSYS_LEVEL_ERROR,
  335. "Received config version (%"PRIu64") is different than my config version (%"PRIu64")! Exiting",
  336. cmap_highest_config_version_received, cmap_my_config_version);
  337. api->shutdown_request();
  338. return ;
  339. }
  340. }
  341. static void cmap_sync_abort (void)
  342. {
  343. }
  344. static void message_handler_req_lib_cmap_set(void *conn, const void *message)
  345. {
  346. const struct req_lib_cmap_set *req_lib_cmap_set = message;
  347. struct res_lib_cmap_set res_lib_cmap_set;
  348. cs_error_t ret;
  349. if (icmap_is_key_ro((char *)req_lib_cmap_set->key_name.value)) {
  350. ret = CS_ERR_ACCESS;
  351. } else {
  352. ret = icmap_set((char *)req_lib_cmap_set->key_name.value, &req_lib_cmap_set->value,
  353. req_lib_cmap_set->value_len, req_lib_cmap_set->type);
  354. }
  355. memset(&res_lib_cmap_set, 0, sizeof(res_lib_cmap_set));
  356. res_lib_cmap_set.header.size = sizeof(res_lib_cmap_set);
  357. res_lib_cmap_set.header.id = MESSAGE_RES_CMAP_SET;
  358. res_lib_cmap_set.header.error = ret;
  359. api->ipc_response_send(conn, &res_lib_cmap_set, sizeof(res_lib_cmap_set));
  360. }
  361. static void message_handler_req_lib_cmap_delete(void *conn, const void *message)
  362. {
  363. const struct req_lib_cmap_set *req_lib_cmap_set = message;
  364. struct res_lib_cmap_delete res_lib_cmap_delete;
  365. cs_error_t ret;
  366. if (icmap_is_key_ro((char *)req_lib_cmap_set->key_name.value)) {
  367. ret = CS_ERR_ACCESS;
  368. } else {
  369. ret = icmap_delete((char *)req_lib_cmap_set->key_name.value);
  370. }
  371. memset(&res_lib_cmap_delete, 0, sizeof(res_lib_cmap_delete));
  372. res_lib_cmap_delete.header.size = sizeof(res_lib_cmap_delete);
  373. res_lib_cmap_delete.header.id = MESSAGE_RES_CMAP_DELETE;
  374. res_lib_cmap_delete.header.error = ret;
  375. api->ipc_response_send(conn, &res_lib_cmap_delete, sizeof(res_lib_cmap_delete));
  376. }
  377. static void message_handler_req_lib_cmap_get(void *conn, const void *message)
  378. {
  379. const struct req_lib_cmap_get *req_lib_cmap_get = message;
  380. struct res_lib_cmap_get *res_lib_cmap_get;
  381. struct res_lib_cmap_get error_res_lib_cmap_get;
  382. cs_error_t ret;
  383. size_t value_len;
  384. size_t res_lib_cmap_get_size;
  385. icmap_value_types_t type;
  386. void *value;
  387. value_len = req_lib_cmap_get->value_len;
  388. res_lib_cmap_get_size = sizeof(*res_lib_cmap_get) + value_len;
  389. res_lib_cmap_get = malloc(res_lib_cmap_get_size);
  390. if (res_lib_cmap_get == NULL) {
  391. ret = CS_ERR_NO_MEMORY;
  392. goto error_exit;
  393. }
  394. memset(res_lib_cmap_get, 0, res_lib_cmap_get_size);
  395. if (value_len > 0) {
  396. value = res_lib_cmap_get->value;
  397. } else {
  398. value = NULL;
  399. }
  400. ret = icmap_get((char *)req_lib_cmap_get->key_name.value,
  401. value,
  402. &value_len,
  403. &type);
  404. if (ret != CS_OK) {
  405. free(res_lib_cmap_get);
  406. goto error_exit;
  407. }
  408. res_lib_cmap_get->header.size = res_lib_cmap_get_size;
  409. res_lib_cmap_get->header.id = MESSAGE_RES_CMAP_GET;
  410. res_lib_cmap_get->header.error = ret;
  411. res_lib_cmap_get->type = type;
  412. res_lib_cmap_get->value_len = value_len;
  413. api->ipc_response_send(conn, res_lib_cmap_get, res_lib_cmap_get_size);
  414. free(res_lib_cmap_get);
  415. return ;
  416. error_exit:
  417. memset(&error_res_lib_cmap_get, 0, sizeof(error_res_lib_cmap_get));
  418. error_res_lib_cmap_get.header.size = sizeof(error_res_lib_cmap_get);
  419. error_res_lib_cmap_get.header.id = MESSAGE_RES_CMAP_GET;
  420. error_res_lib_cmap_get.header.error = ret;
  421. api->ipc_response_send(conn, &error_res_lib_cmap_get, sizeof(error_res_lib_cmap_get));
  422. }
  423. static void message_handler_req_lib_cmap_adjust_int(void *conn, const void *message)
  424. {
  425. const struct req_lib_cmap_adjust_int *req_lib_cmap_adjust_int = message;
  426. struct res_lib_cmap_adjust_int res_lib_cmap_adjust_int;
  427. cs_error_t ret;
  428. if (icmap_is_key_ro((char *)req_lib_cmap_adjust_int->key_name.value)) {
  429. ret = CS_ERR_ACCESS;
  430. } else {
  431. ret = icmap_adjust_int((char *)req_lib_cmap_adjust_int->key_name.value,
  432. req_lib_cmap_adjust_int->step);
  433. }
  434. memset(&res_lib_cmap_adjust_int, 0, sizeof(res_lib_cmap_adjust_int));
  435. res_lib_cmap_adjust_int.header.size = sizeof(res_lib_cmap_adjust_int);
  436. res_lib_cmap_adjust_int.header.id = MESSAGE_RES_CMAP_ADJUST_INT;
  437. res_lib_cmap_adjust_int.header.error = ret;
  438. api->ipc_response_send(conn, &res_lib_cmap_adjust_int, sizeof(res_lib_cmap_adjust_int));
  439. }
  440. static void message_handler_req_lib_cmap_iter_init(void *conn, const void *message)
  441. {
  442. const struct req_lib_cmap_iter_init *req_lib_cmap_iter_init = message;
  443. struct res_lib_cmap_iter_init res_lib_cmap_iter_init;
  444. cs_error_t ret;
  445. icmap_iter_t iter;
  446. icmap_iter_t *hdb_iter;
  447. cmap_iter_handle_t handle = 0ULL;
  448. const char *prefix;
  449. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  450. if (req_lib_cmap_iter_init->prefix.length > 0) {
  451. prefix = (char *)req_lib_cmap_iter_init->prefix.value;
  452. } else {
  453. prefix = NULL;
  454. }
  455. iter = icmap_iter_init(prefix);
  456. if (iter == NULL) {
  457. ret = CS_ERR_NO_SECTIONS;
  458. goto reply_send;
  459. }
  460. ret = hdb_error_to_cs(hdb_handle_create(&conn_info->iter_db, sizeof(iter), &handle));
  461. if (ret != CS_OK) {
  462. goto reply_send;
  463. }
  464. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->iter_db, handle, (void *)&hdb_iter));
  465. if (ret != CS_OK) {
  466. goto reply_send;
  467. }
  468. *hdb_iter = iter;
  469. (void)hdb_handle_put (&conn_info->iter_db, handle);
  470. reply_send:
  471. memset(&res_lib_cmap_iter_init, 0, sizeof(res_lib_cmap_iter_init));
  472. res_lib_cmap_iter_init.header.size = sizeof(res_lib_cmap_iter_init);
  473. res_lib_cmap_iter_init.header.id = MESSAGE_RES_CMAP_ITER_INIT;
  474. res_lib_cmap_iter_init.header.error = ret;
  475. res_lib_cmap_iter_init.iter_handle = handle;
  476. api->ipc_response_send(conn, &res_lib_cmap_iter_init, sizeof(res_lib_cmap_iter_init));
  477. }
  478. static void message_handler_req_lib_cmap_iter_next(void *conn, const void *message)
  479. {
  480. const struct req_lib_cmap_iter_next *req_lib_cmap_iter_next = message;
  481. struct res_lib_cmap_iter_next res_lib_cmap_iter_next;
  482. cs_error_t ret;
  483. icmap_iter_t *iter;
  484. size_t value_len = 0;
  485. icmap_value_types_t type = 0;
  486. const char *res = NULL;
  487. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  488. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->iter_db,
  489. req_lib_cmap_iter_next->iter_handle, (void *)&iter));
  490. if (ret != CS_OK) {
  491. goto reply_send;
  492. }
  493. res = icmap_iter_next(*iter, &value_len, &type);
  494. if (res == NULL) {
  495. ret = CS_ERR_NO_SECTIONS;
  496. }
  497. (void)hdb_handle_put (&conn_info->iter_db, req_lib_cmap_iter_next->iter_handle);
  498. reply_send:
  499. memset(&res_lib_cmap_iter_next, 0, sizeof(res_lib_cmap_iter_next));
  500. res_lib_cmap_iter_next.header.size = sizeof(res_lib_cmap_iter_next);
  501. res_lib_cmap_iter_next.header.id = MESSAGE_RES_CMAP_ITER_NEXT;
  502. res_lib_cmap_iter_next.header.error = ret;
  503. if (res != NULL) {
  504. res_lib_cmap_iter_next.value_len = value_len;
  505. res_lib_cmap_iter_next.type = type;
  506. memcpy(res_lib_cmap_iter_next.key_name.value, res, strlen(res));
  507. res_lib_cmap_iter_next.key_name.length = strlen(res);
  508. }
  509. api->ipc_response_send(conn, &res_lib_cmap_iter_next, sizeof(res_lib_cmap_iter_next));
  510. }
  511. static void message_handler_req_lib_cmap_iter_finalize(void *conn, const void *message)
  512. {
  513. const struct req_lib_cmap_iter_finalize *req_lib_cmap_iter_finalize = message;
  514. struct res_lib_cmap_iter_finalize res_lib_cmap_iter_finalize;
  515. cs_error_t ret;
  516. icmap_iter_t *iter;
  517. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  518. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->iter_db,
  519. req_lib_cmap_iter_finalize->iter_handle, (void *)&iter));
  520. if (ret != CS_OK) {
  521. goto reply_send;
  522. }
  523. icmap_iter_finalize(*iter);
  524. (void)hdb_handle_destroy(&conn_info->iter_db, req_lib_cmap_iter_finalize->iter_handle);
  525. (void)hdb_handle_put (&conn_info->iter_db, req_lib_cmap_iter_finalize->iter_handle);
  526. reply_send:
  527. memset(&res_lib_cmap_iter_finalize, 0, sizeof(res_lib_cmap_iter_finalize));
  528. res_lib_cmap_iter_finalize.header.size = sizeof(res_lib_cmap_iter_finalize);
  529. res_lib_cmap_iter_finalize.header.id = MESSAGE_RES_CMAP_ITER_FINALIZE;
  530. res_lib_cmap_iter_finalize.header.error = ret;
  531. api->ipc_response_send(conn, &res_lib_cmap_iter_finalize, sizeof(res_lib_cmap_iter_finalize));
  532. }
  533. static void cmap_notify_fn(int32_t event,
  534. const char *key_name,
  535. struct icmap_notify_value new_val,
  536. struct icmap_notify_value old_val,
  537. void *user_data)
  538. {
  539. struct cmap_track_user_data *cmap_track_user_data = (struct cmap_track_user_data *)user_data;
  540. struct res_lib_cmap_notify_callback res_lib_cmap_notify_callback;
  541. struct iovec iov[3];
  542. memset(&res_lib_cmap_notify_callback, 0, sizeof(res_lib_cmap_notify_callback));
  543. res_lib_cmap_notify_callback.header.size = sizeof(res_lib_cmap_notify_callback) + new_val.len + old_val.len;
  544. res_lib_cmap_notify_callback.header.id = MESSAGE_RES_CMAP_NOTIFY_CALLBACK;
  545. res_lib_cmap_notify_callback.header.error = CS_OK;
  546. res_lib_cmap_notify_callback.new_value_type = new_val.type;
  547. res_lib_cmap_notify_callback.old_value_type = old_val.type;
  548. res_lib_cmap_notify_callback.new_value_len = new_val.len;
  549. res_lib_cmap_notify_callback.old_value_len = old_val.len;
  550. res_lib_cmap_notify_callback.event = event;
  551. res_lib_cmap_notify_callback.key_name.length = strlen(key_name);
  552. res_lib_cmap_notify_callback.track_inst_handle = cmap_track_user_data->track_inst_handle;
  553. memcpy(res_lib_cmap_notify_callback.key_name.value, key_name, strlen(key_name));
  554. iov[0].iov_base = (char *)&res_lib_cmap_notify_callback;
  555. iov[0].iov_len = sizeof(res_lib_cmap_notify_callback);
  556. iov[1].iov_base = (char *)new_val.data;
  557. iov[1].iov_len = new_val.len;
  558. iov[2].iov_base = (char *)old_val.data;
  559. iov[2].iov_len = old_val.len;
  560. api->ipc_dispatch_iov_send(cmap_track_user_data->conn, iov, 3);
  561. }
  562. static void message_handler_req_lib_cmap_track_add(void *conn, const void *message)
  563. {
  564. const struct req_lib_cmap_track_add *req_lib_cmap_track_add = message;
  565. struct res_lib_cmap_track_add res_lib_cmap_track_add;
  566. cs_error_t ret;
  567. cmap_track_handle_t handle = 0;
  568. icmap_track_t track = NULL;
  569. icmap_track_t *hdb_track;
  570. struct cmap_track_user_data *cmap_track_user_data;
  571. const char *key_name;
  572. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  573. cmap_track_user_data = malloc(sizeof(*cmap_track_user_data));
  574. if (cmap_track_user_data == NULL) {
  575. ret = CS_ERR_NO_MEMORY;
  576. goto reply_send;
  577. }
  578. memset(cmap_track_user_data, 0, sizeof(*cmap_track_user_data));
  579. if (req_lib_cmap_track_add->key_name.length > 0) {
  580. key_name = (char *)req_lib_cmap_track_add->key_name.value;
  581. } else {
  582. key_name = NULL;
  583. }
  584. ret = icmap_track_add(key_name,
  585. req_lib_cmap_track_add->track_type,
  586. cmap_notify_fn,
  587. cmap_track_user_data,
  588. &track);
  589. if (ret != CS_OK) {
  590. free(cmap_track_user_data);
  591. goto reply_send;
  592. }
  593. ret = hdb_error_to_cs(hdb_handle_create(&conn_info->track_db, sizeof(track), &handle));
  594. if (ret != CS_OK) {
  595. free(cmap_track_user_data);
  596. goto reply_send;
  597. }
  598. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->track_db, handle, (void *)&hdb_track));
  599. if (ret != CS_OK) {
  600. free(cmap_track_user_data);
  601. goto reply_send;
  602. }
  603. *hdb_track = track;
  604. cmap_track_user_data->conn = conn;
  605. cmap_track_user_data->track_handle = handle;
  606. cmap_track_user_data->track_inst_handle = req_lib_cmap_track_add->track_inst_handle;
  607. (void)hdb_handle_put (&conn_info->track_db, handle);
  608. reply_send:
  609. memset(&res_lib_cmap_track_add, 0, sizeof(res_lib_cmap_track_add));
  610. res_lib_cmap_track_add.header.size = sizeof(res_lib_cmap_track_add);
  611. res_lib_cmap_track_add.header.id = MESSAGE_RES_CMAP_TRACK_ADD;
  612. res_lib_cmap_track_add.header.error = ret;
  613. res_lib_cmap_track_add.track_handle = handle;
  614. api->ipc_response_send(conn, &res_lib_cmap_track_add, sizeof(res_lib_cmap_track_add));
  615. }
  616. static void message_handler_req_lib_cmap_track_delete(void *conn, const void *message)
  617. {
  618. const struct req_lib_cmap_track_delete *req_lib_cmap_track_delete = message;
  619. struct res_lib_cmap_track_delete res_lib_cmap_track_delete;
  620. cs_error_t ret;
  621. icmap_track_t *track;
  622. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  623. uint64_t track_inst_handle = 0;
  624. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->track_db,
  625. req_lib_cmap_track_delete->track_handle, (void *)&track));
  626. if (ret != CS_OK) {
  627. goto reply_send;
  628. }
  629. track_inst_handle = ((struct cmap_track_user_data *)icmap_track_get_user_data(*track))->track_inst_handle;
  630. free(icmap_track_get_user_data(*track));
  631. ret = icmap_track_delete(*track);
  632. (void)hdb_handle_put (&conn_info->track_db, req_lib_cmap_track_delete->track_handle);
  633. (void)hdb_handle_destroy(&conn_info->track_db, req_lib_cmap_track_delete->track_handle);
  634. reply_send:
  635. memset(&res_lib_cmap_track_delete, 0, sizeof(res_lib_cmap_track_delete));
  636. res_lib_cmap_track_delete.header.size = sizeof(res_lib_cmap_track_delete);
  637. res_lib_cmap_track_delete.header.id = MESSAGE_RES_CMAP_TRACK_DELETE;
  638. res_lib_cmap_track_delete.header.error = ret;
  639. res_lib_cmap_track_delete.track_inst_handle = track_inst_handle;
  640. api->ipc_response_send(conn, &res_lib_cmap_track_delete, sizeof(res_lib_cmap_track_delete));
  641. }
  642. static cs_error_t cmap_mcast_send(enum cmap_mcast_reason reason, int argc, char *argv[])
  643. {
  644. int i;
  645. size_t value_len;
  646. icmap_value_types_t value_type;
  647. cs_error_t err;
  648. size_t item_len;
  649. size_t msg_len = 0;
  650. struct req_exec_cmap_mcast req_exec_cmap_mcast;
  651. struct req_exec_cmap_mcast_item *item = NULL;
  652. struct iovec req_exec_cmap_iovec[MAX_REQ_EXEC_CMAP_MCAST_ITEMS + 1];
  653. ENTER();
  654. if (argc > MAX_REQ_EXEC_CMAP_MCAST_ITEMS) {
  655. return (CS_ERR_TOO_MANY_GROUPS);
  656. }
  657. memset(req_exec_cmap_iovec, 0, sizeof(req_exec_cmap_iovec));
  658. for (i = 0; i < argc; i++) {
  659. err = icmap_get(argv[i], NULL, &value_len, &value_type);
  660. if (err != CS_OK && err != CS_ERR_NOT_EXIST) {
  661. goto free_mem;
  662. }
  663. if (err == CS_ERR_NOT_EXIST) {
  664. value_type = ICMAP_VALUETYPE_NOT_EXIST;
  665. value_len = 0;
  666. }
  667. item_len = MAR_ALIGN_UP(sizeof(*item) + value_len, 8);
  668. item = malloc(item_len);
  669. if (item == NULL) {
  670. goto free_mem;
  671. }
  672. memset(item, 0, item_len);
  673. item->value_type = value_type;
  674. item->value_len = value_len;
  675. item->key_name.length = strlen(argv[i]);
  676. strcpy((char *)item->key_name.value, argv[i]);
  677. if (value_type != ICMAP_VALUETYPE_NOT_EXIST) {
  678. err = icmap_get(argv[i], item->value, &value_len, &value_type);
  679. if (err != CS_OK) {
  680. goto free_mem;
  681. }
  682. }
  683. req_exec_cmap_iovec[i + 1].iov_base = item;
  684. req_exec_cmap_iovec[i + 1].iov_len = item_len;
  685. msg_len += item_len;
  686. qb_log(LOG_TRACE, "Item %u - type %u, len %zu", i, item->value_type, item->value_len);
  687. item = NULL;
  688. }
  689. memset(&req_exec_cmap_mcast, 0, sizeof(req_exec_cmap_mcast));
  690. req_exec_cmap_mcast.header.size = sizeof(req_exec_cmap_mcast) + msg_len;
  691. req_exec_cmap_mcast.reason = reason;
  692. req_exec_cmap_mcast.no_items = argc;
  693. req_exec_cmap_iovec[0].iov_base = &req_exec_cmap_mcast;
  694. req_exec_cmap_iovec[0].iov_len = sizeof(req_exec_cmap_mcast);
  695. qb_log(LOG_TRACE, "Sending %u items (%u iovec) for reason %u", argc, argc + 1, reason);
  696. err = (api->totem_mcast(req_exec_cmap_iovec, argc + 1, TOTEM_AGREED) == 0 ? CS_OK : CS_ERR_MESSAGE_ERROR);
  697. free_mem:
  698. for (i = 0; i < argc; i++) {
  699. free(req_exec_cmap_iovec[i + 1].iov_base);
  700. }
  701. free(item);
  702. LEAVE();
  703. return (err);
  704. }
  705. static struct req_exec_cmap_mcast_item *cmap_mcast_item_find(
  706. const void *message,
  707. char *key)
  708. {
  709. const struct req_exec_cmap_mcast *req_exec_cmap_mcast = message;
  710. int i;
  711. const char *p;
  712. struct req_exec_cmap_mcast_item *item;
  713. mar_uint16_t key_name_len;
  714. p = (const char *)message + sizeof(*req_exec_cmap_mcast);
  715. for (i = 0; i < req_exec_cmap_mcast->no_items; i++) {
  716. item = (struct req_exec_cmap_mcast_item *)p;
  717. key_name_len = item->key_name.length;
  718. if (strlen(key) == key_name_len && strcmp((char *)item->key_name.value, key) == 0) {
  719. return (item);
  720. }
  721. p += MAR_ALIGN_UP(sizeof(*item) + item->value_len, 8);
  722. }
  723. return (NULL);
  724. }
  725. static void message_handler_req_exec_cmap_mcast_reason_sync_nv(
  726. enum cmap_mcast_reason reason,
  727. const void *message,
  728. unsigned int nodeid)
  729. {
  730. char member_config_version[ICMAP_KEYNAME_MAXLEN];
  731. uint64_t config_version = 0;
  732. struct req_exec_cmap_mcast_item *item;
  733. mar_size_t value_len;
  734. ENTER();
  735. item = cmap_mcast_item_find(message, (char *)"totem.config_version");
  736. if (item != NULL) {
  737. value_len = item->value_len;
  738. if (item->value_type == ICMAP_VALUETYPE_NOT_EXIST) {
  739. config_version = 0;
  740. }
  741. if (item->value_type == ICMAP_VALUETYPE_UINT64) {
  742. memcpy(&config_version, item->value, value_len);
  743. }
  744. }
  745. qb_log(LOG_TRACE, "Received config version %"PRIu64" from node %x", config_version, nodeid);
  746. if (nodeid != api->totem_nodeid_get() &&
  747. config_version > cmap_highest_config_version_received) {
  748. cmap_highest_config_version_received = config_version;
  749. }
  750. snprintf(member_config_version, ICMAP_KEYNAME_MAXLEN,
  751. "runtime.totem.pg.mrp.srp.members.%u.config_version", nodeid);
  752. icmap_set_uint64(member_config_version, config_version);
  753. LEAVE();
  754. }
  755. static void message_handler_req_exec_cmap_mcast(
  756. const void *message,
  757. unsigned int nodeid)
  758. {
  759. const struct req_exec_cmap_mcast *req_exec_cmap_mcast = message;
  760. ENTER();
  761. switch (req_exec_cmap_mcast->reason) {
  762. case CMAP_MCAST_REASON_SYNC:
  763. message_handler_req_exec_cmap_mcast_reason_sync_nv(req_exec_cmap_mcast->reason,
  764. message, nodeid);
  765. break;
  766. case CMAP_MCAST_REASON_NEW_CONFIG_VERSION:
  767. message_handler_req_exec_cmap_mcast_reason_sync_nv(req_exec_cmap_mcast->reason,
  768. message, nodeid);
  769. break;
  770. default:
  771. qb_log(LOG_TRACE, "Received mcast with unknown reason %u", req_exec_cmap_mcast->reason);
  772. };
  773. LEAVE();
  774. }
  775. static void exec_cmap_mcast_endian_convert(void *message)
  776. {
  777. struct req_exec_cmap_mcast *req_exec_cmap_mcast = message;
  778. const char *p;
  779. int i;
  780. struct req_exec_cmap_mcast_item *item;
  781. uint16_t u16;
  782. uint32_t u32;
  783. uint64_t u64;
  784. float flt;
  785. double dbl;
  786. swab_coroipc_request_header_t(&req_exec_cmap_mcast->header);
  787. p = (const char *)message + sizeof(*req_exec_cmap_mcast);
  788. for (i = 0; i < req_exec_cmap_mcast->no_items; i++) {
  789. item = (struct req_exec_cmap_mcast_item *)p;
  790. swab_mar_uint16_t(&item->key_name.length);
  791. swab_mar_size_t(&item->value_len);
  792. switch (item->value_type) {
  793. case ICMAP_VALUETYPE_INT16:
  794. case ICMAP_VALUETYPE_UINT16:
  795. memcpy(&u16, item->value, sizeof(u16));
  796. u16 = swab16(u16);
  797. memcpy(item->value, &u16, sizeof(u16));
  798. break;
  799. case ICMAP_VALUETYPE_INT32:
  800. case ICMAP_VALUETYPE_UINT32:
  801. memcpy(&u32, item->value, sizeof(u32));
  802. u32 = swab32(u32);
  803. memcpy(item->value, &u32, sizeof(u32));
  804. break;
  805. case ICMAP_VALUETYPE_INT64:
  806. case ICMAP_VALUETYPE_UINT64:
  807. memcpy(&u64, item->value, sizeof(u64));
  808. u64 = swab64(u64);
  809. memcpy(item->value, &u64, sizeof(u64));
  810. break;
  811. case ICMAP_VALUETYPE_FLOAT:
  812. memcpy(&flt, item->value, sizeof(flt));
  813. swabflt(&flt);
  814. memcpy(item->value, &flt, sizeof(flt));
  815. break;
  816. case ICMAP_VALUETYPE_DOUBLE:
  817. memcpy(&dbl, item->value, sizeof(dbl));
  818. swabdbl(&dbl);
  819. memcpy(item->value, &dbl, sizeof(dbl));
  820. break;
  821. }
  822. p += MAR_ALIGN_UP(sizeof(*item) + item->value_len, 8);
  823. }
  824. }