Line data Source code
1 : /**
2 : * \file oks_merge.cpp
3 : *
4 : * This file is part of the OKS package.
5 : * https://gitlab.cern.ch/atlas-tdaq-software/oks
6 : *
7 : * This file contains the implementation of the OKS application to merge several data files into a single data files.
8 : */
9 :
10 :
11 : #include "oks/kernel.hpp"
12 :
13 : using namespace dunedaq;
14 : using namespace dunedaq::oks;
15 :
16 : ////////////////////////////////////////////////////////////////////////////////////////////////////
17 :
18 : #include "ers/ers.hpp"
19 :
20 0 : ERS_DECLARE_ISSUE(
21 : oks_merge,
22 : BadCommandLine,
23 : "Bad command line: \"" << what << '\"',
24 : ((const char*)what)
25 : )
26 :
27 0 : ERS_DECLARE_ISSUE(
28 : oks_merge,
29 : BadQuery,
30 : "Failed to parse query \"" << query << "\" in class \"" << class_name << '\"',
31 : ((const char*)query)
32 : ((const char*)class_name)
33 : )
34 :
35 0 : ERS_DECLARE_ISSUE(
36 : oks_merge,
37 : BadClass,
38 : "Cannot find class \"" << class_name << '\"',
39 : ((const char*)class_name)
40 : )
41 :
42 : /** Failed to read OKS database file. */
43 :
44 0 : ERS_DECLARE_ISSUE(
45 : oks_merge,
46 : CaughtException,
47 : "Caught " << what << " exception: \'" << text << '\'',
48 : ((const char *)what)
49 : ((const char *)text)
50 : )
51 :
52 : ////////////////////////////////////////////////////////////////////////////////////////////////////
53 :
54 : std::string appTitle;
55 :
56 0 : void printUsage(const char *appName, std::ostream& s)
57 : {
58 0 : s << appTitle << "\n"
59 : "Usage: " << appName << "\n"
60 : " [--class name-of-class [--query query [--print-references recursion-depth [class-name*] [--]]]\n"
61 : " [--version]\n"
62 : " [--help]\n"
63 : " [--out-data-file data_file] [--out-data-file schema_file] inputfiles*\n"
64 : "\n"
65 : " Options:\n"
66 : " -o | --out-data-file datafilename the out filename to store oks objects from input files\n"
67 : " -s | --out-schema-file schemafilename the out filename to store oks classes from input files\n"
68 : " -c | --class class_name dump given class (all objects or matching some query)\n"
69 : " -q | --query query print objects matching query (can only be used with class)\n"
70 : " -r | --print-references N C1 C2 ... CX print objects referenced by found objects (can only be used with query), where:\n"
71 : " * the parameter N defines recursion depth for referenced objects (> 0)\n"
72 : " * the optional set of names {C1 .. CX} defines [sub-]classes for above objects\n"
73 : " -v | --version print version\n"
74 : " -h | --help print this text\n"
75 : "\n"
76 : " Description:\n"
77 : " Merges several oks files into single schema and data files.\n"
78 0 : "\n";
79 0 : }
80 :
81 : enum __OksMergeExitStatus__ {
82 : __Success__ = 0,
83 : __NoDataFilesLoaded__,
84 : __NoSchemaFilesLoaded__,
85 : __BadCommandLine__,
86 : __NoOutputSchemaFile__,
87 : __BadQuery__,
88 : __NoSuchClass__,
89 : __ExceptionCaught__
90 : };
91 :
92 :
93 : static void
94 0 : no_param(const char * s)
95 : {
96 0 : Oks::error_msg("oks_merge") << "no parameter(s) for command line argument \'" << s << "\' provided\n\n";
97 0 : exit(__BadCommandLine__);
98 : }
99 :
100 : int
101 0 : main(int argc, char *argv[])
102 : {
103 0 : appTitle = "OKS merge. OKS kernel version ";
104 0 : appTitle += OksKernel::GetVersion();
105 :
106 0 : const char * appName = "oks_merge";
107 :
108 0 : std::string out_data_file;
109 0 : std::string out_schema_file;
110 :
111 0 : const char * class_name = nullptr;
112 0 : const char * query = nullptr;
113 0 : long recursion_depth = 0;
114 0 : std::vector<std::string> ref_classes;
115 :
116 :
117 0 : if(argc == 1) {
118 0 : printUsage(appName, std::cerr);
119 : return __BadCommandLine__;
120 : }
121 :
122 0 : OksKernel kernel;
123 0 : kernel.set_use_strict_repository_paths(false);
124 :
125 0 : try {
126 :
127 0 : for(int i = 1; i < argc; i++) {
128 0 : const char * cp = argv[i];
129 :
130 0 : if(!strcmp(cp, "-h") || !strcmp(cp, "--help")) {
131 0 : printUsage(appName, std::cout);
132 : return __Success__;
133 : }
134 0 : else if(!strcmp(cp, "-v") || !strcmp(cp, "--version")) {
135 0 : std::cout << appTitle << std::endl;
136 : return __Success__;
137 : }
138 0 : else if(!strcmp(cp, "-o") || !strcmp(cp, "--out-data-file")) {
139 0 : if(++i == argc) { no_param(cp); } else { out_data_file = argv[i]; }
140 : }
141 0 : else if(!strcmp(cp, "-s") || !strcmp(cp, "--out-schema-file")) {
142 0 : if(++i == argc) { no_param(cp); } else { out_schema_file = argv[i]; }
143 : }
144 0 : else if(!strcmp(cp, "-c") || !strcmp(cp, "--class")) {
145 0 : if(++i == argc) { no_param(cp); } else { class_name = argv[i]; }
146 : }
147 0 : else if(!strcmp(cp, "-q") || !strcmp(cp, "--query")) {
148 0 : if(++i == argc) { no_param(cp); } else { query = argv[i]; }
149 : }
150 0 : else if(!strcmp(cp, "-r") || !strcmp(cp, "--print-references")) {
151 0 : if(++i == argc) { no_param(cp); } else { recursion_depth = atol(argv[i]); }
152 0 : int j = 0;
153 0 : for(; j < argc - i - 1; ++j) {
154 0 : if(argv[i+1+j][0] != '-') { ref_classes.push_back(argv[i+1+j]); } else { break; }
155 : }
156 0 : i += j;
157 0 : }
158 0 : else if(strcmp(cp, "--")) {
159 0 : kernel.load_file(cp);
160 : }
161 : }
162 :
163 0 : if(!out_data_file.empty() && kernel.data_files().empty()) {
164 0 : ers::fatal(oks_merge::BadCommandLine(ERS_HERE,"There were no data files loaded"));
165 0 : return __NoDataFilesLoaded__;
166 : }
167 :
168 0 : if(!out_schema_file.empty() && kernel.schema_files().empty()) {
169 0 : ers::fatal(oks_merge::BadCommandLine(ERS_HERE,"There were no schema files loaded"));
170 0 : return __NoSchemaFilesLoaded__;
171 : }
172 :
173 0 : if(query && !class_name) {
174 0 : ers::fatal(oks_merge::BadCommandLine(ERS_HERE,"Query can only be executed when class name is provided (use -c option)"));
175 0 : return __BadCommandLine__;
176 : }
177 :
178 :
179 0 : OksFile * data_file_h = 0;
180 0 : OksFile * schema_file_h = 0;
181 :
182 0 : if(!out_data_file.empty()) {
183 0 : data_file_h = kernel.new_data(out_data_file);
184 : kernel.set_active_data(data_file_h);
185 : }
186 :
187 0 : if(!out_schema_file.empty()) {
188 0 : schema_file_h = kernel.new_schema(out_schema_file);
189 0 : kernel.set_active_schema(schema_file_h);
190 : }
191 :
192 0 : if(!data_file_h && !schema_file_h) {
193 0 : ers::fatal(oks_merge::BadCommandLine(ERS_HERE,"There is no out schema file name defined"));
194 0 : return __NoOutputSchemaFile__;
195 : }
196 :
197 0 : if(schema_file_h) {
198 0 : for(OksClass::Map::const_iterator j = kernel.classes().begin(); j != kernel.classes().end(); ++j) {
199 0 : j->second->set_file(schema_file_h, false);
200 : }
201 :
202 0 : kernel.save_schema(schema_file_h);
203 : }
204 :
205 0 : if(data_file_h) {
206 0 : if(schema_file_h) {
207 0 : data_file_h->add_include_file(out_schema_file);
208 : }
209 :
210 0 : if(class_name && *class_name) {
211 0 : if(OksClass * c = kernel.find_class(class_name)) {
212 0 : if(query && *query) {
213 0 : OksQuery * q = new OksQuery(c, query);
214 0 : if(q->good()) {
215 0 : OksObject::List * objs = c->execute_query(q);
216 0 : size_t num = (objs ? objs->size() : 0);
217 0 : std::cout << "Found " << num << " matching query \"" << query << "\" in class \"" << class_name << "\"";
218 0 : if(num) {
219 0 : OksObject::FSet refs;
220 0 : std::cout << ':' << std::endl;
221 0 : while(!objs->empty()) {
222 0 : OksObject * o = objs->front();
223 0 : objs->pop_front();
224 0 : if(recursion_depth > 0) {
225 0 : oks::ClassSet all_ref_classes;
226 0 : kernel.get_all_classes(ref_classes, all_ref_classes);
227 0 : o->references(refs, recursion_depth, true, &all_ref_classes);
228 0 : std::cout << " - " << o << " references " << refs.size() << " objects" << std::endl;
229 0 : }
230 : else {
231 0 : refs.insert(o);
232 : }
233 : }
234 0 : delete objs;
235 0 : for(OksObject::FSet::iterator i = refs.begin(); i != refs.end(); ++i) {
236 0 : const_cast<OksObject *>(*i)->set_file(data_file_h, false);
237 : }
238 0 : }
239 : else {
240 0 : std::cout << std::endl;
241 : }
242 : }
243 : else {
244 0 : ers::fatal(oks_merge::BadQuery(ERS_HERE, query, class_name));
245 0 : return __BadQuery__;
246 : }
247 0 : delete q;
248 : }
249 : else {
250 0 : std::cout << *c << std::endl;
251 : }
252 : }
253 : else {
254 0 : ers::fatal(oks_merge::BadClass(ERS_HERE, class_name));
255 0 : return __NoSuchClass__;
256 : }
257 : }
258 : else {
259 0 : for(OksObject::Set::const_iterator j = kernel.objects().begin(); j != kernel.objects().end(); ++j) {
260 0 : (*j)->set_file(data_file_h, false);
261 : }
262 : }
263 :
264 0 : kernel.save_data(data_file_h);
265 : }
266 :
267 : }
268 :
269 0 : catch (oks::exception & ex) {
270 0 : ers::fatal(oks_merge::CaughtException(ERS_HERE, "OKS", ex.what()));
271 0 : return __ExceptionCaught__;
272 0 : }
273 :
274 0 : catch (std::exception & ex) {
275 0 : ers::fatal(oks_merge::CaughtException(ERS_HERE, "Standard C++", ex.what()));
276 0 : return __ExceptionCaught__;
277 0 : }
278 :
279 0 : catch (...) {
280 0 : ers::fatal(oks_merge::CaughtException(ERS_HERE, "unknown", ""));
281 0 : return __ExceptionCaught__;
282 0 : }
283 :
284 : return __Success__;
285 0 : }
|