6 #include "boost/program_options.hpp" 11 #include "cetlib/canonical_string.h" 12 #include "cetlib/container_algorithms.h" 33 namespace bpo = boost::program_options;
38 using std::back_inserter;
57 if (value[0] ==
'[' || value[0] ==
'{' ||
58 cet::is_double_quoted_string(value)) {
67 char const* entval = value.c_str();
68 char* endptr =
const_cast<char*
>(entval);
69 strtold(entval, &endptr);
70 if (endptr == entval + value.size()) {
74 cet::canonical_string(value, result);
88 constexpr
size_t maxIDdigits = 5;
89 constexpr
size_t maxNameSpacing = 20;
92 int id =
static_cast<int>(ent.
SMDid);
93 size_t maxIDspace =
std::min(idLen, maxIDdigits);
94 int nspaces = maxIDspace - 1;
95 for (
int i = 0; (nspaces > 0) && (
id > 0); ++i) {
100 for (
int i = 0; i < nspaces; ++i)
102 output << ent.
SMDid <<
": ";
107 size_t nameSpacing = maxNameSpacing;
108 if (longestName < maxNameSpacing)
109 nameSpacing = longestName;
110 nspaces =
static_cast<int>(nameSpacing - name.size());
111 while (nspaces > 0) {
122 vector<FileCatalogMetadataEntry>
const& entries,
129 size_t longestName = 1;
130 for (
size_t i = 0; i < entries.size(); ++i) {
131 if (entries[i].
SMDid > maxID)
132 maxID = entries[i].SMDid;
133 if (entries[i].
name.size() > longestName)
134 longestName = entries[i].
name.size();
137 for (
int i = 0; (i < 5) && (maxID > 0); ++i) {
142 for (
auto const& entry : entries) {
152 output << cet::canonical_string(ent.
name) <<
": ";
159 vector<FileCatalogMetadataEntry>
const& entries,
163 std::ostringstream buf;
165 for (
auto const& entry : entries) {
170 buf.seekp(-2, std::ios_base::cur);
181 vector<FileCatalogMetadataEntry>& all_metadata_entries,
188 sqlite3_stmt* stmt = 0;
189 sqlite3_prepare_v2(sqliteDB,
190 "SELECT rowid, Name, Value from FileCatalog_metadata;",
194 bool row_found =
false;
195 int sqlite_status = SQLITE_OK;
196 while ((sqlite_status = sqlite3_step(stmt)) == SQLITE_ROW) {
198 ent.
SMDid = sqlite3_column_int(stmt, 0);
200 std::string{
reinterpret_cast<char const*
>(sqlite3_column_text(stmt, 1))};
202 std::string{
reinterpret_cast<char const*
>(sqlite3_column_text(stmt, 2))};
203 all_metadata_entries.push_back(ent);
205 if (sqlite_status != SQLITE_DONE) {
206 errors <<
"Unexpected status from table read: " << sqlite3_errmsg(sqliteDB)
207 <<
" (0x" << sqlite_status <<
").\n";
209 int const finalize_status = sqlite3_finalize(stmt);
210 if (finalize_status != SQLITE_OK) {
211 errors <<
"Unexpected status from DB status cleanup: " 212 << sqlite3_errmsg(sqliteDB) <<
" (0x" << finalize_status <<
").\n";
216 <<
"No file catalog Metadata rows found - table is missing or empty\n";
238 vector<FileCatalogMetadataEntry> all_metadata_entries;
240 errors <<
"Unable to to read metadata entries.\n";
245 std::string
const& path = file.GetName();
246 std::string
const& baseName = path.substr(path.find_last_of(
"/") + 1u);
247 output << cet::canonical_string(baseName) <<
": ";
250 output <<
"\nFile catalog metadata from file " << file.GetName() <<
":\n\n";
252 output <<
"-------------------------------\n";
267 bool const want_json)
271 bool printed_opening{
false};
272 for (
auto const& fn : file_names) {
273 std::unique_ptr<TFile> current_file(TFile::Open(fn.c_str(),
"READ"));
274 if (!current_file || current_file->IsZombie()) {
276 errors <<
"Unable to open file '" << fn <<
"' for reading." 277 <<
"\nSkipping file.\n";
281 auto* key_ptr = current_file->GetKey(
"RootFileDB");
282 if (key_ptr ==
nullptr) {
284 errors <<
"\nRequested DB, \"RootFileDB\" of type, \"tkeyvfs\", not " 285 "present in file: \"" 287 <<
"Either this is not an art/ROOT file, it is a corrupt art/ROOT " 289 <<
"or it is an art/ROOT file produced with a version older than " 298 printed_opening =
true;
300 }
else if (want_json) {
305 if (printed_opening) {
315 if (level == kWarning && (!die) && strcmp(location,
"TClass::TClass") == 0 &&
316 std::string(message).find(
"no dictionary") != std::string::npos) {
320 DefaultErrorHandler(level, die, location, message);
330 std::ostringstream descstr;
331 descstr << argv[0] <<
" <options> [<source-file>]+";
332 bpo::options_description desc(descstr.str());
333 desc.add_options()(
"help,h",
"produce help message")(
334 "hr,H",
"produce human-readable output (default is JSON)")(
335 "human-readable",
"produce human-readable output (default is JSON)")(
336 "source,s", bpo::value<stringvec>(),
"source data file (multiple OK)");
337 bpo::options_description all_opts(
"All Options");
341 bpo::positional_options_description pd;
342 pd.add(
"source", -1);
344 bpo::variables_map vm;
346 bpo::store(bpo::command_line_parser(argc, argv)
354 std::cerr <<
"Exception from command line processing in " << argv[0] <<
": " 358 if (vm.count(
"help")) {
359 std::cout << desc << std::endl;
362 bool const want_json =
363 (!vm.count(
"hr")) && (!vm.count(
"human-readable"));
367 size_t const file_count = vm.count(
"source");
368 if (file_count < 1) {
369 cerr <<
"One or more input files must be specified;" 370 <<
" supply filenames as program arguments\n" 371 <<
"For usage and options list, please do 'sam_metadata_dumper " 375 file_names.reserve(file_count);
376 cet::copy_all(vm[
"source"].as<stringvec>(), std::back_inserter(file_names));
std::vector< std::string > stringvec
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
std::map< fhicl::ParameterSetID, ParameterSetBlob > ParameterSetMap