Logo ROOT   6.10/09
Reference Guide
TFile.cxx
Go to the documentation of this file.
1 // @(#)root/io:$Id: 3a19890259ad6443ee313e090166614971ad4296 $
2 // Author: Rene Brun 28/11/94
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /**
13  \defgroup IO Input/Output Library
14 
15  The library collecting the ROOT classes dedicated to data input and output.
16 
17 */
18 
19 /**
20 \file TFile.cxx
21 \class TFile
22 \ingroup IO
23 
24 A ROOT file is a suite of consecutive data records (TKey instances) with
25 a well defined format.
26 
27 If the key is located past the 32 bit file limit (> 2 GB) then some fields will
28 be 8 instead of 4 bytes:
29 
30 Byte Range | Member Name | Description
31 ----------------|-----------|--------------
32 1->4 | Nbytes | Length of compressed object (in bytes)
33 5->6 | Version | TKey version identifier
34 7->10 | ObjLen | Length of uncompressed object
35 11->14 | Datime | Date and time when object was written to file
36 15->16 | KeyLen | Length of the key structure (in bytes)
37 17->18 | Cycle | Cycle of key
38 19->22 [19->26] | SeekKey | Pointer to record itself (consistency check)
39 23->26 [27->34] | SeekPdir | Pointer to directory header
40 27->27 [35->35] | lname | Number of bytes in the class name
41 28->.. [36->..] | ClassName | Object Class Name
42 ..->.. | lname | Number of bytes in the object name
43 ..->.. | Name | lName bytes with the name of the object
44 ..->.. | lTitle | Number of bytes in the object title
45 ..->.. | Title | Title of the object
46 -----> | DATA | Data bytes associated to the object
47 
48 The first data record starts at byte fBEGIN (currently set to kBEGIN).
49 Bytes 1->kBEGIN contain the file description, when fVersion >= 1000000
50 it is a large file (> 2 GB) and the offsets will be 8 bytes long and
51 fUnits will be set to 8:
52 Byte Range | Record Name | Description
53 ----------------|-------------|------------
54 1->4 | "root" | Root file identifier
55 5->8 | fVersion | File format version
56 9->12 | fBEGIN | Pointer to first data record
57 13->16 [13->20] | fEND | Pointer to first free word at the EOF
58 17->20 [21->28] | fSeekFree | Pointer to FREE data record
59 21->24 [29->32] | fNbytesFree | Number of bytes in FREE data record
60 25->28 [33->36] | nfree | Number of free data records
61 29->32 [37->40] | fNbytesName | Number of bytes in TNamed at creation time
62 33->33 [41->41] | fUnits | Number of bytes for file pointers
63 34->37 [42->45] | fCompress | Compression level and algorithm
64 38->41 [46->53] | fSeekInfo | Pointer to TStreamerInfo record
65 42->45 [54->57] | fNbytesInfo | Number of bytes in TStreamerInfo record
66 46->63 [58->75] | fUUID | Universal Unique ID
67 
68 Begin_Macro
69 ../../../tutorials/io/file.C
70 End_Macro
71 The structure of a directory is shown in TDirectoryFile::TDirectoryFile
72 */
73 
74 #include "RConfig.h"
75 
76 #ifdef R__LINUX
77 // for posix_fadvise
78 #ifndef _XOPEN_SOURCE
79 #define _XOPEN_SOURCE 600
80 #endif
81 #endif
82 #include <fcntl.h>
83 #include <errno.h>
84 #include <sys/stat.h>
85 #ifndef WIN32
86 # include <unistd.h>
87 #else
88 # define ssize_t int
89 # include <io.h>
90 # include <sys/types.h>
91 #endif
92 
93 #include "Bytes.h"
94 #include "Compression.h"
95 #include "Riostream.h"
96 #include "RConfigure.h"
97 #include "Strlen.h"
98 #include "TArrayC.h"
99 #include "TClass.h"
100 #include "TClassEdit.h"
101 #include "TClassTable.h"
102 #include "TDatime.h"
103 #include "TError.h"
104 #include "TFile.h"
105 #include "TFileCacheRead.h"
106 #include "TFileCacheWrite.h"
107 #include "TFree.h"
108 #include "TInterpreter.h"
109 #include "TKey.h"
110 #include "TMakeProject.h"
111 #include "TPluginManager.h"
112 #include "TProcessUUID.h"
113 #include "TRegexp.h"
114 #include "TPRegexp.h"
115 #include "TROOT.h"
116 #include "TStreamerInfo.h"
117 #include "TStreamerElement.h"
118 #include "TSystem.h"
119 #include "TTimeStamp.h"
120 #include "TVirtualPerfStats.h"
121 #include "TArchiveFile.h"
122 #include "TEnv.h"
123 #include "TVirtualMonitoring.h"
124 #include "TVirtualMutex.h"
125 #include "TMathBase.h"
126 #include "TObjString.h"
127 #include "TStopwatch.h"
128 #include "compiledata.h"
129 #include <cmath>
130 #include <set>
131 #include "TSchemaRule.h"
132 #include "TSchemaRuleSet.h"
133 #include "TThreadSlots.h"
134 #include "TGlobal.h"
135 
136 using std::sqrt;
137 
138 std::atomic<Long64_t> TFile::fgBytesRead{0};
139 std::atomic<Long64_t> TFile::fgBytesWrite{0};
140 std::atomic<Long64_t> TFile::fgFileCounter{0};
141 std::atomic<Int_t> TFile::fgReadCalls{0};
150 #ifdef R__USE_IMT
152 #endif
153 
154 const Int_t kBEGIN = 100;
157 
158 //*-*x17 macros/layout_file
159 // Needed to add the "fake" global gFile to the list of globals.
160 namespace {
161 static struct AddPseudoGlobals {
162 AddPseudoGlobals() {
163  // User "gCling" as synonym for "libCore static initialization has happened".
164  // This code here must not trigger it.
167 }
168 } gAddPseudoGlobals;
169 }
170 ////////////////////////////////////////////////////////////////////////////////
171 /// File default Constructor.
172 
173 TFile::TFile() : TDirectoryFile(), fInfoCache(0)
174 {
175  fD = -1;
176  fFree = 0;
177  fWritten = 0;
178  fSumBuffer = 0;
179  fSum2Buffer = 0;
180  fClassIndex = 0;
181  fCompress = 0;
182  fProcessIDs = 0;
183  fNProcessIDs = 0;
184  fOffset = 0;
185  fArchive = 0;
186  fCacheRead = 0;
187  fCacheReadMap = new TMap();
188  fCacheWrite = 0;
189  fArchiveOffset = 0;
190  fReadCalls = 0;
191  fInfoCache = 0;
192  fOpenPhases = 0;
193  fNoAnchorInName = kFALSE;
194  fIsRootFile = kTRUE;
195  fIsArchive = kFALSE;
196  fInitDone = kFALSE;
197  fMustFlush = kTRUE;
198  fIsPcmFile = kFALSE;
199  fAsyncHandle = 0;
200  fAsyncOpenStatus = kAOSNotAsync;
201  SetBit(kBinaryFile, kTRUE);
202 
203  fBEGIN = 0;
204  fEND = 0;
205  fBytesRead = 0;
206  fBytesReadExtra = 0;
207  fBytesWrite = 0;
208  fCompress = 0;
209  fNbytesFree = 0;
210  fNbytesInfo = 0;
211  fSeekFree = 0;
212  fSeekInfo = 0;
213  fUnits = 0;
214  fVersion = 0;
215 
216  if (gDebug)
217  Info("TFile", "default ctor");
218 }
219 
220 ////////////////////////////////////////////////////////////////////////////////
221 /// Opens or creates a local ROOT file.
222 ///
223 /// \param[in] fname1 The name of the file
224 /// \param[in] option Specifies the mode in which the file is opened
225 /// \param[in] ftitle The title of the file
226 /// \param[in] compress Specifies the compression algorithm and level
227 ///
228 /// It is recommended to specify fname1 as "<file>.root". The suffix ".root"
229 /// will be used by object browsers to automatically identify the file as
230 /// a ROOT file. If the constructor fails in any way IsZombie() will
231 /// return true. Use IsOpen() to check if the file is (still) open.
232 /// To open non-local files use the static TFile::Open() method, that
233 /// will take care of opening the files using the correct remote file
234 /// access plugin.
235 ///
236 /// Option | Description
237 /// -------|------------
238 /// NEW or CREATE | Create a new file and open it for writing, if the file already exists the file is not opened.
239 /// RECREATE | Create a new file, if the file already exists it will be overwritten.
240 /// UPDATE | Open an existing file for writing. If no file exists, it is created.
241 /// READ | Open an existing file for reading (default).
242 /// NET | Used by derived remote file access classes, not a user callable option.
243 /// WEB | Used by derived remote http access class, not a user callable option.
244 ///
245 /// If option = "" (default), READ is assumed.
246 /// The file can be specified as a URL of the form:
247 ///
248 /// file:///user/rdm/bla.root or file:/user/rdm/bla.root
249 ///
250 /// The file can also be a member of an archive, in which case it is
251 /// specified as:
252 ///
253 /// multi.zip#file.root or multi.zip#0
254 ///
255 /// which will open file.root which is a member of the file multi.zip
256 /// archive or member 1 from the archive. For more on archive file
257 /// support see the TArchiveFile class.
258 /// TFile and its remote access plugins can also be used to open any
259 /// file, i.e. also non ROOT files, using:
260 ///
261 /// file.tar?filetype=raw
262 ///
263 /// This is convenient because the many remote file access plugins allow
264 /// easy access to/from the many different mass storage systems.
265 /// The title of the file (ftitle) will be shown by the ROOT browsers.
266 /// A ROOT file (like a Unix file system) may contain objects and
267 /// directories. There are no restrictions for the number of levels
268 /// of directories.
269 /// A ROOT file is designed such that one can write in the file in pure
270 /// sequential mode (case of BATCH jobs). In this case, the file may be
271 /// read sequentially again without using the file index written
272 /// at the end of the file. In case of a job crash, all the information
273 /// on the file is therefore protected.
274 /// A ROOT file can be used interactively. In this case, one has the
275 /// possibility to delete existing objects and add new ones.
276 /// When an object is deleted from the file, the freed space is added
277 /// into the FREE linked list (fFree). The FREE list consists of a chain
278 /// of consecutive free segments on the file. At the same time, the first
279 /// 4 bytes of the freed record on the file are overwritten by GAPSIZE
280 /// where GAPSIZE = -(Number of bytes occupied by the record).
281 /// Option compress is used to specify the compression level and algorithm:
282 ///
283 /// compress = 100 * algorithm + level
284 ///
285 /// Level | Explanation
286 /// ------|-------------
287 /// 0 | objects written to this file will not be compressed.
288 /// 1 | minimal compression level but fast.
289 /// ... | ....
290 /// 9 | maximal compression level but slower and might use more memory.
291 /// (For the currently supported algorithms, the maximum level is 9)
292 /// If compress is negative it indicates the compression level is not set yet.
293 /// The enumeration ROOT::ECompressionAlgorithm associates each
294 /// algorithm with a number. There is a utility function to help
295 /// to set the value of compress. For example,
296 /// ROOT::CompressionSettings(ROOT::kLZMA, 1)
297 /// will build an integer which will set the compression to use
298 /// the LZMA algorithm and compression level 1. These are defined
299 /// in the header file <em>Compression.h</em>.
300 /// Note that the compression settings may be changed at any time.
301 /// The new compression settings will only apply to branches created
302 /// or attached after the setting is changed and other objects written
303 /// after the setting is changed.
304 /// In case the file does not exist or is not a valid ROOT file,
305 /// it is made a Zombie. One can detect this situation with a code like:
306 /// ~~~{.cpp}
307 /// TFile f("file.root");
308 /// if (f.IsZombie()) {
309 /// std::cout << "Error opening file" << std::endl;
310 /// exit(-1);
311 /// }
312 /// ~~~
313 /// When opening the file, the system checks the validity of this directory.
314 /// If something wrong is detected, an automatic Recovery is performed. In
315 /// this case, the file is scanned sequentially reading all logical blocks
316 /// and attempting to rebuild a correct directory (see TFile::Recover).
317 /// One can disable the automatic recovery procedure when reading one
318 /// or more files by setting the environment variable "TFile.Recover: 0"
319 /// in the system.rootrc file.
320 ///
321 
322 TFile::TFile(const char *fname1, Option_t *option, const char *ftitle, Int_t compress)
323  : TDirectoryFile(), fUrl(fname1,kTRUE), fInfoCache(0), fOpenPhases(0)
324 {
325  if (!gROOT)
326  ::Fatal("TFile::TFile", "ROOT system not initialized");
327 
328  // store name without the options as name and title
329  TString sfname1 = fname1;
330  fNoAnchorInName = kFALSE;
331  if (sfname1.Index("?") != kNPOS) {
332  TString s = sfname1(0, sfname1.Index("?"));
333  SetName(s);
334  fNoAnchorInName = kTRUE;
335  } else
336  SetName(fname1);
337 
338  SetTitle(ftitle);
339 
340  // accept also URL like "file:..." syntax
341  fname1 = fUrl.GetFile();
342 
343  // if option contains filetype=raw then go into raw file mode
344  fIsRootFile = kTRUE;
345  if (strstr(fUrl.GetOptions(), "filetype=raw"))
346  fIsRootFile = kFALSE;
347 
348  // if option contains filetype=pcm then go into ROOT PCM file mode
349  fIsPcmFile = kFALSE;
350  if (strstr(fUrl.GetOptions(), "filetype=pcm"))
351  fIsPcmFile = kTRUE;
352 
353  // Init initialization control flag
354  fInitDone = kFALSE;
355  fMustFlush = kTRUE;
356 
357  // We are opening synchronously
358  fAsyncHandle = 0;
359  fAsyncOpenStatus = kAOSNotAsync;
360 
361  TDirectoryFile::Build(this, 0);
362 
363  fD = -1;
364  fFree = 0;
365  fVersion = gROOT->GetVersionInt(); //ROOT version in integer format
366  fUnits = 4;
367  fOption = option;
368  fCompress = compress;
369  fWritten = 0;
370  fSumBuffer = 0;
371  fSum2Buffer = 0;
372  fBytesRead = 0;
373  fBytesReadExtra = 0;
374  fBytesWrite = 0;
375  fClassIndex = 0;
376  fSeekInfo = 0;
377  fNbytesInfo = 0;
378  fProcessIDs = 0;
379  fNProcessIDs = 0;
380  fOffset = 0;
381  fCacheRead = 0;
382  fCacheReadMap = new TMap();
383  fCacheWrite = 0;
384  fReadCalls = 0;
385  SetBit(kBinaryFile, kTRUE);
386 
387  fOption.ToUpper();
388 
389  fArchiveOffset = 0;
390  fIsArchive = kFALSE;
391  fArchive = 0;
392  if (fIsRootFile && !fIsPcmFile && fOption != "NEW" && fOption != "CREATE"
393  && fOption != "RECREATE") {
394  // If !gPluginMgr then we are at startup and cannot handle plugins
395  // as TArchiveFile yet.
396  fArchive = gPluginMgr ? TArchiveFile::Open(fUrl.GetUrl(), this) : 0;
397  if (fArchive) {
398  fname1 = fArchive->GetArchiveName();
399  // if no archive member is specified then this TFile is just used
400  // to read the archive contents
401  if (!strlen(fArchive->GetMemberName()))
402  fIsArchive = kTRUE;
403  }
404  }
405 
406  if (fOption == "NET")
407  return;
408 
409  if (fOption == "WEB") {
410  fOption = "READ";
411  fWritable = kFALSE;
412  return;
413  }
414 
415  if (fOption == "NEW")
416  fOption = "CREATE";
417 
418  Bool_t create = (fOption == "CREATE") ? kTRUE : kFALSE;
419  Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE;
420  Bool_t update = (fOption == "UPDATE") ? kTRUE : kFALSE;
421  Bool_t read = (fOption == "READ") ? kTRUE : kFALSE;
422  if (!create && !recreate && !update && !read) {
423  read = kTRUE;
424  fOption = "READ";
425  }
426 
427  Bool_t devnull = kFALSE;
428 
429  if (!fname1 || !fname1[0]) {
430  Error("TFile", "file name is not specified");
431  goto zombie;
432  }
433 
434  // support dumping to /dev/null on UNIX
435  if (!strcmp(fname1, "/dev/null") &&
437  devnull = kTRUE;
438  create = kTRUE;
439  recreate = kFALSE;
440  update = kFALSE;
441  read = kFALSE;
442  fOption = "CREATE";
443  SetBit(kDevNull);
444  }
445 
446  const char *fname;
447  if ((fname = gSystem->ExpandPathName(fname1))) {
448  SetName(fname);
449  delete [] fname;
450  fRealName = GetName();
451  fname = fRealName.Data();
452  } else {
453  Error("TFile", "error expanding path %s", fname1);
454  goto zombie;
455  }
456 
457  if (recreate) {
458  if (!gSystem->AccessPathName(fname, kFileExists)) {
459  if (gSystem->Unlink(fname) != 0) {
460  SysError("TFile", "could not delete %s (errno: %d)",
461  fname, gSystem->GetErrno());
462  goto zombie;
463  }
464  }
465  recreate = kFALSE;
466  create = kTRUE;
467  fOption = "CREATE";
468  }
469  if (create && !devnull && !gSystem->AccessPathName(fname, kFileExists)) {
470  Error("TFile", "file %s already exists", fname);
471  goto zombie;
472  }
473  if (update) {
474  if (gSystem->AccessPathName(fname, kFileExists)) {
475  update = kFALSE;
476  create = kTRUE;
477  }
478  if (update && gSystem->AccessPathName(fname, kWritePermission)) {
479  Error("TFile", "no write permission, could not open file %s", fname);
480  goto zombie;
481  }
482  }
483  if (read) {
484  if (gSystem->AccessPathName(fname, kFileExists)) {
485  Error("TFile", "file %s does not exist", fname);
486  goto zombie;
487  }
488  if (gSystem->AccessPathName(fname, kReadPermission)) {
489  Error("TFile", "no read permission, could not open file %s", fname);
490  goto zombie;
491  }
492  }
493 
494  // Connect to file system stream
495  if (create || update) {
496 #ifndef WIN32
497  fD = SysOpen(fname, O_RDWR | O_CREAT, 0644);
498 #else
499  fD = SysOpen(fname, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
500 #endif
501  if (fD == -1) {
502  SysError("TFile", "file %s can not be opened", fname);
503  goto zombie;
504  }
505  fWritable = kTRUE;
506  } else {
507 #ifndef WIN32
508  fD = SysOpen(fname, O_RDONLY, 0644);
509 #else
510  fD = SysOpen(fname, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
511 #endif
512  if (fD == -1) {
513  SysError("TFile", "file %s can not be opened for reading", fname);
514  goto zombie;
515  }
516  fWritable = kFALSE;
517  }
518 
519  Init(create);
520 
521  return;
522 
523 zombie:
524  // error in file opening occurred, make this object a zombie
525  {
527  gROOT->GetListOfClosedObjects()->Add(this);
528  }
529  MakeZombie();
530  gDirectory = gROOT;
531 }
532 
533 ////////////////////////////////////////////////////////////////////////////////
534 /// TFile objects can not be copied.
535 
536 TFile::TFile(const TFile &) : TDirectoryFile(), fInfoCache(0)
537 {
538  MayNotUse("TFile::TFile(const TFile &)");
539 }
540 
541 ////////////////////////////////////////////////////////////////////////////////
542 /// File destructor.
543 
545 {
546  Close();
547 
548  SafeDelete(fAsyncHandle);
549  SafeDelete(fCacheRead);
550  SafeDelete(fCacheReadMap);
551  SafeDelete(fCacheWrite);
552  SafeDelete(fProcessIDs);
553  SafeDelete(fFree);
554  SafeDelete(fArchive);
555  SafeDelete(fInfoCache);
556  SafeDelete(fOpenPhases);
557 
558  {
560  gROOT->GetListOfClosedObjects()->Remove(this);
561  gROOT->GetUUIDs()->RemoveUUID(GetUniqueID());
562  }
563 
564  if (IsOnHeap()) {
565  // Delete object from CINT symbol table so it can not be used anymore.
566  // CINT object are always on the heap.
567  gInterpreter->ResetGlobalVar(this);
568  }
569 
570  if (gDebug)
571  Info("~TFile", "dtor called for %s [%lx]", GetName(),(Long_t)this);
572 }
573 
574 ////////////////////////////////////////////////////////////////////////////////
575 /// Initialize a TFile object.
576 ///
577 /// \param[in] create Create a new file.
578 ///
579 /// TFile implementations providing asynchronous open functionality need to
580 /// override this method to run the appropriate checks before calling this
581 /// standard initialization part. See TXNetFile::Init for an example.
582 
583 void TFile::Init(Bool_t create)
584 {
585  if (fInitDone)
586  // Already called once
587  return;
588  fInitDone = kTRUE;
589 
590  if (!fIsRootFile) {
591  gDirectory = gROOT;
592  return;
593  }
594 
595  if (fArchive) {
596  if (fOption != "READ") {
597  Error("Init", "archive %s can only be opened in read mode", GetName());
598  delete fArchive;
599  fArchive = 0;
600  fIsArchive = kFALSE;
601  goto zombie;
602  }
603 
604  fArchive->OpenArchive();
605 
606  if (fIsArchive) return;
607 
608  // Make sure the anchor is in the name
609  if (!fNoAnchorInName)
610  if (!strchr(GetName(),'#'))
611  SetName(TString::Format("%s#%s", GetName(), fArchive->GetMemberName()));
612 
613  if (fArchive->SetCurrentMember() != -1)
614  fArchiveOffset = fArchive->GetMemberFilePosition();
615  else {
616  Error("Init", "member %s not found in archive %s",
617  fArchive->GetMemberName(), fArchive->GetArchiveName());
618  delete fArchive;
619  fArchive = 0;
620  fIsArchive = kFALSE;
621  goto zombie;
622  }
623  }
624 
625  Int_t nfree;
626  fBEGIN = (Long64_t)kBEGIN; //First used word in file following the file header
627 
628  // make newly opened file the current file and directory
629  cd();
630 
631  if (create) {
632  //*-*---------------NEW file
633  fFree = new TList;
634  fEND = fBEGIN; //Pointer to end of file
635  new TFree(fFree, fBEGIN, Long64_t(kStartBigFile)); //Create new free list
636 
637  //*-* Write Directory info
638  Int_t namelen= TNamed::Sizeof();
639  Int_t nbytes = namelen + TDirectoryFile::Sizeof();
640  TKey *key = new TKey(fName, fTitle, IsA(), nbytes, this);
641  fNbytesName = key->GetKeylen() + namelen;
642  fSeekDir = key->GetSeekKey();
643  fSeekFree = 0;
644  fNbytesFree = 0;
645  WriteHeader();
646  char *buffer = key->GetBuffer();
647  TNamed::FillBuffer(buffer);
649  key->WriteFile();
650  delete key;
651  } else {
652  //*-*----------------UPDATE
653  //char *header = new char[kBEGIN];
654  char *header = new char[kBEGIN+200];
655  Seek(0);
656  //ReadBuffer(header, kBEGIN);
657  if (ReadBuffer(header, kBEGIN+200)) {
658  // ReadBuffer returns kTRUE in case of failure.
659  Error("Init","%s failed to read the file type data.",
660  GetName());
661  delete [] header;
662  goto zombie;
663  }
664 
665  // make sure this is a ROOT file
666  if (strncmp(header, "root", 4)) {
667  Error("Init", "%s not a ROOT file", GetName());
668  delete [] header;
669  goto zombie;
670  }
671 
672  char *buffer = header + 4; // skip the "root" file identifier
673  frombuf(buffer, &fVersion);
674  Int_t headerLength;
675  frombuf(buffer, &headerLength);
676  fBEGIN = (Long64_t)headerLength;
677  if (fVersion < 1000000) { //small file
678  Int_t send,sfree,sinfo;
679  frombuf(buffer, &send); fEND = (Long64_t)send;
680  frombuf(buffer, &sfree); fSeekFree= (Long64_t)sfree;
681  frombuf(buffer, &fNbytesFree);
682  frombuf(buffer, &nfree);
683  frombuf(buffer, &fNbytesName);
684  frombuf(buffer, &fUnits );
685  frombuf(buffer, &fCompress);
686  frombuf(buffer, &sinfo); fSeekInfo = (Long64_t)sinfo;
687  frombuf(buffer, &fNbytesInfo);
688  } else { // new format to support large files
689  frombuf(buffer, &fEND);
690  frombuf(buffer, &fSeekFree);
691  frombuf(buffer, &fNbytesFree);
692  frombuf(buffer, &nfree);
693  frombuf(buffer, &fNbytesName);
694  frombuf(buffer, &fUnits );
695  frombuf(buffer, &fCompress);
696  frombuf(buffer, &fSeekInfo);
697  frombuf(buffer, &fNbytesInfo);
698  }
699  if (fBEGIN < 0 || fBEGIN > fEND) {
700  // humm fBEGIN is wrong ....
701  Error("Init","file %s has an incorrect header length (%lld) or incorrect end of file length (%lld)",
702  GetName(),fBEGIN,fEND);
703  goto zombie;
704  }
705  fSeekDir = fBEGIN;
706  //*-*-------------Read Free segments structure if file is writable
707  if (fWritable) {
708  fFree = new TList;
709  if (fSeekFree > fBEGIN) {
710  ReadFree();
711  } else {
712  Warning("Init","file %s probably not closed, cannot read free segments",GetName());
713  }
714  }
715  //*-*-------------Read directory info
716  // buffer_keyloc is the start of the key record.
717  char *buffer_keyloc = 0;
718 
719  Int_t nbytes = fNbytesName + TDirectoryFile::Sizeof();
720  if ( (nbytes + fBEGIN) > fEND) {
721  // humm fBEGIN is wrong ....
722  Error("Init","file %s has an incorrect header length (%lld) or incorrect end of file length (%lld)",
723  GetName(),fBEGIN+nbytes,fEND);
724  goto zombie;
725  }
726  if (nbytes+fBEGIN > kBEGIN+200) {
727  delete [] header;
728  header = new char[nbytes];
729  buffer = header;
730  Seek(fBEGIN);
731  if (ReadBuffer(buffer,nbytes)) {
732  // ReadBuffer returns kTRUE in case of failure.
733  Error("Init","%s failed to read the file header information at %lld (size=%d)",
734  GetName(),fBEGIN,nbytes);
735  delete [] header;
736  goto zombie;
737  }
738  buffer = header+fNbytesName;
739  buffer_keyloc = header;
740  } else {
741  buffer = header+fBEGIN+fNbytesName;
742  buffer_keyloc = header+fBEGIN;
743  }
744  Version_t version,versiondir;
745  frombuf(buffer,&version); versiondir = version%1000;
746  fDatimeC.ReadBuffer(buffer);
747  fDatimeM.ReadBuffer(buffer);
748  frombuf(buffer, &fNbytesKeys);
749  frombuf(buffer, &fNbytesName);
750  if (version > 1000) {
751  frombuf(buffer, &fSeekDir);
752  frombuf(buffer, &fSeekParent);
753  frombuf(buffer, &fSeekKeys);
754  } else {
755  Int_t sdir,sparent,skeys;
756  frombuf(buffer, &sdir); fSeekDir = (Long64_t)sdir;
757  frombuf(buffer, &sparent); fSeekParent = (Long64_t)sparent;
758  frombuf(buffer, &skeys); fSeekKeys = (Long64_t)skeys;
759  }
760  if (versiondir > 1) fUUID.ReadBuffer(buffer);
761 
762  //*-*---------read TKey::FillBuffer info
763  buffer_keyloc += sizeof(Int_t); // Skip NBytes;
764  Version_t keyversion;
765  frombuf(buffer_keyloc, &keyversion);
766  // Skip ObjLen, DateTime, KeyLen, Cycle, SeekKey, SeekPdir
767  if (keyversion > 1000) {
768  // Large files
769  buffer_keyloc += 2*sizeof(Int_t)+2*sizeof(Short_t)+2*sizeof(Long64_t);
770  } else {
771  buffer_keyloc += 2*sizeof(Int_t)+2*sizeof(Short_t)+2*sizeof(Int_t);
772  }
773  TString cname;
774  cname.ReadBuffer(buffer_keyloc);
775  cname.ReadBuffer(buffer_keyloc); // fName.ReadBuffer(buffer); file may have been renamed
776  fTitle.ReadBuffer(buffer_keyloc);
777  delete [] header;
778  if (fNbytesName < 10 || fNbytesName > 10000) {
779  Error("Init","cannot read directory info of file %s", GetName());
780  goto zombie;
781  }
782 
783  //*-* -------------Check if file is truncated
784  Long64_t size;
785  if ((size = GetSize()) == -1) {
786  Error("Init", "cannot stat the file %s", GetName());
787  goto zombie;
788  }
789 
790  //*-* -------------Check if, in case of inconsistencies, we are requested to
791  //*-* -------------attempt recovering the file
792  Bool_t tryrecover = (gEnv->GetValue("TFile.Recover", 1) == 1) ? kTRUE : kFALSE;
793 
794  //*-* -------------Read keys of the top directory
795  if (fSeekKeys > fBEGIN && fEND <= size) {
796  //normal case. Recover only if file has no keys
798  gDirectory = this;
799  if (!GetNkeys()) {
800  if (tryrecover) {
801  Recover();
802  } else {
803  Error("Init", "file %s has no keys", GetName());
804  goto zombie;
805  }
806  }
807  } else if ((fBEGIN+nbytes == fEND) && (fEND == size)) {
808  //the file might be open by another process and nothing written to the file yet
809  Warning("Init","file %s has no keys", GetName());
810  gDirectory = this;
811  } else {
812  //something had been written to the file. Trailer is missing, must recover
813  if (fEND > size) {
814  if (tryrecover) {
815  Error("Init","file %s is truncated at %lld bytes: should be %lld, "
816  "trying to recover", GetName(), size, fEND);
817  } else {
818  Error("Init","file %s is truncated at %lld bytes: should be %lld",
819  GetName(), size, fEND);
820  goto zombie;
821  }
822  } else {
823  if (tryrecover) {
824  Warning("Init","file %s probably not closed, "
825  "trying to recover", GetName());
826  } else {
827  Warning("Init","file %s probably not closed", GetName());
828  goto zombie;
829  }
830  }
831  Int_t nrecov = Recover();
832  if (nrecov) {
833  Warning("Init", "successfully recovered %d keys", nrecov);
834  } else {
835  Warning("Init", "no keys recovered, file has been made a Zombie");
836  goto zombie;
837  }
838  }
839  }
840 
841  {
843  gROOT->GetListOfFiles()->Add(this);
844  gROOT->GetUUIDs()->AddUUID(fUUID,this);
845  }
846 
847  // Create StreamerInfo index
848  {
849  Int_t lenIndex = gROOT->GetListOfStreamerInfo()->GetSize()+1;
850  if (lenIndex < 5000) lenIndex = 5000;
851  fClassIndex = new TArrayC(lenIndex);
852  if (fgReadInfo) {
853  if (fSeekInfo > fBEGIN) {
854  ReadStreamerInfo();
855  if (IsZombie()) {
857  gROOT->GetListOfFiles()->Remove(this);
858  goto zombie;
859  }
860  } else if (fVersion != gROOT->GetVersionInt() && fVersion > 30000) {
861  // Don't complain about missing streamer info for empty files.
862  if (fKeys->GetSize()) {
863  Warning("Init","no StreamerInfo found in %s therefore preventing schema evolution when reading this file.",GetName());
864  }
865  }
866  }
867  }
868 
869  // Count number of TProcessIDs in this file
870  {
871  TIter next(fKeys);
872  TKey *key;
873  while ((key = (TKey*)next())) {
874  if (!strcmp(key->GetClassName(),"TProcessID")) fNProcessIDs++;
875  }
876  fProcessIDs = new TObjArray(fNProcessIDs+1);
877  }
878  return;
879 
880 zombie:
881  {
883  gROOT->GetListOfClosedObjects()->Add(this);
884  }
885  // error in file opening occurred, make this object a zombie
886  fWritable = kFALSE;
887  MakeZombie();
888  gDirectory = gROOT;
889 }
890 
891 ////////////////////////////////////////////////////////////////////////////////
892 /// Close a file.
893 ///
894 /// \param[in] option If option == "R", all TProcessIDs referenced by this file are deleted.
895 ///
896 /// Calling TFile::Close("R") might be necessary in case one reads a long list
897 /// of files having TRef, writing some of the referenced objects or TRef
898 /// to a new file. If the TRef or referenced objects of the file being closed
899 /// will not be referenced again, it is possible to minimize the size
900 /// of the TProcessID data structures in memory by forcing a delete of
901 /// the unused TProcessID.
902 
903 void TFile::Close(Option_t *option)
904 {
905  TString opt = option;
906 
907  opt.ToLower();
908 
909  if (!IsOpen()) return;
910 
911  if (fIsArchive || !fIsRootFile) {
912  FlushWriteCache();
913  SysClose(fD);
914  fD = -1;
915 
916  if (gMonitoringWriter)
918 
919  return;
920  }
921 
922  if (IsWritable()) {
923  WriteStreamerInfo();
924  }
925 
926  // Finish any concurrent I/O operations before we close the file handles.
927  if (fCacheRead) fCacheRead->Close();
928  {
929  TIter iter(fCacheReadMap);
930  TObject *key = 0;
931  while ((key = iter()) != 0) {
932  TFileCacheRead *cache = dynamic_cast<TFileCacheRead *>(fCacheReadMap->GetValue(key));
933  cache->Close();
934  }
935  }
936 
937  // Delete all supported directories structures from memory
938  // If gDirectory points to this object or any of the nested
939  // TDirectoryFile, TDirectoryFile::Close will induce the proper cd.
940  fMustFlush = kFALSE; // Make sure there is only one Flush.
942 
943  if (IsWritable()) {
944  TFree *f1 = (TFree*)fFree->First();
945  if (f1) {
946  WriteFree(); //*-*- Write free segments linked list
947  WriteHeader(); //*-*- Now write file header ; this forces a Flush/fsync
948  } else {
949  Flush();
950  }
951  }
952  fMustFlush = kTRUE;
953 
954  FlushWriteCache();
955 
956  if (gMonitoringWriter)
958 
959  delete fClassIndex;
960  fClassIndex = 0;
961 
962  // Delete free segments from free list (but don't delete list header)
963  if (fFree) {
964  fFree->Delete();
965  }
966 
967  if (IsOpen()) {
968  SysClose(fD);
969  fD = -1;
970  }
971 
972  fWritable = kFALSE;
973 
974  // delete the TProcessIDs
975  TList pidDeleted;
976  TIter next(fProcessIDs);
977  TProcessID *pid;
978  while ((pid = (TProcessID*)next())) {
979  if (!pid->DecrementCount()) {
980  if (pid != TProcessID::GetSessionProcessID()) pidDeleted.Add(pid);
981  } else if(opt.Contains("r")) {
982  pid->Clear();
983  }
984  }
985  pidDeleted.Delete();
986 
987  if (!IsZombie()) {
989  gROOT->GetListOfFiles()->Remove(this);
990  gROOT->GetListOfBrowsers()->RecursiveRemove(this);
991  gROOT->GetListOfClosedObjects()->Add(this);
992  } else {
993  // If we are a zombie, we are already in the list of closed objects.
994  }
995 }
996 
997 ////////////////////////////////////////////////////////////////////////////////
998 /// Creates key for object and converts data to buffer.
999 
1000 TKey* TFile::CreateKey(TDirectory* mother, const TObject* obj, const char* name, Int_t bufsize)
1002  return new TKey(obj, name, bufsize, mother);
1003 }
1004 
1005 ////////////////////////////////////////////////////////////////////////////////
1006 /// Creates key for object and converts data to buffer.
1007 
1008 TKey* TFile::CreateKey(TDirectory* mother, const void* obj, const TClass* cl, const char* name, Int_t bufsize)
1010  return new TKey(obj, cl, name, bufsize, mother);
1011 }
1012 
1013 ////////////////////////////////////////////////////////////////////////////////
1014 /// Return the current ROOT file if any.
1015 ///
1016 /// Note that if 'cd' has been called on a TDirectory that does not belong to a file,
1017 /// gFile will be unchanged and still points to the file of the previous current
1018 /// directory that was a file.
1019 
1022  static TFile *currentFile = 0;
1023  if (!gThreadTsd)
1024  return currentFile;
1025  else
1026  return *(TFile**)(*gThreadTsd)(&currentFile,ROOT::kFileThreadSlot);
1027 }
1028 
1029 ////////////////////////////////////////////////////////////////////////////////
1030 /// Delete object namecycle.
1031 ///
1032 /// \param[in] namecycle Encodes the name and cycle of the objects to delete
1033 ///
1034 /// Namecycle identifies an object in the top directory of the file namecycle
1035 /// has the format <em>name;cycle</em>.
1036 /// - <em>name = *</em> means all objects
1037 /// - <em>cycle = *</em> means all cycles (memory and keys)
1038 /// - <em>cycle = ""</em> or cycle = 9999 ==> apply to a memory object
1039 /// When name=* use T* to delete subdirectories also
1040 ///
1041 /// Examples:
1042 /// name/cycle | Action
1043 /// -----------|-------
1044 /// foo | delete object named foo in memory
1045 /// foo;1 | delete cycle 1 of foo on file
1046 /// foo;* | delete all cycles of foo on disk and also from memory
1047 /// *;2 | delete all objects on file having the cycle 2
1048 /// *;* | delete all objects from memory and file
1049 /// T*;* | delete all objects from memory and file and all subdirectories
1050 
1051 void TFile::Delete(const char *namecycle)
1053  if (gDebug)
1054  Info("Delete", "deleting name = %s", namecycle);
1055 
1056  TDirectoryFile::Delete(namecycle);
1057 }
1058 
1059 ////////////////////////////////////////////////////////////////////////////////
1060 /// Fill Graphics Structure and Paint.
1061 ///
1062 /// Loop on all objects (memory or file) and all subdirectories.
1063 
1064 void TFile::Draw(Option_t *option)
1066  GetList()->R__FOR_EACH(TObject,Draw)(option);
1067 }
1068 
1069 ////////////////////////////////////////////////////////////////////////////////
1070 /// Draw map of objects in this file.
1071 
1072 void TFile::DrawMap(const char *keys, Option_t *option)
1074  TPluginHandler *h;
1075  if ((h = gROOT->GetPluginManager()->FindHandler("TFileDrawMap"))) {
1076  if (h->LoadPlugin() == -1)
1077  return;
1078  h->ExecPlugin(3, this, keys, option);
1079  }
1080 }
1081 
1082 ////////////////////////////////////////////////////////////////////////////////
1083 /// Synchronize a file's in-memory and on-disk states.
1084 
1085 void TFile::Flush()
1087  if (IsOpen() && fWritable) {
1088  FlushWriteCache();
1089  if (SysSync(fD) < 0) {
1090  // Write the system error only once for this file
1091  SetBit(kWriteError); SetWritable(kFALSE);
1092  SysError("Flush", "error flushing file %s", GetName());
1093  }
1094  }
1095 }
1096 
1097 ////////////////////////////////////////////////////////////////////////////////
1098 /// Flush the write cache if active.
1099 ///
1100 /// Return kTRUE in case of error
1101 
1104  if (fCacheWrite && IsOpen() && fWritable)
1105  return fCacheWrite->Flush();
1106  return kFALSE;
1107 }
1108 
1109 ////////////////////////////////////////////////////////////////////////////////
1110 /// Encode file output buffer.
1111 ///
1112 /// The file output buffer contains only the FREE data record.
1113 
1114 void TFile::FillBuffer(char *&buffer)
1116  Version_t version = TFile::Class_Version();
1117  tobuf(buffer, version);
1118 }
1119 
1120 ////////////////////////////////////////////////////////////////////////////////
1121 /// Return the best buffer size of objects on this file.
1122 ///
1123 /// The best buffer size is estimated based on the current mean value
1124 /// and standard deviation of all objects written so far to this file.
1125 /// Returns mean value + one standard deviation.
1126 
1129  if (!fWritten) return TBuffer::kInitialSize;
1130  Double_t mean = fSumBuffer/fWritten;
1131  Double_t rms2 = TMath::Abs(fSum2Buffer/fSumBuffer -mean*mean);
1132  return (Int_t)(mean + sqrt(rms2));
1133 }
1134 
1135 ////////////////////////////////////////////////////////////////////////////////
1136 /// Return the file compression factor.
1137 ///
1138 /// Add total number of compressed/uncompressed bytes for each key.
1139 /// Returns the ratio of the two.
1140 
1143  Short_t keylen;
1144  UInt_t datime;
1145  Int_t nbytes, objlen, nwh = 64;
1146  char *header = new char[fBEGIN];
1147  char *buffer;
1148  Long64_t idcur = fBEGIN;
1149  Float_t comp,uncomp;
1150  comp = uncomp = fBEGIN;
1151 
1152  while (idcur < fEND-100) {
1153  Seek(idcur);
1154  if (ReadBuffer(header, nwh)) {
1155  // ReadBuffer returns kTRUE in case of failure.
1156 // Error("GetCompressionFactor","%s failed to read the key header information at %lld (size=%d).",
1157 // GetName(),idcur,nwh);
1158  break;
1159  }
1160  buffer=header;
1161  frombuf(buffer, &nbytes);
1162  if (nbytes < 0) {
1163  idcur -= nbytes;
1164  Seek(idcur);
1165  continue;
1166  }
1167  if (nbytes == 0) break; //this may happen when the file is corrupted
1168  Version_t versionkey;
1169  frombuf(buffer, &versionkey);
1170  frombuf(buffer, &objlen);
1171  frombuf(buffer, &datime);
1172  frombuf(buffer, &keylen);
1173  if (!objlen) objlen = nbytes-keylen;
1174  comp += nbytes;
1175  uncomp += keylen + objlen;
1176  idcur += nbytes;
1177  }
1178  delete [] header;
1179  return uncomp/comp;
1180 }
1181 
1182 ////////////////////////////////////////////////////////////////////////////////
1183 /// Method returning errno. Is overriden in TRFIOFile.
1184 
1185 Int_t TFile::GetErrno() const
1187  return TSystem::GetErrno();
1188 }
1189 
1190 ////////////////////////////////////////////////////////////////////////////////
1191 /// Method resetting the errno. Is overridden in TRFIOFile.
1192 
1193 void TFile::ResetErrno() const
1196 }
1197 
1198 ////////////////////////////////////////////////////////////////////////////////
1199 /// Return a pointer to the current read cache.
1200 
1203  if (!tree) {
1204  if (!fCacheRead && fCacheReadMap->GetSize() == 1) {
1205  TIter next(fCacheReadMap);
1206  return (TFileCacheRead *)fCacheReadMap->GetValue(next());
1207  }
1208  return fCacheRead;
1209  }
1210  TFileCacheRead *cache = (TFileCacheRead *)fCacheReadMap->GetValue(tree);
1211  if (!cache) return fCacheRead;
1212  return cache;
1213 }
1214 
1215 ////////////////////////////////////////////////////////////////////////////////
1216 /// Return a pointer to the current write cache.
1217 
1220  return fCacheWrite;
1221 }
1222 
1223 ////////////////////////////////////////////////////////////////////////////////
1224 /// Read the logical record header starting at a certain postion.
1225 ///
1226 /// \param[in] maxbytes Bytes which are read into buf.
1227 /// \param[out] nbytes Number of bytes in record if negative, this is a deleted
1228 /// record if 0, cannot read record, wrong value of argument first
1229 /// \param[out] objlen Uncompressed object size
1230 /// \param[out] keylen Length of logical record header
1231 ///
1232 /// The function reads nread bytes
1233 /// where nread is the minimum of maxbytes and the number of bytes
1234 /// before the end of file. The function returns nread.
1235 /// Note that the arguments objlen and keylen are returned only
1236 /// if maxbytes >=16
1237 
1238 Int_t TFile::GetRecordHeader(char *buf, Long64_t first, Int_t maxbytes, Int_t &nbytes, Int_t &objlen, Int_t &keylen)
1240  nbytes = 0;
1241  objlen = 0;
1242  keylen = 0;
1243  if (first < fBEGIN) return 0;
1244  if (first > fEND) return 0;
1245  Seek(first);
1246  Int_t nread = maxbytes;
1247  if (first+maxbytes > fEND) nread = fEND-maxbytes;
1248  if (nread < 4) {
1249  Warning("GetRecordHeader","%s: parameter maxbytes = %d must be >= 4",
1250  GetName(), nread);
1251  return nread;
1252  }
1253  if (ReadBuffer(buf,nread)) {
1254  // ReadBuffer return kTRUE in case of failure.
1255  Warning("GetRecordHeader","%s: failed to read header data (maxbytes = %d)",
1256  GetName(), nread);
1257  return nread;
1258  }
1259  Version_t versionkey;
1260  Short_t klen;
1261  UInt_t datime;
1262  Int_t nb,olen;
1263  char *buffer = buf;
1264  frombuf(buffer,&nb);
1265  nbytes = nb;
1266  if (nb < 0) return nread;
1267  // const Int_t headerSize = Int_t(sizeof(nb) +sizeof(versionkey) +sizeof(olen) +sizeof(datime) +sizeof(klen));
1268  const Int_t headerSize = 16;
1269  if (nread < headerSize) return nread;
1270  frombuf(buffer, &versionkey);
1271  frombuf(buffer, &olen);
1272  frombuf(buffer, &datime);
1273  frombuf(buffer, &klen);
1274  if (!olen) olen = nbytes-klen;
1275  objlen = olen;
1276  keylen = klen;
1277  return nread;
1278 }
1279 
1280 ////////////////////////////////////////////////////////////////////////////////
1281 /// Returns the current file size. Returns -1 in case the file could not
1282 /// be stat'ed.
1283 
1284 Long64_t TFile::GetSize() const
1286  Long64_t size;
1287 
1288  if (fArchive && fArchive->GetMember()) {
1289  size = fArchive->GetMember()->GetDecompressedSize();
1290  } else {
1291  Long_t id, flags, modtime;
1292  if (const_cast<TFile*>(this)->SysStat(fD, &id, &size, &flags, &modtime)) {
1293  Error("GetSize", "cannot stat the file %s", GetName());
1294  return -1;
1295  }
1296  }
1297  return size;
1298 }
1299 
1300 ////////////////////////////////////////////////////////////////////////////////
1301 /// Returns the cached list of StreamerInfos used in this file.
1302 
1305  return fInfoCache ? fInfoCache : (fInfoCache=GetStreamerInfoList());
1306 }
1307 
1308 ////////////////////////////////////////////////////////////////////////////////
1309 /// Read the list of TStreamerInfo objects written to this file.
1310 ///
1311 /// The function returns a TList. It is the user's responsibility
1312 /// to delete the list created by this function.
1313 ///
1314 /// Note the list, in addition to TStreamerInfo object, contains sometimes
1315 /// a TList named 'listOfRules' and containing the schema evolution rules
1316 /// related to the file's content.
1317 ///
1318 /// Using the list, one can access additional information, e.g.:
1319 /// ~~~{.cpp}
1320 /// TFile f("myfile.root");
1321 /// auto list = f.GetStreamerInfoList();
1322 /// auto info = dynamic_cast<TStreamerInfo*>(list->FindObject("MyClass"));
1323 /// if (info) auto classversionid = info->GetClassVersion();
1324 /// delete list;
1325 /// ~~~
1326 ///
1327 
1330  if (fIsPcmFile) return 0; // No schema evolution for ROOT PCM files.
1331 
1332  TList *list = 0;
1333  if (fSeekInfo) {
1334  TDirectory::TContext ctxt(this); // gFile and gDirectory used in ReadObj
1335  TKey *key = new TKey(this);
1336  char *buffer = new char[fNbytesInfo+1];
1337  char *buf = buffer;
1338  Seek(fSeekInfo);
1339  if (ReadBuffer(buf,fNbytesInfo)) {
1340  // ReadBuffer returns kTRUE in case of failure.
1341  Warning("GetRecordHeader","%s: failed to read the StreamerInfo data from disk.",
1342  GetName());
1343  return 0;
1344  }
1345  key->ReadKeyBuffer(buf);
1346  list = dynamic_cast<TList*>(key->ReadObjWithBuffer(buffer));
1347  if (list) list->SetOwner();
1348  delete [] buffer;
1349  delete key;
1350  } else {
1351  list = (TList*)Get("StreamerInfo"); //for versions 2.26 (never released)
1352  }
1353 
1354  if (list == 0) {
1355  Info("GetStreamerInfoList", "cannot find the StreamerInfo record in file %s",
1356  GetName());
1357  return 0;
1358  }
1359 
1360  return list;
1361 }
1362 
1363 ////////////////////////////////////////////////////////////////////////////////
1364 /// List file contents.
1365 ///
1366 /// Indentation is used to identify the file tree.
1367 /// Subdirectories are listed first, then objects in memory,
1368 /// then objects on the file.
1369 
1370 void TFile::ls(Option_t *option) const
1373  std::cout <<ClassName()<<"**\t\t"<<GetName()<<"\t"<<GetTitle()<<std::endl;
1375  TDirectoryFile::ls(option);
1377 }
1378 
1379 ////////////////////////////////////////////////////////////////////////////////
1380 /// Returns kTRUE in case file is open and kFALSE if file is not open.
1381 
1382 Bool_t TFile::IsOpen() const
1384  return fD == -1 ? kFALSE : kTRUE;
1385 }
1386 
1387 ////////////////////////////////////////////////////////////////////////////////
1388 /// Mark unused bytes on the file.
1389 ///
1390 /// The list of free segments is in the fFree linked list.
1391 /// When an object is deleted from the file, the freed space is added
1392 /// into the FREE linked list (fFree). The FREE list consists of a chain
1393 /// of consecutive free segments on the file. At the same time, the first
1394 /// 4 bytes of the freed record on the file are overwritten by GAPSIZE
1395 /// where GAPSIZE = -(Number of bytes occupied by the record).
1396 
1399  TFree *f1 = (TFree*)fFree->First();
1400  if (!f1) return;
1401  TFree *newfree = f1->AddFree(fFree,first,last);
1402  if(!newfree) return;
1403  Long64_t nfirst = newfree->GetFirst();
1404  Long64_t nlast = newfree->GetLast();
1405  Long64_t nbytesl= nlast-nfirst+1;
1406  if (nbytesl > 2000000000) nbytesl = 2000000000;
1407  Int_t nbytes = -Int_t (nbytesl);
1408  Int_t nb = sizeof(Int_t);
1409  char * buffer = new char[nb];
1410  char * psave = buffer;
1411  tobuf(buffer, nbytes);
1412  if (last == fEND-1) fEND = nfirst;
1413  Seek(nfirst);
1414  // We could not update the meta data for this block on the file.
1415  // This is not fatal as this only means that we won't get it 'right'
1416  // if we ever need to Recover the file before the block is actually
1417  // (attempted to be reused.
1418  // coverity[unchecked_value]
1419  WriteBuffer(psave, nb);
1420  if (fMustFlush) Flush();
1421  delete [] psave;
1422 }
1423 
1424 ////////////////////////////////////////////////////////////////////////////////
1425 /// List the contents of a file sequentially.
1426 /// For each logical record found, it prints:
1427 ///
1428 /// Date/Time Record_Adress Logical_Record_Length ClassName CompressionFactor
1429 ///
1430 /// Example of output
1431 ///
1432 /// 20010404/150437 At:64 N=150 TFile
1433 /// 20010404/150440 At:214 N=28326 TBasket CX = 1.13
1434 /// 20010404/150440 At:28540 N=29616 TBasket CX = 1.08
1435 /// 20010404/150440 At:58156 N=29640 TBasket CX = 1.08
1436 /// 20010404/150440 At:87796 N=29076 TBasket CX = 1.10
1437 /// 20010404/150440 At:116872 N=10151 TBasket CX = 3.15
1438 /// 20010404/150441 At:127023 N=28341 TBasket CX = 1.13
1439 /// 20010404/150441 At:155364 N=29594 TBasket CX = 1.08
1440 /// 20010404/150441 At:184958 N=29616 TBasket CX = 1.08
1441 /// 20010404/150441 At:214574 N=29075 TBasket CX = 1.10
1442 /// 20010404/150441 At:243649 N=9583 TBasket CX = 3.34
1443 /// 20010404/150442 At:253232 N=28324 TBasket CX = 1.13
1444 /// 20010404/150442 At:281556 N=29641 TBasket CX = 1.08
1445 /// 20010404/150442 At:311197 N=29633 TBasket CX = 1.08
1446 /// 20010404/150442 At:340830 N=29091 TBasket CX = 1.10
1447 /// 20010404/150442 At:369921 N=10341 TBasket CX = 3.09
1448 /// 20010404/150442 At:380262 N=509 TH1F CX = 1.93
1449 /// 20010404/150442 At:380771 N=1769 TH2F CX = 4.32
1450 /// 20010404/150442 At:382540 N=1849 TProfile CX = 1.65
1451 /// 20010404/150442 At:384389 N=18434 TNtuple CX = 4.51
1452 /// 20010404/150442 At:402823 N=307 KeysList
1453 /// 20010404/150443 At:403130 N=4548 StreamerInfo CX = 3.65
1454 /// 20010404/150443 At:407678 N=86 FreeSegments
1455 /// 20010404/150443 At:407764 N=1 END
1456 
1457 void TFile::Map()
1459  Short_t keylen,cycle;
1460  UInt_t datime;
1461  Int_t nbytes,date,time,objlen,nwheader;
1462  date = 0;
1463  time = 0;
1464  Long64_t seekkey,seekpdir;
1465  char *buffer;
1466  char nwhc;
1467  Long64_t idcur = fBEGIN;
1468 
1469  nwheader = 64;
1470  Int_t nread = nwheader;
1471 
1472  char header[kBEGIN];
1473  char classname[512];
1474 
1475  while (idcur < fEND) {
1476  Seek(idcur);
1477  if (idcur+nread >= fEND) nread = fEND-idcur-1;
1478  if (ReadBuffer(header, nread)) {
1479  // ReadBuffer returns kTRUE in case of failure.
1480  Warning("Map","%s: failed to read the key data from disk at %lld.",
1481  GetName(),idcur);
1482  break;
1483  }
1484 
1485  buffer=header;
1486  frombuf(buffer, &nbytes);
1487  if (!nbytes) {
1488  Printf("Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes);
1489  date = 0; time = 0;
1490  break;
1491  }
1492  if (nbytes < 0) {
1493  Printf("Address = %lld\tNbytes = %d\t=====G A P===========", idcur, nbytes);
1494  idcur -= nbytes;
1495  Seek(idcur);
1496  continue;
1497  }
1498  Version_t versionkey;
1499  frombuf(buffer, &versionkey);
1500  frombuf(buffer, &objlen);
1501  frombuf(buffer, &datime);
1502  frombuf(buffer, &keylen);
1503  frombuf(buffer, &cycle);
1504  if (versionkey > 1000) {
1505  frombuf(buffer, &seekkey);
1506  frombuf(buffer, &seekpdir);
1507  } else {
1508  Int_t skey,sdir;
1509  frombuf(buffer, &skey); seekkey = (Long64_t)skey;
1510  frombuf(buffer, &sdir); seekpdir = (Long64_t)sdir;
1511  }
1512  frombuf(buffer, &nwhc);
1513  for (int i = 0;i < nwhc; i++) frombuf(buffer, &classname[i]);
1514  classname[(int)nwhc] = '\0'; //cast to avoid warning with gcc3.4
1515  if (idcur == fSeekFree) strlcpy(classname,"FreeSegments",512);
1516  if (idcur == fSeekInfo) strlcpy(classname,"StreamerInfo",512);
1517  if (idcur == fSeekKeys) strlcpy(classname,"KeysList",512);
1518  TDatime::GetDateTime(datime, date, time);
1519  if (objlen != nbytes-keylen) {
1520  Float_t cx = Float_t(objlen+keylen)/Float_t(nbytes);
1521  Printf("%d/%06d At:%lld N=%-8d %-14s CX = %5.2f",date,time,idcur,nbytes,classname,cx);
1522  } else {
1523  Printf("%d/%06d At:%lld N=%-8d %-14s",date,time,idcur,nbytes,classname);
1524  }
1525  idcur += nbytes;
1526  }
1527  Printf("%d/%06d At:%lld N=%-8d %-14s",date,time,idcur,1,"END");
1528 }
1529 
1530 ////////////////////////////////////////////////////////////////////////////////
1531 /// Paint all objects in the file.
1532 
1533 void TFile::Paint(Option_t *option)
1535  GetList()->R__FOR_EACH(TObject,Paint)(option);
1536 }
1537 
1538 ////////////////////////////////////////////////////////////////////////////////
1539 /// Print all objects in the file.
1540 
1541 void TFile::Print(Option_t *option) const
1543  Printf("TFile: name=%s, title=%s, option=%s", GetName(), GetTitle(), GetOption());
1544  GetList()->R__FOR_EACH(TObject,Print)(option);
1545 }
1546 
1547 ////////////////////////////////////////////////////////////////////////////////
1548 /// Read a buffer from the file at the offset 'pos' in the file.
1549 ///
1550 /// Returns kTRUE in case of failure.
1551 /// Compared to ReadBuffer(char*, Int_t), this routine does _not_
1552 /// change the cursor on the physical file representation (fD)
1553 /// if the data is in this TFile's cache.
1554 
1555 Bool_t TFile::ReadBuffer(char *buf, Long64_t pos, Int_t len)
1557  if (IsOpen()) {
1558 
1559  SetOffset(pos);
1560 
1561  Int_t st;
1562  Double_t start = 0;
1563  if (gPerfStats != 0) start = TTimeStamp();
1564 
1565  if ((st = ReadBufferViaCache(buf, len))) {
1566  if (st == 2)
1567  return kTRUE;
1568  return kFALSE;
1569  }
1570 
1571  Seek(pos);
1572  ssize_t siz;
1573 
1574  while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
1575  ResetErrno();
1576 
1577  if (siz < 0) {
1578  SysError("ReadBuffer", "error reading from file %s", GetName());
1579  return kTRUE;
1580  }
1581  if (siz != len) {
1582  Error("ReadBuffer", "error reading all requested bytes from file %s, got %ld of %d",
1583  GetName(), (Long_t)siz, len);
1584  return kTRUE;
1585  }
1586  fBytesRead += siz;
1587  fgBytesRead += siz;
1588  fReadCalls++;
1589  fgReadCalls++;
1590 
1591  if (gMonitoringWriter)
1593  if (gPerfStats != 0) {
1594  gPerfStats->FileReadEvent(this, len, start);
1595  }
1596  return kFALSE;
1597  }
1598  return kTRUE;
1599 }
1600 
1601 ////////////////////////////////////////////////////////////////////////////////
1602 /// Read a buffer from the file. This is the basic low level read operation.
1603 /// Returns kTRUE in case of failure.
1604 
1605 Bool_t TFile::ReadBuffer(char *buf, Int_t len)
1607  if (IsOpen()) {
1608 
1609  Int_t st;
1610  if ((st = ReadBufferViaCache(buf, len))) {
1611  if (st == 2)
1612  return kTRUE;
1613  return kFALSE;
1614  }
1615 
1616  ssize_t siz;
1617  Double_t start = 0;
1618 
1619  if (gPerfStats != 0) start = TTimeStamp();
1620 
1621  while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
1622  ResetErrno();
1623 
1624  if (siz < 0) {
1625  SysError("ReadBuffer", "error reading from file %s", GetName());
1626  return kTRUE;
1627  }
1628  if (siz != len) {
1629  Error("ReadBuffer", "error reading all requested bytes from file %s, got %ld of %d",
1630  GetName(), (Long_t)siz, len);
1631  return kTRUE;
1632  }
1633  fBytesRead += siz;
1634  fgBytesRead += siz;
1635  fReadCalls++;
1636  fgReadCalls++;
1637 
1638  if (gMonitoringWriter)
1640  if (gPerfStats != 0) {
1641  gPerfStats->FileReadEvent(this, len, start);
1642  }
1643  return kFALSE;
1644  }
1645  return kTRUE;
1646 }
1647 
1648 ////////////////////////////////////////////////////////////////////////////////
1649 /// Read the nbuf blocks described in arrays pos and len.
1650 ///
1651 /// The value pos[i] is the seek position of block i of length len[i].
1652 /// Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer.
1653 /// This function is overloaded by TNetFile, TWebFile, etc.
1654 /// Returns kTRUE in case of failure.
1655 
1656 Bool_t TFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
1658  // called with buf=0, from TFileCacheRead to pass list of readahead buffers
1659  if (!buf) {
1660  for (Int_t j = 0; j < nbuf; j++) {
1661  if (ReadBufferAsync(pos[j], len[j])) {
1662  return kTRUE;
1663  }
1664  }
1665  return kFALSE;
1666  }
1667 
1668  Int_t k = 0;
1669  Bool_t result = kTRUE;
1670  TFileCacheRead *old = fCacheRead;
1671  fCacheRead = 0;
1672  Long64_t curbegin = pos[0];
1673  Long64_t cur;
1674  char *buf2 = 0;
1675  Int_t i = 0, n = 0;
1676  while (i < nbuf) {
1677  cur = pos[i]+len[i];
1678  Bool_t bigRead = kTRUE;
1679  if (cur -curbegin < fgReadaheadSize) {n++; i++; bigRead = kFALSE;}
1680  if (bigRead || (i>=nbuf)) {
1681  if (n == 0) {
1682  //if the block to read is about the same size as the read-ahead buffer
1683  //we read the block directly
1684  Seek(pos[i]);
1685  result = ReadBuffer(&buf[k], len[i]);
1686  if (result) break;
1687  k += len[i];
1688  i++;
1689  } else {
1690  //otherwise we read all blocks that fit in the read-ahead buffer
1691  Seek(curbegin);
1692  if (buf2 == 0) buf2 = new char[fgReadaheadSize];
1693  //we read ahead
1694  Long64_t nahead = pos[i-1]+len[i-1]-curbegin;
1695  result = ReadBuffer(buf2, nahead);
1696  if (result) break;
1697  //now copy from the read-ahead buffer to the cache
1698  Int_t kold = k;
1699  for (Int_t j=0;j<n;j++) {
1700  memcpy(&buf[k],&buf2[pos[i-n+j]-curbegin],len[i-n+j]);
1701  k += len[i-n+j];
1702  }
1703  Int_t nok = k-kold;
1704  Long64_t extra = nahead-nok;
1705  fBytesReadExtra += extra;
1706  fBytesRead -= extra;
1707  fgBytesRead -= extra;
1708  n = 0;
1709  }
1710  curbegin = pos[i];
1711  }
1712  }
1713  if (buf2) delete [] buf2;
1714  fCacheRead = old;
1715  return result;
1716 }
1717 
1718 ////////////////////////////////////////////////////////////////////////////////
1719 /// Read buffer via cache.
1720 ///
1721 /// Returns 0 if the requested block is not in the cache, 1 in case read via
1722 /// cache was successful, 2 in case read via cache failed.
1723 
1724 Int_t TFile::ReadBufferViaCache(char *buf, Int_t len)
1726  Long64_t off = GetRelOffset();
1727  if (fCacheRead) {
1728  Int_t st = fCacheRead->ReadBuffer(buf, off, len);
1729  if (st < 0)
1730  return 2; // failure reading
1731  else if (st == 1) {
1732  // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
1733  SetOffset(off + len);
1734  return 1;
1735  }
1736  // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
1737  Seek(off);
1738  } else {
1739  // if write cache is active check if data still in write cache
1740  if (fWritable && fCacheWrite) {
1741  if (fCacheWrite->ReadBuffer(buf, off, len) == 0) {
1742  SetOffset(off + len);
1743  return 1;
1744  }
1745  // fOffset might have been changed via TFileCacheWrite::ReadBuffer(), reset it
1746  SetOffset(off);
1747  }
1748  }
1749 
1750  return 0;
1751 }
1752 
1753 ////////////////////////////////////////////////////////////////////////////////
1754 /// Read the FREE linked list.
1755 ///
1756 /// Every file has a linked list (fFree) of free segments.
1757 /// This linked list has been written on the file via WriteFree
1758 /// as a single data record.
1759 
1760 void TFile::ReadFree()
1762  // Avoid problem with file corruption.
1763  if (fNbytesFree < 0 || fNbytesFree > fEND) {
1764  fNbytesFree = 0;
1765  return;
1766  }
1767  TKey *headerfree = new TKey(fSeekFree, fNbytesFree, this);
1768  headerfree->ReadFile();
1769  char *buffer = headerfree->GetBuffer();
1770  headerfree->ReadKeyBuffer(buffer);
1771  buffer = headerfree->GetBuffer();
1772  while (1) {
1773  TFree *afree = new TFree();
1774  afree->ReadBuffer(buffer);
1775  fFree->Add(afree);
1776  if (afree->GetLast() > fEND) break;
1777  }
1778  delete headerfree;
1779 }
1780 
1781 ////////////////////////////////////////////////////////////////////////////////
1782 /// The TProcessID with number pidf is read from this file.
1783 ///
1784 /// If the object is not already entered in the gROOT list, it is added.
1785 
1788  TProcessID *pid = 0;
1789  TObjArray *pids = GetListOfProcessIDs();
1790  if (pidf < pids->GetSize()) pid = (TProcessID *)pids->UncheckedAt(pidf);
1791  if (pid) {
1792  pid->CheckInit();
1793  return pid;
1794  }
1795 
1796  //check if fProcessIDs[uid] is set in file
1797  //if not set, read the process uid from file
1798  char pidname[32];
1799  snprintf(pidname,32,"ProcessID%d",pidf);
1800  pid = (TProcessID *)Get(pidname);
1801  if (gDebug > 0) {
1802  printf("ReadProcessID, name=%s, file=%s, pid=%lx\n",pidname,GetName(),(Long_t)pid);
1803  }
1804  if (!pid) {
1805  //file->Error("ReadProcessID","Cannot find %s in file %s",pidname,file->GetName());
1806  return pid;
1807  }
1808 
1809  //check that a similar pid is not already registered in fgPIDs
1810  TObjArray *pidslist = TProcessID::GetPIDs();
1811  TIter next(pidslist);
1812  TProcessID *p;
1813  bool found = false;
1814  R__RWLOCK_ACQUIRE_READ(fgRwLock);
1815  while ((p = (TProcessID*)next())) {
1816  if (!strcmp(p->GetTitle(),pid->GetTitle())) {
1817  found = true;
1818  break;
1819  }
1820  }
1821  R__RWLOCK_RELEASE_READ(fgRwLock);
1822 
1823  if (found) {
1824  delete pid;
1825  pids->AddAtAndExpand(p,pidf);
1826  p->IncrementCount();
1827  return p;
1828  }
1829 
1830  pids->AddAtAndExpand(pid,pidf);
1831  pid->IncrementCount();
1832 
1833  R__RWLOCK_ACQUIRE_WRITE(fgRwLock);
1834  pidslist->Add(pid);
1835  Int_t ind = pidslist->IndexOf(pid);
1836  pid->SetUniqueID((UInt_t)ind);
1837  R__RWLOCK_RELEASE_WRITE(fgRwLock);
1838 
1839  return pid;
1840 }
1841 
1842 
1843 ////////////////////////////////////////////////////////////////////////////////
1844 /// Attempt to recover file if not correctly closed
1845 ///
1846 /// The function returns the number of keys that have been recovered.
1847 /// If no keys can be recovered, the file will be declared Zombie by
1848 /// the calling function. This function is automatically called when
1849 /// opening a file.
1850 /// If the file is open in read only mode, the file is not modified.
1851 /// If open in update mode and the function finds something to recover,
1852 /// a new directory header is written to the file. When opening the file gain
1853 /// no message from Recover will be reported.
1854 /// If keys have been recovered, the file is usable and you can safely
1855 /// read the corresponding objects.
1856 /// If the file is not usable (a zombie), you can test for this case
1857 /// with code like:
1858 ///
1859 /// ~~~{.cpp}
1860 /// TFile f("myfile.root");
1861 /// if (f.IsZombie()) {<actions to take if file is unusable>}
1862 /// ~~~
1863 ///
1864 /// If the file has been recovered, the bit kRecovered is set in the TFile object in memory.
1865 /// You can test if the file has been recovered with
1866 ///
1867 /// if (f.TestBit(TFile::kRecovered)) {... the file has been recovered}
1868 ///
1869 /// When writing TTrees to a file, it is important to save the Tree header
1870 /// at regular intervals (see TTree::AutoSave). If a file containing a Tree
1871 /// is recovered, the last Tree header written to the file will be used.
1872 /// In this case all the entries in all the branches written before writing
1873 /// the header are valid entries.
1874 /// One can disable the automatic recovery procedure by setting
1875 ///
1876 /// TFile.Recover 0
1877 ///
1878 /// in the <em>system.rootrc</em> file.
1879 
1882  Short_t keylen,cycle;
1883  UInt_t datime;
1884  Int_t nbytes,date,time,objlen,nwheader;
1885  Long64_t seekkey,seekpdir;
1886  char header[1024];
1887  char *buffer, *bufread;
1888  char nwhc;
1889  Long64_t idcur = fBEGIN;
1890 
1891  Long64_t size;
1892  if ((size = GetSize()) == -1) {
1893  Error("Recover", "cannot stat the file %s", GetName());
1894  return 0;
1895  }
1896 
1897  fEND = Long64_t(size);
1898 
1899  if (fWritable && !fFree) fFree = new TList;
1900 
1901  TKey *key;
1902  Int_t nrecov = 0;
1903  nwheader = 1024;
1904  Int_t nread = nwheader;
1905 
1906  while (idcur < fEND) {
1907  Seek(idcur);
1908  if (idcur+nread >= fEND) nread = fEND-idcur-1;
1909  if (ReadBuffer(header, nread)) {
1910  // ReadBuffer returns kTRUE in case of failure.
1911  Error("Recover","%s: failed to read the key data from disk at %lld.",
1912  GetName(),idcur);
1913  break;
1914  }
1915  buffer = header;
1916  bufread = header;
1917  frombuf(buffer, &nbytes);
1918  if (!nbytes) {
1919  Error("Recover","Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes);
1920  break;
1921  }
1922  if (nbytes < 0) {
1923  idcur -= nbytes;
1924  if (fWritable) new TFree(fFree,idcur,idcur-nbytes-1);
1925  Seek(idcur);
1926  continue;
1927  }
1928  Version_t versionkey;
1929  frombuf(buffer, &versionkey);
1930  frombuf(buffer, &objlen);
1931  frombuf(buffer, &datime);
1932  frombuf(buffer, &keylen);
1933  frombuf(buffer, &cycle);
1934  if (versionkey > 1000) {
1935  frombuf(buffer, &seekkey);
1936  frombuf(buffer, &seekpdir);
1937  } else {
1938  Int_t skey,sdir;
1939  frombuf(buffer, &skey); seekkey = (Long64_t)skey;
1940  frombuf(buffer, &sdir); seekpdir = (Long64_t)sdir;
1941  }
1942  frombuf(buffer, &nwhc);
1943  char *classname = 0;
1944  if (nwhc <= 0 || nwhc > 100) break;
1945  classname = new char[nwhc+1];
1946  int i, nwhci = nwhc;
1947  for (i = 0;i < nwhc; i++) frombuf(buffer, &classname[i]);
1948  classname[nwhci] = '\0';
1949  TDatime::GetDateTime(datime, date, time);
1950  TClass *tclass = TClass::GetClass(classname);
1951  if (seekpdir == fSeekDir && tclass && !tclass->InheritsFrom(TFile::Class())
1952  && strcmp(classname,"TBasket")) {
1953  key = new TKey(this);
1954  key->ReadKeyBuffer(bufread);
1955  if (!strcmp(key->GetName(),"StreamerInfo")) {
1956  fSeekInfo = seekkey;
1957  SafeDelete(fInfoCache);
1958  fNbytesInfo = nbytes;
1959  } else {
1960  AppendKey(key);
1961  nrecov++;
1962  SetBit(kRecovered);
1963  Info("Recover", "%s, recovered key %s:%s at address %lld",GetName(),key->GetClassName(),key->GetName(),idcur);
1964  }
1965  }
1966  delete [] classname;
1967  idcur += nbytes;
1968  }
1969  if (fWritable) {
1970  Long64_t max_file_size = Long64_t(kStartBigFile);
1971  if (max_file_size < fEND) max_file_size = fEND+1000000000;
1972  TFree *last = (TFree*)fFree->Last();
1973  if (last) {
1974  last->AddFree(fFree,fEND,max_file_size);
1975  } else {
1976  new TFree(fFree,fEND,max_file_size);
1977  }
1978  if (nrecov) Write();
1979  }
1980  return nrecov;
1981 }
1982 
1983 ////////////////////////////////////////////////////////////////////////////////
1984 /// Reopen a file with a different access mode.
1985 ///
1986 /// For example, it is possible to change from READ to
1987 /// UPDATE or from NEW, CREATE, RECREATE, UPDATE to READ. Thus the
1988 /// mode argument can be either "READ" or "UPDATE". The method returns
1989 /// 0 in case the mode was successfully modified, 1 in case the mode
1990 /// did not change (was already as requested or wrong input arguments)
1991 /// and -1 in case of failure, in which case the file cannot be used
1992 /// anymore. The current directory (gFile) is changed to this file.
1993 
1996  cd();
1997 
1998  TString opt = mode;
1999  opt.ToUpper();
2000 
2001  if (opt != "READ" && opt != "UPDATE") {
2002  Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data());
2003  return 1;
2004  }
2005 
2006  if (opt == fOption || (opt == "UPDATE" && fOption == "CREATE"))
2007  return 1;
2008 
2009  if (opt == "READ") {
2010  // switch to READ mode
2011 
2012  // flush data still in the pipeline and close the file
2013  if (IsOpen() && IsWritable()) {
2014  WriteStreamerInfo();
2015 
2016  // save directory key list and header
2017  Save();
2018 
2019  TFree *f1 = (TFree*)fFree->First();
2020  if (f1) {
2021  WriteFree(); // write free segments linked list
2022  WriteHeader(); // now write file header
2023  }
2024 
2025  FlushWriteCache();
2026 
2027  // delete free segments from free list
2028  if (fFree) {
2029  fFree->Delete();
2030  SafeDelete(fFree);
2031  }
2032 
2033  SysClose(fD);
2034  fD = -1;
2035 
2036  SetWritable(kFALSE);
2037  }
2038 
2039  // open in READ mode
2040  fOption = opt; // set fOption before SysOpen() for TNetFile
2041 #ifndef WIN32
2042  fD = SysOpen(fRealName, O_RDONLY, 0644);
2043 #else
2044  fD = SysOpen(fRealName, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
2045 #endif
2046  if (fD == -1) {
2047  SysError("ReOpen", "file %s can not be opened in read mode", GetName());
2048  return -1;
2049  }
2050  SetWritable(kFALSE);
2051 
2052  } else {
2053  // switch to UPDATE mode
2054 
2055  // close readonly file
2056  if (IsOpen()) {
2057  SysClose(fD);
2058  fD = -1;
2059  }
2060 
2061  // open in UPDATE mode
2062  fOption = opt; // set fOption before SysOpen() for TNetFile
2063 #ifndef WIN32
2064  fD = SysOpen(fRealName, O_RDWR | O_CREAT, 0644);
2065 #else
2066  fD = SysOpen(fRealName, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
2067 #endif
2068  if (fD == -1) {
2069  SysError("ReOpen", "file %s can not be opened in update mode", GetName());
2070  return -1;
2071  }
2072  SetWritable(kTRUE);
2073 
2074  fFree = new TList;
2075  if (fSeekFree > fBEGIN)
2076  ReadFree();
2077  else
2078  Warning("ReOpen","file %s probably not closed, cannot read free segments", GetName());
2079  }
2080 
2081  return 0;
2082 }
2083 
2084 ////////////////////////////////////////////////////////////////////////////////
2085 /// Set position from where to start reading.
2086 
2087 void TFile::SetOffset(Long64_t offset, ERelativeTo pos)
2089  switch (pos) {
2090  case kBeg:
2091  fOffset = offset + fArchiveOffset;
2092  break;
2093  case kCur:
2094  fOffset += offset;
2095  break;
2096  case kEnd:
2097  // this option is not used currently in the ROOT code
2098  if (fArchiveOffset)
2099  Error("SetOffset", "seeking from end in archive is not (yet) supported");
2100  fOffset = fEND + offset; // is fEND really EOF or logical EOF?
2101  break;
2102  }
2103 }
2104 
2105 ////////////////////////////////////////////////////////////////////////////////
2106 /// Seek to a specific position in the file. Pos it either kBeg, kCur or kEnd.
2107 
2108 void TFile::Seek(Long64_t offset, ERelativeTo pos)
2110  int whence = 0;
2111  switch (pos) {
2112  case kBeg:
2113  whence = SEEK_SET;
2114  offset += fArchiveOffset;
2115  break;
2116  case kCur:
2117  whence = SEEK_CUR;
2118  break;
2119  case kEnd:
2120  whence = SEEK_END;
2121  // this option is not used currently in the ROOT code
2122  if (fArchiveOffset)
2123  Error("Seek", "seeking from end in archive is not (yet) supported");
2124  break;
2125  }
2126  Long64_t retpos;
2127  if ((retpos = SysSeek(fD, offset, whence)) < 0)
2128  SysError("Seek", "cannot seek to position %lld in file %s, retpos=%lld",
2129  offset, GetName(), retpos);
2130 
2131  // used by TFileCacheRead::ReadBuffer()
2132  fOffset = retpos;
2133 }
2134 
2135 ////////////////////////////////////////////////////////////////////////////////
2136 /// See comments for function SetCompressionSettings
2137 ///
2138 
2139 void TFile::SetCompressionAlgorithm(Int_t algorithm)
2141  if (algorithm < 0 || algorithm >= ROOT::kUndefinedCompressionAlgorithm) algorithm = 0;
2142  if (fCompress < 0) {
2143  // if the level is not defined yet use 1 as a default
2144  fCompress = 100 * algorithm + 1;
2145  } else {
2146  int level = fCompress % 100;
2147  fCompress = 100 * algorithm + level;
2148  }
2149 }
2150 
2151 ////////////////////////////////////////////////////////////////////////////////
2152 /// See comments for function SetCompressionSettings
2153 
2156  if (level < 0) level = 0;
2157  if (level > 99) level = 99;
2158  if (fCompress < 0) {
2159  // if the algorithm is not defined yet use 0 as a default
2160  fCompress = level;
2161  } else {
2162  int algorithm = fCompress / 100;
2163  if (algorithm >= ROOT::kUndefinedCompressionAlgorithm) algorithm = 0;
2164  fCompress = 100 * algorithm + level;
2165  }
2166 }
2167 
2168 ////////////////////////////////////////////////////////////////////////////////
2169 /// Used to specify the compression level and algorithm.
2170 ///
2171 /// See the TFile constructor for the details.
2172 
2173 void TFile::SetCompressionSettings(Int_t settings)
2175  fCompress = settings;
2176 }
2177 
2178 ////////////////////////////////////////////////////////////////////////////////
2179 /// Set a pointer to the read cache.
2180 ///
2181 /// <b>This relinquishes ownership</b> of the previous cache, so if you do not
2182 /// already have a pointer to the previous cache (and there was a previous
2183 /// cache), you ought to retrieve (and delete it if needed) using:
2184 ///
2185 /// TFileCacheRead *older = myfile->GetCacheRead();
2186 ///
2187 /// The action specifies how to behave when detaching a cache from the
2188 /// the TFile. If set to (default) kDisconnect, the contents of the cache
2189 /// will be flushed when it is removed from the file, and it will disconnect
2190 /// the cache object from the file. In almost all cases, this is what you want.
2191 /// If you want to disconnect the cache temporarily from this tree and re-attach
2192 /// later to the same fil, you can set action to kDoNotDisconnect. This will allow
2193 /// things like prefetching to continue in the background while it is no longer the
2194 /// default cache for the TTree. Except for a few expert use cases, kDisconnect is
2195 /// likely the correct setting.
2196 ///
2197 /// WARNING: if action=kDoNotDisconnect, you MUST delete the cache before TFile.
2198 ///
2199 
2200 void TFile::SetCacheRead(TFileCacheRead *cache, TObject* tree, ECacheAction action)
2202  if (tree) {
2203  if (cache) fCacheReadMap->Add(tree, cache);
2204  else {
2205  // The only addition to fCacheReadMap is via an interface that takes
2206  // a TFileCacheRead* so the C-cast is safe.
2207  TFileCacheRead* tpf = (TFileCacheRead *)fCacheReadMap->GetValue(tree);
2208  fCacheReadMap->Remove(tree);
2209  if (tpf && (tpf->GetFile() == this) && (action != kDoNotDisconnect)) tpf->SetFile(0, action);
2210  }
2211  }
2212  if (cache) cache->SetFile(this, action);
2213  else if (!tree && fCacheRead && (action != kDoNotDisconnect)) fCacheRead->SetFile(0, action);
2214  // For backward compatibility the last Cache set is the default cache.
2215  fCacheRead = cache;
2216 }
2217 
2218 ////////////////////////////////////////////////////////////////////////////////
2219 /// Set a pointer to the write cache.
2220 ///
2221 /// If file is null the existing write cache is deleted.
2222 
2225  if (!cache && fCacheWrite) delete fCacheWrite;
2226  fCacheWrite = cache;
2227 }
2228 
2229 ////////////////////////////////////////////////////////////////////////////////
2230 /// Return the size in bytes of the file header.
2231 
2232 Int_t TFile::Sizeof() const
2234  return 0;
2235 }
2236 
2237 ////////////////////////////////////////////////////////////////////////////////
2238 /// Stream a TFile object.
2239 
2240 void TFile::Streamer(TBuffer &b)
2241 {
2242  if (b.IsReading()) {
2243  b.ReadVersion(); //Version_t v = b.ReadVersion();
2244  } else {
2245  b.WriteVersion(TFile::IsA());
2246  }
2247 }
2248 
2249 ////////////////////////////////////////////////////////////////////////////////
2250 /// Increment statistics for buffer sizes of objects in this file.
2251 
2252 void TFile::SumBuffer(Int_t bufsize)
2254  fWritten++;
2255  fSumBuffer += double(bufsize);
2256  fSum2Buffer += double(bufsize) * double(bufsize); // avoid reaching MAXINT for temporary
2257 }
2258 
2259 ////////////////////////////////////////////////////////////////////////////////
2260 /// Write memory objects to this file.
2261 ///
2262 /// Loop on all objects in memory (including subdirectories).
2263 /// A new key is created in the KEYS linked list for each object.
2264 /// The list of keys is then saved on the file (via WriteKeys)
2265 /// as a single data record.
2266 /// For values of opt see TObject::Write().
2267 /// The directory header info is rewritten on the directory header record.
2268 /// The linked list of FREE segments is written.
2269 /// The file header is written (bytes 1->fBEGIN).
2270 
2271 Int_t TFile::Write(const char *, Int_t opt, Int_t bufsiz)
2273  if (!IsWritable()) {
2274  if (!TestBit(kWriteError)) {
2275  // Do not print the warning if we already had a SysError.
2276  Warning("Write", "file %s not opened in write mode", GetName());
2277  }
2278  return 0;
2279  }
2280 
2281  if (gDebug) {
2282  if (!GetTitle() || strlen(GetTitle()) == 0)
2283  Info("Write", "writing name = %s", GetName());
2284  else
2285  Info("Write", "writing name = %s title = %s", GetName(), GetTitle());
2286  }
2287 
2288  fMustFlush = kFALSE;
2289  Int_t nbytes = TDirectoryFile::Write(0, opt, bufsiz); // Write directory tree
2290  WriteStreamerInfo();
2291  WriteFree(); // Write free segments linked list
2292  WriteHeader(); // Now write file header
2293  fMustFlush = kTRUE;
2294 
2295  return nbytes;
2296 }
2297 
2298 ////////////////////////////////////////////////////////////////////////////////
2299 /// One can not save a const TDirectory object.
2300 
2301 Int_t TFile::Write(const char *n, Int_t opt, Int_t bufsize) const
2303  Error("Write const","A const TFile object should not be saved. We try to proceed anyway.");
2304  return const_cast<TFile*>(this)->Write(n, opt, bufsize);
2305 }
2306 
2307 ////////////////////////////////////////////////////////////////////////////////
2308 /// Write a buffer to the file. This is the basic low level write operation.
2309 /// Returns kTRUE in case of failure.
2310 
2311 Bool_t TFile::WriteBuffer(const char *buf, Int_t len)
2313  if (IsOpen() && fWritable) {
2314 
2315  Int_t st;
2316  if ((st = WriteBufferViaCache(buf, len))) {
2317  if (st == 2)
2318  return kTRUE;
2319  return kFALSE;
2320  }
2321 
2322  ssize_t siz;
2324  while ((siz = SysWrite(fD, buf, len)) < 0 && GetErrno() == EINTR)
2325  ResetErrno();
2327  if (siz < 0) {
2328  // Write the system error only once for this file
2329  SetBit(kWriteError); SetWritable(kFALSE);
2330  SysError("WriteBuffer", "error writing to file %s (%ld)", GetName(), (Long_t)siz);
2331  return kTRUE;
2332  }
2333  if (siz != len) {
2334  SetBit(kWriteError);
2335  Error("WriteBuffer", "error writing all requested bytes to file %s, wrote %ld of %d",
2336  GetName(), (Long_t)siz, len);
2337  return kTRUE;
2338  }
2339  fBytesWrite += siz;
2340  fgBytesWrite += siz;
2341 
2342  if (gMonitoringWriter)
2344 
2345  return kFALSE;
2346  }
2347  return kTRUE;
2348 }
2349 
2350 ////////////////////////////////////////////////////////////////////////////////
2351 /// Write buffer via cache. Returns 0 if cache is not active, 1 in case
2352 /// write via cache was successful, 2 in case write via cache failed.
2353 
2354 Int_t TFile::WriteBufferViaCache(const char *buf, Int_t len)
2356  if (!fCacheWrite) return 0;
2357 
2358  Int_t st;
2359  Long64_t off = GetRelOffset();
2360  if ((st = fCacheWrite->WriteBuffer(buf, off, len)) < 0) {
2361  SetBit(kWriteError);
2362  Error("WriteBuffer", "error writing to cache");
2363  return 2;
2364  }
2365  if (st > 0) {
2366  // fOffset might have been changed via TFileCacheWrite::WriteBuffer(), reset it
2367  Seek(off + len);
2368  return 1;
2369  }
2370  return 0;
2371 }
2372 
2373 ////////////////////////////////////////////////////////////////////////////////
2374 /// Write FREE linked list on the file.
2375 /// The linked list of FREE segments (fFree) is written as a single data
2376 /// record.
2377 
2378 void TFile::WriteFree()
2380  //*-* Delete old record if it exists
2381  if (fSeekFree != 0) {
2382  MakeFree(fSeekFree, fSeekFree + fNbytesFree -1);
2383  }
2384 
2385  Bool_t largeFile = (fEND > TFile::kStartBigFile);
2386 
2387  auto createKey = [this]() {
2388  Int_t nbytes = 0;
2389  TFree *afree;
2390  TIter next (fFree);
2391  while ((afree = (TFree*) next())) {
2392  nbytes += afree->Sizeof();
2393  }
2394  if (!nbytes) return (TKey*)nullptr;
2395 
2396  TKey *key = new TKey(fName,fTitle,IsA(),nbytes,this);
2397 
2398  if (key->GetSeekKey() == 0) {
2399  delete key;
2400  return (TKey*)nullptr;
2401  }
2402  return key;
2403  };
2404 
2405  TKey *key = createKey();
2406  if (!key) return;
2407 
2408  if (!largeFile && (fEND > TFile::kStartBigFile)) {
2409  // The free block list is large enough to bring the file to larger
2410  // than 2Gb, the references/offsets are now 64bits in the output
2411  // so we need to redo the calculattion since the list of free block
2412  // information will not fit in the original size.
2413  key->Delete();
2414  delete key;
2415 
2416  key = createKey();
2417  if (!key) return;
2418  }
2419 
2420  Int_t nbytes = key->GetObjlen();
2421  char *buffer = key->GetBuffer();
2422  char *start = buffer;
2423 
2424  TIter next (fFree);
2425  TFree *afree;
2426  while ((afree = (TFree*) next())) {
2427  // We could 'waste' time here and double check that
2428  // (buffer+afree->Sizeof() < (start+nbytes)
2429  afree->FillBuffer(buffer);
2430  }
2431  auto actualBytes = buffer-start;
2432  if ( actualBytes != nbytes ) {
2433  if (actualBytes < nbytes) {
2434  // Most likely one of the 'free' segment was used to store this
2435  // TKey, so we had one less TFree to store than we planned.
2436  memset(buffer,0,nbytes-actualBytes);
2437  } else {
2438  Error("WriteFree","The free block list TKey wrote more data than expected (%d vs %ld). Most likely there has been an out-of-bound write.",nbytes,(long int)actualBytes);
2439  }
2440  }
2441  fNbytesFree = key->GetNbytes();
2442  fSeekFree = key->GetSeekKey();
2443  key->WriteFile();
2444  delete key;
2445 }
2446 
2447 ////////////////////////////////////////////////////////////////////////////////
2448 /// Write File Header.
2449 
2450 void TFile::WriteHeader()
2452  SafeDelete(fInfoCache);
2453  TFree *lastfree = (TFree*)fFree->Last();
2454  if (lastfree) fEND = lastfree->GetFirst();
2455  const char *root = "root";
2456  char *psave = new char[fBEGIN];
2457  char *buffer = psave;
2458  Int_t nfree = fFree->GetSize();
2459  memcpy(buffer, root, 4); buffer += 4;
2460  Int_t version = fVersion;
2461  if (version <1000000 && fEND > kStartBigFile) {version += 1000000; fUnits = 8;}
2462  tobuf(buffer, version);
2463  tobuf(buffer, (Int_t)fBEGIN);
2464  if (version < 1000000) {
2465  tobuf(buffer, (Int_t)fEND);
2466  tobuf(buffer, (Int_t)fSeekFree);
2467  tobuf(buffer, fNbytesFree);
2468  tobuf(buffer, nfree);
2469  tobuf(buffer, fNbytesName);
2470  tobuf(buffer, fUnits);
2471  tobuf(buffer, fCompress);
2472  tobuf(buffer, (Int_t)fSeekInfo);
2473  tobuf(buffer, fNbytesInfo);
2474  } else {
2475  tobuf(buffer, fEND);
2476  tobuf(buffer, fSeekFree);
2477  tobuf(buffer, fNbytesFree);
2478  tobuf(buffer, nfree);
2479  tobuf(buffer, fNbytesName);
2480  tobuf(buffer, fUnits);
2481  tobuf(buffer, fCompress);
2482  tobuf(buffer, fSeekInfo);
2483  tobuf(buffer, fNbytesInfo);
2484  }
2485  fUUID.FillBuffer(buffer);
2486  Int_t nbytes = buffer - psave;
2487  Seek(0);
2488  WriteBuffer(psave, nbytes);
2489  Flush(); // Intentionally not conditional on fMustFlush, this is the 'obligatory' flush.
2490  delete [] psave;
2491 }
2492 
2493 ////////////////////////////////////////////////////////////////////////////////
2494 /// Generate source code necessary to access the objects stored in the file.
2495 ///
2496 /// Generate code in directory dirname for all classes specified in
2497 /// argument classes If classes = "*" (default and currently the
2498 /// only supported value), the function generates an include file
2499 /// for each class in the StreamerInfo list for which a TClass
2500 /// object does not exist.
2501 ///
2502 /// The code generated includes:
2503 /// - <em>dirnameProjectHeaders.h</em>, which contains one #include statement per generated header file
2504 /// - <em>dirnameProjectSource.cxx</em>,which contains all the constructors and destructors implementation.
2505 /// and one header per class that is not nested inside another class.
2506 /// The header file name is the fully qualified name of the class after all the special characters
2507 /// "<>,:" are replaced by underscored. For example for std::pair<edm::Vertex,int> the file name is
2508 /// pair_edm__Vertex_int_.h
2509 ///
2510 /// In the generated classes, map, multimap when the first template parameter is a class
2511 /// are replaced by a vector of pair. set and multiset when the tempalte parameter
2512 /// is a class are replaced by a vector. This is required since we do not have the
2513 /// code needed to order and/or compare the object of the classes.
2514 /// This is a quick explanation of the options available:
2515 /// Option | Details
2516 /// -------|--------
2517 /// new (default) | A new directory dirname is created. If dirname already exist, an error message is printed and the function returns.
2518 /// recreate | If dirname does not exist, it is created (like in "new"). If dirname already exist, all existing files in dirname are deleted before creating the new files.
2519 /// update | New classes are added to the existing directory. Existing classes with the same name are replaced by the new definition. If the directory dirname doest not exist, same effect as "new".
2520 /// genreflex | Use genreflex rather than rootcint to generate the dictionary.
2521 /// par | Create a PAR file with the minimal set of code needed to read the content of the ROOT file. The name of the PAR file is basename(dirname), with extension '.par' enforced; the PAR file will be created at dirname(dirname).
2522 ///
2523 /// If, in addition to one of the 3 above options, the option "+" is specified,
2524 /// the function will generate:
2525 /// - a script called MAKEP to build the shared lib
2526 /// - a dirnameLinkDef.h file
2527 /// - rootcint will be run to generate a dirnameProjectDict.cxx file
2528 /// - dirnameProjectDict.cxx will be compiled with the current options in compiledata.h
2529 /// - a shared lib dirname.so will be created.
2530 /// If the option "++" is specified, the generated shared lib is dynamically
2531 /// linked with the current executable module.
2532 /// If the option "+" and "nocompile" are specified, the utility files are generated
2533 /// as in the option "+" but they are not executed.
2534 /// Example:
2535 /// file.MakeProject("demo","*","recreate++");
2536 /// - creates a new directory demo unless it already exist
2537 /// - clear the previous directory content
2538 /// - generate the xxx.h files for all classes xxx found in this file
2539 /// and not yet known to the CINT dictionary.
2540 /// - creates the build script MAKEP
2541 /// - creates a LinkDef.h file
2542 /// - runs rootcint generating demoProjectDict.cxx
2543 /// - compiles demoProjectDict.cxx into demoProjectDict.o
2544 /// - generates a shared lib demo.so
2545 /// - dynamically links the shared lib demo.so to the executable
2546 /// If only the option "+" had been specified, one can still link the
2547 /// shared lib to the current executable module with:
2548 ///
2549 /// gSystem->load("demo/demo.so");
2550 ///
2551 /// The following feature is not yet enabled:
2552 /// One can restrict the list of classes to be generated by using expressions like:
2553 ///
2554 /// classes = "Ali*" generate code only for classes starting with Ali
2555 /// classes = "myClass" generate code for class MyClass only.
2556 ///
2557 
2558 void TFile::MakeProject(const char *dirname, const char * /*classes*/,
2559  Option_t *option)
2560 {
2561  TString opt = option;
2562  opt.ToLower();
2563  Bool_t makepar = kFALSE;
2564  TString parname, pardir;
2565  if (opt.Contains("par")) {
2566  // Create a PAR file
2567  parname = gSystem->BaseName(dirname);
2568  if (parname.EndsWith(".par")) parname.ReplaceAll(".par","");
2569  pardir = gSystem->DirName(dirname);
2570  // Cleanup or prepare the dirs
2571  TString path, filepath;
2572  void *dir = gSystem->OpenDirectory(pardir);
2573  if (dir) {
2574  path.Form("%s/%s", pardir.Data(), parname.Data());
2575  void *dirp = gSystem->OpenDirectory(path);
2576  if (dirp) {
2577  path += "/PROOF-INF";
2578  void *dirinf = gSystem->OpenDirectory(path);
2579  const char *afile = 0;
2580  if (dirinf) {
2581  while ((afile = gSystem->GetDirEntry(dirinf))) {
2582  if (strcmp(afile,".") == 0) continue;
2583  if (strcmp(afile,"..") == 0) continue;
2584  filepath.Form("%s/%s", path.Data(), afile);
2585  if (gSystem->Unlink(filepath))
2586  Warning("MakeProject", "1: problems unlinking '%s' ('%s', '%s')", filepath.Data(), path.Data(), afile);
2587  }
2588  gSystem->FreeDirectory(dirinf);
2589  }
2590  gSystem->Unlink(path);
2591  path.Form("%s/%s", pardir.Data(), parname.Data());
2592  while ((afile = gSystem->GetDirEntry(dirp))) {
2593  if (strcmp(afile,".") == 0) continue;
2594  if (strcmp(afile,"..") == 0) continue;
2595  filepath.Form("%s/%s", path.Data(), afile);
2596  if (gSystem->Unlink(filepath))
2597  Warning("MakeProject", "2: problems unlinking '%s' ('%s', '%s')", filepath.Data(), path.Data(), afile);
2598  }
2599  gSystem->FreeDirectory(dirp);
2600  if (gSystem->Unlink(path))
2601  Warning("MakeProject", "problems unlinking '%s'", path.Data());
2602  }
2603  }
2604  // Make sure that the relevant dirs exists: this is mandatory, so we fail if unsuccessful
2605  path.Form("%s/%s/PROOF-INF", pardir.Data(), parname.Data());
2606  if (gSystem->mkdir(path, kTRUE)) {
2607  Error("MakeProject", "problems creating '%s'", path.Data());
2608  return;
2609  }
2610  makepar = kTRUE;
2611 
2612  } else {
2613  void *dir = gSystem->OpenDirectory(dirname);
2614  TString dirpath;
2615 
2616  if (opt.Contains("update")) {
2617  // check that directory exist, if not create it
2618  if (dir == 0) {
2619  gSystem->mkdir(dirname);
2620  }
2621 
2622  } else if (opt.Contains("recreate")) {
2623  // check that directory exist, if not create it
2624  if (dir == 0) {
2625  if (gSystem->mkdir(dirname) < 0) {
2626  Error("MakeProject","cannot create directory '%s'",dirname);
2627  return;
2628  }
2629  }
2630  // clear directory
2631  while (dir) {
2632  const char *afile = gSystem->GetDirEntry(dir);
2633  if (afile == 0) break;
2634  if (strcmp(afile,".") == 0) continue;
2635  if (strcmp(afile,"..") == 0) continue;
2636  dirpath.Form("%s/%s",dirname,afile);
2637  gSystem->Unlink(dirpath);
2638  }
2639 
2640  } else {
2641  // new is assumed
2642  // if directory already exist, print error message and return
2643  if (dir) {
2644  Error("MakeProject","cannot create directory %s, already existing",dirname);
2645  gSystem->FreeDirectory(dir);
2646  return;
2647  }
2648  if (gSystem->mkdir(dirname) < 0) {
2649  Error("MakeProject","cannot create directory '%s'",dirname);
2650  return;
2651  }
2652  }
2653  if (dir) {
2654  gSystem->FreeDirectory(dir);
2655  }
2656  }
2657  Bool_t genreflex = opt.Contains("genreflex");
2658 
2659  // we are now ready to generate the classes
2660  // loop on all TStreamerInfo
2661  TList *filelist = (TList*)GetStreamerInfoCache();
2662  if (filelist) filelist = (TList*)filelist->Clone();
2663  if (filelist == 0) {
2664  Error("MakeProject","file %s has no StreamerInfo", GetName());
2665  return;
2666  }
2667 
2668  TString clean_dirname(dirname);
2669  if (makepar) clean_dirname.Form("%s/%s", pardir.Data(), parname.Data());
2670  if (clean_dirname[clean_dirname.Length()-1]=='/') {
2671  clean_dirname.Remove(clean_dirname.Length()-1);
2672  } else if (clean_dirname[clean_dirname.Length()-1]=='\\') {
2673  clean_dirname.Remove(clean_dirname.Length()-1);
2674  if (clean_dirname[clean_dirname.Length()-1]=='\\') {
2675  clean_dirname.Remove(clean_dirname.Length()-1);
2676  }
2677  }
2678  TString subdirname( gSystem->BaseName(clean_dirname) );
2679  if (makepar) subdirname = parname;
2680  if (subdirname == "") {
2681  Error("MakeProject","Directory name must not be empty.");
2682  return;
2683  }
2684 
2685  // Start the source file
2686  TString spath; spath.Form("%s/%sProjectSource.cxx",clean_dirname.Data(),subdirname.Data());
2687  FILE *sfp = fopen(spath.Data(),"w");
2688  if (sfp ==0) {
2689  Error("MakeProject","Unable to create the source file %s.",spath.Data());
2690  return;
2691  }
2692  fprintf(sfp, "namespace std {}\nusing namespace std;\n");
2693  fprintf(sfp, "#include \"%sProjectHeaders.h\"\n\n",subdirname.Data() );
2694  if (!genreflex) fprintf(sfp, "#include \"%sLinkDef.h\"\n\n",subdirname.Data() );
2695  fprintf(sfp, "#include \"%sProjectDict.cxx\"\n\n",subdirname.Data() );
2696  fprintf(sfp, "struct DeleteObjectFunctor {\n");
2697  fprintf(sfp, " template <typename T>\n");
2698  fprintf(sfp, " void operator()(const T *ptr) const {\n");
2699  fprintf(sfp, " delete ptr;\n");
2700  fprintf(sfp, " }\n");
2701  fprintf(sfp, " template <typename T, typename Q>\n");
2702  fprintf(sfp, " void operator()(const std::pair<T,Q> &) const {\n");
2703  fprintf(sfp, " // Do nothing\n");
2704  fprintf(sfp, " }\n");
2705  fprintf(sfp, " template <typename T, typename Q>\n");
2706  fprintf(sfp, " void operator()(const std::pair<T,Q*> &ptr) const {\n");
2707  fprintf(sfp, " delete ptr.second;\n");
2708  fprintf(sfp, " }\n");
2709  fprintf(sfp, " template <typename T, typename Q>\n");
2710  fprintf(sfp, " void operator()(const std::pair<T*,Q> &ptr) const {\n");
2711  fprintf(sfp, " delete ptr.first;\n");
2712  fprintf(sfp, " }\n");
2713  fprintf(sfp, " template <typename T, typename Q>\n");
2714  fprintf(sfp, " void operator()(const std::pair<T*,Q*> &ptr) const {\n");
2715  fprintf(sfp, " delete ptr.first;\n");
2716  fprintf(sfp, " delete ptr.second;\n");
2717  fprintf(sfp, " }\n");
2718  fprintf(sfp, "};\n\n");
2719  fclose( sfp );
2720 
2721  // loop on all TStreamerInfo classes to check for empty classes
2722  // and enums listed either as data member or template parameters,
2723  // and filter out 'duplicates' classes/streamerInfos.
2724  TStreamerInfo *info;
2725  TIter flnext(filelist);
2726  TList extrainfos;
2727  TList *list = new TList();
2728  while ((info = (TStreamerInfo*)flnext())) {
2729  if (info->IsA() != TStreamerInfo::Class()) {
2730  continue;
2731  }
2732  if (strstr(info->GetName(),"@@")) {
2733  // Skip schema evolution support streamerInfo
2734  continue;
2735  }
2736  TClass *cl = TClass::GetClass(info->GetName());
2737  if (cl) {
2738  if (cl->HasInterpreterInfo()) continue; // skip known classes
2739  }
2740  // Find and use the proper rules for the TStreamerInfos.
2741  TMakeProject::GenerateMissingStreamerInfos( &extrainfos, info->GetName() );
2742  TIter enext( info->GetElements() );
2743  TStreamerElement *el;
2745  if (cl && cl->GetSchemaRules()) {
2746  rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
2747  }
2748  while( (el=(TStreamerElement*)enext()) ) {
2749  for(auto rule : rules) {
2750  if( rule->IsRenameRule() || rule->IsAliasRule() )
2751  continue;
2752  // Check whether this is an 'attribute' rule.
2753  if ( rule->HasTarget( el->GetName()) && rule->GetAttributes()[0] != 0 ) {
2754  TString attr( rule->GetAttributes() );
2755  attr.ToLower();
2756  if (attr.Contains("owner")) {
2757  if (attr.Contains("notowner")) {
2758  el->SetBit(TStreamerElement::kDoNotDelete);
2759  } else {
2760  el->ResetBit(TStreamerElement::kDoNotDelete);
2761  }
2762  }
2763  }
2764  }
2766  }
2767  TVirtualStreamerInfo *alternate = (TVirtualStreamerInfo*)list->FindObject(info->GetName());
2768  if (alternate) {
2769  if ((info->GetClass() && info->GetClassVersion() == info->GetClass()->GetClassVersion())
2770  || (info->GetClassVersion() > alternate->GetClassVersion()) ) {
2771  list->AddAfter(alternate, info);
2772  list->Remove(alternate);
2773  } // otherwise ignore this info as not being the official one.
2774  } else {
2775  list->Add(info);
2776  }
2777  }
2778  // Now transfer the new StreamerInfo onto the main list and
2779  // to the owning list.
2780  TIter nextextra(&extrainfos);
2781  while ((info = (TStreamerInfo*)nextextra())) {
2782  list->Add(info);
2783  filelist->Add(info);
2784  }
2785 
2786  // loop on all TStreamerInfo classes
2787  TIter next(list);
2788  Int_t ngener = 0;
2789  while ((info = (TStreamerInfo*)next())) {
2790  if (info->IsA() != TStreamerInfo::Class()) {
2791  continue;
2792  }
2793  if (info->GetClassVersion()==-4) continue; // Skip outer level namespace
2794  TIter subnext(list);
2795  TStreamerInfo *subinfo;
2796  TList subClasses;
2797  Int_t len = strlen(info->GetName());
2798  while ((subinfo = (TStreamerInfo*)subnext())) {
2799  if (subinfo->IsA() != TStreamerInfo::Class()) {
2800  continue;
2801  }
2802  if (strncmp(info->GetName(),subinfo->GetName(),len)==0) {
2803  // The 'sub' StreamerInfo start with the main StreamerInfo name,
2804  // it subinfo is likely to be a nested class.
2805  const Int_t sublen = strlen(subinfo->GetName());
2806  if ( (sublen > len) && subinfo->GetName()[len+1]==':'
2807  && !subClasses.FindObject(subinfo->GetName()) /* We need to insure uniqueness */)
2808  {
2809  subClasses.Add(subinfo);
2810  }
2811  }
2812  }
2813  ngener += info->GenerateHeaderFile(clean_dirname.Data(),&subClasses,&extrainfos);
2814  subClasses.Clear("nodelete");
2815  }
2816  TString path;
2817  path.Form("%s/%sProjectHeaders.h",clean_dirname.Data(),subdirname.Data());
2818  FILE *allfp = fopen(path,"a");
2819  if (!allfp) {
2820  Error("MakeProject","Cannot open output file:%s\n",path.Data());
2821  } else {
2822  fprintf(allfp,"#include \"%sProjectInstances.h\"\n", subdirname.Data());
2823  fclose(allfp);
2824  }
2825 
2826  printf("MakeProject has generated %d classes in %s\n",ngener,clean_dirname.Data());
2827 
2828  // generate the shared lib
2829  if (!opt.Contains("+") && !makepar) {
2830  delete list;
2831  filelist->Delete();
2832  delete filelist;
2833  return;
2834  }
2835 
2836  // Makefiles files
2837  FILE *fpMAKE = 0;
2838  if (!makepar) {
2839  // Create the MAKEP file by looping on all *.h files
2840  // delete MAKEP if it already exists
2841 #ifdef WIN32
2842  path.Form("%s/makep.cmd",clean_dirname.Data());
2843 #else
2844  path.Form("%s/MAKEP",clean_dirname.Data());
2845 #endif
2846 #ifdef R__WINGCC
2847  fpMAKE = fopen(path,"wb");
2848 #else
2849  fpMAKE = fopen(path,"w");
2850 #endif
2851  if (!fpMAKE) {
2852  Error("MakeProject", "cannot open file %s", path.Data());
2853  delete list;
2854  filelist->Delete();
2855  delete filelist;
2856  return;
2857  }
2858  }
2859 
2860  // Add rootcint/genreflex statement generating ProjectDict.cxx
2861  FILE *ifp = 0;
2862  path.Form("%s/%sProjectInstances.h",clean_dirname.Data(),subdirname.Data());
2863 #ifdef R__WINGCC
2864  ifp = fopen(path,"wb");
2865 #else
2866  ifp = fopen(path,"w");
2867 #endif
2868  if (!ifp) {
2869  Error("MakeProject", "cannot open path file %s", path.Data());
2870  delete list;
2871  filelist->Delete();
2872  delete filelist;
2873  fclose(fpMAKE);
2874  return;
2875  }
2876 
2877  if (!makepar) {
2878  if (genreflex) {
2879  fprintf(fpMAKE,"genreflex %sProjectHeaders.h -o %sProjectDict.cxx --comments --iocomments %s ",subdirname.Data(),subdirname.Data(),gSystem->GetIncludePath());
2880  path.Form("%s/%sSelection.xml",clean_dirname.Data(),subdirname.Data());
2881  } else {
2882  fprintf(fpMAKE,"rootcint -f %sProjectDict.cxx -c %s ",subdirname.Data(),gSystem->GetIncludePath());
2883  path.Form("%s/%sLinkDef.h",clean_dirname.Data(),subdirname.Data());
2884  }
2885  } else {
2886  path.Form("%s/%sLinkDef.h",clean_dirname.Data(),subdirname.Data());
2887  }
2888 
2889  // Create the LinkDef.h or xml selection file by looping on all *.h files
2890  // replace any existing file.
2891 #ifdef R__WINGCC
2892  FILE *fp = fopen(path,"wb");
2893 #else
2894  FILE *fp = fopen(path,"w");
2895 #endif
2896  if (!fp) {
2897  Error("MakeProject", "cannot open path file %s", path.Data());
2898  delete list;
2899  filelist->Delete();
2900  delete filelist;
2901  fclose(fpMAKE);
2902  fclose(ifp);
2903  return;
2904  }
2905  if (genreflex) {
2906  fprintf(fp,"<lcgdict>\n");
2907  fprintf(fp,"\n");
2908  } else {
2909  fprintf(fp,"#ifdef __CINT__\n");
2910  fprintf(fp,"\n");
2911  }
2912 
2913  TString tmp;
2914  TString instances;
2915  TString selections;
2916  next.Reset();
2917  while ((info = (TStreamerInfo*)next())) {
2918  if (info->IsA() != TStreamerInfo::Class()) {
2919  continue;
2920  }
2921  TClass *cl = TClass::GetClass(info->GetName());
2922  if (cl) {
2923  if (cl->HasInterpreterInfo()) continue; // skip known classes
2924  if (cl->GetSchemaRules()) {
2925  auto rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
2926  TString strrule;
2927  for(auto rule : rules) {
2928  strrule.Clear();
2929  if (genreflex) {
2930  rule->AsString(strrule,"x");
2931  strrule.Append("\n");
2932  if ( selections.Index(strrule) == kNPOS ) {
2933  selections.Append(strrule);
2934  }
2935  } else {
2936  rule->AsString(strrule);
2937  if (strncmp(strrule.Data(),"type=",5)==0) {
2938  strrule.Remove(0,5);
2939  }
2940  fprintf(fp,"#pragma %s;\n",strrule.Data());
2941  }
2942  }
2943  }
2944 
2945  }
2946  if ((info->GetClass() && info->GetClass()->GetCollectionType()) || TClassEdit::IsSTLCont(info->GetName())) {
2947  std::vector<std::string> inside;
2948  int nestedLoc;
2949  TClassEdit::GetSplit( info->GetName(), inside, nestedLoc, TClassEdit::kLong64 );
2950  Int_t stlkind = TClassEdit::STLKind(inside[0].c_str());
2951  TClass *key = TClass::GetClass(inside[1].c_str());
2952  if (key) {
2953  TString what;
2954  switch ( stlkind ) {
2955  case ROOT::kSTLmap:
2956  case ROOT::kSTLmultimap:
2957  if (TClass::GetClass(inside[1].c_str())) {
2958  what = "std::pair<";
2959  what += TMakeProject::UpdateAssociativeToVector( inside[1].c_str() );
2960  what += ",";
2961  what += TMakeProject::UpdateAssociativeToVector( inside[2].c_str() );
2962  if (what[what.Length()-1]=='>') {
2963  what += " >";
2964  } else {
2965  what += ">";
2966  }
2967  if (genreflex) {
2968  tmp.Form("<class name=\"%s\" />\n",what.Data());
2969  if ( selections.Index(tmp) == kNPOS ) {
2970  selections.Append(tmp);
2971  }
2972  tmp.Form("template class %s;\n",what.Data());
2973  if ( instances.Index(tmp) == kNPOS ) {
2974  instances.Append(tmp);
2975  }
2976  } else {
2977  what.ReplaceAll("std::","");
2978  TClass *paircl = TClass::GetClass(what.Data());
2979  if (paircl == 0 || !paircl->HasInterpreterInfo()) {
2980  fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
2981  }
2982  }
2983  break;
2984  }
2985  default:
2986  if (strncmp(key->GetName(),"pair<",strlen("pair<"))==0) {
2987  if (genreflex) {
2988  tmp.Form("<class name=\"%s\" />\n",key->GetName());
2989  if ( selections.Index(tmp) == kNPOS ) {
2990  selections.Append(tmp);
2991  }
2992  tmp.Form("template class %s;\n",key->GetName());
2993  if ( instances.Index(tmp) == kNPOS ) {
2994  instances.Append(tmp);
2995  }
2996  } else {
2997  what.ReplaceAll("std::","");
2998  fprintf(fp,"#pragma link C++ class %s+;\n",key->GetName());
2999  }
3000  }
3001  break;
3002  }
3003  }
3004  continue;
3005  }
3006  {
3008  if (genreflex) {
3009  tmp.Form("<class name=\"%s\" />\n",what.Data());
3010  if ( selections.Index(tmp) == kNPOS ) {
3011  selections.Append(tmp);
3012  }
3013  if (what[what.Length()-1] == '>') {
3014  tmp.Form("template class %s;\n",what.Data());
3015  if ( instances.Index(tmp) == kNPOS ) {
3016  instances.Append(tmp);
3017  }
3018  }
3019  } else {
3020  what.ReplaceAll("std::","");
3021  fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
3022  }
3023  }
3024  if (genreflex) {
3025  // Also request the dictionary for the STL container used as members ...
3026  TIter eliter( info->GetElements() );
3027  TStreamerElement *element;
3028  while( (element = (TStreamerElement*)eliter() ) ) {
3029  if (element->GetClass() && !element->GetClass()->IsLoaded() && element->GetClass()->GetCollectionProxy()) {
3030  TString what( TMakeProject::UpdateAssociativeToVector(element->GetClass()->GetName()) );
3031  tmp.Form("<class name=\"%s\" />\n",what.Data());
3032  if ( selections.Index(tmp) == kNPOS ) {
3033  selections.Append(tmp);
3034  }
3035  tmp.Form("template class %s;\n",what.Data());
3036  if ( instances.Index(tmp) == kNPOS ) {
3037  instances.Append(tmp);
3038  }
3039  }
3040  }
3041  }
3042  }
3043  if (genreflex) {
3044  fprintf(ifp,"#ifndef PROJECT_INSTANCES_H\n");
3045  fprintf(ifp,"#define PROJECT_INSTANCES_H\n");
3046  fprintf(ifp,"%s",instances.Data());
3047  fprintf(ifp,"#endif\n");
3048  fprintf(fp,"%s",selections.Data());
3049  fprintf(fp,"</lcgdict>\n");
3050  } else {
3051  fprintf(fp,"#endif\n");
3052  }
3053  fclose(fp);
3054  fclose(ifp);
3055 
3056  if (!makepar) {
3057  // add compilation line
3058  TString sdirname(subdirname);
3059 
3060  TString cmd = gSystem->GetMakeSharedLib();
3061  TString sources = TString::Format("%sProjectSource.cxx ", sdirname.Data());
3062  cmd.ReplaceAll("$SourceFiles",sources.Data());
3063  TString object = TString::Format("%sProjectSource.", sdirname.Data());
3064  object.Append( gSystem->GetObjExt() );
3065  cmd.ReplaceAll("$ObjectFiles", object.Data());
3066  cmd.ReplaceAll("$IncludePath",TString(gSystem->GetIncludePath()) + " -I" + clean_dirname.Data());
3067  cmd.ReplaceAll("$SharedLib",sdirname+"."+gSystem->GetSoExt());
3068  cmd.ReplaceAll("$LinkedLibs",gSystem->GetLibraries("","SDL"));
3069  cmd.ReplaceAll("$LibName",sdirname);
3070  cmd.ReplaceAll("$BuildDir",".");
3071  TString sOpt;
3072  TString rootbuild = ROOTBUILD;
3073  if (rootbuild.Index("debug",0,TString::kIgnoreCase)==kNPOS) {
3074  sOpt = gSystem->GetFlagsOpt();
3075  } else {
3076  sOpt = gSystem->GetFlagsDebug();
3077  }
3078  cmd.ReplaceAll("$Opt", sOpt);
3079 
3080  if (genreflex) {
3081  fprintf(fpMAKE,"-s %sSelection.xml \n",subdirname.Data());
3082  } else {
3083  fprintf(fpMAKE,"%sProjectHeaders.h ",subdirname.Data());
3084  fprintf(fpMAKE,"%sLinkDef.h \n",subdirname.Data());
3085  }
3086 
3087  fprintf(fpMAKE,"%s\n",cmd.Data());
3088 
3089  printf("%s/MAKEP file has been generated\n", clean_dirname.Data());
3090 
3091  fclose(fpMAKE);
3092 
3093  } else {
3094 
3095  // Create the Makefile
3096  TString filemake = TString::Format("%s/Makefile", clean_dirname.Data());
3097  if (MakeProjectParMake(parname, filemake.Data()) != 0) {
3098  Error("MakeProject", "problems creating PAR make file '%s'", filemake.Data());
3099  delete list;
3100  filelist->Delete();
3101  delete filelist;
3102  return;
3103  }
3104  // Get Makefile.arch
3105  TString mkarchsrc = TString::Format("%s/Makefile.arch", TROOT::GetEtcDir().Data());
3106  if (gSystem->ExpandPathName(mkarchsrc))
3107  Warning("MakeProject", "problems expanding '%s'", mkarchsrc.Data());
3108  TString mkarchdst = TString::Format("%s/Makefile.arch", clean_dirname.Data());
3109  if (gSystem->CopyFile(mkarchsrc.Data(), mkarchdst.Data(), kTRUE) != 0) {
3110  Error("MakeProject", "problems retrieving '%s' to '%s'", mkarchsrc.Data(), mkarchdst.Data());
3111  delete list;
3112  filelist->Delete();
3113  delete filelist;
3114  return;
3115  }
3116  // Create the Makefile
3117  TString proofinf = TString::Format("%s/PROOF-INF", clean_dirname.Data());
3118  if (MakeProjectParProofInf(parname, proofinf.Data()) != 0) {
3119  Error("MakeProject", "problems creating BUILD.sh and/or SETUP.C under '%s'", proofinf.Data());
3120  delete list;
3121  filelist->Delete();
3122  delete filelist;
3123  return;
3124  }
3125 
3126  // Make sure BUILD.sh is executable and create SETUP.C
3127  TString cmod = TString::Format("chmod +x %s/PROOF-INF/BUILD.sh", clean_dirname.Data());
3128 #ifndef WIN32
3129  gSystem->Exec(cmod.Data());
3130 #else
3131  // not really needed for Windows but it would work both both Unix and NT
3132  chmod(cmod.Data(), 00700);
3133 #endif
3134  Printf("Files Makefile, Makefile.arch, PROOF-INF/BUILD.sh and"
3135  " PROOF-INF/SETUP.C have been generated under '%s'", clean_dirname.Data());
3136 
3137  // Generate the PAR file, if not Windows
3138 #ifndef WIN32
3139  TString curdir = gSystem->WorkingDirectory();
3140  if (gSystem->ChangeDirectory(pardir)) {
3141  TString cmd = TString::Format("tar czvf %s.par %s", parname.Data(), parname.Data());
3142  gSystem->Exec(cmd.Data());
3143  if (gSystem->ChangeDirectory(curdir)) {
3144  Info("MakeProject", "PAR file %s.par generated", clean_dirname.Data());
3145  } else {
3146  Warning("MakeProject", "problems changing directory back to '%s'", curdir.Data());
3147  }
3148  } else {
3149  Error("MakeProject", "problems changing directory to '%s' - skipping PAR file generation", pardir.Data());
3150  }
3151 #else
3152  Warning("MakeProject", "on Windows systems the PAR file cannot be generated out of the package directory!");
3153 #endif
3154  }
3155 
3156 
3157  if (!makepar && !opt.Contains("nocompilation")) {
3158  // now execute the generated script compiling and generating the shared lib
3159  path = gSystem->WorkingDirectory();
3160  gSystem->ChangeDirectory(clean_dirname.Data());
3161 #ifndef WIN32
3162  gSystem->Exec("chmod +x MAKEP");
3163  int res = !gSystem->Exec("./MAKEP");
3164 #else
3165  // not really needed for Windows but it would work both both Unix and NT
3166  chmod("makep.cmd",00700);
3167  int res = !gSystem->Exec("MAKEP");
3168 #endif
3169  gSystem->ChangeDirectory(path);
3170  path.Form("%s/%s.%s",clean_dirname.Data(),subdirname.Data(),gSystem->GetSoExt());
3171  if (res) printf("Shared lib %s has been generated\n",path.Data());
3172 
3173  //dynamically link the generated shared lib
3174  if (opt.Contains("++")) {
3175  res = !gSystem->Load(path);
3176  if (res) printf("Shared lib %s has been dynamically linked\n",path.Data());
3177  }
3178  }
3179 
3180  extrainfos.Clear("nodelete");
3181  // filelist->Clear("nodetele");
3182  delete list;
3183  filelist->Delete();
3184  delete filelist;
3185 }
3186 
3187 ////////////////////////////////////////////////////////////////////////////////
3188 /// Create makefile at 'filemake' for PAR package 'pack'.
3189 ///
3190 /// Called by MakeProject when option 'par' is given.
3191 /// Return 0 on success, -1 on error.
3192 
3193 Int_t TFile::MakeProjectParMake(const char *pack, const char *filemake)
3195  // Output file path must be defined
3196  if (!filemake || (filemake && strlen(filemake) <= 0)) {
3197  Error("MakeProjectParMake", "path for output file undefined!");
3198  return -1;
3199  }
3200 
3201  // Package name must be defined
3202  if (!pack || (pack && strlen(pack) <= 0)) {
3203  Error("MakeProjectParMake", "package name undefined!");
3204  return -1;
3205  }
3206 
3207 #ifdef R__WINGCC
3208  FILE *fmk = fopen(filemake, "wb");
3209 #else
3210  FILE *fmk = fopen(filemake, "w");
3211 #endif
3212  if (!fmk) {
3213  Error("MakeProjectParMake", "cannot create file '%s' (errno: %d)", filemake, TSystem::GetErrno());
3214  return -1;
3215  }
3216 
3217  // Fill the file now
3218  fprintf(fmk, "# Makefile for the ROOT test programs.\n");
3219  fprintf(fmk, "# This Makefile shows how to compile and link applications\n");
3220  fprintf(fmk, "# using the ROOT libraries on all supported platforms.\n");
3221  fprintf(fmk, "#\n");
3222  fprintf(fmk, "# Copyright (c) 2000 Rene Brun and Fons Rademakers\n");
3223  fprintf(fmk, "#\n");
3224  fprintf(fmk, "# Author: this makefile has been automatically generated via TFile::MakeProject\n");
3225  fprintf(fmk, "\n");
3226  fprintf(fmk, "include Makefile.arch\n");
3227  fprintf(fmk, "\n");
3228  fprintf(fmk, "#------------------------------------------------------------------------------\n");
3229  fprintf(fmk, "\n");
3230  fprintf(fmk, "PACKO = %sProjectSource.$(ObjSuf)\n", pack);
3231  fprintf(fmk, "PACKS = %sProjectSource.$(SrcSuf) %sProjectDict.$(SrcSuf)\n", pack, pack);
3232  fprintf(fmk, "PACKSO = lib%s.$(DllSuf)\n", pack);
3233  fprintf(fmk, "\n");
3234  fprintf(fmk, "ifeq ($(PLATFORM),win32)\n");
3235  fprintf(fmk, "PACKLIB = lib%s.lib\n", pack);
3236  fprintf(fmk, "else\n");
3237  fprintf(fmk, "PACKLIB = $(PACKSO)\n");
3238  fprintf(fmk, "endif\n");
3239  fprintf(fmk, "\n");
3240  fprintf(fmk, "OBJS = $(PACKO)\n");
3241  fprintf(fmk, "\n");
3242  fprintf(fmk, "PROGRAMS =\n");
3243  fprintf(fmk, "\n");
3244  fprintf(fmk, "#------------------------------------------------------------------------------\n");
3245  fprintf(fmk, "\n");
3246  fprintf(fmk, ".SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(DllSuf)\n");
3247  fprintf(fmk, "\n");
3248  fprintf(fmk, "all: $(PACKLIB)\n");
3249  fprintf(fmk, "\n");
3250  fprintf(fmk, "$(PACKSO): $(PACKO)\n");
3251  fprintf(fmk, "ifeq ($(ARCH),aix)\n");
3252  fprintf(fmk, "\t\t/usr/ibmcxx/bin/makeC++SharedLib $(OutPutOpt) $@ $(LIBS) -p 0 $^\n");
3253  fprintf(fmk, "else\n");
3254  fprintf(fmk, "ifeq ($(ARCH),aix5)\n");
3255  fprintf(fmk, "\t\t/usr/vacpp/bin/makeC++SharedLib $(OutPutOpt) $@ $(LIBS) -p 0 $^\n");
3256  fprintf(fmk, "else\n");
3257  fprintf(fmk, "ifeq ($(PLATFORM),macosx)\n");
3258  fprintf(fmk, "# We need to make both the .dylib and the .so\n");
3259  fprintf(fmk, "\t\t$(LD) $(SOFLAGS)$@ $(LDFLAGS) $^ $(OutPutOpt) $@ $(LIBS)\n");
3260  fprintf(fmk, "ifneq ($(subst $(MACOSX_MINOR),,1234),1234)\n");
3261  fprintf(fmk, "ifeq ($(MACOSX_MINOR),4)\n");
3262  fprintf(fmk, "\t\tln -sf $@ $(subst .$(DllSuf),.so,$@)\n");
3263  fprintf(fmk, "else\n");
3264  fprintf(fmk, "\t\t$(LD) -bundle -undefined $(UNDEFOPT) $(LDFLAGS) $^ \\\n");
3265  fprintf(fmk, "\t\t $(OutPutOpt) $(subst .$(DllSuf),.so,$@)\n");
3266  fprintf(fmk, "endif\n");
3267  fprintf(fmk, "endif\n");
3268  fprintf(fmk, "else\n");
3269  fprintf(fmk, "ifeq ($(PLATFORM),win32)\n");
3270  fprintf(fmk, "\t\tbindexplib $* $^ > $*.def\n");
3271  fprintf(fmk, "\t\tlib -nologo -MACHINE:IX86 $^ -def:$*.def \\\n");
3272  fprintf(fmk, "\t\t $(OutPutOpt)$(PACKLIB)\n");
3273  fprintf(fmk, "\t\t$(LD) $(SOFLAGS) $(LDFLAGS) $^ $*.exp $(LIBS) \\\n");
3274  fprintf(fmk, "\t\t $(OutPutOpt)$@\n");
3275  fprintf(fmk, "else\n");
3276  fprintf(fmk, "\t\t$(LD) $(SOFLAGS) $(LDFLAGS) $^ $(OutPutOpt) $@ $(LIBS) $(EXPLLINKLIBS)\n");
3277  fprintf(fmk, "endif\n");
3278  fprintf(fmk, "endif\n");
3279  fprintf(fmk, "endif\n");
3280  fprintf(fmk, "endif\n");
3281  fprintf(fmk, "\t\t@echo \"$@ done\"\n");
3282  fprintf(fmk, "\n");
3283  fprintf(fmk, "clean:\n");
3284  fprintf(fmk, "\t\t@rm -f $(OBJS) core\n");
3285  fprintf(fmk, "\n");
3286  fprintf(fmk, "distclean: clean\n");
3287  fprintf(fmk, "\t\t@rm -f $(PROGRAMS) $(PACKSO) $(PACKLIB) *Dict.* *.def *.exp \\\n");
3288  fprintf(fmk, "\t\t *.so *.lib *.dll *.d *.log .def so_locations\n");
3289  fprintf(fmk, "\t\t@rm -rf cxx_repository\n");
3290  fprintf(fmk, "\n");
3291  fprintf(fmk, "# Dependencies\n");
3292  fprintf(fmk, "\n");
3293  fprintf(fmk, "%sProjectSource.$(ObjSuf): %sProjectHeaders.h %sLinkDef.h %sProjectDict.$(SrcSuf)\n", pack, pack, pack, pack);
3294  fprintf(fmk, "\n");
3295  fprintf(fmk, "%sProjectDict.$(SrcSuf): %sProjectHeaders.h %sLinkDef.h\n", pack, pack, pack);
3296  fprintf(fmk, "\t\t@echo \"Generating dictionary $@...\"\n");
3297  fprintf(fmk, "\t\t@rootcint -f $@ -c $^\n");
3298  fprintf(fmk, "\n");
3299  fprintf(fmk, ".$(SrcSuf).$(ObjSuf):\n");
3300  fprintf(fmk, "\t\t$(CXX) $(CXXFLAGS) -c $<\n");
3301  fprintf(fmk, "\n");
3302 
3303  // Close the file
3304  fclose(fmk);
3305 
3306  // Done
3307  return 0;
3308 }
3309 
3310 ////////////////////////////////////////////////////////////////////////////////
3311 /// Create BUILD.sh and SETUP.C under 'proofinf' for PAR package 'pack'.
3312 /// Called by MakeProject when option 'par' is given.
3313 /// Return 0 on success, -1 on error.
3314 
3315 Int_t TFile::MakeProjectParProofInf(const char *pack, const char *proofinf)
3317  // Output directory path must be defined ...
3318  if (!proofinf || (proofinf && strlen(proofinf) <= 0)) {
3319  Error("MakeProjectParProofInf", "directory path undefined!");
3320  return -1;
3321  }
3322 
3323  // ... and exist and be a directory
3324  Int_t rcst = 0;
3325  FileStat_t st;
3326  if ((rcst = gSystem->GetPathInfo(proofinf, st)) != 0 || !R_ISDIR(st.fMode)) {
3327  Error("MakeProjectParProofInf", "path '%s' %s", proofinf,
3328  ((rcst == 0) ? "is not a directory" : "does not exist"));
3329  return -1;
3330  }
3331 
3332  // Package name must be defined
3333  if (!pack || (pack && strlen(pack) <= 0)) {
3334  Error("MakeProjectParProofInf", "package name undefined!");
3335  return -1;
3336  }
3337 
3338  TString path;
3339 
3340  // The BUILD.sh first
3341  path.Form("%s/BUILD.sh", proofinf);
3342 #ifdef R__WINGCC
3343  FILE *f = fopen(path.Data(), "wb");
3344 #else
3345  FILE *f = fopen(path.Data(), "w");
3346 #endif
3347  if (!f) {
3348  Error("MakeProjectParProofInf", "cannot create file '%s' (errno: %d)",
3349  path.Data(), TSystem::GetErrno());
3350  return -1;
3351  }
3352 
3353  fprintf(f, "#! /bin/sh\n");
3354  fprintf(f, "# Build libEvent library.\n");
3355  fprintf(f, "\n");
3356  fprintf(f, "#\n");
3357  fprintf(f, "# The environment variables ROOTPROOFLITE and ROOTPROOFCLIENT can be used to\n");
3358  fprintf(f, "# adapt the script to the calling environment\n");
3359  fprintf(f, "#\n");
3360  fprintf(f, "# if test ! \"x$ROOTPROOFLITE\" = \"x\"; then\n");
3361  fprintf(f, "# echo \"event-BUILD: PROOF-Lite node (session has $ROOTPROOFLITE workers)\"\n");
3362  fprintf(f, "# elif test ! \"x$ROOTPROOFCLIENT\" = \"x\"; then\n");
3363  fprintf(f, "# echo \"event-BUILD: PROOF client\"\n");
3364  fprintf(f, "# else\n");
3365  fprintf(f, "# echo \"event-BUILD: standard PROOF node\"\n");
3366  fprintf(f, "# fi\n");
3367  fprintf(f, "\n");
3368  fprintf(f, "if [ \"\" = \"clean\" ]; then\n");
3369  fprintf(f, " make distclean\n");
3370  fprintf(f, " exit 0\n");
3371  fprintf(f, "fi\n");
3372  fprintf(f, "\n");
3373  fprintf(f, "make\n");
3374  fprintf(f, "rc=$?\n");
3375  fprintf(f, "echo \"rc=$?\"\n");
3376  fprintf(f, "if [ $? != \"0\" ] ; then\n");
3377  fprintf(f, " exit 1\n");
3378  fprintf(f, "fi\n");
3379  fprintf(f, "exit 0\n");
3380 
3381  // Close the file
3382  fclose(f);
3383 
3384  // Then SETUP.C
3385  path.Form("%s/SETUP.C", proofinf);
3386 #ifdef R__WINGCC
3387  f = fopen(path.Data(), "wb");
3388 #else
3389  f = fopen(path.Data(), "w");
3390 #endif
3391  if (!f) {
3392  Error("MakeProjectParProofInf", "cannot create file '%s' (errno: %d)",
3393  path.Data(), TSystem::GetErrno());
3394  return -1;
3395  }
3396 
3397  fprintf(f, "Int_t SETUP()\n");
3398  fprintf(f, "{\n");
3399  fprintf(f, "\n");
3400  fprintf(f, "//\n");
3401  fprintf(f, "// The environment variables ROOTPROOFLITE and ROOTPROOFCLIENT can be used to\n");
3402  fprintf(f, "// adapt the macro to the calling environment\n");
3403  fprintf(f, "//\n");
3404  fprintf(f, "// if (gSystem->Getenv(\"ROOTPROOFLITE\")) {\n");
3405  fprintf(f, "// Printf(\"event-SETUP: PROOF-Lite node (session has %%s workers)\",\n");
3406  fprintf(f, "// gSystem->Getenv(\"ROOTPROOFLITE\"));\n");
3407  fprintf(f, "// } else if (gSystem->Getenv(\"ROOTPROOFCLIENT\")) {\n");
3408  fprintf(f, "// Printf(\"event-SETUP: PROOF client\");\n");
3409  fprintf(f, "// } else {\n");
3410  fprintf(f, "// Printf(\"event-SETUP: standard PROOF node\");\n");
3411  fprintf(f, "// }\n");
3412  fprintf(f, "\n");
3413  fprintf(f, " if (gSystem->Load(\"lib%s\") == -1)\n", pack);
3414  fprintf(f, " return -1;\n");
3415  fprintf(f, " return 0;\n");
3416  fprintf(f, "}\n");
3417  fprintf(f, "\n");
3418 
3419  // Close the file
3420  fclose(f);
3421 
3422  // Done
3423  return 0;
3424 }
3425 
3426 ////////////////////////////////////////////////////////////////////////////////
3427 /// Read the list of StreamerInfo from this file.
3428 ///
3429 /// The key with name holding the list of TStreamerInfo objects is read.
3430 /// The corresponding TClass objects are updated.
3431 /// Note that this function is not called if the static member fgReadInfo is false.
3432 /// (see TFile::SetReadStreamerInfo)
3433 
3436  TList *list = GetStreamerInfoList();
3437  if (!list) {
3438  MakeZombie();
3439  return;
3440  }
3441 
3442  list->SetOwner(kFALSE);
3443 
3444  if (gDebug > 0) Info("ReadStreamerInfo", "called for file %s",GetName());
3445 
3446  TStreamerInfo *info;
3447 
3448  Int_t version = fVersion;
3449  if (version > 1000000) version -= 1000000;
3450  if (version < 53419 || (59900 < version && version < 59907)) {
3451  // We need to update the fCheckSum field of the TStreamerBase.
3452 
3453  // loop on all TStreamerInfo classes
3454  TObjLink *lnk = list->FirstLink();
3455  while (lnk) {
3456  info = (TStreamerInfo*)lnk->GetObject();
3457  if (info == 0 || info->IsA() != TStreamerInfo::Class()) {
3458  lnk = lnk->Next();
3459  continue;
3460  }
3461  TIter next(info->GetElements());
3462  TStreamerElement *element;
3463  while ((element = (TStreamerElement*) next())) {
3464  TStreamerBase *base = dynamic_cast<TStreamerBase*>(element);
3465  if (!base) continue;
3466  if (base->GetBaseCheckSum() != 0) continue;
3467  TStreamerInfo *baseinfo = (TStreamerInfo*)list->FindObject(base->GetName());
3468  if (baseinfo) {
3469  base->SetBaseCheckSum(baseinfo->GetCheckSum());
3470  }
3471  }
3472  lnk = lnk->Next();
3473  }
3474  }
3475 
3476  // loop on all TStreamerInfo classes
3477  for (int mode=0;mode<2; ++mode) {
3478  // In order for the collection proxy to be initialized properly, we need
3479  // to setup the TStreamerInfo for non-stl class before the stl classes.
3480  TObjLink *lnk = list->FirstLink();
3481  while (lnk) {
3482  info = (TStreamerInfo*)lnk->GetObject();
3483  if (info == 0) {
3484  lnk = lnk->Next();
3485  continue;
3486  }
3487  if (info->IsA() != TStreamerInfo::Class()) {
3488  if (mode==1) {
3489  TObject *obj = (TObject*)info;
3490  if (strcmp(obj->GetName(),"listOfRules")==0) {
3491 #if 0
3492  // Completely ignore the rules for now.
3493  TList *listOfRules = (TList*)obj;
3494  TObjLink *rulelnk = listOfRules->FirstLink();
3495  while (rulelnk) {
3496  TObjString *rule = (TObjString*)rulelnk->GetObject();
3497  TClass::AddRule( rule->String().Data() );
3498  rulelnk = rulelnk->Next();
3499  }
3500 #endif
3501  } else {
3502  Warning("ReadStreamerInfo","%s has a %s in the list of TStreamerInfo.", GetName(), info->IsA()->GetName());
3503  }
3504  info->SetBit(kCanDelete);
3505  }
3506  lnk = lnk->Next();
3507  continue;
3508  }
3509  // This is a quick way (instead of parsing the name) to see if this is
3510  // the description of an STL container.
3511  if (info->GetElements()==0) {
3512  Warning("ReadStreamerInfo","The StreamerInfo for %s does not have a list of elements.",info->GetName());
3513  lnk = lnk->Next();
3514  continue;
3515  }
3516  TObject *element = info->GetElements()->UncheckedAt(0);
3517  Bool_t isstl = element && strcmp("This",element->GetName())==0;
3518 
3519  if ( (!isstl && mode ==0) || (isstl && mode ==1) ) {
3520  // Skip the STL container the first time around
3521  // Skip the regular classes the second time around;
3522  info->BuildCheck(this);
3523  Int_t uid = info->GetNumber();
3524  Int_t asize = fClassIndex->GetSize();
3525  if (uid >= asize && uid <100000) fClassIndex->Set(2*asize);
3526  if (uid >= 0 && uid < fClassIndex->GetSize()) fClassIndex->fArray[uid] = 1;
3527  else {
3528  printf("ReadStreamerInfo, class:%s, illegal uid=%d\n",info->GetName(),uid);
3529  }
3530  if (gDebug > 0) printf(" -class: %s version: %d info read at slot %d\n",info->GetName(), info->GetClassVersion(),uid);
3531  }
3532  lnk = lnk->Next();
3533  }
3534  }
3535  fClassIndex->fArray[0] = 0;
3536  list->Clear(); //this will delete all TStreamerInfo objects with kCanDelete bit set
3537  delete list;
3538 }
3539 
3540 ////////////////////////////////////////////////////////////////////////////////
3541 /// Specify if the streamerinfos must be read at file opening.
3542 ///
3543 /// If fgReadInfo is true (default) TFile::ReadStreamerInfo is called
3544 /// when opening the file.
3545 /// It may be interesting to set fgReadInfo to false to speedup the file
3546 /// opening time or in case libraries containing classes referenced
3547 /// by the file have not yet been loaded.
3548 /// if fgReadInfo is false, one can still read the StreamerInfo with
3549 /// myfile.ReadStreamerInfo();
3550 
3551 void TFile::SetReadStreamerInfo(Bool_t readinfo)
3553  fgReadInfo = readinfo;
3554 }
3555 
3556 ////////////////////////////////////////////////////////////////////////////////
3557 /// If the streamerinfos are to be read at file opening.
3558 ///
3559 /// See TFile::SetReadStreamerInfo for more documentation.
3560 
3563  return fgReadInfo;
3564 }
3565 
3566 ////////////////////////////////////////////////////////////////////////////////
3567 /// Show the StreamerInfo of all classes written to this file.
3568 
3571  TList *list = GetStreamerInfoList();
3572  if (!list) return;
3573 
3574  list->ls();
3575  delete list;
3576 }
3577 
3578 ////////////////////////////////////////////////////////////////////////////////
3579 /// Check if the ProcessID pidd is already in the file,
3580 /// if not, add it and return the index number in the local file list.
3581 
3584  TProcessID *pid = pidd;
3585  if (!pid) pid = TProcessID::GetPID();
3586  TObjArray *pids = GetListOfProcessIDs();
3587  Int_t npids = GetNProcessIDs();
3588  for (Int_t i=0;i<npids;i++) {
3589  if (pids->At(i) == pid) return (UShort_t)i;
3590  }
3591 
3592  this->SetBit(TFile::kHasReferences);
3593  pids->AddAtAndExpand(pid,npids);
3594  pid->IncrementCount();
3595  char name[32];
3596  snprintf(name,32,"ProcessID%d",npids);
3597  this->WriteTObject(pid,name);
3598  this->IncrementProcessIDs();
3599  if (gDebug > 0) {
3600  Info("WriteProcessID", "name=%s, file=%s", name, GetName());
3601  }
3602  return (UShort_t)npids;
3603 }
3604 
3605 
3606 ////////////////////////////////////////////////////////////////////////////////
3607 /// Write the list of TStreamerInfo as a single object in this file
3608 /// The class Streamer description for all classes written to this file
3609 /// is saved. See class TStreamerInfo.
3610 
3613  //if (!gFile) return;
3614  if (!fWritable) return;
3615  if (!fClassIndex) return;
3616  if (fIsPcmFile) return; // No schema evolution for ROOT PCM files.
3617  if (fClassIndex->fArray[0] == 0
3618  && fSeekInfo != 0) {
3619  // No need to update the index if no new classes added to the file
3620  // but write once an empty StreamerInfo list to mark that there is no need
3621  // for StreamerInfos in this file.
3622  return;
3623  }
3624  if (gDebug > 0) Info("WriteStreamerInfo", "called for file %s",GetName());
3625 
3626  SafeDelete(fInfoCache);
3627 
3628  // build a temporary list with the marked files
3629  TIter next(gROOT->GetListOfStreamerInfo());
3630  TStreamerInfo *info;
3631  TList list;
3632  TList listOfRules;
3633  listOfRules.SetOwner(kTRUE);
3634  listOfRules.SetName("listOfRules");
3635  std::set<TClass*> classSet;
3636 
3637 
3638  while ((info = (TStreamerInfo*)next())) {
3639  Int_t uid = info->GetNumber();
3640  if (fClassIndex->fArray[uid]) {
3641  list.Add(info);
3642  if (gDebug > 0) printf(" -class: %s info number %d saved\n",info->GetName(),uid);
3643 
3644  // Add the IO customization rules to the list to be saved for the underlying
3645  // class but make sure to add them only once.
3646  TClass *clinfo = info->GetClass();
3647  if (clinfo && clinfo->GetSchemaRules()) {
3648  if ( classSet.find( clinfo ) == classSet.end() ) {
3649  if (gDebug > 0) printf(" -class: %s stored the I/O customization rules\n",info->GetName());
3650 
3651  TObjArrayIter it( clinfo->GetSchemaRules()->GetRules() );
3652  ROOT::TSchemaRule *rule;
3653  while( (rule = (ROOT::TSchemaRule*)it.Next()) ) {
3654  TObjString *obj = new TObjString();
3655  rule->AsString(obj->String());
3656  listOfRules.Add(obj);
3657  }
3658  classSet.insert(clinfo);
3659  }
3660  }
3661  }
3662  }
3663 
3664  // Write the StreamerInfo list even if it is empty.
3665  fClassIndex->fArray[0] = 2; //to prevent adding classes in TStreamerInfo::TagFile
3666 
3667  if (listOfRules.GetEntries()) {
3668  // Only add the list of rules if we have something to say.
3669  list.Add(&listOfRules);
3670  }
3671 
3672  // always write with compression on
3673  Int_t compress = fCompress;
3674  fCompress = 1;
3675 
3676  //free previous StreamerInfo record
3677  if (fSeekInfo) MakeFree(fSeekInfo,fSeekInfo+fNbytesInfo-1);
3678  //Create new key
3679  TKey key(&list,"StreamerInfo",GetBestBuffer(), this);
3680  fKeys->Remove(&key);
3681  fSeekInfo = key.GetSeekKey();
3682  fNbytesInfo = key.GetNbytes();
3683  SumBuffer(key.GetObjlen());
3684  key.WriteFile(0);
3685 
3686  fClassIndex->fArray[0] = 0;
3687  fCompress = compress;
3688 
3689  list.RemoveLast(); // remove the listOfRules.
3690 }
3691 
3692 ////////////////////////////////////////////////////////////////////////////////
3693 /// Open a file for reading through the file cache.
3694 ///
3695 /// The file will be downloaded to the cache and opened from there.
3696 /// If the download fails, it will be opened remotely.
3697 /// The file will be downloaded to the directory specified by SetCacheFileDir().
3698 
3699 TFile *TFile::OpenFromCache(const char *name, Option_t *, const char *ftitle,
3700  Int_t compress, Int_t netopt)
3701 {
3702  TFile *f = 0;
3703 
3704  if (fgCacheFileDir == "") {
3705  ::Warning("TFile::OpenFromCache",
3706  "you want to read through a cache, but you have no valid cache "
3707  "directory set - reading remotely");
3708  ::Info("TFile::OpenFromCache", "set cache directory using TFile::SetCacheFileDir()");
3709  } else {
3710  TUrl fileurl(name);
3711  TUrl tagurl;
3712 
3713  if ((!strcmp(fileurl.GetProtocol(), "file"))) {
3714  // it makes no sense to read local files through a file cache
3715  if (!fgCacheFileForce)
3716  ::Warning("TFile::OpenFromCache",
3717  "you want to read through a cache, but you are reading "
3718  "local files - CACHEREAD disabled");
3719  } else {
3720  // this is a remote file and worthwhile to be put into the local cache
3721  // now create cachepath to put it
3722  TString cachefilepath;
3723  TString cachefilepathbasedir;
3724  cachefilepath = fgCacheFileDir;
3725  cachefilepath += fileurl.GetFile();
3726  cachefilepathbasedir = gSystem->DirName(cachefilepath);
3727  if ((gSystem->mkdir(cachefilepathbasedir, kTRUE) < 0) &&
3728  (gSystem->AccessPathName(cachefilepathbasedir, kFileExists))) {
3729  ::Warning("TFile::OpenFromCache","you want to read through a cache, but I "
3730  "cannot create the directory %s - CACHEREAD disabled",
3731  cachefilepathbasedir.Data());
3732  } else {
3733  // check if this should be a zip file
3734  if (strlen(fileurl.GetAnchor())) {
3735  // remove the anchor and change the target name
3736  cachefilepath += "__";
3737  cachefilepath += fileurl.GetAnchor();
3738  fileurl.SetAnchor("");
3739  }
3740  if (strstr(name,"zip=")) {
3741  // filter out this option and change the target cache name
3742  TString urloptions = fileurl.GetOptions();
3743  TString newoptions;
3744  TObjArray *objOptions = urloptions.Tokenize("&");
3745  Int_t optioncount = 0;
3746  TString zipname;
3747  for (Int_t n = 0; n < objOptions->GetEntries(); n++) {
3748  TString loption = ((TObjString*)objOptions->At(n))->GetName();
3749  TObjArray *objTags = loption.Tokenize("=");
3750  if (objTags->GetEntries() == 2) {
3751  TString key = ((TObjString*)objTags->At(0))->GetName();
3752  TString value = ((TObjString*)objTags->At(1))->GetName();
3753  if (key.CompareTo("zip", TString::kIgnoreCase)) {
3754  if (optioncount!=0) {
3755  newoptions += "&";
3756  }
3757  newoptions += key;
3758  newoptions += "=";
3759  newoptions += value;
3760  ++optioncount;
3761  } else {
3762  zipname = value;
3763  }
3764  }
3765  delete objTags;
3766  }
3767  delete objOptions;
3768  fileurl.SetOptions(newoptions.Data());
3769  cachefilepath += "__";
3770  cachefilepath += zipname;
3771  fileurl.SetAnchor("");
3772  }
3773 
3774  Bool_t need2copy = kFALSE;
3775 
3776  // check if file is in the cache
3777  Long_t id;
3778  Long64_t size;
3779  Long_t flags;
3780  Long_t modtime;
3781  if (!gSystem->GetPathInfo(cachefilepath, &id, &size, &flags, &modtime)) {
3782  // file is in the cache
3783  if (!fgCacheFileDisconnected) {
3784  char cacheblock[256];
3785  char remotblock[256];
3786  // check the remote file for it's size and compare some magic bytes
3787  TString cfurl;
3788  cfurl = cachefilepath;
3789  cfurl += "?filetype=raw";
3790  TUrl rurl(name);
3791  TString ropt = rurl.GetOptions();
3792  ropt += "&filetype=raw";
3793  rurl.SetOptions(ropt);
3794 
3795  Bool_t forcedcache = fgCacheFileForce;
3796  fgCacheFileForce = kFALSE;
3797 
3798  TFile *cachefile = TFile::Open(cfurl, "READ");
3799  TFile *remotfile = TFile::Open(rurl.GetUrl(), "READ");
3800 
3801  fgCacheFileForce = forcedcache;
3802 
3803  if (!cachefile) {
3804  need2copy = kTRUE;
3805  ::Error("TFile::OpenFromCache",
3806  "cannot open the cache file to check cache consistency");
3807  return 0;
3808  }
3809 
3810  if (!remotfile) {
3811  ::Error("TFile::OpenFromCache",
3812  "cannot open the remote file to check cache consistency");
3813  return 0;
3814  }
3815 
3816  cachefile->Seek(0);
3817  remotfile->Seek(0);
3818 
3819  if ((!cachefile->ReadBuffer(cacheblock,256)) &&
3820  (!remotfile->ReadBuffer(remotblock,256))) {
3821  if (memcmp(cacheblock, remotblock, 256)) {
3822  ::Warning("TFile::OpenFromCache", "the header of the cache file "
3823  "differs from the remote file - forcing an update");
3824  need2copy = kTRUE;
3825  }
3826  } else {
3827  ::Warning("TFile::OpenFromCache", "the header of the cache and/or "
3828  "remote file are not readable - forcing an update");
3829  need2copy = kTRUE;
3830  }
3831 
3832  delete remotfile;
3833  delete cachefile;
3834  }
3835  } else {
3836  need2copy = kTRUE;
3837  }
3838 
3839  // try to fetch the file (disable now the forced caching)
3840  Bool_t forcedcache = fgCacheFileForce;
3841  fgCacheFileForce = kFALSE;
3842  if (need2copy && !TFile::Cp(name, cachefilepath)) {
3843  ::Warning("TFile::OpenFromCache", "you want to read through a cache, but I "
3844  "cannot make a cache copy of %s - CACHEREAD disabled",
3845  cachefilepathbasedir.Data());
3846  fgCacheFileForce = forcedcache;
3847  if (fgOpenTimeout != 0)
3848  return 0;
3849  } else {
3850  fgCacheFileForce = forcedcache;
3851  ::Info("TFile::OpenFromCache", "using local cache copy of %s [%s]",
3852  name, cachefilepath.Data());
3853  // finally we have the file and can open it locally
3854  fileurl.SetProtocol("file");
3855  fileurl.SetFile(cachefilepath);
3856 
3857  tagurl = fileurl;
3858  TString tagfile;
3859  tagfile = cachefilepath;
3860  tagfile += ".ROOT.cachefile";
3861  tagurl.SetFile(tagfile);
3862  // we symlink this file as a ROOT cached file
3863  gSystem->Symlink(gSystem->BaseName(cachefilepath), tagfile);
3864  return TFile::Open(fileurl.GetUrl(), "READ", ftitle, compress, netopt);
3865  }
3866  }
3867  }
3868  }
3869 
3870  // Failed
3871  return f;
3872 }
3873 
3874 ////////////////////////////////////////////////////////////////////////////////
3875 /// Create / open a file
3876 ///
3877 /// The type of the file can be either a
3878 /// TFile, TNetFile, TWebFile or any TFile derived class for which an
3879 /// plugin library handler has been registered with the plugin manager
3880 /// (for the plugin manager see the TPluginManager class). The returned
3881 /// type of TFile depends on the file name specified by 'url'.
3882 /// If 'url' is a '|'-separated list of file URLs, the 'URLs' are tried
3883 /// sequentially in the specified order until a successful open.
3884 /// If the file starts with "root:", "roots:" or "rootk:" a TNetFile object
3885 /// will be returned, with "http:" a TWebFile, with "file:" a local TFile,
3886 /// etc. (see the list of TFile plugin handlers in $ROOTSYS/etc/system.rootrc
3887 /// for regular expressions that will be checked) and as last a local file will
3888 /// be tried.
3889 /// Before opening a file via TNetFile a check is made to see if the URL
3890 /// specifies a local file. If that is the case the file will be opened
3891 /// via a normal TFile. To force the opening of a local file via a
3892 /// TNetFile use either TNetFile directly or specify as host "localhost".
3893 /// The netopt argument is only used by TNetFile. For the meaning of the
3894 /// options and other arguments see the constructors of the individual
3895 /// file classes. In case of error returns 0.
3896 ///
3897 /// For TFile implementations supporting asynchronous file open, see
3898 /// TFile::AsyncOpen(...), it is possible to request a timeout with the
3899 /// option <b>TIMEOUT=<secs></b>: the timeout must be specified in seconds and
3900 /// it will be internally checked with granularity of one millisec.
3901 /// For remote files there is the option: <b>CACHEREAD</b> opens an existing
3902 /// file for reading through the file cache. The file will be downloaded to
3903 /// the cache and opened from there. If the download fails, it will be opened remotely.
3904 /// The file will be downloaded to the directory specified by SetCacheFileDir().
3905 ///
3906 /// *The caller is responsible for deleting the pointer.*
3907 
3908 TFile *TFile::Open(const char *url, Option_t *options, const char *ftitle,
3909  Int_t compress, Int_t netopt)
3910 {
3911  TPluginHandler *h;
3912  TFile *f = 0;
3913  EFileType type = kFile;
3914 
3915  // Check input
3916  if (!url || strlen(url) <= 0) {
3917  ::Error("TFile::Open", "no url specified");
3918  return f;
3919  }
3920 
3921  TString expandedUrl(url);
3922  gSystem->ExpandPathName(expandedUrl);
3923 
3924  // If a timeout has been specified extract the value and try to apply it (it requires
3925  // support for asynchronous open, though; the following is completely transparent if
3926  // such support if not available for the required protocol)
3927  TString opts(options);
3928  Int_t ito = opts.Index("TIMEOUT=");
3929  if (ito != kNPOS) {
3930  TString sto = opts(ito + strlen("TIMEOUT="), opts.Length());
3931  while (!(sto.IsDigit()) && !(sto.IsNull())) { sto.Remove(sto.Length()-1,1); }
3932  if (!(sto.IsNull())) {
3933  // Timeout in millisecs
3934  Int_t toms = sto.Atoi() * 1000;
3935  if (gDebug > 0) ::Info("TFile::Open", "timeout of %d millisec requested", toms);
3936  // Remove from the options field
3937  sto.Insert(0, "TIMEOUT=");
3938  opts.ReplaceAll(sto, "");
3939  // Asynchrounous open
3940  TFileOpenHandle *fh = TFile::AsyncOpen(expandedUrl, opts, ftitle, compress, netopt);
3941  // Check the result in steps of 1 millisec
3943  aos = TFile::GetAsyncOpenStatus(fh);
3944  Int_t xtms = toms;
3945  while (aos != TFile::kAOSNotAsync && aos == TFile::kAOSInProgress && xtms > 0) {
3946  gSystem->Sleep(1);
3947  xtms -= 1;
3948  aos = TFile::GetAsyncOpenStatus(fh);
3949  }
3950  if (aos == TFile::kAOSNotAsync || aos == TFile::kAOSSuccess) {
3951  // Do open the file now
3952  f = TFile::Open(fh);
3953  if (gDebug > 0) {
3954  if (aos == TFile::kAOSSuccess)
3955  ::Info("TFile::Open", "waited %d millisec for asynchronous open", toms - xtms);
3956  else
3957  ::Info("TFile::Open", "timeout option not supported (requires asynchronous"
3958  " open support)");
3959  }
3960  } else {
3961  if (xtms <= 0)
3962  ::Error("TFile::Open", "timeout expired while opening '%s'", expandedUrl.Data());
3963  // Cleanup the request
3964  SafeDelete(fh);
3965  }
3966  // Done
3967  return f;
3968  } else {
3969  ::Warning("TFile::Open", "incomplete 'TIMEOUT=' option specification - ignored");
3970  opts.ReplaceAll("TIMEOUT=", "");
3971  }
3972  }
3973 
3974  // We will use this from now on
3975  const char *option = opts;
3976 
3977  // Many URLs? Redirect output and print errors in case of global failure
3978  TString namelist(expandedUrl);
3979  Ssiz_t ip = namelist.Index("|");
3980  Bool_t rediroutput = (ip != kNPOS &&
3981  ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
3982  RedirectHandle_t rh;
3983  if (rediroutput) {
3984  TString outf = ".TFileOpen_";
3985  FILE *fout = gSystem->TempFileName(outf);
3986  if (fout) {
3987  fclose(fout);
3988  gSystem->RedirectOutput(outf, "w", &rh);
3989  }
3990  }
3991 
3992  // Try sequentially all names in 'names'
3993  TString name, n;
3994  Ssiz_t from = 0;
3995  while (namelist.Tokenize(n, from, "|") && !f) {
3996 
3997  // check if we read through a file cache
3998  if (!strcasecmp(option, "CACHEREAD") ||
3999  ((!strcasecmp(option,"READ") || !option[0]) && fgCacheFileForce)) {
4000  // Try opening the file from the cache
4001  if ((f = TFile::OpenFromCache(n, option, ftitle, compress, netopt)))
4002  return f;
4003  }
4004 
4005  IncrementFileCounter();
4006 
4007  // change names from e.g. /castor/cern.ch/alice/file.root to
4008  // castor:/castor/cern.ch/alice/file.root as recognized by the plugin manager
4009  TUrl urlname(n, kTRUE);
4010  name = urlname.GetUrl();
4011  // Check first if a pending async open request matches this one
4012  if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4013  TIter nxr(fgAsyncOpenRequests);
4014  TFileOpenHandle *fh = 0;
4015  while ((fh = (TFileOpenHandle *)nxr()))
4016  if (fh->Matches(name))
4017  return TFile::Open(fh);
4018  }
4019 
4020  TString urlOptions(urlname.GetOptions());
4021  if (urlOptions.BeginsWith("pmerge") || urlOptions.Contains("&pmerge") || urlOptions.Contains(" pmerge")) {
4022  type = kMerge;
4023 
4024  // Pass the full name including the url options:
4025  f = (TFile*) gROOT->ProcessLineFast(TString::Format("new TParallelMergingFile(\"%s\",\"%s\",\"%s\",%d)",n.Data(),option,ftitle,compress));
4026 
4027  } else {
4028  // Resolve the file type; this also adjusts names
4029  TString lfname = gEnv->GetValue("Path.Localroot", "");
4030  type = GetType(name, option, &lfname);
4031 
4032  if (type == kLocal) {
4033 
4034  // Local files
4035  if (lfname.IsNull()) {
4036  urlname.SetHost("");
4037  urlname.SetProtocol("file");
4038  lfname = urlname.GetUrl();
4039  }
4040  f = new TFile(lfname.Data(), option, ftitle, compress);
4041 
4042  } else if (type == kNet) {
4043 
4044  // Network files
4045  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
4046  if (h->LoadPlugin() == -1)
4047  return 0;
4048  f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
4049  }
4050 
4051  } else if (type == kWeb) {
4052 
4053  // Web files
4054  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
4055  if (h->LoadPlugin() == -1)
4056  return 0;
4057  f = (TFile*) h->ExecPlugin(2, name.Data(), option);
4058  }
4059 
4060  } else if (type == kFile) {
4061 
4062  // 'file:' protocol
4063  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4064  h->LoadPlugin() == 0) {
4065  name.ReplaceAll("file:", "");
4066  f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
4067  } else
4068  f = new TFile(name.Data(), option, ftitle, compress);
4069 
4070  } else {
4071 
4072  // no recognized specification: try the plugin manager
4073  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name.Data()))) {
4074  if (h->LoadPlugin() == -1)
4075  return 0;
4076  TClass *cl = TClass::GetClass(h->GetClass());
4077  if (cl && cl->InheritsFrom("TNetFile"))
4078  f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
4079  else
4080  f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
4081  } else {
4082  // Just try to open it locally but via TFile::Open, so that we pick-up the correct
4083  // plug-in in the case file name contains information about a special backend (e.g.
4084  // "srm://srm.cern.ch//castor/cern.ch/grid/..." should be considered a castor file
4085  // /castor/cern.ch/grid/...").
4086  f = TFile::Open(urlname.GetFileAndOptions(), option, ftitle, compress);
4087  }
4088  }
4089  }
4090 
4091  if (f && f->IsZombie()) {
4092  TString newUrl = f->GetNewUrl();
4093  delete f;
4094  if( newUrl.Length() && gEnv->GetValue("TFile.CrossProtocolRedirects", 1) )
4095  f = TFile::Open( newUrl, option, ftitle, compress );
4096  else
4097  f = 0;
4098  }
4099  }
4100 
4101  if (rediroutput) {
4102  // Restore output to stdout
4103  gSystem->RedirectOutput(0, "", &rh);
4104  // If we failed print error messages
4105  if (!f)
4106  gSystem->ShowOutput(&rh);
4107  // Remove the file
4108  gSystem->Unlink(rh.fFile);
4109  }
4110 
4111  // if the file is writable, non local, and not opened in raw mode
4112  // we create a default write cache of 512 KBytes
4113  if (type != kLocal && type != kFile &&
4114  f && f->IsWritable() && !f->IsRaw()) {
4115  new TFileCacheWrite(f, 1);
4116  }
4117 
4118  return f;
4119 }
4120 
4121 ////////////////////////////////////////////////////////////////////////////////
4122 /// Submit an asynchronous open request.
4123 
4124 /// See TFile::Open(const char *, ...) for an
4125 /// explanation of the arguments. A handler is returned which is to be passed
4126 /// to TFile::Open(TFileOpenHandle *) to get the real TFile instance once
4127 /// the file is open.
4128 /// This call never blocks and it is provided to allow parallel submission
4129 /// of file opening operations expected to take a long time.
4130 /// TFile::Open(TFileOpenHandle *) may block if the file is not yet ready.
4131 /// The sequence
4132 ///
4133 /// TFile::Open(TFile::AsyncOpen(const char *, ...))
4134 ///
4135 /// is equivalent to
4136 ///
4137 /// TFile::Open(const char *, ...)
4138 ///
4139 /// To be effective, the underlying TFile implementation must be able to
4140 /// support asynchronous open functionality. Currently, only TXNetFile
4141 /// supports it. If the functionality is not implemented, this call acts
4142 /// transparently by returning an handle with the arguments for the
4143 /// standard synchronous open run by TFile::Open(TFileOpenHandle *).
4144 /// The retuned handle will be adopted by TFile after opening completion
4145 /// in TFile::Open(TFileOpenHandle *); if opening is not finalized the
4146 /// handle must be deleted by the caller.
4147 
4148 TFileOpenHandle *TFile::AsyncOpen(const char *url, Option_t *option,
4149  const char *ftitle, Int_t compress,
4150  Int_t netopt)
4151 {
4152  TFileOpenHandle *fh = 0;
4153  TPluginHandler *h;
4154  TFile *f = 0;
4155  Bool_t notfound = kTRUE;
4156 
4157  // Check input
4158  if (!url || strlen(url) <= 0) {
4159  ::Error("TFile::AsyncOpen", "no url specified");
4160  return fh;
4161  }
4162 
4163  // Many URLs? Redirect output and print errors in case of global failure
4164  TString namelist(url);
4165  gSystem->ExpandPathName(namelist);
4166  Ssiz_t ip = namelist.Index("|");
4167  Bool_t rediroutput = (ip != kNPOS &&
4168  ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
4169  RedirectHandle_t rh;
4170  if (rediroutput) {
4171  TString outf = ".TFileAsyncOpen_";
4172  FILE *fout = gSystem->TempFileName(outf);
4173  if (fout) {
4174  fclose(fout);
4175  gSystem->RedirectOutput(outf, "w", &rh);
4176  }
4177  }
4178 
4179  // Try sequentially all names in 'names'
4180  TString name, n;
4181  Ssiz_t from = 0;
4182  while (namelist.Tokenize(n, from, "|") && !f) {
4183 
4184  // change names from e.g. /castor/cern.ch/alice/file.root to
4185  // castor:/castor/cern.ch/alice/file.root as recognized by the plugin manager
4186  TUrl urlname(n, kTRUE);
4187  name = urlname.GetUrl();
4188 
4189  // Resolve the file type; this also adjusts names
4190  EFileType type = GetType(name, option);
4191 
4192  // Here we send the asynchronous request if the functionality is implemented
4193  if (type == kNet) {
4194  // Network files
4195  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4196  (!strcmp(h->GetClass(),"TXNetFile") || !strcmp(h->GetClass(),"TNetXNGFile"))
4197  && h->LoadPlugin() == 0) {
4198  f = (TFile*) h->ExecPlugin(6, name.Data(), option, ftitle, compress, netopt, kTRUE);
4199  notfound = kFALSE;
4200  }
4201  }
4202  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4203  !strcmp(h->GetClass(),"TAlienFile") && h->LoadPlugin() == 0) {
4204  f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, kTRUE);
4205  notfound = kFALSE;
4206  }
4207 
4208  }
4209 
4210  if (rediroutput) {
4211  // Restore output to stdout
4212  gSystem->RedirectOutput(0, "", &rh);
4213  // If we failed print error messages
4214  if (!notfound && !f)
4215  gSystem->ShowOutput(&rh);
4216  // Remove the file
4217  gSystem->Unlink(rh.fFile);
4218  }
4219 
4220  // Make sure that no error occurred
4221  if (notfound) {
4222  SafeDelete(f);
4223  // Save the arguments in the handler, so that a standard open can be
4224  // attempted later on
4225  fh = new TFileOpenHandle(name, option, ftitle, compress, netopt);
4226  } else if (f) {
4227  // Fill the opaque handler to be use to attach the file later on
4228  fh = new TFileOpenHandle(f);
4229  }
4230 
4231  // Record this request
4232  if (fh) {
4233  // Create the lst, if not done already
4234  if (!fgAsyncOpenRequests)
4235  fgAsyncOpenRequests = new TList;
4236  fgAsyncOpenRequests->Add(fh);
4237  }
4238 
4239  // We are done
4240  return fh;
4241 }
4242 
4243 ////////////////////////////////////////////////////////////////////////////////
4244 /// Waits for the completion of an asynchronous open request.
4245 ///
4246 /// Returns the pointer to the associated TFile, transferring ownership of the
4247 /// handle to the TFile instance.
4248 
4251  TFile *f = 0;
4252 
4253  // Note that the request may have failed
4254  if (fh && fgAsyncOpenRequests) {
4255  // Remove it from the pending list: we need to do it at this level to avoid
4256  // recursive calls in the standard TFile::Open
4257  fgAsyncOpenRequests->Remove(fh);
4258  // Was asynchronous open functionality implemented?
4259  if ((f = fh->GetFile()) && !(f->IsZombie())) {
4260  // Yes: wait for the completion of the open phase, if needed
4261  Bool_t cr = (!strcmp(f->GetOption(),"CREATE") ||
4262  !strcmp(f->GetOption(),"RECREATE") ||
4263  !strcmp(f->GetOption(),"NEW")) ? kTRUE : kFALSE;
4264  f->Init(cr);
4265  } else {
4266  // No: process a standard open
4267  f = TFile::Open(fh->GetName(), fh->GetOpt(), fh->GetTitle(),
4268  fh->GetCompress(), fh->GetNetOpt());
4269  }
4270 
4271  // Adopt the handle instance in the TFile instance so that it gets
4272  // automatically cleaned up
4273  if (f) f->fAsyncHandle = fh;
4274  }
4275 
4276  // We are done
4277  return f;
4278 }
4279 
4280 ////////////////////////////////////////////////////////////////////////////////
4281 /// Interface to system open. All arguments like in POSIX open().
4282 
4283 Int_t TFile::SysOpen(const char *pathname, Int_t flags, UInt_t mode)
4285 #if defined(R__WINGCC)
4286  // ALWAYS use binary mode - even cygwin text should be in unix format
4287  // although this is posix default it has to be set explicitly
4288  return ::open(pathname, flags | O_BINARY, mode);
4289 #elif defined(R__SEEK64)
4290  return ::open64(pathname, flags, mode);
4291 #else
4292  return ::open(pathname, flags, mode);
4293 #endif
4294 }
4295 
4296 ////////////////////////////////////////////////////////////////////////////////
4297 /// Interface to system close. All arguments like in POSIX close().
4298 
4301  if (fd < 0) return 0;
4302  return ::close(fd);
4303 }
4304 
4305 ////////////////////////////////////////////////////////////////////////////////
4306 /// Interface to system read. All arguments like in POSIX read().
4307 
4308 Int_t TFile::SysRead(Int_t fd, void *buf, Int_t len)
4310  return ::read(fd, buf, len);
4311 }
4312 
4313 ////////////////////////////////////////////////////////////////////////////////
4314 /// Interface to system write. All arguments like in POSIX write().
4315 
4316 Int_t TFile::SysWrite(Int_t fd, const void *buf, Int_t len)
4318  return ::write(fd, buf, len);
4319 }
4320 ////////////////////////////////////////////////////////////////////////////////
4321 /// Interface to system lseek.
4322 ///
4323 /// All arguments like in POSIX lseek()
4324 /// except that the offset and return value are of a type which are
4325 /// able to handle 64 bit file systems.
4326 
4327 Long64_t TFile::SysSeek(Int_t fd, Long64_t offset, Int_t whence)
4329 #if defined (R__SEEK64)
4330  return ::lseek64(fd, offset, whence);
4331 #elif defined(WIN32)
4332  return ::_lseeki64(fd, offset, whence);
4333 #else
4334  return ::lseek(fd, offset, whence);
4335 #endif
4336 }
4337 
4338 ////////////////////////////////////////////////////////////////////////////////
4339 /// Return file stat information.
4340 ///
4341 /// The interface and return value is
4342 /// identical to TSystem::GetPathInfo(). The function returns 0 in
4343 /// case of success and 1 if the file could not be stat'ed.
4344 
4345 Int_t TFile::SysStat(Int_t, Long_t *id, Long64_t *size, Long_t *flags,
4346  Long_t *modtime)
4347 {
4348  return gSystem->GetPathInfo(fRealName, id, size, flags, modtime);
4349 }
4350 
4351 ////////////////////////////////////////////////////////////////////////////////
4352 /// Interface to system fsync. All arguments like in POSIX fsync().
4353 
4356  if (TestBit(kDevNull)) return 0;
4357 
4358 #ifndef WIN32
4359  return ::fsync(fd);
4360 #else
4361  return ::_commit(fd);
4362 #endif
4363 }
4364 
4365 ////////////////////////////////////////////////////////////////////////////////
4366 /// Return the total number of bytes written so far to the file.
4367 
4370  return fCacheWrite ? fCacheWrite->GetBytesInCache() + fBytesWrite : fBytesWrite;
4371 }
4372 
4373 ////////////////////////////////////////////////////////////////////////////////
4374 /// Static function returning the total number of bytes read from all files.
4375 
4378  return fgBytesRead;
4379 }
4380 
4381 ////////////////////////////////////////////////////////////////////////////////
4382 /// Static function returning the total number of bytes written to all files.
4383 /// Does not take into account what might still be in the write caches.
4384 
4387  return fgBytesWrite;
4388 }
4389 
4390 ////////////////////////////////////////////////////////////////////////////////
4391 /// Static function returning the total number of read calls from all files.
4392 
4395  return fgReadCalls;
4396 }
4397 
4398 ////////////////////////////////////////////////////////////////////////////////
4399 /// Static function returning the readahead buffer size.
4400 
4403  return fgReadaheadSize;
4404 }
4405 
4406 //______________________________________________________________________________
4407 void TFile::SetReadaheadSize(Int_t bytes) { fgReadaheadSize = bytes; }
4409 //______________________________________________________________________________
4410 void TFile::SetFileBytesRead(Long64_t bytes) { fgBytesRead = bytes; }
4412 //______________________________________________________________________________
4413 void TFile::SetFileBytesWritten(Long64_t bytes) { fgBytesWrite = bytes; }
4415 //______________________________________________________________________________
4416 void TFile::SetFileReadCalls(Int_t readcalls) { fgReadCalls = readcalls; }
4418 //______________________________________________________________________________
4419 Long64_t TFile::GetFileCounter() { return fgFileCounter; }
4421 //______________________________________________________________________________
4422 void TFile::IncrementFileCounter() { fgFileCounter++; }
4424 ////////////////////////////////////////////////////////////////////////////////
4425 /// Sets the directory where to locally stage/cache remote files.
4426 /// If the directory is not writable by us return kFALSE.
4427 
4428 Bool_t TFile::SetCacheFileDir(const char *cachedir, Bool_t operatedisconnected,
4429  Bool_t forcecacheread )
4430 {
4431  TString cached = cachedir;
4432  if (!cached.EndsWith("/"))
4433  cached += "/";
4434 
4435  if (gSystem->AccessPathName(cached, kFileExists)) {
4436  // try to create it
4437  gSystem->mkdir(cached, kTRUE);
4438  if (gSystem->AccessPathName(cached, kFileExists)) {
4439  ::Error("TFile::SetCacheFileDir", "no sufficient permissions on cache directory %s or cannot create it", cachedir);
4440  fgCacheFileDir = "";
4441  return kFALSE;
4442  }
4443  gSystem->Chmod(cached, 0700);
4444  }
4445  if (gSystem->AccessPathName(cached, kWritePermission))
4446  gSystem->Chmod(cached, 0700);
4447  fgCacheFileDir = cached;
4448  fgCacheFileDisconnected = operatedisconnected;
4449  fgCacheFileForce = forcecacheread;
4450  return kTRUE;
4451 }
4452 
4453 ////////////////////////////////////////////////////////////////////////////////
4454 /// Get the directory where to locally stage/cache remote files.
4455 
4456 const char *TFile::GetCacheFileDir()
4458  return fgCacheFileDir;
4459 }
4460 
4461 ////////////////////////////////////////////////////////////////////////////////
4462 /// Try to shrink the cache to the desired size.
4463 ///
4464 /// With the clenupinterval you can specify the minimum amount of time after
4465 /// the previous cleanup before the cleanup operation is repeated in
4466 /// the cache directory
4467 
4468 Bool_t TFile::ShrinkCacheFileDir(Long64_t shrinksize, Long_t cleanupinterval)
4470  if (fgCacheFileDir == "") {
4471  return kFALSE;
4472  }
4473 
4474  // check the last clean-up in the cache
4475  Long_t id;
4476  Long64_t size;
4477  Long_t flags;
4478  Long_t modtime;
4479 
4480  TString cachetagfile = fgCacheFileDir;
4481  cachetagfile += ".tag.ROOT.cache";
4482  if (!gSystem->GetPathInfo(cachetagfile, &id, &size, &flags, &modtime)) {
4483  // check the time passed since last cache cleanup
4484  Long_t lastcleanuptime = ((Long_t)time(0) - modtime);
4485  if (lastcleanuptime < cleanupinterval) {
4486  ::Info("TFile::ShrinkCacheFileDir", "clean-up is skipped - last cleanup %lu seconds ago - you requested %lu", lastcleanuptime, cleanupinterval);
4487  return kTRUE;
4488  }
4489  }
4490 
4491  // (re-)create the cache tag file
4492  cachetagfile += "?filetype=raw";
4493  TFile *tagfile = 0;
4494 
4495  if (!(tagfile = TFile::Open(cachetagfile, "RECREATE"))) {
4496  ::Error("TFile::ShrinkCacheFileDir", "cannot create the cache tag file %s", cachetagfile.Data());
4497  return kFALSE;
4498  }
4499 
4500  // the shortest garbage collector in the world - one long line of PERL - unlinks files only,
4501  // if there is a symbolic link with '.ROOT.cachefile' for safety ;-)
4502 
4503  TString cmd;
4504 #if defined(R__WIN32)
4505  cmd = "echo <TFile::ShrinkCacheFileDir>: cleanup to be implemented";
4506 #elif defined(R__MACOSX)
4507  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);
4508 #else
4509  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);
4510 #endif
4511 
4512  tagfile->WriteBuffer(cmd, 4096);
4513  delete tagfile;
4514 
4515  if ((gSystem->Exec(cmd)) != 0) {
4516  ::Error("TFile::ShrinkCacheFileDir", "error executing clean-up script");
4517  return kFALSE;
4518  }
4519 
4520  return kTRUE;
4521 }
4522 
4523 ////////////////////////////////////////////////////////////////////////////////
4524 /// Sets open timeout time (in ms). Returns previous timeout value.
4525 
4528  UInt_t to = fgOpenTimeout;
4529  fgOpenTimeout = timeout;
4530  return to;
4531 }
4532 
4533 ////////////////////////////////////////////////////////////////////////////////
4534 /// Returns open timeout (in ms).
4535 
4538  return fgOpenTimeout;
4539 }
4540 
4541 ////////////////////////////////////////////////////////////////////////////////
4542 /// Sets only staged flag. Returns previous value of flag.
4543 /// When true we check before opening the file if it is staged, if not,
4544 /// the open fails.
4545 
4548  Bool_t f = fgOnlyStaged;
4549  fgOnlyStaged = onlystaged;
4550  return f;
4551 }
4552 
4553 ////////////////////////////////////////////////////////////////////////////////
4554 /// Returns staged only flag.
4555 
4558  return fgOnlyStaged;
4559 }
4560 
4561 ////////////////////////////////////////////////////////////////////////////////
4562 /// Return kTRUE if 'url' matches the coordinates of this file.
4563 ///
4564 /// The check is implementation dependent and may need to be overload
4565 /// by each TFile implementation relying on this check.
4566 /// The default implementation checks the file name only.
4567 
4568 Bool_t TFile::Matches(const char *url)
4570  // Check the full URL, including port and FQDN.
4571  TUrl u(url);
4572 
4573  // Check
4574  if (!strcmp(u.GetFile(), fUrl.GetFile())) {
4575  // Check ports
4576  if (u.GetPort() == fUrl.GetPort()) {
4577  if (!strcmp(u.GetHostFQDN(), fUrl.GetHostFQDN())) {
4578  // Ok, coordinates match
4579  return kTRUE;
4580  }
4581  }
4582  }
4583 
4584  // Default is not matching
4585  return kFALSE;
4586 }
4587 
4588 ////////////////////////////////////////////////////////////////////////////////
4589 /// Return kTRUE if this async request matches the open request
4590 /// specified by 'url'
4591 
4592 Bool_t TFileOpenHandle::Matches(const char *url)
4594  if (fFile) {
4595  return fFile->Matches(url);
4596  } else if (fName.Length() > 0){
4597  // Deep check of URLs
4598  TUrl u(url);
4599  TUrl uref(fName);
4600  if (!strcmp(u.GetFile(), uref.GetFile())) {
4601  // Check ports
4602  if (u.GetPort() == uref.GetPort()) {
4603  // Check also the host name
4604  if (!strcmp(u.GetHostFQDN(), uref.GetHostFQDN())) {
4605  // Ok, coordinates match
4606  return kTRUE;
4607  }
4608  }
4609  }
4610  }
4611 
4612  // Default is not matching
4613  return kFALSE;
4614 }
4615 
4616 ////////////////////////////////////////////////////////////////////////////////
4617 /// Resolve the file type as a function of the protocol field in 'name'
4618 ///
4619 /// If defined, the string 'prefix' is added when testing the locality of
4620 /// a 'name' with network-like structure (i.e. root://host//path); if the file
4621 /// is local, on return 'prefix' will contain the actual local path of the file.
4622 
4623 TFile::EFileType TFile::GetType(const char *name, Option_t *option, TString *prefix)
4626 
4627  TPMERegexp re("^(root|xroot).*", "i");
4628  if (re.Match(name)) {
4629  //
4630  // Should be a network file ...
4631  type = kNet;
4632  // ... but make sure that is not local or that a remote-like connection
4633  // is forced. Treat it as local if:
4634  // i) the url points to the localhost, the file will be opened in
4635  // readonly mode and the current user has read access;
4636  // ii) the specified user is equal to the current user then open local
4637  // TFile.
4638  Bool_t localFile = kFALSE;
4639  TUrl url(name);
4640  //
4641  // Check whether we should try to optimize for local files
4642  Bool_t forceRemote = gEnv->GetValue("Path.ForceRemote", 0);
4643  forceRemote = (forceRemote) ? kTRUE : gEnv->GetValue("TFile.ForceRemote", 0);
4644  TString opts = url.GetOptions();
4645  if (opts.Contains("remote=1"))
4646  forceRemote = kTRUE;
4647  else if (opts.Contains("remote=0"))
4648  forceRemote = kFALSE;
4649  if (!forceRemote) {
4650  // Generic locality test
4651  localFile = gSystem->IsPathLocal(name);
4652  if (localFile) {
4653  // Local path including the prefix
4654  const char *fname = url.GetFileAndOptions();
4655  TString lfname;
4656  if (fname[0] == '/') {
4657  if (prefix)
4658  lfname.Form("%s%s", prefix->Data(), fname);
4659  else
4660  lfname = fname;
4661  } else if (fname[0] == '~' || fname[0] == '$') {
4662  lfname = fname;
4663  } else {
4664  lfname.Form("%s/%s", gSystem->HomeDirectory(), fname);
4665  }
4666  // If option "READ" test existence and access
4667  TString opt = option;
4668  Bool_t read = (opt.IsNull() ||
4669  !opt.CompareTo("READ", TString::kIgnoreCase)) ? kTRUE : kFALSE;
4670  if (read) {
4671  char *fn;
4672  if ((fn = gSystem->ExpandPathName(TUrl(lfname).GetFile()))) {
4674  localFile = kFALSE;
4675  delete [] fn;
4676  }
4677  }
4678  // Return full local path if requested (and if the case)
4679  if (localFile && prefix)
4680  *prefix = lfname;
4681  }
4682  }
4683  //
4684  // Adjust the type according to findings
4685  type = (localFile) ? kLocal : type;
4686  } else if (TPMERegexp("^(http[s]?|s3http[s]?|[a]?s3|gs|gshttp[s]?){1}:", "i").Match(name)) {
4687  //
4688  // Web file
4689  type = kWeb;
4690  } else if (!strncmp(name, "file:", 5)) {
4691  //
4692  // 'file' protocol
4693  type = kFile;
4694  }
4695  // We are done
4696  return type;
4697 }
4698 
4699 ////////////////////////////////////////////////////////////////////////////////
4700 /// Get status of the async open request related to 'name'.
4701 
4704  // Check the list of pending async open requests
4705  if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4706  TIter nxr(fgAsyncOpenRequests);
4707  TFileOpenHandle *fh = 0;
4708  while ((fh = (TFileOpenHandle *)nxr()))
4709  if (fh->Matches(name))
4710  return TFile::GetAsyncOpenStatus(fh);
4711  }
4712 
4713  // Check also the list of files open
4715  TSeqCollection *of = gROOT->GetListOfFiles();
4716  if (of && (of->GetSize() > 0)) {
4717  TIter nxf(of);
4718  TFile *f = 0;
4719  while ((f = (TFile *)nxf()))
4720  if (f->Matches(name))
4721  return f->GetAsyncOpenStatus();
4722  }
4723 
4724  // Default is synchronous mode
4725  return kAOSNotAsync;
4726 }
4727 
4728 ////////////////////////////////////////////////////////////////////////////////
4729 /// Get status of the async open request related to 'handle'.
4730 
4733  if (handle && handle->fFile) {
4734  if (!handle->fFile->IsZombie())
4735  return handle->fFile->GetAsyncOpenStatus();
4736  else
4737  return TFile::kAOSFailure;
4738  }
4739 
4740  // Default is synchronous mode
4741  return TFile::kAOSNotAsync;
4742 }
4743 
4744 ////////////////////////////////////////////////////////////////////////////////
4745 /// Get final URL for file being opened asynchronously.
4746 /// Returns 0 is the information is not yet available.
4747 
4748 const TUrl *TFile::GetEndpointUrl(const char* name)
4750  // Check the list of pending async open requests
4751  if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4752  TIter nxr(fgAsyncOpenRequests);
4753  TFileOpenHandle *fh = 0;
4754  while ((fh = (TFileOpenHandle *)nxr()))
4755  if (fh->Matches(name))
4756  if (fh->fFile)
4757  return fh->fFile->GetEndpointUrl();
4758  }
4759 
4760  // Check also the list of files open
4762  TSeqCollection *of = gROOT->GetListOfFiles();
4763  if (of && (of->GetSize() > 0)) {
4764  TIter nxf(of);
4765  TFile *f = 0;
4766  while ((f = (TFile *)nxf()))
4767  if (f->Matches(name))
4768  return f->GetEndpointUrl();
4769  }
4770 
4771  // Information not yet available
4772  return (const TUrl *)0;
4773 }
4774 
4775 ////////////////////////////////////////////////////////////////////////////////
4776 /// Print file copy progress.
4777 
4778 void TFile::CpProgress(Long64_t bytesread, Long64_t size, TStopwatch &watch)
4780  fprintf(stderr, "[TFile::Cp] Total %.02f MB\t|", (Double_t)size/1048576);
4781 
4782  for (int l = 0; l < 20; l++) {
4783  if (size > 0) {
4784  if (l < 20*bytesread/size)
4785  fprintf(stderr, "=");
4786  else if (l == 20*bytesread/size)
4787  fprintf(stderr, ">");
4788  else if (l > 20*bytesread/size)
4789  fprintf(stderr, ".");
4790  } else
4791  fprintf(stderr, "=");
4792  }
4793  // Allow to update the GUI while uploading files
4795  watch.Stop();
4796  Double_t lCopy_time = watch.RealTime();
4797  fprintf(stderr, "| %.02f %% [%.01f MB/s]\r",
4798  100.0*(size?(bytesread/((float)size)):1), (lCopy_time>0.)?bytesread/lCopy_time/1048576.:0.);
4799  watch.Continue();
4800 }
4801 
4802 ////////////////////////////////////////////////////////////////////////////////
4803 /// Allows to copy this file to the dst URL. Returns kTRUE in case of success,
4804 /// kFALSE otherwise.
4805 
4806 Bool_t TFile::Cp(const char *dst, Bool_t progressbar, UInt_t buffersize)
4808  Bool_t rmdestiferror = kFALSE;
4809  TStopwatch watch;
4810  Bool_t success = kFALSE;
4811 
4812  TUrl dURL(dst, kTRUE);
4813 
4814  TString oopt = "RECREATE";
4815  TString ourl = dURL.GetUrl();
4816 
4817  // Files will be open in RAW mode
4818  TString raw = "filetype=raw";
4819 
4820  // Set optimization options for the destination file
4821  TString opt = dURL.GetOptions();
4822  if (opt != "") opt += "&";
4823  opt += raw;
4824 
4825  // AliEn files need to know where the source file is
4826  if (!strcmp(dURL.GetProtocol(), "alien"))
4827  opt += TString::Format("&source=%s", GetName());
4828 
4829  dURL.SetOptions(opt);
4830 
4831  char *copybuffer = 0;
4832 
4833  TFile *sfile = this;
4834  TFile *dfile = 0;
4835 
4836  // "RECREATE" does not work always well with XROOTD
4837  // namely when some pieces of the path are missing;
4838  // we force "NEW" in such a case
4839  if (TFile::GetType(ourl, "") == TFile::kNet) {
4840  if (gSystem->AccessPathName(ourl)) {
4841  oopt = "NEW";
4842  // Force creation of the missing parts of the path
4843  opt += "&mkpath=1";
4844  dURL.SetOptions(opt);
4845  }
4846  }
4847 
4848  // Open destination file
4849  if (!(dfile = TFile::Open(dURL.GetUrl(), oopt))) {
4850  ::Error("TFile::Cp", "cannot open destination file %s", dst);
4851  goto copyout;
4852  }
4853 
4854  // Probably we created a new file
4855  // We have to remove it in case of errors
4856  rmdestiferror = kTRUE;
4857 
4858  sfile->Seek(0);
4859  dfile->Seek(0);
4860 
4861  copybuffer = new char[buffersize];
4862  if (!copybuffer) {
4863  ::Error("TFile::Cp", "cannot allocate the copy buffer");
4864  goto copyout;
4865  }
4866 
4867  Bool_t readop;
4868  Bool_t writeop;
4869  Long64_t read;
4870  Long64_t written;
4871  Long64_t totalread;
4872  Long64_t filesize;
4873  Long64_t b00;
4874  filesize = sfile->GetSize();
4875  totalread = 0;
4876  watch.Start();
4877 
4878  b00 = sfile->GetBytesRead();
4879 
4880  do {
4881  if (progressbar) CpProgress(totalread, filesize,watch);
4882 
4883  Long64_t b1 = sfile->GetBytesRead() - b00;
4884 
4885  Long64_t readsize;
4886  if (filesize - b1 > (Long64_t)buffersize) {
4887  readsize = buffersize;
4888  } else {
4889  readsize = filesize - b1;
4890  }
4891 
4892  if (readsize == 0) break;
4893 
4894  Long64_t b0 = sfile->GetBytesRead();
4895  sfile->Seek(totalread,TFile::kBeg);
4896  readop = sfile->ReadBuffer(copybuffer, (Int_t)readsize);
4897  read = sfile->GetBytesRead() - b0;
4898  if ((read <= 0) || readop) {
4899  ::Error("TFile::Cp", "cannot read from source file %s. readsize=%lld read=%lld readop=%d",
4900  sfile->GetName(), readsize, read, readop);
4901  goto copyout;
4902  }
4903 
4904  Long64_t w0 = dfile->GetBytesWritten();
4905  writeop = dfile->WriteBuffer(copybuffer, (Int_t)read);
4906  written = dfile->GetBytesWritten() - w0;
4907  if ((written != read) || writeop) {
4908  ::Error("TFile::Cp", "cannot write %lld bytes to destination file %s", read, dst);
4909  goto copyout;
4910  }
4911  totalread += read;
4912  } while (read == (Long64_t)buffersize);
4913 
4914  if (progressbar) {
4915  CpProgress(totalread, filesize,watch);
4916  fprintf(stderr, "\n");
4917  }
4918 
4919  success = kTRUE;
4920 
4921 copyout:
4922  if (dfile) dfile->Close();
4923 
4924  if (dfile) delete dfile;
4925  if (copybuffer) delete[] copybuffer;
4926 
4927  if (rmdestiferror && (success != kTRUE))
4928  gSystem->Unlink(dst);
4929 
4930  watch.Stop();
4931  watch.Reset();
4932 
4933  return success;
4934 }
4935 
4936 ////////////////////////////////////////////////////////////////////////////////
4937 /// Allows to copy file from src to dst URL. Returns kTRUE in case of success,
4938 /// kFALSE otherwise.
4939 
4940 Bool_t TFile::Cp(const char *src, const char *dst, Bool_t progressbar,
4941  UInt_t buffersize)
4942 {
4943  TUrl sURL(src, kTRUE);
4944 
4945  // Files will be open in RAW mode
4946  TString raw = "filetype=raw";
4947 
4948  // Set optimization options for the source file
4949  TString opt = sURL.GetOptions();
4950  if (opt != "") opt += "&";
4951  opt += raw;
4952  // Netx-related options:
4953  // cachesz = 4*buffersize -> 4 buffers as peak mem usage
4954  // readaheadsz = 2*buffersize -> Keep at max 4*buffersize bytes outstanding when reading
4955  // rmpolicy = 1 -> Remove from the cache the blk with the least offset
4956  opt += TString::Format("&cachesz=%d&readaheadsz=%d&rmpolicy=1", 4*buffersize, 2*buffersize);
4957  sURL.SetOptions(opt);
4958 
4959  TFile *sfile = 0;
4960 
4961  Bool_t success = kFALSE;
4962 
4963  // Open source file
4964  if (!(sfile = TFile::Open(sURL.GetUrl(), "READ"))) {
4965  ::Error("TFile::Cp", "cannot open source file %s", src);
4966  } else {
4967  success = sfile->Cp(dst, progressbar, buffersize);
4968  }
4969 
4970  if (sfile) sfile->Close();
4971  if (sfile) delete sfile;
4972 
4973  return success;
4974 }
4975 
4976 //______________________________________________________________________________
4977 //The next statement is not active anymore on Linux.
4978 //Using posix_fadvise introduces a performance penalty (10 %) on optimized files
4979 //and in addition it destroys the information of TTreePerfStats
4980 #if defined(R__neverLINUX) && !defined(R__WINGCC)
4982 {
4983  // Read specified byte range asynchronously. Actually we tell the kernel
4984  // which blocks we are going to read so it can start loading these blocks
4985  // in the buffer cache.
4986 
4987  // Shortcut to avoid having to implement dummy ReadBufferAsync() in all
4988  // I/O plugins. Override ReadBufferAsync() in plugins if async is supported.
4989  if (IsA() != TFile::Class())
4990  return kTRUE;
4991 
4992  int advice = POSIX_FADV_WILLNEED;
4993  if (len == 0) {
4994  // according POSIX spec if len is zero, all data following offset
4995  // is specified. Nevertheless ROOT uses zero to probe readahead
4996  // capabilities.
4997  advice = POSIX_FADV_NORMAL;
4998  }
4999  Double_t start = 0;
5000  if (gPerfStats != 0) start = TTimeStamp();
5001 #if defined(R__SEEK64)
5002  Int_t result = posix_fadvise64(fD, offset, len, advice);
5003 #else
5004  Int_t result = posix_fadvise(fD, offset, len, advice);
5005 #endif
5006  if (gPerfStats != 0) {
5007  gPerfStats->FileReadEvent(this, len, start);
5008  }
5009  return (result != 0);
5010 }
5011 #else
5014  // Not supported yet on non Linux systems.
5015 
5016  return kTRUE;
5017 }
5018 #endif
5019 
5020 ////////////////////////////////////////////////////////////////////////////////
5021 /// Max number of bytes to prefetch.
5022 ///
5023 /// By default this is 75% of the
5024 /// read cache size. But specific TFile implementations may need to change it
5025 
5028  TFileCacheRead *cr = 0;
5029  if ((cr = GetCacheRead())) {
5030  Int_t bytes = cr->GetBufferSize() / 4 * 3;
5031  return ((bytes < 0) ? 0 : bytes);
5032  }
5033  return 0;
5034 }
virtual Bool_t SendFileCloseEvent(TFile *)
virtual void Map()
List the contents of a file sequentially.
Definition: TFile.cxx:1458
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
virtual Bool_t SendFileWriteProgress(TFile *)
void SetFile(const char *file)
Definition: TUrl.h:88
virtual Int_t Sizeof() const
Return the size in bytes of the directory header.
static TProcessID * GetPID()
static: returns pointer to current TProcessID
Definition: TProcessID.cxx:313
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:931
static ROOT::TRWSpinLock fgRwLock
!Read-write lock to protect global PID list
Definition: TFile.h:109
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1272
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:145
Bool_t IsReading() const
Definition: TBuffer.h:81
double read(const std::string &file_name)
reading
void frombuf(char *&buf, Bool_t *x)
Definition: Bytes.h:280
virtual void DrawMap(const char *keys="*", Option_t *option="")
Draw map of objects in this file.
Definition: TFile.cxx:1073
virtual Int_t Recover()
Attempt to recover file if not correctly closed.
Definition: TFile.cxx:1881
An array of TObjects.
Definition: TObjArray.h:37
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition: TROOT.cxx:2569
const char * GetArchiveName() const
Definition: TArchiveFile.h:55
virtual Int_t SysStat(Int_t fd, Long_t *id, Long64_t *size, Long_t *flags, Long_t *modtime)
Return file stat information.
Definition: TFile.cxx:4346
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:423
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:409
virtual const char * GetFlagsOpt() const
Return the optimization flags.
Definition: TSystem.cxx:3767
int GetErrno()
return errno
Double_t RealTime()
Stop the stopwatch (if it is running) and return the realtime (in seconds) passed between the start a...
Definition: TStopwatch.cxx:110
static Bool_t AddRule(const char *rule)
Add a schema evolution customization rule.
Definition: TClass.cxx:1802
virtual Bool_t IsPathLocal(const char *path)
Returns TRUE if the url in &#39;path&#39; points to the local file system.
Definition: TSystem.cxx:1281
long long Long64_t
Definition: RtypesCore.h:69
Long64_t GetLast() const
Definition: TFree.h:41
void Start(Bool_t reset=kTRUE)
Start the stopwatch.
Definition: TStopwatch.cxx:58
static Bool_t fgReadInfo
if true (default) ReadStreamerInfo is called when opening a file
Definition: TFile.h:126
virtual Long64_t SysSeek(Int_t fd, Long64_t offset, Int_t whence)
Interface to system lseek.
Definition: TFile.cxx:4328
EAsyncOpenStatus
Asynchronous open request status.
Definition: TFile.h:57
virtual const char * WorkingDirectory()
Return working directory.
Definition: TSystem.cxx:868
short Version_t
Definition: RtypesCore.h:61
void SetProtocol(const char *proto, Bool_t setDefaultPort=kFALSE)
Set protocol and, optionally, change the port accordingly.
Definition: TUrl.cxx:520
double write(int n, const std::string &file_name, const std::string &vector_type, int compress=0)
writing
virtual void FillBuffer(char *&buffer)
Encode file output buffer.
Definition: TFile.cxx:1115
static std::atomic< Long64_t > fgBytesRead
Number of bytes read by all TFile objects.
Definition: TFile.h:122
void Fatal(const char *location, const char *msgfmt,...)
Collectable string class.
Definition: TObjString.h:28
virtual Int_t ReOpen(Option_t *mode)
Reopen a file with a different access mode.
Definition: TFile.cxx:1995
float Float_t
Definition: RtypesCore.h:53
const Int_t kBEGIN
Definition: TFile.cxx:155
Bool_t Matches(const char *name)
Return kTRUE if this async request matches the open request specified by &#39;url&#39;.
Definition: TFile.cxx:4593
static void IncrementFileCounter()
Definition: TFile.cxx:4423
virtual void ReadFree()
Read the FREE linked list.
Definition: TFile.cxx:1761
A cache when reading files over the network.
const char Option_t
Definition: RtypesCore.h:62
Int_t GetNetOpt() const
Definition: TFile.h:358
virtual void Flush()
Synchronize a file&#39;s in-memory and on-disk states.
Definition: TFile.cxx:1086
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2201
static TList * fgAsyncOpenRequests
Definition: TFile.h:113
const Ssiz_t kNPOS
Definition: RtypesCore.h:115
T ReadBuffer(TBufferFile *buf)
One of the template functions used to read objects from messages.
Definition: MPSendRecv.h:157
virtual void SetOffset(Long64_t offset, ERelativeTo pos=kBeg)
Set position from where to start reading.
Definition: TFile.cxx:2088
This class represents a WWW compatible URL.
Definition: TUrl.h:35
virtual char * GetBuffer() const
Definition: TKey.h:74
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:640
virtual void RemoveLast()
Remove the last object of the list.
Definition: TList.cxx:751
virtual TKey * CreateKey(TDirectory *mother, const TObject *obj, const char *name, Int_t bufsize)
Creates key for object and converts data to buffer.
Definition: TFile.cxx:1001
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition: TSystem.cxx:1370
unsigned short UShort_t
Definition: RtypesCore.h:36
Class holding info about the file being opened.
Definition: TFile.h:330
const char * GetProtocol() const
Definition: TUrl.h:67
static UInt_t fgOpenTimeout
Timeout for open operations in ms - 0 corresponds to blocking i/o.
Definition: TFile.h:118
virtual const char * GetClassName() const
Definition: TKey.h:71
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
TH1 * h
Definition: legend2.C:5
UInt_t GetBaseCheckSum()
virtual void Seek(Long64_t offset, ERelativeTo pos=kBeg)
Seek to a specific position in the file. Pos it either kBeg, kCur or kEnd.
Definition: TFile.cxx:2109
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:46
static void SetFileReadCalls(Int_t readcalls=0)
Definition: TFile.cxx:4417
virtual Int_t GetEntries() const
Definition: TCollection.h:86
virtual Bool_t ReadBuffer(char *buf, Int_t len)
Read a buffer from the file.
Definition: TFile.cxx:1606
virtual const char * HomeDirectory(const char *userName=0)
Return the user&#39;s home directory.
Definition: TSystem.cxx:884
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1112
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
Bool_t HasInterpreterInfo() const
Definition: TClass.h:364
virtual Bool_t ChangeDirectory(const char *path)
Change directory.
Definition: TSystem.cxx:859
const char * GetFileAndOptions() const
Return the file and its options (the string specified behind the ?).
Definition: TUrl.cxx:501
static TArchiveFile * Open(const char *url, TFile *file)
Return proper archive file handler depending on passed url.
#define gROOT
Definition: TROOT.h:375
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:587
virtual Long64_t GetBytesWritten() const
Return the total number of bytes written so far to the file.
Definition: TFile.cxx:4369
Int_t LoadPlugin()
Load the plugin library for this handler.
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition: TSystem.cxx:1825
#define O_BINARY
Definition: civetweb.c:451
Basic string class.
Definition: TString.h:129
static Bool_t ShrinkCacheFileDir(Long64_t shrinkSize, Long_t cleanupInteval=0)
Try to shrink the cache to the desired size.
Definition: TFile.cxx:4469
virtual Int_t Sizeof() const
Return size of the TNamed part of the TObject.
Definition: TNamed.cxx:164
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1099
int Int_t
Definition: RtypesCore.h:41
virtual void FillBuffer(char *&buffer)
Encode TNamed into output buffer.
Definition: TNamed.cxx:95
virtual const char * DirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1003
bool Bool_t
Definition: RtypesCore.h:59
Iterator of object array.
Definition: TObjArray.h:122
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
Int_t WriteBufferViaCache(const char *buf, Int_t len)
Write buffer via cache.
Definition: TFile.cxx:2355
virtual const char * GetSoExt() const
Get the shared library extension.
Definition: TSystem.cxx:3837
#define gInterpreter
Definition: TInterpreter.h:499
const char * GetOptions() const
Definition: TUrl.h:74
Int_t GenerateHeaderFile(const char *dirname, const TList *subClasses=0, const TList *extrainfos=0)
Generate header file for the class described by this TStreamerInfo the function is called by TFile::M...
virtual Int_t Write(const char *name=0, Int_t opt=0, Int_t bufsize=0)
Write all objects in memory to disk.
Type GetType(const std::string &Name)
Definition: Systematics.cxx:34
ERelativeTo
Definition: TFile.h:171
virtual const char * GetFlagsDebug() const
Return the debug flags.
Definition: TSystem.cxx:3759
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
virtual void IgnoreInterrupt(Bool_t ignore=kTRUE)
If ignore is true ignore the interrupt signal, else restore previous behaviour.
Definition: TSystem.cxx:609
static void SetReadStreamerInfo(Bool_t readinfo=kTRUE)
Specify if the streamerinfos must be read at file opening.
Definition: TFile.cxx:3552
virtual TObject * Clone(const char *newname="") const
Make a clone of an collection using the Streamer facility.
static void SetReadaheadSize(Int_t bufsize=256000)
Definition: TFile.cxx:4408
TString & Insert(Ssiz_t pos, const char *s)
Definition: TString.h:597
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
virtual void FillBuffer(char *&buffer)
Encode directory header into output buffer.
R__EXTERN void **(* gThreadTsd)(void *, Int_t)
Definition: TThreadSlots.h:40
void Reset()
Definition: TCollection.h:156
const char * GetHostFQDN() const
Return fully qualified domain name of url host.
Definition: TUrl.cxx:469
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Definition: TSystem.cxx:903
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:687
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition: TUrl.cxx:387
void SysError(const char *location, const char *msgfmt,...)
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:501
void SumBuffer(Int_t bufsize)
Increment statistics for buffer sizes of objects in this file.
Definition: TFile.cxx:2253
virtual void FillBuffer(char *&buffer)
Encode fre structure into output buffer.
Definition: TFree.cxx:109
static Int_t GetErrno()
Static function returning system error number.
Definition: TSystem.cxx:267
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=1, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3909
TFree * AddFree(TList *lfree, Long64_t first, Long64_t last)
Add a new free segment to the list of free segments.
Definition: TFree.cxx:67
Int_t fMode
Definition: TSystem.h:128
virtual Bool_t Cp(const char *dst, Bool_t progressbar=kTRUE, UInt_t buffersize=1000000)
Allows to copy this file to the dst URL.
Definition: TFile.cxx:4807
static void SetFileBytesWritten(Long64_t bytes=0)
Definition: TFile.cxx:4414
const char * GetFile() const
Definition: TUrl.h:72
virtual Int_t GetErrno() const
Method returning errno. Is overriden in TRFIOFile.
Definition: TFile.cxx:1186
static TObjArray * GetPIDs()
static: returns array of TProcessIDs
Definition: TProcessID.cxx:321
double sqrt(double)
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:850
#define SafeDelete(p)
Definition: RConfig.h:499
virtual int Unlink(const char *name)
Unlink, i.e. remove, a file.
Definition: TSystem.cxx:1353
virtual Int_t GetClassVersion() const =0
Sequenceable collection abstract base class.
virtual void ResetErrno() const
Method resetting the errno. Is overridden in TRFIOFile.
Definition: TFile.cxx:1194
void Stop()
Stop the stopwatch.
Definition: TStopwatch.cxx:77
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2345
Service class for TFile.
Definition: TFree.h:27
virtual FILE * TempFileName(TString &base, const char *dir=0)
Create a secure temporary file by appending a unique 6 letter string to base.
Definition: TSystem.cxx:1469
virtual void ReadBuffer(char *&buffer)
Read string from I/O buffer.
Definition: TString.cxx:1238
static Bool_t GetReadStreamerInfo()
If the streamerinfos are to be read at file opening.
Definition: TFile.cxx:3562
void Class()
Definition: Class.C:29
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition: TSystem.cxx:444
virtual void SetCompressionLevel(Int_t level=1)
See comments for function SetCompressionSettings.
Definition: TFile.cxx:2155
virtual void MakeProject(const char *dirname, const char *classes="*", Option_t *option="new")
Generate source code necessary to access the objects stored in the file.
Definition: TFile.cxx:2559
virtual void WriteFree()
Write FREE linked list on the file.
Definition: TFile.cxx:2379
static Long64_t GetFileBytesRead()
Static function returning the total number of bytes read from all files.
Definition: TFile.cxx:4377
static EFileType GetType(const char *name, Option_t *option="", TString *prefix=0)
Resolve the file type as a function of the protocol field in &#39;name&#39;.
Definition: TFile.cxx:4624
static TFile * OpenFromCache(const char *name, Option_t *="", const char *ftitle="", Int_t compress=1, Int_t netopt=0)
Open a file for reading through the file cache.
Definition: TFile.cxx:3700
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1150
static void GetDateTime(UInt_t datetime, Int_t &date, Int_t &time)
Static function that returns the date and time.
Definition: TDatime.cxx:434
R__EXTERN TVirtualMonitoringWriter * gMonitoringWriter
static Long64_t GetFileBytesWritten()
Static function returning the total number of bytes written to all files.
Definition: TFile.cxx:4386
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1443
void Info(const char *location, const char *msgfmt,...)
TString & Append(const char *cs)
Definition: TString.h:497
std::vector< std::vector< double > > Data
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2231
const std::string ClassName(PyObject *pyobj)
Retrieve the class name from the given python object (which may be just an instance of the class)...
Definition: Utility.cxx:702
const char * GetAnchor() const
Definition: TUrl.h:73
TFile * GetFile() const
Definition: TFile.h:349
void tobuf(char *&buf, Bool_t x)
Definition: Bytes.h:57
void Continue()
Resume a stopped stopwatch.
Definition: TStopwatch.cxx:93
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:24
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:69
virtual void Delete(Option_t *option="")
Delete an object from the file.
Definition: TKey.cxx:534
virtual TString GetNewUrl()
Definition: TFile.h:221
void Error(const char *location, const char *msgfmt,...)
R__EXTERN TPluginManager * gPluginMgr
virtual Int_t SysWrite(Int_t fd, const void *buf, Int_t len)
Interface to system write. All arguments like in POSIX write().
Definition: TFile.cxx:4317
void MayNotUse(const char *method)
This function can be used in classes that should override a certain function, but in the inherited cl...
Definition: TError.cxx:269
virtual Int_t SysSync(Int_t fd)
Interface to system fsync. All arguments like in POSIX fsync().
Definition: TFile.cxx:4355
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:698
A doubly linked list.
Definition: TList.h:43
Int_t GetRecordHeader(char *buf, Long64_t first, Int_t maxbytes, Int_t &nbytes, Int_t &objlen, Int_t &keylen)
Read the logical record header starting at a certain postion.
Definition: TFile.cxx:1239
virtual void ls(Option_t *option="") const
List Directory contents.
virtual Int_t SysClose(Int_t fd)
Interface to system close. All arguments like in POSIX close().
Definition: TFile.cxx:4300
Int_t GetObjlen() const
Definition: TKey.h:83
static UInt_t GetOpenTimeout()
Returns open timeout (in ms).
Definition: TFile.cxx:4537
virtual void ShowStreamerInfo()
Show the StreamerInfo of all classes written to this file.
Definition: TFile.cxx:3570
th1 Draw()
EFileType
File type.
Definition: TFile.h:174
virtual Int_t SysRead(Int_t fd, void *buf, Int_t len)
Interface to system read. All arguments like in POSIX read().
Definition: TFile.cxx:4309
const char * GetOpt() const
Definition: TFile.h:356
void ResetErrno()
reset errno
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:222
TClass * GetClass() const
R__EXTERN TSystem * gSystem
Definition: TSystem.h:539
#define R__RWLOCK_RELEASE_READ(rwlock)
virtual Int_t SysOpen(const char *pathname, Int_t flags, UInt_t mode)
Interface to system open. All arguments like in POSIX open().
Definition: TFile.cxx:4284
#define R__RWLOCK_RELEASE_WRITE(rwlock)
UInt_t GetCheckSum() const
virtual void WriteStreamerInfo()
Write the list of TStreamerInfo as a single object in this file The class Streamer description for al...
Definition: TFile.cxx:3612
A ROOT file is structured in Directories (like a file system).
virtual const char * GetLibraries(const char *regexp="", const char *option="", Bool_t isRegexp=kTRUE)
Return a space separated list of loaded shared libraries.
Definition: TSystem.cxx:2079
virtual Int_t Write(const char *name=0, Int_t opt=0, Int_t bufsiz=0)
Write memory objects to this file.
Definition: TFile.cxx:2272
virtual Int_t GetBytesToPrefetch() const
Max number of bytes to prefetch.
Definition: TFile.cxx:5027
Long_t ExecPlugin(int nargs, const T &... params)
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:482
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:679
virtual void Delete(const char *namecycle="")
Delete object namecycle.
Definition: TFile.cxx:1052
void SetBaseCheckSum(UInt_t cs)
virtual Bool_t WriteBuffer(const char *buf, Int_t len)
Write a buffer to the file.
Definition: TFile.cxx:2312
const TMatches FindRules(const TString &source) const
Return all the rules that are about the given &#39;source&#39; class.
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2332
Int_t IncrementCount()
Increase the reference count to this object.
Definition: TProcessID.cxx:283
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual Bool_t ReadFile()
Read the key structure from the file.
Definition: TKey.cxx:1261
Ssiz_t Length() const
Definition: TString.h:388
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1398
virtual void SetFile(TFile *file, TFile::ECacheAction action=TFile::kDisconnect)
Set the file using this cache and reset the current blocks (if any).
static std::atomic< Long64_t > fgFileCounter
Counter for all opened files.
Definition: TFile.h:123
Int_t DecrementCount()
The reference fCount is used to delete the TProcessID in the TFile destructor when fCount = 0...
Definition: TProcessID.cxx:222
static std::atomic< Long64_t > fgBytesWrite
Number of bytes written by all TFile objects.
Definition: TFile.h:121
short Short_t
Definition: RtypesCore.h:35
TLine * l
Definition: textangle.C:4
static void CpProgress(Long64_t bytesread, Long64_t size, TStopwatch &watch)
Print file copy progress.
Definition: TFile.cxx:4779
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2632
static std::atomic< Int_t > fgReadCalls
Number of bytes read from all TFile objects.
Definition: TFile.h:124
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:71
virtual void Draw(Option_t *option="")
Fill Graphics Structure and Paint.
Definition: TFile.cxx:1065
virtual void Delete(const char *namecycle="")
Delete Objects or/and keys in a directory.
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition: TSystem.cxx:660
virtual TList * GetStreamerInfoList()
Read the list of TStreamerInfo objects written to this file.
Definition: TFile.cxx:1329
ROOT::ESTLType GetCollectionType() const
Return the &#39;type&#39; of the STL the TClass is representing.
Definition: TClass.cxx:2803
void Build(TFile *motherFile=0, TDirectory *motherDir=0)
Initialise directory to defaults.
static Int_t GetFileReadCalls()
Static function returning the total number of read calls from all files.
Definition: TFile.cxx:4394
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4602
virtual const char * GetMakeSharedLib() const
Return the command line use to make a shared library.
Definition: TSystem.cxx:3788
void SetName(const char *name)
Definition: TCollection.h:111
virtual TObject * ReadObjWithBuffer(char *bufferRead)
To read a TObject* from bufferRead.
Definition: TKey.cxx:872
void Warning(const char *location, const char *msgfmt,...)
virtual void Init(Bool_t create)
Initialize a TFile object.
Definition: TFile.cxx:584
TString & String()
Definition: TObjString.h:49
Long64_t GetFirst() const
Definition: TFree.h:40
TFile * GetFile() const
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:842
Int_t ReadBufferViaCache(char *buf, Int_t len)
Read buffer via cache.
Definition: TFile.cxx:1725
static TFile *& CurrentFile()
Return the current ROOT file if any.
Definition: TFile.cxx:1021
virtual TObjLink * FirstLink() const
Definition: TList.h:97
Option_t * GetOption() const
Definition: TFile.h:211
#define Printf
Definition: TGeoToOCC.h:18
#define gPerfStats
#define R__LOCKGUARD2(mutex)
static void GenerateMissingStreamerInfos(TList *extrainfos, TStreamerElement *element)
Generate an empty StreamerInfo for types that are used in templates parameters but are not known in t...
const Bool_t kFALSE
Definition: RtypesCore.h:92
virtual Long64_t GetBytesRead() const
Definition: TFile.h:212
virtual void ReadBuffer(char *&buffer)
Decode one free structure from input buffer.
Definition: TFree.cxx:167
static Bool_t fgOnlyStaged
Before the file is opened, it is checked, that the file is staged, if not, the open fails...
Definition: TFile.h:119
static Bool_t GetOnlyStaged()
Returns staged only flag.
Definition: TFile.cxx:4557
virtual void ReadStreamerInfo()
Read the list of StreamerInfo from this file.
Definition: TFile.cxx:3435
virtual Int_t RedirectOutput(const char *name, const char *mode="a", RedirectHandle_t *h=0)
Redirect standard output (stdout, stderr) to the specified file.
Definition: TSystem.cxx:1684
void CheckInit()
Initialize fObjects.
Definition: TProcessID.cxx:176
void SetHost(const char *host)
Definition: TUrl.h:87
TString & Remove(Ssiz_t pos)
Definition: TString.h:621
long Long_t
Definition: RtypesCore.h:50
TFile()
File default Constructor.
Definition: TFile.cxx:174
int Ssiz_t
Definition: RtypesCore.h:63
static void Add(TGlobalMappedFunction *gmf)
Definition: TGlobal.cxx:183
virtual int Chmod(const char *file, UInt_t mode)
Set the file permission bits. Returns -1 in case or error, 0 otherwise.
Definition: TSystem.cxx:1478
Version_t GetClassVersion() const
Definition: TClass.h:372
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition: TKey.cxx:1218
void SetAnchor(const char *anchor)
Definition: TUrl.h:89
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2251
virtual const char * GetIncludePath()
Get the list of include path.
Definition: TSystem.cxx:3805
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
virtual Bool_t IsOpen() const
Returns kTRUE in case file is open and kFALSE if file is not open.
Definition: TFile.cxx:1383
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
#define ClassImp(name)
Definition: Rtypes.h:336
double f(double x)
void Print(std::ostream &os, const OptionType &opt)
Bool_t IsZombie() const
Definition: TObject.h:122
static Bool_t fgCacheFileForce
Indicates, to force all READ to CACHEREAD.
Definition: TFile.h:117
TFile * fFile
TFile instance of the file being opened.
Definition: TFile.h:339
Int_t Sizeof() const
return number of bytes occupied by this TFree on permanent storage
Definition: TFree.cxx:184
virtual Int_t ReadKeys(Bool_t forceRead=kTRUE)
Read the linked list of keys.
virtual Long64_t GetSeekKey() const
Definition: TKey.h:85
double Double_t
Definition: RtypesCore.h:55
virtual void ls(Option_t *option="") const
List (ls) all objects in this collection.
virtual int Symlink(const char *from, const char *to)
Create a symbolic link from file1 to file2.
Definition: TSystem.cxx:1344
static Int_t GetReadaheadSize()
Static function returning the readahead buffer size.
Definition: TFile.cxx:4402
#define R__RWLOCK_ACQUIRE_READ(rwlock)
Describe directory structure in memory.
Definition: TDirectory.h:34
TFileCacheWrite * GetCacheWrite() const
Return a pointer to the current write cache.
Definition: TFile.cxx:1219
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition: TMap.h:40
int type
Definition: TGX11.cxx:120
virtual void Clear(Option_t *option="")
delete the TObjArray pointing to referenced objects this function is called by TFile::Close("R") ...
Definition: TProcessID.cxx:202
R__EXTERN TEnv * gEnv
Definition: TEnv.h:170
virtual Int_t GetBufferSize() const
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:552
virtual Long64_t GetSize() const
Returns the current file size.
Definition: TFile.cxx:1285
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition: TROOT.cxx:2791
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition: TTimeStamp.h:71
Int_t GetNbytes() const
Definition: TKey.h:82
static Bool_t fgCacheFileDisconnected
Indicates, we trust in the files in the cache dir without stat on the cached file.
Definition: TFile.h:116
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:572
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
Definition: TProcessID.cxx:275
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition: TString.cxx:396
Float_t GetCompressionFactor()
Return the file compression factor.
Definition: TFile.cxx:1142
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2885
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:353
Int_t GetCompress() const
Definition: TFile.h:357
virtual Bool_t SendFileReadProgress(TFile *)
virtual void Close(Option_t *option="")
Delete all objects from memory and directory structure itself.
Int_t GetPort() const
Definition: TUrl.h:81
Int_t GetKeylen() const
Definition: TKey.h:80
Bool_t IsNull() const
Definition: TString.h:385
Int_t Match(const TString &s, UInt_t start=0)
Runs a match on s against the regex &#39;this&#39; was created with.
Definition: TPRegexp.cxx:705
virtual void AddAfter(const TObject *after, TObject *obj)
Insert object after object after in the list.
Definition: TList.cxx:225
const TList * GetStreamerInfoCache()
Returns the cached list of StreamerInfos used in this file.
Definition: TFile.cxx:1304
Mother of all ROOT objects.
Definition: TObject.h:37
TObjArray * GetElements() const
Bool_t FlushWriteCache()
Flush the write cache if active.
Definition: TFile.cxx:1103
static Bool_t SetOnlyStaged(Bool_t onlystaged)
Sets only staged flag.
Definition: TFile.cxx:4547
virtual void Paint(Option_t *option="")
Paint all objects in the file.
Definition: TFile.cxx:1534
virtual void SetCompressionSettings(Int_t settings=1)
Used to specify the compression level and algorithm.
Definition: TFile.cxx:2174
static TString fgCacheFileDir
Directory where to locally stage files.
Definition: TFile.h:115
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition: TROOT.cxx:2624
Int_t GetClassVersion() const
virtual const TUrl * GetEndpointUrl() const
Definition: TFile.h:206
static TString UpdateAssociativeToVector(const char *name)
If we have a map, multimap, set or multiset, plus unordered partners, and the key is a class...
RooCmdArg Save(Bool_t flag=kTRUE)
void BuildCheck(TFile *file=0)
Check if built and consistent with the class dictionary.
virtual ~TFile()
File destructor.