+static int process_map_node(xmlNodePtr map_node, struct lttng_handle *handle)
+{
+ int ret;
+ xmlNodePtr node;
+ xmlChar *name = NULL;
+ xmlChar *enabled_str = NULL;
+ int enabled;
+ xmlChar *bitness_str = NULL;
+ enum lttng_map_bitness bitness = LTTNG_MAP_BITNESS_32BITS;
+ xmlChar *boundary_policy_str = NULL;
+ enum lttng_map_boundary_policy boundary_policy = LTTNG_MAP_BOUNDARY_POLICY_OVERFLOW;
+ xmlChar *coalesce_hits_str = NULL;
+ int coalesce_hits;
+ enum lttng_map_status map_status;
+ struct lttng_map *map = NULL;
+ struct lttng_dynamic_array dimension_sizes;
+ enum lttng_error_code error_code;
+
+ assert(strcmp((const char *) map_node->name, config_element_map) == 0);
+
+ lttng_dynamic_array_init(&dimension_sizes, sizeof(uint64_t), NULL);
+
+ for (node = xmlFirstElementChild(map_node); node;
+ node = xmlNextElementSibling(node)) {
+ if (strcmp((const char *) node->name, config_element_name) ==
+ 0) {
+ assert(!name);
+ name = xmlNodeGetContent(node);
+ if (!name) {
+ ERR("Failed to get map name node content.");
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+ } else if (strcmp((const char *) node->name,
+ config_element_enabled) == 0) {
+ assert(!enabled_str);
+ enabled_str = xmlNodeGetContent(node);
+ if (!enabled_str) {
+ ERR("Failed to get map enabled node content.");
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ ret = parse_bool(enabled_str, &enabled);
+ assert(!ret);
+ } else if (strcmp((const char *) node->name,
+ config_element_bitness) == 0) {
+ assert(!bitness_str);
+ bitness_str = xmlNodeGetContent(node);
+ if (!bitness_str) {
+ ERR("Failed to get map bitness node content.");
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ if (strcmp((const char *) bitness_str, "32") == 0) {
+ bitness = LTTNG_MAP_BITNESS_32BITS;
+ } else {
+ assert(strcmp((const char *) bitness_str,
+ "64") == 0);
+ bitness = LTTNG_MAP_BITNESS_64BITS;
+ }
+ } else if (strcmp((const char *) node->name,
+ config_element_boundary_policy) ==
+ 0) {
+ assert(!boundary_policy_str);
+ boundary_policy_str = xmlNodeGetContent(node);
+ if (!boundary_policy_str) {
+ ERR("Failed to get map boundary policy node content.");
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ assert(strcmp((const char *) boundary_policy_str,
+ config_boundary_policy_overflow) ==
+ 0);
+ boundary_policy = LTTNG_MAP_BOUNDARY_POLICY_OVERFLOW;
+ } else if (strcmp((const char *) node->name,
+ config_element_coalesce_hits) == 0) {
+ assert(!coalesce_hits_str);
+ coalesce_hits_str = xmlNodeGetContent(node);
+ if (!coalesce_hits_str) {
+ ERR("Failed to get map coalesce hits node content.");
+ ret = -LTTNG_ERR_NOMEM;
+ goto end;
+ }
+
+ ret = parse_bool(coalesce_hits_str, &coalesce_hits);
+ assert(!ret);
+ } else if (strcmp((const char *) node->name,
+ config_element_dimensions) == 0) {
+ ret = process_dimensions_node(node, &dimension_sizes);
+ if (ret) {
+ goto end;
+ }
+ } else {
+ assert(false);
+ }
+ }
+
+ assert(name);
+ map_status = lttng_map_create((const char *) name,
+ lttng_dynamic_array_get_count(&dimension_sizes),
+ (uint64_t *) dimension_sizes.buffer.data,
+ handle->domain.type, handle->domain.buf_type, bitness,
+ boundary_policy, coalesce_hits, &map);
+ if (map_status != LTTNG_MAP_STATUS_OK) {
+ ERR("Failed to create map.");
+ ret = -LTTNG_ERR_UNK;
+ goto end;
+ }
+
+ error_code = lttng_add_map(handle, map);
+ if (error_code != LTTNG_OK) {
+ ERR("Adding map \"%s\": %s", (const char *) name,
+ lttng_strerror(error_code));
+ ret = error_code;
+ goto end;
+ }
+
+ // FIXME: disabling the map after creating leaves a window of time
+ // where it is enabled, does it matter?
+ if (!enabled) {
+ ret = lttng_disable_map(handle, (const char *) name);
+ if (ret) {
+ goto end;
+ }
+ }
+
+ ret = 0;
+
+end:
+ xmlFree(name);
+ xmlFree(enabled_str);
+ xmlFree(bitness_str);
+ xmlFree(boundary_policy_str);
+ xmlFree(coalesce_hits_str);
+ lttng_dynamic_array_reset(&dimension_sizes);
+ lttng_map_destroy(map);
+
+ return ret;
+}
+