CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/DataFormats/Provenance/src/TransientProductLookupMap.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     Provenance
00004 // Class  :     TransientProductLookupMap
00005 // 
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author:  Chris Jones
00010 //         Created:  Fri May  1 12:17:12 CDT 2009
00011 //
00012 
00013 // system include files
00014 #include <algorithm>
00015 
00016 // user include files
00017 #include "DataFormats/Provenance/interface/TransientProductLookupMap.h"
00018 #include "DataFormats/Provenance/interface/ProcessHistory.h"
00019 #include "DataFormats/Provenance/interface/ConstBranchDescription.h"
00020 
00021 //
00022 // constants, enums and typedefs
00023 //
00024 
00025 //
00026 // static data member definitions
00027 //
00028 
00029 namespace edm {
00030   bool CompareTypeInBranchTypeConstBranchDescription::operator()(std::pair<TypeInBranchType, ConstBranchDescription const*> const& iLHS,
00031                      std::pair<TypeInBranchType, ConstBranchDescription const*> const& iRHS) const {
00032      if(iLHS.first < iRHS.first) {
00033         return true;
00034      }
00035      if(iRHS.first < iLHS.first) {
00036         return false;
00037      }
00038      
00039      int c = iLHS.second->moduleLabel().compare(iRHS.second->moduleLabel());
00040      if(c < 0) {
00041         return true;
00042      }
00043      if(c > 0) {
00044         return false;
00045      }
00046      c = iLHS.second->productInstanceName().compare(iRHS.second->productInstanceName());
00047      if(c < 0) {
00048         return true;
00049      }
00050      if(c > 0) {
00051         return false;
00052      }
00053      
00054      return iLHS.second->processName() < iRHS.second->processName();
00055   }
00056   
00057   //
00058   // constructors and destructor
00059   //
00060   TransientProductLookupMap::TransientProductLookupMap() :
00061       branchLookup_(),
00062       productLookupIndexList_(),
00063       historyIDsForBranchType_(static_cast<unsigned int>(NumBranchTypes), ProcessHistoryID()),
00064       processNameOrderingForBranchType_(static_cast<unsigned int>(NumBranchTypes), std::vector<std::string>()),
00065       fillCount_(0) {
00066   }
00067   
00068   // TransientProductLookupMap::TransientProductLookupMap(TransientProductLookupMap const& rhs) {
00069   //    // do actual copying here;
00070   // }
00071   
00072   //TransientProductLookupMap::~TransientProductLookupMap() {
00073   //}
00074   
00075   void
00076   TransientProductLookupMap::reset() {
00077       branchLookup_.clear();
00078       productLookupIndexList_.clear();
00079       for (unsigned int i = 0; i < static_cast<unsigned int>(NumBranchTypes); ++i) {
00080         historyIDsForBranchType_[i].reset();
00081         processNameOrderingForBranchType_[i].clear();
00082       }
00083       fillCount_ = 0;
00084   }
00085   
00086   //
00087   // assignment operators
00088   //
00089   // TransientProductLookupMap const& TransientProductLookupMap::operator=(TransientProductLookupMap const& rhs) {
00090   //   //An exception safe implementation is
00091   //   TransientProductLookupMap temp(rhs);
00092   //   swap(rhs);
00093   //
00094   //   return *this;
00095   // }
00096   
00097   //
00098   // member functions
00099   //
00100   namespace  {
00101 
00102      struct CompareModuleLabelAndProductInstanceName {
00103         typedef std::pair<std::string const*, std::string const*> StringPtrPair;
00104         bool operator()(StringPtrPair const& iLHS, StringPtrPair const& iRHS) const {
00105            int c = iLHS.first->compare(*iRHS.first);
00106            if (c < 0) return true;
00107            if (c > 0) return false;
00108            return(*iLHS.second < *iRHS.second);
00109         }
00110         bool operator()(ProductLookupIndex const& iLHS, StringPtrPair const& iRHS) const {
00111            int c = iLHS.branchDescription()->moduleLabel().compare(*iRHS.first);
00112            if (c < 0) return true;
00113            if (c > 0) return false;
00114            return(iLHS.branchDescription()->productInstanceName() < *iRHS.second);
00115         }
00116         bool operator()(StringPtrPair const& iLHS, ProductLookupIndex const& iRHS) const {
00117            int c = iLHS.first->compare(iRHS.branchDescription()->moduleLabel());
00118            if (c < 0) return true;
00119            if (c > 0) return false;
00120            return(*iLHS.second < iRHS.branchDescription()->productInstanceName());
00121         }
00122         bool operator()(ProductLookupIndex const& iLHS, ProductLookupIndex const& iRHS) const {
00123            int c = iLHS.branchDescription()->moduleLabel().compare(iRHS.branchDescription()->moduleLabel());
00124            if (c < 0) return true;
00125            if (c > 0) return false;
00126            return(iLHS.branchDescription()->productInstanceName() < iRHS.branchDescription()->productInstanceName());
00127         }
00128      };
00129 
00130      struct BranchTypeOnlyCompare {
00131         bool operator()(std::pair<TypeInBranchType, BranchDescriptionIndex> const& iLHS, std::pair<TypeInBranchType, BranchDescriptionIndex> const& iRHS) const {
00132            return iLHS.first.branchType() < iRHS.first.branchType();
00133         }
00134      };
00135      
00136      struct CompareProcessList {
00137         std::vector<std::string> const* list_;
00138   
00139         CompareProcessList(std::vector<std::string> const* iList) : list_(iList) {}
00140         
00141         bool operator()(ProductLookupIndex const& iLHS, ProductLookupIndex const& iRHS) const {
00142            std::string const& lhs = iLHS.branchDescription()->processName();
00143            std::string const& rhs = iRHS.branchDescription()->processName();
00144            if(lhs == rhs) {return false;}
00145            //NOTE: names in the vector are oldest to newest and we want to order by newest
00146            for(std::vector<std::string>::const_reverse_iterator it = list_->rbegin(), itEnd = list_->rend();
00147                it != itEnd;
00148                ++it){
00149               if(*it == lhs) {return true;}
00150               if(*it == rhs) { return false;}
00151            }
00152            return false;
00153         }
00154      };
00155   }
00156   
00157   static
00158   void
00159   fillInProcessIndexes(TransientProductLookupMap::ProductLookupIndexList::iterator iIt, 
00160                         TransientProductLookupMap::ProductLookupIndexList::iterator iEnd,
00161                         std::vector<std::string> const& iNameOrder) {
00162      //NOTE the iterators are already in the same order as iNameOrder
00163      std::vector<std::string>::const_reverse_iterator itNO = iNameOrder.rbegin();
00164      unsigned int index = 0;
00165      for(; iIt != iEnd; ++iIt) {
00166         if(iIt->isFirst()) {
00167            itNO = iNameOrder.rbegin();
00168            index = 0;
00169         }
00170         while(*itNO != iIt->branchDescription()->processName()) {
00171            ++itNO;
00172            assert(itNO != iNameOrder.rend());
00173            ++index;
00174         }
00175         iIt->setProcessIndex(index);
00176      }
00177   }
00178   
00179   void 
00180   TransientProductLookupMap::reorderIfNecessary(BranchType iBranch, ProcessHistory const& iHistory, std::string const& iNewProcessName) {
00181 
00182      ProcessHistoryID& historyID = historyIDsForBranchType_[iBranch];
00183      if(iHistory.id() == historyID) { 
00184         //std::cout <<"no reordering since history unchanged"<<std::endl;
00185         return;
00186      }
00187      
00188      if(iHistory.empty()) {
00189         //std::cout <<"no reordering since history empty"<<std::endl;
00190         historyID = iHistory.id(); 
00191         return; 
00192      }
00193      std::vector<std::string>& processNameOrdering = processNameOrderingForBranchType_[iBranch];
00194   
00195      //iHistory may be missing entries in processNameOrdering if two files were merged together and one file
00196      // had fewer processing steps than the other one.
00197      //iHistory may have more entries than processNameOrdering if all data products for those extra entries
00198      // were dropped
00199      
00200      //if iHistory already in same order as processNameOrdering than we don't have to do anything
00201      std::vector<std::string>::iterator it = processNameOrdering.begin();
00202      std::vector<std::string>::iterator itEnd = processNameOrdering.end();
00203      ProcessHistory::const_iterator itH = iHistory.begin();
00204      ProcessHistory::const_iterator itHEnd = iHistory.end();
00205      
00206      {
00207         std::vector<std::string>::iterator itStart = it;
00208         bool mustReorder = false;
00209         while(it != itEnd && itH != itHEnd) {
00210            if(*it == itH->processName()) {
00211               ++it;
00212            } else {
00213               //see if we already passed it
00214               for(std::vector<std::string>::iterator itOld = itStart; itOld != it; ++itOld) {
00215                  if(*itOld == itH->processName()) {
00216                     mustReorder = true;
00217                     break;
00218                  }
00219               }
00220               if(mustReorder) {
00221                  break;
00222               }
00223            }
00224            ++itH;
00225         }
00226         if(!mustReorder && it != itEnd && *it == iNewProcessName) {
00227            ++it;
00228         }
00229         //can only reach the end if we found all the items in the correct order
00230         if(it == itEnd) { 
00231            return;
00232         }
00233      }
00234   
00235      //must re-sort
00236      //Increment the fill count so users can check if the map has been modified.
00237      ++fillCount_;
00238      historyID = iHistory.id();
00239      std::vector<std::string> temp(processNameOrdering.size(), std::string());
00240      
00241      
00242      //we want to add the items at the back
00243      std::vector<std::string>::reverse_iterator itR = temp.rbegin();
00244      std::vector<std::string>::reverse_iterator itREnd = temp.rend();
00245      ProcessHistory::const_reverse_iterator itRH = iHistory.rbegin();
00246      ProcessHistory::const_reverse_iterator itRHEnd = iHistory.rend();
00247   
00248      if(processNameOrdering.end() != std::find(processNameOrdering.begin(), processNameOrdering.end(), iNewProcessName)) {
00249         *itR = iNewProcessName;
00250         ++itR;
00251         if (iNewProcessName == itRH->processName()) {
00252           ++itRH;
00253         }
00254      }
00255      for(; itRH != itRHEnd; ++itRH) {
00256         if(processNameOrdering.end() != std::find(processNameOrdering.begin(), processNameOrdering.end(), itRH->processName())) {
00257            
00258            *itR = itRH->processName();
00259            ++itR;
00260         }
00261      }
00262   
00263      //have to fill in the missing processes from processNameOrdering_
00264      // we do this at the beginning because we lookup data in the reverse order
00265      // so we want the ones we know are there to be searched first
00266      std::vector<std::string>::iterator itOld = processNameOrdering.begin();
00267      it = temp.begin();
00268      std::vector<std::string>::iterator itStart = temp.begin()+(itREnd - itR);
00269      while(it != itStart) {
00270         assert(itOld != processNameOrdering.end());
00271         if(temp.end() == std::find(itStart, temp.end(), *itOld)) {
00272            //didn't find it so need to add this to our list
00273            *it = *itOld;
00274            ++it;
00275         }
00276         ++itOld;
00277      }
00278      
00279      processNameOrdering.swap(temp);
00280      
00281      //now we need to go through our data structure and change the processing orders
00282      //first find the range for this BranchType
00283      std::pair<TypeInBranchTypeLookup::iterator, TypeInBranchTypeLookup::iterator> branchRange = 
00284      std::equal_range(branchLookup_.begin(), branchLookup_.end(), std::make_pair(TypeInBranchType(TypeID(), iBranch), BranchDescriptionIndex(0)), BranchTypeOnlyCompare());
00285      
00286      if(branchRange.first == branchRange.second) {
00287         return;
00288      }
00289      //convert this into Index iterators since that is the structure we must reorder
00290      ProductLookupIndexList::iterator itIndex = productLookupIndexList_.begin() + branchRange.first->second;
00291      ProductLookupIndexList::iterator itIndexEnd = productLookupIndexList_.end();
00292      if(branchRange.second != branchLookup_.end()) {
00293         itIndexEnd = productLookupIndexList_.begin() + branchRange.second->second;
00294      }
00295      
00296      while(itIndex != itIndexEnd) {
00297         itIndex->setIsFirst(false);
00298         ProductLookupIndexList::iterator itNext = itIndex;
00299         while(itNext != itIndexEnd && !itNext->isFirst()) {
00300            ++itNext;
00301         }
00302         std::sort(itIndex, itNext, CompareProcessList(&processNameOrdering));
00303         itIndex->setIsFirst(true);
00304         itIndex = itNext;
00305      }
00306      
00307      //Now that we know all the IDs time to set the values
00308      fillInProcessIndexes(productLookupIndexList_.begin() + branchRange.first->second, itIndexEnd, processNameOrdering);
00309   
00310   }
00311   
00312   void 
00313   TransientProductLookupMap::fillFrom(FillFromMap const& iMap) {
00314 
00315      assert(processNameOrderingForBranchType_.size() == historyIDsForBranchType_.size());
00316   
00317      //Increment the fill count so users can check if the map has been modified.
00318      ++fillCount_;
00319 
00320      productLookupIndexList_.clear();
00321      productLookupIndexList_.reserve(iMap.size());
00322      branchLookup_.clear();
00323      branchLookup_.reserve(iMap.size()); //this is an upperbound
00324      
00325      std::set<std::string, std::greater<std::string> > processNames;
00326      TypeInBranchType lastSeen(TypeID(), NumBranchTypes);
00327   
00328      //since the actual strings are stored elsewhere, there is no reason to make a copy
00329      static std::string const kEmpty;
00330      std::string const* lastSeenModule = &kEmpty;
00331      std::string const* lastSeenProductInstance = &kEmpty;
00332      for(FillFromMap::const_iterator it = iMap.begin(), itEnd = iMap.end();
00333          it != itEnd;
00334          ++it) {
00335         bool isFirst =  ((lastSeen < it->first.first) || (it->first.first < lastSeen));
00336         if(isFirst) {
00337            lastSeen = it->first.first;
00338            branchLookup_.push_back(std::make_pair(lastSeen, BranchDescriptionIndex(productLookupIndexList_.size())));
00339         } else {
00340            //see if this is the first of a group that only differ by ProcessName
00341            isFirst = (*lastSeenModule != it->first.second->moduleLabel() ||
00342                       *lastSeenProductInstance != it->first.second->productInstanceName());
00343         }
00344         productLookupIndexList_.push_back(ProductLookupIndex(it->first.second,
00345                                                 it->second,
00346                                                 0,
00347                                                 isFirst)
00348                             );
00349         if(isFirst) {
00350            lastSeenModule = &(it->first.second->moduleLabel());
00351            lastSeenProductInstance = &(it->first.second->productInstanceName());         
00352         }
00353         processNames.insert(it->first.second->processName());
00354      }
00355   
00356      std::vector<ProcessHistoryID>::iterator itPH = historyIDsForBranchType_.begin();
00357      std::vector<ProcessHistoryID>::iterator itPHEnd = historyIDsForBranchType_.end();
00358      
00359      std::vector<std::vector<std::string> >::iterator itPN = processNameOrderingForBranchType_.begin();
00360      std::vector<std::vector<std::string> >::iterator itPNEnd = processNameOrderingForBranchType_.end();
00361      
00362      for(;itPH != itPHEnd; ++itPH, ++itPN) {
00363         *itPH = ProcessHistoryID();
00364         itPN->assign(processNames.begin(), processNames.end());
00365      }
00366   
00367      //Now that we know all the IDs time to set the values
00368      fillInProcessIndexes(productLookupIndexList_.begin(), productLookupIndexList_.end(), processNameOrderingForBranchType_.front());
00369   }
00370   
00371   //
00372   // const member functions
00373   //
00374   namespace {
00375      struct CompareFirst {
00376         bool operator()(TransientProductLookupMap::TypeInBranchTypeLookup::value_type const& iLHS,
00377                         TransientProductLookupMap::TypeInBranchTypeLookup::value_type const& iRHS) const {
00378            return iLHS.first < iRHS.first;
00379         }
00380      };
00381   }
00382 
00383   std::pair<TransientProductLookupMap::const_iterator, TransientProductLookupMap::const_iterator> 
00384   TransientProductLookupMap::equal_range(TypeInBranchType const& iKey) const {
00385      TypeInBranchTypeLookup::const_iterator itFind = std::lower_bound(branchLookup_.begin(),
00386                                                                       branchLookup_.end(),
00387                                                                       std::make_pair(iKey, BranchDescriptionIndex(0)),
00388                                                                       CompareFirst());
00389      if(itFind == branchLookup_.end() || iKey < itFind->first) {
00390         return std::make_pair(productLookupIndexList_.end(), productLookupIndexList_.end());
00391      }
00392      const_iterator itStart = productLookupIndexList_.begin() + itFind->second;
00393      const_iterator itEnd = productLookupIndexList_.end();
00394      if(++itFind != branchLookup_.end()) {
00395         itEnd = productLookupIndexList_.begin() + itFind->second;
00396      }
00397      return std::make_pair(itStart, itEnd);
00398   }
00399   
00400   std::pair<TransientProductLookupMap::const_iterator, TransientProductLookupMap::const_iterator> 
00401   TransientProductLookupMap::equal_range(TypeInBranchType const& iKey,
00402          std::string const& moduleLabel,
00403          std::string const& productInstanceName) const {
00404      std::pair<const_iterator, const_iterator> itPair = this->equal_range(iKey);
00405 
00406      if (itPair.first == itPair.second) {
00407         return itPair;
00408      }
00409 
00410      // Advance lower bound only
00411      itPair.first = std::lower_bound(itPair.first, itPair.second, std::make_pair(&moduleLabel, &productInstanceName), CompareModuleLabelAndProductInstanceName());  
00412      // Protect against no match
00413      if (!(itPair.first < itPair.second) ||
00414          itPair.first->branchDescription()->moduleLabel() != moduleLabel ||
00415          itPair.first->branchDescription()->productInstanceName() != productInstanceName) {
00416        itPair.second = itPair.first;
00417      }
00418      return itPair;
00419   }
00420   
00421   //
00422   // static member functions
00423   //
00424 }