00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "TBasket.h"
00021 #include "TBranch.h"
00022 #include "TBranchClones.h"
00023 #include "TBranchElement.h"
00024 #include "TStreamerInfo.h"
00025 #include "TBranchRef.h"
00026 #include "TError.h"
00027 #include "TProcessID.h"
00028 #include "TMath.h"
00029 #include "TTree.h"
00030 #include "TTreeCloner.h"
00031 #include "TFile.h"
00032 #include "TLeafB.h"
00033 #include "TLeafI.h"
00034 #include "TLeafL.h"
00035
00036 #include <algorithm>
00037
00038
00039 bool TTreeCloner::CompareSeek::operator()(UInt_t i1, UInt_t i2)
00040 {
00041 if (fObject->fBasketSeek[i1] == fObject->fBasketSeek[i2]) {
00042 if (fObject->fBasketEntry[i1] == fObject->fBasketEntry[i2]) {
00043 return i1 < i2;
00044 }
00045 return fObject->fBasketEntry[i1] < fObject->fBasketEntry[i2];
00046 }
00047 return fObject->fBasketSeek[i1] < fObject->fBasketSeek[i2];
00048 }
00049
00050
00051 bool TTreeCloner::CompareEntry::operator()(UInt_t i1, UInt_t i2)
00052 {
00053 if (fObject->fBasketEntry[i1] == fObject->fBasketEntry[i2]) {
00054 return i1 < i2;
00055 }
00056 return fObject->fBasketEntry[i1] < fObject->fBasketEntry[i2];
00057 }
00058
00059
00060 TTreeCloner::TTreeCloner(TTree *from, TTree *to, Option_t *method, UInt_t options) :
00061 fWarningMsg(),
00062 fIsValid(kTRUE),
00063 fNeedConversion(kFALSE),
00064 fOptions(options),
00065 fFromTree(from),
00066 fToTree(to),
00067 fMethod(method),
00068 fFromBranches( from ? from->GetListOfLeaves()->GetEntries()+1 : 0),
00069 fToBranches( to ? to->GetListOfLeaves()->GetEntries()+1 : 0),
00070 fMaxBaskets(CollectBranches()),
00071 fBasketBranchNum(new UInt_t[fMaxBaskets]),
00072 fBasketNum(new UInt_t[fMaxBaskets]),
00073 fBasketSeek(new Long64_t[fMaxBaskets]),
00074 fBasketEntry(new Long64_t[fMaxBaskets]),
00075 fBasketIndex(new UInt_t[fMaxBaskets]),
00076 fCloneMethod(TTreeCloner::kDefault),
00077 fToStartEntries(0)
00078 {
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
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 TString opt(method);
00119 opt.ToLower();
00120 if (opt.Contains("sortbasketsbybranch")) {
00121
00122 fCloneMethod = TTreeCloner::kSortBasketsByBranch;
00123 } else if (opt.Contains("sortbasketsbyentry")) {
00124
00125 fCloneMethod = TTreeCloner::kSortBasketsByEntry;
00126 } else {
00127
00128 fCloneMethod = TTreeCloner::kSortBasketsByOffset;
00129 }
00130 if (fToTree) fToStartEntries = fToTree->GetEntries();
00131 }
00132
00133
00134 Bool_t TTreeCloner::Exec()
00135 {
00136
00137
00138 CopyStreamerInfos();
00139 CopyProcessIds();
00140 CloseOutWriteBaskets();
00141 CollectBaskets();
00142 SortBaskets();
00143 WriteBaskets();
00144 CopyMemoryBaskets();
00145
00146 return kTRUE;
00147 }
00148
00149
00150 TTreeCloner::~TTreeCloner()
00151 {
00152
00153
00154 delete [] fBasketBranchNum;
00155 delete [] fBasketNum;
00156 delete [] fBasketSeek;
00157 delete [] fBasketEntry;
00158 delete [] fBasketIndex;
00159 }
00160
00161
00162 void TTreeCloner::CloseOutWriteBaskets()
00163 {
00164
00165
00166
00167 for(Int_t i=0; i<fToBranches.GetEntries(); ++i) {
00168 TBranch *to = (TBranch*)fToBranches.UncheckedAt(i);
00169 to->FlushOneBasket(to->GetWriteBasket());
00170 }
00171 }
00172
00173
00174 UInt_t TTreeCloner::CollectBranches(TBranch *from, TBranch *to) {
00175
00176
00177
00178
00179
00180
00181
00182 UInt_t numBaskets = 0;
00183 if (from->InheritsFrom(TBranchClones::Class())) {
00184 TBranchClones *fromclones = (TBranchClones*) from;
00185 TBranchClones *toclones = (TBranchClones*) to;
00186 numBaskets += CollectBranches(fromclones->fBranchCount, toclones->fBranchCount);
00187
00188 } else if (from->InheritsFrom(TBranchElement::Class())) {
00189 Int_t nb = from->GetListOfLeaves()->GetEntries();
00190 Int_t fnb = to->GetListOfLeaves()->GetEntries();
00191 if (nb != fnb && (nb == 0 || fnb == 0)) {
00192
00193
00194 fWarningMsg.Form("The export branch and the import branch do not have the same split level. (The branch name is %s.)",
00195 from->GetName());
00196 if (!(fOptions & kNoWarnings)) {
00197 Warning("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
00198 }
00199 fNeedConversion = kTRUE;
00200 fIsValid = kFALSE;
00201 return 0;
00202 }
00203 if (((TBranchElement*) from)->GetStreamerType() != ((TBranchElement*) to)->GetStreamerType()) {
00204 fWarningMsg.Form("The export branch and the import branch do not have the same streamer type. (The branch name is %s.)",
00205 from->GetName());
00206 if (!(fOptions & kNoWarnings)) {
00207 Warning("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
00208 }
00209 fIsValid = kFALSE;
00210 return 0;
00211 }
00212 TBranchElement *fromelem = (TBranchElement*) from;
00213 TBranchElement *toelem = (TBranchElement*) to;
00214 if (fromelem->fMaximum > toelem->fMaximum) toelem->fMaximum = fromelem->fMaximum;
00215 } else {
00216
00217 Int_t nb = from->GetListOfLeaves()->GetEntries();
00218 Int_t fnb = to->GetListOfLeaves()->GetEntries();
00219 if (nb != fnb) {
00220 fWarningMsg.Form("The export branch and the import branch (%s) do not have the same number of leaves (%d vs %d)",
00221 from->GetName(), fnb, nb);
00222 if (!(fOptions & kNoWarnings)) {
00223 Error("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
00224 }
00225 fIsValid = kFALSE;
00226 return 0;
00227 }
00228 for (Int_t i=0;i<nb;i++) {
00229
00230 TLeaf *fromleaf_gen = (TLeaf*)from->GetListOfLeaves()->At(i);
00231 TLeaf *toleaf_gen = (TLeaf*)to->GetListOfLeaves()->At(i);
00232 if (toleaf_gen->IsA() != fromleaf_gen->IsA() ) {
00233
00234 fWarningMsg.Form("The export leaf and the import leaf (%s.%s) do not have the data type (%s vs %s)",
00235 from->GetName(),fromleaf_gen->GetName(),fromleaf_gen->GetTypeName(),toleaf_gen->GetTypeName());
00236 if (! (fOptions & kNoWarnings) ) {
00237 Warning("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
00238 }
00239 fIsValid = kFALSE;
00240 fNeedConversion = kTRUE;
00241 return 0;
00242 }
00243 if (fromleaf_gen->IsA()==TLeafI::Class()) {
00244 TLeafI *fromleaf = (TLeafI*)fromleaf_gen;
00245 TLeafI *toleaf = (TLeafI*)toleaf_gen;
00246 if (fromleaf->GetMaximum() > toleaf->GetMaximum())
00247 toleaf->SetMaximum( fromleaf->GetMaximum() );
00248 if (fromleaf->GetMinimum() < toleaf->GetMinimum())
00249 toleaf->SetMinimum( fromleaf->GetMinimum() );
00250 } else if (fromleaf_gen->IsA()==TLeafL::Class()) {
00251 TLeafL *fromleaf = (TLeafL*)fromleaf_gen;
00252 TLeafL *toleaf = (TLeafL*)toleaf_gen;
00253 if (fromleaf->GetMaximum() > toleaf->GetMaximum())
00254 toleaf->SetMaximum( fromleaf->GetMaximum() );
00255 if (fromleaf->GetMinimum() < toleaf->GetMinimum())
00256 toleaf->SetMinimum( fromleaf->GetMinimum() );
00257 } else if (fromleaf_gen->IsA()==TLeafB::Class()) {
00258 TLeafB *fromleaf = (TLeafB*)fromleaf_gen;
00259 TLeafB *toleaf = (TLeafB*)toleaf_gen;
00260 if (fromleaf->GetMaximum() > toleaf->GetMaximum())
00261 toleaf->SetMaximum( fromleaf->GetMaximum() );
00262 if (fromleaf->GetMinimum() < toleaf->GetMinimum())
00263 toleaf->SetMinimum( fromleaf->GetMinimum() );
00264 }
00265 }
00266
00267 }
00268
00269 fFromBranches.AddLast(from);
00270 fToBranches.AddLast(to);
00271
00272 numBaskets += from->GetWriteBasket();
00273 numBaskets += CollectBranches(from->GetListOfBranches(),to->GetListOfBranches());
00274
00275 return numBaskets;
00276 }
00277
00278
00279 UInt_t TTreeCloner::CollectBranches(TObjArray *from, TObjArray *to)
00280 {
00281
00282
00283
00284
00285
00286 Int_t fnb = from->GetEntries();
00287 Int_t tnb = to->GetEntries();
00288 if (!fnb || !tnb) {
00289 return 0;
00290 }
00291
00292 UInt_t numBasket = 0;
00293 Int_t fi = 0;
00294 Int_t ti = 0;
00295 while (ti < tnb) {
00296 TBranch* fb = (TBranch*) from->UncheckedAt(fi);
00297 TBranch* tb = (TBranch*) to->UncheckedAt(ti);
00298 Int_t firstfi = fi;
00299 while (strcmp(fb->GetName(), tb->GetName())) {
00300 ++fi;
00301 if (fi >= fnb) {
00302
00303 fi = 0;
00304 }
00305 if (fi==firstfi) {
00306
00307 fb = 0;
00308 break;
00309 }
00310 fb = (TBranch*) from->UncheckedAt(fi);
00311 }
00312 if (fb) {
00313 numBasket += CollectBranches(fb, tb);
00314 ++fi;
00315 if (fi >= fnb) {
00316 fi = 0;
00317 }
00318 } else {
00319 if (tb->GetMother()==tb) {
00320
00321 if (!(fOptions & kIgnoreMissingTopLevel)) {
00322 fWarningMsg.Form("One of the export top level branches (%s) is not present in the import TTree.",
00323 tb->GetName());
00324 if (!(fOptions & kNoWarnings)) {
00325 Error("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
00326 }
00327 fIsValid = kFALSE;
00328 }
00329 } else {
00330 fWarningMsg.Form("One of the export sub-branches (%s) is not present in the import TTree.",
00331 tb->GetName());
00332 if (!(fOptions & kNoWarnings)) {
00333 Error("TTreeCloner::CollectBranches", "%s", fWarningMsg.Data());
00334 }
00335 fIsValid = kFALSE;
00336 }
00337 }
00338 ++ti;
00339 }
00340 return numBasket;
00341 }
00342
00343
00344 UInt_t TTreeCloner::CollectBranches()
00345 {
00346
00347
00348
00349
00350
00351 if (!fFromTree || !fToTree) {
00352 return 0;
00353 }
00354 UInt_t numBasket = CollectBranches(fFromTree->GetListOfBranches(),
00355 fToTree->GetListOfBranches());
00356
00357 if (fFromTree->GetBranchRef()) {
00358 fToTree->BranchRef();
00359 numBasket += CollectBranches(fFromTree->GetBranchRef(),fToTree->GetBranchRef());
00360 }
00361 return numBasket;
00362 }
00363
00364
00365 void TTreeCloner::CollectBaskets()
00366 {
00367
00368
00369
00370 UInt_t len = fFromBranches.GetEntries();
00371
00372 for(UInt_t i=0,bi=0; i<len; ++i) {
00373 TBranch *from = (TBranch*)fFromBranches.UncheckedAt(i);
00374 for(Int_t b=0; b<from->GetWriteBasket(); ++b,++bi) {
00375 fBasketBranchNum[bi] = i;
00376 fBasketNum[bi] = b;
00377 fBasketSeek[bi] = from->GetBasketSeek(b);
00378
00379 fBasketEntry[bi] = from->GetBasketEntry()[b];
00380 fBasketIndex[bi] = bi;
00381 }
00382 }
00383 }
00384
00385
00386 void TTreeCloner::CopyStreamerInfos()
00387 {
00388
00389
00390
00391 TFile *fromFile = fFromTree->GetDirectory()->GetFile();
00392 TFile *toFile = fToTree->GetDirectory()->GetFile();
00393 TList *l = fromFile->GetStreamerInfoList();
00394 TIter next(l);
00395 TStreamerInfo *oldInfo;
00396 while ( (oldInfo = (TStreamerInfo*)next()) ) {
00397 if (oldInfo->IsA() != TStreamerInfo::Class()) {
00398 continue;
00399 }
00400 TStreamerInfo *curInfo = 0;
00401 TClass *cl = TClass::GetClass(oldInfo->GetName());
00402
00403 if ((cl->IsLoaded() && (cl->GetNew()!=0 || cl->HasDefaultConstructor()))
00404 || !cl->IsLoaded()) {
00405
00406 curInfo = (TStreamerInfo*)cl->GetStreamerInfo(oldInfo->GetClassVersion());
00407 if (oldInfo->GetClassVersion()==1) {
00408
00409
00410 TStreamerInfo *matchInfo = (TStreamerInfo*)cl->FindStreamerInfo(oldInfo->GetCheckSum());
00411 if (matchInfo) {
00412 curInfo = matchInfo;
00413 }
00414 }
00415 curInfo->ForceWriteInfo(toFile);
00416 } else {
00417
00418
00419
00420
00421
00422 oldInfo->ForceWriteInfo(toFile);
00423 }
00424 }
00425 delete l;
00426 }
00427
00428
00429 void TTreeCloner::CopyMemoryBaskets()
00430 {
00431
00432
00433 TBasket *basket = 0;
00434 for(Int_t i=0; i<fToBranches.GetEntries(); ++i) {
00435 TBranch *from = (TBranch*)fFromBranches.UncheckedAt( i );
00436 TBranch *to = (TBranch*)fToBranches.UncheckedAt( i );
00437
00438 basket = from->GetListOfBaskets()->GetEntries() ? from->GetBasket(from->GetWriteBasket()) : 0;
00439 if (basket) {
00440 basket = (TBasket*)basket->Clone();
00441 basket->SetBranch(to);
00442 to->AddBasket(*basket, kFALSE, fToStartEntries+from->GetBasketEntry()[from->GetWriteBasket()]);
00443 } else {
00444 to->AddLastBasket( fToStartEntries+from->GetBasketEntry()[from->GetWriteBasket()] );
00445 }
00446
00447
00448 if (from->GetEntries()!=0 && from->GetWriteBasket()==0 && (basket==0 || basket->GetNevBuf()==0)) {
00449 to->SetEntries(to->GetEntries()+from->GetEntries());
00450 }
00451 }
00452 }
00453
00454
00455 void TTreeCloner::CopyProcessIds()
00456 {
00457
00458
00459
00460
00461
00462 TFile *fromfile = fFromTree->GetDirectory()->GetFile();
00463 TFile *tofile = fToTree->GetDirectory()->GetFile();
00464
00465 fPidOffset = tofile->GetNProcessIDs();
00466
00467 TIter next(fromfile->GetListOfKeys());
00468 TKey *key;
00469 TDirectory::TContext cur(gDirectory,fromfile);
00470 while ((key = (TKey*)next())) {
00471 if (!strcmp(key->GetClassName(),"TProcessID")) {
00472 TProcessID *pid = (TProcessID*)key->ReadObjectAny(0);
00473
00474
00475 UShort_t out = 0;
00476 TObjArray *pids = tofile->GetListOfProcessIDs();
00477 Int_t npids = tofile->GetNProcessIDs();
00478 Bool_t wasIn = kFALSE;
00479 for (Int_t i=0;i<npids;i++) {
00480 if (pids->At(i) == pid) {out = (UShort_t)i; wasIn = kTRUE; break;}
00481 }
00482
00483 if (!wasIn) {
00484 TDirectory *dirsav = gDirectory;
00485 tofile->cd();
00486 tofile->SetBit(TFile::kHasReferences);
00487 pids->AddAtAndExpand(pid,npids);
00488 pid->IncrementCount();
00489 char name[32];
00490 snprintf(name,32,"ProcessID%d",npids);
00491 pid->Write(name);
00492 tofile->IncrementProcessIDs();
00493 if (gDebug > 0) {
00494 Info("WriteProcessID", "name=%s, file=%s", name, tofile->GetName());
00495 }
00496 if (dirsav) dirsav->cd();
00497 out = (UShort_t)npids;
00498 }
00499 if (out<fPidOffset) {
00500 Error("CopyProcessIDs","Copied %s from %s might already exist!\n",
00501 pid->GetName(),fromfile->GetName());
00502 }
00503 }
00504 }
00505 }
00506
00507
00508 void TTreeCloner::SortBaskets()
00509 {
00510
00511
00512
00513
00514
00515 switch (fCloneMethod) {
00516 case kSortBasketsByBranch:
00517
00518 break;
00519 case kSortBasketsByEntry: {
00520 for(UInt_t i = 0; i < fMaxBaskets; ++i) { fBasketIndex[i] = i; }
00521 std::sort(fBasketIndex, fBasketIndex+fMaxBaskets, CompareEntry( this) );
00522 break;
00523 }
00524 case kSortBasketsByOffset:
00525 default: {
00526 for(UInt_t i = 0; i < fMaxBaskets; ++i) { fBasketIndex[i] = i; }
00527 std::sort(fBasketIndex, fBasketIndex+fMaxBaskets, CompareSeek( this) );
00528 break;
00529 }
00530 }
00531 }
00532
00533
00534 void TTreeCloner::WriteBaskets()
00535 {
00536
00537
00538 TBasket *basket = new TBasket();
00539 for(UInt_t j=0; j<fMaxBaskets; ++j) {
00540 TBranch *from = (TBranch*)fFromBranches.UncheckedAt( fBasketBranchNum[ fBasketIndex[j] ] );
00541 TBranch *to = (TBranch*)fToBranches.UncheckedAt( fBasketBranchNum[ fBasketIndex[j] ] );
00542
00543 TFile *tofile = to->GetFile(0);
00544 TFile *fromfile = from->GetFile(0);
00545
00546 Int_t index = fBasketNum[ fBasketIndex[j] ];
00547
00548 Long64_t pos = from->GetBasketSeek(index);
00549 if (pos!=0) {
00550 if (from->GetBasketBytes()[index] == 0) {
00551 from->GetBasketBytes()[index] = basket->ReadBasketBytes(pos, fromfile);
00552 }
00553 Int_t len = from->GetBasketBytes()[index];
00554
00555 basket->LoadBasketBuffers(pos,len,fromfile);
00556 basket->IncrementPidOffset(fPidOffset);
00557 basket->CopyTo(tofile);
00558 to->AddBasket(*basket,kTRUE,fToStartEntries + from->GetBasketEntry()[index]);
00559 } else {
00560 TBasket *frombasket = from->GetBasket( index );
00561 if (frombasket->GetNevBuf()>0) {
00562 TBasket *tobasket = (TBasket*)frombasket->Clone();
00563 tobasket->SetBranch(to);
00564 to->AddBasket(*tobasket, kFALSE, fToStartEntries+from->GetBasketEntry()[index]);
00565 to->FlushOneBasket(to->GetWriteBasket());
00566 }
00567 }
00568 }
00569 delete basket;
00570 }