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 
242  //we want to add the items at the back
243  std::vector<std::string>::reverse_iterator itR = temp.rbegin();
244  std::vector<std::string>::reverse_iterator itREnd = temp.rend();
246  ProcessHistory::const_reverse_iterator itRHEnd = iHistory.rend();
247 
248  if(processNameOrdering.end() != std::find(processNameOrdering.begin(), processNameOrdering.end(), iNewProcessName)) {
249  *itR = iNewProcessName;
250  ++itR;
251  if (iNewProcessName == itRH->processName()) {
252  ++itRH;
253  }
254  }
255  for(; itRH != itRHEnd; ++itRH) {
256  if(processNameOrdering.end() != std::find(processNameOrdering.begin(), processNameOrdering.end(), itRH->processName())) {
257 
258  *itR = itRH->processName();
259  ++itR;
260  }
261  }
262 
263  //have to fill in the missing processes from processNameOrdering_
264  // we do this at the beginning because we lookup data in the reverse order
265  // so we want the ones we know are there to be searched first
266  std::vector<std::string>::iterator itOld = processNameOrdering.begin();
267  it = temp.begin();
268  std::vector<std::string>::iterator itStart = temp.begin()+(itREnd - itR);
269  while(it != itStart) {
270  assert(itOld != processNameOrdering.end());
271  if(temp.end() == std::find(itStart, temp.end(), *itOld)) {
272  //didn't find it so need to add this to our list
273  *it = *itOld;
274  ++it;
275  }
276  ++itOld;
277  }
278 
279  processNameOrdering.swap(temp);
280 
281  //now we need to go through our data structure and change the processing orders
282  //first find the range for this BranchType
283  std::pair<TypeInBranchTypeLookup::iterator, TypeInBranchTypeLookup::iterator> branchRange =
284  std::equal_range(branchLookup_.begin(), branchLookup_.end(), std::make_pair(TypeInBranchType(TypeID(), iBranch), BranchDescriptionIndex(0)), BranchTypeOnlyCompare());
285 
286  if(branchRange.first == branchRange.second) {
287  return;
288  }
289  //convert this into Index iterators since that is the structure we must reorder
290  ProductLookupIndexList::iterator itIndex = productLookupIndexList_.begin() + branchRange.first->second;
291  ProductLookupIndexList::iterator itIndexEnd = productLookupIndexList_.end();
292  if(branchRange.second != branchLookup_.end()) {
293  itIndexEnd = productLookupIndexList_.begin() + branchRange.second->second;
294  }
295 
296  while(itIndex != itIndexEnd) {
297  itIndex->setIsFirst(false);
298  ProductLookupIndexList::iterator itNext = itIndex;
299  while(itNext != itIndexEnd && !itNext->isFirst()) {
300  ++itNext;
301  }
302  std::sort(itIndex, itNext, CompareProcessList(&processNameOrdering));
303  itIndex->setIsFirst(true);
304  itIndex = itNext;
305  }
306 
307  //Now that we know all the IDs time to set the values
308  fillInProcessIndexes(productLookupIndexList_.begin() + branchRange.first->second, itIndexEnd, processNameOrdering);
309 
310  }
311 
312  void
314 
316 
317  //Increment the fill count so users can check if the map has been modified.
318  ++fillCount_;
319 
320  productLookupIndexList_.clear();
321  productLookupIndexList_.reserve(iMap.size());
322  branchLookup_.clear();
323  branchLookup_.reserve(iMap.size()); //this is an upperbound
324 
325  std::set<std::string, std::greater<std::string> > processNames;
327 
328  //since the actual strings are stored elsewhere, there is no reason to make a copy
329  static std::string const kEmpty;
330  std::string const* lastSeenModule = &kEmpty;
331  std::string const* lastSeenProductInstance = &kEmpty;
332  for(FillFromMap::const_iterator it = iMap.begin(), itEnd = iMap.end();
333  it != itEnd;
334  ++it) {
335  bool isFirst = ((lastSeen < it->first.first) || (it->first.first < lastSeen));
336  if(isFirst) {
337  lastSeen = it->first.first;
338  branchLookup_.push_back(std::make_pair(lastSeen, BranchDescriptionIndex(productLookupIndexList_.size())));
339  } else {
340  //see if this is the first of a group that only differ by ProcessName
341  isFirst = (*lastSeenModule != it->first.second->moduleLabel() ||
342  *lastSeenProductInstance != it->first.second->productInstanceName());
343  }
344  productLookupIndexList_.push_back(ProductLookupIndex(it->first.second,
345  it->second,
346  0,
347  isFirst)
348  );
349  if(isFirst) {
350  lastSeenModule = &(it->first.second->moduleLabel());
351  lastSeenProductInstance = &(it->first.second->productInstanceName());
352  }
353  processNames.insert(it->first.second->processName());
354  }
355 
356  std::vector<ProcessHistoryID>::iterator itPH = historyIDsForBranchType_.begin();
357  std::vector<ProcessHistoryID>::iterator itPHEnd = historyIDsForBranchType_.end();
358 
359  std::vector<std::vector<std::string> >::iterator itPN = processNameOrderingForBranchType_.begin();
360  std::vector<std::vector<std::string> >::iterator itPNEnd = processNameOrderingForBranchType_.end();
361 
362  for(;itPH != itPHEnd; ++itPH, ++itPN) {
363  *itPH = ProcessHistoryID();
364  itPN->assign(processNames.begin(), processNames.end());
365  }
366 
367  //Now that we know all the IDs time to set the values
369  }
370 
371  //
372  // const member functions
373  //
374  namespace {
375  struct CompareFirst {
378  return iLHS.first < iRHS.first;
379  }
380  };
381  }
382 
383  std::pair<TransientProductLookupMap::const_iterator, TransientProductLookupMap::const_iterator>
385  TypeInBranchTypeLookup::const_iterator itFind = std::lower_bound(branchLookup_.begin(),
386  branchLookup_.end(),
387  std::make_pair(iKey, BranchDescriptionIndex(0)),
388  CompareFirst());
389  if(itFind == branchLookup_.end() || iKey < itFind->first) {
390  return std::make_pair(productLookupIndexList_.end(), productLookupIndexList_.end());
391  }
392  const_iterator itStart = productLookupIndexList_.begin() + itFind->second;
394  if(++itFind != branchLookup_.end()) {
395  itEnd = productLookupIndexList_.begin() + itFind->second;
396  }
397  return std::make_pair(itStart, itEnd);
398  }
399 
400  std::pair<TransientProductLookupMap::const_iterator, TransientProductLookupMap::const_iterator>
402  std::string const& moduleLabel,
403  std::string const& productInstanceName) const {
404  std::pair<const_iterator, const_iterator> itPair = this->equal_range(iKey);
405 
406  if (itPair.first == itPair.second) {
407  return itPair;
408  }
409 
410  // Advance lower bound only
411  itPair.first = std::lower_bound(itPair.first, itPair.second, std::make_pair(&moduleLabel, &productInstanceName), CompareModuleLabelAndProductInstanceName());
412  // Protect against no match
413  if (!(itPair.first < itPair.second) ||
414  itPair.first->branchDescription()->moduleLabel() != moduleLabel ||
415  itPair.first->branchDescription()->productInstanceName() != productInstanceName) {
416  itPair.second = itPair.first;
417  }
418  return itPair;
419  }
420 
421  //
422  // static member functions
423  //
424 }
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
Definition: Hash.h:36
void reorderIfNecessary(BranchType, ProcessHistory const &, std::string const &iNewProcessName)
reorders the ProductLookupIndexes for the BranchType based on the processing ordering ...
ProductLookupIndexList productLookupIndexList_
Container::value_type value_type
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_
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
const std::string * moduleLabel() const
Definition: HLTadd.h:40