00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 #include "RConfig.h"
00061
00062 #ifdef R__LINUX
00063
00064 #ifndef _XOPEN_SOURCE
00065 #define _XOPEN_SOURCE 600
00066 #endif
00067 #endif
00068 #include <fcntl.h>
00069 #include <errno.h>
00070 #include <sys/stat.h>
00071 #ifndef WIN32
00072 # include <unistd.h>
00073 #else
00074 # define ssize_t int
00075 # include <io.h>
00076 # include <sys/types.h>
00077 #endif
00078
00079 #include "Bytes.h"
00080 #include "Riostream.h"
00081 #include "Strlen.h"
00082 #include "TArrayC.h"
00083 #include "TClass.h"
00084 #include "TClassEdit.h"
00085 #include "TClassTable.h"
00086 #include "TDatime.h"
00087 #include "TError.h"
00088 #include "TFile.h"
00089 #include "TFileCacheRead.h"
00090 #include "TFileCacheWrite.h"
00091 #include "TFree.h"
00092 #include "TInterpreter.h"
00093 #include "TKey.h"
00094 #include "TMakeProject.h"
00095 #include "TPluginManager.h"
00096 #include "TProcessUUID.h"
00097 #include "TRegexp.h"
00098 #include "TROOT.h"
00099 #include "TStreamerInfo.h"
00100 #include "TStreamerElement.h"
00101 #include "TSystem.h"
00102 #include "TTimeStamp.h"
00103 #include "TVirtualPerfStats.h"
00104 #include "TArchiveFile.h"
00105 #include "TEnv.h"
00106 #include "TVirtualMonitoring.h"
00107 #include "TVirtualMutex.h"
00108 #include "TMathBase.h"
00109 #include "TObjString.h"
00110 #include "TStopwatch.h"
00111 #include "compiledata.h"
00112 #include <cmath>
00113 #include <set>
00114 #include "TSchemaRule.h"
00115 #include "TSchemaRuleSet.h"
00116
00117 TFile *gFile;
00118
00119
00120 Long64_t TFile::fgBytesRead = 0;
00121 Long64_t TFile::fgBytesWrite = 0;
00122 Long64_t TFile::fgFileCounter = 0;
00123 Int_t TFile::fgReadaheadSize = 256000;
00124 Int_t TFile::fgReadCalls = 0;
00125 Bool_t TFile::fgReadInfo = kTRUE;
00126 TList *TFile::fgAsyncOpenRequests = 0;
00127 TString TFile::fgCacheFileDir;
00128 Bool_t TFile::fgCacheFileForce = kFALSE;
00129 Bool_t TFile::fgCacheFileDisconnected = kTRUE;
00130 UInt_t TFile::fgOpenTimeout = TFile::kEternalTimeout;
00131 Bool_t TFile::fgOnlyStaged = 0;
00132
00133 const Int_t kBEGIN = 100;
00134
00135 ClassImp(TFile)
00136
00137
00138
00139
00140 TFile::TFile() : TDirectoryFile(), fInfoCache(0)
00141 {
00142
00143
00144 fD = -1;
00145 fFree = 0;
00146 fWritten = 0;
00147 fSumBuffer = 0;
00148 fSum2Buffer = 0;
00149 fClassIndex = 0;
00150 fProcessIDs = 0;
00151 fNProcessIDs = 0;
00152 fOffset = 0;
00153 fArchive = 0;
00154 fCacheRead = 0;
00155 fCacheWrite = 0;
00156 fArchiveOffset = 0;
00157 fReadCalls = 0;
00158 fInfoCache = 0;
00159 fOpenPhases = 0;
00160 fNoAnchorInName = kFALSE;
00161 fIsRootFile = kTRUE;
00162 fIsArchive = kFALSE;
00163 fInitDone = kFALSE;
00164 fMustFlush = kTRUE;
00165 fAsyncHandle = 0;
00166 fAsyncOpenStatus = kAOSNotAsync;
00167 SetBit(kBinaryFile, kTRUE);
00168
00169 if (gDebug)
00170 Info("TFile", "default ctor");
00171 }
00172
00173
00174 TFile::TFile(const char *fname1, Option_t *option, const char *ftitle, Int_t compress)
00175 : TDirectoryFile(), fUrl(fname1,kTRUE), fInfoCache(0), fOpenPhases(0)
00176 {
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 if (!gROOT)
00268 ::Fatal("TFile::TFile", "ROOT system not initialized");
00269
00270
00271 TString sfname1 = fname1;
00272 fNoAnchorInName = kFALSE;
00273 if (sfname1.Index("?") != kNPOS) {
00274 TString s = sfname1(0, sfname1.Index("?"));
00275 SetName(s);
00276 fNoAnchorInName = kTRUE;
00277 } else
00278 SetName(fname1);
00279
00280 SetTitle(ftitle);
00281
00282
00283 fname1 = fUrl.GetFile();
00284
00285
00286 fIsRootFile = kTRUE;
00287 if (strstr(fUrl.GetOptions(), "filetype=raw"))
00288 fIsRootFile = kFALSE;
00289
00290
00291 fInitDone = kFALSE;
00292 fMustFlush = kTRUE;
00293
00294
00295 fAsyncHandle = 0;
00296 fAsyncOpenStatus = kAOSNotAsync;
00297
00298 TDirectoryFile::Build(this, 0);
00299
00300 fD = -1;
00301 fFree = 0;
00302 fVersion = gROOT->GetVersionInt();
00303 fUnits = 4;
00304 fOption = option;
00305 fCompress = compress;
00306 fWritten = 0;
00307 fSumBuffer = 0;
00308 fSum2Buffer = 0;
00309 fBytesRead = 0;
00310 fBytesReadExtra = 0;
00311 fBytesWrite = 0;
00312 fClassIndex = 0;
00313 fSeekInfo = 0;
00314 fNbytesInfo = 0;
00315 fProcessIDs = 0;
00316 fNProcessIDs = 0;
00317 fOffset = 0;
00318 fCacheRead = 0;
00319 fCacheWrite = 0;
00320 fReadCalls = 0;
00321 SetBit(kBinaryFile, kTRUE);
00322
00323 fOption.ToUpper();
00324
00325 fArchiveOffset = 0;
00326 fIsArchive = kFALSE;
00327 fArchive = 0;
00328 if (fIsRootFile) {
00329 fArchive = TArchiveFile::Open(fUrl.GetUrl(), this);
00330 if (fArchive) {
00331 fname1 = fArchive->GetArchiveName();
00332
00333
00334 if (!strlen(fArchive->GetMemberName()))
00335 fIsArchive = kTRUE;
00336 }
00337 }
00338
00339 if (fOption == "NET")
00340 return;
00341
00342 if (fOption == "WEB") {
00343 fOption = "READ";
00344 fWritable = kFALSE;
00345 return;
00346 }
00347
00348 if (fOption == "NEW")
00349 fOption = "CREATE";
00350
00351 Bool_t create = (fOption == "CREATE") ? kTRUE : kFALSE;
00352 Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE;
00353 Bool_t update = (fOption == "UPDATE") ? kTRUE : kFALSE;
00354 Bool_t read = (fOption == "READ") ? kTRUE : kFALSE;
00355 if (!create && !recreate && !update && !read) {
00356 read = kTRUE;
00357 fOption = "READ";
00358 }
00359
00360 Bool_t devnull = kFALSE;
00361
00362 if (!fname1 || !strlen(fname1)) {
00363 Error("TFile", "file name is not specified");
00364 goto zombie;
00365 }
00366
00367
00368 if (!strcmp(fname1, "/dev/null") &&
00369 !gSystem->AccessPathName(fname1, kWritePermission)) {
00370 devnull = kTRUE;
00371 create = kTRUE;
00372 recreate = kFALSE;
00373 update = kFALSE;
00374 read = kFALSE;
00375 fOption = "CREATE";
00376 SetBit(kDevNull);
00377 }
00378
00379 const char *fname;
00380 if ((fname = gSystem->ExpandPathName(fname1))) {
00381 SetName(fname);
00382 delete [] fname;
00383 fRealName = GetName();
00384 fname = fRealName.Data();
00385 } else {
00386 Error("TFile", "error expanding path %s", fname1);
00387 goto zombie;
00388 }
00389
00390 if (recreate) {
00391 if (!gSystem->AccessPathName(fname, kFileExists))
00392 gSystem->Unlink(fname);
00393 recreate = kFALSE;
00394 create = kTRUE;
00395 fOption = "CREATE";
00396 }
00397 if (create && !devnull && !gSystem->AccessPathName(fname, kFileExists)) {
00398 Error("TFile", "file %s already exists", fname);
00399 goto zombie;
00400 }
00401 if (update) {
00402 if (gSystem->AccessPathName(fname, kFileExists)) {
00403 update = kFALSE;
00404 create = kTRUE;
00405 }
00406 if (update && gSystem->AccessPathName(fname, kWritePermission)) {
00407 Error("TFile", "no write permission, could not open file %s", fname);
00408 goto zombie;
00409 }
00410 }
00411 if (read) {
00412 if (gSystem->AccessPathName(fname, kFileExists)) {
00413 Error("TFile", "file %s does not exist", fname);
00414 goto zombie;
00415 }
00416 if (gSystem->AccessPathName(fname, kReadPermission)) {
00417 Error("TFile", "no read permission, could not open file %s", fname);
00418 goto zombie;
00419 }
00420 }
00421
00422
00423 if (create || update) {
00424 #ifndef WIN32
00425 fD = SysOpen(fname, O_RDWR | O_CREAT, 0644);
00426 #else
00427 fD = SysOpen(fname, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
00428 #endif
00429 if (fD == -1) {
00430 SysError("TFile", "file %s can not be opened", fname);
00431 goto zombie;
00432 }
00433 fWritable = kTRUE;
00434 } else {
00435 #ifndef WIN32
00436 fD = SysOpen(fname, O_RDONLY, 0644);
00437 #else
00438 fD = SysOpen(fname, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
00439 #endif
00440 if (fD == -1) {
00441 SysError("TFile", "file %s can not be opened for reading", fname);
00442 goto zombie;
00443 }
00444 fWritable = kFALSE;
00445 }
00446
00447 Init(create);
00448
00449 return;
00450
00451 zombie:
00452
00453 MakeZombie();
00454 gDirectory = gROOT;
00455 }
00456
00457
00458 TFile::TFile(const TFile &) : TDirectoryFile(), fInfoCache(0)
00459 {
00460
00461
00462 MayNotUse("TFile::TFile(const TFile &)");
00463 }
00464
00465
00466 TFile::~TFile()
00467 {
00468
00469
00470 Close();
00471
00472 SafeDelete(fProcessIDs);
00473 SafeDelete(fFree);
00474 SafeDelete(fArchive);
00475 SafeDelete(fInfoCache);
00476 SafeDelete(fOpenPhases);
00477 SafeDelete(fAsyncHandle);
00478 SafeDelete(fCacheRead);
00479 SafeDelete(fCacheWrite);
00480
00481 R__LOCKGUARD2(gROOTMutex);
00482 gROOT->GetListOfFiles()->Remove(this);
00483 gROOT->GetUUIDs()->RemoveUUID(GetUniqueID());
00484
00485 if (gDebug)
00486 Info("~TFile", "dtor called for %s [%lx]", GetName(),(Long_t)this);
00487 }
00488
00489
00490 void TFile::Init(Bool_t create)
00491 {
00492
00493
00494
00495
00496
00497 if (fInitDone)
00498
00499 return;
00500 fInitDone = kTRUE;
00501
00502 if (!fIsRootFile) {
00503 gDirectory = gROOT;
00504 return;
00505 }
00506
00507 if (fArchive) {
00508 if (fOption != "READ") {
00509 Error("Init", "archive %s can only be opened in read mode", GetName());
00510 delete fArchive;
00511 fArchive = 0;
00512 fIsArchive = kFALSE;
00513 goto zombie;
00514 }
00515
00516 fArchive->OpenArchive();
00517
00518 if (fIsArchive) return;
00519
00520
00521 if (!fNoAnchorInName)
00522 if (!strchr(GetName(),'#'))
00523 SetName(Form("%s#%s", GetName(), fArchive->GetMemberName()));
00524
00525 if (fArchive->SetCurrentMember() != -1)
00526 fArchiveOffset = fArchive->GetMemberFilePosition();
00527 else {
00528 Error("Init", "member %s not found in archive %s",
00529 fArchive->GetMemberName(), fArchive->GetArchiveName());
00530 delete fArchive;
00531 fArchive = 0;
00532 fIsArchive = kFALSE;
00533 goto zombie;
00534 }
00535 }
00536
00537 Int_t nfree;
00538 fBEGIN = (Long64_t)kBEGIN;
00539
00540
00541 cd();
00542
00543 if (create) {
00544
00545 fFree = new TList;
00546 fEND = fBEGIN;
00547 new TFree(fFree, fBEGIN, Long64_t(kStartBigFile));
00548
00549
00550 Int_t namelen= TNamed::Sizeof();
00551 Int_t nbytes = namelen + TDirectoryFile::Sizeof();
00552 TKey *key = new TKey(fName, fTitle, IsA(), nbytes, this);
00553 fNbytesName = key->GetKeylen() + namelen;
00554 fSeekDir = key->GetSeekKey();
00555 fSeekFree = 0;
00556 fNbytesFree = 0;
00557 WriteHeader();
00558 char *buffer = key->GetBuffer();
00559 TNamed::FillBuffer(buffer);
00560 TDirectoryFile::FillBuffer(buffer);
00561 key->WriteFile();
00562 delete key;
00563 } else {
00564
00565
00566 char *header = new char[kBEGIN+200];
00567 Seek(0);
00568
00569 ReadBuffer(header, kBEGIN+200);
00570
00571
00572 if (strncmp(header, "root", 4)) {
00573 Error("Init", "%s not a ROOT file", GetName());
00574 delete [] header;
00575 goto zombie;
00576 }
00577
00578 char *buffer = header + 4;
00579 frombuf(buffer, &fVersion);
00580 Int_t headerLength;
00581 frombuf(buffer, &headerLength);
00582 fBEGIN = (Long64_t)headerLength;
00583 if (fVersion < 1000000) {
00584 Int_t send,sfree,sinfo;
00585 frombuf(buffer, &send); fEND = (Long64_t)send;
00586 frombuf(buffer, &sfree); fSeekFree= (Long64_t)sfree;
00587 frombuf(buffer, &fNbytesFree);
00588 frombuf(buffer, &nfree);
00589 frombuf(buffer, &fNbytesName);
00590 frombuf(buffer, &fUnits );
00591 frombuf(buffer, &fCompress);
00592 frombuf(buffer, &sinfo); fSeekInfo = (Long64_t)sinfo;
00593 frombuf(buffer, &fNbytesInfo);
00594 } else {
00595 frombuf(buffer, &fEND);
00596 frombuf(buffer, &fSeekFree);
00597 frombuf(buffer, &fNbytesFree);
00598 frombuf(buffer, &nfree);
00599 frombuf(buffer, &fNbytesName);
00600 frombuf(buffer, &fUnits );
00601 frombuf(buffer, &fCompress);
00602 frombuf(buffer, &fSeekInfo);
00603 frombuf(buffer, &fNbytesInfo);
00604 }
00605 fSeekDir = fBEGIN;
00606
00607 if (fWritable) {
00608 fFree = new TList;
00609 if (fSeekFree > fBEGIN) {
00610 ReadFree();
00611 } else {
00612 Warning("Init","file %s probably not closed, cannot read free segments",GetName());
00613 }
00614 }
00615
00616
00617 char *buffer_keyloc = 0;
00618
00619 Int_t nbytes = fNbytesName + TDirectoryFile::Sizeof();
00620 if (nbytes+fBEGIN > kBEGIN+200) {
00621 delete [] header;
00622 header = new char[nbytes];
00623 buffer = header;
00624 Seek(fBEGIN);
00625 ReadBuffer(buffer,nbytes);
00626 buffer = header+fNbytesName;
00627 buffer_keyloc = header;
00628 } else {
00629 buffer = header+fBEGIN+fNbytesName;
00630 buffer_keyloc = header+fBEGIN;
00631 }
00632 Version_t version,versiondir;
00633 frombuf(buffer,&version); versiondir = version%1000;
00634 fDatimeC.ReadBuffer(buffer);
00635 fDatimeM.ReadBuffer(buffer);
00636 frombuf(buffer, &fNbytesKeys);
00637 frombuf(buffer, &fNbytesName);
00638 if (version > 1000) {
00639 frombuf(buffer, &fSeekDir);
00640 frombuf(buffer, &fSeekParent);
00641 frombuf(buffer, &fSeekKeys);
00642 } else {
00643 Int_t sdir,sparent,skeys;
00644 frombuf(buffer, &sdir); fSeekDir = (Long64_t)sdir;
00645 frombuf(buffer, &sparent); fSeekParent = (Long64_t)sparent;
00646 frombuf(buffer, &skeys); fSeekKeys = (Long64_t)skeys;
00647 }
00648 if (versiondir > 1) fUUID.ReadBuffer(buffer);
00649
00650
00651 buffer_keyloc += sizeof(Int_t);
00652 Version_t keyversion;
00653 frombuf(buffer_keyloc, &keyversion);
00654
00655 if (keyversion > 1000) {
00656
00657 buffer_keyloc += 2*sizeof(Int_t)+2*sizeof(Short_t)+2*sizeof(Long64_t);
00658 } else {
00659 buffer_keyloc += 2*sizeof(Int_t)+2*sizeof(Short_t)+2*sizeof(Int_t);
00660 }
00661 TString cname;
00662 cname.ReadBuffer(buffer_keyloc);
00663 cname.ReadBuffer(buffer_keyloc);
00664 fTitle.ReadBuffer(buffer_keyloc);
00665 delete [] header;
00666 if (fNbytesName < 10 || fNbytesName > 10000) {
00667 Error("Init","cannot read directory info of file %s", GetName());
00668 goto zombie;
00669 }
00670
00671
00672 Long64_t size;
00673 if ((size = GetSize()) == -1) {
00674 Error("Init", "cannot stat the file %s", GetName());
00675 goto zombie;
00676 }
00677
00678
00679
00680 Bool_t tryrecover = (gEnv->GetValue("TFile.Recover", 1) == 1) ? kTRUE : kFALSE;
00681
00682
00683 if (fSeekKeys > fBEGIN && fEND <= size) {
00684
00685 TDirectoryFile::ReadKeys(kFALSE);
00686 gDirectory = this;
00687 if (!GetNkeys()) {
00688 if (tryrecover) {
00689 Recover();
00690 } else {
00691 Error("Init", "file %s has no keys", GetName());
00692 goto zombie;
00693 }
00694 }
00695 } else if ((fBEGIN+nbytes == fEND) && (fEND == size)) {
00696
00697 Warning("Init","file %s has no keys", GetName());
00698 gDirectory = this;
00699 } else {
00700
00701 if (fEND > size) {
00702 if (tryrecover) {
00703 Error("Init","file %s is truncated at %lld bytes: should be %lld, "
00704 "trying to recover", GetName(), size, fEND);
00705 } else {
00706 Error("Init","file %s is truncated at %lld bytes: should be %lld",
00707 GetName(), size, fEND);
00708 goto zombie;
00709 }
00710 } else {
00711 if (tryrecover) {
00712 Warning("Init","file %s probably not closed, "
00713 "trying to recover", GetName());
00714 } else {
00715 Warning("Init","file %s probably not closed", GetName());
00716 goto zombie;
00717 }
00718 }
00719 Int_t nrecov = Recover();
00720 if (nrecov) {
00721 Warning("Init", "successfully recovered %d keys", nrecov);
00722 } else {
00723 Warning("Init", "no keys recovered, file has been made a Zombie");
00724 goto zombie;
00725 }
00726 }
00727 }
00728
00729 {
00730 R__LOCKGUARD2(gROOTMutex);
00731 gROOT->GetListOfFiles()->Add(this);
00732 gROOT->GetUUIDs()->AddUUID(fUUID,this);
00733 }
00734
00735
00736 {
00737 Int_t lenIndex = gROOT->GetListOfStreamerInfo()->GetSize()+1;
00738 if (lenIndex < 5000) lenIndex = 5000;
00739 fClassIndex = new TArrayC(lenIndex);
00740 if (fgReadInfo) {
00741 if (fSeekInfo > fBEGIN) {
00742 ReadStreamerInfo();
00743 } else if (fVersion != gROOT->GetVersionInt() && fVersion > 30000) {
00744 Warning("Init","no StreamerInfo found in %s therefore preventing schema evolution when reading this file.",GetName());
00745 }
00746 }
00747 }
00748
00749
00750 {
00751 TIter next(fKeys);
00752 TKey *key;
00753 while ((key = (TKey*)next())) {
00754 if (!strcmp(key->GetClassName(),"TProcessID")) fNProcessIDs++;
00755 }
00756 fProcessIDs = new TObjArray(fNProcessIDs+1);
00757 return;
00758 }
00759
00760 zombie:
00761
00762 MakeZombie();
00763 gDirectory = gROOT;
00764 }
00765
00766
00767 void TFile::Close(Option_t *option)
00768 {
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778 TString opt = option;
00779
00780 opt.ToLower();
00781
00782 if (!IsOpen()) return;
00783
00784 if (fIsArchive || !fIsRootFile) {
00785 FlushWriteCache();
00786 SysClose(fD);
00787 fD = -1;
00788
00789 if (gMonitoringWriter)
00790 gMonitoringWriter->SendFileCloseEvent(this);
00791
00792 return;
00793 }
00794
00795 if (IsWritable()) {
00796 WriteStreamerInfo();
00797 }
00798
00799 delete fClassIndex;
00800 fClassIndex = 0;
00801
00802
00803
00804
00805 TDirectoryFile::Close();
00806
00807 if (IsWritable()) {
00808 TFree *f1 = (TFree*)fFree->First();
00809 if (f1) {
00810 WriteFree();
00811 WriteHeader();
00812 }
00813 }
00814
00815 FlushWriteCache();
00816
00817 if (gMonitoringWriter)
00818 gMonitoringWriter->SendFileCloseEvent(this);
00819
00820
00821 if (fFree) {
00822 fFree->Delete();
00823 }
00824
00825 if (IsOpen()) {
00826 SysClose(fD);
00827 fD = -1;
00828 }
00829
00830 fWritable = kFALSE;
00831
00832
00833 TList pidDeleted;
00834 TIter next(fProcessIDs);
00835 TProcessID *pid;
00836 while ((pid = (TProcessID*)next())) {
00837 if (!pid->DecrementCount()) {
00838 if (pid != TProcessID::GetSessionProcessID()) pidDeleted.Add(pid);
00839 } else if(opt.Contains("r")) {
00840 pid->Clear();
00841 }
00842 }
00843 pidDeleted.Delete();
00844
00845 R__LOCKGUARD2(gROOTMutex);
00846 gROOT->GetListOfFiles()->Remove(this);
00847 gROOT->GetListOfBrowsers()->RecursiveRemove(this);
00848 }
00849
00850
00851 TKey* TFile::CreateKey(TDirectory* mother, const TObject* obj, const char* name, Int_t bufsize)
00852 {
00853
00854
00855 return new TKey(obj, name, bufsize, mother);
00856 }
00857
00858
00859 TKey* TFile::CreateKey(TDirectory* mother, const void* obj, const TClass* cl, const char* name, Int_t bufsize)
00860 {
00861
00862
00863 return new TKey(obj, cl, name, bufsize, mother);
00864 }
00865
00866
00867 void TFile::Delete(const char *namecycle)
00868 {
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885 if (gDebug)
00886 Info("Delete", "deleting name = %s", namecycle);
00887
00888 TDirectoryFile::Delete(namecycle);
00889 }
00890
00891
00892 void TFile::Draw(Option_t *option)
00893 {
00894
00895
00896
00897 GetList()->R__FOR_EACH(TObject,Draw)(option);
00898 }
00899
00900
00901 void TFile::DrawMap(const char *keys, Option_t *option)
00902 {
00903
00904
00905 TPluginHandler *h;
00906 if ((h = gROOT->GetPluginManager()->FindHandler("TFileDrawMap"))) {
00907 if (h->LoadPlugin() == -1)
00908 return;
00909 h->ExecPlugin(3, this, keys, option);
00910 }
00911 }
00912
00913
00914 void TFile::Flush()
00915 {
00916
00917 if (IsOpen() && fWritable) {
00918 FlushWriteCache();
00919 if (SysSync(fD) < 0) {
00920
00921 SetBit(kWriteError); SetWritable(kFALSE);
00922 SysError("Flush", "error flushing file %s", GetName());
00923 }
00924 }
00925 }
00926
00927
00928 Bool_t TFile::FlushWriteCache()
00929 {
00930
00931
00932
00933 if (fCacheWrite && IsOpen() && fWritable)
00934 return fCacheWrite->Flush();
00935 return kFALSE;
00936 }
00937
00938
00939 void TFile::FillBuffer(char *&buffer)
00940 {
00941
00942
00943
00944 Version_t version = TFile::Class_Version();
00945 tobuf(buffer, version);
00946 }
00947
00948
00949 Int_t TFile::GetBestBuffer() const
00950 {
00951
00952
00953
00954
00955
00956 if (!fWritten) return TBuffer::kInitialSize;
00957 Double_t mean = fSumBuffer/fWritten;
00958 Double_t rms2 = TMath::Abs(fSum2Buffer/fSumBuffer -mean*mean);
00959 return (Int_t)(mean + sqrt(rms2));
00960 }
00961
00962
00963 Float_t TFile::GetCompressionFactor()
00964 {
00965
00966
00967
00968
00969 Short_t keylen;
00970 UInt_t datime;
00971 Int_t nbytes, objlen, nwh = 64;
00972 char *header = new char[fBEGIN];
00973 char *buffer;
00974 Long64_t idcur = fBEGIN;
00975 Float_t comp,uncomp;
00976 comp = uncomp = fBEGIN;
00977
00978 while (idcur < fEND-100) {
00979 Seek(idcur);
00980 ReadBuffer(header, nwh);
00981 buffer=header;
00982 frombuf(buffer, &nbytes);
00983 if (nbytes < 0) {
00984 idcur -= nbytes;
00985 Seek(idcur);
00986 continue;
00987 }
00988 if (nbytes == 0) break;
00989 Version_t versionkey;
00990 frombuf(buffer, &versionkey);
00991 frombuf(buffer, &objlen);
00992 frombuf(buffer, &datime);
00993 frombuf(buffer, &keylen);
00994 if (!objlen) objlen = nbytes-keylen;
00995 comp += nbytes;
00996 uncomp += keylen + objlen;
00997 idcur += nbytes;
00998 }
00999 delete [] header;
01000 return uncomp/comp;
01001 }
01002
01003
01004 Int_t TFile::GetErrno() const
01005 {
01006
01007
01008 return TSystem::GetErrno();
01009 }
01010
01011
01012 void TFile::ResetErrno() const
01013 {
01014
01015
01016 TSystem::ResetErrno();
01017 }
01018
01019
01020 TFileCacheRead *TFile::GetCacheRead() const
01021 {
01022
01023
01024 return fCacheRead;
01025 }
01026
01027
01028 TFileCacheWrite *TFile::GetCacheWrite() const
01029 {
01030
01031
01032 return fCacheWrite;
01033 }
01034
01035
01036 Int_t TFile::GetRecordHeader(char *buf, Long64_t first, Int_t maxbytes, Int_t &nbytes, Int_t &objlen, Int_t &keylen)
01037 {
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051 if (first < fBEGIN) return 0;
01052 if (first > fEND) return 0;
01053 Seek(first);
01054 Int_t nread = maxbytes;
01055 if (first+maxbytes > fEND) nread = fEND-maxbytes;
01056 if (nread < 4) {
01057 Warning("GetRecordHeader","%s: parameter maxbytes = %d must be >= 4",
01058 GetName(), nread);
01059 return nread;
01060 }
01061 ReadBuffer(buf,nread);
01062 Version_t versionkey;
01063 Short_t klen;
01064 UInt_t datime;
01065 Int_t nb,olen;
01066 char *buffer = buf;
01067 frombuf(buffer,&nb);
01068 nbytes = nb;
01069 if (nb < 0) return nread;
01070
01071 const Int_t headerSize = 16;
01072 if (nread < headerSize) return nread;
01073 frombuf(buffer, &versionkey);
01074 frombuf(buffer, &olen);
01075 frombuf(buffer, &datime);
01076 frombuf(buffer, &klen);
01077 if (!olen) olen = nbytes-klen;
01078 objlen = olen;
01079 keylen = klen;
01080 return nread;
01081 }
01082
01083
01084 Long64_t TFile::GetSize() const
01085 {
01086
01087
01088
01089 Long64_t size;
01090
01091 if (fArchive && fArchive->GetMember()) {
01092 size = fArchive->GetMember()->GetDecompressedSize();
01093 } else {
01094 Long_t id, flags, modtime;
01095 if (const_cast<TFile*>(this)->SysStat(fD, &id, &size, &flags, &modtime)) {
01096 Error("GetSize", "cannot stat the file %s", GetName());
01097 return -1;
01098 }
01099 }
01100 return size;
01101 }
01102
01103
01104 const TList *TFile::GetStreamerInfoCache()
01105 {
01106
01107
01108 return fInfoCache ? fInfoCache : (fInfoCache=GetStreamerInfoList());
01109 }
01110
01111
01112 TList *TFile::GetStreamerInfoList()
01113 {
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125 TList *list = 0;
01126 if (fSeekInfo) {
01127 TDirectory::TContext ctx(gDirectory,this);
01128 TKey *key = new TKey(this);
01129 char *buffer = new char[fNbytesInfo+1];
01130 char *buf = buffer;
01131 Seek(fSeekInfo);
01132 ReadBuffer(buf,fNbytesInfo);
01133 key->ReadKeyBuffer(buf);
01134 list = (TList*)key->ReadObjWithBuffer(buffer);
01135 if (list) list->SetOwner();
01136 delete [] buffer;
01137 delete key;
01138 } else {
01139 list = (TList*)Get("StreamerInfo");
01140 }
01141
01142 if (list == 0) {
01143 Info("GetStreamerInfoList", "cannot find the StreamerInfo record in file %s",
01144 GetName());
01145 return 0;
01146 }
01147
01148 return list;
01149 }
01150
01151
01152 void TFile::ls(Option_t *option) const
01153 {
01154
01155
01156
01157
01158
01159 TROOT::IndentLevel();
01160 cout <<ClassName()<<"**\t\t"<<GetName()<<"\t"<<GetTitle()<<endl;
01161 TROOT::IncreaseDirLevel();
01162 TDirectoryFile::ls(option);
01163 TROOT::DecreaseDirLevel();
01164 }
01165
01166
01167 Bool_t TFile::IsOpen() const
01168 {
01169
01170
01171 return fD == -1 ? kFALSE : kTRUE;
01172 }
01173
01174
01175 void TFile::MakeFree(Long64_t first, Long64_t last)
01176 {
01177
01178
01179
01180
01181
01182
01183
01184
01185 TFree *f1 = (TFree*)fFree->First();
01186 if (!f1) return;
01187 TFree *newfree = f1->AddFree(fFree,first,last);
01188 if(!newfree) return;
01189 Long64_t nfirst = newfree->GetFirst();
01190 Long64_t nlast = newfree->GetLast();
01191 Long64_t nbytesl= nlast-nfirst+1;
01192 if (nbytesl > 2000000000) nbytesl = 2000000000;
01193 Int_t nbytes = -Int_t (nbytesl);
01194 Int_t nb = sizeof(Int_t);
01195 char * buffer = new char[nb];
01196 char * psave = buffer;
01197 tobuf(buffer, nbytes);
01198 if (last == fEND-1) fEND = nfirst;
01199 Seek(nfirst);
01200 WriteBuffer(psave, nb);
01201 Flush();
01202 delete [] psave;
01203 }
01204
01205
01206 void TFile::Map()
01207 {
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238 Short_t keylen,cycle;
01239 UInt_t datime;
01240 Int_t nbytes,date,time,objlen,nwheader;
01241 Long64_t seekkey,seekpdir;
01242 char *buffer;
01243 char nwhc;
01244 Long64_t idcur = fBEGIN;
01245
01246 nwheader = 64;
01247 Int_t nread = nwheader;
01248
01249 char header[kBEGIN];
01250 char classname[512];
01251
01252 while (idcur < fEND) {
01253 Seek(idcur);
01254 if (idcur+nread >= fEND) nread = fEND-idcur-1;
01255 ReadBuffer(header, nread);
01256 buffer=header;
01257 frombuf(buffer, &nbytes);
01258 if (!nbytes) {
01259 Printf("Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes);
01260 date = 0; time = 0;
01261 break;
01262 }
01263 if (nbytes < 0) {
01264 Printf("Address = %lld\tNbytes = %d\t=====G A P===========", idcur, nbytes);
01265 idcur -= nbytes;
01266 Seek(idcur);
01267 continue;
01268 }
01269 Version_t versionkey;
01270 frombuf(buffer, &versionkey);
01271 frombuf(buffer, &objlen);
01272 frombuf(buffer, &datime);
01273 frombuf(buffer, &keylen);
01274 frombuf(buffer, &cycle);
01275 if (versionkey > 1000) {
01276 frombuf(buffer, &seekkey);
01277 frombuf(buffer, &seekpdir);
01278 } else {
01279 Int_t skey,sdir;
01280 frombuf(buffer, &skey); seekkey = (Long64_t)skey;
01281 frombuf(buffer, &sdir); seekpdir = (Long64_t)sdir;
01282 }
01283 frombuf(buffer, &nwhc);
01284 for (int i = 0;i < nwhc; i++) frombuf(buffer, &classname[i]);
01285 classname[(int)nwhc] = '\0';
01286 if (idcur == fSeekFree) strlcpy(classname,"FreeSegments",512);
01287 if (idcur == fSeekInfo) strlcpy(classname,"StreamerInfo",512);
01288 if (idcur == fSeekKeys) strlcpy(classname,"KeysList",512);
01289 TDatime::GetDateTime(datime, date, time);
01290 if (objlen != nbytes-keylen) {
01291 Float_t cx = Float_t(objlen+keylen)/Float_t(nbytes);
01292 Printf("%d/%06d At:%lld N=%-8d %-14s CX = %5.2f",date,time,idcur,nbytes,classname,cx);
01293 } else {
01294 Printf("%d/%06d At:%lld N=%-8d %-14s",date,time,idcur,nbytes,classname);
01295 }
01296 idcur += nbytes;
01297 }
01298 Printf("%d/%06d At:%lld N=%-8d %-14s",date,time,idcur,1,"END");
01299 }
01300
01301
01302 void TFile::Paint(Option_t *option)
01303 {
01304
01305
01306 GetList()->R__FOR_EACH(TObject,Paint)(option);
01307 }
01308
01309
01310 void TFile::Print(Option_t *option) const
01311 {
01312
01313
01314 Printf("TFile: name=%s, title=%s, option=%s", GetName(), GetTitle(), GetOption());
01315 GetList()->R__FOR_EACH(TObject,Print)(option);
01316 }
01317
01318
01319 Bool_t TFile::ReadBuffer(char *buf, Long64_t pos, Int_t len)
01320 {
01321
01322
01323
01324
01325
01326
01327 if (IsOpen()) {
01328
01329 SetOffset(pos);
01330
01331 Int_t st;
01332 if ((st = ReadBufferViaCache(buf, len))) {
01333 if (st == 2)
01334 return kTRUE;
01335 return kFALSE;
01336 }
01337
01338 Seek(pos);
01339
01340 ssize_t siz;
01341 Double_t start = 0;
01342 if (gPerfStats != 0) start = TTimeStamp();
01343
01344 while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
01345 ResetErrno();
01346
01347 if (siz < 0) {
01348 SysError("ReadBuffer", "error reading from file %s", GetName());
01349 return kTRUE;
01350 }
01351 if (siz != len) {
01352 Error("ReadBuffer", "error reading all requested bytes from file %s, got %ld of %d",
01353 GetName(), (Long_t)siz, len);
01354 return kTRUE;
01355 }
01356 fBytesRead += siz;
01357 fgBytesRead += siz;
01358 fReadCalls++;
01359 fgReadCalls++;
01360
01361 if (gMonitoringWriter)
01362 gMonitoringWriter->SendFileReadProgress(this);
01363 if (gPerfStats != 0) {
01364 gPerfStats->FileReadEvent(this, len, start);
01365 }
01366 return kFALSE;
01367 }
01368 return kTRUE;
01369 }
01370
01371
01372 Bool_t TFile::ReadBuffer(char *buf, Int_t len)
01373 {
01374
01375
01376
01377 if (IsOpen()) {
01378
01379 Int_t st;
01380 if ((st = ReadBufferViaCache(buf, len))) {
01381 if (st == 2)
01382 return kTRUE;
01383 return kFALSE;
01384 }
01385
01386 ssize_t siz;
01387
01388 Double_t start = 0;
01389 if (gPerfStats != 0) start = TTimeStamp();
01390
01391 while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
01392 ResetErrno();
01393
01394 if (siz < 0) {
01395 SysError("ReadBuffer", "error reading from file %s", GetName());
01396 return kTRUE;
01397 }
01398 if (siz != len) {
01399 Error("ReadBuffer", "error reading all requested bytes from file %s, got %ld of %d",
01400 GetName(), (Long_t)siz, len);
01401 return kTRUE;
01402 }
01403 fBytesRead += siz;
01404 fgBytesRead += siz;
01405 fReadCalls++;
01406 fgReadCalls++;
01407
01408 if (gMonitoringWriter)
01409 gMonitoringWriter->SendFileReadProgress(this);
01410 if (gPerfStats != 0) {
01411 gPerfStats->FileReadEvent(this, len, start);
01412 }
01413 return kFALSE;
01414 }
01415 return kTRUE;
01416 }
01417
01418
01419 Bool_t TFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
01420 {
01421
01422
01423
01424
01425
01426
01427
01428 if (!buf) {
01429 for (Int_t j = 0; j < nbuf; j++) {
01430 if (ReadBufferAsync(pos[j], len[j])) {
01431 return kTRUE;
01432 }
01433 }
01434 return kFALSE;
01435 }
01436
01437 Int_t k = 0;
01438 Bool_t result = kTRUE;
01439 TFileCacheRead *old = fCacheRead;
01440 fCacheRead = 0;
01441 Long64_t curbegin = pos[0];
01442 Long64_t cur;
01443 char *buf2 = 0;
01444 Int_t i = 0, n = 0;
01445 while (i < nbuf) {
01446 cur = pos[i]+len[i];
01447 Bool_t bigRead = kTRUE;
01448 if (cur -curbegin < fgReadaheadSize) {n++; i++; bigRead = kFALSE;}
01449 if (bigRead || (i>=nbuf)) {
01450 if (n == 0) {
01451
01452
01453 Seek(pos[i]);
01454 result = ReadBuffer(&buf[k], len[i]);
01455 if (result) break;
01456 k += len[i];
01457 i++;
01458 } else {
01459
01460 Seek(curbegin);
01461 if (buf2 == 0) buf2 = new char[fgReadaheadSize];
01462
01463 Long64_t nahead = pos[i-1]+len[i-1]-curbegin;
01464 result = ReadBuffer(buf2, nahead);
01465 if (result) break;
01466
01467 Int_t kold = k;
01468 for (Int_t j=0;j<n;j++) {
01469 memcpy(&buf[k],&buf2[pos[i-n+j]-curbegin],len[i-n+j]);
01470 k += len[i-n+j];
01471 }
01472 Int_t nok = k-kold;
01473 Long64_t extra = nahead-nok;
01474 fBytesReadExtra += extra;
01475 fBytesRead -= extra;
01476 fgBytesRead -= extra;
01477 n = 0;
01478 }
01479 curbegin = pos[i];
01480 }
01481 }
01482 if (buf2) delete [] buf2;
01483 fCacheRead = old;
01484 return result;
01485 }
01486
01487
01488 Int_t TFile::ReadBufferViaCache(char *buf, Int_t len)
01489 {
01490
01491
01492
01493
01494 Long64_t off = GetRelOffset();
01495 if (fCacheRead) {
01496 Int_t st = fCacheRead->ReadBuffer(buf, off, len);
01497 if (st < 0)
01498 return 2;
01499 else if (st == 1) {
01500
01501 SetOffset(off + len);
01502 return 1;
01503 }
01504
01505 Seek(off);
01506 } else {
01507
01508 if (fWritable && fCacheWrite) {
01509 if (fCacheWrite->ReadBuffer(buf, off, len) == 0) {
01510 SetOffset(off + len);
01511 return 1;
01512 }
01513
01514 SetOffset(off);
01515 }
01516 }
01517
01518 return 0;
01519 }
01520
01521
01522 void TFile::ReadFree()
01523 {
01524
01525
01526
01527
01528
01529 TKey *headerfree = new TKey(fSeekFree, fNbytesFree, this);
01530 headerfree->ReadFile();
01531 char *buffer = headerfree->GetBuffer();
01532 headerfree->ReadKeyBuffer(buffer);
01533 buffer = headerfree->GetBuffer();
01534 while (1) {
01535 TFree *afree = new TFree();
01536 afree->ReadBuffer(buffer);
01537 fFree->Add(afree);
01538 if (afree->GetLast() > fEND) break;
01539 }
01540 delete headerfree;
01541 }
01542
01543
01544 TProcessID *TFile::ReadProcessID(UShort_t pidf)
01545 {
01546
01547
01548
01549 TProcessID *pid = 0;
01550 TObjArray *pids = GetListOfProcessIDs();
01551 if (pidf < pids->GetSize()) pid = (TProcessID *)pids->UncheckedAt(pidf);
01552 if (pid) {
01553 pid->CheckInit();
01554 return pid;
01555 }
01556
01557
01558
01559 char pidname[32];
01560 snprintf(pidname,32,"ProcessID%d",pidf);
01561 pid = (TProcessID *)Get(pidname);
01562 if (gDebug > 0) {
01563 printf("ReadProcessID, name=%s, file=%s, pid=%lx\n",pidname,GetName(),(Long_t)pid);
01564 }
01565 if (!pid) {
01566
01567 return pid;
01568 }
01569
01570 TObjArray *pidslist = TProcessID::GetPIDs();
01571 TIter next(pidslist);
01572 TProcessID *p;
01573 while ((p = (TProcessID*)next())) {
01574 if (!strcmp(p->GetTitle(),pid->GetTitle())) {
01575 delete pid;
01576 pids->AddAtAndExpand(p,pidf);
01577 p->IncrementCount();
01578 return p;
01579 }
01580 }
01581 pids->AddAtAndExpand(pid,pidf);
01582 pid->IncrementCount();
01583 pidslist->Add(pid);
01584 Int_t ind = pidslist->IndexOf(pid);
01585 pid->SetUniqueID((UInt_t)ind);
01586 return pid;
01587 }
01588
01589
01590
01591 Int_t TFile::Recover()
01592 {
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623 Short_t keylen,cycle;
01624 UInt_t datime;
01625 Int_t nbytes,date,time,objlen,nwheader;
01626 Long64_t seekkey,seekpdir;
01627 char header[1024];
01628 char *buffer, *bufread;
01629 char nwhc;
01630 Long64_t idcur = fBEGIN;
01631
01632 Long64_t size;
01633 if ((size = GetSize()) == -1) {
01634 Error("Recover", "cannot stat the file %s", GetName());
01635 return 0;
01636 }
01637
01638 fEND = Long64_t(size);
01639
01640 if (fWritable && !fFree) fFree = new TList;
01641
01642 TKey *key;
01643 Int_t nrecov = 0;
01644 nwheader = 1024;
01645 Int_t nread = nwheader;
01646
01647 while (idcur < fEND) {
01648 Seek(idcur);
01649 if (idcur+nread >= fEND) nread = fEND-idcur-1;
01650 ReadBuffer(header, nread);
01651 buffer = header;
01652 bufread = header;
01653 frombuf(buffer, &nbytes);
01654 if (!nbytes) {
01655 Printf("Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes);
01656 break;
01657 }
01658 if (nbytes < 0) {
01659 idcur -= nbytes;
01660 if (fWritable) new TFree(fFree,idcur,idcur-nbytes-1);
01661 Seek(idcur);
01662 continue;
01663 }
01664 Version_t versionkey;
01665 frombuf(buffer, &versionkey);
01666 frombuf(buffer, &objlen);
01667 frombuf(buffer, &datime);
01668 frombuf(buffer, &keylen);
01669 frombuf(buffer, &cycle);
01670 if (versionkey > 1000) {
01671 frombuf(buffer, &seekkey);
01672 frombuf(buffer, &seekpdir);
01673 } else {
01674 Int_t skey,sdir;
01675 frombuf(buffer, &skey); seekkey = (Long64_t)skey;
01676 frombuf(buffer, &sdir); seekpdir = (Long64_t)sdir;
01677 }
01678 frombuf(buffer, &nwhc);
01679 char *classname = 0;
01680 if (nwhc <= 0 || nwhc > 100) break;
01681 classname = new char[nwhc+1];
01682 int i, nwhci = nwhc;
01683 for (i = 0;i < nwhc; i++) frombuf(buffer, &classname[i]);
01684 classname[nwhci] = '\0';
01685 TDatime::GetDateTime(datime, date, time);
01686 TClass *tclass = TClass::GetClass(classname);
01687 if (seekpdir == fSeekDir && tclass && !tclass->InheritsFrom(TFile::Class())
01688 && strcmp(classname,"TBasket")) {
01689 key = new TKey(this);
01690 key->ReadKeyBuffer(bufread);
01691 if (!strcmp(key->GetName(),"StreamerInfo")) {
01692 fSeekInfo = seekkey;
01693 SafeDelete(fInfoCache);
01694 fNbytesInfo = nbytes;
01695 } else {
01696 AppendKey(key);
01697 nrecov++;
01698 SetBit(kRecovered);
01699 Info("Recover", "%s, recovered key %s:%s at address %lld",GetName(),key->GetClassName(),key->GetName(),idcur);
01700 }
01701 }
01702 delete [] classname;
01703 idcur += nbytes;
01704 }
01705 if (fWritable) {
01706 Long64_t max_file_size = Long64_t(kStartBigFile);
01707 if (max_file_size < fEND) max_file_size = fEND+1000000000;
01708 TFree *last = (TFree*)fFree->Last();
01709 if (last) {
01710 last->AddFree(fFree,fEND,max_file_size);
01711 } else {
01712 new TFree(fFree,fEND,max_file_size);
01713 }
01714 if (nrecov) Write();
01715 }
01716 return nrecov;
01717 }
01718
01719
01720 Int_t TFile::ReOpen(Option_t *mode)
01721 {
01722
01723
01724
01725
01726
01727
01728
01729
01730 cd();
01731
01732 TString opt = mode;
01733 opt.ToUpper();
01734
01735 if (opt != "READ" && opt != "UPDATE") {
01736 Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data());
01737 return 1;
01738 }
01739
01740 if (opt == fOption || (opt == "UPDATE" && fOption == "CREATE"))
01741 return 1;
01742
01743 if (opt == "READ") {
01744
01745
01746
01747 if (IsOpen() && IsWritable()) {
01748 WriteStreamerInfo();
01749
01750
01751 Save();
01752
01753 TFree *f1 = (TFree*)fFree->First();
01754 if (f1) {
01755 WriteFree();
01756 WriteHeader();
01757 }
01758
01759 FlushWriteCache();
01760
01761
01762 if (fFree) {
01763 fFree->Delete();
01764 SafeDelete(fFree);
01765 }
01766
01767 SysClose(fD);
01768 fD = -1;
01769
01770 SetWritable(kFALSE);
01771 }
01772
01773
01774 fOption = opt;
01775 #ifndef WIN32
01776 fD = SysOpen(fRealName, O_RDONLY, 0644);
01777 #else
01778 fD = SysOpen(fRealName, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
01779 #endif
01780 if (fD == -1) {
01781 SysError("ReOpen", "file %s can not be opened in read mode", GetName());
01782 return -1;
01783 }
01784 SetWritable(kFALSE);
01785
01786 } else {
01787
01788
01789
01790 if (IsOpen()) {
01791 SysClose(fD);
01792 fD = -1;
01793 }
01794
01795
01796 fOption = opt;
01797 #ifndef WIN32
01798 fD = SysOpen(fRealName, O_RDWR | O_CREAT, 0644);
01799 #else
01800 fD = SysOpen(fRealName, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
01801 #endif
01802 if (fD == -1) {
01803 SysError("ReOpen", "file %s can not be opened in update mode", GetName());
01804 return -1;
01805 }
01806 SetWritable(kTRUE);
01807
01808 fFree = new TList;
01809 if (fSeekFree > fBEGIN)
01810 ReadFree();
01811 else
01812 Warning("ReOpen","file %s probably not closed, cannot read free segments", GetName());
01813 }
01814
01815 return 0;
01816 }
01817
01818
01819 void TFile::SetOffset(Long64_t offset, ERelativeTo pos)
01820 {
01821
01822
01823 switch (pos) {
01824 case kBeg:
01825 fOffset = offset + fArchiveOffset;
01826 break;
01827 case kCur:
01828 fOffset += offset;
01829 break;
01830 case kEnd:
01831
01832 if (fArchiveOffset)
01833 Error("SetOffset", "seeking from end in archive is not (yet) supported");
01834 fOffset = fEND + offset;
01835 break;
01836 }
01837 }
01838
01839
01840 void TFile::Seek(Long64_t offset, ERelativeTo pos)
01841 {
01842
01843
01844 int whence = 0;
01845 switch (pos) {
01846 case kBeg:
01847 whence = SEEK_SET;
01848 offset += fArchiveOffset;
01849 break;
01850 case kCur:
01851 whence = SEEK_CUR;
01852 break;
01853 case kEnd:
01854 whence = SEEK_END;
01855
01856 if (fArchiveOffset)
01857 Error("Seek", "seeking from end in archive is not (yet) supported");
01858 break;
01859 }
01860 Long64_t retpos;
01861 if ((retpos = SysSeek(fD, offset, whence)) < 0)
01862 SysError("Seek", "cannot seek to position %lld in file %s, retpos=%lld",
01863 offset, GetName(), retpos);
01864
01865
01866 fOffset = retpos;
01867 }
01868
01869
01870 void TFile::SetCompressionLevel(Int_t level)
01871 {
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885 if (level < 0) level = 0;
01886 if (level > 9) level = 9;
01887 fCompress = level;
01888 }
01889
01890
01891 void TFile::SetCacheRead(TFileCacheRead *cache)
01892 {
01893
01894
01895
01896
01897
01898
01899 fCacheRead = cache;
01900 }
01901
01902
01903 void TFile::SetCacheWrite(TFileCacheWrite *cache)
01904 {
01905
01906
01907
01908 if (!cache && fCacheWrite) delete fCacheWrite;
01909 fCacheWrite = cache;
01910 }
01911
01912
01913 Int_t TFile::Sizeof() const
01914 {
01915
01916
01917 return 0;
01918 }
01919
01920
01921 void TFile::Streamer(TBuffer &b)
01922 {
01923
01924
01925 if (b.IsReading()) {
01926 b.ReadVersion();
01927 } else {
01928 b.WriteVersion(TFile::IsA());
01929 }
01930 }
01931
01932
01933 void TFile::SumBuffer(Int_t bufsize)
01934 {
01935
01936
01937 fWritten++;
01938 fSumBuffer += bufsize;
01939 fSum2Buffer += bufsize*bufsize;
01940 }
01941
01942
01943 void TFile::UseCache(Int_t , Int_t )
01944 {
01945
01946
01947
01948
01949
01950 }
01951
01952
01953 Int_t TFile::Write(const char *, Int_t opt, Int_t bufsiz)
01954 {
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965 if (!IsWritable()) {
01966 if (!TestBit(kWriteError)) {
01967
01968 Warning("Write", "file %s not opened in write mode", GetName());
01969 }
01970 return 0;
01971 }
01972
01973 TDirectory *cursav = gDirectory;
01974 cd();
01975
01976 if (gDebug) {
01977 if (!GetTitle() || strlen(GetTitle()) == 0)
01978 Info("Write", "writing name = %s", GetName());
01979 else
01980 Info("Write", "writing name = %s title = %s", GetName(), GetTitle());
01981 }
01982
01983 fMustFlush = kFALSE;
01984 Int_t nbytes = TDirectoryFile::Write(0, opt, bufsiz);
01985 WriteStreamerInfo();
01986 WriteFree();
01987 WriteHeader();
01988 fMustFlush = kTRUE;
01989
01990 if (cursav) {
01991 cursav->cd();
01992 } else {
01993 gDirectory = 0;
01994 }
01995 return nbytes;
01996 }
01997
01998
01999 Int_t TFile::Write(const char *n, Int_t opt, Int_t bufsize) const
02000 {
02001
02002
02003 Error("Write const","A const TFile object should not be saved. We try to proceed anyway.");
02004 return const_cast<TFile*>(this)->Write(n, opt, bufsize);
02005 }
02006
02007
02008 Bool_t TFile::WriteBuffer(const char *buf, Int_t len)
02009 {
02010
02011
02012
02013 if (IsOpen() && fWritable) {
02014
02015 Int_t st;
02016 if ((st = WriteBufferViaCache(buf, len))) {
02017 if (st == 2)
02018 return kTRUE;
02019 return kFALSE;
02020 }
02021
02022 ssize_t siz;
02023 gSystem->IgnoreInterrupt();
02024 while ((siz = SysWrite(fD, buf, len)) < 0 && GetErrno() == EINTR)
02025 ResetErrno();
02026 gSystem->IgnoreInterrupt(kFALSE);
02027 if (siz < 0) {
02028
02029 SetBit(kWriteError); SetWritable(kFALSE);
02030 SysError("WriteBuffer", "error writing to file %s (%ld)", GetName(), (Long_t)siz);
02031 return kTRUE;
02032 }
02033 if (siz != len) {
02034 SetBit(kWriteError);
02035 Error("WriteBuffer", "error writing all requested bytes to file %s, wrote %ld of %d",
02036 GetName(), (Long_t)siz, len);
02037 return kTRUE;
02038 }
02039 fBytesWrite += siz;
02040 fgBytesWrite += siz;
02041
02042 if (gMonitoringWriter)
02043 gMonitoringWriter->SendFileWriteProgress(this);
02044
02045 return kFALSE;
02046 }
02047 return kTRUE;
02048 }
02049
02050
02051 Int_t TFile::WriteBufferViaCache(const char *buf, Int_t len)
02052 {
02053
02054
02055
02056 if (!fCacheWrite) return 0;
02057
02058 Int_t st;
02059 Long64_t off = GetRelOffset();
02060 if ((st = fCacheWrite->WriteBuffer(buf, off, len)) < 0) {
02061 SetBit(kWriteError);
02062 Error("WriteBuffer", "error writing to cache");
02063 return 2;
02064 }
02065 if (st > 0) {
02066
02067 Seek(off + len);
02068 return 1;
02069 }
02070 return 0;
02071 }
02072
02073
02074 void TFile::WriteFree()
02075 {
02076
02077
02078
02079
02080
02081 if (fSeekFree != 0){
02082 MakeFree(fSeekFree, fSeekFree + fNbytesFree -1);
02083 }
02084
02085 Int_t nbytes = 0;
02086 TFree *afree;
02087 TIter next (fFree);
02088 while ((afree = (TFree*) next())) {
02089 nbytes += afree->Sizeof();
02090 }
02091 if (!nbytes) return;
02092
02093 TKey *key = new TKey(fName,fTitle,IsA(),nbytes,this);
02094 if (key->GetSeekKey() == 0) {
02095 delete key;
02096 return;
02097 }
02098 char *buffer = key->GetBuffer();
02099 char *start = buffer;
02100
02101 next.Reset();
02102 while ((afree = (TFree*) next())) {
02103 afree->FillBuffer(buffer);
02104 }
02105 if ( (buffer-start)!=nbytes ) {
02106
02107
02108 memset(buffer,0,nbytes-(buffer-start));
02109 }
02110 fNbytesFree = key->GetNbytes();
02111 fSeekFree = key->GetSeekKey();
02112 key->WriteFile();
02113 delete key;
02114 }
02115
02116
02117 void TFile::WriteHeader()
02118 {
02119
02120
02121 SafeDelete(fInfoCache);
02122 TFree *lastfree = (TFree*)fFree->Last();
02123 if (lastfree) fEND = lastfree->GetFirst();
02124 const char *root = "root";
02125 char *psave = new char[fBEGIN];
02126 char *buffer = psave;
02127 Int_t nfree = fFree->GetSize();
02128 memcpy(buffer, root, 4); buffer += 4;
02129 Int_t version = fVersion;
02130 if (version <1000000 && fEND > kStartBigFile) {version += 1000000; fUnits = 8;}
02131 tobuf(buffer, version);
02132 tobuf(buffer, (Int_t)fBEGIN);
02133 if (version < 1000000) {
02134 tobuf(buffer, (Int_t)fEND);
02135 tobuf(buffer, (Int_t)fSeekFree);
02136 tobuf(buffer, fNbytesFree);
02137 tobuf(buffer, nfree);
02138 tobuf(buffer, fNbytesName);
02139 tobuf(buffer, fUnits);
02140 tobuf(buffer, fCompress);
02141 tobuf(buffer, (Int_t)fSeekInfo);
02142 tobuf(buffer, fNbytesInfo);
02143 } else {
02144 tobuf(buffer, fEND);
02145 tobuf(buffer, fSeekFree);
02146 tobuf(buffer, fNbytesFree);
02147 tobuf(buffer, nfree);
02148 tobuf(buffer, fNbytesName);
02149 tobuf(buffer, fUnits);
02150 tobuf(buffer, fCompress);
02151 tobuf(buffer, fSeekInfo);
02152 tobuf(buffer, fNbytesInfo);
02153 }
02154 fUUID.FillBuffer(buffer);
02155 Int_t nbytes = buffer - psave;
02156 Seek(0);
02157 WriteBuffer(psave, nbytes);
02158 Flush();
02159 delete [] psave;
02160 }
02161
02162
02163 void TFile::MakeProject(const char *dirname, const char * ,
02164 Option_t *option)
02165 {
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231 TString opt = option;
02232 opt.ToLower();
02233 {
02234 void *dir = gSystem->OpenDirectory(dirname);
02235 TString dirpath;
02236
02237 if (opt.Contains("update")) {
02238
02239 if (dir == 0) {
02240 gSystem->mkdir(dirname);
02241 }
02242
02243 } else if (opt.Contains("recreate")) {
02244
02245 if (dir == 0) {
02246 gSystem->mkdir(dirname);
02247 }
02248
02249 while (dir) {
02250 const char *afile = gSystem->GetDirEntry(dir);
02251 if (afile == 0) break;
02252 if (strcmp(afile,".") == 0) continue;
02253 if (strcmp(afile,"..") == 0) continue;
02254 dirpath.Form("%s/%s",dirname,afile);
02255 gSystem->Unlink(dirpath);
02256 }
02257
02258 } else {
02259
02260
02261 if (dir) {
02262 Error("MakeProject","cannot create directory %s, already existing",dirname);
02263 gSystem->FreeDirectory(dir);
02264 return;
02265 }
02266 gSystem->mkdir(dirname);
02267 }
02268 if (dir) {
02269 gSystem->FreeDirectory(dir);
02270 }
02271 }
02272 Bool_t genreflex = opt.Contains("genreflex");
02273
02274
02275
02276 TList *filelist = (TList*)GetStreamerInfoCache()->Clone();
02277 if (filelist == 0) {
02278 Error("MakeProject","file %s has no StreamerInfo", GetName());
02279 return;
02280 }
02281
02282
02283 TString spath; spath.Form("%s/%sProjectSource.cxx",dirname,dirname);
02284 FILE *sfp = fopen(spath.Data(),"w");
02285 fprintf(sfp, "#include \"%sProjectHeaders.h\"\n\n",dirname );
02286 if (!genreflex) fprintf(sfp, "#include \"%sLinkDef.h\"\n\n",dirname );
02287 fprintf(sfp, "#include \"%sProjectDict.cxx\"\n\n",dirname );
02288 fprintf(sfp, "struct DeleteObjectFunctor {\n");
02289 fprintf(sfp, " template <typename T>\n");
02290 fprintf(sfp, " void operator()(const T *ptr) const {\n");
02291 fprintf(sfp, " delete ptr;\n");
02292 fprintf(sfp, " }\n");
02293 fprintf(sfp, " template <typename T, typename Q>\n");
02294 fprintf(sfp, " void operator()(const std::pair<T,Q> &) const {\n");
02295 fprintf(sfp, " // Do nothing\n");
02296 fprintf(sfp, " }\n");
02297 fprintf(sfp, " template <typename T, typename Q>\n");
02298 fprintf(sfp, " void operator()(const std::pair<T,Q*> &ptr) const {\n");
02299 fprintf(sfp, " delete ptr.second;\n");
02300 fprintf(sfp, " }\n");
02301 fprintf(sfp, " template <typename T, typename Q>\n");
02302 fprintf(sfp, " void operator()(const std::pair<T*,Q> &ptr) const {\n");
02303 fprintf(sfp, " delete ptr.first;\n");
02304 fprintf(sfp, " }\n");
02305 fprintf(sfp, " template <typename T, typename Q>\n");
02306 fprintf(sfp, " void operator()(const std::pair<T*,Q*> &ptr) const {\n");
02307 fprintf(sfp, " delete ptr.first;\n");
02308 fprintf(sfp, " delete ptr.second;\n");
02309 fprintf(sfp, " }\n");
02310 fprintf(sfp, "};\n\n");
02311 fclose( sfp );
02312
02313
02314
02315
02316 TStreamerInfo *info;
02317 TIter flnext(filelist);
02318 TList extrainfos;
02319 TList *list = new TList();
02320 while ((info = (TStreamerInfo*)flnext())) {
02321 if (info->IsA() != TStreamerInfo::Class()) {
02322 continue;
02323 }
02324 TClass *cl = TClass::GetClass(info->GetName());
02325 if (cl) {
02326 if (cl->GetClassInfo()) continue;
02327 }
02328
02329 TMakeProject::GenerateMissingStreamerInfos( &extrainfos, info->GetName() );
02330 TIter enext( info->GetElements() );
02331 TStreamerElement *el;
02332 const ROOT::TSchemaMatch* rules = 0;
02333 if (cl && cl->GetSchemaRules()) {
02334 rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
02335 }
02336 while( (el=(TStreamerElement*)enext()) ) {
02337 if (rules) {
02338 for(Int_t art = 0; art < rules->GetEntries(); ++art) {
02339 ROOT::TSchemaRule *rule = (ROOT::TSchemaRule*)rules->At(art);
02340 if( rule->IsRenameRule() || rule->IsAliasRule() )
02341 continue;
02342
02343 if ( rule->HasTarget( el->GetName()) && rule->GetAttributes()[0] != 0 ) {
02344 TString attr( rule->GetAttributes() );
02345 attr.ToLower();
02346 if (attr.Contains("owner")) {
02347 if (attr.Contains("notowner")) {
02348 el->SetBit(TStreamerElement::kDoNotDelete);
02349 } else {
02350 el->ResetBit(TStreamerElement::kDoNotDelete);
02351 }
02352 }
02353 }
02354 }
02355 }
02356 TMakeProject::GenerateMissingStreamerInfos(&extrainfos, el);
02357 }
02358 delete rules;
02359 TVirtualStreamerInfo *alternate = (TVirtualStreamerInfo*)list->FindObject(info->GetName());
02360 if (alternate) {
02361 if ((info->GetClass() && info->GetClassVersion() == info->GetClass()->GetClassVersion())
02362 || (info->GetClassVersion() > alternate->GetClassVersion()) ) {
02363 list->AddAfter(alternate, info);
02364 list->Remove(alternate);
02365 }
02366 } else {
02367 list->Add(info);
02368 }
02369 }
02370
02371
02372 TIter nextextra(&extrainfos);
02373 while ((info = (TStreamerInfo*)nextextra())) {
02374 list->Add(info);
02375 filelist->Add(info);
02376 }
02377
02378
02379 TIter next(list);
02380 Int_t ngener = 0;
02381 while ((info = (TStreamerInfo*)next())) {
02382 if (info->IsA() != TStreamerInfo::Class()) {
02383 continue;
02384 }
02385 if (info->GetClassVersion()==-4) continue;
02386 TIter subnext(list);
02387 TStreamerInfo *subinfo;
02388 TList subClasses;
02389 Int_t len = strlen(info->GetName());
02390 while ((subinfo = (TStreamerInfo*)subnext())) {
02391 if (subinfo->IsA() != TStreamerInfo::Class()) {
02392 continue;
02393 }
02394 if (strncmp(info->GetName(),subinfo->GetName(),len)==0) {
02395
02396
02397 const Int_t sublen = strlen(subinfo->GetName());
02398 if ( (sublen > len) && subinfo->GetName()[len+1]==':'
02399 && !subClasses.FindObject(subinfo->GetName()) )
02400 {
02401 subClasses.Add(subinfo);
02402 }
02403 }
02404 }
02405 ngener += info->GenerateHeaderFile(dirname,&subClasses,&extrainfos);
02406 subClasses.Clear("nodelete");
02407 }
02408 TString path;
02409 path.Form("%s/%sProjectHeaders.h",dirname,dirname);
02410 FILE *allfp = fopen(path,"a");
02411 if (!allfp) {
02412 Error("MakeProject","Cannot open output file:%s\n",path.Data());
02413 } else {
02414 fprintf(allfp,"#include \"%sProjectInstances.h\"\n", dirname);
02415 fclose(allfp);
02416 }
02417
02418 printf("MakeProject has generated %d classes in %s\n",ngener,dirname);
02419
02420
02421 if (!opt.Contains("+")) {
02422 delete list;
02423 filelist->Delete();
02424 delete filelist;
02425 return;
02426 }
02427
02428
02429
02430 #ifdef WIN32
02431 path.Form("%s/makep.cmd",dirname);
02432 #else
02433 path.Form("%s/MAKEP",dirname);
02434 #endif
02435 #ifdef R__WINGCC
02436 FILE *fpMAKE = fopen(path,"wb");
02437 #else
02438 FILE *fpMAKE = fopen(path,"w");
02439 #endif
02440 if (!fpMAKE) {
02441 Error("MakeProject", "cannot open file %s", path.Data());
02442 delete list;
02443 filelist->Delete();
02444 delete filelist;
02445 return;
02446 }
02447
02448
02449 FILE *ifp = 0;
02450 path.Form("%s/%sProjectInstances.h",dirname,dirname);
02451 #ifdef R__WINGCC
02452 ifp = fopen(path,"wb");
02453 #else
02454 ifp = fopen(path,"w");
02455 #endif
02456 if (!ifp) {
02457 Error("MakeProject", "cannot open path file %s", path.Data());
02458 delete list;
02459 filelist->Delete();
02460 delete filelist;
02461 fclose(fpMAKE);
02462 return;
02463 }
02464
02465 if (genreflex) {
02466 fprintf(fpMAKE,"genreflex %sProjectHeaders.h -o %sProjectDict.cxx --comments --iocomments %s ",dirname,dirname,gSystem->GetIncludePath());
02467 path.Form("%s/%sSelection.xml",dirname,dirname);
02468 } else {
02469 fprintf(fpMAKE,"rootcint -f %sProjectDict.cxx -c %s ",dirname,gSystem->GetIncludePath());
02470 path.Form("%s/%sLinkDef.h",dirname,dirname);
02471 }
02472
02473
02474 #ifdef R__WINGCC
02475 FILE *fp = fopen(path,"wb");
02476 #else
02477 FILE *fp = fopen(path,"w");
02478 #endif
02479 if (!fp) {
02480 Error("MakeProject", "cannot open path file %s", path.Data());
02481 delete list;
02482 filelist->Delete();
02483 delete filelist;
02484 fclose(fpMAKE);
02485 fclose(ifp);
02486 return;
02487 }
02488 if (genreflex) {
02489 fprintf(fp,"<lcgdict>\n");
02490 fprintf(fp,"\n");
02491 } else {
02492 fprintf(fp,"#ifdef __CINT__\n");
02493 fprintf(fp,"\n");
02494 }
02495
02496 TString tmp;
02497 TString instances;
02498 TString selections;
02499 next.Reset();
02500 while ((info = (TStreamerInfo*)next())) {
02501 if (info->IsA() != TStreamerInfo::Class()) {
02502 continue;
02503 }
02504 TClass *cl = TClass::GetClass(info->GetName());
02505 if (cl) {
02506 if (cl->GetClassInfo()) continue;
02507 const ROOT::TSchemaMatch* rules = 0;
02508 if (cl->GetSchemaRules()) {
02509 rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
02510 TString strrule;
02511 if (rules) {
02512 for(Int_t art = 0; art < rules->GetEntries(); ++art) {
02513 ROOT::TSchemaRule *rule = (ROOT::TSchemaRule*)rules->At(art);
02514 strrule.Clear();
02515 if (genreflex) {
02516 rule->AsString(strrule,"x");
02517 strrule.Append("\n");
02518 if ( selections.Index(strrule) == kNPOS ) {
02519 selections.Append(strrule);
02520 }
02521 } else {
02522 rule->AsString(strrule);
02523 if (strncmp(strrule.Data(),"type=",5)==0) {
02524 strrule.Remove(0,5);
02525 }
02526 fprintf(fp,"#pragma %s;\n",strrule.Data());
02527 }
02528 }
02529 }
02530 delete rules;
02531 }
02532
02533 }
02534 if (TClassEdit::IsSTLCont(info->GetName())) {
02535 std::vector<std::string> inside;
02536 int nestedLoc;
02537 TClassEdit::GetSplit( info->GetName(), inside, nestedLoc, TClassEdit::kLong64 );
02538 Int_t stlkind = TClassEdit::STLKind(inside[0].c_str());
02539 TClass *key = TClass::GetClass(inside[1].c_str());
02540 if (key) {
02541 TString what;
02542 switch ( stlkind ) {
02543 case TClassEdit::kMap:
02544 case TClassEdit::kMultiMap:
02545 if (TClass::GetClass(inside[1].c_str())) {
02546 what = "std::pair<";
02547 what += TMakeProject::UpdateAssociativeToVector( inside[1].c_str() );
02548 what += ",";
02549 what += TMakeProject::UpdateAssociativeToVector( inside[2].c_str() );
02550 if (what[what.Length()-1]=='>') {
02551 what += " >";
02552 } else {
02553 what += ">";
02554 }
02555 if (genreflex) {
02556 tmp.Form("<class name=\"%s\" />\n",what.Data());
02557 if ( selections.Index(tmp) == kNPOS ) {
02558 selections.Append(tmp);
02559 }
02560 tmp.Form("template class %s;\n",what.Data());
02561 if ( instances.Index(tmp) == kNPOS ) {
02562 instances.Append(tmp);
02563 }
02564 } else {
02565 what.ReplaceAll("std::","");
02566 fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
02567 }
02568 break;
02569 }
02570 default:
02571 if (strncmp(key->GetName(),"pair<",strlen("pair<"))==0) {
02572 if (genreflex) {
02573 tmp.Form("<class name=\"%s\" />\n",key->GetName());
02574 if ( selections.Index(tmp) == kNPOS ) {
02575 selections.Append(tmp);
02576 }
02577 tmp.Form("template class %s;\n",key->GetName());
02578 if ( instances.Index(tmp) == kNPOS ) {
02579 instances.Append(tmp);
02580 }
02581 } else {
02582 what.ReplaceAll("std::","");
02583 fprintf(fp,"#pragma link C++ class %s+;\n",key->GetName());
02584 }
02585 }
02586 break;
02587 }
02588 }
02589 continue;
02590 }
02591 {
02592 TString what(TMakeProject::UpdateAssociativeToVector(info->GetName()).Data());
02593 if (genreflex) {
02594 tmp.Form("<class name=\"%s\" />\n",what.Data());
02595 if ( selections.Index(tmp) == kNPOS ) {
02596 selections.Append(tmp);
02597 }
02598 if (what[what.Length()-1] == '>') {
02599 tmp.Form("template class %s;\n",what.Data());
02600 if ( instances.Index(tmp) == kNPOS ) {
02601 instances.Append(tmp);
02602 }
02603 }
02604 } else {
02605 what.ReplaceAll("std::","");
02606 fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
02607 }
02608 }
02609 if (genreflex) {
02610
02611 TIter eliter( info->GetElements() );
02612 TStreamerElement *element;
02613 while( (element = (TStreamerElement*)eliter() ) ) {
02614 if (element->GetClass() && !element->GetClass()->IsLoaded() && element->GetClass()->GetCollectionProxy()) {
02615 TString what( TMakeProject::UpdateAssociativeToVector(element->GetClass()->GetName()) );
02616 tmp.Form("<class name=\"%s\" />\n",what.Data());
02617 if ( selections.Index(tmp) == kNPOS ) {
02618 selections.Append(tmp);
02619 }
02620 tmp.Form("template class %s;\n",what.Data());
02621 if ( instances.Index(tmp) == kNPOS ) {
02622 instances.Append(tmp);
02623 }
02624 }
02625 }
02626 }
02627 }
02628 if (genreflex) {
02629 fprintf(ifp,"#ifndef PROJECT_INSTANCES_H\n");
02630 fprintf(ifp,"#define PROJECT_INSTANCES_H\n");
02631 fprintf(ifp,"%s",instances.Data());
02632 fprintf(ifp,"#endif\n");
02633 fprintf(fp,"%s",selections.Data());
02634 fprintf(fp,"</lcgdict>\n");
02635 } else {
02636 fprintf(fp,"#endif\n");
02637 }
02638 fclose(fp);
02639 fclose(ifp);
02640 if (genreflex) {
02641 fprintf(fpMAKE,"-s %sSelection.xml \n",dirname);
02642 } else {
02643 fprintf(fpMAKE,"%sProjectHeaders.h ",dirname);
02644 fprintf(fpMAKE,"%sLinkDef.h \n",dirname);
02645 }
02646
02647
02648 TString sdirname(dirname);
02649
02650 TString cmd = gSystem->GetMakeSharedLib();
02651 TString sources( sdirname+"ProjectSource.cxx ");
02652 cmd.ReplaceAll("$SourceFiles",sources.Data());
02653 TString object( sdirname + "ProjectSource." );
02654 object.Append( gSystem->GetObjExt() );
02655 cmd.ReplaceAll("$ObjectFiles", object.Data());
02656 cmd.ReplaceAll("$IncludePath",TString(gSystem->GetIncludePath()) + " -I" + dirname);
02657 cmd.ReplaceAll("$SharedLib",sdirname+"."+gSystem->GetSoExt());
02658 cmd.ReplaceAll("$LinkedLibs",gSystem->GetLibraries("","SDL"));
02659 cmd.ReplaceAll("$LibName",sdirname);
02660 cmd.ReplaceAll("$BuildDir",".");
02661 TString sOpt;
02662 TString rootbuild = ROOTBUILD;
02663 if (rootbuild.Index("debug",0,TString::kIgnoreCase)==kNPOS) {
02664 sOpt = gSystem->GetFlagsOpt();
02665 } else {
02666 sOpt = gSystem->GetFlagsDebug();
02667 }
02668 cmd.ReplaceAll("$Opt", sOpt);
02669
02670 fprintf(fpMAKE,"%s\n",cmd.Data());
02671
02672 fclose(fpMAKE);
02673 printf("%s/MAKEP file has been generated\n",dirname);
02674
02675 if (!opt.Contains("nocompilation")) {
02676
02677 path = gSystem->WorkingDirectory();
02678 gSystem->ChangeDirectory(dirname);
02679 #ifndef WIN32
02680 gSystem->Exec("chmod +x MAKEP");
02681 int res = !gSystem->Exec("./MAKEP");
02682 #else
02683
02684 chmod("makep.cmd",00700);
02685 int res = !gSystem->Exec("MAKEP");
02686 #endif
02687 gSystem->ChangeDirectory(path);
02688 path.Form("%s/%s.%s",dirname,dirname,gSystem->GetSoExt());
02689 if (res) printf("Shared lib %s has been generated\n",path.Data());
02690
02691
02692 if (opt.Contains("++")) {
02693 res = !gSystem->Load(path);
02694 if (res) printf("Shared lib %s has been dynamically linked\n",path.Data());
02695 }
02696 }
02697
02698 extrainfos.Clear("nodelete");
02699
02700 delete list;
02701 filelist->Delete();
02702 delete filelist;
02703 }
02704
02705
02706 void TFile::ReadStreamerInfo()
02707 {
02708
02709
02710
02711
02712
02713
02714 TList *list = GetStreamerInfoList();
02715 if (!list) {
02716 MakeZombie();
02717 return;
02718 }
02719
02720 list->SetOwner(kFALSE);
02721
02722 if (gDebug > 0) Info("ReadStreamerInfo", "called for file %s",GetName());
02723
02724
02725 TStreamerInfo *info;
02726 for (int mode=0;mode<2; ++mode) {
02727
02728
02729 TObjLink *lnk = list->FirstLink();
02730 while (lnk) {
02731 info = (TStreamerInfo*)lnk->GetObject();
02732
02733 if (info->IsA() != TStreamerInfo::Class()) {
02734 if (mode==1) {
02735 TObject *obj = (TObject*)info;
02736 if (strcmp(obj->GetName(),"listOfRules")==0) {
02737 TList *listOfRules = (TList*)obj;
02738 TObjLink *rulelnk = listOfRules->FirstLink();
02739 while (rulelnk) {
02740 TObjString *rule = (TObjString*)rulelnk->GetObject();
02741 TClass::AddRule( rule->String().Data() );
02742 rulelnk = rulelnk->Next();
02743 }
02744 } else {
02745 Warning("ReadStreamerInfo","%s has a %s in the list of TStreamerInfo.", GetName(), info->IsA()->GetName());
02746 }
02747 info->SetBit(kCanDelete);
02748 }
02749 lnk = lnk->Next();
02750 continue;
02751 }
02752
02753
02754 TObject *element = info->GetElements()->UncheckedAt(0);
02755 Bool_t isstl = element && strcmp("This",element->GetName())==0;
02756
02757 if ( (!isstl && mode ==0) || (isstl && mode ==1) ) {
02758
02759
02760 info->BuildCheck();
02761 Int_t uid = info->GetNumber();
02762 Int_t asize = fClassIndex->GetSize();
02763 if (uid >= asize && uid <100000) fClassIndex->Set(2*asize);
02764 if (uid >= 0 && uid < fClassIndex->GetSize()) fClassIndex->fArray[uid] = 1;
02765 else {
02766 printf("ReadStreamerInfo, class:%s, illegal uid=%d\n",info->GetName(),uid);
02767 }
02768 if (gDebug > 0) printf(" -class: %s version: %d info read at slot %d\n",info->GetName(), info->GetClassVersion(),uid);
02769 }
02770 lnk = lnk->Next();
02771 }
02772 }
02773 fClassIndex->fArray[0] = 0;
02774 list->Clear();
02775 delete list;
02776 }
02777
02778
02779 void TFile::SetReadStreamerInfo(Bool_t readinfo)
02780 {
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790 fgReadInfo = readinfo;
02791 }
02792
02793
02794 void TFile::ShowStreamerInfo()
02795 {
02796
02797
02798 TList *list = GetStreamerInfoList();
02799
02800 if (!list) return;
02801
02802 list->ls();
02803 delete list;
02804 }
02805
02806
02807 UShort_t TFile::WriteProcessID(TProcessID *pidd)
02808 {
02809
02810
02811
02812 TProcessID *pid = pidd;
02813 if (!pid) pid = TProcessID::GetPID();
02814 TObjArray *pids = GetListOfProcessIDs();
02815 Int_t npids = GetNProcessIDs();
02816 for (Int_t i=0;i<npids;i++) {
02817 if (pids->At(i) == pid) return (UShort_t)i;
02818 }
02819
02820 this->SetBit(TFile::kHasReferences);
02821 pids->AddAtAndExpand(pid,npids);
02822 pid->IncrementCount();
02823 char name[32];
02824 snprintf(name,32,"ProcessID%d",npids);
02825 this->WriteTObject(pid,name);
02826 this->IncrementProcessIDs();
02827 if (gDebug > 0) {
02828 Info("WriteProcessID", "name=%s, file=%s", name, GetName());
02829 }
02830 return (UShort_t)npids;
02831 }
02832
02833
02834
02835 void TFile::WriteStreamerInfo()
02836 {
02837
02838
02839
02840
02841
02842 if (!fWritable) return;
02843 if (!fClassIndex) return;
02844
02845 if (fClassIndex->fArray[0] == 0) return;
02846 if (gDebug > 0) Info("WriteStreamerInfo", "called for file %s",GetName());
02847
02848 SafeDelete(fInfoCache);
02849
02850
02851 TIter next(gROOT->GetListOfStreamerInfo());
02852 TStreamerInfo *info;
02853 TList list;
02854 TList listOfRules;
02855 listOfRules.SetOwner(kTRUE);
02856 listOfRules.SetName("listOfRules");
02857 std::set<TClass*> classSet;
02858
02859
02860 while ((info = (TStreamerInfo*)next())) {
02861 Int_t uid = info->GetNumber();
02862 if (fClassIndex->fArray[uid]) {
02863 list.Add(info);
02864 if (gDebug > 0) printf(" -class: %s info number %d saved\n",info->GetName(),uid);
02865
02866
02867
02868 TClass *clinfo = info->GetClass();
02869 if (clinfo && clinfo->GetSchemaRules()) {
02870 if ( classSet.find( clinfo ) == classSet.end() ) {
02871 if (gDebug > 0) printf(" -class: %s stored the I/O customization rules\n",info->GetName());
02872
02873 TObjArrayIter it( clinfo->GetSchemaRules()->GetRules() );
02874 ROOT::TSchemaRule *rule;
02875 while( (rule = (ROOT::TSchemaRule*)it.Next()) ) {
02876 TObjString *obj = new TObjString();
02877 rule->AsString(obj->String());
02878 listOfRules.Add(obj);
02879 }
02880 classSet.insert(clinfo);
02881 }
02882 }
02883 }
02884 }
02885 if (list.GetSize() == 0) return;
02886 fClassIndex->fArray[0] = 2;
02887
02888 if (listOfRules.GetEntries()) {
02889
02890 list.Add(&listOfRules);
02891 }
02892
02893
02894 Int_t compress = fCompress;
02895 fCompress = 1;
02896
02897
02898 if (fSeekInfo) MakeFree(fSeekInfo,fSeekInfo+fNbytesInfo-1);
02899
02900 TKey key(&list,"StreamerInfo",GetBestBuffer(), this);
02901 fKeys->Remove(&key);
02902 fSeekInfo = key.GetSeekKey();
02903 fNbytesInfo = key.GetNbytes();
02904 SumBuffer(key.GetObjlen());
02905 key.WriteFile(0);
02906
02907 fClassIndex->fArray[0] = 0;
02908 fCompress = compress;
02909
02910 list.RemoveLast();
02911 }
02912
02913
02914 TFile *TFile::OpenFromCache(const char *name, Option_t *, const char *ftitle,
02915 Int_t compress, Int_t netopt)
02916 {
02917
02918
02919
02920
02921
02922 TFile *f = 0;
02923
02924 if (fgCacheFileDir == "") {
02925 ::Warning("TFile::OpenFromCache",
02926 "you want to read through a cache, but you have no valid cache "
02927 "directory set - reading remotely");
02928 ::Info("TFile::OpenFromCache", "set cache directory using TFile::SetCacheFileDir()");
02929 } else {
02930 TUrl fileurl(name);
02931 TUrl tagurl;
02932
02933 if ((!strcmp(fileurl.GetProtocol(), "file"))) {
02934
02935 if (!fgCacheFileForce)
02936 ::Warning("TFile::OpenFromCache",
02937 "you want to read through a cache, but you are reading "
02938 "local files - CACHEREAD disabled");
02939 } else {
02940
02941
02942 TString cachefilepath;
02943 TString cachefilepathbasedir;
02944 cachefilepath = fgCacheFileDir;
02945 cachefilepath += fileurl.GetFile();
02946 cachefilepathbasedir = gSystem->DirName(cachefilepath);
02947 if ((gSystem->mkdir(cachefilepathbasedir, kTRUE) < 0) &&
02948 (gSystem->AccessPathName(cachefilepathbasedir, kFileExists))) {
02949 ::Warning("TFile::OpenFromCache","you want to read through a cache, but I "
02950 "cannot create the directory %s - CACHEREAD disabled",
02951 cachefilepathbasedir.Data());
02952 } else {
02953
02954 if (strlen(fileurl.GetAnchor())) {
02955
02956 cachefilepath += "__";
02957 cachefilepath += fileurl.GetAnchor();
02958 fileurl.SetAnchor("");
02959 }
02960 if (strstr(name,"zip=")) {
02961
02962 TString urloptions = fileurl.GetOptions();
02963 TString newoptions;
02964 TObjArray *objOptions = urloptions.Tokenize("&");
02965 Int_t optioncount = 0;
02966 TString zipname;
02967 for (Int_t n = 0; n < objOptions->GetEntries(); n++) {
02968 TString loption = ((TObjString*)objOptions->At(n))->GetName();
02969 TObjArray *objTags = loption.Tokenize("=");
02970 if (objTags->GetEntries() == 2) {
02971 TString key = ((TObjString*)objTags->At(0))->GetName();
02972 TString value = ((TObjString*)objTags->At(1))->GetName();
02973 if (key.CompareTo("zip", TString::kIgnoreCase)) {
02974 if (optioncount!=0) {
02975 newoptions += "&";
02976 }
02977 newoptions += key;
02978 newoptions += "=";
02979 newoptions += value;
02980 ++optioncount;
02981 } else {
02982 zipname = value;
02983 }
02984 }
02985 delete objTags;
02986 }
02987 delete objOptions;
02988 fileurl.SetOptions(newoptions.Data());
02989 cachefilepath += "__";
02990 cachefilepath += zipname;
02991 fileurl.SetAnchor("");
02992 }
02993
02994 Bool_t need2copy = kFALSE;
02995
02996
02997 Long_t id;
02998 Long64_t size;
02999 Long_t flags;
03000 Long_t modtime;
03001 if (!gSystem->GetPathInfo(cachefilepath, &id, &size, &flags, &modtime)) {
03002
03003 if (!fgCacheFileDisconnected) {
03004 char cacheblock[256];
03005 char remotblock[256];
03006
03007 TString cfurl;
03008 cfurl = cachefilepath;
03009 cfurl += "?filetype=raw";
03010 TUrl rurl(name);
03011 TString ropt = rurl.GetOptions();
03012 ropt += "&filetype=raw";
03013 rurl.SetOptions(ropt);
03014
03015 Bool_t forcedcache = fgCacheFileForce;
03016 fgCacheFileForce = kFALSE;
03017
03018 TFile *cachefile = TFile::Open(cfurl, "READ");
03019 TFile *remotfile = TFile::Open(rurl.GetUrl(), "READ");
03020
03021 fgCacheFileForce = forcedcache;
03022
03023 if (!cachefile) {
03024 need2copy = kTRUE;
03025 ::Error("TFile::OpenFromCache",
03026 "cannot open the cache file to check cache consistency");
03027 return 0;
03028 }
03029
03030 if (!remotfile) {
03031 ::Error("TFile::OpenFromCache",
03032 "cannot open the remote file to check cache consistency");
03033 return 0;
03034 }
03035
03036 cachefile->Seek(0);
03037 remotfile->Seek(0);
03038
03039 if ((!cachefile->ReadBuffer(cacheblock,256)) &&
03040 (!remotfile->ReadBuffer(remotblock,256))) {
03041 if (memcmp(cacheblock, remotblock, 256)) {
03042 ::Warning("TFile::OpenFromCache", "the header of the cache file "
03043 "differs from the remote file - forcing an update");
03044 need2copy = kTRUE;
03045 }
03046 } else {
03047 ::Warning("TFile::OpenFromCache", "the header of the cache and/or "
03048 "remote file are not readable - forcing an update");
03049 need2copy = kTRUE;
03050 }
03051
03052 delete remotfile;
03053 delete cachefile;
03054 }
03055 } else {
03056 need2copy = kTRUE;
03057 }
03058
03059
03060 Bool_t forcedcache = fgCacheFileForce;
03061 fgCacheFileForce = kFALSE;
03062 if (need2copy && !TFile::Cp(name, cachefilepath)) {
03063 ::Warning("TFile::OpenFromCache", "you want to read through a cache, but I "
03064 "cannot make a cache copy of %s - CACHEREAD disabled",
03065 cachefilepathbasedir.Data());
03066 fgCacheFileForce = forcedcache;
03067 if (fgOpenTimeout != 0)
03068 return 0;
03069 } else {
03070 fgCacheFileForce = forcedcache;
03071 ::Info("TFile::OpenFromCache", "using local cache copy of %s [%s]",
03072 name, cachefilepath.Data());
03073
03074 fileurl.SetProtocol("file");
03075 fileurl.SetFile(cachefilepath);
03076
03077 tagurl = fileurl;
03078 TString tagfile;
03079 tagfile = cachefilepath;
03080 tagfile += ".ROOT.cachefile";
03081 tagurl.SetFile(tagfile);
03082
03083 gSystem->Symlink(cachefilepath, tagfile);
03084 return TFile::Open(fileurl.GetUrl(), "READ", ftitle, compress, netopt);
03085 }
03086 }
03087 }
03088 }
03089
03090
03091 return f;
03092 }
03093
03094
03095 TFile *TFile::Open(const char *url, Option_t *options, const char *ftitle,
03096 Int_t compress, Int_t netopt)
03097 {
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132 TPluginHandler *h;
03133 TFile *f = 0;
03134 EFileType type = kFile;
03135
03136
03137 if (!url || strlen(url) <= 0) {
03138 ::Error("TFile::Open", "no url specified");
03139 return f;
03140 }
03141
03142 TString expandedUrl(url);
03143 gSystem->ExpandPathName(expandedUrl);
03144
03145
03146
03147
03148 TString opts(options);
03149 Int_t ito = opts.Index("TIMEOUT=");
03150 if (ito != kNPOS) {
03151 TString sto = opts(ito + strlen("TIMEOUT="), opts.Length());
03152 while (!(sto.IsDigit()) && !(sto.IsNull())) { sto.Remove(sto.Length()-1,1); }
03153 if (!(sto.IsNull())) {
03154
03155 Int_t toms = sto.Atoi() * 1000;
03156 if (gDebug > 0) ::Info("TFile::Open", "timeout of %d millisec requested", toms);
03157
03158 sto.Insert(0, "TIMEOUT=");
03159 opts.ReplaceAll(sto, "");
03160
03161 TFileOpenHandle *fh = TFile::AsyncOpen(expandedUrl, opts, ftitle, compress, netopt);
03162
03163 TFile::EAsyncOpenStatus aos = TFile::kAOSNotAsync;
03164 aos = TFile::GetAsyncOpenStatus(fh);
03165 Int_t xtms = toms;
03166 while (aos != TFile::kAOSNotAsync && aos == TFile::kAOSInProgress && xtms > 0) {
03167 gSystem->Sleep(1);
03168 xtms -= 1;
03169 aos = TFile::GetAsyncOpenStatus(fh);
03170 }
03171 if (aos == TFile::kAOSNotAsync || aos == TFile::kAOSSuccess) {
03172
03173 f = TFile::Open(fh);
03174 if (gDebug > 0) {
03175 if (aos == TFile::kAOSSuccess)
03176 ::Info("TFile::Open", "waited %d millisec for asynchronous open", toms - xtms);
03177 else
03178 ::Info("TFile::Open", "timeout option not supported (requires asynchronous"
03179 " open support)");
03180 }
03181 } else {
03182 if (xtms <= 0)
03183 ::Error("TFile::Open", "timeout expired while opening '%s'", expandedUrl.Data());
03184
03185 SafeDelete(fh);
03186 }
03187
03188 return f;
03189 } else {
03190 ::Warning("TFile::Open", "incomplete 'TIMEOUT=' option specification - ignored");
03191 opts.ReplaceAll("TIMEOUT=", "");
03192 }
03193 }
03194
03195
03196 const char *option = opts;
03197
03198
03199 TString namelist(expandedUrl);
03200 Ssiz_t ip = namelist.Index("|");
03201 Bool_t rediroutput = (ip != kNPOS &&
03202 ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
03203 RedirectHandle_t rh;
03204 if (rediroutput) {
03205 TString outf = ".TFileOpen_";
03206 FILE *fout = gSystem->TempFileName(outf);
03207 if (fout) {
03208 fclose(fout);
03209 gSystem->RedirectOutput(outf, "w", &rh);
03210 }
03211 }
03212
03213
03214 TString name, n;
03215 Ssiz_t from = 0;
03216 while (namelist.Tokenize(n, from, "|") && !f) {
03217
03218
03219 if (!strcasecmp(option, "CACHEREAD") ||
03220 ((!strcasecmp(option,"READ") || !strlen(option)) && fgCacheFileForce)) {
03221
03222 if ((f = TFile::OpenFromCache(n, option, ftitle, compress, netopt)))
03223 return f;
03224 }
03225
03226 IncrementFileCounter();
03227
03228
03229
03230 TUrl urlname(n, kTRUE);
03231 name = urlname.GetUrl();
03232
03233 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
03234 TIter nxr(fgAsyncOpenRequests);
03235 TFileOpenHandle *fh = 0;
03236 while ((fh = (TFileOpenHandle *)nxr()))
03237 if (fh->Matches(name))
03238 return TFile::Open(fh);
03239 }
03240
03241
03242 TString lfname = gEnv->GetValue("Path.Localroot", "");
03243 type = GetType(name, option, &lfname);
03244
03245 if (type == kLocal) {
03246
03247
03248 if (lfname.IsNull()) {
03249 urlname.SetHost("");
03250 urlname.SetProtocol("file");
03251 lfname = urlname.GetUrl();
03252 }
03253 f = new TFile(lfname.Data(), option, ftitle, compress);
03254
03255 } else if (type == kNet) {
03256
03257
03258 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
03259 if (h->LoadPlugin() == -1)
03260 return 0;
03261 f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
03262 }
03263
03264 } else if (type == kWeb) {
03265
03266
03267 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
03268 if (h->LoadPlugin() == -1)
03269 return 0;
03270 f = (TFile*) h->ExecPlugin(2, name.Data(), option);
03271 }
03272
03273 } else if (type == kFile) {
03274
03275
03276 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
03277 h->LoadPlugin() == 0) {
03278 name.ReplaceAll("file:", "");
03279 f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
03280 } else
03281 f = new TFile(name.Data(), option, ftitle, compress);
03282
03283 } else {
03284
03285
03286 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name.Data()))) {
03287 if (h->LoadPlugin() == -1)
03288 return 0;
03289 TClass *cl = TClass::GetClass(h->GetClass());
03290 if (cl && cl->InheritsFrom("TNetFile"))
03291 f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
03292 else
03293 f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
03294 } else {
03295
03296
03297
03298
03299 f = TFile::Open(urlname.GetFileAndOptions(), option, ftitle, compress);
03300 }
03301 }
03302
03303 if (f && f->IsZombie()) {
03304 delete f;
03305 f = 0;
03306 }
03307 }
03308
03309 if (rediroutput) {
03310
03311 gSystem->RedirectOutput(0, "", &rh);
03312
03313 if (!f)
03314 gSystem->ShowOutput(&rh);
03315
03316 gSystem->Unlink(rh.fFile);
03317 }
03318
03319
03320
03321 if (type != kLocal && type != kFile &&
03322 f && f->IsWritable() && !f->IsRaw()) {
03323 new TFileCacheWrite(f, 1);
03324 }
03325
03326 return f;
03327 }
03328
03329
03330 TFileOpenHandle *TFile::AsyncOpen(const char *url, Option_t *option,
03331 const char *ftitle, Int_t compress,
03332 Int_t netopt)
03333 {
03334
03335
03336
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355 TFileOpenHandle *fh = 0;
03356 TPluginHandler *h;
03357 TFile *f = 0;
03358 Bool_t notfound = kTRUE;
03359
03360
03361 if (!url || strlen(url) <= 0) {
03362 ::Error("TFile::AsyncOpen", "no url specified");
03363 return fh;
03364 }
03365
03366
03367 TString namelist(url);
03368 gSystem->ExpandPathName(namelist);
03369 Ssiz_t ip = namelist.Index("|");
03370 Bool_t rediroutput = (ip != kNPOS &&
03371 ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
03372 RedirectHandle_t rh;
03373 if (rediroutput) {
03374 TString outf = ".TFileAsyncOpen_";
03375 FILE *fout = gSystem->TempFileName(outf);
03376 if (fout) {
03377 fclose(fout);
03378 gSystem->RedirectOutput(outf, "w", &rh);
03379 }
03380 }
03381
03382
03383 TString name, n;
03384 Ssiz_t from = 0;
03385 while (namelist.Tokenize(n, from, "|") && !f) {
03386
03387
03388
03389 TUrl urlname(n, kTRUE);
03390 name = urlname.GetUrl();
03391
03392
03393 EFileType type = GetType(name, option);
03394
03395
03396 if (type == kNet) {
03397
03398 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
03399 !strcmp(h->GetClass(),"TXNetFile") && h->LoadPlugin() == 0) {
03400 f = (TFile*) h->ExecPlugin(6, name.Data(), option, ftitle, compress, netopt, kTRUE);
03401 notfound = kFALSE;
03402 }
03403 }
03404 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
03405 !strcmp(h->GetClass(),"TAlienFile") && h->LoadPlugin() == 0) {
03406 f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, kTRUE);
03407 notfound = kFALSE;
03408 }
03409
03410 }
03411
03412 if (rediroutput) {
03413
03414 gSystem->RedirectOutput(0, "", &rh);
03415
03416 if (!notfound && !f)
03417 gSystem->ShowOutput(&rh);
03418
03419 gSystem->Unlink(rh.fFile);
03420 }
03421
03422
03423 if (notfound) {
03424 SafeDelete(f);
03425
03426
03427 fh = new TFileOpenHandle(name, option, ftitle, compress, netopt);
03428 } else if (f) {
03429
03430 fh = new TFileOpenHandle(f);
03431 }
03432
03433
03434 if (fh) {
03435
03436 if (!fgAsyncOpenRequests)
03437 fgAsyncOpenRequests = new TList;
03438 fgAsyncOpenRequests->Add(fh);
03439 }
03440
03441
03442 return fh;
03443 }
03444
03445
03446 TFile *TFile::Open(TFileOpenHandle *fh)
03447 {
03448
03449
03450
03451
03452 TFile *f = 0;
03453
03454
03455 if (fh && fgAsyncOpenRequests) {
03456
03457
03458 fgAsyncOpenRequests->Remove(fh);
03459
03460 if ((f = fh->GetFile()) && !(f->IsZombie())) {
03461
03462 Bool_t cr = (!strcmp(f->GetOption(),"CREATE") ||
03463 !strcmp(f->GetOption(),"RECREATE") ||
03464 !strcmp(f->GetOption(),"NEW")) ? kTRUE : kFALSE;
03465 f->Init(cr);
03466 } else {
03467
03468 f = TFile::Open(fh->GetName(), fh->GetOpt(), fh->GetTitle(),
03469 fh->GetCompress(), fh->GetNetOpt());
03470 }
03471
03472
03473
03474 f->fAsyncHandle = fh;
03475 }
03476
03477
03478 return f;
03479 }
03480
03481
03482 Int_t TFile::SysOpen(const char *pathname, Int_t flags, UInt_t mode)
03483 {
03484
03485
03486 #if defined(R__WINGCC)
03487
03488
03489 return ::open(pathname, flags | O_BINARY, mode);
03490 #elif defined(R__SEEK64)
03491 return ::open64(pathname, flags, mode);
03492 #else
03493 return ::open(pathname, flags, mode);
03494 #endif
03495 }
03496
03497
03498 Int_t TFile::SysClose(Int_t fd)
03499 {
03500
03501
03502 if (fd < 0) return 0;
03503 return ::close(fd);
03504 }
03505
03506
03507 Int_t TFile::SysRead(Int_t fd, void *buf, Int_t len)
03508 {
03509
03510
03511 return ::read(fd, buf, len);
03512 }
03513
03514
03515 Int_t TFile::SysWrite(Int_t fd, const void *buf, Int_t len)
03516 {
03517
03518
03519 return ::write(fd, buf, len);
03520 }
03521
03522 Long64_t TFile::SysSeek(Int_t fd, Long64_t offset, Int_t whence)
03523 {
03524
03525
03526
03527
03528 #if defined (R__SEEK64)
03529 return ::lseek64(fd, offset, whence);
03530 #elif defined(WIN32)
03531 return ::_lseeki64(fd, offset, whence);
03532 #else
03533 return ::lseek(fd, offset, whence);
03534 #endif
03535 }
03536
03537
03538 Int_t TFile::SysStat(Int_t, Long_t *id, Long64_t *size, Long_t *flags,
03539 Long_t *modtime)
03540 {
03541
03542
03543
03544
03545 return gSystem->GetPathInfo(fRealName, id, size, flags, modtime);
03546 }
03547
03548
03549 Int_t TFile::SysSync(Int_t fd)
03550 {
03551
03552
03553 if (TestBit(kDevNull)) return 0;
03554
03555 #ifndef WIN32
03556 return ::fsync(fd);
03557 #else
03558 return ::_commit(fd);
03559 #endif
03560 }
03561
03562
03563 Long64_t TFile::GetBytesWritten() const
03564 {
03565
03566
03567 return fCacheWrite ? fCacheWrite->GetBytesInCache() + fBytesWrite : fBytesWrite;
03568 }
03569
03570
03571 Long64_t TFile::GetFileBytesRead()
03572 {
03573
03574
03575 return fgBytesRead;
03576 }
03577
03578
03579 Long64_t TFile::GetFileBytesWritten()
03580 {
03581
03582
03583
03584 return fgBytesWrite;
03585 }
03586
03587
03588 Int_t TFile::GetFileReadCalls()
03589 {
03590
03591
03592 return fgReadCalls;
03593 }
03594
03595
03596 Int_t TFile::GetReadaheadSize()
03597 {
03598
03599
03600 return fgReadaheadSize;
03601 }
03602
03603
03604 void TFile::SetReadaheadSize(Int_t bytes) { fgReadaheadSize = bytes; }
03605
03606
03607 void TFile::SetFileBytesRead(Long64_t bytes) { fgBytesRead = bytes; }
03608
03609
03610 void TFile::SetFileBytesWritten(Long64_t bytes) { fgBytesWrite = bytes; }
03611
03612
03613 void TFile::SetFileReadCalls(Int_t readcalls) { fgReadCalls = readcalls; }
03614
03615
03616 Long64_t TFile::GetFileCounter() { return fgFileCounter; }
03617
03618
03619 void TFile::IncrementFileCounter() { fgFileCounter++; }
03620
03621
03622 Bool_t TFile::SetCacheFileDir(const char *cachedir, Bool_t operatedisconnected,
03623 Bool_t forcecacheread )
03624 {
03625
03626
03627
03628 TString cached = cachedir;
03629 if (!cached.EndsWith("/"))
03630 cached += "/";
03631
03632 if (gSystem->AccessPathName(cached, kFileExists)) {
03633
03634 gSystem->mkdir(cached, kTRUE);
03635 if (gSystem->AccessPathName(cached, kFileExists)) {
03636 ::Error("TFile::SetCacheFileDir", "no suffcient permissions on cache directory %s or cannot create it", cachedir);
03637 fgCacheFileDir = "";
03638 return kFALSE;
03639 }
03640 gSystem->Chmod(cached, 0700);
03641 }
03642 if (gSystem->AccessPathName(cached, kWritePermission))
03643 gSystem->Chmod(cached, 0700);
03644 fgCacheFileDir = cached;
03645 fgCacheFileDisconnected = operatedisconnected;
03646 fgCacheFileForce = forcecacheread;
03647 return kTRUE;
03648 }
03649
03650
03651 const char *TFile::GetCacheFileDir()
03652 {
03653
03654
03655 return fgCacheFileDir;
03656 }
03657
03658
03659 Bool_t TFile::ShrinkCacheFileDir(Long64_t shrinksize, Long_t cleanupinterval)
03660 {
03661
03662
03663
03664
03665
03666 if (fgCacheFileDir == "") {
03667 return kFALSE;
03668 }
03669
03670
03671 Long_t id;
03672 Long64_t size;
03673 Long_t flags;
03674 Long_t modtime;
03675
03676 TString cachetagfile = fgCacheFileDir;
03677 cachetagfile += ".tag.ROOT.cache";
03678 if (!gSystem->GetPathInfo(cachetagfile, &id, &size, &flags, &modtime)) {
03679
03680 Long_t lastcleanuptime = ((Long_t)time(0) - modtime);
03681 if (lastcleanuptime < cleanupinterval) {
03682 ::Info("TFile::ShrinkCacheFileDir", "clean-up is skipped - last cleanup %lu seconds ago - you requested %lu", lastcleanuptime, cleanupinterval);
03683 return kTRUE;
03684 }
03685 }
03686
03687
03688 cachetagfile += "?filetype=raw";
03689 TFile *tagfile = 0;
03690
03691 if (!(tagfile = TFile::Open(cachetagfile, "RECREATE"))) {
03692 ::Error("TFile::ShrinkCacheFileDir", "cannot create the cache tag file %s", cachetagfile.Data());
03693 return kFALSE;
03694 }
03695
03696
03697
03698
03699 TString cmd;
03700 #if defined(R__WIN32)
03701 cmd = "echo <TFile::ShrinkCacheFileDir>: cleanup to be implemented";
03702 #elif defined(R__MACOSX)
03703 cmd.Format("perl -e 'my $cachepath = \"%s\"; my $cachesize = %lld;my $findcommand=\"find $cachepath -type f -exec stat -f \\\"\\%%a::\\%%N::\\%%z\\\" \\{\\} \\\\\\;\";my $totalsize=0;open FIND, \"$findcommand | sort -k 1 |\";while (<FIND>) { my ($accesstime, $filename, $filesize) = split \"::\",$_; $totalsize += $filesize;if ($totalsize > $cachesize) {if ( ( -e \"${filename}.ROOT.cachefile\" ) && ( -e \"${filename}\" ) ) {unlink \"$filename.ROOT.cachefile\";unlink \"$filename\";}}}close FIND;' ", fgCacheFileDir.Data(),shrinksize);
03704 #else
03705 cmd.Format("perl -e 'my $cachepath = \"%s\"; my $cachesize = %lld;my $findcommand=\"find $cachepath -type f -exec stat -c \\\"\\%%x::\\%%n::\\%%s\\\" \\{\\} \\\\\\;\";my $totalsize=0;open FIND, \"$findcommand | sort -k 1 |\";while (<FIND>) { my ($accesstime, $filename, $filesize) = split \"::\",$_; $totalsize += $filesize;if ($totalsize > $cachesize) {if ( ( -e \"${filename}.ROOT.cachefile\" ) && ( -e \"${filename}\" ) ) {unlink \"$filename.ROOT.cachefile\";unlink \"$filename\";}}}close FIND;' ", fgCacheFileDir.Data(),shrinksize);
03706 #endif
03707
03708 tagfile->WriteBuffer(cmd, 4096);
03709 delete tagfile;
03710
03711 if ((gSystem->Exec(cmd)) != 0) {
03712 ::Error("TFile::ShrinkCacheFileDir", "error executing clean-up script");
03713 return kFALSE;
03714 }
03715
03716 return kTRUE;
03717 }
03718
03719
03720 UInt_t TFile::SetOpenTimeout(UInt_t timeout)
03721 {
03722
03723
03724 UInt_t to = fgOpenTimeout;
03725 fgOpenTimeout = timeout;
03726 return to;
03727 }
03728
03729
03730 UInt_t TFile::GetOpenTimeout()
03731 {
03732
03733
03734 return fgOpenTimeout;
03735 }
03736
03737
03738 Bool_t TFile::SetOnlyStaged(Bool_t onlystaged)
03739 {
03740
03741
03742
03743
03744 Bool_t f = fgOnlyStaged;
03745 fgOnlyStaged = onlystaged;
03746 return f;
03747 }
03748
03749
03750 Bool_t TFile::GetOnlyStaged()
03751 {
03752
03753
03754 return fgOnlyStaged;
03755 }
03756
03757
03758 Bool_t TFile::Matches(const char *url)
03759 {
03760
03761
03762
03763
03764
03765
03766 TUrl u(url);
03767
03768
03769 if (!strcmp(u.GetFile(), fUrl.GetFile())) {
03770
03771 if (u.GetPort() == fUrl.GetPort()) {
03772 if (!strcmp(u.GetHostFQDN(), fUrl.GetHostFQDN())) {
03773
03774 return kTRUE;
03775 }
03776 }
03777 }
03778
03779
03780 return kFALSE;
03781 }
03782
03783
03784 Bool_t TFileOpenHandle::Matches(const char *url)
03785 {
03786
03787
03788
03789 if (fFile) {
03790 return fFile->Matches(url);
03791 } else if (fName.Length() > 0){
03792
03793 TUrl u(url);
03794 TUrl uref(fName);
03795 if (!strcmp(u.GetFile(), uref.GetFile())) {
03796
03797 if (u.GetPort() == uref.GetPort()) {
03798
03799 if (!strcmp(u.GetHostFQDN(), uref.GetHostFQDN())) {
03800
03801 return kTRUE;
03802 }
03803 }
03804 }
03805 }
03806
03807
03808 return kFALSE;
03809 }
03810
03811
03812 TFile::EFileType TFile::GetType(const char *name, Option_t *option, TString *prefix)
03813 {
03814
03815
03816
03817
03818
03819 EFileType type = kDefault;
03820
03821 TRegexp re("^root.*:");
03822 TString sname = name;
03823 if (sname.Index(re) != kNPOS) {
03824
03825
03826 type = kNet;
03827
03828
03829
03830
03831
03832
03833 Bool_t localFile = kFALSE;
03834 TUrl url(name);
03835
03836
03837 Bool_t forceRemote = gEnv->GetValue("Path.ForceRemote", 0);
03838 forceRemote = (forceRemote) ? kTRUE : gEnv->GetValue("TFile.ForceRemote", 0);
03839 TString opts = url.GetOptions();
03840 if (opts.Contains("remote=1"))
03841 forceRemote = kTRUE;
03842 else if (opts.Contains("remote=0"))
03843 forceRemote = kFALSE;
03844 if (!forceRemote) {
03845
03846 localFile = gSystem->IsPathLocal(name);
03847 if (localFile) {
03848
03849 const char *fname = url.GetFileAndOptions();
03850 TString lfname;
03851 if (fname[0] == '/') {
03852 if (prefix)
03853 lfname = Form("%s%s", prefix->Data(), fname);
03854 else
03855 lfname = fname;
03856 } else if (fname[0] == '~' || fname[0] == '$') {
03857 lfname = fname;
03858 } else {
03859 lfname = Form("%s/%s", gSystem->HomeDirectory(), fname);
03860 }
03861
03862 TString opt = option;
03863 Bool_t read = (opt.IsNull() ||
03864 !opt.CompareTo("READ", TString::kIgnoreCase)) ? kTRUE : kFALSE;
03865 if (read) {
03866 char *fn;
03867 if ((fn = gSystem->ExpandPathName(TUrl(lfname).GetFile()))) {
03868 if (gSystem->AccessPathName(fn, kReadPermission))
03869 localFile = kFALSE;
03870 delete [] fn;
03871 }
03872 }
03873
03874 if (localFile && prefix)
03875 *prefix = lfname;
03876 }
03877 }
03878
03879
03880 type = (localFile) ? kLocal : type;
03881 } else if (!strncmp(name, "http:", 5)) {
03882
03883
03884 type = kWeb;
03885 } else if (!strncmp(name, "file:", 5)) {
03886
03887
03888 type = kFile;
03889 }
03890
03891
03892 return type;
03893 }
03894
03895
03896 TFile::EAsyncOpenStatus TFile::GetAsyncOpenStatus(const char* name)
03897 {
03898
03899
03900
03901 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
03902 TIter nxr(fgAsyncOpenRequests);
03903 TFileOpenHandle *fh = 0;
03904 while ((fh = (TFileOpenHandle *)nxr()))
03905 if (fh->Matches(name))
03906 return TFile::GetAsyncOpenStatus(fh);
03907 }
03908
03909
03910 TSeqCollection *of = gROOT->GetListOfFiles();
03911 if (of && (of->GetSize() > 0)) {
03912 TIter nxf(of);
03913 TFile *f = 0;
03914 while ((f = (TFile *)nxf()))
03915 if (f->Matches(name))
03916 return f->GetAsyncOpenStatus();
03917 }
03918
03919
03920 return kAOSNotAsync;
03921 }
03922
03923
03924 TFile::EAsyncOpenStatus TFile::GetAsyncOpenStatus(TFileOpenHandle *handle)
03925 {
03926
03927
03928 if (handle && handle->fFile) {
03929 if (!handle->fFile->IsZombie())
03930 return handle->fFile->GetAsyncOpenStatus();
03931 else
03932 return TFile::kAOSFailure;
03933 }
03934
03935
03936 return TFile::kAOSNotAsync;
03937 }
03938
03939
03940 const TUrl *TFile::GetEndpointUrl(const char* name)
03941 {
03942
03943
03944
03945
03946 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
03947 TIter nxr(fgAsyncOpenRequests);
03948 TFileOpenHandle *fh = 0;
03949 while ((fh = (TFileOpenHandle *)nxr()))
03950 if (fh->Matches(name))
03951 if (fh->fFile)
03952 return fh->fFile->GetEndpointUrl();
03953 }
03954
03955
03956 TSeqCollection *of = gROOT->GetListOfFiles();
03957 if (of && (of->GetSize() > 0)) {
03958 TIter nxf(of);
03959 TFile *f = 0;
03960 while ((f = (TFile *)nxf()))
03961 if (f->Matches(name))
03962 return f->GetEndpointUrl();
03963 }
03964
03965
03966 return (const TUrl *)0;
03967 }
03968
03969
03970 void TFile::CpProgress(Long64_t bytesread, Long64_t size, TStopwatch &watch)
03971 {
03972
03973
03974 fprintf(stderr, "[TFile::Cp] Total %.02f MB\t|", (Double_t)size/1048576);
03975
03976 for (int l = 0; l < 20; l++) {
03977 if (size > 0) {
03978 if (l < 20*bytesread/size)
03979 fprintf(stderr, "=");
03980 else if (l == 20*bytesread/size)
03981 fprintf(stderr, ">");
03982 else if (l > 20*bytesread/size)
03983 fprintf(stderr, ".");
03984 } else
03985 fprintf(stderr, "=");
03986 }
03987
03988 gSystem->ProcessEvents();
03989 watch.Stop();
03990 Double_t lCopy_time = watch.RealTime();
03991 fprintf(stderr, "| %.02f %% [%.01f MB/s]\r",
03992 100.0*(size?(bytesread/size):1), bytesread/lCopy_time/1048576.);
03993 watch.Continue();
03994 }
03995
03996
03997 Bool_t TFile::Cp(const char *src, const char *dst, Bool_t progressbar,
03998 UInt_t buffersize)
03999 {
04000
04001
04002
04003 Bool_t rmdestiferror = kFALSE;
04004 TStopwatch watch;
04005 Bool_t success = kFALSE;
04006
04007 TUrl sURL(src, kTRUE);
04008 TUrl dURL(dst, kTRUE);
04009
04010 TString oopt = "RECREATE";
04011 TString ourl = dURL.GetUrl();
04012
04013
04014 TString raw = "filetype=raw";
04015
04016
04017 TString opt = sURL.GetOptions();
04018 if (opt != "") opt += "&";
04019 opt += raw;
04020
04021
04022
04023
04024 opt += Form("&cachesz=%d&readaheadsz=%d&rmpolicy=1", 4*buffersize, 2*buffersize);
04025 sURL.SetOptions(opt);
04026
04027
04028 opt = dURL.GetOptions();
04029 if (opt != "") opt += "&";
04030 opt += raw;
04031 dURL.SetOptions(opt);
04032
04033 char *copybuffer = 0;
04034
04035 TFile *sfile = 0;
04036 TFile *dfile = 0;
04037
04038
04039 if (!(sfile = TFile::Open(sURL.GetUrl(), "READ"))) {
04040 ::Error("TFile::Cp", "cannot open source file %s", src);
04041 goto copyout;
04042 }
04043
04044
04045
04046 if (TFile::GetType(ourl, "") == TFile::kNet)
04047 if (gSystem->AccessPathName(ourl)) {
04048 oopt = "NEW";
04049
04050 opt += "&mkpath=1";
04051 dURL.SetOptions(opt);
04052 }
04053
04054
04055 if (!(dfile = TFile::Open(dURL.GetUrl(), oopt))) {
04056 ::Error("TFile::Cp", "cannot open destination file %s", dst);
04057 goto copyout;
04058 }
04059
04060
04061
04062 rmdestiferror = kTRUE;
04063
04064 sfile->Seek(0);
04065 dfile->Seek(0);
04066
04067 copybuffer = new char[buffersize];
04068 if (!copybuffer) {
04069 ::Error("TFile::Cp", "cannot allocate the copy buffer");
04070 goto copyout;
04071 }
04072
04073 Bool_t readop;
04074 Bool_t writeop;
04075 Long64_t read;
04076 Long64_t written;
04077 Long64_t totalread;
04078 Long64_t filesize;
04079 Long64_t b00;
04080 filesize = sfile->GetSize();
04081 totalread = 0;
04082 watch.Start();
04083
04084 b00 = sfile->GetBytesRead();
04085
04086 do {
04087 if (progressbar) CpProgress(totalread, filesize,watch);
04088
04089 Long64_t b1 = sfile->GetBytesRead() - b00;
04090
04091 Long64_t readsize;
04092 if (filesize - b1 > (Long64_t)buffersize) {
04093 readsize = buffersize;
04094 } else {
04095 readsize = filesize - b1;
04096 }
04097
04098 if (readsize == 0) break;
04099
04100 Long64_t b0 = sfile->GetBytesRead();
04101 sfile->Seek(totalread,TFile::kBeg);
04102 readop = sfile->ReadBuffer(copybuffer, (Int_t)readsize);
04103 read = sfile->GetBytesRead() - b0;
04104 if ((read <= 0) || readop) {
04105 ::Error("TFile::Cp", "cannot read from source file %s. readsize=%lld read=%lld readop=%d",
04106 src, readsize, read, readop);
04107 goto copyout;
04108 }
04109
04110 Long64_t w0 = dfile->GetBytesWritten();
04111 writeop = dfile->WriteBuffer(copybuffer, (Int_t)read);
04112 written = dfile->GetBytesWritten() - w0;
04113 if ((written != read) || writeop) {
04114 ::Error("TFile::Cp", "cannot write %lld bytes to destination file %s", read, dst);
04115 goto copyout;
04116 }
04117 totalread += read;
04118 } while (read == (Long64_t)buffersize);
04119
04120 if (progressbar) {
04121 CpProgress(totalread, filesize,watch);
04122 fprintf(stderr, "\n");
04123 }
04124
04125 success = kTRUE;
04126
04127 copyout:
04128 if (sfile) sfile->Close();
04129 if (dfile) dfile->Close();
04130
04131 if (sfile) delete sfile;
04132 if (dfile) delete dfile;
04133 if (copybuffer) delete[] copybuffer;
04134
04135 if (rmdestiferror && (success != kTRUE))
04136 gSystem->Unlink(dst);
04137
04138 watch.Stop();
04139 watch.Reset();
04140
04141 return success;
04142 }
04143
04144
04145
04146
04147
04148 #if defined(R__neverLINUX) && !defined(R__WINGCC)
04149 Bool_t TFile::ReadBufferAsync(Long64_t offset, Int_t len)
04150 {
04151
04152
04153
04154
04155
04156
04157 if (IsA() != TFile::Class())
04158 return kTRUE;
04159
04160 int advice = POSIX_FADV_WILLNEED;
04161 if (len == 0) {
04162
04163
04164
04165 advice = POSIX_FADV_NORMAL;
04166 }
04167 Double_t start = 0;
04168 if (gPerfStats != 0) start = TTimeStamp();
04169 #if defined(R__SEEK64)
04170 Int_t result = posix_fadvise64(fD, offset, len, advice);
04171 #else
04172 Int_t result = posix_fadvise(fD, offset, len, advice);
04173 #endif
04174 if (gPerfStats != 0) {
04175 gPerfStats->FileReadEvent(this, len, start);
04176 }
04177 return (result != 0);
04178 }
04179 #else
04180 Bool_t TFile::ReadBufferAsync(Long64_t, Int_t)
04181 {
04182
04183
04184 return kTRUE;
04185 }
04186 #endif
04187
04188
04189 Int_t TFile::GetBytesToPrefetch() const
04190 {
04191
04192
04193
04194 TFileCacheRead *cr = 0;
04195 if ((cr = GetCacheRead())) {
04196 Int_t bytes = cr->GetBufferSize() / 4 * 3;
04197 return ((bytes < 0) ? 0 : bytes);
04198 }
04199 return 0;
04200 }