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