1 /* 2 * Copyright © 2013-2017 Inria. All rights reserved. 3 * See COPYING in top-level directory. 4 */ 5 6 /** \file 7 * \brief Topology differences. 8 */ 9 10 #ifndef HWLOC_DIFF_H 11 #define HWLOC_DIFF_H 12 13 #ifndef HWLOC_H 14 #error Please include the main hwloc.h instead 15 #endif 16 17 18 #ifdef __cplusplus 19 extern "C" { 20 #elif 0 21 } 22 #endif 23 24 25 /** \defgroup hwlocality_diff Topology differences 26 * 27 * Applications that manipulate many similar topologies, for instance 28 * one for each node of a homogeneous cluster, may want to compress 29 * topologies to reduce the memory footprint. 30 * 31 * This file offers a way to manipulate the difference between topologies 32 * and export/import it to/from XML. 33 * Compression may therefore be achieved by storing one topology 34 * entirely while the others are only described by their differences 35 * with the former. 36 * The actual topology can be reconstructed when actually needed by 37 * applying the precomputed difference to the reference topology. 38 * 39 * This interface targets very similar nodes. 40 * Only very simple differences between topologies are actually 41 * supported, for instance a change in the memory size, the name 42 * of the object, or some info attribute. 43 * More complex differences such as adding or removing objects cannot 44 * be represented in the difference structures and therefore return 45 * errors. 46 * 47 * It means that there is no need to apply the difference when 48 * looking at the tree organization (how many levels, how many 49 * objects per level, what kind of objects, CPU and node sets, etc) 50 * and when binding to objects. 51 * However the difference must be applied when looking at object 52 * attributes such as the name, the memory size or info attributes. 53 * 54 * @{ 55 */ 56 57 58 /** \brief Type of one object attribute difference. 59 */ 60 typedef enum hwloc_topology_diff_obj_attr_type_e { 61 /** \brief The object local memory is modified. 62 * The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_uint64_s 63 * (and the index field is ignored). 64 */ 65 HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE, 66 67 /** \brief The object name is modified. 68 * The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_string_s 69 * (and the name field is ignored). 70 */ 71 72 HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME, 73 /** \brief the value of an info attribute is modified. 74 * The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_string_s. 75 */ 76 HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO 77 } hwloc_topology_diff_obj_attr_type_t; 78 79 /** \brief One object attribute difference. 80 */ 81 union hwloc_topology_diff_obj_attr_u { 82 struct hwloc_topology_diff_obj_attr_generic_s { 83 /* each part of the union must start with these */ 84 hwloc_topology_diff_obj_attr_type_t type; 85 } generic; 86 87 /** \brief Integer attribute modification with an optional index. */ 88 struct hwloc_topology_diff_obj_attr_uint64_s { 89 /* used for storing integer attributes */ 90 hwloc_topology_diff_obj_attr_type_t type; 91 hwloc_uint64_t index; /* not used for SIZE */ 92 hwloc_uint64_t oldvalue; 93 hwloc_uint64_t newvalue; 94 } uint64; 95 96 /** \brief String attribute modification with an optional name */ 97 struct hwloc_topology_diff_obj_attr_string_s { 98 /* used for storing name and info pairs */ 99 hwloc_topology_diff_obj_attr_type_t type; 100 char *name; /* not used for NAME */ 101 char *oldvalue; 102 char *newvalue; 103 } string; 104 }; 105 106 107 /** \brief Type of one element of a difference list. 108 */ 109 typedef enum hwloc_topology_diff_type_e { 110 /** \brief An object attribute was changed. 111 * The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_s. 112 */ 113 HWLOC_TOPOLOGY_DIFF_OBJ_ATTR, 114 115 /** \brief The difference is too complex, 116 * it cannot be represented. The difference below 117 * this object has not been checked. 118 * hwloc_topology_diff_build() will return 1. 119 * 120 * The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_too_complex_s. 121 */ 122 HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX 123 } hwloc_topology_diff_type_t; 124 125 /** \brief One element of a difference list between two topologies. 126 */ 127 typedef union hwloc_topology_diff_u { 128 struct hwloc_topology_diff_generic_s { 129 /* each part of the union must start with these */ 130 hwloc_topology_diff_type_t type; 131 union hwloc_topology_diff_u * next; /* pointer to the next element of the list, or NULL */ 132 } generic; 133 134 /* A difference in an object attribute. */ 135 struct hwloc_topology_diff_obj_attr_s { 136 hwloc_topology_diff_type_t type; /* must be ::HWLOC_TOPOLOGY_DIFF_OBJ_ATTR */ 137 union hwloc_topology_diff_u * next; 138 /* List of attribute differences for a single object */ 139 int obj_depth; 140 unsigned obj_index; 141 union hwloc_topology_diff_obj_attr_u diff; 142 } obj_attr; 143 144 /* A difference that is too complex. */ 145 struct hwloc_topology_diff_too_complex_s { 146 hwloc_topology_diff_type_t type; /* must be ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX */ 147 union hwloc_topology_diff_u * next; 148 /* Where we had to stop computing the diff in the first topology */ 149 int obj_depth; 150 unsigned obj_index; 151 } too_complex; 152 } * hwloc_topology_diff_t; 153 154 155 /** \brief Compute the difference between 2 topologies. 156 * 157 * The difference is stored as a list of ::hwloc_topology_diff_t entries 158 * starting at \p diff. 159 * It is computed by doing a depth-first traversal of both topology trees 160 * simultaneously. 161 * 162 * If the difference between 2 objects is too complex to be represented 163 * (for instance if some objects have different types, or different numbers 164 * of children), a special diff entry of type ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX 165 * is queued. 166 * The computation of the diff does not continue below these objects. 167 * So each such diff entry means that the difference between two subtrees 168 * could not be computed. 169 * 170 * \return 0 if the difference can be represented properly. 171 * 172 * \return 0 with \p diff pointing to NULL if there is no difference 173 * between the topologies. 174 * 175 * \return 1 if the difference is too complex (see above). Some entries in 176 * the list will be of type ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX. 177 * 178 * \return -1 on any other error. 179 * 180 * \note \p flags is currently not used. It should be 0. 181 * 182 * \note The output diff has to be freed with hwloc_topology_diff_destroy(). 183 * 184 * \note The output diff can only be exported to XML or passed to 185 * hwloc_topology_diff_apply() if 0 was returned, i.e. if no entry of type 186 * ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX is listed. 187 * 188 * \note The output diff may be modified by removing some entries from 189 * the list. The removed entries should be freed by passing them to 190 * to hwloc_topology_diff_destroy() (possible as another list). 191 */ 192 HWLOC_DECLSPEC int hwloc_topology_diff_build(hwloc_topology_t topology, hwloc_topology_t newtopology, unsigned long flags, hwloc_topology_diff_t *diff); 193 194 /** \brief Flags to be given to hwloc_topology_diff_apply(). 195 */ 196 enum hwloc_topology_diff_apply_flags_e { 197 /** \brief Apply topology diff in reverse direction. 198 * \hideinitializer 199 */ 200 HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE = (1UL<<0) 201 }; 202 203 /** \brief Apply a topology diff to an existing topology. 204 * 205 * \p flags is an OR'ed set of ::hwloc_topology_diff_apply_flags_e. 206 * 207 * The new topology is modified in place. hwloc_topology_dup() 208 * may be used to duplicate it before patching. 209 * 210 * If the difference cannot be applied entirely, all previous applied 211 * elements are unapplied before returning. 212 * 213 * \return 0 on success. 214 * 215 * \return -N if applying the difference failed while trying 216 * to apply the N-th part of the difference. For instance -1 217 * is returned if the very first difference element could not 218 * be applied. 219 */ 220 HWLOC_DECLSPEC int hwloc_topology_diff_apply(hwloc_topology_t topology, hwloc_topology_diff_t diff, unsigned long flags); 221 222 /** \brief Destroy a list of topology differences. 223 */ 224 HWLOC_DECLSPEC int hwloc_topology_diff_destroy(hwloc_topology_diff_t diff); 225 226 /** \brief Load a list of topology differences from a XML file. 227 * 228 * If not \c NULL, \p refname will be filled with the identifier 229 * string of the reference topology for the difference file, 230 * if any was specified in the XML file. 231 * This identifier is usually the name of the other XML file 232 * that contains the reference topology. 233 * 234 * \note the pointer returned in refname should later be freed 235 * by the caller. 236 */ 237 HWLOC_DECLSPEC int hwloc_topology_diff_load_xml(const char *xmlpath, hwloc_topology_diff_t *diff, char **refname); 238 239 /** \brief Export a list of topology differences to a XML file. 240 * 241 * If not \c NULL, \p refname defines an identifier string 242 * for the reference topology which was used as a base when 243 * computing this difference. 244 * This identifier is usually the name of the other XML file 245 * that contains the reference topology. 246 * This attribute is given back when reading the diff from XML. 247 */ 248 HWLOC_DECLSPEC int hwloc_topology_diff_export_xml(hwloc_topology_diff_t diff, const char *refname, const char *xmlpath); 249 250 /** \brief Load a list of topology differences from a XML buffer. 251 * 252 * If not \c NULL, \p refname will be filled with the identifier 253 * string of the reference topology for the difference file, 254 * if any was specified in the XML file. 255 * This identifier is usually the name of the other XML file 256 * that contains the reference topology. 257 * 258 * \note the pointer returned in refname should later be freed 259 * by the caller. 260 */ 261 HWLOC_DECLSPEC int hwloc_topology_diff_load_xmlbuffer(const char *xmlbuffer, int buflen, hwloc_topology_diff_t *diff, char **refname); 262 263 /** \brief Export a list of topology differences to a XML buffer. 264 * 265 * If not \c NULL, \p refname defines an identifier string 266 * for the reference topology which was used as a base when 267 * computing this difference. 268 * This identifier is usually the name of the other XML file 269 * that contains the reference topology. 270 * This attribute is given back when reading the diff from XML. 271 * 272 * \note The XML buffer should later be freed with hwloc_free_xmlbuffer(). 273 */ 274 HWLOC_DECLSPEC int hwloc_topology_diff_export_xmlbuffer(hwloc_topology_diff_t diff, const char *refname, char **xmlbuffer, int *buflen); 275 276 /** @} */ 277 278 279 #ifdef __cplusplus 280 } /* extern "C" */ 281 #endif 282 283 284 #endif /* HWLOC_DIFF_H */