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