1 /*
2 * Copyright © 2013-2019 Inria. All rights reserved.
3 * See COPYING in top-level directory.
4 */
5
6 #include <private/private.h>
7 #include <hwloc.h>
8 #include <hwloc/diff.h>
9
10 #include "misc.h"
11
usage(const char * callname __hwloc_attribute_unused,FILE * where)12 void usage(const char *callname __hwloc_attribute_unused, FILE *where)
13 {
14 fprintf(where, "Usage: hwloc-diff [options] <old.xml> <new.xml> [<output.diff.xml>]\n");
15 fprintf(where, "Options:\n");
16 fprintf(where, " --refname <name> Change the XML reference identifier to <name> in the output\n");
17 fprintf(where, " (default is the filename of the first topology\n");
18 fprintf(where, " --version Report version and exit\n");
19 }
20
main(int argc,char * argv[])21 int main(int argc, char *argv[])
22 {
23 hwloc_topology_t topo1, topo2;
24 hwloc_topology_diff_t firstdiff = NULL, diff;
25 unsigned long flags = HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM | HWLOC_TOPOLOGY_FLAG_WHOLE_IO | HWLOC_TOPOLOGY_FLAG_ICACHES;
26 char *callname, *input1, *input2, *output, *outputname, *refname = NULL;
27 char *xmlbuffer;
28 int xmlbuflen;
29 unsigned i, j;
30 int err;
31
32 putenv((char *) "HWLOC_XML_VERBOSE=1");
33 callname = argv[0];
34 /* skip argv[0], handle options */
35 argc--;
36 argv++;
37
38 while (argc && *argv[0] == '-') {
39 if (!strcmp (argv[0], "--refname")) {
40 if (argc < 2) {
41 usage(callname, stderr);
42 exit(EXIT_FAILURE);
43 }
44 refname = argv[1];
45 argc--;
46 argv++;
47 } else if (!strcmp (argv[0], "--version")) {
48 printf("%s %s\n", callname, HWLOC_VERSION);
49 exit(EXIT_SUCCESS);
50 } else {
51 fprintf(stderr, "Unrecognized options: %s\n", argv[0]);
52 usage(callname, stderr);
53 exit(EXIT_FAILURE);
54 }
55 argc--;
56 argv++;
57 }
58
59 if (argc < 2) {
60 usage(callname, stderr);
61 exit(EXIT_FAILURE);
62 }
63 input1 = argv[0];
64 input2 = argv[1];
65 argc -= 2;
66 argv += 2;
67 if (argc >= 1) {
68 output = argv[0];
69 outputname = argv[0];
70 argc--;
71 argv++;
72 } else {
73 output = NULL;
74 outputname = (char *) "stdout";
75 }
76
77 hwloc_topology_init(&topo1);
78 hwloc_topology_set_flags(topo1, flags);
79 err = hwloc_topology_set_xml(topo1, input1);
80 if (err < 0) {
81 fprintf(stderr, "Failed to load 1st XML topology %s\n", input1);
82 goto out_with_topo1;
83 }
84 err = hwloc_topology_load(topo1);
85 if (err < 0) {
86 fprintf(stderr, "Failed to load 1st topology %s\n", input1);
87 goto out_with_topo1;
88 }
89
90 hwloc_topology_init(&topo2);
91 hwloc_topology_set_flags(topo2, flags);
92 err = hwloc_topology_set_xml(topo2, input2);
93 if (err < 0) {
94 fprintf(stderr, "Failed to load 2nd XML topology %s\n", input2);
95 goto out_with_topo2;
96 }
97 err = hwloc_topology_load(topo2);
98 if (err < 0) {
99 fprintf(stderr, "Failed to load 2nd topology %s\n", input2);
100 goto out_with_topo2;
101 }
102
103 if (!refname) {
104 refname = strrchr(input1, '/');
105 if (refname)
106 refname++;
107 else
108 refname = input1;
109 }
110
111 err = hwloc_topology_diff_build(topo1, topo2, 0, &firstdiff);
112 if (err < 0) {
113 fprintf(stderr, "Failed to compute the diff (%s)\n", strerror(errno));
114 goto out_with_topo2;
115 }
116
117 diff = firstdiff;
118 i = 0, j = 0;
119 while (diff) {
120 i++;
121 if (diff->generic.type == HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX)
122 j++;
123 diff = diff->generic.next;
124 }
125 if (!i) {
126 fprintf(stderr, "Found no difference, exporting empty topology diff to %s\n", outputname);
127 } else if (!j) {
128 fprintf(stderr, "Found %u differences, exporting to %s\n", i, outputname);
129 } else {
130 fprintf(stderr, "Found %u differences, including %u too complex ones.\n", i, j);
131 fprintf(stderr, "Cannot export differences to %s\n", outputname);
132 }
133 if (!j) {
134 if (output) {
135 err = hwloc_topology_diff_export_xml(topo1, firstdiff, refname, output);
136 } else {
137 err = hwloc_topology_diff_export_xmlbuffer(topo1, firstdiff, refname, &xmlbuffer, &xmlbuflen);
138 if (!err) {
139 printf("%s\n", xmlbuffer);
140 hwloc_free_xmlbuffer(topo1, xmlbuffer);
141 }
142 }
143 if (err < 0)
144 fprintf(stderr, "Failed to export topology diff %s\n", output);
145 }
146
147 hwloc_topology_diff_destroy(topo1, firstdiff);
148
149 hwloc_topology_destroy(topo2);
150 hwloc_topology_destroy(topo1);
151
152 if (j)
153 exit(EXIT_FAILURE);
154 else
155 exit(EXIT_SUCCESS);
156
157 out_with_topo2:
158 hwloc_topology_destroy(topo2);
159 out_with_topo1:
160 hwloc_topology_destroy(topo1);
161 exit(EXIT_FAILURE);
162 }
163