LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
sam_metadata_dumper.cc File Reference
#include "art/Framework/IO/Root/GetFileFormatEra.h"
#include "art/Framework/IO/Root/RootDB/SQLite3Wrapper.h"
#include "art/Framework/IO/Root/RootDB/tkeyvfs.h"
#include "boost/program_options.hpp"
#include "canvas/Persistency/Provenance/FileFormatVersion.h"
#include "canvas/Persistency/Provenance/ParameterSetBlob.h"
#include "canvas/Persistency/Provenance/ParameterSetMap.h"
#include "canvas/Persistency/Provenance/rootNames.h"
#include "cetlib/canonical_string.h"
#include "cetlib/container_algorithms.h"
#include "fhiclcpp/ParameterSet.h"
#include "fhiclcpp/make_ParameterSet.h"
#include "TError.h"
#include "TFile.h"
#include "sqlite3.h"
#include <algorithm>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <ostream>
#include <sstream>
#include <string>
#include <vector>

Go to the source code of this file.

Classes

struct  FileCatalogMetadataEntry
 

Typedefs

typedef vector< string > stringvec
 

Functions

std::string entryValue (std::string const &value)
 
void print_one_fc_metadata_entry_hr (FileCatalogMetadataEntry const &ent, size_t idLen, size_t longestName, ostream &output)
 
void print_all_fc_metadata_entries_hr (vector< FileCatalogMetadataEntry > const &entries, ostream &output, ostream &)
 
void print_one_fc_metadata_entry_JSON (FileCatalogMetadataEntry const &ent, ostream &output)
 
void print_all_fc_metadata_entries_JSON (vector< FileCatalogMetadataEntry > const &entries, ostream &output, ostream &)
 
bool read_all_fc_metadata_entries (TFile &file, vector< FileCatalogMetadataEntry > &all_metadata_entries, ostream &errors)
 
int print_fc_metadata_from_file (TFile &file, ostream &output, ostream &errors, bool want_json)
 
int print_fc_metadata_from_files (stringvec const &file_names, ostream &output, ostream &errors, bool const want_json)
 
void RootErrorHandler (int level, bool die, char const *location, char const *message)
 
int main (int argc, char *argv[])
 

Typedef Documentation

typedef vector<string> stringvec

Definition at line 46 of file sam_metadata_dumper.cc.

Function Documentation

std::string entryValue ( std::string const &  value)

Definition at line 54 of file sam_metadata_dumper.cc.

References FileCatalogMetadataEntry::value.

Referenced by print_one_fc_metadata_entry_hr(), and print_one_fc_metadata_entry_JSON().

55 {
56  std::string result;
57  if (value[0] == '[' || value[0] == '{' ||
58  cet::is_double_quoted_string(value)) {
59  // Assume entry is already a legal JSON representation.
60  result = value;
61  } else {
62  // Attempt to convert to number. If this works, we don't
63  // canonicalize the string. Note that we use the glibc version
64  // because we don't want to have to catch the exception. We could
65  // use streams, but we don't care about the result and dealing with
66  // streams is awkward.
67  char const* entval = value.c_str();
68  char* endptr = const_cast<char*>(entval);
69  strtold(entval, &endptr);
70  if (endptr == entval + value.size()) {
71  // Full conversion: no string canonicalization necessary.
72  result = value;
73  } else {
74  cet::canonical_string(value, result);
75  }
76  }
77  return result;
78 }
std::string value(boost::any const &)
int main ( int  argc,
char *  argv[] 
)

Definition at line 325 of file sam_metadata_dumper.cc.

References e, print_fc_metadata_from_files(), RootErrorHandler(), and tkeyvfs_init().

326 {
327  // ------------------
328  // use the boost command line option processing library to help out
329  // with command line options
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");
338  all_opts.add(desc);
339  // Each non-option argument is interpreted as the name of a files to
340  // be processed. Any number of filenames is allowed.
341  bpo::positional_options_description pd;
342  pd.add("source", -1);
343  // The variables_map contains the actual program options.
344  bpo::variables_map vm;
345  try {
346  bpo::store(bpo::command_line_parser(argc, argv)
347  .options(all_opts)
348  .positional(pd)
349  .run(),
350  vm);
351  bpo::notify(vm);
352  }
353  catch (bpo::error const& e) {
354  std::cerr << "Exception from command line processing in " << argv[0] << ": "
355  << e.what() << "\n";
356  return 2;
357  }
358  if (vm.count("help")) {
359  std::cout << desc << std::endl;
360  return 1;
361  }
362  bool const want_json =
363  (!vm.count("hr")) && (!vm.count("human-readable")); // Default is JSON.
364 
365  // Get the names of the files we will process.
366  stringvec file_names;
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 "
372  "--help'.\n";
373  return 3;
374  }
375  file_names.reserve(file_count);
376  cet::copy_all(vm["source"].as<stringvec>(), std::back_inserter(file_names));
377 
378  // Set the ROOT error handler.
379  SetErrorHandler(RootErrorHandler);
380 
381  // Register the tkey VFS with sqlite:
382  tkeyvfs_init();
383 
384  // Do the work.
385  return print_fc_metadata_from_files(file_names, cout, cerr, want_json);
386 }
void RootErrorHandler(int level, bool die, char const *location, char const *message)
std::vector< std::string > stringvec
int tkeyvfs_init(void)
Definition: tkeyvfs.cc:1768
int print_fc_metadata_from_files(stringvec const &file_names, ostream &output, ostream &errors, bool const want_json)
Float_t e
Definition: plot.C:34
void print_all_fc_metadata_entries_hr ( vector< FileCatalogMetadataEntry > const &  entries,
ostream &  output,
ostream &   
)

