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 */