Function is little more complex, but it is designed to be used in future without big changes. Signed-off-by: Jan Friesse <jfriesse@xxxxxxxxxx> --- exec/cmap.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 247 insertions(+), 0 deletions(-) diff --git a/exec/cmap.c b/exec/cmap.c index f4b688d..4b6efb4 100644 --- a/exec/cmap.c +++ b/exec/cmap.c @@ -59,6 +59,9 @@ LOGSYS_DECLARE_SUBSYS ("CMAP"); +#define MAX_REQ_EXEC_CMAP_MCAST_ITEMS 32 +#define ICMAP_VALUETYPE_NOT_EXIST 0 + struct cmap_conn_info { struct hdb_handle_database iter_db; struct hdb_handle_database track_db; @@ -73,6 +76,14 @@ struct cmap_track_user_data { uint64_t track_inst_handle; }; +enum cmap_message_req_types { + MESSAGE_REQ_EXEC_CMAP_MCAST = 0, +}; + +enum cmap_mcast_reason { + CMAP_MCAST_REASON_SYNC = 0, +}; + static struct corosync_api_v1 *api; static char *cmap_exec_init_fn (struct corosync_api_v1 *corosync_api); @@ -97,6 +108,14 @@ static void cmap_notify_fn(int32_t event, struct icmap_notify_value old_val, void *user_data); +static void message_handler_req_exec_cmap_mcast( + const void *message, + unsigned int nodeid); + +static void exec_cmap_mcast_endian_convert(void *message); + +static int cmap_mcast_send(enum cmap_mcast_reason reason, int argc, char *argv[]); + /* * Library Handler Definition */ @@ -140,6 +159,13 @@ static struct corosync_lib_handler cmap_lib_engine[] = }, }; +static struct corosync_exec_handler cmap_exec_engine[] = +{ + { /* 0 - MESSAGE_REQ_EXEC_CMAP_MCAST */ + .exec_handler_fn = message_handler_req_exec_cmap_mcast, + .exec_endian_convert_fn = exec_cmap_mcast_endian_convert + }, +}; struct corosync_service_engine cmap_service_engine = { .name = "corosync configuration map access", @@ -154,6 +180,8 @@ struct corosync_service_engine cmap_service_engine = { .lib_engine_count = sizeof (cmap_lib_engine) / sizeof (struct corosync_lib_handler), .exec_init_fn = cmap_exec_init_fn, .exec_exit_fn = cmap_exec_exit_fn, + .exec_engine = cmap_exec_engine, + .exec_engine_count = sizeof (cmap_exec_engine) / sizeof (struct corosync_exec_handler), }; struct corosync_service_engine *cmap_get_service_engine_ver0 (void) @@ -161,6 +189,24 @@ struct corosync_service_engine *cmap_get_service_engine_ver0 (void) return (&cmap_service_engine); } +struct req_exec_cmap_mcast_item { + mar_name_t key_name __attribute__((aligned(8))); + mar_uint8_t value_type __attribute__((aligned(8))); + mar_size_t value_len __attribute__((aligned(8))); + uint8_t value[] __attribute__((aligned(8))); +}; + +struct req_exec_cmap_mcast { + struct qb_ipc_request_header header __attribute__((aligned(8))); + mar_uint8_t reason __attribute__((aligned(8))); + mar_uint8_t no_items __attribute__((aligned(8))); + mar_uint8_t reserved1 __attribute__((aligned(8))); + mar_uint8_t reserver2 __attribute__((aligned(8))); + /* + * Following are array of req_exec_cmap_mcast_item + */ +}; + static int cmap_exec_exit_fn(void) { return 0; @@ -602,3 +648,204 @@ reply_send: api->ipc_response_send(conn, &res_lib_cmap_track_delete, sizeof(res_lib_cmap_track_delete)); } + +static int cmap_mcast_send(enum cmap_mcast_reason reason, int argc, char *argv[]) +{ + int i; + size_t value_len; + icmap_value_types_t value_type; + cs_error_t err; + size_t item_len; + size_t msg_len = 0; + struct req_exec_cmap_mcast req_exec_cmap_mcast; + struct req_exec_cmap_mcast_item *item; + struct iovec req_exec_cmap_iovec[MAX_REQ_EXEC_CMAP_MCAST_ITEMS + 1]; + + ENTER(); + + if (argc > MAX_REQ_EXEC_CMAP_MCAST_ITEMS) { + return (CS_ERR_TOO_MANY_GROUPS); + } + + memset(req_exec_cmap_iovec, 0, sizeof(req_exec_cmap_iovec)); + + for (i = 0; i < argc; i++) { + err = icmap_get(argv[i], NULL, &value_len, &value_type); + if (err != CS_OK && err != CS_ERR_NOT_EXIST) { + goto free_mem; + } + if (err == CS_ERR_NOT_EXIST) { + value_type = ICMAP_VALUETYPE_NOT_EXIST; + value_len = 0; + } + + item_len = sizeof(*item) + value_len; + + item = malloc(item_len); + if (item == NULL) { + goto free_mem; + } + memset(item, 0, sizeof(item_len)); + + item->value_type = value_type; + item->value_len = value_len; + item->key_name.length = strlen(argv[i]); + strcpy((char *)item->key_name.value, argv[i]); + + if (value_type != ICMAP_VALUETYPE_NOT_EXIST) { + err = icmap_get(argv[i], item->value, &value_len, &value_type); + if (err != CS_OK) { + goto free_mem; + } + } + + req_exec_cmap_iovec[i + 1].iov_base = item; + req_exec_cmap_iovec[i + 1].iov_len = item_len; + msg_len += item_len; + + qb_log(LOG_TRACE, "Item %u - type %u, len %zu", i, item->value_type, item->value_len); + + item = NULL; + } + + memset(&req_exec_cmap_mcast, 0, sizeof(req_exec_cmap_mcast)); + req_exec_cmap_mcast.header.size = sizeof(req_exec_cmap_mcast) + msg_len; + req_exec_cmap_mcast.reason = reason; + req_exec_cmap_mcast.no_items = argc; + req_exec_cmap_iovec[0].iov_base = &req_exec_cmap_mcast; + req_exec_cmap_iovec[0].iov_len = sizeof(req_exec_cmap_mcast); + + qb_log(LOG_TRACE, "Sending %u items (%u iovec) for reason %u", argc, argc + 1, reason); + err = api->totem_mcast(req_exec_cmap_iovec, argc + 1, TOTEM_AGREED); + +free_mem: + for (i = 0; i < argc; i++) { + free(req_exec_cmap_iovec[i + 1].iov_base); + } + + free(item); + + LEAVE(); + return (err); +} + +static struct req_exec_cmap_mcast_item *cmap_mcast_item_find( + const void *message, + char *key) +{ + const struct req_exec_cmap_mcast *req_exec_cmap_mcast = message; + int i; + const char *p; + struct req_exec_cmap_mcast_item *item; + mar_uint16_t key_name_len; + + p = (const char *)message + sizeof(*req_exec_cmap_mcast); + + for (i = 0; i < req_exec_cmap_mcast->no_items; i++) { + item = (struct req_exec_cmap_mcast_item *)p; + + key_name_len = item->key_name.length; + if (strlen(key) == key_name_len && strcmp((char *)item->key_name.value, key) == 0) { + return (item); + } + + p += sizeof(*item) + item->value_len; + } + + return (NULL); +} + +static void message_handler_req_exec_cmap_mcast_reason_sync( + const void *message, + unsigned int nodeid) +{ + uint64_t config_version = 0; + struct req_exec_cmap_mcast_item *item; + mar_size_t value_len; + + ENTER(); + + item = cmap_mcast_item_find(message, (char *)"totem.config_version"); + if (item != NULL) { + value_len = item->value_len; + + if (item->value_type == ICMAP_VALUETYPE_NOT_EXIST) { + config_version = 0; + } + + if (item->value_type == ICMAP_VALUETYPE_UINT64) { + memcpy(&config_version, item->value, value_len); + } + } + + qb_log(LOG_TRACE, "Received config version %"PRIu64" from node %x", config_version, nodeid); + + LEAVE(); +} + +static void message_handler_req_exec_cmap_mcast( + const void *message, + unsigned int nodeid) +{ + const struct req_exec_cmap_mcast *req_exec_cmap_mcast = message; + + ENTER(); + + switch (req_exec_cmap_mcast->reason) { + case CMAP_MCAST_REASON_SYNC: + message_handler_req_exec_cmap_mcast_reason_sync(message, nodeid); + break; + default: + qb_log(LOG_TRACE, "Received mcast with unknown reason %u", req_exec_cmap_mcast->reason); + }; + + LEAVE(); +} + +static void exec_cmap_mcast_endian_convert(void *message) +{ + struct req_exec_cmap_mcast *req_exec_cmap_mcast = message; + const char *p; + int i; + struct req_exec_cmap_mcast_item *item; + uint16_t u16; + uint32_t u32; + uint64_t u64; + + swab_coroipc_request_header_t(&req_exec_cmap_mcast->header); + + p = (const char *)message + sizeof(*req_exec_cmap_mcast); + + for (i = 0; i < req_exec_cmap_mcast->no_items; i++) { + item = (struct req_exec_cmap_mcast_item *)p; + + swab_mar_uint16_t(&item->key_name.length); + swab_mar_size_t(&item->value_len); + + switch (item->value_type) { + case ICMAP_VALUETYPE_INT16: + case ICMAP_VALUETYPE_UINT16: + memcpy(&u16, item->value, sizeof(u16)); + u16 = swab16(u16); + memcpy(item->value, &u16, sizeof(u16)); + break; + case ICMAP_VALUETYPE_INT32: + case ICMAP_VALUETYPE_UINT32: + memcpy(&u32, item->value, sizeof(u32)); + u32 = swab32(u32); + memcpy(item->value, &u32, sizeof(u32)); + break; + case ICMAP_VALUETYPE_INT64: + case ICMAP_VALUETYPE_UINT64: + memcpy(&u64, item->value, sizeof(u64)); + u64 = swab64(u64); + memcpy(item->value, &u64, sizeof(u64)); + break; + /* + * TODO: Need to convert also float and double + */ + } + + p += sizeof(*item) + item->value_len; + } +} -- 1.7.1 _______________________________________________ discuss mailing list discuss@xxxxxxxxxxxx http://lists.corosync.org/mailman/listinfo/discuss