4
0

cmap.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022
  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. memcpy(res_lib_cmap_iter_next.key_name.value, res, strlen(res));
  503. res_lib_cmap_iter_next.key_name.length = strlen(res);
  504. }
  505. api->ipc_response_send(conn, &res_lib_cmap_iter_next, sizeof(res_lib_cmap_iter_next));
  506. }
  507. static void message_handler_req_lib_cmap_iter_finalize(void *conn, const void *message)
  508. {
  509. const struct req_lib_cmap_iter_finalize *req_lib_cmap_iter_finalize = message;
  510. struct res_lib_cmap_iter_finalize res_lib_cmap_iter_finalize;
  511. cs_error_t ret;
  512. icmap_iter_t *iter;
  513. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  514. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->iter_db,
  515. req_lib_cmap_iter_finalize->iter_handle, (void *)&iter));
  516. if (ret != CS_OK) {
  517. goto reply_send;
  518. }
  519. icmap_iter_finalize(*iter);
  520. (void)hdb_handle_destroy(&conn_info->iter_db, req_lib_cmap_iter_finalize->iter_handle);
  521. (void)hdb_handle_put (&conn_info->iter_db, req_lib_cmap_iter_finalize->iter_handle);
  522. reply_send:
  523. memset(&res_lib_cmap_iter_finalize, 0, sizeof(res_lib_cmap_iter_finalize));
  524. res_lib_cmap_iter_finalize.header.size = sizeof(res_lib_cmap_iter_finalize);
  525. res_lib_cmap_iter_finalize.header.id = MESSAGE_RES_CMAP_ITER_FINALIZE;
  526. res_lib_cmap_iter_finalize.header.error = ret;
  527. api->ipc_response_send(conn, &res_lib_cmap_iter_finalize, sizeof(res_lib_cmap_iter_finalize));
  528. }
  529. static void cmap_notify_fn(int32_t event,
  530. const char *key_name,
  531. struct icmap_notify_value new_val,
  532. struct icmap_notify_value old_val,
  533. void *user_data)
  534. {
  535. struct cmap_track_user_data *cmap_track_user_data = (struct cmap_track_user_data *)user_data;
  536. struct res_lib_cmap_notify_callback res_lib_cmap_notify_callback;
  537. struct iovec iov[3];
  538. memset(&res_lib_cmap_notify_callback, 0, sizeof(res_lib_cmap_notify_callback));
  539. res_lib_cmap_notify_callback.header.size = sizeof(res_lib_cmap_notify_callback) + new_val.len + old_val.len;
  540. res_lib_cmap_notify_callback.header.id = MESSAGE_RES_CMAP_NOTIFY_CALLBACK;
  541. res_lib_cmap_notify_callback.header.error = CS_OK;
  542. res_lib_cmap_notify_callback.new_value_type = new_val.type;
  543. res_lib_cmap_notify_callback.old_value_type = old_val.type;
  544. res_lib_cmap_notify_callback.new_value_len = new_val.len;
  545. res_lib_cmap_notify_callback.old_value_len = old_val.len;
  546. res_lib_cmap_notify_callback.event = event;
  547. res_lib_cmap_notify_callback.key_name.length = strlen(key_name);
  548. res_lib_cmap_notify_callback.track_inst_handle = cmap_track_user_data->track_inst_handle;
  549. memcpy(res_lib_cmap_notify_callback.key_name.value, key_name, strlen(key_name));
  550. iov[0].iov_base = (char *)&res_lib_cmap_notify_callback;
  551. iov[0].iov_len = sizeof(res_lib_cmap_notify_callback);
  552. iov[1].iov_base = (char *)new_val.data;
  553. iov[1].iov_len = new_val.len;
  554. iov[2].iov_base = (char *)old_val.data;
  555. iov[2].iov_len = old_val.len;
  556. api->ipc_dispatch_iov_send(cmap_track_user_data->conn, iov, 3);
  557. }
  558. static void message_handler_req_lib_cmap_track_add(void *conn, const void *message)
  559. {
  560. const struct req_lib_cmap_track_add *req_lib_cmap_track_add = message;
  561. struct res_lib_cmap_track_add res_lib_cmap_track_add;
  562. cs_error_t ret;
  563. cmap_track_handle_t handle = 0;
  564. icmap_track_t track = NULL;
  565. icmap_track_t *hdb_track;
  566. struct cmap_track_user_data *cmap_track_user_data;
  567. const char *key_name;
  568. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  569. cmap_track_user_data = malloc(sizeof(*cmap_track_user_data));
  570. if (cmap_track_user_data == NULL) {
  571. ret = CS_ERR_NO_MEMORY;
  572. goto reply_send;
  573. }
  574. memset(cmap_track_user_data, 0, sizeof(*cmap_track_user_data));
  575. if (req_lib_cmap_track_add->key_name.length > 0) {
  576. key_name = (char *)req_lib_cmap_track_add->key_name.value;
  577. } else {
  578. key_name = NULL;
  579. }
  580. ret = icmap_track_add(key_name,
  581. req_lib_cmap_track_add->track_type,
  582. cmap_notify_fn,
  583. cmap_track_user_data,
  584. &track);
  585. if (ret != CS_OK) {
  586. free(cmap_track_user_data);
  587. goto reply_send;
  588. }
  589. ret = hdb_error_to_cs(hdb_handle_create(&conn_info->track_db, sizeof(track), &handle));
  590. if (ret != CS_OK) {
  591. free(cmap_track_user_data);
  592. goto reply_send;
  593. }
  594. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->track_db, handle, (void *)&hdb_track));
  595. if (ret != CS_OK) {
  596. free(cmap_track_user_data);
  597. goto reply_send;
  598. }
  599. *hdb_track = track;
  600. cmap_track_user_data->conn = conn;
  601. cmap_track_user_data->track_handle = handle;
  602. cmap_track_user_data->track_inst_handle = req_lib_cmap_track_add->track_inst_handle;
  603. (void)hdb_handle_put (&conn_info->track_db, handle);
  604. reply_send:
  605. memset(&res_lib_cmap_track_add, 0, sizeof(res_lib_cmap_track_add));
  606. res_lib_cmap_track_add.header.size = sizeof(res_lib_cmap_track_add);
  607. res_lib_cmap_track_add.header.id = MESSAGE_RES_CMAP_TRACK_ADD;
  608. res_lib_cmap_track_add.header.error = ret;
  609. res_lib_cmap_track_add.track_handle = handle;
  610. api->ipc_response_send(conn, &res_lib_cmap_track_add, sizeof(res_lib_cmap_track_add));
  611. }
  612. static void message_handler_req_lib_cmap_track_delete(void *conn, const void *message)
  613. {
  614. const struct req_lib_cmap_track_delete *req_lib_cmap_track_delete = message;
  615. struct res_lib_cmap_track_delete res_lib_cmap_track_delete;
  616. cs_error_t ret;
  617. icmap_track_t *track;
  618. struct cmap_conn_info *conn_info = (struct cmap_conn_info *)api->ipc_private_data_get (conn);
  619. uint64_t track_inst_handle = 0;
  620. ret = hdb_error_to_cs(hdb_handle_get(&conn_info->track_db,
  621. req_lib_cmap_track_delete->track_handle, (void *)&track));
  622. if (ret != CS_OK) {
  623. goto reply_send;
  624. }
  625. track_inst_handle = ((struct cmap_track_user_data *)icmap_track_get_user_data(*track))->track_inst_handle;
  626. free(icmap_track_get_user_data(*track));
  627. ret = icmap_track_delete(*track);
  628. (void)hdb_handle_put (&conn_info->track_db, req_lib_cmap_track_delete->track_handle);
  629. (void)hdb_handle_destroy(&conn_info->track_db, req_lib_cmap_track_delete->track_handle);
  630. reply_send:
  631. memset(&res_lib_cmap_track_delete, 0, sizeof(res_lib_cmap_track_delete));
  632. res_lib_cmap_track_delete.header.size = sizeof(res_lib_cmap_track_delete);
  633. res_lib_cmap_track_delete.header.id = MESSAGE_RES_CMAP_TRACK_DELETE;
  634. res_lib_cmap_track_delete.header.error = ret;
  635. res_lib_cmap_track_delete.track_inst_handle = track_inst_handle;
  636. api->ipc_response_send(conn, &res_lib_cmap_track_delete, sizeof(res_lib_cmap_track_delete));
  637. }
  638. static cs_error_t cmap_mcast_send(enum cmap_mcast_reason reason, int argc, char *argv[])
  639. {
  640. int i;
  641. size_t value_len;
  642. icmap_value_types_t value_type;
  643. cs_error_t err;
  644. size_t item_len;
  645. size_t msg_len = 0;
  646. struct req_exec_cmap_mcast req_exec_cmap_mcast;
  647. struct req_exec_cmap_mcast_item *item = NULL;
  648. struct iovec req_exec_cmap_iovec[MAX_REQ_EXEC_CMAP_MCAST_ITEMS + 1];
  649. ENTER();
  650. if (argc > MAX_REQ_EXEC_CMAP_MCAST_ITEMS) {
  651. return (CS_ERR_TOO_MANY_GROUPS);
  652. }
  653. memset(req_exec_cmap_iovec, 0, sizeof(req_exec_cmap_iovec));
  654. for (i = 0; i < argc; i++) {
  655. err = icmap_get(argv[i], NULL, &value_len, &value_type);
  656. if (err != CS_OK && err != CS_ERR_NOT_EXIST) {
  657. goto free_mem;
  658. }
  659. if (err == CS_ERR_NOT_EXIST) {
  660. value_type = ICMAP_VALUETYPE_NOT_EXIST;
  661. value_len = 0;
  662. }
  663. item_len = MAR_ALIGN_UP(sizeof(*item) + value_len, 8);
  664. item = malloc(item_len);
  665. if (item == NULL) {
  666. goto free_mem;
  667. }
  668. memset(item, 0, item_len);
  669. item->value_type = value_type;
  670. item->value_len = value_len;
  671. item->key_name.length = strlen(argv[i]);
  672. strcpy((char *)item->key_name.value, argv[i]);
  673. if (value_type != ICMAP_VALUETYPE_NOT_EXIST) {
  674. err = icmap_get(argv[i], item->value, &value_len, &value_type);
  675. if (err != CS_OK) {
  676. goto free_mem;
  677. }
  678. }
  679. req_exec_cmap_iovec[i + 1].iov_base = item;
  680. req_exec_cmap_iovec[i + 1].iov_len = item_len;
  681. msg_len += item_len;
  682. qb_log(LOG_TRACE, "Item %u - type %u, len %zu", i, item->value_type, item->value_len);
  683. item = NULL;
  684. }
  685. memset(&req_exec_cmap_mcast, 0, sizeof(req_exec_cmap_mcast));
  686. req_exec_cmap_mcast.header.size = sizeof(req_exec_cmap_mcast) + msg_len;
  687. req_exec_cmap_mcast.reason = reason;
  688. req_exec_cmap_mcast.no_items = argc;
  689. req_exec_cmap_iovec[0].iov_base = &req_exec_cmap_mcast;
  690. req_exec_cmap_iovec[0].iov_len = sizeof(req_exec_cmap_mcast);
  691. qb_log(LOG_TRACE, "Sending %u items (%u iovec) for reason %u", argc, argc + 1, reason);
  692. err = (api->totem_mcast(req_exec_cmap_iovec, argc + 1, TOTEM_AGREED) == 0 ? CS_OK : CS_ERR_MESSAGE_ERROR);
  693. free_mem:
  694. for (i = 0; i < argc; i++) {
  695. free(req_exec_cmap_iovec[i + 1].iov_base);
  696. }
  697. free(item);
  698. LEAVE();
  699. return (err);
  700. }
  701. static struct req_exec_cmap_mcast_item *cmap_mcast_item_find(
  702. const void *message,
  703. char *key)
  704. {
  705. const struct req_exec_cmap_mcast *req_exec_cmap_mcast = message;
  706. int i;
  707. const char *p;
  708. struct req_exec_cmap_mcast_item *item;
  709. mar_uint16_t key_name_len;
  710. p = (const char *)message + sizeof(*req_exec_cmap_mcast);
  711. for (i = 0; i < req_exec_cmap_mcast->no_items; i++) {
  712. item = (struct req_exec_cmap_mcast_item *)p;
  713. key_name_len = item->key_name.length;
  714. if (strlen(key) == key_name_len && strcmp((char *)item->key_name.value, key) == 0) {
  715. return (item);
  716. }
  717. p += MAR_ALIGN_UP(sizeof(*item) + item->value_len, 8);
  718. }
  719. return (NULL);
  720. }
  721. static void message_handler_req_exec_cmap_mcast_reason_sync_nv(
  722. enum cmap_mcast_reason reason,
  723. const void *message,
  724. unsigned int nodeid)
  725. {
  726. char member_config_version[ICMAP_KEYNAME_MAXLEN];
  727. uint64_t config_version = 0;
  728. struct req_exec_cmap_mcast_item *item;
  729. mar_size_t value_len;
  730. ENTER();
  731. item = cmap_mcast_item_find(message, (char *)"totem.config_version");
  732. if (item != NULL) {
  733. value_len = item->value_len;
  734. if (item->value_type == ICMAP_VALUETYPE_NOT_EXIST) {
  735. config_version = 0;
  736. }
  737. if (item->value_type == ICMAP_VALUETYPE_UINT64) {
  738. memcpy(&config_version, item->value, value_len);
  739. }
  740. }
  741. qb_log(LOG_TRACE, "Received config version %"PRIu64" from node %x", config_version, nodeid);
  742. if (nodeid != api->totem_nodeid_get() &&
  743. config_version > cmap_highest_config_version_received) {
  744. cmap_highest_config_version_received = config_version;
  745. }
  746. snprintf(member_config_version, ICMAP_KEYNAME_MAXLEN,
  747. "runtime.totem.pg.mrp.srp.members.%u.config_version", nodeid);
  748. icmap_set_uint64(member_config_version, config_version);
  749. LEAVE();
  750. }
  751. static void message_handler_req_exec_cmap_mcast(
  752. const void *message,
  753. unsigned int nodeid)
  754. {
  755. const struct req_exec_cmap_mcast *req_exec_cmap_mcast = message;
  756. ENTER();
  757. switch (req_exec_cmap_mcast->reason) {
  758. case CMAP_MCAST_REASON_SYNC:
  759. message_handler_req_exec_cmap_mcast_reason_sync_nv(req_exec_cmap_mcast->reason,
  760. message, nodeid);
  761. break;
  762. case CMAP_MCAST_REASON_NEW_CONFIG_VERSION:
  763. message_handler_req_exec_cmap_mcast_reason_sync_nv(req_exec_cmap_mcast->reason,
  764. message, nodeid);
  765. break;
  766. default:
  767. qb_log(LOG_TRACE, "Received mcast with unknown reason %u", req_exec_cmap_mcast->reason);
  768. };
  769. LEAVE();
  770. }
  771. static void exec_cmap_mcast_endian_convert(void *message)
  772. {
  773. struct req_exec_cmap_mcast *req_exec_cmap_mcast = message;
  774. const char *p;
  775. int i;
  776. struct req_exec_cmap_mcast_item *item;
  777. uint16_t u16;
  778. uint32_t u32;
  779. uint64_t u64;
  780. float flt;
  781. double dbl;
  782. swab_coroipc_request_header_t(&req_exec_cmap_mcast->header);
  783. p = (const char *)message + sizeof(*req_exec_cmap_mcast);
  784. for (i = 0; i < req_exec_cmap_mcast->no_items; i++) {
  785. item = (struct req_exec_cmap_mcast_item *)p;
  786. swab_mar_uint16_t(&item->key_name.length);
  787. swab_mar_size_t(&item->value_len);
  788. switch (item->value_type) {
  789. case ICMAP_VALUETYPE_INT16:
  790. case ICMAP_VALUETYPE_UINT16:
  791. memcpy(&u16, item->value, sizeof(u16));
  792. u16 = swab16(u16);
  793. memcpy(item->value, &u16, sizeof(u16));
  794. break;
  795. case ICMAP_VALUETYPE_INT32:
  796. case ICMAP_VALUETYPE_UINT32:
  797. memcpy(&u32, item->value, sizeof(u32));
  798. u32 = swab32(u32);
  799. memcpy(item->value, &u32, sizeof(u32));
  800. break;
  801. case ICMAP_VALUETYPE_INT64:
  802. case ICMAP_VALUETYPE_UINT64:
  803. memcpy(&u64, item->value, sizeof(u64));
  804. u64 = swab64(u64);
  805. memcpy(item->value, &u64, sizeof(u64));
  806. break;
  807. case ICMAP_VALUETYPE_FLOAT:
  808. memcpy(&flt, item->value, sizeof(flt));
  809. swabflt(&flt);
  810. memcpy(item->value, &flt, sizeof(flt));
  811. break;
  812. case ICMAP_VALUETYPE_DOUBLE:
  813. memcpy(&dbl, item->value, sizeof(dbl));
  814. swabdbl(&dbl);
  815. memcpy(item->value, &dbl, sizeof(dbl));
  816. break;
  817. }
  818. p += MAR_ALIGN_UP(sizeof(*item) + item->value_len, 8);
  819. }
  820. }