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  {
118  //all EventSetupRecordIntervalFinders are sequentially set to the
119  // new SyncValue in the call. The async part is just waiting for
120  // the Records to be available which is done after the SyncValue setup.
121  actReg->preESSyncIOVSignal_.emit(iSync);
122  auto postSignal = [&iSync](ActivityRegistry* actReg) { actReg->postESSyncIOVSignal_.emit(iSync); };
123  std::unique_ptr<ActivityRegistry, decltype(postSignal)> guard(actReg, postSignal);
124  eventSetupForInstanceAsync(iSync, task, endIOVWaitingTasks, eventSetupImpls);
125  }
126  sentry.completedSuccessfully();
127  } catch (...) {
128  task.doneWaiting(std::current_exception());
129  }
130  };
131  if (doWeNeedToWaitForIOVsToFinish(iSync) || iForceCacheClear) {
132  // We get inside this block if there is an EventSetup
133  // module not able to handle concurrent IOVs (usually an ESSource)
134  // and the new sync value is outside the current IOV of that module.
135  // Also at beginRun when forcing caches to clear.
136  auto group = taskToStartAfterIOVInit.group();
137  ServiceWeakToken weakToken = iToken;
138  queueWhichWaitsForIOVsToFinish.push(*group,
139  [iSync, taskToStartAfterIOVInit, asyncEventSetup, weakToken]() mutable {
140  ServiceRegistry::Operate operate(weakToken.lock());
141  asyncEventSetup(iSync, taskToStartAfterIOVInit);
142  });
143  } else {
144  asyncEventSetup(iSync, taskToStartAfterIOVInit);
145  }
146  }
147 
149  IOVSyncValue const& syncValue,
150  WaitingTaskHolder const& taskToStartAfterIOVInit,
151  WaitingTaskList& endIOVWaitingTasks,
152  std::vector<std::shared_ptr<const EventSetupImpl>>& eventSetupImpls) {
154 
155  bool newEventSetupImpl = false;
156  eventSetupImpls.clear();
157  eventSetupImpls.reserve(providers_.size());
158 
159  // Note that unless there are one or more SubProcesses providers_ will only
160  // contain one element.
161 
162  for (auto& eventSetupProvider : providers_) {
163  eventSetupProvider->setAllValidityIntervals(syncValue);
164  }
165 
166  for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
167  // For a particular record, if the top level process or any SubProcess requires
168  // starting a new IOV, then we must start a new IOV for all of them. And we
169  // need to know whether this is needed at this point in time. This is
170  // recorded in the EventSetupRecordProviders.
171  eventSetupRecordIOVQueue->setNewIntervalForAnySubProcess();
172  }
173 
174  for (auto& eventSetupProvider : providers_) {
175  // Decides whether we can reuse the existing EventSetupImpl and if we can
176  // returns it. If a new one is needed it will create it, although the pointers
177  // to the EventSetupRecordImpl's will not be set yet in the returned EventSetupImpl
178  // object.
179  eventSetupImpls.push_back(eventSetupProvider->eventSetupForInstance(syncValue, newEventSetupImpl));
180  }
181 
182  for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
183  eventSetupRecordIOVQueue->checkForNewIOVs(taskToStartAfterIOVInit, endIOVWaitingTasks, newEventSetupImpl);
184  }
185  }
186 
188  if (hasNonconcurrentFinder()) {
189  for (auto& eventSetupProvider : providers_) {
190  if (eventSetupProvider->doWeNeedToWaitForIOVsToFinish(syncValue)) {
191  return true;
192  }
193  }
194  }
195  return false;
196  }
197 
199  for (auto& eventSetupProvider : providers_) {
200  eventSetupProvider->forceCacheClear();
201  }
202  }
203 
204  std::shared_ptr<DataProxyProvider> EventSetupsController::getESProducerAndRegisterProcess(
205  ParameterSet const& pset, unsigned subProcessIndex) {
206  // Try to find a DataProxyProvider with a matching ParameterSet
207  auto elements = esproducers_.equal_range(pset.id());
208  for (auto it = elements.first; it != elements.second; ++it) {
209  // Untracked parameters must also match, do complete comparison if IDs match
210  if (isTransientEqual(pset, *it->second.pset())) {
211  // Register processes with an exact match
212  it->second.subProcessIndexes().push_back(subProcessIndex);
213  // Return the DataProxyProvider
214  return it->second.provider();
215  }
216  }
217  // Could not find it
218  return std::shared_ptr<DataProxyProvider>();
219  }
220 
222  std::shared_ptr<DataProxyProvider> const& component,
223  unsigned subProcessIndex) {
224  auto newElement =
225  esproducers_.insert(std::pair<ParameterSetID, ESProducerInfo>(pset.id(), ESProducerInfo(&pset, component)));
226  // Register processes with an exact match
227  newElement->second.subProcessIndexes().push_back(subProcessIndex);
228  }
229 
230  std::shared_ptr<EventSetupRecordIntervalFinder> EventSetupsController::getESSourceAndRegisterProcess(
231  ParameterSet const& pset, unsigned subProcessIndex) {
232  // Try to find a EventSetupRecordIntervalFinder with a matching ParameterSet
233  auto elements = essources_.equal_range(pset.id());
234  for (auto it = elements.first; it != elements.second; ++it) {
235  // Untracked parameters must also match, do complete comparison if IDs match
236  if (isTransientEqual(pset, *it->second.pset())) {
237  // Register processes with an exact match
238  it->second.subProcessIndexes().push_back(subProcessIndex);
239  // Return the EventSetupRecordIntervalFinder
240  return it->second.finder();
241  }
242  }
243  // Could not find it
244  return std::shared_ptr<EventSetupRecordIntervalFinder>();
245  }
246 
248  std::shared_ptr<EventSetupRecordIntervalFinder> const& component,
249  unsigned subProcessIndex) {
250  auto newElement =
251  essources_.insert(std::pair<ParameterSetID, ESSourceInfo>(pset.id(), ESSourceInfo(&pset, component)));
252  // Register processes with an exact match
253  newElement->second.subProcessIndexes().push_back(subProcessIndex);
254  }
255 
257  esproducers_.clear();
258  essources_.clear();
259  }
260 
262  unsigned subProcessIndex,
263  unsigned precedingProcessIndex,
264  bool& firstProcessWithThisPSet,
265  bool& precedingHasMatchingPSet) const {
266  auto elements = esproducers_.equal_range(psetID);
267  for (auto it = elements.first; it != elements.second; ++it) {
268  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
269 
270  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
271  if (iFound == subProcessIndexes.end()) {
272  continue;
273  }
274 
275  if (iFound == subProcessIndexes.begin()) {
276  firstProcessWithThisPSet = true;
277  precedingHasMatchingPSet = false;
278  } else {
279  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
280  if (iFoundPreceding == iFound) {
281  firstProcessWithThisPSet = false;
282  precedingHasMatchingPSet = false;
283  } else {
284  firstProcessWithThisPSet = false;
285  precedingHasMatchingPSet = true;
286  }
287  }
288  return;
289  }
290  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatches\n"
291  << "Subprocess index not found. This should never happen\n"
292  << "Please report this to a Framework Developer\n";
293  }
294 
296  unsigned subProcessIndex,
297  unsigned precedingProcessIndex) const {
298  auto elements = esproducers_.equal_range(psetID);
299  for (auto it = elements.first; it != elements.second; ++it) {
300  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
301 
302  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
303  if (iFound == subProcessIndexes.end()) {
304  continue;
305  }
306 
307  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
308  if (iFoundPreceding == iFound) {
309  break;
310  } else {
311  return iFoundPreceding == subProcessIndexes.begin();
312  }
313  }
314  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::isFirstMatch\n"
315  << "Subprocess index not found. This should never happen\n"
316  << "Please report this to a Framework Developer\n";
317  return false;
318  }
319 
321  unsigned subProcessIndex,
322  unsigned precedingProcessIndex) const {
323  auto elements = esproducers_.equal_range(psetID);
324  for (auto it = elements.first; it != elements.second; ++it) {
325  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
326 
327  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
328  if (iFound == subProcessIndexes.end()) {
329  continue;
330  }
331 
332  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
333  if (iFoundPreceding == iFound) {
334  break;
335  } else {
336  return (++iFoundPreceding) == iFound;
337  }
338  }
339  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::isLastMatch\n"
340  << "Subprocess index not found. This should never happen\n"
341  << "Please report this to a Framework Developer\n";
342  return false;
343  }
344 
346  unsigned subProcessIndex,
347  unsigned precedingProcessIndex) const {
348  auto elements = essources_.equal_range(psetID);
349  for (auto it = elements.first; it != elements.second; ++it) {
350  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
351 
352  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
353  if (iFound == subProcessIndexes.end()) {
354  continue;
355  }
356 
357  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
358  if (iFoundPreceding == iFound) {
359  return false;
360  } else {
361  return true;
362  }
363  }
364  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatchingESSource\n"
365  << "Subprocess index not found. This should never happen\n"
366  << "Please report this to a Framework Developer\n";
367  return false;
368  }
369 
371  unsigned subProcessIndex,
372  unsigned precedingProcessIndex) const {
373  auto elements = esproducers_.equal_range(psetID);
374  for (auto it = elements.first; it != elements.second; ++it) {
375  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
376 
377  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
378  if (iFound == subProcessIndexes.end()) {
379  continue;
380  }
381 
382  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
383  if (iFoundPreceding == iFound) {
384  return false;
385  } else {
386  return true;
387  }
388  }
389  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatchingESSource\n"
390  << "Subprocess index not found. This should never happen\n"
391  << "Please report this to a Framework Developer\n";
392  return false;
393  }
394 
395  ParameterSet& EventSetupsController::getESProducerPSet(ParameterSetID const& psetID, unsigned subProcessIndex) {
396  auto elements = esproducers_.equal_range(psetID);
397  for (auto it = elements.first; it != elements.second; ++it) {
398  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
399 
400  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
401  if (iFound == subProcessIndexes.end()) {
402  continue;
403  }
404  return *it->second.pset();
405  }
406  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::getESProducerPSet\n"
407  << "Subprocess index not found. This should never happen\n"
408  << "Please report this to a Framework Developer\n";
409  }
410 
412  // Loop over SubProcesses, skip the top level process.
413  auto esProvider = providers_.begin();
414  auto const esProviderEnd = providers_.end();
415  if (esProvider != esProviderEnd)
416  ++esProvider;
417  for (; esProvider != esProviderEnd; ++esProvider) {
418  // An element is added to this set for each ESProducer
419  // when we have determined which preceding process
420  // this process can share that ESProducer with or
421  // we have determined that it cannot be shared with
422  // any preceding process.
423  // Note the earliest possible preceding process
424  // will be the one selected if there is more than one.
425  std::set<ParameterSetIDHolder> sharingCheckDone;
426 
427  // This will hold an entry for DataProxy's that are
428  // referenced by an EventSetupRecord in this SubProcess.
429  // But only for DataProxy's that are associated with
430  // an ESProducer (not the ones associated with ESSource's
431  // or EDLooper's)
432  std::map<EventSetupRecordKey, std::vector<ComponentDescription const*>> referencedESProducers;
433 
434  // For each EventSetupProvider from a SubProcess, loop over the
435  // EventSetupProviders from the preceding processes (the first
436  // preceding process will be the top level process and the others
437  // SubProcess's)
438  for (auto precedingESProvider = providers_.begin(); precedingESProvider != esProvider; ++precedingESProvider) {
439  (*esProvider)
440  ->checkESProducerSharing(
441  typeResolverMaker_, **precedingESProvider, sharingCheckDone, referencedESProducers, *this);
442  }
443 
444  (*esProvider)->resetRecordToProxyPointers();
445  }
446  for (auto& eventSetupProvider : providers_) {
447  eventSetupProvider->clearInitializationData();
448  }
449  }
450 
452  std::set<EventSetupRecordKey> keys;
453  for (auto const& provider : providers_) {
454  provider->fillKeys(keys);
455  }
456 
457  for (auto const& key : keys) {
458  eventSetupRecordIOVQueues_.push_back(
459  std::make_unique<EventSetupRecordIOVQueue>(numberOfConcurrentIOVs_.numberOfConcurrentIOVs(key)));
461  for (auto& provider : providers_) {
462  EventSetupRecordProvider* recProvider = provider->tryToGetRecordProvider(key);
463  if (recProvider) {
464  iovQueue.addRecProvider(recProvider);
465  }
466  }
467  }
468  }
469 
471  oneapi::tbb::task_group& iGroup,
472  eventsetup::EventSetupsController& espController) {
473  FinalWaitingTask waitUntilIOVInitializationCompletes{iGroup};
474 
475  // These do nothing ...
476  WaitingTaskList dummyWaitingTaskList;
477  std::vector<std::shared_ptr<const EventSetupImpl>> dummyEventSetupImpls;
478 
479  {
480  WaitingTaskHolder waitingTaskHolder(iGroup, &waitUntilIOVInitializationCompletes);
481  // Caught exception is propagated via WaitingTaskHolder
482  CMS_SA_ALLOW try {
483  // All the real work is done here.
484  espController.eventSetupForInstanceAsync(
485  syncValue, waitingTaskHolder, dummyWaitingTaskList, dummyEventSetupImpls);
486  dummyWaitingTaskList.doneWaiting(std::exception_ptr{});
487  } catch (...) {
488  dummyWaitingTaskList.doneWaiting(std::exception_ptr{});
489  waitingTaskHolder.doneWaiting(std::current_exception());
490  }
491  }
492  waitUntilIOVInitializationCompletes.wait();
493  }
494  } // namespace eventsetup
495 } // 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_