|
|
@@ -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;
|
|
|
+ }
|
|
|
+}
|