00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <iostream>
00015 #include "Reflex/Type.h"
00016 #include "Reflex/Object.h"
00017
00018
00019 #include "DataFormats/FWLite/interface/DataGetterHelper.h"
00020 #include "TFile.h"
00021 #include "TTree.h"
00022 #include "TTreeCache.h"
00023 #include "FWCore/Utilities/interface/Exception.h"
00024 #include "DataFormats/Common/interface/EDProduct.h"
00025
00026 #include "FWCore/FWLite/interface/setRefStreamer.h"
00027
00028 #include "FWCore/Utilities/interface/WrappedClassName.h"
00029
00030 #include "FWCore/Utilities/interface/EDMException.h"
00031
00032 #define TTCACHE_SIZE 20*1024*1024
00033
00034 namespace fwlite {
00035
00036
00037
00038
00039
00040
00041
00042
00043 class withTCache {
00044 public:
00045 withTCache(TFile* file, TTreeCache* tc) : f_(file) { f_->SetCacheRead(tc); }
00046 ~withTCache() { f_->SetCacheRead(0); }
00047 private:
00048 TFile* f_;
00049 };
00050
00051
00052
00053
00054 typedef std::map<internal::DataKey, boost::shared_ptr<internal::Data> > DataMap;
00055
00056 static internal::Data branchNotFound;
00057
00058
00059
00060
00061 DataGetterHelper::DataGetterHelper(TTree* tree,
00062 boost::shared_ptr<HistoryGetterBase> historyGetter,
00063 boost::shared_ptr<BranchMapReader> branchMap,
00064 boost::shared_ptr<edm::EDProductGetter> getter,
00065 bool useCache):
00066 branchMap_(branchMap),
00067 historyGetter_(historyGetter),
00068 getter_(getter),
00069 tcache_(0),
00070 tcTrained_(false)
00071 {
00072 if(0==tree) {
00073 throw cms::Exception("NoTree")<<"The TTree pointer passed to the constructor was null";
00074 }
00075 tree_ = tree;
00076 if (useCache) {
00077 tree_->SetCacheSize(TTCACHE_SIZE);
00078 TFile* iFile(branchMap_->getFile());
00079 tcache_.reset(dynamic_cast<TTreeCache*>(iFile->GetCacheRead()));
00080 iFile->SetCacheRead(0);
00081
00082 }
00083 }
00084
00085
00086
00087
00088
00089
00090 DataGetterHelper::~DataGetterHelper() { }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 static
00120 TBranch* findBranch(TTree* iTree, const std::string& iMainLabels, const std::string& iProcess) {
00121 std::string branchName(iMainLabels);
00122 branchName+=iProcess;
00123
00124 branchName+=".";
00125 return iTree->GetBranch(branchName.c_str());
00126 }
00127
00128 void
00129 DataGetterHelper::getBranchData(edm::EDProductGetter* iGetter,
00130 Long64_t index,
00131 internal::Data& iData) const
00132 {
00133 GetterOperate op(iGetter);
00134
00135
00136
00137
00138 Reflex::Object obj = iData.obj_;
00139 iData.obj_ = iData.obj_.TypeOf().Construct();
00140 iData.pObj_ = iData.obj_.Address();
00141 iData.branch_->SetAddress(&(iData.pObj_));
00142
00143 if(0!=iData.pProd_) {
00144
00145 void* p = iData.pProd_;
00146 iData.pProd_ = reinterpret_cast<edm::EDProduct*>(static_cast<char*>(iData.obj_.Address())+(static_cast<char*>(p)-static_cast<char*>(obj.Address())));
00147 }
00148 obj.Destruct();
00149
00150
00151 if (0 == tcache_.get()) {
00152 iData.branch_->GetEntry(index);
00153 } else {
00154 if (!tcTrained_) {
00155 tcache_->SetLearnEntries(100);
00156 tcache_->SetEntryRange(0, tree_->GetEntries());
00157 tcTrained_ = true;
00158 }
00159 withTCache tcguard(branchMap_->getFile(), tcache_.get());
00160 tree_->LoadTree(index);
00161 iData.branch_->GetEntry(index);
00162 }
00163 iData.lastProduct_=index;
00164 }
00165
00166
00167 internal::Data&
00168 DataGetterHelper::getBranchDataFor(const std::type_info& iInfo,
00169 const char* iModuleLabel,
00170 const char* iProductInstanceLabel,
00171 const char* iProcessLabel) const
00172 {
00173 edm::TypeID type(iInfo);
00174 internal::DataKey key(type, iModuleLabel, iProductInstanceLabel, iProcessLabel);
00175
00176 boost::shared_ptr<internal::Data> theData;
00177 DataMap::iterator itFind = data_.find(key);
00178 if(itFind == data_.end() ) {
00179
00180 const std::string sep("_");
00181
00182 std::string name(type.friendlyClassName());
00183 name +=sep+std::string(key.module());
00184 name +=sep+std::string(key.product())+sep;
00185
00186
00187 std::string foundProcessLabel;
00188 TBranch* branch = 0;
00189
00190 if (0==iProcessLabel || iProcessLabel==key.kEmpty() ||
00191 strlen(iProcessLabel)==0) {
00192 const std::string* lastLabel=0;
00193
00194 const edm::ProcessHistory& h = DataGetterHelper::history();
00195 for (edm::ProcessHistory::const_reverse_iterator iproc = h.rbegin(), eproc = h.rend();
00196 iproc != eproc;
00197 ++iproc) {
00198
00199 lastLabel = &(iproc->processName());
00200 branch=findBranch(tree_,name,iproc->processName());
00201 if(0!=branch) {
00202 break;
00203 }
00204 }
00205 if(0==branch) {
00206 return branchNotFound;
00207 }
00208
00209 if(0!=lastLabel) {
00210 internal::DataKey fullKey(type,iModuleLabel,iProductInstanceLabel,lastLabel->c_str());
00211 itFind = data_.find(fullKey);
00212 if(itFind != data_.end()) {
00213
00214 theData = itFind->second;
00215 } else {
00216
00217 foundProcessLabel = *lastLabel;
00218 }
00219 }
00220 } else {
00221
00222 branch = findBranch(tree_,name,key.process());
00223 if(0==branch){
00224 return branchNotFound;
00225 }
00226 }
00227
00228
00229 char* newModule = new char[strlen(iModuleLabel)+1];
00230 std::strcpy(newModule,iModuleLabel);
00231 labels_.push_back(newModule);
00232
00233 char* newProduct = const_cast<char*>(key.product());
00234 if(newProduct[0] != 0) {
00235 newProduct = new char[strlen(newProduct)+1];
00236 std::strcpy(newProduct,key.product());
00237 labels_.push_back(newProduct);
00238 }
00239 char* newProcess = const_cast<char*>(key.process());
00240 if(newProcess[0]!=0) {
00241 newProcess = new char[strlen(newProcess)+1];
00242 std::strcpy(newProcess,key.process());
00243 labels_.push_back(newProcess);
00244 }
00245 internal::DataKey newKey(edm::TypeID(iInfo),newModule,newProduct,newProcess);
00246
00247 if(0 == theData.get() ) {
00248
00249
00250
00251 Reflex::Type rType = Reflex::Type::ByTypeInfo(iInfo);
00252 if(rType == Reflex::Type()) {
00253 throw cms::Exception("UnknownType")<<"No Reflex dictionary exists for type "<<iInfo.name();
00254 }
00255 Reflex::Object obj = rType.Construct();
00256
00257 if(obj.Address() == 0) {
00258 throw cms::Exception("ConstructionFailed")<<"failed to construct an instance of "<<rType.Name();
00259 }
00260 boost::shared_ptr<internal::Data> newData(new internal::Data() );
00261 newData->branch_ = branch;
00262 newData->obj_ = obj;
00263 newData->lastProduct_=-1;
00264 newData->pObj_ = obj.Address();
00265 newData->pProd_ = 0;
00266 branch->SetAddress(&(newData->pObj_));
00267 theData = newData;
00268 }
00269 itFind = data_.insert(std::make_pair(newKey, theData)).first;
00270
00271 if(foundProcessLabel.size()) {
00272
00273 newProcess = new char[foundProcessLabel.size()+1];
00274 std::strcpy(newProcess,foundProcessLabel.c_str());
00275 labels_.push_back(newProcess);
00276 internal::DataKey newKey(edm::TypeID(iInfo),newModule,newProduct,newProcess);
00277
00278 data_.insert(std::make_pair(newKey,theData));
00279 }
00280 }
00281 return *(itFind->second);
00282 }
00283
00284 const std::string
00285 DataGetterHelper::getBranchNameFor(const std::type_info& iInfo,
00286 const char* iModuleLabel,
00287 const char* iProductInstanceLabel,
00288 const char* iProcessLabel) const
00289 {
00290 internal::Data& theData =
00291 DataGetterHelper::getBranchDataFor(iInfo, iModuleLabel, iProductInstanceLabel, iProcessLabel);
00292
00293 if (0 != theData.branch_) {
00294 return std::string(theData.branch_->GetName());
00295 }
00296 return std::string("");
00297 }
00298
00299 bool
00300 DataGetterHelper::getByLabel(const std::type_info& iInfo,
00301 const char* iModuleLabel,
00302 const char* iProductInstanceLabel,
00303 const char* iProcessLabel,
00304 void* oData, Long_t index) const
00305 {
00306
00307 void** pOData = reinterpret_cast<void**>(oData);
00308 *pOData = 0;
00309
00310 internal::Data& theData =
00311 DataGetterHelper::getBranchDataFor(iInfo, iModuleLabel, iProductInstanceLabel, iProcessLabel);
00312
00313 if (0 != theData.branch_) {
00314 if(index != theData.lastProduct_) {
00315
00316 getBranchData(getter_.get(), index, theData);
00317 }
00318 *pOData = theData.obj_.Address();
00319 }
00320
00321 if ( 0 == *pOData ) return false;
00322 else return true;
00323 }
00324
00325
00326 edm::EDProduct const*
00327 DataGetterHelper::getByProductID(edm::ProductID const& iID, Long_t index) const
00328 {
00329 std::map<edm::ProductID,boost::shared_ptr<internal::Data> >::const_iterator itFound = idToData_.find(iID);
00330 if(itFound == idToData_.end() ) {
00331 edm::BranchDescription bDesc = branchMap_->productToBranch(iID);
00332
00333 if (!bDesc.branchID().isValid()) {
00334 return 0;
00335 }
00336
00337
00338 Reflex::Type type( Reflex::Type::ByName(edm::wrappedClassName(bDesc.fullClassName())));
00339 assert( Reflex::Type() != type) ;
00340
00341
00342 const char* pIL = bDesc.productInstanceName().c_str();
00343 if(pIL[0] == 0) {
00344 pIL = 0;
00345 }
00346 internal::DataKey k(edm::TypeID(type.TypeInfo()),
00347 bDesc.moduleLabel().c_str(),
00348 pIL,
00349 bDesc.processName().c_str());
00350
00351
00352 KeyToDataMap::iterator itData = data_.find(k);
00353 if(data_.end() == itData) {
00354
00355 void* dummy = 0;
00356 getByLabel(type.TypeInfo(),
00357 k.module(),
00358 k.product(),
00359 k.process(),
00360 &dummy, index);
00361 if (0 == dummy) {
00362 return 0;
00363 }
00364 itData = data_.find(k);
00365 assert(itData != data_.end());
00366
00367 assert(dummy == itData->second->obj_.Address());
00368 }
00369 itFound = idToData_.insert(std::make_pair(iID,itData->second)).first;
00370 }
00371 if(index != itFound->second->lastProduct_) {
00372
00373 getBranchData(getter_.get(), index, *(itFound->second));
00374 }
00375 if(0==itFound->second->pProd_) {
00376
00377 static Reflex::Type sEDProd( Reflex::Type::ByTypeInfo(typeid(edm::EDProduct)));
00378
00379 Reflex::Object edProdObj = itFound->second->obj_.CastObject( sEDProd );
00380
00381 itFound->second->pProd_ = reinterpret_cast<edm::EDProduct*>(edProdObj.Address());
00382
00383 if(0==itFound->second->pProd_) {
00384 cms::Exception("FailedConversion")
00385 <<"failed to convert a '"<<itFound->second->obj_.TypeOf().Name()<<"' to a edm::EDProduct";
00386 }
00387 }
00388 return itFound->second->pProd_;
00389 }
00390
00391
00392 const edm::ProcessHistory& DataGetterHelper::history() const {
00393 return historyGetter_->history();
00394 }
00395
00396
00397
00398
00399
00400 void
00401 DataGetterHelper::throwProductNotFoundException(const std::type_info& iType, const char* iModule, const char* iProduct, const char* iProcess)
00402 {
00403 edm::TypeID type(iType);
00404 throw edm::Exception(edm::errors::ProductNotFound)<<"A branch was found for \n type ='"<<type.className()<<"'\n module='"<<iModule
00405 <<"'\n productInstance='"<<((0!=iProduct)?iProduct:"")<<"'\n process='"<<((0!=iProcess)?iProcess:"")<<"'\n"
00406 "but no data is available for this Lumi";
00407 }
00408
00409 }