CMS 3D CMS Logo

EventSetupRecordImpl.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Framework
4 // Class : EventSetupRecordImpl
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Author: Chris Jones
10 // Created: Sat Mar 26 18:06:32 EST 2005
11 //
12 
13 // system include files
14 #include <cassert>
15 #include <string>
16 #include <exception>
17 
18 // user include files
24 
27 
28 namespace edm {
29  namespace eventsetup {
30  //
31  // constants, enums and typedefs
32  //
33 
34  //
35  // static data member definitions
36  //
37 
38  //
39  // constructors and destructor
40  //
42  : validity_(),
43  key_(iKey),
44  proxies_(),
45  eventSetup_(nullptr),
46  cacheIdentifier_(1), //start with 1 since 0 means we haven't checked yet
47  transientAccessRequested_(false) {}
48 
49  //
50  // member functions
51  //
52  void EventSetupRecordImpl::set(const ValidityInterval& iInterval) { validity_ = iInterval; }
53 
54  void EventSetupRecordImpl::getESProducers(std::vector<ComponentDescription const*>& esproducers) {
55  esproducers.clear();
56  esproducers.reserve(proxies_.size());
57  for (auto const& iData : proxies_) {
58  ComponentDescription const* componentDescription = iData->providerDescription();
59  if (!componentDescription->isLooper_ && !componentDescription->isSource_) {
60  esproducers.push_back(componentDescription);
61  }
62  }
63  }
64 
65  std::vector<ComponentDescription const*> EventSetupRecordImpl::componentsForRegisteredDataKeys() const {
66  std::vector<ComponentDescription const*> ret;
67  ret.reserve(proxies_.size());
68  for (auto const& proxy : proxies_) {
69  ret.push_back(proxy->providerDescription());
70  }
71  return ret;
72  }
73 
74  bool EventSetupRecordImpl::add(const DataKey& iKey, const DataProxy* iProxy) {
75  //
76  const DataProxy* proxy = find(iKey);
77  if (nullptr != proxy) {
78  //
79  // we already know the field exist, so do not need to check against end()
80  //
81 
82  // POLICY: If a Producer and a Source both claim to deliver the same data, the
83  // Producer 'trumps' the Source. If two modules of the same type claim to deliver the
84  // same data, this is an error unless the configuration specifically states which one
85  // is to be chosen. A Looper trumps both a Producer and a Source.
86 
87  assert(proxy->providerDescription());
88  assert(iProxy->providerDescription());
89  if (iProxy->providerDescription()->isLooper_) {
90  proxies_[std::distance(keysForProxies_.begin(),
91  std::lower_bound(keysForProxies_.begin(), keysForProxies_.end(), iKey))] = iProxy;
92  return true;
93  }
94 
95  if (proxy->providerDescription()->isSource_ == iProxy->providerDescription()->isSource_) {
96  //should lookup to see if there is a specified 'chosen' one and only if not, throw the exception
97  throw cms::Exception("EventSetupConflict")
98  << "two EventSetup " << (proxy->providerDescription()->isSource_ ? "Sources" : "Producers")
99  << " want to deliver type=\"" << iKey.type().name() << "\" label=\"" << iKey.name().value() << "\"\n"
100  << " from record " << key().type().name() << ". The two providers are \n"
101  << "1) type=\"" << proxy->providerDescription()->type_ << "\" label=\""
102  << proxy->providerDescription()->label_ << "\"\n"
103  << "2) type=\"" << iProxy->providerDescription()->type_ << "\" label=\""
104  << iProxy->providerDescription()->label_ << "\"\n"
105  << "Please either\n remove one of these "
106  << (proxy->providerDescription()->isSource_ ? "Sources" : "Producers")
107  << "\n or find a way of configuring one of them so it does not deliver this data"
108  << "\n or use an es_prefer statement in the configuration to choose one.";
109  } else if (proxy->providerDescription()->isSource_) {
110  proxies_[std::distance(keysForProxies_.begin(),
111  std::lower_bound(keysForProxies_.begin(), keysForProxies_.end(), iKey))] = iProxy;
112  } else {
113  return false;
114  }
115  } else {
116  auto lb = std::lower_bound(keysForProxies_.begin(), keysForProxies_.end(), iKey);
117  auto index = std::distance(keysForProxies_.begin(), lb);
118  keysForProxies_.insert(lb, iKey);
119  proxies_.insert(proxies_.begin() + index, iProxy);
120  }
121  return true;
122  }
123 
125  keysForProxies_.clear();
126  proxies_.clear();
127  }
128 
130  transientAccessRequested_ = false;
131  ++cacheIdentifier_;
132  }
133 
135  bool returnValue = transientAccessRequested_;
136  transientAccessRequested_ = false;
137  return returnValue;
138  }
139 
140  //
141  // const member functions
142  //
143 
144  const void* EventSetupRecordImpl::getFromProxy(DataKey const& iKey,
145  const ComponentDescription*& iDesc,
146  bool iTransientAccessOnly) const {
147  if (iTransientAccessOnly) {
148  this->transientAccessRequested();
149  }
150 
151  const DataProxy* proxy = this->find(iKey);
152 
153  const void* hold = nullptr;
154 
155  if (nullptr != proxy) {
156  try {
157  convertException::wrap([&]() {
158  hold = proxy->get(*this, iKey, iTransientAccessOnly, eventSetup_->activityRegistry());
159  iDesc = proxy->providerDescription();
160  });
161  } catch (cms::Exception& e) {
162  addTraceInfoToCmsException(e, iKey.name().value(), proxy->providerDescription(), iKey);
163  //NOTE: the above function can't do the 'throw' since it causes the C++ class type
164  // of the throw to be changed, a 'rethrow' does not have that problem
165  throw;
166  }
167  }
168  return hold;
169  }
170 
171  const void* EventSetupRecordImpl::getFromProxy(ESProxyIndex iProxyIndex,
172  bool iTransientAccessOnly,
173  const ComponentDescription*& iDesc,
174  DataKey const*& oGottenKey) const {
175  if (iProxyIndex.value() >= static_cast<ESProxyIndex::Value_t>(proxies_.size())) {
176  return nullptr;
177  }
178  if (iTransientAccessOnly) {
179  this->transientAccessRequested();
180  }
181 
182  const DataProxy* proxy = proxies_[iProxyIndex.value()];
183  assert(nullptr != proxy);
184  iDesc = proxy->providerDescription();
185 
186  const void* hold = nullptr;
187 
188  auto const& key = keysForProxies_[iProxyIndex.value()];
189  oGottenKey = &key;
190  try {
192  [&]() { hold = proxy->get(*this, key, iTransientAccessOnly, eventSetup_->activityRegistry()); });
193  } catch (cms::Exception& e) {
194  addTraceInfoToCmsException(e, key.name().value(), proxy->providerDescription(), key);
195  //NOTE: the above function can't do the 'throw' since it causes the C++ class type
196  // of the throw to be changed, a 'rethrow' does not have that problem
197  throw;
198  }
199  return hold;
200  }
201 
202  const DataProxy* EventSetupRecordImpl::find(const DataKey& iKey) const {
203  auto lb = std::lower_bound(keysForProxies_.begin(), keysForProxies_.end(), iKey);
204  if ((lb == keysForProxies_.end()) or (*lb != iKey)) {
205  return nullptr;
206  }
207  return proxies_[std::distance(keysForProxies_.begin(), lb)];
208  }
209 
210  bool EventSetupRecordImpl::doGet(const DataKey& aKey, bool aGetTransiently) const {
211  const DataProxy* proxy = find(aKey);
212  if (nullptr != proxy) {
213  try {
215  [&]() { proxy->doGet(*this, aKey, aGetTransiently, eventSetup_->activityRegistry()); });
216  } catch (cms::Exception& e) {
217  addTraceInfoToCmsException(e, aKey.name().value(), proxy->providerDescription(), aKey);
218  //NOTE: the above function can't do the 'throw' since it causes the C++ class type
219  // of the throw to be changed, a 'rethrow' does not have that problem
220  throw;
221  }
222  }
223  return nullptr != proxy;
224  }
225 
226  bool EventSetupRecordImpl::wasGotten(const DataKey& aKey) const {
227  const DataProxy* proxy = find(aKey);
228  if (nullptr != proxy) {
229  return proxy->cacheIsValid();
230  }
231  return false;
232  }
233 
235  const DataProxy* proxy = find(aKey);
236  if (nullptr != proxy) {
237  return proxy->providerDescription();
238  }
239  return nullptr;
240  }
241 
242  void EventSetupRecordImpl::fillRegisteredDataKeys(std::vector<DataKey>& oToFill) const {
243  oToFill = keysForProxies_;
244  }
245 
246  void EventSetupRecordImpl::validate(const ComponentDescription* iDesc, const ESInputTag& iTag) const {
247  if (iDesc && !iTag.module().empty()) {
248  bool matched = false;
249  if (iDesc->label_.empty()) {
250  matched = iDesc->type_ == iTag.module();
251  } else {
252  matched = iDesc->label_ == iTag.module();
253  }
254  if (!matched) {
255  throw cms::Exception("EventSetupWrongModule")
256  << "EventSetup data was retrieved using an ESInputTag with the values\n"
257  << " moduleLabel = '" << iTag.module() << "'\n"
258  << " dataLabel = '" << iTag.data() << "'\n"
259  << "but the data matching the C++ class type and dataLabel comes from module type=" << iDesc->type_
260  << " label='" << iDesc->label_ << "'.\n Please either change the ESInputTag's 'module' label to be "
261  << (iDesc->label_.empty() ? iDesc->type_ : iDesc->label_) << "\n or add the EventSetup module "
262  << iTag.module() << " to the configuration.";
263  }
264  }
265  }
266 
268  const char* iName,
269  const ComponentDescription* iDescription,
270  const DataKey& iKey) const {
271  std::ostringstream ost;
272  ost << "Using EventSetup component " << iDescription->type_ << "/'" << iDescription->label_ << "' to make data "
273  << iKey.type().name() << "/'" << iName << "' in record " << this->key().type().name();
274  iException.addContext(ost.str());
275  }
276 
277  //
278  // static member functions
279  //
280  } // namespace eventsetup
281 } // namespace edm
void getESProducers(std::vector< ComponentDescription const * > &esproducers)
bool cacheIsValid() const
Definition: DataProxy.h:43
virtual EventSetupRecordKey key() const =0
void const * get(EventSetupRecordImpl const &, DataKey const &iKey, bool iTransiently, ActivityRegistry const *) const
Definition: DataProxy.cc:122
void addTraceInfoToCmsException(cms::Exception &iException, char const *iName, ComponentDescription const *, DataKey const &) const
DataProxy const * find(DataKey const &aKey) const
std::vector< ComponentDescription const * > componentsForRegisteredDataKeys() const
there is a 1-to-1 correspondence between elements returned and the elements returned from fillRegiste...
#define nullptr
void addTraceInfoToCmsException(cms::Exception &iException, char const *iName, ComponentDescription const *, DataKey const &) const
void validate(ComponentDescription const *, ESInputTag const &) const
void doGet(EventSetupRecordImpl const &iRecord, DataKey const &iKey, bool iTransiently, ActivityRegistry const *) const
Definition: DataProxy.cc:148
void const * getFromProxy(DataKey const &iKey, ComponentDescription const *&iDesc, bool iTransientAccessOnly) const
ComponentDescription const * providerDescription(DataKey const &aKey) const
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
bool add(DataKey const &iKey, DataProxy const *iProxy)
void set(ValidityInterval const &)
bool wasGotten(DataKey const &aKey) const
const std::string & data() const
Definition: ESInputTag.h:104
ComponentDescription const * providerDescription() const
returns the description of the DataProxyProvider which owns this Proxy
Definition: DataProxy.h:55
const TypeTag & type() const
Definition: DataKey.h:52
void addContext(std::string const &context)
Definition: Exception.cc:165
bool transientReset()
returns &#39;true&#39; if a transient request has occurred since the last call to transientReset.
EventSetupRecordImpl(const EventSetupRecordKey &iKey)
constexpr Value_t value() const noexcept
Definition: ESIndices.h:43
HLT enums.
const NameTag & name() const
Definition: DataKey.h:53
const char * value() const
Definition: DataKeyTags.h:39
auto wrap(F iFunc) -> decltype(iFunc())
void fillRegisteredDataKeys(std::vector< DataKey > &oToFill) const
clears the oToFill vector and then fills it with the keys for all registered data keys ...
const std::string & module() const
Definition: ESInputTag.h:99
DataProxy const * find(DataKey const &aKey) const
bool doGet(DataKey const &aKey, bool aGetTransiently=false) const
returns false if no data available for key