DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
oks_diff_data.cxx File Reference
#include <iostream>
#include <set>
#include "oks/kernel.hpp"
#include "oks/class.hpp"
#include "oks/object.hpp"
#include "oks/attribute.hpp"
#include "oks/relationship.hpp"
Include dependency graph for oks_diff_data.cxx:

Go to the source code of this file.

Functions

static void printRecursion (int level)
 
static void ReportCompositeParents (OksObject *o, int recursionLevel=-1)
 
static void printShortUsage (const char *appName, std::ostream &s)
 
static void printUsage (const char *appName, std::ostream &s)
 
int main (int argc, const char *argv[])
 

Variables

std::string appTitle
 

Function Documentation

◆ main()

int main ( int argc,
const char * argv[] )

Definition at line 149 of file oks_diff_data.cxx.

150{
151 appTitle = "OKS data files comparer. OKS kernel version ";
153
154 bool printAttributeDifferences = false;
155 bool printRelationshipDifferences = false;
156 bool printCompositeParentsMode = false;
157 bool verboseMode = false;
158
159 const char * appName = "oks_diff_data";
160
161 if(argc == 1) {
162 printUsage(appName, std::cerr);
163 return 1;
164 }
165
166
167 // allocate enough space for list of schema files
168
169 const char ** schemaFiles = new const char * [argc];
170 schemaFiles[0] = 0;
171
172 const char * dataFile1 = 0;
173 const char * dataFile2 = 0;
174
175 const char * class_name = 0;
176 const char * object_id = 0;
177
178 for(int i = 1; i < argc; i++) {
179 if(!strcmp(argv[i], "-a") || !strcmp(argv[i], "--attributes"))
180 printAttributeDifferences = true;
181 else if(!strcmp(argv[i], "-r") || !strcmp(argv[i], "--relationships"))
182 printRelationshipDifferences = true;
183 else if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--composite-parents"))
184 printCompositeParentsMode = true;
185 else if(!strcmp(argv[i], "-all") || !strcmp(argv[i], "--all")) {
186 printAttributeDifferences = true;
187 printRelationshipDifferences = true;
188 printCompositeParentsMode = true;
189 }
190 else if(!strcmp(argv[i], "-b") || !strcmp(argv[i], "--verbose"))
191 verboseMode = true;
192 else if(!strcmp(argv[i], "-h")) {
193 printShortUsage(appName, std::cout);
194 return 0;
195 }
196 else if(!strcmp(argv[i], "--help")) {
197 printUsage(appName, std::cout);
198 return 0;
199 }
200 else if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
201 std::cout << appTitle << std::endl;
202 return 0;
203 }
204 else if(!strcmp(argv[i], "-s") || !strcmp(argv[i], "--schema-files")) {
205 for(int j = 0; j < argc - i - 1; ++j) {
206 if(argv[i+1+j][0] != '-') schemaFiles[j] = argv[i+1+j];
207 else {
208 schemaFiles[j]=0;
209 i+=j;
210 break;
211 }
212 }
213 }
214 else if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--class-name")) {
215 if(argv[i+1][0] != '-') class_name=argv[++i];
216 }
217 else if(!strcmp(argv[i], "-o") || !strcmp(argv[i], "--object-id")) {
218 if(argv[i+1][0] != '-') object_id=argv[++i];
219 }
220 else if(!strcmp(argv[i], "-d1") || !strcmp(argv[i], "--data-file1")) {
221 if(argv[i+1][0] != '-') dataFile1=argv[++i];
222 }
223 else if(!strcmp(argv[i], "-d2") || !strcmp(argv[i], "--data-file2")) {
224 if(argv[i+1][0] != '-') dataFile2=argv[++i];
225 }
226 else {
227 std::cerr << "ERROR: Unknown parameter: \"" << argv[i] << "\"\n\n";
228 printUsage(appName, std::cerr);
229 return 1;
230 }
231 }
232
233
234 // check schema and data files
235
236 if(dataFile1 == 0) {
237 std::cerr << "ERROR: First data file is not defined.\n\n";
238 printUsage(appName, std::cerr);
239 return 1;
240 }
241
242 if(dataFile2 == 0) {
243 std::cerr << "ERROR: Second data file is not defined.\n\n";
244 printUsage(appName, std::cerr);
245 return 1;
246 }
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
258 int return_status = 0;
259
260
261 // create two kernels and load the data
262
263 OksKernel kernel1;
264 OksKernel kernel2;
265
266 try {
267
268 if(!verboseMode) {
269 kernel1.set_silence_mode(true);
270 kernel2.set_silence_mode(true);
271 }
272
273 for(int i=0; schemaFiles[i] != 0; ++i) {
274 const char *s_file = schemaFiles[i];
275
276 kernel1.load_schema(s_file);
277 kernel2.load_schema(s_file);
278 }
279
280 kernel1.load_data(dataFile1);
281 kernel2.load_data(dataFile2);
282
283 const OksClass::Map& classes = kernel1.classes();
284 OksClass::Map::const_iterator class_iterator = classes.begin();
285
286 if(classes.empty()) {
287 std::cerr << "ERROR: No classes were found in loaded schema file(s), exiting ...\n";
288 return 4;
289 }
290
291 std::cout << std::endl;
292
293 int classDiffsCount = 0;
294
295 OksClass *c1, *c2;
296 for(;class_iterator != classes.end(); ++class_iterator) {
297 c1 = class_iterator->second;
298 std::string className(c1->get_name());
299
300 if(class_name && className != class_name) {
301 continue;
302 }
303
304 if(verboseMode) classDiffsCount = 0;
305
306 if(verboseMode) {
307 std::cout << "TESTING IN CLASS \"" << className << "\"... ";
308 std::cout.flush();
309 }
310
311 if(!(c2 = kernel2.find_class(className))) {
312 if(verboseMode && !classDiffsCount) std::cout << std::endl;
313 std::cout << " DIFFERENCE " << ++classDiffsCount << "."
314 " Database \'" << dataFile2 << "\' does not have class \"" << className << "\", skip testing ...\n";
315 continue;
316 }
317
318 if(*c1 != *c2) {
319 if(verboseMode && !classDiffsCount) std::cout << std::endl;
320 std::cout << " DIFFERENCE " << ++classDiffsCount << "."
321 " Class \"" << className << "\" is different in \"" << dataFile1 << "\" and \"" << dataFile2 << "\", skip testing ...\n";
322 continue;
323 }
324
325 const OksObject::Map * objects1 = c1->objects();
326 const OksObject::Map * objects2 = c2->objects();
327 OksObject::Map::const_iterator object_iterator = objects1->begin();
328
329 for(;object_iterator != objects1->end(); ++object_iterator) {
330 const std::string * objUID = (*object_iterator).first;
331 OksObject * o1 = (*object_iterator).second;
332
333 if(object_id && o1->GetId() != object_id) {
334 continue;
335 }
336
337 OksObject * o2 = c2->get_object(objUID);
338
339 if(!o2) {
340 if(verboseMode && !classDiffsCount) std::cout << std::endl;
341 std::cout << " DIFFERENCE " << ++classDiffsCount << "."
342 " There is no object " << o1 << " in the \"" << dataFile2 << "\" database file.\n";
343 continue;
344 }
345
346 if(*o1 == *o2) continue;
347
348 if(verboseMode && !classDiffsCount) std::cout << std::endl;
349 std::cout << " DIFFERENCE " << ++classDiffsCount << ". The OBJECTS " << o1 << " differed:\n";
350
351 int objDiffsCount = 0;
352
353
354 const std::list<OksAttribute *> * alist = c1->all_attributes();
355 const std::list<OksRelationship *> * rlist = c1->all_relationships();
356
357 if(alist) {
358 for(std::list<OksAttribute *>::const_iterator ai = alist->begin(); ai != alist->end(); ++ai) {
359 OksAttribute * a = *ai;
360 OksData * d1(o1->GetAttributeValue(a->get_name()));
361 OksData * d2(o2->GetAttributeValue(a->get_name()));
362
363 if(!(*d1 == *d2)) {
364 ++objDiffsCount;
365
366 if(printAttributeDifferences) {
367 std::cout << " " << classDiffsCount << "." << objDiffsCount
368 << " The ATTRIBUTE \"" << a->get_name() << "\" values differed:\n"
369 " the value in the FILE \"" << dataFile1 << "\" is: " << *d1 << "\n"
370 " the value in the FILE \"" << dataFile2 << "\" is: " << *d2 << std::endl;
371 }
372 }
373 }
374 }
375
376
377 if(rlist) {
378 for(std::list<OksRelationship *>::const_iterator ri = rlist->begin(); ri != rlist->end(); ++ri) {
379 OksRelationship * r = *ri;
380 OksData * d1(o1->GetRelationshipValue(r->get_name()));
381 OksData * d2(o2->GetRelationshipValue(r->get_name()));
382
383 if(!(*d1 == *d2)) {
384 ++objDiffsCount;
385
386 if(printRelationshipDifferences) {
387 std::cout << " " << classDiffsCount << '.' << objDiffsCount
388 << " The RELATIONSHIP \"" << r->get_name() << "\" values differed:\n"
389 " the value in the FILE \"" << dataFile1 << "\" is: " << *d1 << "\n"
390 " the value in the FILE \"" << dataFile2 << "\" is: " << *d2 << std::endl;
391 }
392 }
393 }
394 }
395
396 if(objDiffsCount && printCompositeParentsMode) {
397 std::cout << " COMPOSITE PARENT(S) of the OBJECTS " << o1 << ":\n";
398 std::cout << " In the FILE \"" << dataFile1 << "\"\n"; ReportCompositeParents(o1);
399 std::cout << " In the FILE \"" << dataFile2 << "\"\n"; ReportCompositeParents(o2);
400 }
401 }
402
403
404 object_iterator = objects2->begin();
405
406 for(;object_iterator != objects2->end(); ++object_iterator) {
407 const std::string * objUID = (*object_iterator).first;
408 OksObject * o1 = c1->get_object(objUID);
409
410 if(!o1 && (!object_id || *objUID == object_id)) {
411 if(!classDiffsCount) std::cout << std::endl;
412 std::cout << " DIFFERENCE " << ++classDiffsCount << "."
413 " There is no object " << (*object_iterator).second << " in the \"" << dataFile1 << "\" database file.\n";
414 }
415 }
416
417 if(verboseMode && !classDiffsCount) {
418 std::cout << " no differences were found\n";
419 }
420 }
421 }
422
423 catch (oks::exception & ex) {
424 std::cerr << "Caught oks exception:\n" << ex << std::endl;
425 return_status = 10;
426 }
427
428 catch (std::exception & e) {
429 std::cerr << "Caught standard C++ exception: " << e.what() << std::endl;
430 return_status = 10;
431 }
432
433 catch (...) {
434 std::cerr << "Caught unknown exception" << std::endl;
435 return_status = 10;
436 }
437
438 delete [] schemaFiles;
439
440 if(verboseMode)
441 std::cout << "\nExiting " << appName << "...\n";
442
443 return return_status;
444}
OKS attribute class.
const std::string & get_name() const noexcept
out stream operator
The OKS class.
Definition class.hpp:200
const OksObject::Map * objects() const noexcept
Definition class.hpp:804
const std::list< OksAttribute * > * all_attributes() const noexcept
Definition class.hpp:475
const std::string & get_name() const noexcept
Definition class.hpp:363
OksObject * get_object(const std::string &id) const noexcept
Get object by ID.
Definition class.cpp:1521
std::map< const char *, OksClass *, SortStr > Map
Definition class.hpp:233
const std::list< OksRelationship * > * all_relationships() const noexcept
Definition class.hpp:585
Provides interface to the OKS kernel.
Definition kernel.hpp:577
OksFile * load_data(const std::string &name, bool bind=true)
Load OKS data file.
Definition kernel.cpp:3559
const OksClass::Map & classes() const
Get classes.
Definition kernel.hpp:1767
void set_silence_mode(const bool b)
Set status of silence mode. To switch 'On'/'Off' use the method's parameter:
Definition kernel.hpp:698
static const char * GetVersion()
Get OKS version. The method returns string containing CVS tag and date of OKS build.
Definition kernel.cpp:297
OksClass * find_class(const std::string &class_name) const
Find class by name (C++ string).
Definition kernel.hpp:1814
OksFile * load_schema(const std::string &name, const OksFile *parent=0)
Load OKS schema file.
Definition kernel.cpp:2297
OksObject describes instance of OksClass.
Definition object.hpp:836
std::unordered_map< const std::string *, OksObject *, oks::hash_str, oks::equal_str > Map
Definition object.hpp:865
OksData * GetRelationshipValue(const std::string &) const
Get value of relationship by name.
Definition object.cpp:2004
const std::string & GetId() const
Definition object.hpp:995
OksData * GetAttributeValue(const std::string &name) const
Get value of attribute by name.
Definition object.cpp:1919
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)
std::string appTitle
int classDiffsCount
the structure to pass common parameters to various read() methods of OksData and OksObject class
Definition object.hpp:449

