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