Line data Source code
1 : //
2 : // DUNE DAQ modification notice:
3 : // This file has been modified from the original ATLAS config source for the DUNE DAQ project.
4 : // Fork baseline commit: 67a24e731 (2022-10-27).
5 : // Renamed since fork: yes (from bin/config_dump.cpp to apps/config_dump.cxx).
6 : //
7 :
8 : #include <stdlib.h>
9 :
10 : #include <iostream>
11 : #include <string>
12 :
13 : #include <boost/program_options.hpp>
14 :
15 : #include "conffwk/Configuration.hpp"
16 : #include "conffwk/ConfigObject.hpp"
17 : #include "conffwk/Schema.hpp"
18 :
19 : using namespace dunedaq::conffwk;
20 :
21 0 : ERS_DECLARE_ISSUE(
22 : config_dump,
23 : BadCommandLine,
24 : "bad command line: " << reason,
25 : ((const char*)reason)
26 : )
27 :
28 0 : ERS_DECLARE_ISSUE(
29 : config_dump,
30 : ConfigException,
31 : "caught dunedaq::conffwk::Exception exception",
32 : )
33 :
34 : struct SortByName
35 : {
36 : bool
37 0 : operator()(const ConfigObject *o1, const ConfigObject *o2) const
38 : {
39 0 : return o1->UID() < o2->UID();
40 : }
41 : };
42 :
43 : static void
44 0 : print_referenced_by(const ConfigObject &obj, const char *prefix)
45 : {
46 0 : std::vector<ConfigObject> values;
47 0 : obj.referenced_by(values, "*", false, 0, 0);
48 0 : if (values.size() == 0)
49 : {
50 0 : std::cout << prefix << "is not referenced by others objects\n";
51 : }
52 : else
53 : {
54 0 : std::cout << prefix << "is referenced by " << values.size() << " object" << (values.size() == 1 ? "" : "s") << ":\n";
55 0 : for (const auto &iobj : values)
56 0 : std::cout << prefix << " * " << iobj << std::endl;
57 :
58 : }
59 0 : }
60 :
61 : static void
62 0 : print_versions(const std::vector<dunedaq::conffwk::Version>& versions)
63 : {
64 0 : const auto len = versions.size();
65 0 : unsigned int idx = 1;
66 0 : for (const auto& x : versions)
67 : {
68 0 : char buf[50];
69 0 : std::time_t t(x.get_timestamp());
70 0 : std::strftime(buf, 50, "%F %T %Z", std::localtime(&t));
71 0 : std::cout << " * version [" << idx++ << '/' << len << "]\n"
72 0 : " id: " << x.get_id() << "\n"
73 0 : " user: " << x.get_user() << "\n"
74 : " date: " << buf << "\n"
75 0 : " comment: " << x.get_comment() << "\n"
76 0 : " files:\n";
77 :
78 0 : for (const auto& f : x.get_files())
79 0 : std::cout << " - \"" << f << "\"\n";
80 : }
81 0 : }
82 :
83 0 : int main(int argc, char *argv[])
84 : {
85 0 : const std::string any("*");
86 0 : std::string db_name, class_name, object_id, since, until;
87 :
88 0 : bool changes = false;
89 :
90 0 : bool skip_irrelevant = true;
91 0 : dunedaq::conffwk::Version::QueryType query_type = dunedaq::conffwk::Version::query_by_tag;
92 :
93 0 : bool direct_info = false;
94 0 : bool objects_details = false;
95 0 : bool contained_in = false;
96 0 : bool referenced_by = false;
97 :
98 0 : boost::program_options::options_description desc(
99 : "Dumps class and objects descriptions using abstract conffwk API.\n"
100 : "Without -c or -o options, the utility lists all classes.\n"
101 : "\n"
102 0 : "Options/Arguments");
103 :
104 0 : try
105 : {
106 0 : std::vector<std::string> vesrions_str;
107 0 : std::string class_name2;
108 :
109 0 : desc.add_options()
110 0 : (
111 : "database,d",
112 0 : boost::program_options::value<std::string>(&db_name)->required(),
113 : "database specification in format plugin-name:parameters"
114 : )
115 0 : (
116 : "changes,a",
117 : "print details of new repository versions or modified files"
118 : )
119 0 : (
120 : "versions,v",
121 0 : boost::program_options::value<std::vector<std::string>>(&vesrions_str)->multitoken()->zero_tokens(),
122 : "print details of versions from archive providing 4 parameters \"all|skip\" \"date|id|tag\" \"since\" \"until\""
123 : )
124 0 : (
125 : "class-direct-info,c",
126 0 : boost::program_options::value<std::string>(&class_name)->default_value("")->implicit_value(any),
127 : "print direct properties of all classes, or given class if name is provided"
128 : )
129 0 : (
130 : "class-all-info,C",
131 0 : boost::program_options::value<std::string>(&class_name2)->default_value("")->implicit_value(any),
132 : "similar to -c, but prints all properties of class (all attributes, all superclasses, etc.)"
133 : )
134 0 : (
135 : "list-objects,o",
136 : "list objects of class"
137 : )
138 0 : (
139 : "print-referenced-by,r",
140 : "print objects referencing given object (only with -o option)"
141 : )
142 0 : (
143 : "dump-objects,O",
144 0 : boost::program_options::value<std::string>(&object_id)->default_value("")->implicit_value(any),
145 : "dump all objects of class or details of given object, if id is provided (-c is required)"
146 : )
147 0 : (
148 : "show-contained-in,n",
149 : "when dump an object, print out the database file it belongs to"
150 : )
151 0 : (
152 : "help,h",
153 : "print help message"
154 : );
155 :
156 0 : boost::program_options::variables_map vm;
157 0 : boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
158 :
159 0 : if (vm.count("help"))
160 : {
161 0 : std::cout << desc << std::endl;
162 0 : return EXIT_SUCCESS;
163 : }
164 :
165 0 : boost::program_options::notify(vm);
166 :
167 0 : if (!class_name.empty())
168 0 : direct_info = true;
169 :
170 0 : if (!class_name2.empty())
171 : {
172 0 : if (!class_name.empty())
173 0 : throw std::runtime_error("cannot use -c and -C options simultaneously");
174 : else
175 0 : class_name = std::move(class_name2);
176 : }
177 :
178 0 : if (vm.count("changes"))
179 0 : changes = true;
180 :
181 0 : if (!vesrions_str.empty())
182 : {
183 0 : if (vesrions_str.size() != 4)
184 : {
185 0 : throw std::runtime_error("-v option must have 4 parameters, see help");
186 : }
187 : else
188 : {
189 0 : if (vesrions_str[0] == "all")
190 : skip_irrelevant = false;
191 0 : else if (vesrions_str[0] != "skip")
192 0 : throw std::runtime_error("first parameter of -v has to be \"all\" or \"skip\"");
193 :
194 0 : if (vesrions_str[1] == "date")
195 : query_type = dunedaq::conffwk::Version::query_by_date;
196 0 : else if (vesrions_str[1] == "id")
197 : query_type = dunedaq::conffwk::Version::query_by_id;
198 0 : else if (vesrions_str[1] != "tag")
199 0 : throw std::runtime_error("second versions parameter must be \"date\", \"id\" or \"tag\"");
200 :
201 0 : since = vesrions_str[2];
202 0 : until = vesrions_str[3];
203 : }
204 : }
205 :
206 0 : if (!object_id.empty())
207 0 : objects_details = true;
208 :
209 0 : if (vm.count("list-objects"))
210 : {
211 0 : objects_details = false;
212 0 : object_id = any;
213 : }
214 :
215 0 : if (vm.count("print-referenced-by"))
216 0 : referenced_by = true;
217 :
218 0 : if (vm.count("show-contained-in"))
219 0 : contained_in = true;
220 :
221 0 : if (class_name.empty() && !object_id.empty() && object_id != any)
222 0 : throw std::runtime_error("object id is set, but no class name given (use -c option)");
223 0 : }
224 0 : catch (std::exception &ex)
225 : {
226 0 : ers::fatal(config_dump::BadCommandLine(ERS_HERE, ex.what()));
227 0 : return EXIT_FAILURE;
228 0 : }
229 :
230 :
231 0 : try
232 : {
233 0 : Configuration conf(db_name);
234 :
235 : // get versions if any
236 0 : if (changes)
237 : {
238 0 : std::cout << "Changes:\n";
239 0 : print_versions(conf.get_changes());
240 0 : return EXIT_SUCCESS;
241 : }
242 :
243 0 : if (!since.empty())
244 : {
245 0 : std::cout << "Versions:\n";
246 0 : print_versions(conf.get_versions(since, until, query_type, skip_irrelevant));
247 0 : return EXIT_SUCCESS;
248 : }
249 :
250 0 : std::set<std::string> classes;
251 :
252 0 : if (!class_name.empty() && class_name != any)
253 0 : classes.insert(class_name);
254 : else
255 0 : for (const auto &i : conf.superclasses())
256 0 : classes.insert(*i.first);
257 :
258 : // if there are no options, just list classes
259 0 : if (class_name.empty() && object_id.empty())
260 : {
261 0 : std::cout << "The database schema has " << classes.size() << " class(es):\n";
262 0 : for (const auto &i : classes)
263 0 : std::cout << " - \'" << i << "\'\n";
264 0 : return EXIT_SUCCESS;
265 : }
266 :
267 : // only print details of classes
268 0 : if (!class_name.empty() && object_id.empty())
269 : {
270 0 : if (class_name == any)
271 0 : std::cout << "The database schema has " << classes.size() << " class(es):\n";
272 :
273 0 : for (const auto &i : classes)
274 0 : conf.get_class_info(i, direct_info).print(std::cout, " ");
275 :
276 0 : return EXIT_SUCCESS;
277 : }
278 :
279 0 : const char *prefix = "";
280 0 : const char *prefix2 = " ";
281 0 : const char *prefix3 = " ";
282 :
283 : // list or print all objects of class(es)
284 0 : if (object_id == any)
285 : {
286 0 : if (class_name.empty() || class_name == any)
287 : {
288 0 : std::cout << "The database schema has " << classes.size() << " class(es):\n";
289 : prefix = " ";
290 : prefix2 = " ";
291 : prefix3 = " ";
292 : }
293 :
294 0 : for (std::set<std::string>::const_iterator i = classes.begin(); i != classes.end(); ++i)
295 : {
296 0 : std::vector<ConfigObject> objects;
297 0 : conf.get(*i, objects);
298 0 : if (objects.empty())
299 : {
300 0 : std::cout << prefix << "The class \'" << *i << "\' has no objects\n";
301 : }
302 : else
303 : {
304 0 : std::cout << prefix << "The class \'" << *i << "\' has " << objects.size() << " object(s) including sub-classes:\n";
305 :
306 : // sort by ID for consistent output
307 0 : std::set<const ConfigObject*, SortByName> sorted_by_id;
308 :
309 0 : for (const auto &j : objects)
310 0 : sorted_by_id.insert(&j);
311 :
312 0 : for (const auto &j : sorted_by_id)
313 0 : if (j->class_name() == *i)
314 : {
315 0 : if (objects_details)
316 0 : j->print_ref(std::cout, conf, prefix2, contained_in);
317 : else
318 0 : std::cout << prefix << " - \'" << j->UID() << "\'\n";
319 :
320 0 : if (referenced_by)
321 0 : print_referenced_by(*j, prefix3);
322 : }
323 : else
324 : {
325 0 : std::cout << prefix << " - \'" << j->UID() << "\' (database class name = \'" << j->class_name() << "\')\n";
326 : }
327 0 : }
328 0 : }
329 : }
330 : else
331 : {
332 0 : ConfigObject obj;
333 0 : conf.get(class_name, object_id, obj);
334 0 : obj.print_ref(std::cout, conf, "", contained_in);
335 0 : if (referenced_by)
336 0 : print_referenced_by(obj, prefix2);
337 0 : }
338 0 : }
339 0 : catch (dunedaq::conffwk::Exception &ex)
340 : {
341 0 : ers::fatal(config_dump::ConfigException(ERS_HERE, ex));
342 0 : return EXIT_FAILURE;
343 0 : }
344 :
345 0 : return EXIT_SUCCESS;
346 0 : }
|