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 
25 
26 #include <algorithm>
27 #include <iostream>
28 #include <set>
29 
30 namespace edm {
31  namespace eventsetup {
32 
34 
35  std::shared_ptr<EventSetupProvider> EventSetupsController::makeProvider(ParameterSet& iPSet,
36  ActivityRegistry* activityRegistry,
37  ParameterSet const* eventSetupPset) {
38  // Makes an EventSetupProvider
39  // Also parses the prefer information from ParameterSets and puts
40  // it in a map that is stored in the EventSetupProvider
41  std::shared_ptr<EventSetupProvider> returnValue(
42  makeEventSetupProvider(iPSet, providers_.size(), activityRegistry));
43 
44  // Construct the ESProducers and ESSources
45  // shared_ptrs to them are temporarily stored in this
46  // EventSetupsController and in the EventSetupProvider
47  fillEventSetupProvider(*this, *returnValue, iPSet);
48 
50 
51  providers_.push_back(returnValue);
52  return returnValue;
53  }
54 
55  void EventSetupsController::setMaxConcurrentIOVs(unsigned int nStreams, unsigned int nConcurrentLumis) {
56  numberOfConcurrentIOVs_.setMaxConcurrentIOVs(nStreams, nConcurrentLumis);
57  }
58 
61  for (auto& eventSetupProvider : providers_) {
63  }
64 
65  for (auto& eventSetupProvider : providers_) {
66  eventSetupProvider->finishConfiguration(numberOfConcurrentIOVs_, hasNonconcurrentFinder_);
67  }
68 
69  // When the ESSources and ESProducers were constructed a first pass was
70  // done which attempts to get component sharing between SubProcesses
71  // correct, but in this pass only the configuration of the components
72  // being shared are compared. This is not good enough for ESProducers.
73  // In the following function, all the other components that contribute
74  // to the same record and also the records that record depends on are
75  // also checked. The component sharing is appropriately fixed as necessary.
78 
82  }
83  }
84 
86  IOVSyncValue const& syncValue,
87  WaitingTaskHolder const& taskToStartAfterIOVInit,
88  WaitingTaskList& endIOVWaitingTasks,
89  std::vector<std::shared_ptr<const EventSetupImpl>>& eventSetupImpls) {
91 
92  bool newEventSetupImpl = false;
93  eventSetupImpls.clear();
94  eventSetupImpls.reserve(providers_.size());
95 
96  // Note that unless there are one or more SubProcesses providers_ will only
97  // contain one element.
98 
99  for (auto& eventSetupProvider : providers_) {
100  eventSetupProvider->setAllValidityIntervals(syncValue);
101  }
102 
103  for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
104  // For a particular record, if the top level process or any SubProcess requires
105  // starting a new IOV, then we must start a new IOV for all of them. And we
106  // need to know whether this is needed at this point in time. This is
107  // recorded in the EventSetupRecordProviders.
108  eventSetupRecordIOVQueue->setNewIntervalForAnySubProcess();
109  }
110 
111  for (auto& eventSetupProvider : providers_) {
112  // Decides whether we can reuse the existing EventSetupImpl and if we can
113  // returns it. If a new one is needed it will create it, although the pointers
114  // to the EventSetupRecordImpl's will not be set yet in the returned EventSetupImpl
115  // object.
116  eventSetupImpls.push_back(eventSetupProvider->eventSetupForInstance(syncValue, newEventSetupImpl));
117  }
118 
119  for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
120  eventSetupRecordIOVQueue->checkForNewIOVs(taskToStartAfterIOVInit, endIOVWaitingTasks, newEventSetupImpl);
121  }
122  }
123 
125  // This function only supports use cases where the event setup
126  // system is used without multiple concurrent IOVs.
127  // At the time this comment is being written, this is used for
128  // run transitions and in unit test code. In the future,
129  // it may only be needed for unit tests. This function uses
130  // the other version of eventSetupForInstance that
131  // supports concurrent IOVs. To get this to work, a couple
132  // arguments to that function need dummy objects that do
133  // not serve any purpose in this context. We also need to
134  // add in a task to wait for the asynchronous initialization
135  // of IOVs to complete.
136 
137  auto waitUntilIOVInitializationCompletes = make_empty_waiting_task();
138  waitUntilIOVInitializationCompletes->increment_ref_count();
139 
140  // These do nothing ...
141  WaitingTaskList dummyWaitingTaskList;
142  std::vector<std::shared_ptr<const EventSetupImpl>> dummyEventSetupImpls;
143 
144  {
145  WaitingTaskHolder waitingTaskHolder(waitUntilIOVInitializationCompletes.get());
146 
147  try {
148  // All the real work is done here.
149  eventSetupForInstance(syncValue, waitingTaskHolder, dummyWaitingTaskList, dummyEventSetupImpls);
150  dummyWaitingTaskList.doneWaiting(std::exception_ptr{});
151  } catch (...) {
152  dummyWaitingTaskList.doneWaiting(std::exception_ptr{});
153  waitingTaskHolder.doneWaiting(std::current_exception());
154  }
155  }
156  waitUntilIOVInitializationCompletes->wait_for_all();
157 
158  if (waitUntilIOVInitializationCompletes->exceptionPtr() != nullptr) {
159  std::rethrow_exception(*(waitUntilIOVInitializationCompletes->exceptionPtr()));
160  }
161  }
162 
164  if (hasNonconcurrentFinder()) {
165  for (auto& eventSetupProvider : providers_) {
166  if (eventSetupProvider->doWeNeedToWaitForIOVsToFinish(syncValue)) {
167  return true;
168  }
169  }
170  }
171  return false;
172  }
173 
175  for (auto& eventSetupProvider : providers_) {
176  eventSetupProvider->forceCacheClear();
177  }
178  }
179 
180  std::shared_ptr<DataProxyProvider> EventSetupsController::getESProducerAndRegisterProcess(
181  ParameterSet const& pset, unsigned subProcessIndex) {
182  // Try to find a DataProxyProvider with a matching ParameterSet
183  auto elements = esproducers_.equal_range(pset.id());
184  for (auto it = elements.first; it != elements.second; ++it) {
185  // Untracked parameters must also match, do complete comparison if IDs match
186  if (isTransientEqual(pset, *it->second.pset())) {
187  // Register processes with an exact match
188  it->second.subProcessIndexes().push_back(subProcessIndex);
189  // Return the DataProxyProvider
190  return it->second.provider();
191  }
192  }
193  // Could not find it
194  return std::shared_ptr<DataProxyProvider>();
195  }
196 
198  std::shared_ptr<DataProxyProvider> const& component,
199  unsigned subProcessIndex) {
200  auto newElement =
201  esproducers_.insert(std::pair<ParameterSetID, ESProducerInfo>(pset.id(), ESProducerInfo(&pset, component)));
202  // Register processes with an exact match
203  newElement->second.subProcessIndexes().push_back(subProcessIndex);
204  }
205 
206  std::shared_ptr<EventSetupRecordIntervalFinder> EventSetupsController::getESSourceAndRegisterProcess(
207  ParameterSet const& pset, unsigned subProcessIndex) {
208  // Try to find a EventSetupRecordIntervalFinder with a matching ParameterSet
209  auto elements = essources_.equal_range(pset.id());
210  for (auto it = elements.first; it != elements.second; ++it) {
211  // Untracked parameters must also match, do complete comparison if IDs match
212  if (isTransientEqual(pset, *it->second.pset())) {
213  // Register processes with an exact match
214  it->second.subProcessIndexes().push_back(subProcessIndex);
215  // Return the EventSetupRecordIntervalFinder
216  return it->second.finder();
217  }
218  }
219  // Could not find it
220  return std::shared_ptr<EventSetupRecordIntervalFinder>();
221  }
222 
224  std::shared_ptr<EventSetupRecordIntervalFinder> const& component,
225  unsigned subProcessIndex) {
226  auto newElement =
227  essources_.insert(std::pair<ParameterSetID, ESSourceInfo>(pset.id(), ESSourceInfo(&pset, component)));
228  // Register processes with an exact match
229  newElement->second.subProcessIndexes().push_back(subProcessIndex);
230  }
231 
233  esproducers_.clear();
234  essources_.clear();
235  }
236 
238  unsigned subProcessIndex,
239  unsigned precedingProcessIndex,
240  bool& firstProcessWithThisPSet,
241  bool& precedingHasMatchingPSet) const {
242  auto elements = esproducers_.equal_range(psetID);
243  for (auto it = elements.first; it != elements.second; ++it) {
244  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
245 
246  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
247  if (iFound == subProcessIndexes.end()) {
248  continue;
249  }
250 
251  if (iFound == subProcessIndexes.begin()) {
252  firstProcessWithThisPSet = true;
253  precedingHasMatchingPSet = false;
254  } else {
255  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
256  if (iFoundPreceding == iFound) {
257  firstProcessWithThisPSet = false;
258  precedingHasMatchingPSet = false;
259  } else {
260  firstProcessWithThisPSet = false;
261  precedingHasMatchingPSet = true;
262  }
263  }
264  return;
265  }
266  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatches\n"
267  << "Subprocess index not found. This should never happen\n"
268  << "Please report this to a Framework Developer\n";
269  }
270 
272  unsigned subProcessIndex,
273  unsigned precedingProcessIndex) const {
274  auto elements = esproducers_.equal_range(psetID);
275  for (auto it = elements.first; it != elements.second; ++it) {
276  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
277 
278  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
279  if (iFound == subProcessIndexes.end()) {
280  continue;
281  }
282 
283  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
284  if (iFoundPreceding == iFound) {
285  break;
286  } else {
287  return iFoundPreceding == subProcessIndexes.begin();
288  }
289  }
290  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::isFirstMatch\n"
291  << "Subprocess index not found. This should never happen\n"
292  << "Please report this to a Framework Developer\n";
293  return false;
294  }
295 
297  unsigned subProcessIndex,
298  unsigned precedingProcessIndex) const {
299  auto elements = esproducers_.equal_range(psetID);
300  for (auto it = elements.first; it != elements.second; ++it) {
301  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
302 
303  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
304  if (iFound == subProcessIndexes.end()) {
305  continue;
306  }
307 
308  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
309  if (iFoundPreceding == iFound) {
310  break;
311  } else {
312  return (++iFoundPreceding) == iFound;
313  }
314  }
315  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::isLastMatch\n"
316  << "Subprocess index not found. This should never happen\n"
317  << "Please report this to a Framework Developer\n";
318  return false;
319  }
320 
322  unsigned subProcessIndex,
323  unsigned precedingProcessIndex) const {
324  auto elements = essources_.equal_range(psetID);
325  for (auto it = elements.first; it != elements.second; ++it) {
326  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
327 
328  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
329  if (iFound == subProcessIndexes.end()) {
330  continue;
331  }
332 
333  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
334  if (iFoundPreceding == iFound) {
335  return false;
336  } else {
337  return true;
338  }
339  }
340  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatchingESSource\n"
341  << "Subprocess index not found. This should never happen\n"
342  << "Please report this to a Framework Developer\n";
343  return false;
344  }
345 
347  unsigned subProcessIndex,
348  unsigned precedingProcessIndex) const {
349  auto elements = esproducers_.equal_range(psetID);
350  for (auto it = elements.first; it != elements.second; ++it) {
351  std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
352 
353  auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
354  if (iFound == subProcessIndexes.end()) {
355  continue;
356  }
357 
358  auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
359  if (iFoundPreceding == iFound) {
360  return false;
361  } else {
362  return true;
363  }
364  }
365  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatchingESSource\n"
366  << "Subprocess index not found. This should never happen\n"
367  << "Please report this to a Framework Developer\n";
368  return false;
369  }
370 
372  unsigned subProcessIndex) 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  return it->second.pset();
382  }
383  throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::getESProducerPSet\n"
384  << "Subprocess index not found. This should never happen\n"
385  << "Please report this to a Framework Developer\n";
386  return nullptr;
387  }
388 
390  // Loop over SubProcesses, skip the top level process.
391  auto esProvider = providers_.begin();
392  auto const esProviderEnd = providers_.end();
393  if (esProvider != esProviderEnd)
394  ++esProvider;
395  for (; esProvider != esProviderEnd; ++esProvider) {
396  // An element is added to this set for each ESProducer
397  // when we have determined which preceding process
398  // this process can share that ESProducer with or
399  // we have determined that it cannot be shared with
400  // any preceding process.
401  // Note the earliest possible preceding process
402  // will be the one selected if there is more than one.
403  std::set<ParameterSetIDHolder> sharingCheckDone;
404 
405  // This will hold an entry for DataProxy's that are
406  // referenced by an EventSetupRecord in this SubProcess.
407  // But only for DataProxy's that are associated with
408  // an ESProducer (not the ones associated with ESSource's
409  // or EDLooper's)
410  std::map<EventSetupRecordKey, std::vector<ComponentDescription const*>> referencedESProducers;
411 
412  // For each EventSetupProvider from a SubProcess, loop over the
413  // EventSetupProviders from the preceding processes (the first
414  // preceding process will be the top level process and the others
415  // SubProcess's)
416  for (auto precedingESProvider = providers_.begin(); precedingESProvider != esProvider; ++precedingESProvider) {
417  (*esProvider)->checkESProducerSharing(**precedingESProvider, sharingCheckDone, referencedESProducers, *this);
418  }
419 
420  (*esProvider)->resetRecordToProxyPointers();
421  }
422  for (auto& eventSetupProvider : providers_) {
423  eventSetupProvider->clearInitializationData();
424  }
425  }
426 
428  std::set<EventSetupRecordKey> keys;
429  for (auto const& provider : providers_) {
430  provider->fillKeys(keys);
431  }
432 
433  for (auto const& key : keys) {
434  eventSetupRecordIOVQueues_.push_back(
435  std::make_unique<EventSetupRecordIOVQueue>(numberOfConcurrentIOVs_.numberOfConcurrentIOVs(key)));
437  for (auto& provider : providers_) {
438  EventSetupRecordProvider* recProvider = provider->tryToGetRecordProvider(key);
439  if (recProvider) {
440  iovQueue.addRecProvider(recProvider);
441  }
442  }
443  }
444  }
445 
446  } // namespace eventsetup
447 } // namespace edm
void lookForMatches(ParameterSetID const &psetID, unsigned subProcessIndex, unsigned precedingProcessIndex, bool &firstProcessWithThisPSet, bool &precedingHasMatchingPSet) const
std::shared_ptr< EventSetupRecordIntervalFinder > getESSourceAndRegisterProcess(ParameterSet const &pset, unsigned subProcessIndex)
bool isFirstMatch(ParameterSetID const &psetID, unsigned subProcessIndex, unsigned precedingProcessIndex) const
void addRecProvider(EventSetupRecordProvider *recProvider)
bool isMatchingESProducer(ParameterSetID const &psetID, unsigned subProcessIndex, unsigned precedingProcessIndex) const
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
ParameterSetID id() const
void putESProducer(ParameterSet const &pset, std::shared_ptr< DataProxyProvider > const &component, unsigned subProcessIndex)
std::multimap< ParameterSetID, ESProducerInfo > esproducers_
bool isLastMatch(ParameterSetID const &psetID, unsigned subProcessIndex, unsigned precedingProcessIndex) const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
ParameterSet const * getESProducerPSet(ParameterSetID const &psetID, unsigned subProcessIndex) const
void setMaxConcurrentIOVs(unsigned int nStreams, unsigned int nConcurrentLumis)
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 fillRecordsNotAllowingConcurrentIOVs(EventSetupProvider const &)
std::unique_ptr< edm::EmptyWaitingTask, waitingtask::TaskDestroyer > make_empty_waiting_task()
Create an EmptyWaitingTask which will properly be destroyed.
std::multimap< ParameterSetID, ESSourceInfo > essources_
bool doWeNeedToWaitForIOVsToFinish(IOVSyncValue const &) const
unsigned int numberOfConcurrentIOVs(EventSetupRecordKey const &, bool printInfoMsg=false) const
void eventSetupForInstance(IOVSyncValue const &, WaitingTaskHolder const &taskToStartAfterIOVInit, WaitingTaskList &endIOVWaitingTasks, std::vector< std::shared_ptr< const EventSetupImpl >> &)
std::shared_ptr< EventSetupProvider > makeProvider(ParameterSet &, ActivityRegistry *, ParameterSet const *eventSetupPset=nullptr)
HLT enums.
std::unique_ptr< EventSetupProvider > makeEventSetupProvider(ParameterSet const &params, unsigned subProcessIndex, ActivityRegistry *)
bool isMatchingESSource(ParameterSetID const &psetID, unsigned subProcessIndex, unsigned precedingProcessIndex) const
void readConfigurationParameters(ParameterSet const *eventSetupPset)
std::vector< propagate_const< std::shared_ptr< EventSetupProvider > > > providers_
bool isTransientEqual(ParameterSet const &a, ParameterSet const &b)
void setMaxConcurrentIOVs(unsigned int nStreams, unsigned int nConcurrentLumis)