◆ printRecursion()

static void printRecursion ( int level)
static

Definition at line 52 of file oks_diff_data.cxx.

53{
54 while(level--) std::cout << " ";
55}

◆ printShortUsage()

static void printShortUsage ( const char * appName,
std::ostream & s )
static

Definition at line 96 of file oks_diff_data.cxx.

97{
98 s << appTitle << "\n"
99 "Usage: " << appName << " [-a] [-r] [-p] [-all] [-h] [-v] [-c class [-o object_id]] "
100 "[-s schema_file(s)] -d1 data_file1 -d2 data_file2\n"
101 "\n"
102 " Options (if two objects differed):\n"
103 "\t-a produce a listing of differences for object's attributes\n"
104 "\t-r produce a listing of differences for object's relationships\n"
105 "\t-p produce a listing of object's composite parents\n"
106 "\t-all the same as \'-a -r -p\'\n"
107 "\n"
108 " General Options/Arguments:\n"
109 "\t-c class-name optional name of class which objects to be checked\n"
110 "\t-o object-id optional id to check only this object (only used with -c)\n"
111 "\t-s schema-file optional list of schema files\n"
112 "\t-d1 data-file first compared datafile\n"
113 "\t-d2 data-file second compared datafile\n"
114 "\t-v print version\n"
115 "\t-b verbose mode\n"
116 "\t-h print this text\n"
117 "\n";
118}

