00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <algorithm>
00015
00016
00017 #include "DataFormats/Provenance/interface/TransientProductLookupMap.h"
00018 #include "DataFormats/Provenance/interface/ProcessHistory.h"
00019 #include "DataFormats/Provenance/interface/ConstBranchDescription.h"
00020
00021
00022
00023
00024
00025
00026
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
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
00069
00070
00071
00072
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
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
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
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
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
00185 return;
00186 }
00187
00188 if(iHistory.empty()) {
00189
00190 historyID = iHistory.id();
00191 return;
00192 }
00193 std::vector<std::string>& processNameOrdering = processNameOrderingForBranchType_[iBranch];
00194
00195
00196
00197
00198
00199
00200
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
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
00230 if(it == itEnd) {
00231 return;
00232 }
00233 }
00234
00235
00236
00237 ++fillCount_;
00238 historyID = iHistory.id();
00239 std::vector<std::string> temp(processNameOrdering.size(), std::string());
00240
00241
00242 std::vector<std::string>::reverse_iterator itR = temp.rbegin();
00243 std::vector<std::string>::reverse_iterator itREnd = temp.rend();
00244 ProcessHistory::const_reverse_iterator itRH = iHistory.rbegin();
00245 ProcessHistory::const_reverse_iterator itRHEnd = iHistory.rend();
00246
00247 if(processNameOrdering.end() != std::find(processNameOrdering.begin(), processNameOrdering.end(), iNewProcessName)) {
00248 *itR = iNewProcessName;
00249 ++itR;
00250 if (iNewProcessName == itRH->processName()) {
00251 ++itRH;
00252 }
00253 }
00254 for(; itRH != itRHEnd; ++itRH) {
00255 if(processNameOrdering.end() != std::find(processNameOrdering.begin(), processNameOrdering.end(), itRH->processName())) {
00256
00257 *itR = itRH->processName();
00258 ++itR;
00259 }
00260 }
00261
00262
00263
00264
00265 std::vector<std::string>::iterator itOld = processNameOrdering.begin();
00266 it = temp.begin();
00267 std::vector<std::string>::iterator itStart = temp.begin()+(itREnd - itR);
00268 while(it != itStart) {
00269 assert(itOld != processNameOrdering.end());
00270 if(temp.end() == std::find(itStart, temp.end(), *itOld)) {
00271
00272 *it = *itOld;
00273 ++it;
00274 }
00275 ++itOld;
00276 }
00277
00278 processNameOrdering.swap(temp);
00279
00280
00281
00282 std::pair<TypeInBranchTypeLookup::iterator, TypeInBranchTypeLookup::iterator> branchRange =
00283 std::equal_range(branchLookup_.begin(), branchLookup_.end(), std::make_pair(TypeInBranchType(TypeID(), iBranch), BranchDescriptionIndex(0)), BranchTypeOnlyCompare());
00284
00285 if(branchRange.first == branchRange.second) {
00286 return;
00287 }
00288
00289 ProductLookupIndexList::iterator itIndex = productLookupIndexList_.begin() + branchRange.first->second;
00290 ProductLookupIndexList::iterator itIndexEnd = productLookupIndexList_.end();
00291 if(branchRange.second != branchLookup_.end()) {
00292 itIndexEnd = productLookupIndexList_.begin() + branchRange.second->second;
00293 }
00294
00295 while(itIndex != itIndexEnd) {
00296 itIndex->setIsFirst(false);
00297 ProductLookupIndexList::iterator itNext = itIndex;
00298 while(itNext != itIndexEnd && !itNext->isFirst()) {
00299 ++itNext;
00300 }
00301 std::sort(itIndex, itNext, CompareProcessList(&processNameOrdering));
00302 itIndex->setIsFirst(true);
00303 itIndex = itNext;
00304 }
00305
00306
00307 fillInProcessIndexes(productLookupIndexList_.begin() + branchRange.first->second, itIndexEnd, processNameOrdering);
00308
00309 }
00310
00311 void
00312 TransientProductLookupMap::fillFrom(FillFromMap const& iMap) {
00313
00314 assert(processNameOrderingForBranchType_.size() == historyIDsForBranchType_.size());
00315
00316
00317 ++fillCount_;
00318
00319 productLookupIndexList_.clear();
00320 productLookupIndexList_.reserve(iMap.size());
00321 branchLookup_.clear();
00322 branchLookup_.reserve(iMap.size());
00323
00324 std::set<std::string, std::greater<std::string> > processNames;
00325 TypeInBranchType lastSeen(TypeID(), NumBranchTypes);
00326
00327
00328 static std::string const kEmpty;
00329 std::string const* lastSeenModule = &kEmpty;
00330 std::string const* lastSeenProductInstance = &kEmpty;
00331 for(FillFromMap::const_iterator it = iMap.begin(), itEnd = iMap.end();
00332 it != itEnd;
00333 ++it) {
00334 bool isFirst = ((lastSeen < it->first.first) || (it->first.first < lastSeen));
00335 if(isFirst) {
00336 lastSeen = it->first.first;
00337 branchLookup_.push_back(std::make_pair(lastSeen, BranchDescriptionIndex(productLookupIndexList_.size())));
00338 } else {
00339
00340 isFirst = (*lastSeenModule != it->first.second->moduleLabel() ||
00341 *lastSeenProductInstance != it->first.second->productInstanceName());
00342 }
00343 productLookupIndexList_.push_back(ProductLookupIndex(it->first.second,
00344 it->second,
00345 0,
00346 isFirst)
00347 );
00348 if(isFirst) {
00349 lastSeenModule = &(it->first.second->moduleLabel());
00350 lastSeenProductInstance = &(it->first.second->productInstanceName());
00351 }
00352 processNames.insert(it->first.second->processName());
00353 }
00354
00355 std::vector<ProcessHistoryID>::iterator itPH = historyIDsForBranchType_.begin();
00356 std::vector<ProcessHistoryID>::iterator itPHEnd = historyIDsForBranchType_.end();
00357
00358 std::vector<std::vector<std::string> >::iterator itPN = processNameOrderingForBranchType_.begin();
00359
00360
00361 for(;itPH != itPHEnd; ++itPH, ++itPN) {
00362 *itPH = ProcessHistoryID();
00363 itPN->assign(processNames.begin(), processNames.end());
00364 }
00365
00366
00367 fillInProcessIndexes(productLookupIndexList_.begin(), productLookupIndexList_.end(), processNameOrderingForBranchType_.front());
00368 }
00369
00370
00371
00372
00373 namespace {
00374 struct CompareFirst {
00375 bool operator()(TransientProductLookupMap::TypeInBranchTypeLookup::value_type const& iLHS,
00376 TransientProductLookupMap::TypeInBranchTypeLookup::value_type const& iRHS) const {
00377 return iLHS.first < iRHS.first;
00378 }
00379 };
00380 }
00381
00382 std::pair<TransientProductLookupMap::const_iterator, TransientProductLookupMap::const_iterator>
00383 TransientProductLookupMap::equal_range(TypeInBranchType const& iKey) const {
00384 TypeInBranchTypeLookup::const_iterator itFind = std::lower_bound(branchLookup_.begin(),
00385 branchLookup_.end(),
00386 std::make_pair(iKey, BranchDescriptionIndex(0)),
00387 CompareFirst());
00388 if(itFind == branchLookup_.end() || iKey < itFind->first) {
00389 return std::make_pair(productLookupIndexList_.end(), productLookupIndexList_.end());
00390 }
00391 const_iterator itStart = productLookupIndexList_.begin() + itFind->second;
00392 const_iterator itEnd = productLookupIndexList_.end();
00393 if(++itFind != branchLookup_.end()) {
00394 itEnd = productLookupIndexList_.begin() + itFind->second;
00395 }
00396 return std::make_pair(itStart, itEnd);
00397 }
00398
00399 std::pair<TransientProductLookupMap::const_iterator, TransientProductLookupMap::const_iterator>
00400 TransientProductLookupMap::equal_range(TypeInBranchType const& iKey,
00401 std::string const& moduleLabel,
00402 std::string const& productInstanceName) const {
00403 std::pair<const_iterator, const_iterator> itPair = this->equal_range(iKey);
00404
00405 if (itPair.first == itPair.second) {
00406 return itPair;
00407 }
00408
00409
00410 itPair.first = std::lower_bound(itPair.first, itPair.second, std::make_pair(&moduleLabel, &productInstanceName), CompareModuleLabelAndProductInstanceName());
00411
00412 if (!(itPair.first < itPair.second) ||
00413 itPair.first->branchDescription()->moduleLabel() != moduleLabel ||
00414 itPair.first->branchDescription()->productInstanceName() != productInstanceName) {
00415 itPair.second = itPair.first;
00416 }
00417 return itPair;
00418 }
00419
00420
00421
00422
00423 }