DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
oks_diff_data.cxx
Go to the documentation of this file.
1//
2// DUNE DAQ modification notice:
3// This file has been modified from the original ATLAS oks_utils source for the DUNE DAQ project.
4// Fork baseline commit: c2e7dfc7 (2022-03-30).
5// Renamed since fork: yes (from src/bin/oks_diff_data.cpp to apps/oks_diff_data.cxx).
6//
7
40
41#include <iostream>
42
43#include <set>
44
45#include "oks/attribute.hpp"
46#include "oks/class.hpp"
47#include "oks/kernel.hpp"
48#include "oks/object.hpp"
49#include "oks/relationship.hpp"
50
51using namespace dunedaq;
52using namespace dunedaq::oks;
53
54std::string appTitle;
55
56static void
58{
59 while (level--)
60 std::cout << " ";
61}
62
63static void
64ReportCompositeParents(OksObject* o, int recursionLevel = -1)
65{
66 static std::set<OksRCR*, std::less<OksRCR*>> rcr_set;
67
68 recursionLevel++;
69
70 const std::list<OksRCR*>* rcr_list = o->reverse_composite_rels();
71
72 if (rcr_list) {
73 for (std::list<OksRCR*>::const_iterator i = rcr_list->begin(); i != rcr_list->end(); ++i) {
74 OksRCR* rcr = *i;
75
76 printRecursion(recursionLevel);
77
78 std::cout << " " << rcr->obj << " ==\\" << rcr->relationship->get_name() << "\\==> " << o << std::endl;
79
80 if (!rcr_set.empty() && rcr_set.find(rcr) != rcr_set.end()) {
81 printRecursion(recursionLevel);
82 std::cout << " The composite parent(s) of " << rcr->obj
83 << " were reported in this loop (circular references)\n";
84 } else {
85 rcr_set.insert(rcr);
86 ReportCompositeParents(rcr->obj, recursionLevel);
87 rcr_set.erase(rcr);
88 }
89 }
90 } else {
91 printRecursion(recursionLevel);
92 std::cout << " " << o << " has no composite parents\n";
93 }
94
95 recursionLevel--;
96}
97
98static void
99printShortUsage(const char* appName, std::ostream& s)
100{
101 s << appTitle
102 << "\n"
103 "Usage: "
104 << appName
105 << " [-a] [-r] [-p] [-all] [-h] [-v] [-c class [-o object_id]] "
106 "[-s schema_file(s)] -d1 data_file1 -d2 data_file2\n"
107 "\n"
108 " Options (if two objects differed):\n"
109 "\t-a produce a listing of differences for object's attributes\n"
110 "\t-r produce a listing of differences for object's relationships\n"
111 "\t-p produce a listing of object's composite parents\n"
112 "\t-all the same as \'-a -r -p\'\n"
113 "\n"
114 " General Options/Arguments:\n"
115 "\t-c class-name optional name of class which objects to be checked\n"
116 "\t-o object-id optional id to check only this object (only used with -c)\n"
117 "\t-s schema-file optional list of schema files\n"
118 "\t-d1 data-file first compared datafile\n"
119 "\t-d2 data-file second compared datafile\n"
120 "\t-v print version\n"
121 "\t-b verbose mode\n"
122 "\t-h print this text\n"
123 "\n";
124}
125
126static void
127printUsage(const char* appName, std::ostream& s)
128{
129 s << appTitle
130 << "\n"
131 "Usage: "
132 << appName
133 << " [--attributes] [--relationships] [--composite-parents] [--all] [--help] [--version]"
134 " [--class-name name_of_class [--object-id id_of_object]]\n"
135 " [--schema-files schema_file(s)] --data-file1 data_file1 --data-file2 data_file2\n"
136 "\n"
137 " Options (if two objects differed):\n"
138 "\t--attributes produce a listing of differences for object's attributes\n"
139 "\t--relationships produce a listing of differences for object's relationships\n"
140 "\t--composite-parents produce a listing of object's composite parents\n"
141 "\t-all the same as \'--attributes --relationships --composite-parents\'\n"
142 "\n"
143 " General Options/Arguments:\n"
144 "\t--class-name class-name optional name of class which objects to be checked\n"
145 "\t--object-id object-id optional id to check only this object (only used with --class-name)\n"
146 "\t--schema-files schema-file optional list of schema files\n"
147 "\t--data-file1 data-file first compared datafile\n"
148 "\t--data-file2 data-file second compared datafile\n"
149 "\t--version print version\n"
150 "\t--verbose verbose mode\n"
151 "\t--help print this text\n"
152 "\n";
153}
154
155int
156main(int argc, const char* argv[])
157{
158 appTitle = "OKS data files comparer. OKS kernel version ";
160
161 bool printAttributeDifferences = false;
162 bool printRelationshipDifferences = false;
163 bool printCompositeParentsMode = false;
164 bool verboseMode = false;
165
166 const char* appName = "oks_diff_data";
167
168 if (argc == 1) {
169 printUsage(appName, std::cerr);
170 return 1;
171 }
172
173 // allocate enough space for list of schema files
174
175 const char** schemaFiles = new const char*[argc];
176 schemaFiles[0] = 0;
177
178 const char* dataFile1 = 0;
179 const char* dataFile2 = 0;
180
181 const char* class_name = 0;
182 const char* object_id = 0;
183
184 for (int i = 1; i < argc; i++) {
185 if (!strcmp(argv[i], "-a") || !strcmp(argv[i], "--attributes"))
186 printAttributeDifferences = true;
187 else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--relationships"))
188 printRelationshipDifferences = true;
189 else if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "--composite-parents"))
190 printCompositeParentsMode = true;
191 else if (!strcmp(argv[i], "-all") || !strcmp(argv[i], "--all")) {
192 printAttributeDifferences = true;
193 printRelationshipDifferences = true;
194 printCompositeParentsMode = true;
195 } else if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--verbose"))
196 verboseMode = true;
197 else if (!strcmp(argv[i], "-h")) {
198 printShortUsage(appName, std::cout);
199 return 0;
200 } else if (!strcmp(argv[i], "--help")) {
201 printUsage(appName, std::cout);
202 return 0;
203 } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
204 std::cout << appTitle << std::endl;
205 return 0;
206 } else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--schema-files")) {
207 for (int j = 0; j < argc - i - 1; ++j) {
208 if (argv[i + 1 + j][0] != '-')
209 schemaFiles[j] = argv[i + 1 + j];
210 else {
211 schemaFiles[j] = 0;
212 i += j;
213 break;
214 }
215 }
216 } else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--class-name")) {
217 if (argv[i + 1][0] != '-')
218 class_name = argv[++i];
219 } else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--object-id")) {
220 if (argv[i + 1][0] != '-')
221 object_id = argv[++i];
222 } else if (!strcmp(argv[i], "-d1") || !strcmp(argv[i], "--data-file1")) {
223 if (argv[i + 1][0] != '-')
224 dataFile1 = argv[++i];
225 } else if (!strcmp(argv[i], "-d2") || !strcmp(argv[i], "--data-file2")) {
226 if (argv[i + 1][0] != '-')
227 dataFile2 = argv[++i];
228 } else {
229 std::cerr << "ERROR: Unknown parameter: \"" << argv[i] << "\"\n\n";
230 printUsage(appName, std::cerr);
231 return 1;
232 }
233 }
234
235 // check schema and data files
236
237 if (dataFile1 == 0) {
238 std::cerr << "ERROR: First data file is not defined.\n\n";
239 printUsage(appName, std::cerr);
240 return 1;
241 }
242
243 if (dataFile2 == 0) {
244 std::cerr << "ERROR: Second data file is not defined.\n\n";
245 printUsage(appName, std::cerr);
246 return 1;
247 }
248
249 // check object id and class name
250
251 if (object_id && !class_name) {
252 std::cerr << "ERROR: object ID cannot be used without class name.\n\n";
253 printUsage(appName, std::cerr);
254 return 1;
255 }
256
257 int return_status = 0;
258
259 // create two kernels and load the data
260
261 OksKernel kernel1;
262 OksKernel kernel2;
263
264 try {
265
266 if (!verboseMode) {
267 kernel1.set_silence_mode(true);
268 kernel2.set_silence_mode(true);
269 }
270
271 for (int i = 0; schemaFiles[i] != 0; ++i) {
272 const char* s_file = schemaFiles[i];
273
274 kernel1.load_schema(s_file);
275 kernel2.load_schema(s_file);
276 }
277
278 kernel1.load_data(dataFile1);
279 kernel2.load_data(dataFile2);
280
281 const OksClass::Map& classes = kernel1.classes();
282 OksClass::Map::const_iterator class_iterator = classes.begin();
283
284 if (classes.empty()) {
285 std::cerr << "ERROR: No classes were found in loaded schema file(s), exiting ...\n";
286 return 4;
287 }
288
289 std::cout << std::endl;
290
291 int classDiffsCount = 0;
292
293 OksClass *c1, *c2;
294 for (; class_iterator != classes.end(); ++class_iterator) {
295 c1 = class_iterator->second;
296 std::string className(c1->get_name());
297
298 if (class_name && className != class_name) {
299 continue;
300 }
301
302 if (verboseMode)
303 classDiffsCount = 0;
304
305 if (verboseMode) {
306 std::cout << "TESTING IN CLASS \"" << className << "\"... ";
307 std::cout.flush();
308 }
309
310 if (!(c2 = kernel2.find_class(className))) {
311 if (verboseMode && !classDiffsCount)
312 std::cout << std::endl;
313 std::cout << " DIFFERENCE " << ++classDiffsCount
314 << "."
315 " Database \'"
316 << dataFile2 << "\' does not have class \"" << className << "\", skip testing ...\n";
317 continue;
318 }
319
320 if (*c1 != *c2) {
321 if (verboseMode && !classDiffsCount)
322 std::cout << std::endl;
323 std::cout << " DIFFERENCE " << ++classDiffsCount
324 << "."
325 " Class \""
326 << className << "\" is different in \"" << dataFile1 << "\" and \"" << dataFile2
327 << "\", skip testing ...\n";
328 continue;
329 }
330
331 const OksObject::Map* objects1 = c1->objects();
332 const OksObject::Map* objects2 = c2->objects();
333 OksObject::Map::const_iterator object_iterator = objects1->begin();
334
335 for (; object_iterator != objects1->end(); ++object_iterator) {
336 const std::string* objUID = (*object_iterator).first;
337 OksObject* o1 = (*object_iterator).second;
338
339 if (object_id && o1->GetId() != object_id) {
340 continue;
341 }
342
343 OksObject* o2 = c2->get_object(objUID);
344
345 if (!o2) {
346 if (verboseMode && !classDiffsCount)
347 std::cout << std::endl;
348 std::cout << " DIFFERENCE " << ++classDiffsCount
349 << "."
350 " There is no object "
351 << o1 << " in the \"" << dataFile2 << "\" database file.\n";
352 continue;
353 }
354
355 if (*o1 == *o2)
356 continue;
357
358 if (verboseMode && !classDiffsCount)
359 std::cout << std::endl;
360 std::cout << " DIFFERENCE " << ++classDiffsCount << ". The OBJECTS " << o1 << " differed:\n";
361
362 int objDiffsCount = 0;
363
364 const std::list<OksAttribute*>* alist = c1->all_attributes();
365 const std::list<OksRelationship*>* rlist = c1->all_relationships();
366
367 if (alist) {
368 for (std::list<OksAttribute*>::const_iterator ai = alist->begin(); ai != alist->end(); ++ai) {
369 OksAttribute* a = *ai;
370 OksData* d1(o1->GetAttributeValue(a->get_name()));
371 OksData* d2(o2->GetAttributeValue(a->get_name()));
372
373 if (!(*d1 == *d2)) {
374 ++objDiffsCount;
375
376 if (printAttributeDifferences) {
377 std::cout << " " << classDiffsCount << "." << objDiffsCount << " The ATTRIBUTE \"" << a->get_name()
378 << "\" values differed:\n"
379 " the value in the FILE \""
380 << dataFile1 << "\" is: " << *d1
381 << "\n"
382 " the value in the FILE \""
383 << dataFile2 << "\" is: " << *d2 << std::endl;
384 }
385 }
386 }
387 }
388
389 if (rlist) {
390 for (std::list<OksRelationship*>::const_iterator ri = rlist->begin(); ri != rlist->end(); ++ri) {
391 OksRelationship* r = *ri;
392 OksData* d1(o1->GetRelationshipValue(r->get_name()));
393 OksData* d2(o2->GetRelationshipValue(r->get_name()));
394
395 if (!(*d1 == *d2)) {
396 ++objDiffsCount;
397
398 if (printRelationshipDifferences) {
399 std::cout << " " << classDiffsCount << '.' << objDiffsCount << " The RELATIONSHIP \"" << r->get_name()
400 << "\" values differed:\n"
401 " the value in the FILE \""
402 << dataFile1 << "\" is: " << *d1
403 << "\n"
404 " the value in the FILE \""
405 << dataFile2 << "\" is: " << *d2 << std::endl;
406 }
407 }
408 }
409 }
410
411 if (objDiffsCount && printCompositeParentsMode) {
412 std::cout << " COMPOSITE PARENT(S) of the OBJECTS " << o1 << ":\n";
413 std::cout << " In the FILE \"" << dataFile1 << "\"\n";
415 std::cout << " In the FILE \"" << dataFile2 << "\"\n";
417 }
418 }
419
420 object_iterator = objects2->begin();
421
422 for (; object_iterator != objects2->end(); ++object_iterator) {
423 const std::string* objUID = (*object_iterator).first;
424 OksObject* o1 = c1->get_object(objUID);
425
426 if (!o1 && (!object_id || *objUID == object_id)) {
427 if (!classDiffsCount)
428 std::cout << std::endl;
429 std::cout << " DIFFERENCE " << ++classDiffsCount
430 << "."
431 " There is no object "
432 << (*object_iterator).second << " in the \"" << dataFile1 << "\" database file.\n";
433 }
434 }
435
436 if (verboseMode && !classDiffsCount) {
437 std::cout << " no differences were found\n";
438 }
439 }
440 }
441
442 catch (oks::exception& ex) {
443 std::cerr << "Caught oks exception:\n" << ex << std::endl;
444 return_status = 10;
445 }
446
447 catch (std::exception& e) {
448 std::cerr << "Caught standard C++ exception: " << e.what() << std::endl;
449 return_status = 10;
450 }
451
452 catch (...) {
453 std::cerr << "Caught unknown exception" << std::endl;
454 return_status = 10;
455 }
456
457 delete[] schemaFiles;
458
459 if (verboseMode)
460 std::cout << "\nExiting " << appName << "...\n";
461
462 return return_status;
463}
OKS attribute class.
Definition attribute.hpp:94
const std::string & get_name() const noexcept
out stream operator
The OKS class.
Definition class.hpp:223
const OksObject::Map * objects() const noexcept
Definition class.hpp:762
const std::list< OksAttribute * > * all_attributes() const noexcept
Definition class.hpp:470
const std::string & get_name() const noexcept
Definition class.hpp:374
OksObject * get_object(const std::string &id) const noexcept
Get object by ID.
Definition class.cpp:1479
std::map< const char *, OksClass *, SortStr > Map
Definition class.hpp:252
const std::list< OksRelationship * > * all_relationships() const noexcept
Definition class.hpp:568
Provides interface to the OKS kernel.
Definition kernel.hpp:615
OksFile * load_data(const std::string &name, bool bind=true)
Load OKS data file.
Definition kernel.cpp:3347
const OksClass::Map & classes() const
Get classes.
Definition kernel.hpp:1711
void set_silence_mode(const bool b)
Set status of silence mode. To switch 'On'/'Off' use the method's parameter:
Definition kernel.hpp:730
static const char * GetVersion()
Get OKS version. The method returns string containing CVS tag and date of OKS build.
Definition kernel.cpp:274
OksClass * find_class(const std::string &class_name) const
Find class by name (C++ string).
Definition kernel.hpp:1754
OksFile * load_schema(const std::string &name, const OksFile *parent=0)
Load OKS schema file.
Definition kernel.cpp:2129
OksObject describes instance of OksClass.
Definition object.hpp:1144
const std::list< OksRCR * > * reverse_composite_rels() const
Return information about composite parents. The method returns list of the OKS object's reverse compo...
Definition object.hpp:1589
OksData * GetRelationshipValue(const std::string &) const
Get value of relationship by name.
Definition object.cpp:1944
std::unordered_map< const std::string *, OksObject *, oks::hash_str, oks::equal_str > Map
Definition object.hpp:1170
const std::string & GetId() const
Definition object.hpp:1290
OksData * GetAttributeValue(const std::string &name) const
Get value of attribute by name.
Definition object.cpp:1852
const std::string & get_name() const noexcept
int main(int argc, char *argv[])
The DUNE-DAQ namespace.
static void printUsage(const char *appName, std::ostream &s)
static void ReportCompositeParents(OksObject *o, int recursionLevel=-1)
static void printShortUsage(const char *appName, std::ostream &s)
static void printRecursion(int level)
std::string appTitle
int classDiffsCount
Struct OKS data.
Definition object.hpp:510
The struct OksRCR describes Reverse Composite Relationship (i.e. back reference from child to composi...
Definition object.hpp:1078
const OksRelationship * relationship
Definition object.hpp:1093