◆ printUsage()

static void printUsage ( const char * appName,
std::ostream & s )
static

Definition at line 122 of file oks_diff_data.cxx.

123{
124 s << appTitle << "\n"
125 "Usage: " << appName << " [--attributes] [--relationships] [--composite-parents] [--all] [--help] [--version]"
126 " [--class-name name_of_class [--object-id id_of_object]]\n"
127 " [--schema-files schema_file(s)] --data-file1 data_file1 --data-file2 data_file2\n"
128 "\n"
129 " Options (if two objects differed):\n"
130 "\t--attributes produce a listing of differences for object's attributes\n"
131 "\t--relationships produce a listing of differences for object's relationships\n"
132 "\t--composite-parents produce a listing of object's composite parents\n"
133 "\t-all the same as \'--attributes --relationships --composite-parents\'\n"
134 "\n"
135 " General Options/Arguments:\n"
136 "\t--class-name class-name optional name of class which objects to be checked\n"
137 "\t--object-id object-id optional id to check only this object (only used with --class-name)\n"
138 "\t--schema-files schema-file optional list of schema files\n"
139 "\t--data-file1 data-file first compared datafile\n"
140 "\t--data-file2 data-file second compared datafile\n"
141 "\t--version print version\n"
142 "\t--verbose verbose mode\n"
143 "\t--help print this text\n"
144 "\n";
145}