Definition at line 121 of file sam_metadata_dumper.cc.

References FileCatalogMetadataEntry::name, print_one_fc_metadata_entry_hr(), and FileCatalogMetadataEntry::SMDid.

Referenced by print_fc_metadata_from_file().

125 {
126  // For nice formatting, determine maximum id length and name size,
127  // so that values can be lined up.
128  int maxID = 1;
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();
135  }
136  size_t idLen = 1;
137  for (int i = 0; (i < 5) && (maxID > 0); ++i) {
138  maxID /= 10;
139  if (maxID > 0)
140  ++idLen;
141  }
142  for (auto const& entry : entries) {
143  print_one_fc_metadata_entry_hr(entry, idLen, longestName, output);
144  }
145 }
void print_one_fc_metadata_entry_hr(FileCatalogMetadataEntry const &ent, size_t idLen, size_t longestName, ostream &output)
void print_all_fc_metadata_entries_JSON ( vector< FileCatalogMetadataEntry > const &  entries,
ostream &  output,
ostream &   
)

Definition at line 158 of file sam_metadata_dumper.cc.

References print_one_fc_metadata_entry_JSON().

Referenced by print_fc_metadata_from_file().

162 {
163  std::ostringstream buf; // Need seekp to work.
164  buf << "{\n";
165  for (auto const& entry : entries) {
166  buf << " "; // Indent.
168  buf << ",\n";
169  }
170  buf.seekp(-2, std::ios_base::cur);
171  buf << "\n }";
172  output << buf.str();
173 }
void print_one_fc_metadata_entry_JSON(FileCatalogMetadataEntry const &ent, ostream &output)
int print_fc_metadata_from_file ( TFile &  file,
ostream &  output,
ostream &  errors,
bool  want_json 
)

Definition at line 233 of file sam_metadata_dumper.cc.

References print_all_fc_metadata_entries_hr(), print_all_fc_metadata_entries_JSON(), and read_all_fc_metadata_entries().

Referenced by print_fc_metadata_from_files().

237 {
238  vector<FileCatalogMetadataEntry> all_metadata_entries;
239  if (!read_all_fc_metadata_entries(file, all_metadata_entries, errors)) {
240  errors << "Unable to to read metadata entries.\n";
241  return 1;
242  }
243  // Iterate through all the entries, printing each one.
244  if (want_json) {
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) << ": ";
248  print_all_fc_metadata_entries_JSON(all_metadata_entries, output, errors);
249  } else { // Human-readable.
250  output << "\nFile catalog metadata from file " << file.GetName() << ":\n\n";
251  print_all_fc_metadata_entries_hr(all_metadata_entries, output, errors);
252  output << "-------------------------------\n";
253  }
254  return 0;
255 }
bool read_all_fc_metadata_entries(TFile &file, vector< FileCatalogMetadataEntry > &all_metadata_entries, ostream &errors)
void print_all_fc_metadata_entries_JSON(vector< FileCatalogMetadataEntry > const &entries, ostream &output, ostream &)
TFile * file
void print_all_fc_metadata_entries_hr(vector< FileCatalogMetadataEntry > const &entries, ostream &output, ostream &)
int print_fc_metadata_from_files ( stringvec const &  file_names,
ostream &  output,
ostream &  errors,
bool const  want_json 
)

Definition at line 264 of file sam_metadata_dumper.cc.

References print_fc_metadata_from_file().

Referenced by main().

