FileCatalogMetadata.h
Go to the documentation of this file.
1 #ifndef art_Framework_Services_System_FileCatalogMetadata_h
2 #define art_Framework_Services_System_FileCatalogMetadata_h
3 
4 // ======================================================================
5 // FileCatalogMetadata
6 //
7 // Multi-threading considerations:
8 //
9 // This service is intended to be used by users via a ServiceHandle,
10 // which can be created at any point during job execution. The
11 // interface exposed to the user allows both the insertion AND
12 // extraction of metadata. To ensure well-defined behavior for
13 // attempts to concurrently insert and retrieve, the relevant
14 // functions must be guarded with locks.
15 //
16 // For this class, we use a simple std::mutex, ensuring that member
17 // functions calling other member functions do not create a deadlock.
18 
25 #include "fhiclcpp/types/Atom.h"
28 
29 #include <mutex>
30 #include <string>
31 #include <unordered_map>
32 #include <vector>
33 
34 namespace art {
35  class FileCatalogMetadata;
36  class ActivityRegistry;
37 }
38 
40 public:
41  using collection_type = std::vector<std::pair<std::string, std::string>>;
42  using value_type = typename collection_type::value_type;
43 
44  struct Config {
45  fhicl::Atom<bool> checkSyntax{fhicl::Name("checkSyntax"), false};
47  fhicl::Name("applicationFamily")};
49  fhicl::Name("applicationVersion")};
52 
54  fhicl::Name("metadataFromInput"),
56  "This list specifies the metadata that is inherited\n"
57  "from the input file. Currently only the run type and\n"
58  "file type metadata can be inherited. The default list is empty."),
59  std::vector<std::string>{}};
60 
61  bool
63  {
64  return cet::search_all(metadataFromInput(), name);
65  }
66 
68  fhicl::Name("fileType"),
69  fhicl::Comment("Can specify 'fileType' only if it is not specified\n"
70  "in the 'metadataFromInput' list."),
71  [this] { return !inMetadataList("fileType"); },
72  "unknown"};
73 
75  fhicl::Name("runType"),
76  fhicl::Comment("Can specify 'runType' only if it is not specified\n"
77  "in the 'metadataFromInput' list."),
78  [this] { return !inMetadataList("runType"); }};
79  };
80 
82  explicit FileCatalogMetadata(Parameters const& config);
83 
84  // Add a new value to the metadata store.
85  void addMetadata(std::string const& key, std::string const& value);
86  // Ensure the value is a canonical string representation.
87  void addMetadataString(std::string const& key, std::string const& value);
88 
89  void getMetadata(collection_type& coll)
90  const; // Dump stored metadata into the provided container.
91 
92  // RootInput can set the run-type and file-type parameters
93  void setMetadataFromInput(collection_type const& coll);
94 
95  // Ascertain whether JSON syntax checking is desired.
96  bool
98  {
99  return checkSyntax_;
100  }
101 
102 private:
103  bool const checkSyntax_;
105 
107  public:
108  InheritedMetadata(std::vector<std::string> const& sortedMdToInherit,
109  collection_type const& coll)
110  {
111  NewToOld const translator;
112  for (auto const& pr : coll) {
113  if (cet::search_all(sortedMdToInherit, translator(pr.first))) {
114  inputmd_.insert(pr);
115  orderedmd_.emplace_back(pr);
116  }
117  }
118  }
119 
120  auto const&
121  entries() const
122  {
123  return orderedmd_;
124  }
125 
126  void
127  check_values(collection_type const& fromInput) const
128  {
129  for (auto const& pr : fromInput) {
130  auto it = inputmd_.find(pr.first);
131  if (it == cend(inputmd_)) {
133  << "Metadata key " << pr.first
134  << " missing from list of metadata to inherit from input files.\n";
135  } else if (it->second != pr.second) {
137  << "The value for '" << pr.first
138  << "' for the current file is: " << pr.second
139  << ", which conflicts with the value from the first input file (\""
140  << it->second << "\").\n";
141  }
142  }
143  }
144 
145  private:
147  std::unordered_map<std::string, std::string> inputmd_;
148  };
149 
150  std::unique_ptr<InheritedMetadata> imd_{};
151  std::vector<std::string> mdToInherit_;
152 
153  // To lock via a static mutex, we must wrap it in an inline function
154  // so it can be used in contexts where users don't link against the
155  // library associated with this class.
156  static std::mutex&
158  {
159  static std::mutex m;
160  return m;
161  };
162 };
163 
164 inline void
166  std::string const& value)
167 {
168  // No lock here -- it is held by addMetadata
169  addMetadata(key, cet::canonical_string(value));
170 }
171 
172 inline void
174  collection_type const& mdFromInput)
175 {
177  if (mdToInherit_.empty()) {
178  return;
179  }
180 
181  if (!imd_) {
182  imd_ = std::make_unique<InheritedMetadata>(mdToInherit_, mdFromInput);
183  } else {
184  imd_->check_values(mdFromInput);
185  }
186 
187  OldToNew const translator;
188  for (auto const& pr : imd_->entries()) {
189  addMetadataString(translator(pr.first), pr.second);
190  }
191 }
192 
193 inline void
195 {
196  std::lock_guard<std::mutex> lock{service_mutex()};
197  cet::copy_all(md_, std::back_inserter(coll));
198 }
199 
201 #endif /* art_Framework_Services_System_FileCatalogMetadata_h */
202 
203 // Local Variables:
204 // mode: c++
205 // End:
const XML_Char * name
Definition: expat.h:151
FileCatalogMetadata(Parameters const &config)
std::vector< std::string > mdToInherit_
std::vector< std::pair< std::string, std::string >> collection_type
void check_values(collection_type const &fromInput) const
set< int >::iterator it
#define CET_ASSERT_ONLY_ONE_THREAD()
fhicl::OptionalAtom< std::string > applicationVersion
void setMetadataFromInput(collection_type const &coll)
fhicl::Sequence< std::string > metadataFromInput
bool inMetadataList(std::string const &name) const
#define DECLARE_ART_SERVICE(svc, scope)
Definition: ServiceMacros.h:91
Definition: config.py:1
fhicl::Atom< std::string > fileType
std::unordered_map< std::string, std::string > inputmd_
void addMetadataString(std::string const &key, std::string const &value)
typename collection_type::value_type value_type
bool search_all(FwdCont const &, Datum const &)
const XML_Char int const XML_Char * value
Definition: expat.h:331
fhicl::OptionalAtom< std::string > applicationFamily
fhicl::OptionalAtom< std::string > group
InheritedMetadata(std::vector< std::string > const &sortedMdToInherit, collection_type const &coll)
std::unique_ptr< InheritedMetadata > imd_
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
auto copy_all(FwdCont &, FwdIter)
bool canonical_string(std::string const &str, std::string &result)
void addMetadata(std::string const &key, std::string const &value)
Service to store calibration data products (CDP) in the SQLite3 metadatabase of a file...
Definition: FillParentInfo.h:8
void getMetadata(collection_type &coll) const
fhicl::OptionalAtom< std::string > processID
fhicl::OptionalAtom< std::string > runType
static std::mutex & service_mutex()
enum BeamMode string