◆ ReportCompositeParents()

static void ReportCompositeParents ( OksObject * o,
int recursionLevel = -1 )
static

Definition at line 58 of file oks_diff_data.cxx.

59{
60 static std::set<OksRCR *, std::less<OksRCR *> > rcr_set;
61
62 recursionLevel++;
63
64 const std::list<OksRCR *> * rcr_list = o->reverse_composite_rels();
65
66 if(rcr_list) {
67 for(std::list<OksRCR *>::const_iterator i = rcr_list->begin(); i != rcr_list->end(); ++i) {
68 OksRCR *rcr = *i;
69
70 printRecursion(recursionLevel);
71
72 std::cout << " " << rcr->obj << " ==\\" << rcr->relationship->get_name()
73 << "\\==> " << o << std::endl;
74
75 if(!rcr_set.empty() && rcr_set.find(rcr) != rcr_set.end()) {
76 printRecursion(recursionLevel);
77 std::cout << " The composite parent(s) of " << rcr->obj
78 << " were reported in this loop (circular references)\n";
79 }
80 else {
81 rcr_set.insert(rcr);
82 ReportCompositeParents(rcr->obj, recursionLevel);
83 rcr_set.erase(rcr);
84 }
85 }
86 }
87 else {
88 printRecursion(recursionLevel);
89 std::cout << " " << o << " has no composite parents\n";
90 }
91
92 recursionLevel--;
93}
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:1310
const std::string & get_name() const noexcept
static void printRecursion(int level)
The struct OksRCR describes Reverse Composite Relationship (i.e. back reference from child to composi...
Definition object.hpp:762
OksObject * obj
Definition object.hpp:773
const OksRelationship * relationship
Definition object.hpp:774

Variable Documentation

◆ appTitle

std::string appTitle

Definition at line 48 of file oks_diff_data.cxx.