268 {
269  int rc{0};
270  bool first{true};
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()) {
275  ++rc;
276  errors << "Unable to open file '" << fn << "' for reading."
277  << "\nSkipping file.\n";
278  continue;
279  }
280 
281  auto* key_ptr = current_file->GetKey("RootFileDB");
282  if (key_ptr == nullptr) {
283  ++rc;
284  errors << "\nRequested DB, \"RootFileDB\" of type, \"tkeyvfs\", not "
285  "present in file: \""
286  << fn << "\"\n"
287  << "Either this is not an art/ROOT file, it is a corrupt art/ROOT "
288  "file,\n"
289  << "or it is an art/ROOT file produced with a version older than "
290  "v1_00_12.\n";
291  continue;
292  }
293 
294  if (first) {
295  first = false;
296  if (want_json) {
297  output << "{\n ";
298  printed_opening = true;
299  }
300  } else if (want_json) {
301  output << ",\n ";
302  }
303  rc += print_fc_metadata_from_file(*current_file, output, errors, want_json);
304  }
305  if (printed_opening) {
306  output << "\n}\n";
307  }
308  return rc;
309 }
int print_fc_metadata_from_file(TFile &file, ostream &output, ostream &errors, bool want_json)
void print_one_fc_metadata_entry_hr ( FileCatalogMetadataEntry const &  ent,
size_t  idLen,
size_t  longestName,
ostream &  output 
)

Definition at line 82 of file sam_metadata_dumper.cc.

References entryValue(), min, FileCatalogMetadataEntry::name, FileCatalogMetadataEntry::SMDid, and FileCatalogMetadataEntry::value.

Referenced by print_all_fc_metadata_entries_hr().

86 {
87  const std::string& name = ent.name;
88  constexpr size_t maxIDdigits = 5;
89  constexpr size_t maxNameSpacing = 20;
90 
91  // right-justify SMDid (unless it is more than 5 digits)
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) {
96  id /= 10;
97  if (id > 0)
98  --nspaces;
99  }
100  for (int i = 0; i < nspaces; ++i)
101  output << " ";
102  output << ent.SMDid << ": ";
103 
104  output << name;
105 
106  // right-justify value (unless name is more than 20 characters)
107  size_t nameSpacing = maxNameSpacing;
108  if (longestName < maxNameSpacing)
109  nameSpacing = longestName;
110  nspaces = static_cast<int>(nameSpacing - name.size());
111  while (nspaces > 0) {
112  output << " ";
113  --nspaces;
114  }
115 
116  output << " " << entryValue(ent.value) << "\n";
117 }
std::string entryValue(std::string const &value)
Int_t min
Definition: plot.C:26
void print_one_fc_metadata_entry_JSON ( FileCatalogMetadataEntry const &  ent,
ostream &  output 
)

Definition at line 149 of file sam_metadata_dumper.cc.

References entryValue(), FileCatalogMetadataEntry::name, and FileCatalogMetadataEntry::value.

Referenced by print_all_fc_metadata_entries_JSON().

151 {
152  output << cet::canonical_string(ent.name) << ": ";
153 
154  output << entryValue(ent.value);
155 }
std::string entryValue(std::string const &value)
bool read_all_fc_metadata_entries ( TFile &  file,
vector< FileCatalogMetadataEntry > &  all_metadata_entries,
ostream &  errors 
)

Definition at line 179 of file sam_metadata_dumper.cc.

References file, FileCatalogMetadataEntry::name, FileCatalogMetadataEntry::SMDid, and FileCatalogMetadataEntry::value.

Referenced by print_fc_metadata_from_file().

183 {
185  // Open the DB
186  art::SQLite3Wrapper sqliteDB{&file, "RootFileDB"};
187  // Read the entries into memory.
188  sqlite3_stmt* stmt = 0;
189  sqlite3_prepare_v2(sqliteDB,
190  "SELECT rowid, Name, Value from FileCatalog_metadata;",
191  -1,
192  &stmt,
193  nullptr);
194  bool row_found = false;
195  int sqlite_status = SQLITE_OK;
196  while ((sqlite_status = sqlite3_step(stmt)) == SQLITE_ROW) {
197  row_found = true;
198  ent.SMDid = sqlite3_column_int(stmt, 0);
199  ent.name =
200  std::string{reinterpret_cast<char const*>(sqlite3_column_text(stmt, 1))};
201  ent.value =
202  std::string{reinterpret_cast<char const*>(sqlite3_column_text(stmt, 2))};
203  all_metadata_entries.push_back(ent);
204  }
205  if (sqlite_status != SQLITE_DONE) {
206  errors << "Unexpected status from table read: " << sqlite3_errmsg(sqliteDB)
207  << " (0x" << sqlite_status << ").\n";
208  }
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";
213  }
214  if (!row_found) {
215  errors
216  << "No file catalog Metadata rows found - table is missing or empty\n";
217  return false;
218  }
219  return true;
220 }
TFile * file
void RootErrorHandler ( int  level,
bool  die,
char const *  location,
char const *  message 
)

Definition at line 312 of file sam_metadata_dumper.cc.

Referenced by main(), and art::setRootErrorHandler().

313 {
314  // Ignore dictionary errors.
315  if (level == kWarning && (!die) && strcmp(location, "TClass::TClass") == 0 &&
316  std::string(message).find("no dictionary") != std::string::npos) {
317  return;
318  } else {
319  // Default behavior
320  DefaultErrorHandler(level, die, location, message);
321  }
322 }