CMS 3D CMS Logo

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 
32 
33 #include <algorithm>
34 #include <exception>
35 #include <iostream>
36 #include <set>
37 
38 namespace edm {
39  namespace eventsetup {
40 
42  EventSetupsController::EventSetupsController(ModuleTypeResolverBase const* resolver) : typeResolver_(resolver) {}
43 
45  for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
46  eventSetupRecordIOVQueue->endIOVAsync(iEndTask);
47  }
48  }
49 
50  std::shared_ptr<EventSetupProvider> EventSetupsController::makeProvider(ParameterSet& iPSet,
51  ActivityRegistry* activityRegistry,
52  ParameterSet const* eventSetupPset,
53  unsigned int maxConcurrentIOVs,
54  bool dumpOptions) {
55  // Makes an EventSetupProvider
56  // Also parses the prefer information from ParameterSets and puts
57  // it in a map that is stored in the EventSetupProvider
58  std::shared_ptr<EventSetupProvider> returnValue(
59  makeEventSetupProvider(iPSet, providers_.size(), activityRegistry));
60 
61  // Construct the ESProducers and ESSources
62  // shared_ptrs to them are temporarily stored in this
63  // EventSetupsController and in the EventSetupProvider
64  fillEventSetupProvider(typeResolver_, *this, *returnValue, iPSet);
65 
66  numberOfConcurrentIOVs_.readConfigurationParameters(eventSetupPset, maxConcurrentIOVs, dumpOptions);
67 
68  providers_.push_back(returnValue);
69  return returnValue;
70  }
71 
74  for (auto& eventSetupProvider : providers_) {
76  }
77 
78  for (auto& eventSetupProvider : providers_) {
79  eventSetupProvider->finishConfiguration(numberOfConcurrentIOVs_, hasNonconcurrentFinder_);
80  }
81 
82  // When the ESSources and ESProducers were constructed a first pass was
83  // done which attempts to get component sharing between SubProcesses
84  // correct, but in this pass only the configuration of the components
85  // being shared are compared. This is not good enough for ESProducers.
86  // In the following function, all the other components that contribute
87  // to the same record and also the records that record depends on are
88  // also checked. The component sharing is appropriately fixed as necessary.
91 
95  }
96  }
97 
99  IOVSyncValue const& iSync,
100  WaitingTaskHolder& taskToStartAfterIOVInit,
101  WaitingTaskList& endIOVWaitingTasks,
102  std::vector<std::shared_ptr<const EventSetupImpl>>& eventSetupImpls,
103  edm::SerialTaskQueue& queueWhichWaitsForIOVsToFinish,
104  ActivityRegistry* actReg,
105  ServiceToken const& iToken,
106  bool iForceCacheClear) {
107  auto asyncEventSetup =
108  [this, &endIOVWaitingTasks, &eventSetupImpls, &queueWhichWaitsForIOVsToFinish, actReg, iForceCacheClear](
109  IOVSyncValue const& iSync, WaitingTaskHolder& task) {
110  queueWhichWaitsForIOVsToFinish.pause();
111  CMS_SA_ALLOW try {
112  if (iForceCacheClear) {
113  forceCacheClear();
114  }
116  actReg->preESSyncIOVSignal_.emit(iSync);
117  eventSetupForInstanceAsync(iSync, task, endIOVWaitingTasks, eventSetupImpls);
118  sentry.completedSuccessfully();
119  } catch (...) {
120  task.doneWaiting(std::current_exception());
121  }
122  };
123  if (doWeNeedToWaitForIOVsToFinish(iSync) || iForceCacheClear) {
124  // We get inside this block if there is an EventSetup
125  // module not able to handle concurrent IOVs (usually an ESSource)
126  // and the new sync value is outside the current IOV of that module.
127  // Also at beginRun when forcing caches to clear.
128  auto group = taskToStartAfterIOVInit.group();
129  ServiceWeakToken weakToken = iToken;
130  queueWhichWaitsForIOVsToFinish.push(*group,
131  [iSync, taskToStartAfterIOVInit, asyncEventSetup, weakToken]() mutable {
132  ServiceRegistry::Operate operate(weakToken.lock());
133  asyncEventSetup(iSync, taskToStartAfterIOVInit);
134  });
135  } else {
136  asyncEventSetup(iSync, taskToStartAfterIOVInit);
137  }
138  }
139 
141  IOVSyncValue const& syncValue,
142  WaitingTaskHolder const& taskToStartAfterIOVInit,
143  WaitingTaskList& endIOVWaitingTasks,
144  std::vector<std::shared_ptr<const EventSetupImpl>>& eventSetupImpls) {
146 
147  bool newEventSetupImpl = false;
148  eventSetupImpls.clear();
149  eventSetupImpls.reserve(providers_.size());
150 
151  // Note that unless there are one or more SubProcesses providers_ will only
152  // contain one element.
153 
154  for (auto& eventSetupProvider : providers_) {
155  eventSetupProvider->setAllValidityIntervals(syncValue);
156  }
157 
158  for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
159  // For a particular record, if the top level process or any SubProcess requires
160  // starting a new IOV, then we must start a new IOV for all of them. And we
161  // need to know whether this is needed at this point in time. This is
162  // recorded in the EventSetupRecordProviders.
163  eventSetupRecordIOVQueue->setNewIntervalForAnySubProcess();
164  }
165 
166  for (auto& eventSetupProvider : providers_) {
167  // Decides whether we can reuse the existing EventSetupImpl and if we can
168  // returns it. If a new one is needed it will create it, although the pointers
169  // to the EventSetupRecordImpl's will not be set yet in the returned EventSetupImpl
170  // object.
171  eventSetupImpls.push_back(eventSetupProvider->eventSetupForInstance(syncValue, newEventSetupImpl));
172  }
173 
174  for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
175  eventSetupRecordIOVQueue->checkForNewIOVs(taskToStartAfterIOVInit, endIOVWaitingTasks, newEventSetupImpl);
176  }
177  }
178 
180  if (hasNonconcurrentFinder()) {
181  for (auto& eventSetupProvider : providers_) {
182  if (eventSetupProvider->doWeNeedToWaitForIOVsToFinish(syncValue)) {
183  return true;
184  }
185  }
186  }
187  return false;
188  }
189 
191  for (auto& eventSetupProvider : providers_) {
192  eventSetupProvider->forceCacheClear();
193  }
194  }
195 
196  std::shared_ptr<DataProxyProvider> EventSetupsController::getESProducerAndRegisterProcess(
197  ParameterSet const& pset, unsigned subProcessIndex) {
198  // Try to find a DataProxyProvider with a matching ParameterSet
199  auto elements = esproducers_.equal_range(pset.id());
200  for (auto it = elements.first; it != elements.second; ++it) {
201  // Untracked parameters must also match, do complete comparison if IDs match
202  if (isTransientEqual(pset, *it->second.pset())) {
203  // Register processes with an exact match
204  it->second.subProcessIndexes().push_back(subProcessIndex);
205  // Return the DataProxyProvider
206  return it->second.provider();
207  }
208  }
209  // Could not find it
210  return std::shared_ptr<DataProxyProvider>();
211  }
212 
214  std::shared_ptr<DataProxyProvider> const& component,
215  unsigned subProcessIndex) {
216  auto newElement =
217  esproducers_.insert(std::pair<ParameterSetID, ESProducerInfo>(pset.id(), ESProducerInfo(&pset, component)));
218  // Register processes with an exact match
219  newElement->second.subProcessIndexes().push_back(subProcessIndex);
220  }
221 
222  std::shared_ptr<EventSetupRecordIntervalFinder> EventSetupsController::getESSourceAndRegisterProcess(
223  ParameterSet const& pset, unsigned subProcessIndex) {
224  // Try to find a EventSetupRecordIntervalFinder with a matching ParameterSet
225  auto elements = essources_.equal_range(pset.id());
226  for (auto it = elements.first; it != elements.second; ++it) {
227  // Untracked parameters must also match, do complete comparison if IDs match
228  if (isTransientEqual(pset, *it->second.pset())) {
229  // Register processes with an exact match
230  it->second.subProcessIndexes().push_back(subProcessIndex);
231  // Return the EventSetupRecordIntervalFinder
232  return it->second.finder();
233  }
234  }
235  // Could not find it
236  return std::shared_ptr<EventSetupRecordIntervalFinder>();
237  }
238 
240  std::shared_ptr<EventSetupRecordIntervalFinder> const& component,
241  unsigned subProcessIndex) {
242  auto newElement =
243  essources_.insert(std::pair<ParameterSetID, ESSourceInfo>(pset.id(), ESSourceInfo(&pset, component)));
244  // Register processes with an exact match
245  newElement->second.subProcessIndexes().push_back(subProcessIndex);
246  }
247 
249  esproducers_.clear();
250  essources_.clear();
251  }
252 
254  unsigned subProcessIndex,
255  unsigned precedingProcessIndex,
256  bool& firstProcessWithThisPSet,
257  bool& precedingHasMatchingPSet) const {
258  auto elements = esproducers_.equal_range(psetID);
259  for (auto it = elements.first; it != elements.second; ++it) {
260  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
261 
262  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
263  if (iFound == subProcessIndexes.end()) {
264  continue;
265  }
266 
267  if (iFound == subProcessIndexes.begin()) {
268  firstProcessWithThisPSet = true;
269  precedingHasMatchingPSet = false;
270  } else {
271  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
272  if (iFoundPreceding == iFound) {
273  firstProcessWithThisPSet = false;
274  precedingHasMatchingPSet = false;
275  } else {
276  firstProcessWithThisPSet = false;
277  precedingHasMatchingPSet = true;
278  }
279  }
280  return;
281  }
282  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatches\n"
283  << "Subprocess index not found. This should never happen\n"
284  << "Please report this to a Framework Developer\n";
285  }
286 
288  unsigned subProcessIndex,
289  unsigned precedingProcessIndex) const {
290  auto elements = esproducers_.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  break;
302  } else {
303  return iFoundPreceding == subProcessIndexes.begin();
304  }
305  }
306  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::isFirstMatch\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  break;
327  } else {
328  return (++iFoundPreceding) == iFound;
329  }
330  }
331  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::isLastMatch\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,
339  unsigned precedingProcessIndex) const {
340  auto elements = essources_.equal_range(psetID);
341  for (auto it = elements.first; it != elements.second; ++it) {
342  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
343 
344  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
345  if (iFound == subProcessIndexes.end()) {
346  continue;
347  }
348 
349  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
350  if (iFoundPreceding == iFound) {
351  return false;
352  } else {
353  return true;
354  }
355  }
356  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatchingESSource\n"
357  << "Subprocess index not found. This should never happen\n"
358  << "Please report this to a Framework Developer\n";
359  return false;
360  }
361 
363  unsigned subProcessIndex,
364  unsigned precedingProcessIndex) const {
365  auto elements = esproducers_.equal_range(psetID);
366  for (auto it = elements.first; it != elements.second; ++it) {
367  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
368 
369  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
370  if (iFound == subProcessIndexes.end()) {
371  continue;
372  }
373 
374  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
375  if (iFoundPreceding == iFound) {
376  return false;
377  } else {
378  return true;
379  }
380  }
381  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatchingESSource\n"
382  << "Subprocess index not found. This should never happen\n"
383  << "Please report this to a Framework Developer\n";
384  return false;
385  }
386 
387  ParameterSet& EventSetupsController::getESProducerPSet(ParameterSetID const& psetID, unsigned subProcessIndex) {
388  auto elements = esproducers_.equal_range(psetID);
389  for (auto it = elements.first; it != elements.second; ++it) {
390  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
391 
392  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
393  if (iFound == subProcessIndexes.end()) {
394  continue;
395  }
396  return *it->second.pset();
397  }
398  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::getESProducerPSet\n"
399  << "Subprocess index not found. This should never happen\n"
400  << "Please report this to a Framework Developer\n";
401  }
402 
404  // Loop over SubProcesses, skip the top level process.
405  auto esProvider = providers_.begin();
406  auto const esProviderEnd = providers_.end();
407  if (esProvider != esProviderEnd)
408  ++esProvider;
409  for (; esProvider != esProviderEnd; ++esProvider) {
410  // An element is added to this set for each ESProducer
411  // when we have determined which preceding process
412  // this process can share that ESProducer with or
413  // we have determined that it cannot be shared with
414  // any preceding process.
415  // Note the earliest possible preceding process
416  // will be the one selected if there is more than one.
417  std::set<ParameterSetIDHolder> sharingCheckDone;
418 
419  // This will hold an entry for DataProxy's that are
420  // referenced by an EventSetupRecord in this SubProcess.
421  // But only for DataProxy's that are associated with
422  // an ESProducer (not the ones associated with ESSource's
423  // or EDLooper's)
424  std::map<EventSetupRecordKey, std::vector<ComponentDescription const*>> referencedESProducers;
425 
426  // For each EventSetupProvider from a SubProcess, loop over the
427  // EventSetupProviders from the preceding processes (the first
428  // preceding process will be the top level process and the others
429  // SubProcess's)
430  for (auto precedingESProvider = providers_.begin(); precedingESProvider != esProvider; ++precedingESProvider) {
431  (*esProvider)
432  ->checkESProducerSharing(
433  typeResolver_, **precedingESProvider, sharingCheckDone, referencedESProducers, *this);
434  }
435 
436  (*esProvider)->resetRecordToProxyPointers();
437  }
438  for (auto& eventSetupProvider : providers_) {
439  eventSetupProvider->clearInitializationData();
440  }
441  }
442 
444  std::set<EventSetupRecordKey> keys;
445  for (auto const& provider : providers_) {
446  provider->fillKeys(keys);
447  }
448 
449  for (auto const& key : keys) {
450  eventSetupRecordIOVQueues_.push_back(
451  std::make_unique<EventSetupRecordIOVQueue>(numberOfConcurrentIOVs_.numberOfConcurrentIOVs(key)));
453  for (auto& provider : providers_) {
454  EventSetupRecordProvider* recProvider = provider->tryToGetRecordProvider(key);
455  if (recProvider) {
456  iovQueue.addRecProvider(recProvider);
457  }
458  }
459  }
460  }
461 
463  oneapi::tbb::task_group& iGroup,
464  eventsetup::EventSetupsController& espController) {
465  FinalWaitingTask waitUntilIOVInitializationCompletes{iGroup};
466 
467  // These do nothing ...
468  WaitingTaskList dummyWaitingTaskList;
469  std::vector<std::shared_ptr<const EventSetupImpl>> dummyEventSetupImpls;
470 
471  {
472  WaitingTaskHolder waitingTaskHolder(iGroup, &waitUntilIOVInitializationCompletes);
473  // Caught exception is propagated via WaitingTaskHolder
474  CMS_SA_ALLOW try {
475  // All the real work is done here.
476  espController.eventSetupForInstanceAsync(
477  syncValue, waitingTaskHolder, dummyWaitingTaskList, dummyEventSetupImpls);
478  dummyWaitingTaskList.doneWaiting(std::exception_ptr{});
479  } catch (...) {
480  dummyWaitingTaskList.doneWaiting(std::exception_ptr{});
481  waitingTaskHolder.doneWaiting(std::current_exception());
482  }
483  }
484  waitUntilIOVInitializationCompletes.wait();
485  }
486  } // namespace eventsetup
487 } // 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)
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)
ModuleTypeResolverBase const * typeResolver_
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)
oneapi::tbb::task_group * group() const noexcept
ParameterSet & getESProducerPSet(ParameterSetID const &psetID, unsigned subProcessIndex)
bool isLastMatch(ParameterSetID const &psetID, unsigned subProcessIndex, unsigned precedingProcessIndex) const
void putESProducer(ParameterSet &pset, std::shared_ptr< DataProxyProvider > const &component, unsigned subProcessIndex)
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 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)
void eventSetupForInstanceAsync(IOVSyncValue const &, WaitingTaskHolder const &taskToStartAfterIOVInit, WaitingTaskList &endIOVWaitingTasks, std::vector< std::shared_ptr< const EventSetupImpl >> &)
ServiceToken lock() const
Definition: ServiceToken.h:101
void readConfigurationParameters(ParameterSet const *eventSetupPset, unsigned int maxConcurrentIOVs, bool dumpOptions)
void fillEventSetupProvider(ModuleTypeResolverBase const *resolver, EventSetupsController &esController, EventSetupProvider &cp, ParameterSet &params)
bool isFirstMatch(ParameterSetID const &psetID, unsigned subProcessIndex, unsigned precedingProcessIndex) const
void endIOVsAsync(edm::WaitingTaskHolder iEndTask)
HLT enums.
void runOrQueueEventSetupForInstanceAsync(IOVSyncValue const &, WaitingTaskHolder &taskToStartAfterIOVInit, WaitingTaskList &endIOVWaitingTasks, std::vector< std::shared_ptr< const EventSetupImpl >> &, edm::SerialTaskQueue &queueWhichWaitsForIOVsToFinish, ActivityRegistry *, ServiceToken const &, bool iForceCacheClear=false)
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