CMS 3D CMS Logo

EventSetupsController.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Framework
4 // Class : EventSetupsController
5 //
6 // Implementation:
7 // [Notes on implementation]
8 //
9 // Original Author: Chris Jones, W. David Dagenhart
10 // Created: Wed Jan 12 14:30:44 CST 2011
11 //
12 
14 
26 
27 #include <algorithm>
28 #include <iostream>
29 #include <set>
30 
31 namespace edm {
32  namespace eventsetup {
33 
35 
37  for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
38  eventSetupRecordIOVQueue->endIOVAsync(iEndTask);
39  }
40  }
41 
42  std::shared_ptr<EventSetupProvider> EventSetupsController::makeProvider(ParameterSet& iPSet,
43  ActivityRegistry* activityRegistry,
44  ParameterSet const* eventSetupPset,
45  unsigned int maxConcurrentIOVs,
46  bool dumpOptions) {
47  // Makes an EventSetupProvider
48  // Also parses the prefer information from ParameterSets and puts
49  // it in a map that is stored in the EventSetupProvider
50  std::shared_ptr<EventSetupProvider> returnValue(
51  makeEventSetupProvider(iPSet, providers_.size(), activityRegistry));
52 
53  // Construct the ESProducers and ESSources
54  // shared_ptrs to them are temporarily stored in this
55  // EventSetupsController and in the EventSetupProvider
56  fillEventSetupProvider(*this, *returnValue, iPSet);
57 
58  numberOfConcurrentIOVs_.readConfigurationParameters(eventSetupPset, maxConcurrentIOVs, dumpOptions);
59 
60  providers_.push_back(returnValue);
61  return returnValue;
62  }
63 
66  for (auto& eventSetupProvider : providers_) {
68  }
69 
70  for (auto& eventSetupProvider : providers_) {
71  eventSetupProvider->finishConfiguration(numberOfConcurrentIOVs_, hasNonconcurrentFinder_);
72  }
73 
74  // When the ESSources and ESProducers were constructed a first pass was
75  // done which attempts to get component sharing between SubProcesses
76  // correct, but in this pass only the configuration of the components
77  // being shared are compared. This is not good enough for ESProducers.
78  // In the following function, all the other components that contribute
79  // to the same record and also the records that record depends on are
80  // also checked. The component sharing is appropriately fixed as necessary.
83 
87  }
88  }
89 
91  IOVSyncValue const& syncValue,
92  WaitingTaskHolder const& taskToStartAfterIOVInit,
93  WaitingTaskList& endIOVWaitingTasks,
94  std::vector<std::shared_ptr<const EventSetupImpl>>& eventSetupImpls) {
96 
97  bool newEventSetupImpl = false;
98  eventSetupImpls.clear();
99  eventSetupImpls.reserve(providers_.size());
100 
101  // Note that unless there are one or more SubProcesses providers_ will only
102  // contain one element.
103 
104  for (auto& eventSetupProvider : providers_) {
105  eventSetupProvider->setAllValidityIntervals(syncValue);
106  }
107 
108  for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
109  // For a particular record, if the top level process or any SubProcess requires
110  // starting a new IOV, then we must start a new IOV for all of them. And we
111  // need to know whether this is needed at this point in time. This is
112  // recorded in the EventSetupRecordProviders.
113  eventSetupRecordIOVQueue->setNewIntervalForAnySubProcess();
114  }
115 
116  for (auto& eventSetupProvider : providers_) {
117  // Decides whether we can reuse the existing EventSetupImpl and if we can
118  // returns it. If a new one is needed it will create it, although the pointers
119  // to the EventSetupRecordImpl's will not be set yet in the returned EventSetupImpl
120  // object.
121  eventSetupImpls.push_back(eventSetupProvider->eventSetupForInstance(syncValue, newEventSetupImpl));
122  }
123 
124  for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
125  eventSetupRecordIOVQueue->checkForNewIOVs(taskToStartAfterIOVInit, endIOVWaitingTasks, newEventSetupImpl);
126  }
127  }
128 
130  if (hasNonconcurrentFinder()) {
131  for (auto& eventSetupProvider : providers_) {
132  if (eventSetupProvider->doWeNeedToWaitForIOVsToFinish(syncValue)) {
133  return true;
134  }
135  }
136  }
137  return false;
138  }
139 
141  for (auto& eventSetupProvider : providers_) {
142  eventSetupProvider->forceCacheClear();
143  }
144  }
145 
146  std::shared_ptr<DataProxyProvider> EventSetupsController::getESProducerAndRegisterProcess(
147  ParameterSet const& pset, unsigned subProcessIndex) {
148  // Try to find a DataProxyProvider with a matching ParameterSet
149  auto elements = esproducers_.equal_range(pset.id());
150  for (auto it = elements.first; it != elements.second; ++it) {
151  // Untracked parameters must also match, do complete comparison if IDs match
152  if (isTransientEqual(pset, *it->second.pset())) {
153  // Register processes with an exact match
154  it->second.subProcessIndexes().push_back(subProcessIndex);
155  // Return the DataProxyProvider
156  return it->second.provider();
157  }
158  }
159  // Could not find it
160  return std::shared_ptr<DataProxyProvider>();
161  }
162 
164  std::shared_ptr<DataProxyProvider> const& component,
165  unsigned subProcessIndex) {
166  auto newElement =
167  esproducers_.insert(std::pair<ParameterSetID, ESProducerInfo>(pset.id(), ESProducerInfo(&pset, component)));
168  // Register processes with an exact match
169  newElement->second.subProcessIndexes().push_back(subProcessIndex);
170  }
171 
172  std::shared_ptr<EventSetupRecordIntervalFinder> EventSetupsController::getESSourceAndRegisterProcess(
173  ParameterSet const& pset, unsigned subProcessIndex) {
174  // Try to find a EventSetupRecordIntervalFinder with a matching ParameterSet
175  auto elements = essources_.equal_range(pset.id());
176  for (auto it = elements.first; it != elements.second; ++it) {
177  // Untracked parameters must also match, do complete comparison if IDs match
178  if (isTransientEqual(pset, *it->second.pset())) {
179  // Register processes with an exact match
180  it->second.subProcessIndexes().push_back(subProcessIndex);
181  // Return the EventSetupRecordIntervalFinder
182  return it->second.finder();
183  }
184  }
185  // Could not find it
186  return std::shared_ptr<EventSetupRecordIntervalFinder>();
187  }
188 
190  std::shared_ptr<EventSetupRecordIntervalFinder> const& component,
191  unsigned subProcessIndex) {
192  auto newElement =
193  essources_.insert(std::pair<ParameterSetID, ESSourceInfo>(pset.id(), ESSourceInfo(&pset, component)));
194  // Register processes with an exact match
195  newElement->second.subProcessIndexes().push_back(subProcessIndex);
196  }
197 
199  esproducers_.clear();
200  essources_.clear();
201  }
202 
204  unsigned subProcessIndex,
205  unsigned precedingProcessIndex,
206  bool& firstProcessWithThisPSet,
207  bool& precedingHasMatchingPSet) const {
208  auto elements = esproducers_.equal_range(psetID);
209  for (auto it = elements.first; it != elements.second; ++it) {
210  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
211 
212  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
213  if (iFound == subProcessIndexes.end()) {
214  continue;
215  }
216 
217  if (iFound == subProcessIndexes.begin()) {
218  firstProcessWithThisPSet = true;
219  precedingHasMatchingPSet = false;
220  } else {
221  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
222  if (iFoundPreceding == iFound) {
223  firstProcessWithThisPSet = false;
224  precedingHasMatchingPSet = false;
225  } else {
226  firstProcessWithThisPSet = false;
227  precedingHasMatchingPSet = true;
228  }
229  }
230  return;
231  }
232  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatches\n"
233  << "Subprocess index not found. This should never happen\n"
234  << "Please report this to a Framework Developer\n";
235  }
236 
238  unsigned subProcessIndex,
239  unsigned precedingProcessIndex) const {
240  auto elements = esproducers_.equal_range(psetID);
241  for (auto it = elements.first; it != elements.second; ++it) {
242  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
243 
244  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
245  if (iFound == subProcessIndexes.end()) {
246  continue;
247  }
248 
249  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
250  if (iFoundPreceding == iFound) {
251  break;
252  } else {
253  return iFoundPreceding == subProcessIndexes.begin();
254  }
255  }
256  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::isFirstMatch\n"
257  << "Subprocess index not found. This should never happen\n"
258  << "Please report this to a Framework Developer\n";
259  return false;
260  }
261 
263  unsigned subProcessIndex,
264  unsigned precedingProcessIndex) const {
265  auto elements = esproducers_.equal_range(psetID);
266  for (auto it = elements.first; it != elements.second; ++it) {
267  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
268 
269  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
270  if (iFound == subProcessIndexes.end()) {
271  continue;
272  }
273 
274  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
275  if (iFoundPreceding == iFound) {
276  break;
277  } else {
278  return (++iFoundPreceding) == iFound;
279  }
280  }
281  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::isLastMatch\n"
282  << "Subprocess index not found. This should never happen\n"
283  << "Please report this to a Framework Developer\n";
284  return false;
285  }
286 
288  unsigned subProcessIndex,
289  unsigned precedingProcessIndex) const {
290  auto elements = essources_.equal_range(psetID);
291  for (auto it = elements.first; it != elements.second; ++it) {
292  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
293 
294  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
295  if (iFound == subProcessIndexes.end()) {
296  continue;
297  }
298 
299  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
300  if (iFoundPreceding == iFound) {
301  return false;
302  } else {
303  return true;
304  }
305  }
306  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatchingESSource\n"
307  << "Subprocess index not found. This should never happen\n"
308  << "Please report this to a Framework Developer\n";
309  return false;
310  }
311 
313  unsigned subProcessIndex,
314  unsigned precedingProcessIndex) const {
315  auto elements = esproducers_.equal_range(psetID);
316  for (auto it = elements.first; it != elements.second; ++it) {
317  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
318 
319  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
320  if (iFound == subProcessIndexes.end()) {
321  continue;
322  }
323 
324  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
325  if (iFoundPreceding == iFound) {
326  return false;
327  } else {
328  return true;
329  }
330  }
331  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatchingESSource\n"
332  << "Subprocess index not found. This should never happen\n"
333  << "Please report this to a Framework Developer\n";
334  return false;
335  }
336 
338  unsigned subProcessIndex) const {
339  auto elements = esproducers_.equal_range(psetID);
340  for (auto it = elements.first; it != elements.second; ++it) {
341  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
342 
343  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
344  if (iFound == subProcessIndexes.end()) {
345  continue;
346  }
347  return it->second.pset();
348  }
349  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::getESProducerPSet\n"
350  << "Subprocess index not found. This should never happen\n"
351  << "Please report this to a Framework Developer\n";
352  return nullptr;
353  }
354 
356  // Loop over SubProcesses, skip the top level process.
357  auto esProvider = providers_.begin();
358  auto const esProviderEnd = providers_.end();
359  if (esProvider != esProviderEnd)
360  ++esProvider;
361  for (; esProvider != esProviderEnd; ++esProvider) {
362  // An element is added to this set for each ESProducer
363  // when we have determined which preceding process
364  // this process can share that ESProducer with or
365  // we have determined that it cannot be shared with
366  // any preceding process.
367  // Note the earliest possible preceding process
368  // will be the one selected if there is more than one.
369  std::set<ParameterSetIDHolder> sharingCheckDone;
370 
371  // This will hold an entry for DataProxy's that are
372  // referenced by an EventSetupRecord in this SubProcess.
373  // But only for DataProxy's that are associated with
374  // an ESProducer (not the ones associated with ESSource's
375  // or EDLooper's)
376  std::map<EventSetupRecordKey, std::vector<ComponentDescription const*>> referencedESProducers;
377 
378  // For each EventSetupProvider from a SubProcess, loop over the
379  // EventSetupProviders from the preceding processes (the first
380  // preceding process will be the top level process and the others
381  // SubProcess's)
382  for (auto precedingESProvider = providers_.begin(); precedingESProvider != esProvider; ++precedingESProvider) {
383  (*esProvider)->checkESProducerSharing(**precedingESProvider, sharingCheckDone, referencedESProducers, *this);
384  }
385 
386  (*esProvider)->resetRecordToProxyPointers();
387  }
388  for (auto& eventSetupProvider : providers_) {
389  eventSetupProvider->clearInitializationData();
390  }
391  }
392 
394  std::set<EventSetupRecordKey> keys;
395  for (auto const& provider : providers_) {
396  provider->fillKeys(keys);
397  }
398 
399  for (auto const& key : keys) {
400  eventSetupRecordIOVQueues_.push_back(
401  std::make_unique<EventSetupRecordIOVQueue>(numberOfConcurrentIOVs_.numberOfConcurrentIOVs(key)));
403  for (auto& provider : providers_) {
404  EventSetupRecordProvider* recProvider = provider->tryToGetRecordProvider(key);
405  if (recProvider) {
406  iovQueue.addRecProvider(recProvider);
407  }
408  }
409  }
410  }
411 
413  oneapi::tbb::task_group& iGroup,
414  eventsetup::EventSetupsController& espController) {
415  FinalWaitingTask waitUntilIOVInitializationCompletes;
416 
417  // These do nothing ...
418  WaitingTaskList dummyWaitingTaskList;
419  std::vector<std::shared_ptr<const EventSetupImpl>> dummyEventSetupImpls;
420 
421  {
422  WaitingTaskHolder waitingTaskHolder(iGroup, &waitUntilIOVInitializationCompletes);
423  // Caught exception is propagated via WaitingTaskHolder
424  CMS_SA_ALLOW try {
425  // All the real work is done here.
426  espController.eventSetupForInstanceAsync(
427  syncValue, waitingTaskHolder, dummyWaitingTaskList, dummyEventSetupImpls);
428  dummyWaitingTaskList.doneWaiting(std::exception_ptr{});
429  } catch (...) {
430  dummyWaitingTaskList.doneWaiting(std::exception_ptr{});
431  waitingTaskHolder.doneWaiting(std::current_exception());
432  }
433  }
434  do {
435  iGroup.wait();
436  } while (not waitUntilIOVInitializationCompletes.done());
437 
438  if (waitUntilIOVInitializationCompletes.exceptionPtr() != nullptr) {
439  std::rethrow_exception(*(waitUntilIOVInitializationCompletes.exceptionPtr()));
440  }
441  }
442  } // namespace eventsetup
443 } // namespace edm
std::shared_ptr< EventSetupRecordIntervalFinder > getESSourceAndRegisterProcess(ParameterSet const &pset, unsigned subProcessIndex)
#define CMS_SA_ALLOW
void addRecProvider(EventSetupRecordProvider *recProvider)
std::vector< propagate_const< std::unique_ptr< EventSetupRecordIOVQueue > > > eventSetupRecordIOVQueues_
void putESSource(ParameterSet const &pset, std::shared_ptr< EventSetupRecordIntervalFinder > const &component, unsigned subProcessIndex)
Definition: Hash.h:43
std::exception_ptr const * exceptionPtr() const
Returns exception thrown by dependent task.
Definition: WaitingTask.h:51
ParameterSet const * getESProducerPSet(ParameterSetID const &psetID, unsigned subProcessIndex) const
void putESProducer(ParameterSet const &pset, std::shared_ptr< DataProxyProvider > const &component, unsigned subProcessIndex)
bool isMatchingESSource(ParameterSetID const &psetID, unsigned subProcessIndex, unsigned precedingProcessIndex) const
std::multimap< ParameterSetID, ESProducerInfo > esproducers_
std::unique_ptr< EventSetupProvider > makeEventSetupProvider(ParameterSet const &params, unsigned subProcessIndex, ActivityRegistry *activityRegistry)
void lookForMatches(ParameterSetID const &psetID, unsigned subProcessIndex, unsigned precedingProcessIndex, bool &firstProcessWithThisPSet, bool &precedingHasMatchingPSet) const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
void synchronousEventSetupForInstance(IOVSyncValue const &syncValue, oneapi::tbb::task_group &iGroup, eventsetup::EventSetupsController &espController)
bool isLastMatch(ParameterSetID const &psetID, unsigned subProcessIndex, unsigned precedingProcessIndex) const
void doneWaiting(std::exception_ptr iPtr)
Signals that the resource is now available and tasks should be spawned.
std::shared_ptr< DataProxyProvider > getESProducerAndRegisterProcess(ParameterSet const &pset, unsigned subProcessIndex)
void fillEventSetupProvider(EventSetupsController &esController, EventSetupProvider &cp, ParameterSet &params)
void doneWaiting(std::exception_ptr iExcept)
void fillRecordsNotAllowingConcurrentIOVs(EventSetupProvider const &)
std::multimap< ParameterSetID, ESSourceInfo > essources_
bool isMatchingESProducer(ParameterSetID const &psetID, unsigned subProcessIndex, unsigned precedingProcessIndex) const
std::shared_ptr< EventSetupProvider > makeProvider(ParameterSet &, ActivityRegistry *, ParameterSet const *eventSetupPset=nullptr, unsigned int maxConcurrentIOVs=0, bool dumpOptions=false)
bool done() const
Definition: WaitingTask.h:82
void eventSetupForInstanceAsync(IOVSyncValue const &, WaitingTaskHolder const &taskToStartAfterIOVInit, WaitingTaskList &endIOVWaitingTasks, std::vector< std::shared_ptr< const EventSetupImpl >> &)
void readConfigurationParameters(ParameterSet const *eventSetupPset, unsigned int maxConcurrentIOVs, bool dumpOptions)
bool isFirstMatch(ParameterSetID const &psetID, unsigned subProcessIndex, unsigned precedingProcessIndex) const
void endIOVsAsync(edm::WaitingTaskHolder iEndTask)
HLT enums.
bool doWeNeedToWaitForIOVsToFinish(IOVSyncValue const &) const
std::vector< propagate_const< std::shared_ptr< EventSetupProvider > > > providers_
bool isTransientEqual(ParameterSet const &a, ParameterSet const &b)
unsigned int numberOfConcurrentIOVs(EventSetupRecordKey const &, bool printInfoMsg=false) const