CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
TransientProductLookupMap.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Provenance
4 // Class : TransientProductLookupMap
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Original Author: Chris Jones
10 // Created: Fri May 1 12:17:12 CDT 2009
11 //
12 
13 // system include files
14 #include <algorithm>
15 
16 // user include files
20 
21 //
22 // constants, enums and typedefs
23 //
24 
25 //
26 // static data member definitions
27 //
28 
29 namespace edm {
30  bool CompareTypeInBranchTypeConstBranchDescription::operator()(std::pair<TypeInBranchType, ConstBranchDescription const*> const& iLHS,
31  std::pair<TypeInBranchType, ConstBranchDescription const*> const& iRHS) const {
32  if(iLHS.first < iRHS.first) {
33  return true;
34  }
35  if(iRHS.first < iLHS.first) {
36  return false;
37  }
38 
39  int c = iLHS.second->moduleLabel().compare(iRHS.second->moduleLabel());
40  if(c < 0) {
41  return true;
42  }
43  if(c > 0) {
44  return false;
45  }
46  c = iLHS.second->productInstanceName().compare(iRHS.second->productInstanceName());
47  if(c < 0) {
48  return true;
49  }
50  if(c > 0) {
51  return false;
52  }
53 
54  return iLHS.second->processName() < iRHS.second->processName();
55  }
56 
57  //
58  // constructors and destructor
59  //
61  branchLookup_(),
62  productLookupIndexList_(),
63  historyIDsForBranchType_(static_cast<unsigned int>(NumBranchTypes), ProcessHistoryID()),
64  processNameOrderingForBranchType_(static_cast<unsigned int>(NumBranchTypes), std::vector<std::string>()),
65  fillCount_(0) {
66  }
67 
68  // TransientProductLookupMap::TransientProductLookupMap(TransientProductLookupMap const& rhs) {
69  // // do actual copying here;
70  // }
71 
72  //TransientProductLookupMap::~TransientProductLookupMap() {
73  //}
74 
75  void
77  branchLookup_.clear();
79  for (unsigned int i = 0; i < static_cast<unsigned int>(NumBranchTypes); ++i) {
80  historyIDsForBranchType_[i].reset();
82  }
83  fillCount_ = 0;
84  }
85 
86  //
87  // assignment operators
88  //
89  // TransientProductLookupMap const& TransientProductLookupMap::operator=(TransientProductLookupMap const& rhs) {
90  // //An exception safe implementation is
91  // TransientProductLookupMap temp(rhs);
92  // swap(rhs);
93  //
94  // return *this;
95  // }
96 
97  //
98  // member functions
99  //
100  namespace {
101 
102  struct CompareModuleLabelAndProductInstanceName {
103  typedef std::pair<std::string const*, std::string const*> StringPtrPair;
104  bool operator()(StringPtrPair const& iLHS, StringPtrPair const& iRHS) const {
105  int c = iLHS.first->compare(*iRHS.first);
106  if (c < 0) return true;
107  if (c > 0) return false;
108  return(*iLHS.second < *iRHS.second);
109  }
110  bool operator()(ProductLookupIndex const& iLHS, StringPtrPair const& iRHS) const {
111  int c = iLHS.branchDescription()->moduleLabel().compare(*iRHS.first);
112  if (c < 0) return true;
113  if (c > 0) return false;
114  return(iLHS.branchDescription()->productInstanceName() < *iRHS.second);
115  }
116  bool operator()(StringPtrPair const& iLHS, ProductLookupIndex const& iRHS) const {
117  int c = iLHS.first->compare(iRHS.branchDescription()->moduleLabel());
118  if (c < 0) return true;
119  if (c > 0) return false;
120  return(*iLHS.second < iRHS.branchDescription()->productInstanceName());
121  }
122  bool operator()(ProductLookupIndex const& iLHS, ProductLookupIndex const& iRHS) const {
123  int c = iLHS.branchDescription()->moduleLabel().compare(iRHS.branchDescription()->moduleLabel());
124  if (c < 0) return true;
125  if (c > 0) return false;
126  return(iLHS.branchDescription()->productInstanceName() < iRHS.branchDescription()->productInstanceName());
127  }
128  };
129 
130  struct BranchTypeOnlyCompare {
131  bool operator()(std::pair<TypeInBranchType, BranchDescriptionIndex> const& iLHS, std::pair<TypeInBranchType, BranchDescriptionIndex> const& iRHS) const {
132  return iLHS.first.branchType() < iRHS.first.branchType();
133  }
134  };
135 
136  struct CompareProcessList {
137  std::vector<std::string> const* list_;
138 
139  CompareProcessList(std::vector<std::string> const* iList) : list_(iList) {}
140 
141  bool operator()(ProductLookupIndex const& iLHS, ProductLookupIndex const& iRHS) const {
142  std::string const& lhs = iLHS.branchDescription()->processName();
143  std::string const& rhs = iRHS.branchDescription()->processName();
144  if(lhs == rhs) {return false;}
145  //NOTE: names in the vector are oldest to newest and we want to order by newest
146  for(std::vector<std::string>::const_reverse_iterator it = list_->rbegin(), itEnd = list_->rend();
147  it != itEnd;
148  ++it){
149  if(*it == lhs) {return true;}
150  if(*it == rhs) { return false;}
151  }
152  return false;
153  }
154  };
155  }
156 
157  static
158  void
159  fillInProcessIndexes(TransientProductLookupMap::ProductLookupIndexList::iterator iIt,
160  TransientProductLookupMap::ProductLookupIndexList::iterator iEnd,
161  std::vector<std::string> const& iNameOrder) {
162  //NOTE the iterators are already in the same order as iNameOrder
163  std::vector<std::string>::const_reverse_iterator itNO = iNameOrder.rbegin();
164  unsigned int index = 0;
165  for(; iIt != iEnd; ++iIt) {
166  if(iIt->isFirst()) {
167  itNO = iNameOrder.rbegin();
168  index = 0;
169  }
170  while(*itNO != iIt->branchDescription()->processName()) {
171  ++itNO;
172  assert(itNO != iNameOrder.rend());
173  ++index;
174  }
175  iIt->setProcessIndex(index);
176  }
177  }
178 
179  void
180  TransientProductLookupMap::reorderIfNecessary(BranchType iBranch, ProcessHistory const& iHistory, std::string const& iNewProcessName) {
181 
182  ProcessHistoryID& historyID = historyIDsForBranchType_[iBranch];
183  if(iHistory.id() == historyID) {
184  //std::cout <<"no reordering since history unchanged"<<std::endl;
185  return;
186  }
187 
188  if(iHistory.empty()) {
189  //std::cout <<"no reordering since history empty"<<std::endl;
190  historyID = iHistory.id();
191  return;
192  }
193  std::vector<std::string>& processNameOrdering = processNameOrderingForBranchType_[iBranch];
194 
195  //iHistory may be missing entries in processNameOrdering if two files were merged together and one file
196  // had fewer processing steps than the other one.
197  //iHistory may have more entries than processNameOrdering if all data products for those extra entries
198  // were dropped
199 
200  //if iHistory already in same order as processNameOrdering than we don't have to do anything
201  std::vector<std::string>::iterator it = processNameOrdering.begin();
202  std::vector<std::string>::iterator itEnd = processNameOrdering.end();
203  ProcessHistory::const_iterator itH = iHistory.begin();
204  ProcessHistory::const_iterator itHEnd = iHistory.end();
205 
206  {
207  std::vector<std::string>::iterator itStart = it;
208  bool mustReorder = false;
209  while(it != itEnd && itH != itHEnd) {
210  if(*it == itH->processName()) {
211  ++it;
212  } else {
213  //see if we already passed it
214  for(std::vector<std::string>::iterator itOld = itStart; itOld != it; ++itOld) {
215  if(*itOld == itH->processName()) {
216  mustReorder = true;
217  break;
218  }
219  }
220  if(mustReorder) {
221  break;
222  }
223  }
224  ++itH;
225  }
226  if(!mustReorder && it != itEnd && *it == iNewProcessName) {
227  ++it;
228  }
229  //can only reach the end if we found all the items in the correct order
230  if(it == itEnd) {
231  return;
232  }
233  }
234 
235  //must re-sort
236  //Increment the fill count so users can check if the map has been modified.
237  ++fillCount_;
238  historyID = iHistory.id();
239  std::vector<std::string> temp(processNameOrdering.size(), std::string());
240 
241  //we want to add the items at the back
242  std::vector<std::string>::reverse_iterator itR = temp.rbegin();
243  std::vector<std::string>::reverse_iterator itREnd = temp.rend();
245  ProcessHistory::const_reverse_iterator itRHEnd = iHistory.rend();
246 
247  if(processNameOrdering.end() != std::find(processNameOrdering.begin(), processNameOrdering.end(), iNewProcessName)) {
248  *itR = iNewProcessName;
249  ++itR;
250  if (iNewProcessName == itRH->processName()) {
251  ++itRH;
252  }
253  }
254  for(; itRH != itRHEnd; ++itRH) {
255  if(processNameOrdering.end() != std::find(processNameOrdering.begin(), processNameOrdering.end(), itRH->processName())) {
256 
257  *itR = itRH->processName();
258  ++itR;
259  }
260  }
261 
262  //have to fill in the missing processes from processNameOrdering_
263  // we do this at the beginning because we lookup data in the reverse order
264  // so we want the ones we know are there to be searched first
265  std::vector<std::string>::iterator itOld = processNameOrdering.begin();
266  it = temp.begin();
267  std::vector<std::string>::iterator itStart = temp.begin()+(itREnd - itR);
268  while(it != itStart) {
269  assert(itOld != processNameOrdering.end());
270  if(temp.end() == std::find(itStart, temp.end(), *itOld)) {
271  //didn't find it so need to add this to our list
272  *it = *itOld;
273  ++it;
274  }
275  ++itOld;
276  }
277 
278  processNameOrdering.swap(temp);
279 
280  //now we need to go through our data structure and change the processing orders
281  //first find the range for this BranchType
282  std::pair<TypeInBranchTypeLookup::iterator, TypeInBranchTypeLookup::iterator> branchRange =
283  std::equal_range(branchLookup_.begin(), branchLookup_.end(), std::make_pair(TypeInBranchType(TypeID(), iBranch), BranchDescriptionIndex(0)), BranchTypeOnlyCompare());
284 
285  if(branchRange.first == branchRange.second) {
286  return;
287  }
288  //convert this into Index iterators since that is the structure we must reorder
289  ProductLookupIndexList::iterator itIndex = productLookupIndexList_.begin() + branchRange.first->second;
290  ProductLookupIndexList::iterator itIndexEnd = productLookupIndexList_.end();
291  if(branchRange.second != branchLookup_.end()) {
292  itIndexEnd = productLookupIndexList_.begin() + branchRange.second->second;
293  }
294 
295  while(itIndex != itIndexEnd) {
296  itIndex->setIsFirst(false);
297  ProductLookupIndexList::iterator itNext = itIndex;
298  while(itNext != itIndexEnd && !itNext->isFirst()) {
299  ++itNext;
300  }
301  std::sort(itIndex, itNext, CompareProcessList(&processNameOrdering));
302  itIndex->setIsFirst(true);
303  itIndex = itNext;
304  }
305 
306  //Now that we know all the IDs time to set the values
307  fillInProcessIndexes(productLookupIndexList_.begin() + branchRange.first->second, itIndexEnd, processNameOrdering);
308 
309  }
310 
311  void
313 
315 
316  //Increment the fill count so users can check if the map has been modified.
317  ++fillCount_;
318 
319  productLookupIndexList_.clear();
320  productLookupIndexList_.reserve(iMap.size());
321  branchLookup_.clear();
322  branchLookup_.reserve(iMap.size()); //this is an upperbound
323 
324  std::set<std::string, std::greater<std::string> > processNames;
326 
327  //since the actual strings are stored elsewhere, there is no reason to make a copy
328  static std::string const kEmpty;
329  std::string const* lastSeenModule = &kEmpty;
330  std::string const* lastSeenProductInstance = &kEmpty;
331  for(FillFromMap::const_iterator it = iMap.begin(), itEnd = iMap.end();
332  it != itEnd;
333  ++it) {
334  bool isFirst = ((lastSeen < it->first.first) || (it->first.first < lastSeen));
335  if(isFirst) {
336  lastSeen = it->first.first;
337  branchLookup_.push_back(std::make_pair(lastSeen, BranchDescriptionIndex(productLookupIndexList_.size())));
338  } else {
339  //see if this is the first of a group that only differ by ProcessName
340  isFirst = (*lastSeenModule != it->first.second->moduleLabel() ||
341  *lastSeenProductInstance != it->first.second->productInstanceName());
342  }
343  productLookupIndexList_.push_back(ProductLookupIndex(it->first.second,
344  it->second,
345  0,
346  isFirst)
347  );
348  if(isFirst) {
349  lastSeenModule = &(it->first.second->moduleLabel());
350  lastSeenProductInstance = &(it->first.second->productInstanceName());
351  }
352  processNames.insert(it->first.second->processName());
353  }
354 
355  std::vector<ProcessHistoryID>::iterator itPH = historyIDsForBranchType_.begin();
356  std::vector<ProcessHistoryID>::iterator itPHEnd = historyIDsForBranchType_.end();
357 
358  std::vector<std::vector<std::string> >::iterator itPN = processNameOrderingForBranchType_.begin();
359  //std::vector<std::vector<std::string> >::iterator itPNEnd = processNameOrderingForBranchType_.end();
360 
361  for(;itPH != itPHEnd; ++itPH, ++itPN) {
362  *itPH = ProcessHistoryID();
363  itPN->assign(processNames.begin(), processNames.end());
364  }
365 
366  //Now that we know all the IDs time to set the values
368  }
369 
370  //
371  // const member functions
372  //
373  namespace {
374  struct CompareFirst {
377  return iLHS.first < iRHS.first;
378  }
379  };
380  }
381 
382  std::pair<TransientProductLookupMap::const_iterator, TransientProductLookupMap::const_iterator>
384  TypeInBranchTypeLookup::const_iterator itFind = std::lower_bound(branchLookup_.begin(),
385  branchLookup_.end(),
386  std::make_pair(iKey, BranchDescriptionIndex(0)),
387  CompareFirst());
388  if(itFind == branchLookup_.end() || iKey < itFind->first) {
389  return std::make_pair(productLookupIndexList_.end(), productLookupIndexList_.end());
390  }
391  const_iterator itStart = productLookupIndexList_.begin() + itFind->second;
393  if(++itFind != branchLookup_.end()) {
394  itEnd = productLookupIndexList_.begin() + itFind->second;
395  }
396  return std::make_pair(itStart, itEnd);
397  }
398 
399  std::pair<TransientProductLookupMap::const_iterator, TransientProductLookupMap::const_iterator>
401  std::string const& moduleLabel,
402  std::string const& productInstanceName) const {
403  std::pair<const_iterator, const_iterator> itPair = this->equal_range(iKey);
404 
405  if (itPair.first == itPair.second) {
406  return itPair;
407  }
408 
409  // Advance lower bound only
410  itPair.first = std::lower_bound(itPair.first, itPair.second, std::make_pair(&moduleLabel, &productInstanceName), CompareModuleLabelAndProductInstanceName());
411  // Protect against no match
412  if (!(itPair.first < itPair.second) ||
413  itPair.first->branchDescription()->moduleLabel() != moduleLabel ||
414  itPair.first->branchDescription()->productInstanceName() != productInstanceName) {
415  itPair.second = itPair.first;
416  }
417  return itPair;
418  }
419 
420  //
421  // static member functions
422  //
423 }
const_reverse_iterator rbegin() const
collection_type::const_iterator const_iterator
const_iterator begin() const
int i
Definition: DBlmapReader.cc:9
collection_type::const_reverse_iterator const_reverse_iterator
bool isFirst(HepMC::GenParticle *x)
Definition: Hash.h:41
void reorderIfNecessary(BranchType, ProcessHistory const &, std::string const &iNewProcessName)
reorders the ProductLookupIndexes for the BranchType based on the processing ordering ...
ProductLookupIndexList productLookupIndexList_
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
BranchType
Definition: BranchType.h:11
ProductLookupIndexList::const_iterator const_iterator
const_reverse_iterator rend() const
std::vector< ProcessHistoryID > historyIDsForBranchType_
Container::value_type value_type
bool empty() const
std::vector< std::vector< std::string > > processNameOrderingForBranchType_
Hash< ProcessHistoryType > ProcessHistoryID
static void fillInProcessIndexes(TransientProductLookupMap::ProductLookupIndexList::iterator iIt, TransientProductLookupMap::ProductLookupIndexList::iterator iEnd, std::vector< std::string > const &iNameOrder)
bool operator()(std::pair< TypeInBranchType, ConstBranchDescription const * > const &iLHS, std::pair< TypeInBranchType, ConstBranchDescription const * > const &iRHS) const
std::pair< const_iterator, const_iterator > equal_range(TypeInBranchType const &) const
returns a pair of iterators that define the range for items matching the TypeInBranchType ...
const_iterator end() const
ProcessHistoryID id() const
std::map< std::pair< TypeInBranchType, ConstBranchDescription const * >, ProductTransientIndex, CompareTypeInBranchTypeConstBranchDescription > FillFromMap
unsigned int BranchDescriptionIndex