diff options
Diffstat (limited to 'hwloc-1.2.1/src/topology-xml.c')
-rw-r--r-- | hwloc-1.2.1/src/topology-xml.c | 700 |
1 files changed, 700 insertions, 0 deletions
diff --git a/hwloc-1.2.1/src/topology-xml.c b/hwloc-1.2.1/src/topology-xml.c new file mode 100644 index 00000000..60b3ea1f --- /dev/null +++ b/hwloc-1.2.1/src/topology-xml.c @@ -0,0 +1,700 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2011 INRIA. All rights reserved. + * Copyright © 2009-2011 Université Bordeaux 1 + * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved. + * See COPYING in top-level directory. + */ + +#include <private/autogen/config.h> +#include <hwloc.h> +#include <private/private.h> +#include <private/debug.h> + +#ifdef HWLOC_HAVE_XML + +#include <libxml/parser.h> +#include <libxml/tree.h> + +#include <assert.h> +#include <strings.h> + +int +hwloc_backend_xml_init(struct hwloc_topology *topology, const char *xmlpath, const char *xmlbuffer, int buflen) +{ + xmlDoc *doc = NULL; + + assert(topology->backend_type == HWLOC_BACKEND_NONE); + + LIBXML_TEST_VERSION; + + if (xmlpath) + doc = xmlReadFile(xmlpath, NULL, 0); + else if (xmlbuffer) + doc = xmlReadMemory(xmlbuffer, buflen, "", NULL, 0); + if (!doc) + return -1; + + topology->backend_params.xml.doc = doc; + topology->is_thissystem = 0; + topology->backend_type = HWLOC_BACKEND_XML; + return 0; +} + +void +hwloc_backend_xml_exit(struct hwloc_topology *topology) +{ + assert(topology->backend_type == HWLOC_BACKEND_XML); + xmlFreeDoc((xmlDoc*)topology->backend_params.xml.doc); + topology->backend_type = HWLOC_BACKEND_NONE; +} + +/****************************** + ********* XML import ********* + ******************************/ + +static void hwloc__xml_import_node(struct hwloc_topology *topology, struct hwloc_obj *parent, xmlNode *node, int depth); + +static const xmlChar * +hwloc__xml_import_attr_value(xmlAttr *attr) +{ + xmlNode *subnode; + /* use the first valid attribute content */ + for (subnode = attr->children; subnode; subnode = subnode->next) { + if (subnode->type == XML_TEXT_NODE) { + if (subnode->content && subnode->content[0] != '\0' && subnode->content[0] != '\n') + return subnode->content; + } else { + fprintf(stderr, "ignoring unexpected xml attr node type %u\n", subnode->type); + } + } + return NULL; +} + +static void +hwloc__xml_import_object_attr(struct hwloc_topology *topology __hwloc_attribute_unused, struct hwloc_obj *obj, + const xmlChar *_name, const xmlChar *_value) +{ + const char *name = (const char *) _name; + const char *value = (const char *) _value; + + if (!strcmp(name, "type")) { + /* already handled */ + return; + } + + else if (!strcmp(name, "os_level")) + obj->os_level = strtoul(value, NULL, 10); + else if (!strcmp(name, "os_index")) + obj->os_index = strtoul(value, NULL, 10); + else if (!strcmp(name, "cpuset")) { + obj->cpuset = hwloc_bitmap_alloc(); + hwloc_bitmap_sscanf(obj->cpuset, value); + } else if (!strcmp(name, "complete_cpuset")) { + obj->complete_cpuset = hwloc_bitmap_alloc(); + hwloc_bitmap_sscanf(obj->complete_cpuset,value); + } else if (!strcmp(name, "online_cpuset")) { + obj->online_cpuset = hwloc_bitmap_alloc(); + hwloc_bitmap_sscanf(obj->online_cpuset, value); + } else if (!strcmp(name, "allowed_cpuset")) { + obj->allowed_cpuset = hwloc_bitmap_alloc(); + hwloc_bitmap_sscanf(obj->allowed_cpuset, value); + } else if (!strcmp(name, "nodeset")) { + obj->nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_sscanf(obj->nodeset, value); + } else if (!strcmp(name, "complete_nodeset")) { + obj->complete_nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_sscanf(obj->complete_nodeset, value); + } else if (!strcmp(name, "allowed_nodeset")) { + obj->allowed_nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_sscanf(obj->allowed_nodeset, value); + } else if (!strcmp(name, "name")) + obj->name = strdup(value); + + else if (!strcmp(name, "cache_size")) { + unsigned long long lvalue = strtoull(value, NULL, 10); + if (obj->type == HWLOC_OBJ_CACHE) + obj->attr->cache.size = lvalue; + else + fprintf(stderr, "ignoring cache_size attribute for non-cache object type\n"); + } + + else if (!strcmp(name, "cache_linesize")) { + unsigned long lvalue = strtoul(value, NULL, 10); + if (obj->type == HWLOC_OBJ_CACHE) + obj->attr->cache.linesize = lvalue; + else + fprintf(stderr, "ignoring cache_linesize attribute for non-cache object type\n"); + } + + else if (!strcmp(name, "local_memory")) + obj->memory.local_memory = strtoull(value, NULL, 10); + + else if (!strcmp(name, "depth")) { + unsigned long lvalue = strtoul(value, NULL, 10); + switch (obj->type) { + case HWLOC_OBJ_CACHE: + obj->attr->cache.depth = lvalue; + break; + case HWLOC_OBJ_GROUP: + obj->attr->group.depth = lvalue; + break; + default: + fprintf(stderr, "ignoring depth attribute for object type without depth\n"); + break; + } + } + + + + /************************* + * deprecated (from 1.0) + */ + else if (!strcmp(name, "dmi_board_vendor")) { + hwloc_add_object_info(obj, "DMIBoardVendor", strdup(value)); + } + else if (!strcmp(name, "dmi_board_name")) { + hwloc_add_object_info(obj, "DMIBoardName", strdup(value)); + } + + /************************* + * deprecated (from 0.9) + */ + else if (!strcmp(name, "memory_kB")) { + unsigned long long lvalue = strtoull(value, NULL, 10); + switch (obj->type) { + case HWLOC_OBJ_CACHE: + obj->attr->cache.size = lvalue << 10; + break; + case HWLOC_OBJ_NODE: + case HWLOC_OBJ_MACHINE: + case HWLOC_OBJ_SYSTEM: + obj->memory.local_memory = lvalue << 10; + break; + default: + fprintf(stderr, "ignoring memory_kB attribute for object type without memory\n"); + break; + } + } + else if (!strcmp(name, "huge_page_size_kB")) { + unsigned long lvalue = strtoul(value, NULL, 10); + switch (obj->type) { + case HWLOC_OBJ_NODE: + case HWLOC_OBJ_MACHINE: + case HWLOC_OBJ_SYSTEM: + if (!obj->memory.page_types) { + obj->memory.page_types = malloc(sizeof(*obj->memory.page_types)); + obj->memory.page_types_len = 1; + } + obj->memory.page_types[0].size = lvalue << 10; + break; + default: + fprintf(stderr, "ignoring huge_page_size_kB attribute for object type without huge pages\n"); + break; + } + } + else if (!strcmp(name, "huge_page_free")) { + unsigned long lvalue = strtoul(value, NULL, 10); + switch (obj->type) { + case HWLOC_OBJ_NODE: + case HWLOC_OBJ_MACHINE: + case HWLOC_OBJ_SYSTEM: + if (!obj->memory.page_types) { + obj->memory.page_types = malloc(sizeof(*obj->memory.page_types)); + obj->memory.page_types_len = 1; + } + obj->memory.page_types[0].count = lvalue; + break; + default: + fprintf(stderr, "ignoring huge_page_free attribute for object type without huge pages\n"); + break; + } + } + /* + * end of deprecated (from 0.9) + *******************************/ + + + + else + fprintf(stderr, "ignoring unknown object attribute %s\n", name); +} + +static void +hwloc__xml_import_object_node(struct hwloc_topology *topology, struct hwloc_obj *parent, struct hwloc_obj *obj, xmlNode *node, int depth) +{ + xmlAttr *attr = NULL; + + /* first determine the object type */ + for (attr = node->properties; attr; attr = attr->next) { + if (attr->type == XML_ATTRIBUTE_NODE && !strcmp((const char*) attr->name, "type")) { + const xmlChar *value = hwloc__xml_import_attr_value(attr); + if (!value) { + fprintf(stderr, "ignoring xml object without type attr %s\n", (const char*) value); + return; + } + obj->type = hwloc_obj_type_of_string((const char*) value); + if (obj->type == (hwloc_obj_type_t)-1) { + fprintf(stderr, "ignoring unknown object type %s\n", (const char*) value); + return; + } + break; + } else { + fprintf(stderr, "ignoring unexpected xml attr type %u\n", attr->type); + } + } + if (obj->type == HWLOC_OBJ_TYPE_MAX) { + fprintf(stderr, "ignoring object without type\n"); + return; + } + + /* process attributes now that the type is known */ + for (attr = node->properties; attr; attr = attr->next) { + if (attr->type == XML_ATTRIBUTE_NODE) { + const xmlChar *value = hwloc__xml_import_attr_value(attr); + if (value) + hwloc__xml_import_object_attr(topology, obj, attr->name, value); + } else { + fprintf(stderr, "ignoring unexpected xml object attr type %u\n", attr->type); + } + } + + if (depth > 0) { /* root object is already in place */ + /* add object */ + hwloc_insert_object_by_parent(topology, parent, obj); + } + + /* process children */ + if (node->children) + hwloc__xml_import_node(topology, obj, node->children, depth+1); +} + +static void +hwloc__xml_import_pagetype_node(struct hwloc_topology *topology __hwloc_attribute_unused, struct hwloc_obj *obj, xmlNode *node) +{ + uint64_t size = 0, count = 0; + xmlAttr *attr = NULL; + + for (attr = node->properties; attr; attr = attr->next) { + if (attr->type == XML_ATTRIBUTE_NODE) { + const xmlChar *value = hwloc__xml_import_attr_value(attr); + if (value) { + if (!strcmp((char *) attr->name, "size")) + size = strtoul((char *) value, NULL, 10); + else if (!strcmp((char *) attr->name, "count")) + count = strtoul((char *) value, NULL, 10); + else + fprintf(stderr, "ignoring unknown pagetype attribute %s\n", (char *) attr->name); + } + } else { + fprintf(stderr, "ignoring unexpected xml pagetype attr type %u\n", attr->type); + } + } + + if (size) { + int idx = obj->memory.page_types_len; + obj->memory.page_types = realloc(obj->memory.page_types, (idx+1)*sizeof(*obj->memory.page_types)); + obj->memory.page_types_len = idx+1; + obj->memory.page_types[idx].size = size; + obj->memory.page_types[idx].count = count; + } else + fprintf(stderr, "ignoring pagetype attribute without size\n"); +} + +static void +hwloc__xml_import_distances_node(struct hwloc_topology *topology __hwloc_attribute_unused, struct hwloc_obj *obj, xmlNode *node) +{ + unsigned long reldepth = 0, nbobjs = 0; + float latbase = 0; + xmlAttr *attr = NULL; + xmlNode *subnode; + + for (attr = node->properties; attr; attr = attr->next) { + if (attr->type == XML_ATTRIBUTE_NODE) { + const xmlChar *value = hwloc__xml_import_attr_value(attr); + if (value) { + if (!strcmp((char *) attr->name, "nbobjs")) + nbobjs = strtoul((char *) value, NULL, 10); + else if (!strcmp((char *) attr->name, "relative_depth")) + reldepth = strtoul((char *) value, NULL, 10); + else if (!strcmp((char *) attr->name, "latency_base")) + latbase = (float) atof((char *) value); + else + fprintf(stderr, "ignoring unknown distances attribute %s\n", (char *) attr->name); + } else + fprintf(stderr, "ignoring unexpected xml distances attr name `%s' with no value\n", (const char*) attr->name); + } else { + fprintf(stderr, "ignoring unexpected xml distances attr type %u\n", attr->type); + } + } + + if (nbobjs && reldepth && latbase) { + int idx = obj->distances_count; + unsigned nbcells, i; + float *matrix, latmax = 0; + + nbcells = 0; + if (node->children) + for(subnode = node->children; subnode; subnode = subnode->next) + if (subnode->type == XML_ELEMENT_NODE) + nbcells++; + if (nbcells != nbobjs*nbobjs) { + fprintf(stderr, "ignoring distances with %u cells instead of %lu\n", nbcells, nbobjs*nbobjs); + return; + } + + obj->distances = realloc(obj->distances, (idx+1)*sizeof(*obj->distances)); + obj->distances_count = idx+1; + obj->distances[idx] = malloc(sizeof(**obj->distances)); + obj->distances[idx]->relative_depth = reldepth; + obj->distances[idx]->nbobjs = nbobjs; + obj->distances[idx]->latency = matrix = malloc(nbcells*sizeof(float)); + obj->distances[idx]->latency_base = latbase; + + i = 0; + for(subnode = node->children; subnode; subnode = subnode->next) + if (subnode->type == XML_ELEMENT_NODE) { + /* read one cell */ + for (attr = subnode->properties; attr; attr = attr->next) + if (attr->type == XML_ATTRIBUTE_NODE) { + const xmlChar *value = hwloc__xml_import_attr_value(attr); + if (value) { + if (!strcmp((char *) attr->name, "value")) { + float val = (float) atof((char *) value); + matrix[i] = val; + if (val > latmax) + latmax = val; + } else + fprintf(stderr, "ignoring unknown distance attribute %s\n", (char *) attr->name); + } else + fprintf(stderr, "ignoring unexpected xml distance attr name `%s' with no value\n", (const char*) attr->name); + } else { + fprintf(stderr, "ignoring unexpected xml distance attr type %u\n", attr->type); + } + /* next matrix cell */ + i++; + } + + obj->distances[idx]->latency_max = latmax; + } +} + +static void +hwloc__xml_import_info_node(struct hwloc_topology *topology __hwloc_attribute_unused, struct hwloc_obj *obj, xmlNode *node) +{ + char *infoname = NULL; + char *infovalue = NULL; + xmlAttr *attr = NULL; + + for (attr = node->properties; attr; attr = attr->next) { + if (attr->type == XML_ATTRIBUTE_NODE) { + const xmlChar *value = hwloc__xml_import_attr_value(attr); + if (value) { + if (!strcmp((char *) attr->name, "name")) + infoname = (char *) value; + else if (!strcmp((char *) attr->name, "value")) + infovalue = (char *) value; + else + fprintf(stderr, "ignoring unknown info attribute %s\n", (char *) attr->name); + } + } else { + fprintf(stderr, "ignoring unexpected xml info attr type %u\n", attr->type); + } + } + + if (infoname) + /* empty strings are ignored by libxml */ + hwloc_add_object_info(obj, infoname, infovalue ? infovalue : ""); + else + fprintf(stderr, "ignoring info attribute without name\n"); +} + +static void +hwloc__xml_import_node(struct hwloc_topology *topology, struct hwloc_obj *parent, xmlNode *node, int depth) +{ + for (; node; node = node->next) { + if (node->type == XML_ELEMENT_NODE) { + if (!strcmp((const char*) node->name, "object")) { + /* object attributes */ + struct hwloc_obj *obj; + if (depth) + obj = hwloc_alloc_setup_object(HWLOC_OBJ_TYPE_MAX, -1); + else + obj = topology->levels[0][0]; + hwloc__xml_import_object_node(topology, parent, obj, node, depth); + + } else if (!strcmp((const char*) node->name, "page_type")) { + hwloc__xml_import_pagetype_node(topology, parent, node); + + } else if (!strcmp((const char*) node->name, "info")) { + hwloc__xml_import_info_node(topology, parent, node); + + } else if (!strcmp((const char*) node->name, "distances")) { + hwloc__xml_import_distances_node(topology, parent, node); + + } else { + /* unknown class */ + fprintf(stderr, "ignoring unexpected node class `%s'\n", (const char*) node->name); + continue; + } + + } else if (node->type == XML_TEXT_NODE) { + if (node->content && node->content[0] != '\0' && node->content[0] != '\n') + fprintf(stderr, "ignoring object text content %s\n", (const char*) node->content); + } else { + fprintf(stderr, "ignoring unexpected xml node type %u\n", node->type); + } + } +} + +static void +hwloc__xml_import_topology_node(struct hwloc_topology *topology, xmlNode *node) +{ + xmlAttr *attr = NULL; + + if (strcmp((const char *) node->name, "topology") && strcmp((const char *) node->name, "root")) { + /* root node should be in "topology" class (or "root" if importing from < 1.0) */ + fprintf(stderr, "ignoring object of class `%s' not at the top the xml hierarchy\n", (const char *) node->name); + return; + } + + /* process attributes */ + for (attr = node->properties; attr; attr = attr->next) { + if (attr->type == XML_ATTRIBUTE_NODE) { + const xmlChar *value = hwloc__xml_import_attr_value(attr); + if (value) { + fprintf(stderr, "ignoring unknown root attribute %s\n", (char *) attr->name); + } + } else { + fprintf(stderr, "ignoring unexpected xml root attr type %u\n", attr->type); + } + } + + /* process children */ + if (node->children) + hwloc__xml_import_node(topology, NULL, node->children, 0); +} + +void +hwloc_look_xml(struct hwloc_topology *topology) +{ + xmlNode* root_node; + xmlDtd *dtd; + + topology->support.discovery->pu = 1; + + dtd = xmlGetIntSubset((xmlDoc*) topology->backend_params.xml.doc); + if (!dtd) + fprintf(stderr, "Loading XML topology without DTD\n"); + else if (strcmp((char *) dtd->SystemID, "hwloc.dtd")) + fprintf(stderr, "Loading XML topology with wrong DTD SystemID (%s instead of %s)\n", + (char *) dtd->SystemID, "hwloc.dtd"); + + root_node = xmlDocGetRootElement((xmlDoc*) topology->backend_params.xml.doc); + + hwloc__xml_import_topology_node(topology, root_node); + if (root_node->next) + fprintf(stderr, "ignoring non-first root nodes\n"); + + /* keep the "Backend" information intact */ + /* we could add "BackendSource=XML" to notify that XML was used between the actual backend and here */ +} + +static void +hwloc_xml__check_distances(struct hwloc_topology *topology, hwloc_obj_t obj) +{ + hwloc_obj_t child; + unsigned i=0; + while (i<obj->distances_count) { + unsigned depth = obj->depth + obj->distances[i]->relative_depth; + unsigned nbobjs = hwloc_get_nbobjs_inside_cpuset_by_depth(topology, obj->cpuset, depth); + if (nbobjs != obj->distances[i]->nbobjs) { + fprintf(stderr, "ignoring invalid distance matrix with %u objs instead of %u\n", + obj->distances[i]->nbobjs, nbobjs); + hwloc_free_logical_distances(obj->distances[i]); + memmove(&obj->distances[i], &obj->distances[i+1], (obj->distances_count-i-1)*sizeof(*obj->distances)); + obj->distances_count--; + } else + i++; + } + + child = obj->first_child; + while (child != NULL) { + hwloc_xml__check_distances(topology, child); + child = child->next_sibling; + } +} + +void +hwloc_xml_check_distances(struct hwloc_topology *topology) +{ + /* now that the topology tree has been properly setup, + * check that our distance matrice sizes make sense */ + hwloc_xml__check_distances(topology, topology->levels[0][0]); +} + +/****************************** + ********* XML export ********* + ******************************/ + +static void +hwloc__xml_export_object (hwloc_topology_t topology, hwloc_obj_t obj, xmlNodePtr root_node) +{ + xmlNodePtr node = NULL, ptnode = NULL, dnode = NULL, dcnode = NULL; + char *cpuset = NULL; + char tmp[255]; + unsigned i; + + /* xmlNewChild() creates a new node, which is "attached" as child node + * of root_node node. */ + node = xmlNewChild(root_node, NULL, BAD_CAST "object", NULL); + xmlNewProp(node, BAD_CAST "type", BAD_CAST hwloc_obj_type_string(obj->type)); + sprintf(tmp, "%d", obj->os_level); + xmlNewProp(node, BAD_CAST "os_level", BAD_CAST tmp); + if (obj->os_index != (unsigned) -1) { + sprintf(tmp, "%u", obj->os_index); + xmlNewProp(node, BAD_CAST "os_index", BAD_CAST tmp); + } + if (obj->cpuset) { + hwloc_bitmap_asprintf(&cpuset, obj->cpuset); + xmlNewProp(node, BAD_CAST "cpuset", BAD_CAST cpuset); + free(cpuset); + } + if (obj->complete_cpuset) { + hwloc_bitmap_asprintf(&cpuset, obj->complete_cpuset); + xmlNewProp(node, BAD_CAST "complete_cpuset", BAD_CAST cpuset); + free(cpuset); + } + if (obj->online_cpuset) { + hwloc_bitmap_asprintf(&cpuset, obj->online_cpuset); + xmlNewProp(node, BAD_CAST "online_cpuset", BAD_CAST cpuset); + free(cpuset); + } + if (obj->allowed_cpuset) { + hwloc_bitmap_asprintf(&cpuset, obj->allowed_cpuset); + xmlNewProp(node, BAD_CAST "allowed_cpuset", BAD_CAST cpuset); + free(cpuset); + } + if (obj->nodeset && !hwloc_bitmap_isfull(obj->nodeset)) { + hwloc_bitmap_asprintf(&cpuset, obj->nodeset); + xmlNewProp(node, BAD_CAST "nodeset", BAD_CAST cpuset); + free(cpuset); + } + if (obj->complete_nodeset && !hwloc_bitmap_isfull(obj->complete_nodeset)) { + hwloc_bitmap_asprintf(&cpuset, obj->complete_nodeset); + xmlNewProp(node, BAD_CAST "complete_nodeset", BAD_CAST cpuset); + free(cpuset); + } + if (obj->allowed_nodeset && !hwloc_bitmap_isfull(obj->allowed_nodeset)) { + hwloc_bitmap_asprintf(&cpuset, obj->allowed_nodeset); + xmlNewProp(node, BAD_CAST "allowed_nodeset", BAD_CAST cpuset); + free(cpuset); + } + + if (obj->name) + xmlNewProp(node, BAD_CAST "name", BAD_CAST obj->name); + + switch (obj->type) { + case HWLOC_OBJ_CACHE: + sprintf(tmp, "%llu", (unsigned long long) obj->attr->cache.size); + xmlNewProp(node, BAD_CAST "cache_size", BAD_CAST tmp); + sprintf(tmp, "%u", obj->attr->cache.depth); + xmlNewProp(node, BAD_CAST "depth", BAD_CAST tmp); + sprintf(tmp, "%u", (unsigned) obj->attr->cache.linesize); + xmlNewProp(node, BAD_CAST "cache_linesize", BAD_CAST tmp); + break; + case HWLOC_OBJ_GROUP: + sprintf(tmp, "%u", obj->attr->group.depth); + xmlNewProp(node, BAD_CAST "depth", BAD_CAST tmp); + break; + default: + break; + } + + if (obj->memory.local_memory) { + sprintf(tmp, "%llu", (unsigned long long) obj->memory.local_memory); + xmlNewProp(node, BAD_CAST "local_memory", BAD_CAST tmp); + } + for(i=0; i<obj->memory.page_types_len; i++) { + ptnode = xmlNewChild(node, NULL, BAD_CAST "page_type", NULL); + sprintf(tmp, "%llu", (unsigned long long) obj->memory.page_types[i].size); + xmlNewProp(ptnode, BAD_CAST "size", BAD_CAST tmp); + sprintf(tmp, "%llu", (unsigned long long) obj->memory.page_types[i].count); + xmlNewProp(ptnode, BAD_CAST "count", BAD_CAST tmp); + } + + for(i=0; i<obj->infos_count; i++) { + ptnode = xmlNewChild(node, NULL, BAD_CAST "info", NULL); + xmlNewProp(ptnode, BAD_CAST "name", BAD_CAST obj->infos[i].name); + xmlNewProp(ptnode, BAD_CAST "value", BAD_CAST obj->infos[i].value); + } + + for(i=0; i<obj->distances_count; i++) { + unsigned nbobjs = obj->distances[i]->nbobjs; + unsigned j; + dnode = xmlNewChild(node, NULL, BAD_CAST "distances", NULL); + sprintf(tmp, "%u", nbobjs); + xmlNewProp(dnode, BAD_CAST "nbobjs", BAD_CAST tmp); + sprintf(tmp, "%u", obj->distances[i]->relative_depth); + xmlNewProp(dnode, BAD_CAST "relative_depth", BAD_CAST tmp); + sprintf(tmp, "%f", obj->distances[i]->latency_base); + xmlNewProp(dnode, BAD_CAST "latency_base", BAD_CAST tmp); + for(j=0; j<nbobjs*nbobjs; j++) { + dcnode = xmlNewChild(dnode, NULL, BAD_CAST "latency", NULL); + sprintf(tmp, "%f", obj->distances[i]->latency[j]); + xmlNewProp(dcnode, BAD_CAST "value", BAD_CAST tmp); + } + } + + if (obj->arity) { + unsigned x; + for (x=0; x<obj->arity; x++) + hwloc__xml_export_object (topology, obj->children[x], node); + } +} + +static void +hwloc__xml_export_topology_info (hwloc_topology_t topology __hwloc_attribute_unused, xmlNodePtr root_node __hwloc_attribute_unused) +{ +} + +static xmlDocPtr +hwloc__topology_prepare_export(hwloc_topology_t topology) +{ + xmlDocPtr doc = NULL; /* document pointer */ + xmlNodePtr root_node = NULL; /* root pointer */ + xmlDtdPtr dtd = NULL; /* DTD pointer */ + + LIBXML_TEST_VERSION; + + /* Creates a new document, a node and set it as a root node. */ + doc = xmlNewDoc(BAD_CAST "1.0"); + root_node = xmlNewNode(NULL, BAD_CAST "topology"); + xmlDocSetRootElement(doc, root_node); + + /* Creates a DTD declaration. Isn't mandatory. */ + dtd = xmlCreateIntSubset(doc, BAD_CAST "topology", NULL, BAD_CAST "hwloc.dtd"); + + hwloc__xml_export_object (topology, hwloc_get_root_obj(topology), root_node); + + hwloc__xml_export_topology_info (topology, root_node); + + return doc; +} + +void hwloc_topology_export_xml(hwloc_topology_t topology, const char *filename) +{ + xmlDocPtr doc = hwloc__topology_prepare_export(topology); + xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1); + xmlFreeDoc(doc); +} + +void hwloc_topology_export_xmlbuffer(hwloc_topology_t topology, char **xmlbuffer, int *buflen) +{ + xmlDocPtr doc = hwloc__topology_prepare_export(topology); + xmlDocDumpFormatMemoryEnc(doc, (xmlChar **)xmlbuffer, buflen, "UTF-8", 1); + xmlFreeDoc(doc); +} + + +#endif /* HWLOC_HAVE_XML */ |