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