Logo ROOT   6.07/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
151 ROOT::TRWSpinLock TFile::fgRwLock;
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 /// Using the list, one can access additional information, e.g.:
1315 /// ~~~{.cpp}
1316 /// TFile f("myfile.root");
1317 /// auto list = f.GetStreamerInfoList();
1318 /// auto info = (TStreamerInfo*)list->FindObject("MyClass");
1319 /// auto classversionid = info->GetClassVersion();
1320 /// delete list;
1321 /// ~~~
1322 ///
1323 
1326  if (fIsPcmFile) return 0; // No schema evolution for ROOT PCM files.
1327 
1328  TList *list = 0;
1329  if (fSeekInfo) {
1330  TDirectory::TContext ctxt(this); // gFile and gDirectory used in ReadObj
1331  TKey *key = new TKey(this);
1332  char *buffer = new char[fNbytesInfo+1];
1333  char *buf = buffer;
1334  Seek(fSeekInfo);
1335  if (ReadBuffer(buf,fNbytesInfo)) {
1336  // ReadBuffer returns kTRUE in case of failure.
1337  Warning("GetRecordHeader","%s: failed to read the StreamerInfo data from disk.",
1338  GetName());
1339  return 0;
1340  }
1341  key->ReadKeyBuffer(buf);
1342  list = dynamic_cast<TList*>(key->ReadObjWithBuffer(buffer));
1343  if (list) list->SetOwner();
1344  delete [] buffer;
1345  delete key;
1346  } else {
1347  list = (TList*)Get("StreamerInfo"); //for versions 2.26 (never released)
1348  }
1349 
1350  if (list == 0) {
1351  Info("GetStreamerInfoList", "cannot find the StreamerInfo record in file %s",
1352  GetName());
1353  return 0;
1354  }
1355 
1356  return list;
1357 }
1358 
1359 ////////////////////////////////////////////////////////////////////////////////
1360 /// List file contents.
1361 ///
1362 /// Indentation is used to identify the file tree.
1363 /// Subdirectories are listed first, then objects in memory,
1364 /// then objects on the file.
1365 
1366 void TFile::ls(Option_t *option) const
1369  std::cout <<ClassName()<<"**\t\t"<<GetName()<<"\t"<<GetTitle()<<std::endl;
1371  TDirectoryFile::ls(option);
1373 }
1374 
1375 ////////////////////////////////////////////////////////////////////////////////
1376 /// Returns kTRUE in case file is open and kFALSE if file is not open.
1377 
1378 Bool_t TFile::IsOpen() const
1380  return fD == -1 ? kFALSE : kTRUE;
1381 }
1382 
1383 ////////////////////////////////////////////////////////////////////////////////
1384 /// Mark unused bytes on the file.
1385 ///
1386 /// The list of free segments is in the fFree linked list.
1387 /// When an object is deleted from the file, the freed space is added
1388 /// into the FREE linked list (fFree). The FREE list consists of a chain
1389 /// of consecutive free segments on the file. At the same time, the first
1390 /// 4 bytes of the freed record on the file are overwritten by GAPSIZE
1391 /// where GAPSIZE = -(Number of bytes occupied by the record).
1392 
1395  TFree *f1 = (TFree*)fFree->First();
1396  if (!f1) return;
1397  TFree *newfree = f1->AddFree(fFree,first,last);
1398  if(!newfree) return;
1399  Long64_t nfirst = newfree->GetFirst();
1400  Long64_t nlast = newfree->GetLast();
1401  Long64_t nbytesl= nlast-nfirst+1;
1402  if (nbytesl > 2000000000) nbytesl = 2000000000;
1403  Int_t nbytes = -Int_t (nbytesl);
1404  Int_t nb = sizeof(Int_t);
1405  char * buffer = new char[nb];
1406  char * psave = buffer;
1407  tobuf(buffer, nbytes);
1408  if (last == fEND-1) fEND = nfirst;
1409  Seek(nfirst);
1410  // We could not update the meta data for this block on the file.
1411  // This is not fatal as this only means that we won't get it 'right'
1412  // if we ever need to Recover the file before the block is actually
1413  // (attempted to be reused.
1414  // coverity[unchecked_value]
1415  WriteBuffer(psave, nb);
1416  if (fMustFlush) Flush();
1417  delete [] psave;
1418 }
1419 
1420 ////////////////////////////////////////////////////////////////////////////////
1421 /// List the contents of a file sequentially.
1422 /// For each logical record found, it prints:
1423 ///
1424 /// Date/Time Record_Adress Logical_Record_Length ClassName CompressionFactor
1425 ///
1426 /// Example of output
1427 ///
1428 /// 20010404/150437 At:64 N=150 TFile
1429 /// 20010404/150440 At:214 N=28326 TBasket CX = 1.13
1430 /// 20010404/150440 At:28540 N=29616 TBasket CX = 1.08
1431 /// 20010404/150440 At:58156 N=29640 TBasket CX = 1.08
1432 /// 20010404/150440 At:87796 N=29076 TBasket CX = 1.10
1433 /// 20010404/150440 At:116872 N=10151 TBasket CX = 3.15
1434 /// 20010404/150441 At:127023 N=28341 TBasket CX = 1.13
1435 /// 20010404/150441 At:155364 N=29594 TBasket CX = 1.08
1436 /// 20010404/150441 At:184958 N=29616 TBasket CX = 1.08
1437 /// 20010404/150441 At:214574 N=29075 TBasket CX = 1.10
1438 /// 20010404/150441 At:243649 N=9583 TBasket CX = 3.34
1439 /// 20010404/150442 At:253232 N=28324 TBasket CX = 1.13
1440 /// 20010404/150442 At:281556 N=29641 TBasket CX = 1.08
1441 /// 20010404/150442 At:311197 N=29633 TBasket CX = 1.08
1442 /// 20010404/150442 At:340830 N=29091 TBasket CX = 1.10
1443 /// 20010404/150442 At:369921 N=10341 TBasket CX = 3.09
1444 /// 20010404/150442 At:380262 N=509 TH1F CX = 1.93
1445 /// 20010404/150442 At:380771 N=1769 TH2F CX = 4.32
1446 /// 20010404/150442 At:382540 N=1849 TProfile CX = 1.65
1447 /// 20010404/150442 At:384389 N=18434 TNtuple CX = 4.51
1448 /// 20010404/150442 At:402823 N=307 KeysList
1449 /// 20010404/150443 At:403130 N=4548 StreamerInfo CX = 3.65
1450 /// 20010404/150443 At:407678 N=86 FreeSegments
1451 /// 20010404/150443 At:407764 N=1 END
1452 
1453 void TFile::Map()
1455  Short_t keylen,cycle;
1456  UInt_t datime;
1457  Int_t nbytes,date,time,objlen,nwheader;
1458  date = 0;
1459  time = 0;
1460  Long64_t seekkey,seekpdir;
1461  char *buffer;
1462  char nwhc;
1463  Long64_t idcur = fBEGIN;
1464 
1465  nwheader = 64;
1466  Int_t nread = nwheader;
1467 
1468  char header[kBEGIN];
1469  char classname[512];
1470 
1471  while (idcur < fEND) {
1472  Seek(idcur);
1473  if (idcur+nread >= fEND) nread = fEND-idcur-1;
1474  if (ReadBuffer(header, nread)) {
1475  // ReadBuffer returns kTRUE in case of failure.
1476  Warning("Map","%s: failed to read the key data from disk at %lld.",
1477  GetName(),idcur);
1478  break;
1479  }
1480 
1481  buffer=header;
1482  frombuf(buffer, &nbytes);
1483  if (!nbytes) {
1484  Printf("Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes);
1485  date = 0; time = 0;
1486  break;
1487  }
1488  if (nbytes < 0) {
1489  Printf("Address = %lld\tNbytes = %d\t=====G A P===========", idcur, nbytes);
1490  idcur -= nbytes;
1491  Seek(idcur);
1492  continue;
1493  }
1494  Version_t versionkey;
1495  frombuf(buffer, &versionkey);
1496  frombuf(buffer, &objlen);
1497  frombuf(buffer, &datime);
1498  frombuf(buffer, &keylen);
1499  frombuf(buffer, &cycle);
1500  if (versionkey > 1000) {
1501  frombuf(buffer, &seekkey);
1502  frombuf(buffer, &seekpdir);
1503  } else {
1504  Int_t skey,sdir;
1505  frombuf(buffer, &skey); seekkey = (Long64_t)skey;
1506  frombuf(buffer, &sdir); seekpdir = (Long64_t)sdir;
1507  }
1508  frombuf(buffer, &nwhc);
1509  for (int i = 0;i < nwhc; i++) frombuf(buffer, &classname[i]);
1510  classname[(int)nwhc] = '\0'; //cast to avoid warning with gcc3.4
1511  if (idcur == fSeekFree) strlcpy(classname,"FreeSegments",512);
1512  if (idcur == fSeekInfo) strlcpy(classname,"StreamerInfo",512);
1513  if (idcur == fSeekKeys) strlcpy(classname,"KeysList",512);
1514  TDatime::GetDateTime(datime, date, time);
1515  if (objlen != nbytes-keylen) {
1516  Float_t cx = Float_t(objlen+keylen)/Float_t(nbytes);
1517  Printf("%d/%06d At:%lld N=%-8d %-14s CX = %5.2f",date,time,idcur,nbytes,classname,cx);
1518  } else {
1519  Printf("%d/%06d At:%lld N=%-8d %-14s",date,time,idcur,nbytes,classname);
1520  }
1521  idcur += nbytes;
1522  }
1523  Printf("%d/%06d At:%lld N=%-8d %-14s",date,time,idcur,1,"END");
1524 }
1525 
1526 ////////////////////////////////////////////////////////////////////////////////
1527 /// Paint all objects in the file.
1528 
1529 void TFile::Paint(Option_t *option)
1531  GetList()->R__FOR_EACH(TObject,Paint)(option);
1532 }
1533 
1534 ////////////////////////////////////////////////////////////////////////////////
1535 /// Print all objects in the file.
1536 
1537 void TFile::Print(Option_t *option) const
1539  Printf("TFile: name=%s, title=%s, option=%s", GetName(), GetTitle(), GetOption());
1540  GetList()->R__FOR_EACH(TObject,Print)(option);
1541 }
1542 
1543 ////////////////////////////////////////////////////////////////////////////////
1544 /// Read a buffer from the file at the offset 'pos' in the file.
1545 ///
1546 /// Returns kTRUE in case of failure.
1547 /// Compared to ReadBuffer(char*, Int_t), this routine does _not_
1548 /// change the cursor on the physical file representation (fD)
1549 /// if the data is in this TFile's cache.
1550 
1551 Bool_t TFile::ReadBuffer(char *buf, Long64_t pos, Int_t len)
1553  if (IsOpen()) {
1554 
1555  SetOffset(pos);
1556 
1557  Int_t st;
1558  Double_t start = 0;
1559  if (gPerfStats != 0) start = TTimeStamp();
1560 
1561  if ((st = ReadBufferViaCache(buf, len))) {
1562  if (st == 2)
1563  return kTRUE;
1564  return kFALSE;
1565  }
1566 
1567  Seek(pos);
1568  ssize_t siz;
1569 
1570  while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
1571  ResetErrno();
1572 
1573  if (siz < 0) {
1574  SysError("ReadBuffer", "error reading from file %s", GetName());
1575  return kTRUE;
1576  }
1577  if (siz != len) {
1578  Error("ReadBuffer", "error reading all requested bytes from file %s, got %ld of %d",
1579  GetName(), (Long_t)siz, len);
1580  return kTRUE;
1581  }
1582  fBytesRead += siz;
1583  fgBytesRead += siz;
1584  fReadCalls++;
1585  fgReadCalls++;
1586 
1587  if (gMonitoringWriter)
1589  if (gPerfStats != 0) {
1590  gPerfStats->FileReadEvent(this, len, start);
1591  }
1592  return kFALSE;
1593  }
1594  return kTRUE;
1595 }
1596 
1597 ////////////////////////////////////////////////////////////////////////////////
1598 /// Read a buffer from the file. This is the basic low level read operation.
1599 /// Returns kTRUE in case of failure.
1600 
1601 Bool_t TFile::ReadBuffer(char *buf, Int_t len)
1603  if (IsOpen()) {
1604 
1605  Int_t st;
1606  if ((st = ReadBufferViaCache(buf, len))) {
1607  if (st == 2)
1608  return kTRUE;
1609  return kFALSE;
1610  }
1611 
1612  ssize_t siz;
1613  Double_t start = 0;
1614 
1615  if (gPerfStats != 0) start = TTimeStamp();
1616 
1617  while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
1618  ResetErrno();
1619 
1620  if (siz < 0) {
1621  SysError("ReadBuffer", "error reading from file %s", GetName());
1622  return kTRUE;
1623  }
1624  if (siz != len) {
1625  Error("ReadBuffer", "error reading all requested bytes from file %s, got %ld of %d",
1626  GetName(), (Long_t)siz, len);
1627  return kTRUE;
1628  }
1629  fBytesRead += siz;
1630  fgBytesRead += siz;
1631  fReadCalls++;
1632  fgReadCalls++;
1633 
1634  if (gMonitoringWriter)
1636  if (gPerfStats != 0) {
1637  gPerfStats->FileReadEvent(this, len, start);
1638  }
1639  return kFALSE;
1640  }
1641  return kTRUE;
1642 }
1643 
1644 ////////////////////////////////////////////////////////////////////////////////
1645 /// Read the nbuf blocks described in arrays pos and len.
1646 ///
1647 /// The value pos[i] is the seek position of block i of length len[i].
1648 /// Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer.
1649 /// This function is overloaded by TNetFile, TWebFile, etc.
1650 /// Returns kTRUE in case of failure.
1651 
1652 Bool_t TFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
1654  // called with buf=0, from TFileCacheRead to pass list of readahead buffers
1655  if (!buf) {
1656  for (Int_t j = 0; j < nbuf; j++) {
1657  if (ReadBufferAsync(pos[j], len[j])) {
1658  return kTRUE;
1659  }
1660  }
1661  return kFALSE;
1662  }
1663 
1664  Int_t k = 0;
1665  Bool_t result = kTRUE;
1666  TFileCacheRead *old = fCacheRead;
1667  fCacheRead = 0;
1668  Long64_t curbegin = pos[0];
1669  Long64_t cur;
1670  char *buf2 = 0;
1671  Int_t i = 0, n = 0;
1672  while (i < nbuf) {
1673  cur = pos[i]+len[i];
1674  Bool_t bigRead = kTRUE;
1675  if (cur -curbegin < fgReadaheadSize) {n++; i++; bigRead = kFALSE;}
1676  if (bigRead || (i>=nbuf)) {
1677  if (n == 0) {
1678  //if the block to read is about the same size as the read-ahead buffer
1679  //we read the block directly
1680  Seek(pos[i]);
1681  result = ReadBuffer(&buf[k], len[i]);
1682  if (result) break;
1683  k += len[i];
1684  i++;
1685  } else {
1686  //otherwise we read all blocks that fit in the read-ahead buffer
1687  Seek(curbegin);
1688  if (buf2 == 0) buf2 = new char[fgReadaheadSize];
1689  //we read ahead
1690  Long64_t nahead = pos[i-1]+len[i-1]-curbegin;
1691  result = ReadBuffer(buf2, nahead);
1692  if (result) break;
1693  //now copy from the read-ahead buffer to the cache
1694  Int_t kold = k;
1695  for (Int_t j=0;j<n;j++) {
1696  memcpy(&buf[k],&buf2[pos[i-n+j]-curbegin],len[i-n+j]);
1697  k += len[i-n+j];
1698  }
1699  Int_t nok = k-kold;
1700  Long64_t extra = nahead-nok;
1701  fBytesReadExtra += extra;
1702  fBytesRead -= extra;
1703  fgBytesRead -= extra;
1704  n = 0;
1705  }
1706  curbegin = pos[i];
1707  }
1708  }
1709  if (buf2) delete [] buf2;
1710  fCacheRead = old;
1711  return result;
1712 }
1713 
1714 ////////////////////////////////////////////////////////////////////////////////
1715 /// Read buffer via cache.
1716 ///
1717 /// Returns 0 if the requested block is not in the cache, 1 in case read via
1718 /// cache was successful, 2 in case read via cache failed.
1719 
1720 Int_t TFile::ReadBufferViaCache(char *buf, Int_t len)
1722  Long64_t off = GetRelOffset();
1723  if (fCacheRead) {
1724  Int_t st = fCacheRead->ReadBuffer(buf, off, len);
1725  if (st < 0)
1726  return 2; // failure reading
1727  else if (st == 1) {
1728  // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
1729  SetOffset(off + len);
1730  return 1;
1731  }
1732  // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
1733  Seek(off);
1734  } else {
1735  // if write cache is active check if data still in write cache
1736  if (fWritable && fCacheWrite) {
1737  if (fCacheWrite->ReadBuffer(buf, off, len) == 0) {
1738  SetOffset(off + len);
1739  return 1;
1740  }
1741  // fOffset might have been changed via TFileCacheWrite::ReadBuffer(), reset it
1742  SetOffset(off);
1743  }
1744  }
1745 
1746  return 0;
1747 }
1748 
1749 ////////////////////////////////////////////////////////////////////////////////
1750 /// Read the FREE linked list.
1751 ///
1752 /// Every file has a linked list (fFree) of free segments.
1753 /// This linked list has been written on the file via WriteFree
1754 /// as a single data record.
1755 
1756 void TFile::ReadFree()
1758  // Avoid problem with file corruption.
1759  if (fNbytesFree < 0 || fNbytesFree > fEND) {
1760  fNbytesFree = 0;
1761  return;
1762  }
1763  TKey *headerfree = new TKey(fSeekFree, fNbytesFree, this);
1764  headerfree->ReadFile();
1765  char *buffer = headerfree->GetBuffer();
1766  headerfree->ReadKeyBuffer(buffer);
1767  buffer = headerfree->GetBuffer();
1768  while (1) {
1769  TFree *afree = new TFree();
1770  afree->ReadBuffer(buffer);
1771  fFree->Add(afree);
1772  if (afree->GetLast() > fEND) break;
1773  }
1774  delete headerfree;
1775 }
1776 
1777 ////////////////////////////////////////////////////////////////////////////////
1778 /// The TProcessID with number pidf is read from this file.
1779 ///
1780 /// If the object is not already entered in the gROOT list, it is added.
1781 
1784  TProcessID *pid = 0;
1785  TObjArray *pids = GetListOfProcessIDs();
1786  if (pidf < pids->GetSize()) pid = (TProcessID *)pids->UncheckedAt(pidf);
1787  if (pid) {
1788  pid->CheckInit();
1789  return pid;
1790  }
1791 
1792  //check if fProcessIDs[uid] is set in file
1793  //if not set, read the process uid from file
1794  char pidname[32];
1795  snprintf(pidname,32,"ProcessID%d",pidf);
1796  pid = (TProcessID *)Get(pidname);
1797  if (gDebug > 0) {
1798  printf("ReadProcessID, name=%s, file=%s, pid=%lx\n",pidname,GetName(),(Long_t)pid);
1799  }
1800  if (!pid) {
1801  //file->Error("ReadProcessID","Cannot find %s in file %s",pidname,file->GetName());
1802  return pid;
1803  }
1804 
1805  //check that a similar pid is not already registered in fgPIDs
1806  TObjArray *pidslist = TProcessID::GetPIDs();
1807  TIter next(pidslist);
1808  TProcessID *p;
1809  bool found = false;
1810  R__RWLOCK_ACQUIRE_READ(fgRwLock);
1811  while ((p = (TProcessID*)next())) {
1812  if (!strcmp(p->GetTitle(),pid->GetTitle())) {
1813  found = true;
1814  break;
1815  }
1816  }
1817  R__RWLOCK_RELEASE_READ(fgRwLock);
1818 
1819  if (found) {
1820  delete pid;
1821  pids->AddAtAndExpand(p,pidf);
1822  p->IncrementCount();
1823  return p;
1824  }
1825 
1826  pids->AddAtAndExpand(pid,pidf);
1827  pid->IncrementCount();
1828 
1829  R__RWLOCK_ACQUIRE_WRITE(fgRwLock);
1830  pidslist->Add(pid);
1831  Int_t ind = pidslist->IndexOf(pid);
1832  pid->SetUniqueID((UInt_t)ind);
1833  R__RWLOCK_RELEASE_WRITE(fgRwLock);
1834 
1835  return pid;
1836 }
1837 
1838 
1839 ////////////////////////////////////////////////////////////////////////////////
1840 /// Attempt to recover file if not correctly closed
1841 ///
1842 /// The function returns the number of keys that have been recovered.
1843 /// If no keys can be recovered, the file will be declared Zombie by
1844 /// the calling function. This function is automatically called when
1845 /// opening a file.
1846 /// If the file is open in read only mode, the file is not modified.
1847 /// If open in update mode and the function finds something to recover,
1848 /// a new directory header is written to the file. When opening the file gain
1849 /// no message from Recover will be reported.
1850 /// If keys have been recovered, the file is usable and you can safely
1851 /// read the corresponding objects.
1852 /// If the file is not usable (a zombie), you can test for this case
1853 /// with code like:
1854 ///
1855 /// ~~~{.cpp}
1856 /// TFile f("myfile.root");
1857 /// if (f.IsZombie()) {<actions to take if file is unusable>}
1858 /// ~~~
1859 ///
1860 /// If the file has been recovered, the bit kRecovered is set in the TFile object in memory.
1861 /// You can test if the file has been recovered with
1862 ///
1863 /// if (f.TestBit(TFile::kRecovered)) {... the file has been recovered}
1864 ///
1865 /// When writing TTrees to a file, it is important to save the Tree header
1866 /// at regular intervals (see TTree::AutoSave). If a file containing a Tree
1867 /// is recovered, the last Tree header written to the file will be used.
1868 /// In this case all the entries in all the branches written before writing
1869 /// the header are valid entries.
1870 /// One can disable the automatic recovery procedure by setting
1871 ///
1872 /// TFile.Recover 0
1873 ///
1874 /// in the <em>system.rootrc</em> file.
1875 
1878  Short_t keylen,cycle;
1879  UInt_t datime;
1880  Int_t nbytes,date,time,objlen,nwheader;
1881  Long64_t seekkey,seekpdir;
1882  char header[1024];
1883  char *buffer, *bufread;
1884  char nwhc;
1885  Long64_t idcur = fBEGIN;
1886 
1887  Long64_t size;
1888  if ((size = GetSize()) == -1) {
1889  Error("Recover", "cannot stat the file %s", GetName());
1890  return 0;
1891  }
1892 
1893  fEND = Long64_t(size);
1894 
1895  if (fWritable && !fFree) fFree = new TList;
1896 
1897  TKey *key;
1898  Int_t nrecov = 0;
1899  nwheader = 1024;
1900  Int_t nread = nwheader;
1901 
1902  while (idcur < fEND) {
1903  Seek(idcur);
1904  if (idcur+nread >= fEND) nread = fEND-idcur-1;
1905  if (ReadBuffer(header, nread)) {
1906  // ReadBuffer returns kTRUE in case of failure.
1907  Error("Recover","%s: failed to read the key data from disk at %lld.",
1908  GetName(),idcur);
1909  break;
1910  }
1911  buffer = header;
1912  bufread = header;
1913  frombuf(buffer, &nbytes);
1914  if (!nbytes) {
1915  Error("Recover","Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes);
1916  break;
1917  }
1918  if (nbytes < 0) {
1919  idcur -= nbytes;
1920  if (fWritable) new TFree(fFree,idcur,idcur-nbytes-1);
1921  Seek(idcur);
1922  continue;
1923  }
1924  Version_t versionkey;
1925  frombuf(buffer, &versionkey);
1926  frombuf(buffer, &objlen);
1927  frombuf(buffer, &datime);
1928  frombuf(buffer, &keylen);
1929  frombuf(buffer, &cycle);
1930  if (versionkey > 1000) {
1931  frombuf(buffer, &seekkey);
1932  frombuf(buffer, &seekpdir);
1933  } else {
1934  Int_t skey,sdir;
1935  frombuf(buffer, &skey); seekkey = (Long64_t)skey;
1936  frombuf(buffer, &sdir); seekpdir = (Long64_t)sdir;
1937  }
1938  frombuf(buffer, &nwhc);
1939  char *classname = 0;
1940  if (nwhc <= 0 || nwhc > 100) break;
1941  classname = new char[nwhc+1];
1942  int i, nwhci = nwhc;
1943  for (i = 0;i < nwhc; i++) frombuf(buffer, &classname[i]);
1944  classname[nwhci] = '\0';
1945  TDatime::GetDateTime(datime, date, time);
1946  TClass *tclass = TClass::GetClass(classname);
1947  if (seekpdir == fSeekDir && tclass && !tclass->InheritsFrom(TFile::Class())
1948  && strcmp(classname,"TBasket")) {
1949  key = new TKey(this);
1950  key->ReadKeyBuffer(bufread);
1951  if (!strcmp(key->GetName(),"StreamerInfo")) {
1952  fSeekInfo = seekkey;
1953  SafeDelete(fInfoCache);
1954  fNbytesInfo = nbytes;
1955  } else {
1956  AppendKey(key);
1957  nrecov++;
1958  SetBit(kRecovered);
1959  Info("Recover", "%s, recovered key %s:%s at address %lld",GetName(),key->GetClassName(),key->GetName(),idcur);
1960  }
1961  }
1962  delete [] classname;
1963  idcur += nbytes;
1964  }
1965  if (fWritable) {
1966  Long64_t max_file_size = Long64_t(kStartBigFile);
1967  if (max_file_size < fEND) max_file_size = fEND+1000000000;
1968  TFree *last = (TFree*)fFree->Last();
1969  if (last) {
1970  last->AddFree(fFree,fEND,max_file_size);
1971  } else {
1972  new TFree(fFree,fEND,max_file_size);
1973  }
1974  if (nrecov) Write();
1975  }
1976  return nrecov;
1977 }
1978 
1979 ////////////////////////////////////////////////////////////////////////////////
1980 /// Reopen a file with a different access mode.
1981 ///
1982 /// For example, it is possible to change from READ to
1983 /// UPDATE or from NEW, CREATE, RECREATE, UPDATE to READ. Thus the
1984 /// mode argument can be either "READ" or "UPDATE". The method returns
1985 /// 0 in case the mode was successfully modified, 1 in case the mode
1986 /// did not change (was already as requested or wrong input arguments)
1987 /// and -1 in case of failure, in which case the file cannot be used
1988 /// anymore. The current directory (gFile) is changed to this file.
1989 
1992  cd();
1993 
1994  TString opt = mode;
1995  opt.ToUpper();
1996 
1997  if (opt != "READ" && opt != "UPDATE") {
1998  Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data());
1999  return 1;
2000  }
2001 
2002  if (opt == fOption || (opt == "UPDATE" && fOption == "CREATE"))
2003  return 1;
2004 
2005  if (opt == "READ") {
2006  // switch to READ mode
2007 
2008  // flush data still in the pipeline and close the file
2009  if (IsOpen() && IsWritable()) {
2010  WriteStreamerInfo();
2011 
2012  // save directory key list and header
2013  Save();
2014 
2015  TFree *f1 = (TFree*)fFree->First();
2016  if (f1) {
2017  WriteFree(); // write free segments linked list
2018  WriteHeader(); // now write file header
2019  }
2020 
2021  FlushWriteCache();
2022 
2023  // delete free segments from free list
2024  if (fFree) {
2025  fFree->Delete();
2026  SafeDelete(fFree);
2027  }
2028 
2029  SysClose(fD);
2030  fD = -1;
2031 
2032  SetWritable(kFALSE);
2033  }
2034 
2035  // open in READ mode
2036  fOption = opt; // set fOption before SysOpen() for TNetFile
2037 #ifndef WIN32
2038  fD = SysOpen(fRealName, O_RDONLY, 0644);
2039 #else
2040  fD = SysOpen(fRealName, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
2041 #endif
2042  if (fD == -1) {
2043  SysError("ReOpen", "file %s can not be opened in read mode", GetName());
2044  return -1;
2045  }
2046  SetWritable(kFALSE);
2047 
2048  } else {
2049  // switch to UPDATE mode
2050 
2051  // close readonly file
2052  if (IsOpen()) {
2053  SysClose(fD);
2054  fD = -1;
2055  }
2056 
2057  // open in UPDATE mode
2058  fOption = opt; // set fOption before SysOpen() for TNetFile
2059 #ifndef WIN32
2060  fD = SysOpen(fRealName, O_RDWR | O_CREAT, 0644);
2061 #else
2062  fD = SysOpen(fRealName, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
2063 #endif
2064  if (fD == -1) {
2065  SysError("ReOpen", "file %s can not be opened in update mode", GetName());
2066  return -1;
2067  }
2068  SetWritable(kTRUE);
2069 
2070  fFree = new TList;
2071  if (fSeekFree > fBEGIN)
2072  ReadFree();
2073  else
2074  Warning("ReOpen","file %s probably not closed, cannot read free segments", GetName());
2075  }
2076 
2077  return 0;
2078 }
2079 
2080 ////////////////////////////////////////////////////////////////////////////////
2081 /// Set position from where to start reading.
2082 
2083 void TFile::SetOffset(Long64_t offset, ERelativeTo pos)
2085  switch (pos) {
2086  case kBeg:
2087  fOffset = offset + fArchiveOffset;
2088  break;
2089  case kCur:
2090  fOffset += offset;
2091  break;
2092  case kEnd:
2093  // this option is not used currently in the ROOT code
2094  if (fArchiveOffset)
2095  Error("SetOffset", "seeking from end in archive is not (yet) supported");
2096  fOffset = fEND + offset; // is fEND really EOF or logical EOF?
2097  break;
2098  }
2099 }
2100 
2101 ////////////////////////////////////////////////////////////////////////////////
2102 /// Seek to a specific position in the file. Pos it either kBeg, kCur or kEnd.
2103 
2104 void TFile::Seek(Long64_t offset, ERelativeTo pos)
2106  int whence = 0;
2107  switch (pos) {
2108  case kBeg:
2109  whence = SEEK_SET;
2110  offset += fArchiveOffset;
2111  break;
2112  case kCur:
2113  whence = SEEK_CUR;
2114  break;
2115  case kEnd:
2116  whence = SEEK_END;
2117  // this option is not used currently in the ROOT code
2118  if (fArchiveOffset)
2119  Error("Seek", "seeking from end in archive is not (yet) supported");
2120  break;
2121  }
2122  Long64_t retpos;
2123  if ((retpos = SysSeek(fD, offset, whence)) < 0)
2124  SysError("Seek", "cannot seek to position %lld in file %s, retpos=%lld",
2125  offset, GetName(), retpos);
2126 
2127  // used by TFileCacheRead::ReadBuffer()
2128  fOffset = retpos;
2129 }
2130 
2131 ////////////////////////////////////////////////////////////////////////////////
2132 /// See comments for function SetCompressionSettings
2133 ///
2134 
2135 void TFile::SetCompressionAlgorithm(Int_t algorithm)
2137  if (algorithm < 0 || algorithm >= ROOT::kUndefinedCompressionAlgorithm) algorithm = 0;
2138  if (fCompress < 0) {
2139  // if the level is not defined yet use 1 as a default
2140  fCompress = 100 * algorithm + 1;
2141  } else {
2142  int level = fCompress % 100;
2143  fCompress = 100 * algorithm + level;
2144  }
2145 }
2146 
2147 ////////////////////////////////////////////////////////////////////////////////
2148 /// See comments for function SetCompressionSettings
2149 
2152  if (level < 0) level = 0;
2153  if (level > 99) level = 99;
2154  if (fCompress < 0) {
2155  // if the algorithm is not defined yet use 0 as a default
2156  fCompress = level;
2157  } else {
2158  int algorithm = fCompress / 100;
2159  if (algorithm >= ROOT::kUndefinedCompressionAlgorithm) algorithm = 0;
2160  fCompress = 100 * algorithm + level;
2161  }
2162 }
2163 
2164 ////////////////////////////////////////////////////////////////////////////////
2165 /// Used to specify the compression level and algorithm.
2166 ///
2167 /// See the TFile constructor for the details.
2168 
2169 void TFile::SetCompressionSettings(Int_t settings)
2171  fCompress = settings;
2172 }
2173 
2174 ////////////////////////////////////////////////////////////////////////////////
2175 /// Set a pointer to the read cache.
2176 ///
2177 /// <b>This relinquishes ownership</b> of the previous cache, so if you do not
2178 /// already have a pointer to the previous cache (and there was a previous
2179 /// cache), you ought to retrieve (and delete it if needed) using:
2180 ///
2181 /// TFileCacheRead *older = myfile->GetCacheRead();
2182 ///
2183 /// The action specifies how to behave when detaching a cache from the
2184 /// the TFile. If set to (default) kDisconnect, the contents of the cache
2185 /// will be flushed when it is removed from the file, and it will disconnect
2186 /// the cache object from the file. In almost all cases, this is what you want.
2187 /// If you want to disconnect the cache temporarily from this tree and re-attach
2188 /// later to the same fil, you can set action to kDoNotDisconnect. This will allow
2189 /// things like prefetching to continue in the background while it is no longer the
2190 /// default cache for the TTree. Except for a few expert use cases, kDisconnect is
2191 /// likely the correct setting.
2192 ///
2193 /// WARNING: if action=kDoNotDisconnect, you MUST delete the cache before TFile.
2194 ///
2195 
2196 void TFile::SetCacheRead(TFileCacheRead *cache, TObject* tree, ECacheAction action)
2198  if (tree) {
2199  if (cache) fCacheReadMap->Add(tree, cache);
2200  else {
2201  // The only addition to fCacheReadMap is via an interface that takes
2202  // a TFileCacheRead* so the C-cast is safe.
2203  TFileCacheRead* tpf = (TFileCacheRead *)fCacheReadMap->GetValue(tree);
2204  fCacheReadMap->Remove(tree);
2205  if (tpf && (tpf->GetFile() == this) && (action != kDoNotDisconnect)) tpf->SetFile(0, action);
2206  }
2207  }
2208  if (cache) cache->SetFile(this, action);
2209  else if (!tree && fCacheRead && (action != kDoNotDisconnect)) fCacheRead->SetFile(0, action);
2210  // For backward compatibility the last Cache set is the default cache.
2211  fCacheRead = cache;
2212 }
2213 
2214 ////////////////////////////////////////////////////////////////////////////////
2215 /// Set a pointer to the write cache.
2216 ///
2217 /// If file is null the existing write cache is deleted.
2218 
2221  if (!cache && fCacheWrite) delete fCacheWrite;
2222  fCacheWrite = cache;
2223 }
2224 
2225 ////////////////////////////////////////////////////////////////////////////////
2226 /// Return the size in bytes of the file header.
2227 
2228 Int_t TFile::Sizeof() const
2230  return 0;
2231 }
2232 
2233 ////////////////////////////////////////////////////////////////////////////////
2234 /// Stream a TFile object.
2235 
2236 void TFile::Streamer(TBuffer &b)
2237 {
2238  if (b.IsReading()) {
2239  b.ReadVersion(); //Version_t v = b.ReadVersion();
2240  } else {
2241  b.WriteVersion(TFile::IsA());
2242  }
2243 }
2244 
2245 ////////////////////////////////////////////////////////////////////////////////
2246 /// Increment statistics for buffer sizes of objects in this file.
2247 
2248 void TFile::SumBuffer(Int_t bufsize)
2250  fWritten++;
2251  fSumBuffer += double(bufsize);
2252  fSum2Buffer += double(bufsize) * double(bufsize); // avoid reaching MAXINT for temporary
2253 }
2254 
2255 ////////////////////////////////////////////////////////////////////////////////
2256 /// Write memory objects to this file.
2257 ///
2258 /// Loop on all objects in memory (including subdirectories).
2259 /// A new key is created in the KEYS linked list for each object.
2260 /// The list of keys is then saved on the file (via WriteKeys)
2261 /// as a single data record.
2262 /// For values of opt see TObject::Write().
2263 /// The directory header info is rewritten on the directory header record.
2264 /// The linked list of FREE segments is written.
2265 /// The file header is written (bytes 1->fBEGIN).
2266 
2267 Int_t TFile::Write(const char *, Int_t opt, Int_t bufsiz)
2269  if (!IsWritable()) {
2270  if (!TestBit(kWriteError)) {
2271  // Do not print the warning if we already had a SysError.
2272  Warning("Write", "file %s not opened in write mode", GetName());
2273  }
2274  return 0;
2275  }
2276 
2277  if (gDebug) {
2278  if (!GetTitle() || strlen(GetTitle()) == 0)
2279  Info("Write", "writing name = %s", GetName());
2280  else
2281  Info("Write", "writing name = %s title = %s", GetName(), GetTitle());
2282  }
2283 
2284  fMustFlush = kFALSE;
2285  Int_t nbytes = TDirectoryFile::Write(0, opt, bufsiz); // Write directory tree
2286  WriteStreamerInfo();
2287  WriteFree(); // Write free segments linked list
2288  WriteHeader(); // Now write file header
2289  fMustFlush = kTRUE;
2290 
2291  return nbytes;
2292 }
2293 
2294 ////////////////////////////////////////////////////////////////////////////////
2295 /// One can not save a const TDirectory object.
2296 
2297 Int_t TFile::Write(const char *n, Int_t opt, Int_t bufsize) const
2299  Error("Write const","A const TFile object should not be saved. We try to proceed anyway.");
2300  return const_cast<TFile*>(this)->Write(n, opt, bufsize);
2301 }
2302 
2303 ////////////////////////////////////////////////////////////////////////////////
2304 /// Write a buffer to the file. This is the basic low level write operation.
2305 /// Returns kTRUE in case of failure.
2306 
2307 Bool_t TFile::WriteBuffer(const char *buf, Int_t len)
2309  if (IsOpen() && fWritable) {
2310 
2311  Int_t st;
2312  if ((st = WriteBufferViaCache(buf, len))) {
2313  if (st == 2)
2314  return kTRUE;
2315  return kFALSE;
2316  }
2317 
2318  ssize_t siz;
2320  while ((siz = SysWrite(fD, buf, len)) < 0 && GetErrno() == EINTR)
2321  ResetErrno();
2323  if (siz < 0) {
2324  // Write the system error only once for this file
2325  SetBit(kWriteError); SetWritable(kFALSE);
2326  SysError("WriteBuffer", "error writing to file %s (%ld)", GetName(), (Long_t)siz);
2327  return kTRUE;
2328  }
2329  if (siz != len) {
2330  SetBit(kWriteError);
2331  Error("WriteBuffer", "error writing all requested bytes to file %s, wrote %ld of %d",
2332  GetName(), (Long_t)siz, len);
2333  return kTRUE;
2334  }
2335  fBytesWrite += siz;
2336  fgBytesWrite += siz;
2337 
2338  if (gMonitoringWriter)
2340 
2341  return kFALSE;
2342  }
2343  return kTRUE;
2344 }
2345 
2346 ////////////////////////////////////////////////////////////////////////////////
2347 /// Write buffer via cache. Returns 0 if cache is not active, 1 in case
2348 /// write via cache was successful, 2 in case write via cache failed.
2349 
2350 Int_t TFile::WriteBufferViaCache(const char *buf, Int_t len)
2352  if (!fCacheWrite) return 0;
2353 
2354  Int_t st;
2355  Long64_t off = GetRelOffset();
2356  if ((st = fCacheWrite->WriteBuffer(buf, off, len)) < 0) {
2357  SetBit(kWriteError);
2358  Error("WriteBuffer", "error writing to cache");
2359  return 2;
2360  }
2361  if (st > 0) {
2362  // fOffset might have been changed via TFileCacheWrite::WriteBuffer(), reset it
2363  Seek(off + len);
2364  return 1;
2365  }
2366  return 0;
2367 }
2368 
2369 ////////////////////////////////////////////////////////////////////////////////
2370 /// Write FREE linked list on the file.
2371 /// The linked list of FREE segments (fFree) is written as a single data
2372 /// record.
2373 
2374 void TFile::WriteFree()
2376  //*-* Delete old record if it exists
2377  if (fSeekFree != 0){
2378  MakeFree(fSeekFree, fSeekFree + fNbytesFree -1);
2379  }
2380 
2381  Int_t nbytes = 0;
2382  TFree *afree;
2383  TIter next (fFree);
2384  while ((afree = (TFree*) next())) {
2385  nbytes += afree->Sizeof();
2386  }
2387  if (!nbytes) return;
2388 
2389  TKey *key = new TKey(fName,fTitle,IsA(),nbytes,this);
2390  if (key->GetSeekKey() == 0) {
2391  delete key;
2392  return;
2393  }
2394  char *buffer = key->GetBuffer();
2395  char *start = buffer;
2396 
2397  next.Reset();
2398  while ((afree = (TFree*) next())) {
2399  afree->FillBuffer(buffer);
2400  }
2401  if ( (buffer-start)!=nbytes ) {
2402  // Most likely one of the 'free' segment was used to store this
2403  // TKey, so we had one less TFree to store than we planned.
2404  memset(buffer,0,nbytes-(buffer-start));
2405  }
2406  fNbytesFree = key->GetNbytes();
2407  fSeekFree = key->GetSeekKey();
2408  key->WriteFile();
2409  delete key;
2410 }
2411 
2412 ////////////////////////////////////////////////////////////////////////////////
2413 /// Write File Header.
2414 
2415 void TFile::WriteHeader()
2417  SafeDelete(fInfoCache);
2418  TFree *lastfree = (TFree*)fFree->Last();
2419  if (lastfree) fEND = lastfree->GetFirst();
2420  const char *root = "root";
2421  char *psave = new char[fBEGIN];
2422  char *buffer = psave;
2423  Int_t nfree = fFree->GetSize();
2424  memcpy(buffer, root, 4); buffer += 4;
2425  Int_t version = fVersion;
2426  if (version <1000000 && fEND > kStartBigFile) {version += 1000000; fUnits = 8;}
2427  tobuf(buffer, version);
2428  tobuf(buffer, (Int_t)fBEGIN);
2429  if (version < 1000000) {
2430  tobuf(buffer, (Int_t)fEND);
2431  tobuf(buffer, (Int_t)fSeekFree);
2432  tobuf(buffer, fNbytesFree);
2433  tobuf(buffer, nfree);
2434  tobuf(buffer, fNbytesName);
2435  tobuf(buffer, fUnits);
2436  tobuf(buffer, fCompress);
2437  tobuf(buffer, (Int_t)fSeekInfo);
2438  tobuf(buffer, fNbytesInfo);
2439  } else {
2440  tobuf(buffer, fEND);
2441  tobuf(buffer, fSeekFree);
2442  tobuf(buffer, fNbytesFree);
2443  tobuf(buffer, nfree);
2444  tobuf(buffer, fNbytesName);
2445  tobuf(buffer, fUnits);
2446  tobuf(buffer, fCompress);
2447  tobuf(buffer, fSeekInfo);
2448  tobuf(buffer, fNbytesInfo);
2449  }
2450  fUUID.FillBuffer(buffer);
2451  Int_t nbytes = buffer - psave;
2452  Seek(0);
2453  WriteBuffer(psave, nbytes);
2454  Flush(); // Intentionally not conditional on fMustFlush, this is the 'obligatory' flush.
2455  delete [] psave;
2456 }
2457 
2458 ////////////////////////////////////////////////////////////////////////////////
2459 /// Generate source code necessary to access the objects stored in the file.
2460 ///
2461 /// Generate code in directory dirname for all classes specified in
2462 /// argument classes If classes = "*" (default and currently the
2463 /// only supported value), the function generates an include file
2464 /// for each class in the StreamerInfo list for which a TClass
2465 /// object does not exist.
2466 ///
2467 /// The code generated includes:
2468 /// - <em>dirnameProjectHeaders.h</em>, which contains one #include statement per generated header file
2469 /// - <em>dirnameProjectSource.cxx</em>,which contains all the constructors and destructors implementation.
2470 /// and one header per class that is not nested inside another class.
2471 /// The header file name is the fully qualified name of the class after all the special characters
2472 /// "<>,:" are replaced by underscored. For example for std::pair<edm::Vertex,int> the file name is
2473 /// pair_edm__Vertex_int_.h
2474 ///
2475 /// In the generated classes, map, multimap when the first template parameter is a class
2476 /// are replaced by a vector of pair. set and multiset when the tempalte parameter
2477 /// is a class are replaced by a vector. This is required since we do not have the
2478 /// code needed to order and/or compare the object of the classes.
2479 /// This is a quick explanation of the options available:
2480 /// Option | Details
2481 /// -------|--------
2482 /// new (default) | A new directory dirname is created. If dirname already exist, an error message is printed and the function returns.
2483 /// 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.
2484 /// 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".
2485 /// genreflex | Use genreflex rather than rootcint to generate the dictionary.
2486 /// 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).
2487 ///
2488 /// If, in addition to one of the 3 above options, the option "+" is specified,
2489 /// the function will generate:
2490 /// - a script called MAKEP to build the shared lib
2491 /// - a dirnameLinkDef.h file
2492 /// - rootcint will be run to generate a dirnameProjectDict.cxx file
2493 /// - dirnameProjectDict.cxx will be compiled with the current options in compiledata.h
2494 /// - a shared lib dirname.so will be created.
2495 /// If the option "++" is specified, the generated shared lib is dynamically
2496 /// linked with the current executable module.
2497 /// If the option "+" and "nocompile" are specified, the utility files are generated
2498 /// as in the option "+" but they are not executed.
2499 /// Example:
2500 /// file.MakeProject("demo","*","recreate++");
2501 /// - creates a new directory demo unless it already exist
2502 /// - clear the previous directory content
2503 /// - generate the xxx.h files for all classes xxx found in this file
2504 /// and not yet known to the CINT dictionary.
2505 /// - creates the build script MAKEP
2506 /// - creates a LinkDef.h file
2507 /// - runs rootcint generating demoProjectDict.cxx
2508 /// - compiles demoProjectDict.cxx into demoProjectDict.o
2509 /// - generates a shared lib demo.so
2510 /// - dynamically links the shared lib demo.so to the executable
2511 /// If only the option "+" had been specified, one can still link the
2512 /// shared lib to the current executable module with:
2513 ///
2514 /// gSystem->load("demo/demo.so");
2515 ///
2516 /// The following feature is not yet enabled:
2517 /// One can restrict the list of classes to be generated by using expressions like:
2518 ///
2519 /// classes = "Ali*" generate code only for classes starting with Ali
2520 /// classes = "myClass" generate code for class MyClass only.
2521 ///
2522 
2523 void TFile::MakeProject(const char *dirname, const char * /*classes*/,
2524  Option_t *option)
2525 {
2526  TString opt = option;
2527  opt.ToLower();
2528  Bool_t makepar = kFALSE;
2529  TString parname, pardir;
2530  if (opt.Contains("par")) {
2531  // Create a PAR file
2532  parname = gSystem->BaseName(dirname);
2533  if (parname.EndsWith(".par")) parname.ReplaceAll(".par","");
2534  pardir = gSystem->DirName(dirname);
2535  // Cleanup or prepare the dirs
2536  TString path, filepath;
2537  void *dir = gSystem->OpenDirectory(pardir);
2538  if (dir) {
2539  path.Form("%s/%s", pardir.Data(), parname.Data());
2540  void *dirp = gSystem->OpenDirectory(path);
2541  if (dirp) {
2542  path += "/PROOF-INF";
2543  void *dirinf = gSystem->OpenDirectory(path);
2544  const char *afile = 0;
2545  if (dirinf) {
2546  while ((afile = gSystem->GetDirEntry(dirinf))) {
2547  if (strcmp(afile,".") == 0) continue;
2548  if (strcmp(afile,"..") == 0) continue;
2549  filepath.Form("%s/%s", path.Data(), afile);
2550  if (gSystem->Unlink(filepath))
2551  Warning("MakeProject", "1: problems unlinking '%s' ('%s', '%s')", filepath.Data(), path.Data(), afile);
2552  }
2553  gSystem->FreeDirectory(dirinf);
2554  }
2555  gSystem->Unlink(path);
2556  path.Form("%s/%s", pardir.Data(), parname.Data());
2557  while ((afile = gSystem->GetDirEntry(dirp))) {
2558  if (strcmp(afile,".") == 0) continue;
2559  if (strcmp(afile,"..") == 0) continue;
2560  filepath.Form("%s/%s", path.Data(), afile);
2561  if (gSystem->Unlink(filepath))
2562  Warning("MakeProject", "2: problems unlinking '%s' ('%s', '%s')", filepath.Data(), path.Data(), afile);
2563  }
2564  gSystem->FreeDirectory(dirp);
2565  if (gSystem->Unlink(path))
2566  Warning("MakeProject", "problems unlinking '%s'", path.Data());
2567  }
2568  }
2569  // Make sure that the relevant dirs exists: this is mandatory, so we fail if unsuccessful
2570  path.Form("%s/%s/PROOF-INF", pardir.Data(), parname.Data());
2571  if (gSystem->mkdir(path, kTRUE)) {
2572  Error("MakeProject", "problems creating '%s'", path.Data());
2573  return;
2574  }
2575  makepar = kTRUE;
2576 
2577  } else {
2578  void *dir = gSystem->OpenDirectory(dirname);
2579  TString dirpath;
2580 
2581  if (opt.Contains("update")) {
2582  // check that directory exist, if not create it
2583  if (dir == 0) {
2584  gSystem->mkdir(dirname);
2585  }
2586 
2587  } else if (opt.Contains("recreate")) {
2588  // check that directory exist, if not create it
2589  if (dir == 0) {
2590  if (gSystem->mkdir(dirname) < 0) {
2591  Error("MakeProject","cannot create directory '%s'",dirname);
2592  return;
2593  }
2594  }
2595  // clear directory
2596  while (dir) {
2597  const char *afile = gSystem->GetDirEntry(dir);
2598  if (afile == 0) break;
2599  if (strcmp(afile,".") == 0) continue;
2600  if (strcmp(afile,"..") == 0) continue;
2601  dirpath.Form("%s/%s",dirname,afile);
2602  gSystem->Unlink(dirpath);
2603  }
2604 
2605  } else {
2606  // new is assumed
2607  // if directory already exist, print error message and return
2608  if (dir) {
2609  Error("MakeProject","cannot create directory %s, already existing",dirname);
2610  gSystem->FreeDirectory(dir);
2611  return;
2612  }
2613  if (gSystem->mkdir(dirname) < 0) {
2614  Error("MakeProject","cannot create directory '%s'",dirname);
2615  return;
2616  }
2617  }
2618  if (dir) {
2619  gSystem->FreeDirectory(dir);
2620  }
2621  }
2622  Bool_t genreflex = opt.Contains("genreflex");
2623 
2624  // we are now ready to generate the classes
2625  // loop on all TStreamerInfo
2626  TList *filelist = (TList*)GetStreamerInfoCache();
2627  if (filelist) filelist = (TList*)filelist->Clone();
2628  if (filelist == 0) {
2629  Error("MakeProject","file %s has no StreamerInfo", GetName());
2630  return;
2631  }
2632 
2633  TString clean_dirname(dirname);
2634  if (makepar) clean_dirname.Form("%s/%s", pardir.Data(), parname.Data());
2635  if (clean_dirname[clean_dirname.Length()-1]=='/') {
2636  clean_dirname.Remove(clean_dirname.Length()-1);
2637  } else if (clean_dirname[clean_dirname.Length()-1]=='\\') {
2638  clean_dirname.Remove(clean_dirname.Length()-1);
2639  if (clean_dirname[clean_dirname.Length()-1]=='\\') {
2640  clean_dirname.Remove(clean_dirname.Length()-1);
2641  }
2642  }
2643  TString subdirname( gSystem->BaseName(clean_dirname) );
2644  if (makepar) subdirname = parname;
2645  if (subdirname == "") {
2646  Error("MakeProject","Directory name must not be empty.");
2647  return;
2648  }
2649 
2650  // Start the source file
2651  TString spath; spath.Form("%s/%sProjectSource.cxx",clean_dirname.Data(),subdirname.Data());
2652  FILE *sfp = fopen(spath.Data(),"w");
2653  if (sfp ==0) {
2654  Error("MakeProject","Unable to create the source file %s.",spath.Data());
2655  return;
2656  }
2657  fprintf(sfp, "namespace std {}\nusing namespace std;\n");
2658  fprintf(sfp, "#include \"%sProjectHeaders.h\"\n\n",subdirname.Data() );
2659  if (!genreflex) fprintf(sfp, "#include \"%sLinkDef.h\"\n\n",subdirname.Data() );
2660  fprintf(sfp, "#include \"%sProjectDict.cxx\"\n\n",subdirname.Data() );
2661  fprintf(sfp, "struct DeleteObjectFunctor {\n");
2662  fprintf(sfp, " template <typename T>\n");
2663  fprintf(sfp, " void operator()(const T *ptr) const {\n");
2664  fprintf(sfp, " delete ptr;\n");
2665  fprintf(sfp, " }\n");
2666  fprintf(sfp, " template <typename T, typename Q>\n");
2667  fprintf(sfp, " void operator()(const std::pair<T,Q> &) const {\n");
2668  fprintf(sfp, " // Do nothing\n");
2669  fprintf(sfp, " }\n");
2670  fprintf(sfp, " template <typename T, typename Q>\n");
2671  fprintf(sfp, " void operator()(const std::pair<T,Q*> &ptr) const {\n");
2672  fprintf(sfp, " delete ptr.second;\n");
2673  fprintf(sfp, " }\n");
2674  fprintf(sfp, " template <typename T, typename Q>\n");
2675  fprintf(sfp, " void operator()(const std::pair<T*,Q> &ptr) const {\n");
2676  fprintf(sfp, " delete ptr.first;\n");
2677  fprintf(sfp, " }\n");
2678  fprintf(sfp, " template <typename T, typename Q>\n");
2679  fprintf(sfp, " void operator()(const std::pair<T*,Q*> &ptr) const {\n");
2680  fprintf(sfp, " delete ptr.first;\n");
2681  fprintf(sfp, " delete ptr.second;\n");
2682  fprintf(sfp, " }\n");
2683  fprintf(sfp, "};\n\n");
2684  fclose( sfp );
2685 
2686  // loop on all TStreamerInfo classes to check for empty classes
2687  // and enums listed either as data member or template parameters,
2688  // and filter out 'duplicates' classes/streamerInfos.
2689  TStreamerInfo *info;
2690  TIter flnext(filelist);
2691  TList extrainfos;
2692  TList *list = new TList();
2693  while ((info = (TStreamerInfo*)flnext())) {
2694  if (info->IsA() != TStreamerInfo::Class()) {
2695  continue;
2696  }
2697  if (strstr(info->GetName(),"@@")) {
2698  // Skip schema evolution support streamerInfo
2699  continue;
2700  }
2701  TClass *cl = TClass::GetClass(info->GetName());
2702  if (cl) {
2703  if (cl->HasInterpreterInfo()) continue; // skip known classes
2704  }
2705  // Find and use the proper rules for the TStreamerInfos.
2706  TMakeProject::GenerateMissingStreamerInfos( &extrainfos, info->GetName() );
2707  TIter enext( info->GetElements() );
2708  TStreamerElement *el;
2710  if (cl && cl->GetSchemaRules()) {
2711  rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
2712  }
2713  while( (el=(TStreamerElement*)enext()) ) {
2714  for(auto rule : rules) {
2715  if( rule->IsRenameRule() || rule->IsAliasRule() )
2716  continue;
2717  // Check whether this is an 'attribute' rule.
2718  if ( rule->HasTarget( el->GetName()) && rule->GetAttributes()[0] != 0 ) {
2719  TString attr( rule->GetAttributes() );
2720  attr.ToLower();
2721  if (attr.Contains("owner")) {
2722  if (attr.Contains("notowner")) {
2723  el->SetBit(TStreamerElement::kDoNotDelete);
2724  } else {
2725  el->ResetBit(TStreamerElement::kDoNotDelete);
2726  }
2727  }
2728  }
2729  }
2731  }
2732  TVirtualStreamerInfo *alternate = (TVirtualStreamerInfo*)list->FindObject(info->GetName());
2733  if (alternate) {
2734  if ((info->GetClass() && info->GetClassVersion() == info->GetClass()->GetClassVersion())
2735  || (info->GetClassVersion() > alternate->GetClassVersion()) ) {
2736  list->AddAfter(alternate, info);
2737  list->Remove(alternate);
2738  } // otherwise ignore this info as not being the official one.
2739  } else {
2740  list->Add(info);
2741  }
2742  }
2743  // Now transfer the new StreamerInfo onto the main list and
2744  // to the owning list.
2745  TIter nextextra(&extrainfos);
2746  while ((info = (TStreamerInfo*)nextextra())) {
2747  list->Add(info);
2748  filelist->Add(info);
2749  }
2750 
2751  // loop on all TStreamerInfo classes
2752  TIter next(list);
2753  Int_t ngener = 0;
2754  while ((info = (TStreamerInfo*)next())) {
2755  if (info->IsA() != TStreamerInfo::Class()) {
2756  continue;
2757  }
2758  if (info->GetClassVersion()==-4) continue; // Skip outer level namespace
2759  TIter subnext(list);
2760  TStreamerInfo *subinfo;
2761  TList subClasses;
2762  Int_t len = strlen(info->GetName());
2763  while ((subinfo = (TStreamerInfo*)subnext())) {
2764  if (subinfo->IsA() != TStreamerInfo::Class()) {
2765  continue;
2766  }
2767  if (strncmp(info->GetName(),subinfo->GetName(),len)==0) {
2768  // The 'sub' StreamerInfo start with the main StreamerInfo name,
2769  // it subinfo is likely to be a nested class.
2770  const Int_t sublen = strlen(subinfo->GetName());
2771  if ( (sublen > len) && subinfo->GetName()[len+1]==':'
2772  && !subClasses.FindObject(subinfo->GetName()) /* We need to insure uniqueness */)
2773  {
2774  subClasses.Add(subinfo);
2775  }
2776  }
2777  }
2778  ngener += info->GenerateHeaderFile(clean_dirname.Data(),&subClasses,&extrainfos);
2779  subClasses.Clear("nodelete");
2780  }
2781  TString path;
2782  path.Form("%s/%sProjectHeaders.h",clean_dirname.Data(),subdirname.Data());
2783  FILE *allfp = fopen(path,"a");
2784  if (!allfp) {
2785  Error("MakeProject","Cannot open output file:%s\n",path.Data());
2786  } else {
2787  fprintf(allfp,"#include \"%sProjectInstances.h\"\n", subdirname.Data());
2788  fclose(allfp);
2789  }
2790 
2791  printf("MakeProject has generated %d classes in %s\n",ngener,clean_dirname.Data());
2792 
2793  // generate the shared lib
2794  if (!opt.Contains("+") && !makepar) {
2795  delete list;
2796  filelist->Delete();
2797  delete filelist;
2798  return;
2799  }
2800 
2801  // Makefiles files
2802  FILE *fpMAKE = 0;
2803  if (!makepar) {
2804  // Create the MAKEP file by looping on all *.h files
2805  // delete MAKEP if it already exists
2806 #ifdef WIN32
2807  path.Form("%s/makep.cmd",clean_dirname.Data());
2808 #else
2809  path.Form("%s/MAKEP",clean_dirname.Data());
2810 #endif
2811 #ifdef R__WINGCC
2812  fpMAKE = fopen(path,"wb");
2813 #else
2814  fpMAKE = fopen(path,"w");
2815 #endif
2816  if (!fpMAKE) {
2817  Error("MakeProject", "cannot open file %s", path.Data());
2818  delete list;
2819  filelist->Delete();
2820  delete filelist;
2821  return;
2822  }
2823  }
2824 
2825  // Add rootcint/genreflex statement generating ProjectDict.cxx
2826  FILE *ifp = 0;
2827  path.Form("%s/%sProjectInstances.h",clean_dirname.Data(),subdirname.Data());
2828 #ifdef R__WINGCC
2829  ifp = fopen(path,"wb");
2830 #else
2831  ifp = fopen(path,"w");
2832 #endif
2833  if (!ifp) {
2834  Error("MakeProject", "cannot open path file %s", path.Data());
2835  delete list;
2836  filelist->Delete();
2837  delete filelist;
2838  fclose(fpMAKE);
2839  return;
2840  }
2841 
2842  if (!makepar) {
2843  if (genreflex) {
2844  fprintf(fpMAKE,"genreflex %sProjectHeaders.h -o %sProjectDict.cxx --comments --iocomments %s ",subdirname.Data(),subdirname.Data(),gSystem->GetIncludePath());
2845  path.Form("%s/%sSelection.xml",clean_dirname.Data(),subdirname.Data());
2846  } else {
2847  fprintf(fpMAKE,"rootcint -f %sProjectDict.cxx -c %s ",subdirname.Data(),gSystem->GetIncludePath());
2848  path.Form("%s/%sLinkDef.h",clean_dirname.Data(),subdirname.Data());
2849  }
2850  } else {
2851  path.Form("%s/%sLinkDef.h",clean_dirname.Data(),subdirname.Data());
2852  }
2853 
2854  // Create the LinkDef.h or xml selection file by looping on all *.h files
2855  // replace any existing file.
2856 #ifdef R__WINGCC
2857  FILE *fp = fopen(path,"wb");
2858 #else
2859  FILE *fp = fopen(path,"w");
2860 #endif
2861  if (!fp) {
2862  Error("MakeProject", "cannot open path file %s", path.Data());
2863  delete list;
2864  filelist->Delete();
2865  delete filelist;
2866  fclose(fpMAKE);
2867  fclose(ifp);
2868  return;
2869  }
2870  if (genreflex) {
2871  fprintf(fp,"<lcgdict>\n");
2872  fprintf(fp,"\n");
2873  } else {
2874  fprintf(fp,"#ifdef __CINT__\n");
2875  fprintf(fp,"\n");
2876  }
2877 
2878  TString tmp;
2879  TString instances;
2880  TString selections;
2881  next.Reset();
2882  while ((info = (TStreamerInfo*)next())) {
2883  if (info->IsA() != TStreamerInfo::Class()) {
2884  continue;
2885  }
2886  TClass *cl = TClass::GetClass(info->GetName());
2887  if (cl) {
2888  if (cl->HasInterpreterInfo()) continue; // skip known classes
2889  if (cl->GetSchemaRules()) {
2890  auto rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
2891  TString strrule;
2892  for(auto rule : rules) {
2893  strrule.Clear();
2894  if (genreflex) {
2895  rule->AsString(strrule,"x");
2896  strrule.Append("\n");
2897  if ( selections.Index(strrule) == kNPOS ) {
2898  selections.Append(strrule);
2899  }
2900  } else {
2901  rule->AsString(strrule);
2902  if (strncmp(strrule.Data(),"type=",5)==0) {
2903  strrule.Remove(0,5);
2904  }
2905  fprintf(fp,"#pragma %s;\n",strrule.Data());
2906  }
2907  }
2908  }
2909 
2910  }
2911  if ((info->GetClass() && info->GetClass()->GetCollectionType()) || TClassEdit::IsSTLCont(info->GetName())) {
2912  std::vector<std::string> inside;
2913  int nestedLoc;
2914  TClassEdit::GetSplit( info->GetName(), inside, nestedLoc, TClassEdit::kLong64 );
2915  Int_t stlkind = TClassEdit::STLKind(inside[0].c_str());
2916  TClass *key = TClass::GetClass(inside[1].c_str());
2917  if (key) {
2918  TString what;
2919  switch ( stlkind ) {
2920  case ROOT::kSTLmap:
2921  case ROOT::kSTLmultimap:
2922  if (TClass::GetClass(inside[1].c_str())) {
2923  what = "std::pair<";
2924  what += TMakeProject::UpdateAssociativeToVector( inside[1].c_str() );
2925  what += ",";
2926  what += TMakeProject::UpdateAssociativeToVector( inside[2].c_str() );
2927  if (what[what.Length()-1]=='>') {
2928  what += " >";
2929  } else {
2930  what += ">";
2931  }
2932  if (genreflex) {
2933  tmp.Form("<class name=\"%s\" />\n",what.Data());
2934  if ( selections.Index(tmp) == kNPOS ) {
2935  selections.Append(tmp);
2936  }
2937  tmp.Form("template class %s;\n",what.Data());
2938  if ( instances.Index(tmp) == kNPOS ) {
2939  instances.Append(tmp);
2940  }
2941  } else {
2942  what.ReplaceAll("std::","");
2943  TClass *paircl = TClass::GetClass(what.Data());
2944  if (paircl == 0 || !paircl->HasInterpreterInfo()) {
2945  fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
2946  }
2947  }
2948  break;
2949  }
2950  default:
2951  if (strncmp(key->GetName(),"pair<",strlen("pair<"))==0) {
2952  if (genreflex) {
2953  tmp.Form("<class name=\"%s\" />\n",key->GetName());
2954  if ( selections.Index(tmp) == kNPOS ) {
2955  selections.Append(tmp);
2956  }
2957  tmp.Form("template class %s;\n",key->GetName());
2958  if ( instances.Index(tmp) == kNPOS ) {
2959  instances.Append(tmp);
2960  }
2961  } else {
2962  what.ReplaceAll("std::","");
2963  fprintf(fp,"#pragma link C++ class %s+;\n",key->GetName());
2964  }
2965  }
2966  break;
2967  }
2968  }
2969  continue;
2970  }
2971  {
2973  if (genreflex) {
2974  tmp.Form("<class name=\"%s\" />\n",what.Data());
2975  if ( selections.Index(tmp) == kNPOS ) {
2976  selections.Append(tmp);
2977  }
2978  if (what[what.Length()-1] == '>') {
2979  tmp.Form("template class %s;\n",what.Data());
2980  if ( instances.Index(tmp) == kNPOS ) {
2981  instances.Append(tmp);
2982  }
2983  }
2984  } else {
2985  what.ReplaceAll("std::","");
2986  fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
2987  }
2988  }
2989  if (genreflex) {
2990  // Also request the dictionary for the STL container used as members ...
2991  TIter eliter( info->GetElements() );
2992  TStreamerElement *element;
2993  while( (element = (TStreamerElement*)eliter() ) ) {
2994  if (element->GetClass() && !element->GetClass()->IsLoaded() && element->GetClass()->GetCollectionProxy()) {
2995  TString what( TMakeProject::UpdateAssociativeToVector(element->GetClass()->GetName()) );
2996  tmp.Form("<class name=\"%s\" />\n",what.Data());
2997  if ( selections.Index(tmp) == kNPOS ) {
2998  selections.Append(tmp);
2999  }
3000  tmp.Form("template class %s;\n",what.Data());
3001  if ( instances.Index(tmp) == kNPOS ) {
3002  instances.Append(tmp);
3003  }
3004  }
3005  }
3006  }
3007  }
3008  if (genreflex) {
3009  fprintf(ifp,"#ifndef PROJECT_INSTANCES_H\n");
3010  fprintf(ifp,"#define PROJECT_INSTANCES_H\n");
3011  fprintf(ifp,"%s",instances.Data());
3012  fprintf(ifp,"#endif\n");
3013  fprintf(fp,"%s",selections.Data());
3014  fprintf(fp,"</lcgdict>\n");
3015  } else {
3016  fprintf(fp,"#endif\n");
3017  }
3018  fclose(fp);
3019  fclose(ifp);
3020 
3021  if (!makepar) {
3022  // add compilation line
3023  TString sdirname(subdirname);
3024 
3025  TString cmd = gSystem->GetMakeSharedLib();
3026  TString sources = TString::Format("%sProjectSource.cxx ", sdirname.Data());
3027  cmd.ReplaceAll("$SourceFiles",sources.Data());
3028  TString object = TString::Format("%sProjectSource.", sdirname.Data());
3029  object.Append( gSystem->GetObjExt() );
3030  cmd.ReplaceAll("$ObjectFiles", object.Data());
3031  cmd.ReplaceAll("$IncludePath",TString(gSystem->GetIncludePath()) + " -I" + clean_dirname.Data());
3032  cmd.ReplaceAll("$SharedLib",sdirname+"."+gSystem->GetSoExt());
3033  cmd.ReplaceAll("$LinkedLibs",gSystem->GetLibraries("","SDL"));
3034  cmd.ReplaceAll("$LibName",sdirname);
3035  cmd.ReplaceAll("$BuildDir",".");
3036  TString sOpt;
3037  TString rootbuild = ROOTBUILD;
3038  if (rootbuild.Index("debug",0,TString::kIgnoreCase)==kNPOS) {
3039  sOpt = gSystem->GetFlagsOpt();
3040  } else {
3041  sOpt = gSystem->GetFlagsDebug();
3042  }
3043  cmd.ReplaceAll("$Opt", sOpt);
3044 
3045  if (genreflex) {
3046  fprintf(fpMAKE,"-s %sSelection.xml \n",subdirname.Data());
3047  } else {
3048  fprintf(fpMAKE,"%sProjectHeaders.h ",subdirname.Data());
3049  fprintf(fpMAKE,"%sLinkDef.h \n",subdirname.Data());
3050  }
3051 
3052  fprintf(fpMAKE,"%s\n",cmd.Data());
3053 
3054  printf("%s/MAKEP file has been generated\n", clean_dirname.Data());
3055 
3056  fclose(fpMAKE);
3057 
3058  } else {
3059 
3060  // Create the Makefile
3061  TString filemake = TString::Format("%s/Makefile", clean_dirname.Data());
3062  if (MakeProjectParMake(parname, filemake.Data()) != 0) {
3063  Error("MakeProject", "problems creating PAR make file '%s'", filemake.Data());
3064  delete list;
3065  filelist->Delete();
3066  delete filelist;
3067  return;
3068  }
3069  // Get Makefile.arch
3070 #ifdef ROOTETCDIR
3071  TString mkarchsrc = TString::Format("%s/Makefile.arch", ROOTETCDIR);
3072 #else
3073  TString mkarchsrc("$(ROOTSYS)/etc/Makefile.arch");
3074 #endif
3075  if (gSystem->ExpandPathName(mkarchsrc))
3076  Warning("MakeProject", "problems expanding '%s'", mkarchsrc.Data());
3077  TString mkarchdst = TString::Format("%s/Makefile.arch", clean_dirname.Data());
3078  if (gSystem->CopyFile(mkarchsrc.Data(), mkarchdst.Data(), kTRUE) != 0) {
3079  Error("MakeProject", "problems retrieving '%s' to '%s'", mkarchsrc.Data(), mkarchdst.Data());
3080  delete list;
3081  filelist->Delete();
3082  delete filelist;
3083  return;
3084  }
3085  // Create the Makefile
3086  TString proofinf = TString::Format("%s/PROOF-INF", clean_dirname.Data());
3087  if (MakeProjectParProofInf(parname, proofinf.Data()) != 0) {
3088  Error("MakeProject", "problems creating BUILD.sh and/or SETUP.C under '%s'", proofinf.Data());
3089  delete list;
3090  filelist->Delete();
3091  delete filelist;
3092  return;
3093  }
3094 
3095  // Make sure BUILD.sh is executable and create SETUP.C
3096  TString cmod = TString::Format("chmod +x %s/PROOF-INF/BUILD.sh", clean_dirname.Data());
3097 #ifndef WIN32
3098  gSystem->Exec(cmod.Data());
3099 #else
3100  // not really needed for Windows but it would work both both Unix and NT
3101  chmod(cmod.Data(), 00700);
3102 #endif
3103  Printf("Files Makefile, Makefile.arch, PROOF-INF/BUILD.sh and"
3104  " PROOF-INF/SETUP.C have been generated under '%s'", clean_dirname.Data());
3105 
3106  // Generate the PAR file, if not Windows
3107 #ifndef WIN32
3108  TString curdir = gSystem->WorkingDirectory();
3109  if (gSystem->ChangeDirectory(pardir)) {
3110  TString cmd = TString::Format("tar czvf %s.par %s", parname.Data(), parname.Data());
3111  gSystem->Exec(cmd.Data());
3112  if (gSystem->ChangeDirectory(curdir)) {
3113  Info("MakeProject", "PAR file %s.par generated", clean_dirname.Data());
3114  } else {
3115  Warning("MakeProject", "problems changing directory back to '%s'", curdir.Data());
3116  }
3117  } else {
3118  Error("MakeProject", "problems changing directory to '%s' - skipping PAR file generation", pardir.Data());
3119  }
3120 #else
3121  Warning("MakeProject", "on Windows systems the PAR file cannot be generated out of the package directory!");
3122 #endif
3123  }
3124 
3125 
3126  if (!makepar && !opt.Contains("nocompilation")) {
3127  // now execute the generated script compiling and generating the shared lib
3128  path = gSystem->WorkingDirectory();
3129  gSystem->ChangeDirectory(clean_dirname.Data());
3130 #ifndef WIN32
3131  gSystem->Exec("chmod +x MAKEP");
3132  int res = !gSystem->Exec("./MAKEP");
3133 #else
3134  // not really needed for Windows but it would work both both Unix and NT
3135  chmod("makep.cmd",00700);
3136  int res = !gSystem->Exec("MAKEP");
3137 #endif
3138  gSystem->ChangeDirectory(path);
3139  path.Form("%s/%s.%s",clean_dirname.Data(),subdirname.Data(),gSystem->GetSoExt());
3140  if (res) printf("Shared lib %s has been generated\n",path.Data());
3141 
3142  //dynamically link the generated shared lib
3143  if (opt.Contains("++")) {
3144  res = !gSystem->Load(path);
3145  if (res) printf("Shared lib %s has been dynamically linked\n",path.Data());
3146  }
3147  }
3148 
3149  extrainfos.Clear("nodelete");
3150  // filelist->Clear("nodetele");
3151  delete list;
3152  filelist->Delete();
3153  delete filelist;
3154 }
3155 
3156 ////////////////////////////////////////////////////////////////////////////////
3157 /// Create makefile at 'filemake' for PAR package 'pack'.
3158 ///
3159 /// Called by MakeProject when option 'par' is given.
3160 /// Return 0 on success, -1 on error.
3161 
3162 Int_t TFile::MakeProjectParMake(const char *pack, const char *filemake)
3164  // Output file path must be defined
3165  if (!filemake || (filemake && strlen(filemake) <= 0)) {
3166  Error("MakeProjectParMake", "path for output file undefined!");
3167  return -1;
3168  }
3169 
3170  // Package name must be defined
3171  if (!pack || (pack && strlen(pack) <= 0)) {
3172  Error("MakeProjectParMake", "package name undefined!");
3173  return -1;
3174  }
3175 
3176 #ifdef R__WINGCC
3177  FILE *fmk = fopen(filemake, "wb");
3178 #else
3179  FILE *fmk = fopen(filemake, "w");
3180 #endif
3181  if (!fmk) {
3182  Error("MakeProjectParMake", "cannot create file '%s' (errno: %d)", filemake, TSystem::GetErrno());
3183  return -1;
3184  }
3185 
3186  // Fill the file now
3187  fprintf(fmk, "# Makefile for the ROOT test programs.\n");
3188  fprintf(fmk, "# This Makefile shows how to compile and link applications\n");
3189  fprintf(fmk, "# using the ROOT libraries on all supported platforms.\n");
3190  fprintf(fmk, "#\n");
3191  fprintf(fmk, "# Copyright (c) 2000 Rene Brun and Fons Rademakers\n");
3192  fprintf(fmk, "#\n");
3193  fprintf(fmk, "# Author: this makefile has been automatically generated via TFile::MakeProject\n");
3194  fprintf(fmk, "\n");
3195  fprintf(fmk, "include Makefile.arch\n");
3196  fprintf(fmk, "\n");
3197  fprintf(fmk, "#------------------------------------------------------------------------------\n");
3198  fprintf(fmk, "\n");
3199  fprintf(fmk, "PACKO = %sProjectSource.$(ObjSuf)\n", pack);
3200  fprintf(fmk, "PACKS = %sProjectSource.$(SrcSuf) %sProjectDict.$(SrcSuf)\n", pack, pack);
3201  fprintf(fmk, "PACKSO = lib%s.$(DllSuf)\n", pack);
3202  fprintf(fmk, "\n");
3203  fprintf(fmk, "ifeq ($(PLATFORM),win32)\n");
3204  fprintf(fmk, "PACKLIB = lib%s.lib\n", pack);
3205  fprintf(fmk, "else\n");
3206  fprintf(fmk, "PACKLIB = $(PACKSO)\n");
3207  fprintf(fmk, "endif\n");
3208  fprintf(fmk, "\n");
3209  fprintf(fmk, "OBJS = $(PACKO)\n");
3210  fprintf(fmk, "\n");
3211  fprintf(fmk, "PROGRAMS =\n");
3212  fprintf(fmk, "\n");
3213  fprintf(fmk, "#------------------------------------------------------------------------------\n");
3214  fprintf(fmk, "\n");
3215  fprintf(fmk, ".SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(DllSuf)\n");
3216  fprintf(fmk, "\n");
3217  fprintf(fmk, "all: $(PACKLIB)\n");
3218  fprintf(fmk, "\n");
3219  fprintf(fmk, "$(PACKSO): $(PACKO)\n");
3220  fprintf(fmk, "ifeq ($(ARCH),aix)\n");
3221  fprintf(fmk, "\t\t/usr/ibmcxx/bin/makeC++SharedLib $(OutPutOpt) $@ $(LIBS) -p 0 $^\n");
3222  fprintf(fmk, "else\n");
3223  fprintf(fmk, "ifeq ($(ARCH),aix5)\n");
3224  fprintf(fmk, "\t\t/usr/vacpp/bin/makeC++SharedLib $(OutPutOpt) $@ $(LIBS) -p 0 $^\n");
3225  fprintf(fmk, "else\n");
3226  fprintf(fmk, "ifeq ($(PLATFORM),macosx)\n");
3227  fprintf(fmk, "# We need to make both the .dylib and the .so\n");
3228  fprintf(fmk, "\t\t$(LD) $(SOFLAGS)$@ $(LDFLAGS) $^ $(OutPutOpt) $@ $(LIBS)\n");
3229  fprintf(fmk, "ifneq ($(subst $(MACOSX_MINOR),,1234),1234)\n");
3230  fprintf(fmk, "ifeq ($(MACOSX_MINOR),4)\n");
3231  fprintf(fmk, "\t\tln -sf $@ $(subst .$(DllSuf),.so,$@)\n");
3232  fprintf(fmk, "else\n");
3233  fprintf(fmk, "\t\t$(LD) -bundle -undefined $(UNDEFOPT) $(LDFLAGS) $^ \\\n");
3234  fprintf(fmk, "\t\t $(OutPutOpt) $(subst .$(DllSuf),.so,$@)\n");
3235  fprintf(fmk, "endif\n");
3236  fprintf(fmk, "endif\n");
3237  fprintf(fmk, "else\n");
3238  fprintf(fmk, "ifeq ($(PLATFORM),win32)\n");
3239  fprintf(fmk, "\t\tbindexplib $* $^ > $*.def\n");
3240  fprintf(fmk, "\t\tlib -nologo -MACHINE:IX86 $^ -def:$*.def \\\n");
3241  fprintf(fmk, "\t\t $(OutPutOpt)$(PACKLIB)\n");
3242  fprintf(fmk, "\t\t$(LD) $(SOFLAGS) $(LDFLAGS) $^ $*.exp $(LIBS) \\\n");
3243  fprintf(fmk, "\t\t $(OutPutOpt)$@\n");
3244  fprintf(fmk, "else\n");
3245  fprintf(fmk, "\t\t$(LD) $(SOFLAGS) $(LDFLAGS) $^ $(OutPutOpt) $@ $(LIBS) $(EXPLLINKLIBS)\n");
3246  fprintf(fmk, "endif\n");
3247  fprintf(fmk, "endif\n");
3248  fprintf(fmk, "endif\n");
3249  fprintf(fmk, "endif\n");
3250  fprintf(fmk, "\t\t@echo \"$@ done\"\n");
3251  fprintf(fmk, "\n");
3252  fprintf(fmk, "clean:\n");
3253  fprintf(fmk, "\t\t@rm -f $(OBJS) core\n");
3254  fprintf(fmk, "\n");
3255  fprintf(fmk, "distclean: clean\n");
3256  fprintf(fmk, "\t\t@rm -f $(PROGRAMS) $(PACKSO) $(PACKLIB) *Dict.* *.def *.exp \\\n");
3257  fprintf(fmk, "\t\t *.so *.lib *.dll *.d *.log .def so_locations\n");
3258  fprintf(fmk, "\t\t@rm -rf cxx_repository\n");
3259  fprintf(fmk, "\n");
3260  fprintf(fmk, "# Dependencies\n");
3261  fprintf(fmk, "\n");
3262  fprintf(fmk, "%sProjectSource.$(ObjSuf): %sProjectHeaders.h %sLinkDef.h %sProjectDict.$(SrcSuf)\n", pack, pack, pack, pack);
3263  fprintf(fmk, "\n");
3264  fprintf(fmk, "%sProjectDict.$(SrcSuf): %sProjectHeaders.h %sLinkDef.h\n", pack, pack, pack);
3265  fprintf(fmk, "\t\t@echo \"Generating dictionary $@...\"\n");
3266  fprintf(fmk, "\t\t@rootcint -f $@ -c $^\n");
3267  fprintf(fmk, "\n");
3268  fprintf(fmk, ".$(SrcSuf).$(ObjSuf):\n");
3269  fprintf(fmk, "\t\t$(CXX) $(CXXFLAGS) -c $<\n");
3270  fprintf(fmk, "\n");
3271 
3272  // Close the file
3273  fclose(fmk);
3274 
3275  // Done
3276  return 0;
3277 }
3278 
3279 ////////////////////////////////////////////////////////////////////////////////
3280 /// Create BUILD.sh and SETUP.C under 'proofinf' for PAR package 'pack'.
3281 /// Called by MakeProject when option 'par' is given.
3282 /// Return 0 on success, -1 on error.
3283 
3284 Int_t TFile::MakeProjectParProofInf(const char *pack, const char *proofinf)
3286  // Output directory path must be defined ...
3287  if (!proofinf || (proofinf && strlen(proofinf) <= 0)) {
3288  Error("MakeProjectParProofInf", "directory path undefined!");
3289  return -1;
3290  }
3291 
3292  // ... and exist and be a directory
3293  Int_t rcst = 0;
3294  FileStat_t st;
3295  if ((rcst = gSystem->GetPathInfo(proofinf, st)) != 0 || !R_ISDIR(st.fMode)) {
3296  Error("MakeProjectParProofInf", "path '%s' %s", proofinf,
3297  ((rcst == 0) ? "is not a directory" : "does not exist"));
3298  return -1;
3299  }
3300 
3301  // Package name must be defined
3302  if (!pack || (pack && strlen(pack) <= 0)) {
3303  Error("MakeProjectParProofInf", "package name undefined!");
3304  return -1;
3305  }
3306 
3307  TString path;
3308 
3309  // The BUILD.sh first
3310  path.Form("%s/BUILD.sh", proofinf);
3311 #ifdef R__WINGCC
3312  FILE *f = fopen(path.Data(), "wb");
3313 #else
3314  FILE *f = fopen(path.Data(), "w");
3315 #endif
3316  if (!f) {
3317  Error("MakeProjectParProofInf", "cannot create file '%s' (errno: %d)",
3318  path.Data(), TSystem::GetErrno());
3319  return -1;
3320  }
3321 
3322  fprintf(f, "#! /bin/sh\n");
3323  fprintf(f, "# Build libEvent library.\n");
3324  fprintf(f, "\n");
3325  fprintf(f, "#\n");
3326  fprintf(f, "# The environment variables ROOTPROOFLITE and ROOTPROOFCLIENT can be used to\n");
3327  fprintf(f, "# adapt the script to the calling environment\n");
3328  fprintf(f, "#\n");
3329  fprintf(f, "# if test ! \"x$ROOTPROOFLITE\" = \"x\"; then\n");
3330  fprintf(f, "# echo \"event-BUILD: PROOF-Lite node (session has $ROOTPROOFLITE workers)\"\n");
3331  fprintf(f, "# elif test ! \"x$ROOTPROOFCLIENT\" = \"x\"; then\n");
3332  fprintf(f, "# echo \"event-BUILD: PROOF client\"\n");
3333  fprintf(f, "# else\n");
3334  fprintf(f, "# echo \"event-BUILD: standard PROOF node\"\n");
3335  fprintf(f, "# fi\n");
3336  fprintf(f, "\n");
3337  fprintf(f, "if [ \"\" = \"clean\" ]; then\n");
3338  fprintf(f, " make distclean\n");
3339  fprintf(f, " exit 0\n");
3340  fprintf(f, "fi\n");
3341  fprintf(f, "\n");
3342  fprintf(f, "make\n");
3343  fprintf(f, "rc=$?\n");
3344  fprintf(f, "echo \"rc=$?\"\n");
3345  fprintf(f, "if [ $? != \"0\" ] ; then\n");
3346  fprintf(f, " exit 1\n");
3347  fprintf(f, "fi\n");
3348  fprintf(f, "exit 0\n");
3349 
3350  // Close the file
3351  fclose(f);
3352 
3353  // Then SETUP.C
3354  path.Form("%s/SETUP.C", proofinf);
3355 #ifdef R__WINGCC
3356  f = fopen(path.Data(), "wb");
3357 #else
3358  f = fopen(path.Data(), "w");
3359 #endif
3360  if (!f) {
3361  Error("MakeProjectParProofInf", "cannot create file '%s' (errno: %d)",
3362  path.Data(), TSystem::GetErrno());
3363  return -1;
3364  }
3365 
3366  fprintf(f, "Int_t SETUP()\n");
3367  fprintf(f, "{\n");
3368  fprintf(f, "\n");
3369  fprintf(f, "//\n");
3370  fprintf(f, "// The environment variables ROOTPROOFLITE and ROOTPROOFCLIENT can be used to\n");
3371  fprintf(f, "// adapt the macro to the calling environment\n");
3372  fprintf(f, "//\n");
3373  fprintf(f, "// if (gSystem->Getenv(\"ROOTPROOFLITE\")) {\n");
3374  fprintf(f, "// Printf(\"event-SETUP: PROOF-Lite node (session has %%s workers)\",\n");
3375  fprintf(f, "// gSystem->Getenv(\"ROOTPROOFLITE\"));\n");
3376  fprintf(f, "// } else if (gSystem->Getenv(\"ROOTPROOFCLIENT\")) {\n");
3377  fprintf(f, "// Printf(\"event-SETUP: PROOF client\");\n");
3378  fprintf(f, "// } else {\n");
3379  fprintf(f, "// Printf(\"event-SETUP: standard PROOF node\");\n");
3380  fprintf(f, "// }\n");
3381  fprintf(f, "\n");
3382  fprintf(f, " if (gSystem->Load(\"lib%s\") == -1)\n", pack);
3383  fprintf(f, " return -1;\n");
3384  fprintf(f, " return 0;\n");
3385  fprintf(f, "}\n");
3386  fprintf(f, "\n");
3387 
3388  // Close the file
3389  fclose(f);
3390 
3391  // Done
3392  return 0;
3393 }
3394 
3395 ////////////////////////////////////////////////////////////////////////////////
3396 /// Read the list of StreamerInfo from this file.
3397 ///
3398 /// The key with name holding the list of TStreamerInfo objects is read.
3399 /// The corresponding TClass objects are updated.
3400 /// Note that this function is not called if the static member fgReadInfo is false.
3401 /// (see TFile::SetReadStreamerInfo)
3402 
3405  TList *list = GetStreamerInfoList();
3406  if (!list) {
3407  MakeZombie();
3408  return;
3409  }
3410 
3411  list->SetOwner(kFALSE);
3412 
3413  if (gDebug > 0) Info("ReadStreamerInfo", "called for file %s",GetName());
3414 
3415  TStreamerInfo *info;
3416 
3417  Int_t version = fVersion;
3418  if (version > 1000000) version -= 1000000;
3419  if (version < 53419 || (59900 < version && version < 59907)) {
3420  // We need to update the fCheckSum field of the TStreamerBase.
3421 
3422  // loop on all TStreamerInfo classes
3423  TObjLink *lnk = list->FirstLink();
3424  while (lnk) {
3425  info = (TStreamerInfo*)lnk->GetObject();
3426  if (info == 0 || info->IsA() != TStreamerInfo::Class()) {
3427  lnk = lnk->Next();
3428  continue;
3429  }
3430  TIter next(info->GetElements());
3431  TStreamerElement *element;
3432  while ((element = (TStreamerElement*) next())) {
3433  TStreamerBase *base = dynamic_cast<TStreamerBase*>(element);
3434  if (!base) continue;
3435  if (base->GetBaseCheckSum() != 0) continue;
3436  TStreamerInfo *baseinfo = (TStreamerInfo*)list->FindObject(base->GetName());
3437  if (baseinfo) {
3438  base->SetBaseCheckSum(baseinfo->GetCheckSum());
3439  }
3440  }
3441  lnk = lnk->Next();
3442  }
3443  }
3444 
3445  // loop on all TStreamerInfo classes
3446  for (int mode=0;mode<2; ++mode) {
3447  // In order for the collection proxy to be initialized properly, we need
3448  // to setup the TStreamerInfo for non-stl class before the stl classes.
3449  TObjLink *lnk = list->FirstLink();
3450  while (lnk) {
3451  info = (TStreamerInfo*)lnk->GetObject();
3452  if (info == 0) {
3453  lnk = lnk->Next();
3454  continue;
3455  }
3456  if (info->IsA() != TStreamerInfo::Class()) {
3457  if (mode==1) {
3458  TObject *obj = (TObject*)info;
3459  if (strcmp(obj->GetName(),"listOfRules")==0) {
3460 #if 0
3461  // Completely ignore the rules for now.
3462  TList *listOfRules = (TList*)obj;
3463  TObjLink *rulelnk = listOfRules->FirstLink();
3464  while (rulelnk) {
3465  TObjString *rule = (TObjString*)rulelnk->GetObject();
3466  TClass::AddRule( rule->String().Data() );
3467  rulelnk = rulelnk->Next();
3468  }
3469 #endif
3470  } else {
3471  Warning("ReadStreamerInfo","%s has a %s in the list of TStreamerInfo.", GetName(), info->IsA()->GetName());
3472  }
3473  info->SetBit(kCanDelete);
3474  }
3475  lnk = lnk->Next();
3476  continue;
3477  }
3478  // This is a quick way (instead of parsing the name) to see if this is
3479  // the description of an STL container.
3480  if (info->GetElements()==0) {
3481  Warning("ReadStreamerInfo","The StreamerInfo for %s does not have a list of elements.",info->GetName());
3482  lnk = lnk->Next();
3483  continue;
3484  }
3485  TObject *element = info->GetElements()->UncheckedAt(0);
3486  Bool_t isstl = element && strcmp("This",element->GetName())==0;
3487 
3488  if ( (!isstl && mode ==0) || (isstl && mode ==1) ) {
3489  // Skip the STL container the first time around
3490  // Skip the regular classes the second time around;
3491  info->BuildCheck(this);
3492  Int_t uid = info->GetNumber();
3493  Int_t asize = fClassIndex->GetSize();
3494  if (uid >= asize && uid <100000) fClassIndex->Set(2*asize);
3495  if (uid >= 0 && uid < fClassIndex->GetSize()) fClassIndex->fArray[uid] = 1;
3496  else {
3497  printf("ReadStreamerInfo, class:%s, illegal uid=%d\n",info->GetName(),uid);
3498  }
3499  if (gDebug > 0) printf(" -class: %s version: %d info read at slot %d\n",info->GetName(), info->GetClassVersion(),uid);
3500  }
3501  lnk = lnk->Next();
3502  }
3503  }
3504  fClassIndex->fArray[0] = 0;
3505  list->Clear(); //this will delete all TStreamerInfo objects with kCanDelete bit set
3506  delete list;
3507 }
3508 
3509 ////////////////////////////////////////////////////////////////////////////////
3510 /// Specify if the streamerinfos must be read at file opening.
3511 ///
3512 /// If fgReadInfo is true (default) TFile::ReadStreamerInfo is called
3513 /// when opening the file.
3514 /// It may be interesting to set fgReadInfo to false to speedup the file
3515 /// opening time or in case libraries containing classes referenced
3516 /// by the file have not yet been loaded.
3517 /// if fgReadInfo is false, one can still read the StreamerInfo with
3518 /// myfile.ReadStreamerInfo();
3519 
3520 void TFile::SetReadStreamerInfo(Bool_t readinfo)
3522  fgReadInfo = readinfo;
3523 }
3524 
3525 ////////////////////////////////////////////////////////////////////////////////
3526 /// If the streamerinfos are to be read at file opening.
3527 ///
3528 /// See TFile::SetReadStreamerInfo for more documentation.
3529 
3532  return fgReadInfo;
3533 }
3534 
3535 ////////////////////////////////////////////////////////////////////////////////
3536 /// Show the StreamerInfo of all classes written to this file.
3537 
3540  TList *list = GetStreamerInfoList();
3541  if (!list) return;
3542 
3543  list->ls();
3544  delete list;
3545 }
3546 
3547 ////////////////////////////////////////////////////////////////////////////////
3548 /// Check if the ProcessID pidd is already in the file,
3549 /// if not, add it and return the index number in the local file list.
3550 
3553  TProcessID *pid = pidd;
3554  if (!pid) pid = TProcessID::GetPID();
3555  TObjArray *pids = GetListOfProcessIDs();
3556  Int_t npids = GetNProcessIDs();
3557  for (Int_t i=0;i<npids;i++) {
3558  if (pids->At(i) == pid) return (UShort_t)i;
3559  }
3560 
3561  this->SetBit(TFile::kHasReferences);
3562  pids->AddAtAndExpand(pid,npids);
3563  pid->IncrementCount();
3564  char name[32];
3565  snprintf(name,32,"ProcessID%d",npids);
3566  this->WriteTObject(pid,name);
3567  this->IncrementProcessIDs();
3568  if (gDebug > 0) {
3569  Info("WriteProcessID", "name=%s, file=%s", name, GetName());
3570  }
3571  return (UShort_t)npids;
3572 }
3573 
3574 
3575 ////////////////////////////////////////////////////////////////////////////////
3576 /// Write the list of TStreamerInfo as a single object in this file
3577 /// The class Streamer description for all classes written to this file
3578 /// is saved. See class TStreamerInfo.
3579 
3582  //if (!gFile) return;
3583  if (!fWritable) return;
3584  if (!fClassIndex) return;
3585  if (fIsPcmFile) return; // No schema evolution for ROOT PCM files.
3586  //no need to update the index if no new classes added to the file
3587  if (fClassIndex->fArray[0] == 0) return;
3588  if (gDebug > 0) Info("WriteStreamerInfo", "called for file %s",GetName());
3589 
3590  SafeDelete(fInfoCache);
3591 
3592  // build a temporary list with the marked files
3593  TIter next(gROOT->GetListOfStreamerInfo());
3594  TStreamerInfo *info;
3595  TList list;
3596  TList listOfRules;
3597  listOfRules.SetOwner(kTRUE);
3598  listOfRules.SetName("listOfRules");
3599  std::set<TClass*> classSet;
3600 
3601 
3602  while ((info = (TStreamerInfo*)next())) {
3603  Int_t uid = info->GetNumber();
3604  if (fClassIndex->fArray[uid]) {
3605  list.Add(info);
3606  if (gDebug > 0) printf(" -class: %s info number %d saved\n",info->GetName(),uid);
3607 
3608  // Add the IO customization rules to the list to be saved for the underlying
3609  // class but make sure to add them only once.
3610  TClass *clinfo = info->GetClass();
3611  if (clinfo && clinfo->GetSchemaRules()) {
3612  if ( classSet.find( clinfo ) == classSet.end() ) {
3613  if (gDebug > 0) printf(" -class: %s stored the I/O customization rules\n",info->GetName());
3614 
3615  TObjArrayIter it( clinfo->GetSchemaRules()->GetRules() );
3616  ROOT::TSchemaRule *rule;
3617  while( (rule = (ROOT::TSchemaRule*)it.Next()) ) {
3618  TObjString *obj = new TObjString();
3619  rule->AsString(obj->String());
3620  listOfRules.Add(obj);
3621  }
3622  classSet.insert(clinfo);
3623  }
3624  }
3625  }
3626  }
3627 
3628  // Write the StreamerInfo list even if it is empty.
3629  fClassIndex->fArray[0] = 2; //to prevent adding classes in TStreamerInfo::TagFile
3630 
3631  if (listOfRules.GetEntries()) {
3632  // Only add the list of rules if we have something to say.
3633  list.Add(&listOfRules);
3634  }
3635 
3636  // always write with compression on
3637  Int_t compress = fCompress;
3638  fCompress = 1;
3639 
3640  //free previous StreamerInfo record
3641  if (fSeekInfo) MakeFree(fSeekInfo,fSeekInfo+fNbytesInfo-1);
3642  //Create new key
3643  TKey key(&list,"StreamerInfo",GetBestBuffer(), this);
3644  fKeys->Remove(&key);
3645  fSeekInfo = key.GetSeekKey();
3646  fNbytesInfo = key.GetNbytes();
3647  SumBuffer(key.GetObjlen());
3648  key.WriteFile(0);
3649 
3650  fClassIndex->fArray[0] = 0;
3651  fCompress = compress;
3652 
3653  list.RemoveLast(); // remove the listOfRules.
3654 }
3655 
3656 ////////////////////////////////////////////////////////////////////////////////
3657 /// Open a file for reading through the file cache.
3658 ///
3659 /// The file will be downloaded to the cache and opened from there.
3660 /// If the download fails, it will be opened remotely.
3661 /// The file will be downloaded to the directory specified by SetCacheFileDir().
3662 
3663 TFile *TFile::OpenFromCache(const char *name, Option_t *, const char *ftitle,
3664  Int_t compress, Int_t netopt)
3665 {
3666  TFile *f = 0;
3667 
3668  if (fgCacheFileDir == "") {
3669  ::Warning("TFile::OpenFromCache",
3670  "you want to read through a cache, but you have no valid cache "
3671  "directory set - reading remotely");
3672  ::Info("TFile::OpenFromCache", "set cache directory using TFile::SetCacheFileDir()");
3673  } else {
3674  TUrl fileurl(name);
3675  TUrl tagurl;
3676 
3677  if ((!strcmp(fileurl.GetProtocol(), "file"))) {
3678  // it makes no sense to read local files through a file cache
3679  if (!fgCacheFileForce)
3680  ::Warning("TFile::OpenFromCache",
3681  "you want to read through a cache, but you are reading "
3682  "local files - CACHEREAD disabled");
3683  } else {
3684  // this is a remote file and worthwhile to be put into the local cache
3685  // now create cachepath to put it
3686  TString cachefilepath;
3687  TString cachefilepathbasedir;
3688  cachefilepath = fgCacheFileDir;
3689  cachefilepath += fileurl.GetFile();
3690  cachefilepathbasedir = gSystem->DirName(cachefilepath);
3691  if ((gSystem->mkdir(cachefilepathbasedir, kTRUE) < 0) &&
3692  (gSystem->AccessPathName(cachefilepathbasedir, kFileExists))) {
3693  ::Warning("TFile::OpenFromCache","you want to read through a cache, but I "
3694  "cannot create the directory %s - CACHEREAD disabled",
3695  cachefilepathbasedir.Data());
3696  } else {
3697  // check if this should be a zip file
3698  if (strlen(fileurl.GetAnchor())) {
3699  // remove the anchor and change the target name
3700  cachefilepath += "__";
3701  cachefilepath += fileurl.GetAnchor();
3702  fileurl.SetAnchor("");
3703  }
3704  if (strstr(name,"zip=")) {
3705  // filter out this option and change the target cache name
3706  TString urloptions = fileurl.GetOptions();
3707  TString newoptions;
3708  TObjArray *objOptions = urloptions.Tokenize("&");
3709  Int_t optioncount = 0;
3710  TString zipname;
3711  for (Int_t n = 0; n < objOptions->GetEntries(); n++) {
3712  TString loption = ((TObjString*)objOptions->At(n))->GetName();
3713  TObjArray *objTags = loption.Tokenize("=");
3714  if (objTags->GetEntries() == 2) {
3715  TString key = ((TObjString*)objTags->At(0))->GetName();
3716  TString value = ((TObjString*)objTags->At(1))->GetName();
3717  if (key.CompareTo("zip", TString::kIgnoreCase)) {
3718  if (optioncount!=0) {
3719  newoptions += "&";
3720  }
3721  newoptions += key;
3722  newoptions += "=";
3723  newoptions += value;
3724  ++optioncount;
3725  } else {
3726  zipname = value;
3727  }
3728  }
3729  delete objTags;
3730  }
3731  delete objOptions;
3732  fileurl.SetOptions(newoptions.Data());
3733  cachefilepath += "__";
3734  cachefilepath += zipname;
3735  fileurl.SetAnchor("");
3736  }
3737 
3738  Bool_t need2copy = kFALSE;
3739 
3740  // check if file is in the cache
3741  Long_t id;
3742  Long64_t size;
3743  Long_t flags;
3744  Long_t modtime;
3745  if (!gSystem->GetPathInfo(cachefilepath, &id, &size, &flags, &modtime)) {
3746  // file is in the cache
3747  if (!fgCacheFileDisconnected) {
3748  char cacheblock[256];
3749  char remotblock[256];
3750  // check the remote file for it's size and compare some magic bytes
3751  TString cfurl;
3752  cfurl = cachefilepath;
3753  cfurl += "?filetype=raw";
3754  TUrl rurl(name);
3755  TString ropt = rurl.GetOptions();
3756  ropt += "&filetype=raw";
3757  rurl.SetOptions(ropt);
3758 
3759  Bool_t forcedcache = fgCacheFileForce;
3760  fgCacheFileForce = kFALSE;
3761 
3762  TFile *cachefile = TFile::Open(cfurl, "READ");
3763  TFile *remotfile = TFile::Open(rurl.GetUrl(), "READ");
3764 
3765  fgCacheFileForce = forcedcache;
3766 
3767  if (!cachefile) {
3768  need2copy = kTRUE;
3769  ::Error("TFile::OpenFromCache",
3770  "cannot open the cache file to check cache consistency");
3771  return 0;
3772  }
3773 
3774  if (!remotfile) {
3775  ::Error("TFile::OpenFromCache",
3776  "cannot open the remote file to check cache consistency");
3777  return 0;
3778  }
3779 
3780  cachefile->Seek(0);
3781  remotfile->Seek(0);
3782 
3783  if ((!cachefile->ReadBuffer(cacheblock,256)) &&
3784  (!remotfile->ReadBuffer(remotblock,256))) {
3785  if (memcmp(cacheblock, remotblock, 256)) {
3786  ::Warning("TFile::OpenFromCache", "the header of the cache file "
3787  "differs from the remote file - forcing an update");
3788  need2copy = kTRUE;
3789  }
3790  } else {
3791  ::Warning("TFile::OpenFromCache", "the header of the cache and/or "
3792  "remote file are not readable - forcing an update");
3793  need2copy = kTRUE;
3794  }
3795 
3796  delete remotfile;
3797  delete cachefile;
3798  }
3799  } else {
3800  need2copy = kTRUE;
3801  }
3802 
3803  // try to fetch the file (disable now the forced caching)
3804  Bool_t forcedcache = fgCacheFileForce;
3805  fgCacheFileForce = kFALSE;
3806  if (need2copy && !TFile::Cp(name, cachefilepath)) {
3807  ::Warning("TFile::OpenFromCache", "you want to read through a cache, but I "
3808  "cannot make a cache copy of %s - CACHEREAD disabled",
3809  cachefilepathbasedir.Data());
3810  fgCacheFileForce = forcedcache;
3811  if (fgOpenTimeout != 0)
3812  return 0;
3813  } else {
3814  fgCacheFileForce = forcedcache;
3815  ::Info("TFile::OpenFromCache", "using local cache copy of %s [%s]",
3816  name, cachefilepath.Data());
3817  // finally we have the file and can open it locally
3818  fileurl.SetProtocol("file");
3819  fileurl.SetFile(cachefilepath);
3820 
3821  tagurl = fileurl;
3822  TString tagfile;
3823  tagfile = cachefilepath;
3824  tagfile += ".ROOT.cachefile";
3825  tagurl.SetFile(tagfile);
3826  // we symlink this file as a ROOT cached file
3827  gSystem->Symlink(gSystem->BaseName(cachefilepath), tagfile);
3828  return TFile::Open(fileurl.GetUrl(), "READ", ftitle, compress, netopt);
3829  }
3830  }
3831  }
3832  }
3833 
3834  // Failed
3835  return f;
3836 }
3837 
3838 ////////////////////////////////////////////////////////////////////////////////
3839 /// Create / open a file
3840 ///
3841 /// The type of the file can be either a
3842 /// TFile, TNetFile, TWebFile or any TFile derived class for which an
3843 /// plugin library handler has been registered with the plugin manager
3844 /// (for the plugin manager see the TPluginManager class). The returned
3845 /// type of TFile depends on the file name specified by 'url'.
3846 /// If 'url' is a '|'-separated list of file URLs, the 'URLs' are tried
3847 /// sequentially in the specified order until a successful open.
3848 /// If the file starts with "root:", "roots:" or "rootk:" a TNetFile object
3849 /// will be returned, with "http:" a TWebFile, with "file:" a local TFile,
3850 /// etc. (see the list of TFile plugin handlers in $ROOTSYS/etc/system.rootrc
3851 /// for regular expressions that will be checked) and as last a local file will
3852 /// be tried.
3853 /// Before opening a file via TNetFile a check is made to see if the URL
3854 /// specifies a local file. If that is the case the file will be opened
3855 /// via a normal TFile. To force the opening of a local file via a
3856 /// TNetFile use either TNetFile directly or specify as host "localhost".
3857 /// The netopt argument is only used by TNetFile. For the meaning of the
3858 /// options and other arguments see the constructors of the individual
3859 /// file classes. In case of error returns 0.
3860 ///
3861 /// For TFile implementations supporting asynchronous file open, see
3862 /// TFile::AsyncOpen(...), it is possible to request a timeout with the
3863 /// option <b>TIMEOUT=<secs></b>: the timeout must be specified in seconds and
3864 /// it will be internally checked with granularity of one millisec.
3865 /// For remote files there is the option: <b>CACHEREAD</b> opens an existing
3866 /// file for reading through the file cache. The file will be downloaded to
3867 /// the cache and opened from there. If the download fails, it will be opened remotely.
3868 /// The file will be downloaded to the directory specified by SetCacheFileDir().
3869 
3870 TFile *TFile::Open(const char *url, Option_t *options, const char *ftitle,
3871  Int_t compress, Int_t netopt)
3872 {
3873  TPluginHandler *h;
3874  TFile *f = 0;
3875  EFileType type = kFile;
3876 
3877  // Check input
3878  if (!url || strlen(url) <= 0) {
3879  ::Error("TFile::Open", "no url specified");
3880  return f;
3881  }
3882 
3883  TString expandedUrl(url);
3884  gSystem->ExpandPathName(expandedUrl);
3885 
3886  // If a timeout has been specified extract the value and try to apply it (it requires
3887  // support for asynchronous open, though; the following is completely transparent if
3888  // such support if not available for the required protocol)
3889  TString opts(options);
3890  Int_t ito = opts.Index("TIMEOUT=");
3891  if (ito != kNPOS) {
3892  TString sto = opts(ito + strlen("TIMEOUT="), opts.Length());
3893  while (!(sto.IsDigit()) && !(sto.IsNull())) { sto.Remove(sto.Length()-1,1); }
3894  if (!(sto.IsNull())) {
3895  // Timeout in millisecs
3896  Int_t toms = sto.Atoi() * 1000;
3897  if (gDebug > 0) ::Info("TFile::Open", "timeout of %d millisec requested", toms);
3898  // Remove from the options field
3899  sto.Insert(0, "TIMEOUT=");
3900  opts.ReplaceAll(sto, "");
3901  // Asynchrounous open
3902  TFileOpenHandle *fh = TFile::AsyncOpen(expandedUrl, opts, ftitle, compress, netopt);
3903  // Check the result in steps of 1 millisec
3905  aos = TFile::GetAsyncOpenStatus(fh);
3906  Int_t xtms = toms;
3907  while (aos != TFile::kAOSNotAsync && aos == TFile::kAOSInProgress && xtms > 0) {
3908  gSystem->Sleep(1);
3909  xtms -= 1;
3910  aos = TFile::GetAsyncOpenStatus(fh);
3911  }
3912  if (aos == TFile::kAOSNotAsync || aos == TFile::kAOSSuccess) {
3913  // Do open the file now
3914  f = TFile::Open(fh);
3915  if (gDebug > 0) {
3916  if (aos == TFile::kAOSSuccess)
3917  ::Info("TFile::Open", "waited %d millisec for asynchronous open", toms - xtms);
3918  else
3919  ::Info("TFile::Open", "timeout option not supported (requires asynchronous"
3920  " open support)");
3921  }
3922  } else {
3923  if (xtms <= 0)
3924  ::Error("TFile::Open", "timeout expired while opening '%s'", expandedUrl.Data());
3925  // Cleanup the request
3926  SafeDelete(fh);
3927  }
3928  // Done
3929  return f;
3930  } else {
3931  ::Warning("TFile::Open", "incomplete 'TIMEOUT=' option specification - ignored");
3932  opts.ReplaceAll("TIMEOUT=", "");
3933  }
3934  }
3935 
3936  // We will use this from now on
3937  const char *option = opts;
3938 
3939  // Many URLs? Redirect output and print errors in case of global failure
3940  TString namelist(expandedUrl);
3941  Ssiz_t ip = namelist.Index("|");
3942  Bool_t rediroutput = (ip != kNPOS &&
3943  ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
3944  RedirectHandle_t rh;
3945  if (rediroutput) {
3946  TString outf = ".TFileOpen_";
3947  FILE *fout = gSystem->TempFileName(outf);
3948  if (fout) {
3949  fclose(fout);
3950  gSystem->RedirectOutput(outf, "w", &rh);
3951  }
3952  }
3953 
3954  // Try sequentially all names in 'names'
3955  TString name, n;
3956  Ssiz_t from = 0;
3957  while (namelist.Tokenize(n, from, "|") && !f) {
3958 
3959  // check if we read through a file cache
3960  if (!strcasecmp(option, "CACHEREAD") ||
3961  ((!strcasecmp(option,"READ") || !option[0]) && fgCacheFileForce)) {
3962  // Try opening the file from the cache
3963  if ((f = TFile::OpenFromCache(n, option, ftitle, compress, netopt)))
3964  return f;
3965  }
3966 
3967  IncrementFileCounter();
3968 
3969  // change names from e.g. /castor/cern.ch/alice/file.root to
3970  // castor:/castor/cern.ch/alice/file.root as recognized by the plugin manager
3971  TUrl urlname(n, kTRUE);
3972  name = urlname.GetUrl();
3973  // Check first if a pending async open request matches this one
3974  if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
3975  TIter nxr(fgAsyncOpenRequests);
3976  TFileOpenHandle *fh = 0;
3977  while ((fh = (TFileOpenHandle *)nxr()))
3978  if (fh->Matches(name))
3979  return TFile::Open(fh);
3980  }
3981 
3982  TString urlOptions(urlname.GetOptions());
3983  if (urlOptions.BeginsWith("pmerge") || urlOptions.Contains("&pmerge") || urlOptions.Contains(" pmerge")) {
3984  type = kMerge;
3985 
3986  // Pass the full name including the url options:
3987  f = (TFile*) gROOT->ProcessLineFast(TString::Format("new TParallelMergingFile(\"%s\",\"%s\",\"%s\",%d)",n.Data(),option,ftitle,compress));
3988 
3989  } else {
3990  // Resolve the file type; this also adjusts names
3991  TString lfname = gEnv->GetValue("Path.Localroot", "");
3992  type = GetType(name, option, &lfname);
3993 
3994  if (type == kLocal) {
3995 
3996  // Local files
3997  if (lfname.IsNull()) {
3998  urlname.SetHost("");
3999  urlname.SetProtocol("file");
4000  lfname = urlname.GetUrl();
4001  }
4002  f = new TFile(lfname.Data(), option, ftitle, compress);
4003 
4004  } else if (type == kNet) {
4005 
4006  // Network files
4007  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
4008  if (h->LoadPlugin() == -1)
4009  return 0;
4010  f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
4011  }
4012 
4013  } else if (type == kWeb) {
4014 
4015  // Web files
4016  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
4017  if (h->LoadPlugin() == -1)
4018  return 0;
4019  f = (TFile*) h->ExecPlugin(2, name.Data(), option);
4020  }
4021 
4022  } else if (type == kFile) {
4023 
4024  // 'file:' protocol
4025  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4026  h->LoadPlugin() == 0) {
4027  name.ReplaceAll("file:", "");
4028  f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
4029  } else
4030  f = new TFile(name.Data(), option, ftitle, compress);
4031 
4032  } else {
4033 
4034  // no recognized specification: try the plugin manager
4035  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name.Data()))) {
4036  if (h->LoadPlugin() == -1)
4037  return 0;
4038  TClass *cl = TClass::GetClass(h->GetClass());
4039  if (cl && cl->InheritsFrom("TNetFile"))
4040  f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
4041  else
4042  f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
4043  } else {
4044  // Just try to open it locally but via TFile::Open, so that we pick-up the correct
4045  // plug-in in the case file name contains information about a special backend (e.g.
4046  // "srm://srm.cern.ch//castor/cern.ch/grid/..." should be considered a castor file
4047  // /castor/cern.ch/grid/...").
4048  f = TFile::Open(urlname.GetFileAndOptions(), option, ftitle, compress);
4049  }
4050  }
4051  }
4052 
4053  if (f && f->IsZombie()) {
4054  TString newUrl = f->GetNewUrl();
4055  delete f;
4056  if( newUrl.Length() && gEnv->GetValue("TFile.CrossProtocolRedirects", 1) )
4057  f = TFile::Open( newUrl, option, ftitle, compress );
4058  else
4059  f = 0;
4060  }
4061  }
4062 
4063  if (rediroutput) {
4064  // Restore output to stdout
4065  gSystem->RedirectOutput(0, "", &rh);
4066  // If we failed print error messages
4067  if (!f)
4068  gSystem->ShowOutput(&rh);
4069  // Remove the file
4070  gSystem->Unlink(rh.fFile);
4071  }
4072 
4073  // if the file is writable, non local, and not opened in raw mode
4074  // we create a default write cache of 512 KBytes
4075  if (type != kLocal && type != kFile &&
4076  f && f->IsWritable() && !f->IsRaw()) {
4077  new TFileCacheWrite(f, 1);
4078  }
4079 
4080  return f;
4081 }
4082 
4083 ////////////////////////////////////////////////////////////////////////////////
4084 /// Submit an asynchronous open request.
4085 
4086 /// See TFile::Open(const char *, ...) for an
4087 /// explanation of the arguments. A handler is returned which is to be passed
4088 /// to TFile::Open(TFileOpenHandle *) to get the real TFile instance once
4089 /// the file is open.
4090 /// This call never blocks and it is provided to allow parallel submission
4091 /// of file opening operations expected to take a long time.
4092 /// TFile::Open(TFileOpenHandle *) may block if the file is not yet ready.
4093 /// The sequence
4094 ///
4095 /// TFile::Open(TFile::AsyncOpen(const char *, ...))
4096 ///
4097 /// is equivalent to
4098 ///
4099 /// TFile::Open(const char *, ...)
4100 ///
4101 /// To be effective, the underlying TFile implementation must be able to
4102 /// support asynchronous open functionality. Currently, only TXNetFile
4103 /// supports it. If the functionality is not implemented, this call acts
4104 /// transparently by returning an handle with the arguments for the
4105 /// standard synchronous open run by TFile::Open(TFileOpenHandle *).
4106 /// The retuned handle will be adopted by TFile after opening completion
4107 /// in TFile::Open(TFileOpenHandle *); if opening is not finalized the
4108 /// handle must be deleted by the caller.
4109 
4110 TFileOpenHandle *TFile::AsyncOpen(const char *url, Option_t *option,
4111  const char *ftitle, Int_t compress,
4112  Int_t netopt)
4113 {
4114  TFileOpenHandle *fh = 0;
4115  TPluginHandler *h;
4116  TFile *f = 0;
4117  Bool_t notfound = kTRUE;
4118 
4119  // Check input
4120  if (!url || strlen(url) <= 0) {
4121  ::Error("TFile::AsyncOpen", "no url specified");
4122  return fh;
4123  }
4124 
4125  // Many URLs? Redirect output and print errors in case of global failure
4126  TString namelist(url);
4127  gSystem->ExpandPathName(namelist);
4128  Ssiz_t ip = namelist.Index("|");
4129  Bool_t rediroutput = (ip != kNPOS &&
4130  ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
4131  RedirectHandle_t rh;
4132  if (rediroutput) {
4133  TString outf = ".TFileAsyncOpen_";
4134  FILE *fout = gSystem->TempFileName(outf);
4135  if (fout) {
4136  fclose(fout);
4137  gSystem->RedirectOutput(outf, "w", &rh);
4138  }
4139  }
4140 
4141  // Try sequentially all names in 'names'
4142  TString name, n;
4143  Ssiz_t from = 0;
4144  while (namelist.Tokenize(n, from, "|") && !f) {
4145 
4146  // change names from e.g. /castor/cern.ch/alice/file.root to
4147  // castor:/castor/cern.ch/alice/file.root as recognized by the plugin manager
4148  TUrl urlname(n, kTRUE);
4149  name = urlname.GetUrl();
4150 
4151  // Resolve the file type; this also adjusts names
4152  EFileType type = GetType(name, option);
4153 
4154  // Here we send the asynchronous request if the functionality is implemented
4155  if (type == kNet) {
4156  // Network files
4157  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4158  (!strcmp(h->GetClass(),"TXNetFile") || !strcmp(h->GetClass(),"TNetXNGFile"))
4159  && h->LoadPlugin() == 0) {
4160  f = (TFile*) h->ExecPlugin(6, name.Data(), option, ftitle, compress, netopt, kTRUE);
4161  notfound = kFALSE;
4162  }
4163  }
4164  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4165  !strcmp(h->GetClass(),"TAlienFile") && h->LoadPlugin() == 0) {
4166  f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, kTRUE);
4167  notfound = kFALSE;
4168  }
4169 
4170  }
4171 
4172  if (rediroutput) {
4173  // Restore output to stdout
4174  gSystem->RedirectOutput(0, "", &rh);
4175  // If we failed print error messages
4176  if (!notfound && !f)
4177  gSystem->ShowOutput(&rh);
4178  // Remove the file
4179  gSystem->Unlink(rh.fFile);
4180  }
4181 
4182  // Make sure that no error occurred
4183  if (notfound) {
4184  SafeDelete(f);
4185  // Save the arguments in the handler, so that a standard open can be
4186  // attempted later on
4187  fh = new TFileOpenHandle(name, option, ftitle, compress, netopt);
4188  } else if (f) {
4189  // Fill the opaque handler to be use to attach the file later on
4190  fh = new TFileOpenHandle(f);
4191  }
4192 
4193  // Record this request
4194  if (fh) {
4195  // Create the lst, if not done already
4196  if (!fgAsyncOpenRequests)
4197  fgAsyncOpenRequests = new TList;
4198  fgAsyncOpenRequests->Add(fh);
4199  }
4200 
4201  // We are done
4202  return fh;
4203 }
4204 
4205 ////////////////////////////////////////////////////////////////////////////////
4206 /// Waits for the completion of an asynchronous open request.
4207 ///
4208 /// Returns the pointer to the associated TFile, transferring ownership of the
4209 /// handle to the TFile instance.
4210 
4213  TFile *f = 0;
4214 
4215  // Note that the request may have failed
4216  if (fh && fgAsyncOpenRequests) {
4217  // Remove it from the pending list: we need to do it at this level to avoid
4218  // recursive calls in the standard TFile::Open
4219  fgAsyncOpenRequests->Remove(fh);
4220  // Was asynchronous open functionality implemented?
4221  if ((f = fh->GetFile()) && !(f->IsZombie())) {
4222  // Yes: wait for the completion of the open phase, if needed
4223  Bool_t cr = (!strcmp(f->GetOption(),"CREATE") ||
4224  !strcmp(f->GetOption(),"RECREATE") ||
4225  !strcmp(f->GetOption(),"NEW")) ? kTRUE : kFALSE;
4226  f->Init(cr);
4227  } else {
4228  // No: process a standard open
4229  f = TFile::Open(fh->GetName(), fh->GetOpt(), fh->GetTitle(),
4230  fh->GetCompress(), fh->GetNetOpt());
4231  }
4232 
4233  // Adopt the handle instance in the TFile instance so that it gets
4234  // automatically cleaned up
4235  if (f) f->fAsyncHandle = fh;
4236  }
4237 
4238  // We are done
4239  return f;
4240 }
4241 
4242 ////////////////////////////////////////////////////////////////////////////////
4243 /// Interface to system open. All arguments like in POSIX open().
4244 
4245 Int_t TFile::SysOpen(const char *pathname, Int_t flags, UInt_t mode)
4247 #if defined(R__WINGCC)
4248  // ALWAYS use binary mode - even cygwin text should be in unix format
4249  // although this is posix default it has to be set explicitly
4250  return ::open(pathname, flags | O_BINARY, mode);
4251 #elif defined(R__SEEK64)
4252  return ::open64(pathname, flags, mode);
4253 #else
4254  return ::open(pathname, flags, mode);
4255 #endif
4256 }
4257 
4258 ////////////////////////////////////////////////////////////////////////////////
4259 /// Interface to system close. All arguments like in POSIX close().
4260 
4263  if (fd < 0) return 0;
4264  return ::close(fd);
4265 }
4266 
4267 ////////////////////////////////////////////////////////////////////////////////
4268 /// Interface to system read. All arguments like in POSIX read().
4269 
4270 Int_t TFile::SysRead(Int_t fd, void *buf, Int_t len)
4272  return ::read(fd, buf, len);
4273 }
4274 
4275 ////////////////////////////////////////////////////////////////////////////////
4276 /// Interface to system write. All arguments like in POSIX write().
4277 
4278 Int_t TFile::SysWrite(Int_t fd, const void *buf, Int_t len)
4280  return ::write(fd, buf, len);
4281 }
4282 ////////////////////////////////////////////////////////////////////////////////
4283 /// Interface to system lseek.
4284 ///
4285 /// All arguments like in POSIX lseek()
4286 /// except that the offset and return value are of a type which are
4287 /// able to handle 64 bit file systems.
4288 
4289 Long64_t TFile::SysSeek(Int_t fd, Long64_t offset, Int_t whence)
4291 #if defined (R__SEEK64)
4292  return ::lseek64(fd, offset, whence);
4293 #elif defined(WIN32)
4294  return ::_lseeki64(fd, offset, whence);
4295 #else
4296  return ::lseek(fd, offset, whence);
4297 #endif
4298 }
4299 
4300 ////////////////////////////////////////////////////////////////////////////////
4301 /// Return file stat information.
4302 ///
4303 /// The interface and return value is
4304 /// identical to TSystem::GetPathInfo(). The function returns 0 in
4305 /// case of success and 1 if the file could not be stat'ed.
4306 
4307 Int_t TFile::SysStat(Int_t, Long_t *id, Long64_t *size, Long_t *flags,
4308  Long_t *modtime)
4309 {
4310  return gSystem->GetPathInfo(fRealName, id, size, flags, modtime);
4311 }
4312 
4313 ////////////////////////////////////////////////////////////////////////////////
4314 /// Interface to system fsync. All arguments like in POSIX fsync().
4315 
4318  if (TestBit(kDevNull)) return 0;
4319 
4320 #ifndef WIN32
4321  return ::fsync(fd);
4322 #else
4323  return ::_commit(fd);
4324 #endif
4325 }
4326 
4327 ////////////////////////////////////////////////////////////////////////////////
4328 /// Return the total number of bytes written so far to the file.
4329 
4332  return fCacheWrite ? fCacheWrite->GetBytesInCache() + fBytesWrite : fBytesWrite;
4333 }
4334 
4335 ////////////////////////////////////////////////////////////////////////////////
4336 /// Static function returning the total number of bytes read from all files.
4337 
4340  return fgBytesRead;
4341 }
4342 
4343 ////////////////////////////////////////////////////////////////////////////////
4344 /// Static function returning the total number of bytes written to all files.
4345 /// Does not take into account what might still be in the write caches.
4346 
4349  return fgBytesWrite;
4350 }
4351 
4352 ////////////////////////////////////////////////////////////////////////////////
4353 /// Static function returning the total number of read calls from all files.
4354 
4357  return fgReadCalls;
4358 }
4359 
4360 ////////////////////////////////////////////////////////////////////////////////
4361 /// Static function returning the readahead buffer size.
4362 
4365  return fgReadaheadSize;
4366 }
4367 
4368 //______________________________________________________________________________
4369 void TFile::SetReadaheadSize(Int_t bytes) { fgReadaheadSize = bytes; }
4371 //______________________________________________________________________________
4372 void TFile::SetFileBytesRead(Long64_t bytes) { fgBytesRead = bytes; }
4374 //______________________________________________________________________________
4375 void TFile::SetFileBytesWritten(Long64_t bytes) { fgBytesWrite = bytes; }
4377 //______________________________________________________________________________
4378 void TFile::SetFileReadCalls(Int_t readcalls) { fgReadCalls = readcalls; }
4380 //______________________________________________________________________________
4381 Long64_t TFile::GetFileCounter() { return fgFileCounter; }
4383 //______________________________________________________________________________
4384 void TFile::IncrementFileCounter() { fgFileCounter++; }
4386 ////////////////////////////////////////////////////////////////////////////////
4387 /// Sets the directory where to locally stage/cache remote files.
4388 /// If the directory is not writable by us return kFALSE.
4389 
4390 Bool_t TFile::SetCacheFileDir(const char *cachedir, Bool_t operatedisconnected,
4391  Bool_t forcecacheread )
4392 {
4393  TString cached = cachedir;
4394  if (!cached.EndsWith("/"))
4395  cached += "/";
4396 
4397  if (gSystem->AccessPathName(cached, kFileExists)) {
4398  // try to create it
4399  gSystem->mkdir(cached, kTRUE);
4400  if (gSystem->AccessPathName(cached, kFileExists)) {
4401  ::Error("TFile::SetCacheFileDir", "no sufficient permissions on cache directory %s or cannot create it", cachedir);
4402  fgCacheFileDir = "";
4403  return kFALSE;
4404  }
4405  gSystem->Chmod(cached, 0700);
4406  }
4407  if (gSystem->AccessPathName(cached, kWritePermission))
4408  gSystem->Chmod(cached, 0700);
4409  fgCacheFileDir = cached;
4410  fgCacheFileDisconnected = operatedisconnected;
4411  fgCacheFileForce = forcecacheread;
4412  return kTRUE;
4413 }
4414 
4415 ////////////////////////////////////////////////////////////////////////////////
4416 /// Get the directory where to locally stage/cache remote files.
4417 
4418 const char *TFile::GetCacheFileDir()
4420  return fgCacheFileDir;
4421 }
4422 
4423 ////////////////////////////////////////////////////////////////////////////////
4424 /// Try to shrink the cache to the desired size.
4425 ///
4426 /// With the clenupinterval you can specify the minimum amount of time after
4427 /// the previous cleanup before the cleanup operation is repeated in
4428 /// the cache directory
4429 
4430 Bool_t TFile::ShrinkCacheFileDir(Long64_t shrinksize, Long_t cleanupinterval)
4432  if (fgCacheFileDir == "") {
4433  return kFALSE;
4434  }
4435 
4436  // check the last clean-up in the cache
4437  Long_t id;
4438  Long64_t size;
4439  Long_t flags;
4440  Long_t modtime;
4441 
4442  TString cachetagfile = fgCacheFileDir;
4443  cachetagfile += ".tag.ROOT.cache";
4444  if (!gSystem->GetPathInfo(cachetagfile, &id, &size, &flags, &modtime)) {
4445  // check the time passed since last cache cleanup
4446  Long_t lastcleanuptime = ((Long_t)time(0) - modtime);
4447  if (lastcleanuptime < cleanupinterval) {
4448  ::Info("TFile::ShrinkCacheFileDir", "clean-up is skipped - last cleanup %lu seconds ago - you requested %lu", lastcleanuptime, cleanupinterval);
4449  return kTRUE;
4450  }
4451  }
4452 
4453  // (re-)create the cache tag file
4454  cachetagfile += "?filetype=raw";
4455  TFile *tagfile = 0;
4456 
4457  if (!(tagfile = TFile::Open(cachetagfile, "RECREATE"))) {
4458  ::Error("TFile::ShrinkCacheFileDir", "cannot create the cache tag file %s", cachetagfile.Data());
4459  return kFALSE;
4460  }
4461 
4462  // the shortest garbage collector in the world - one long line of PERL - unlinks files only,
4463  // if there is a symbolic link with '.ROOT.cachefile' for safety ;-)
4464 
4465  TString cmd;
4466 #if defined(R__WIN32)
4467  cmd = "echo <TFile::ShrinkCacheFileDir>: cleanup to be implemented";
4468 #elif defined(R__MACOSX)
4469  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);
4470 #else
4471  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);
4472 #endif
4473 
4474  tagfile->WriteBuffer(cmd, 4096);
4475  delete tagfile;
4476 
4477  if ((gSystem->Exec(cmd)) != 0) {
4478  ::Error("TFile::ShrinkCacheFileDir", "error executing clean-up script");
4479  return kFALSE;
4480  }
4481 
4482  return kTRUE;
4483 }
4484 
4485 ////////////////////////////////////////////////////////////////////////////////
4486 /// Sets open timeout time (in ms). Returns previous timeout value.
4487 
4490  UInt_t to = fgOpenTimeout;
4491  fgOpenTimeout = timeout;
4492  return to;
4493 }
4494 
4495 ////////////////////////////////////////////////////////////////////////////////
4496 /// Returns open timeout (in ms).
4497 
4500  return fgOpenTimeout;
4501 }
4502 
4503 ////////////////////////////////////////////////////////////////////////////////
4504 /// Sets only staged flag. Returns previous value of flag.
4505 /// When true we check before opening the file if it is staged, if not,
4506 /// the open fails.
4507 
4510  Bool_t f = fgOnlyStaged;
4511  fgOnlyStaged = onlystaged;
4512  return f;
4513 }
4514 
4515 ////////////////////////////////////////////////////////////////////////////////
4516 /// Returns staged only flag.
4517 
4520  return fgOnlyStaged;
4521 }
4522 
4523 ////////////////////////////////////////////////////////////////////////////////
4524 /// Return kTRUE if 'url' matches the coordinates of this file.
4525 ///
4526 /// The check is implementation dependent and may need to be overload
4527 /// by each TFile implementation relying on this check.
4528 /// The default implementation checks the file name only.
4529 
4530 Bool_t TFile::Matches(const char *url)
4532  // Check the full URL, including port and FQDN.
4533  TUrl u(url);
4534 
4535  // Check
4536  if (!strcmp(u.GetFile(), fUrl.GetFile())) {
4537  // Check ports
4538  if (u.GetPort() == fUrl.GetPort()) {
4539  if (!strcmp(u.GetHostFQDN(), fUrl.GetHostFQDN())) {
4540  // Ok, coordinates match
4541  return kTRUE;
4542  }
4543  }
4544  }
4545 
4546  // Default is not matching
4547  return kFALSE;
4548 }
4549 
4550 ////////////////////////////////////////////////////////////////////////////////
4551 /// Return kTRUE if this async request matches the open request
4552 /// specified by 'url'
4553 
4554 Bool_t TFileOpenHandle::Matches(const char *url)
4556  if (fFile) {
4557  return fFile->Matches(url);
4558  } else if (fName.Length() > 0){
4559  // Deep check of URLs
4560  TUrl u(url);
4561  TUrl uref(fName);
4562  if (!strcmp(u.GetFile(), uref.GetFile())) {
4563  // Check ports
4564  if (u.GetPort() == uref.GetPort()) {
4565  // Check also the host name
4566  if (!strcmp(u.GetHostFQDN(), uref.GetHostFQDN())) {
4567  // Ok, coordinates match
4568  return kTRUE;
4569  }
4570  }
4571  }
4572  }
4573 
4574  // Default is not matching
4575  return kFALSE;
4576 }
4577 
4578 ////////////////////////////////////////////////////////////////////////////////
4579 /// Resolve the file type as a function of the protocol field in 'name'
4580 ///
4581 /// If defined, the string 'prefix' is added when testing the locality of
4582 /// a 'name' with network-like structure (i.e. root://host//path); if the file
4583 /// is local, on return 'prefix' will contain the actual local path of the file.
4584 
4585 TFile::EFileType TFile::GetType(const char *name, Option_t *option, TString *prefix)
4588 
4589  TPMERegexp re("^(root|xroot).*", "i");
4590  if (re.Match(name)) {
4591  //
4592  // Should be a network file ...
4593  type = kNet;
4594  // ... but make sure that is not local or that a remote-like connection
4595  // is forced. Treat it as local if:
4596  // i) the url points to the localhost, the file will be opened in
4597  // readonly mode and the current user has read access;
4598  // ii) the specified user is equal to the current user then open local
4599  // TFile.
4600  Bool_t localFile = kFALSE;
4601  TUrl url(name);
4602  //
4603  // Check whether we should try to optimize for local files
4604  Bool_t forceRemote = gEnv->GetValue("Path.ForceRemote", 0);
4605  forceRemote = (forceRemote) ? kTRUE : gEnv->GetValue("TFile.ForceRemote", 0);
4606  TString opts = url.GetOptions();
4607  if (opts.Contains("remote=1"))
4608  forceRemote = kTRUE;
4609  else if (opts.Contains("remote=0"))
4610  forceRemote = kFALSE;
4611  if (!forceRemote) {
4612  // Generic locality test
4613  localFile = gSystem->IsPathLocal(name);
4614  if (localFile) {
4615  // Local path including the prefix
4616  const char *fname = url.GetFileAndOptions();
4617  TString lfname;
4618  if (fname[0] == '/') {
4619  if (prefix)
4620  lfname.Form("%s%s", prefix->Data(), fname);
4621  else
4622  lfname = fname;
4623  } else if (fname[0] == '~' || fname[0] == '$') {
4624  lfname = fname;
4625  } else {
4626  lfname.Form("%s/%s", gSystem->HomeDirectory(), fname);
4627  }
4628  // If option "READ" test existence and access
4629  TString opt = option;
4630  Bool_t read = (opt.IsNull() ||
4631  !opt.CompareTo("READ", TString::kIgnoreCase)) ? kTRUE : kFALSE;
4632  if (read) {
4633  char *fn;
4634  if ((fn = gSystem->ExpandPathName(TUrl(lfname).GetFile()))) {
4636  localFile = kFALSE;
4637  delete [] fn;
4638  }
4639  }
4640  // Return full local path if requested (and if the case)
4641  if (localFile && prefix)
4642  *prefix = lfname;
4643  }
4644  }
4645  //
4646  // Adjust the type according to findings
4647  type = (localFile) ? kLocal : type;
4648  } else if (TPMERegexp("^(http[s]?|s3http[s]?|[a]?s3|gs|gshttp[s]?){1}:", "i").Match(name)) {
4649  //
4650  // Web file
4651  type = kWeb;
4652  } else if (!strncmp(name, "file:", 5)) {
4653  //
4654  // 'file' protocol
4655  type = kFile;
4656  }
4657  // We are done
4658  return type;
4659 }
4660 
4661 ////////////////////////////////////////////////////////////////////////////////
4662 /// Get status of the async open request related to 'name'.
4663 
4666  // Check the list of pending async open requests
4667  if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4668  TIter nxr(fgAsyncOpenRequests);
4669  TFileOpenHandle *fh = 0;
4670  while ((fh = (TFileOpenHandle *)nxr()))
4671  if (fh->Matches(name))
4672  return TFile::GetAsyncOpenStatus(fh);
4673  }
4674 
4675  // Check also the list of files open
4677  TSeqCollection *of = gROOT->GetListOfFiles();
4678  if (of && (of->GetSize() > 0)) {
4679  TIter nxf(of);
4680  TFile *f = 0;
4681  while ((f = (TFile *)nxf()))
4682  if (f->Matches(name))
4683  return f->GetAsyncOpenStatus();
4684  }
4685 
4686  // Default is synchronous mode
4687  return kAOSNotAsync;
4688 }
4689 
4690 ////////////////////////////////////////////////////////////////////////////////
4691 /// Get status of the async open request related to 'handle'.
4692 
4695  if (handle && handle->fFile) {
4696  if (!handle->fFile->IsZombie())
4697  return handle->fFile->GetAsyncOpenStatus();
4698  else
4699  return TFile::kAOSFailure;
4700  }
4701 
4702  // Default is synchronous mode
4703  return TFile::kAOSNotAsync;
4704 }
4705 
4706 ////////////////////////////////////////////////////////////////////////////////
4707 /// Get final URL for file being opened asynchronously.
4708 /// Returns 0 is the information is not yet available.
4709 
4710 const TUrl *TFile::GetEndpointUrl(const char* name)
4712  // Check the list of pending async open requests
4713  if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4714  TIter nxr(fgAsyncOpenRequests);
4715  TFileOpenHandle *fh = 0;
4716  while ((fh = (TFileOpenHandle *)nxr()))
4717  if (fh->Matches(name))
4718  if (fh->fFile)
4719  return fh->fFile->GetEndpointUrl();
4720  }
4721 
4722  // Check also the list of files open
4724  TSeqCollection *of = gROOT->GetListOfFiles();
4725  if (of && (of->GetSize() > 0)) {
4726  TIter nxf(of);
4727  TFile *f = 0;
4728  while ((f = (TFile *)nxf()))
4729  if (f->Matches(name))
4730  return f->GetEndpointUrl();
4731  }
4732 
4733  // Information not yet available
4734  return (const TUrl *)0;
4735 }
4736 
4737 ////////////////////////////////////////////////////////////////////////////////
4738 /// Print file copy progress.
4739 
4740 void TFile::CpProgress(Long64_t bytesread, Long64_t size, TStopwatch &watch)
4742  fprintf(stderr, "[TFile::Cp] Total %.02f MB\t|", (Double_t)size/1048576);
4743 
4744  for (int l = 0; l < 20; l++) {
4745  if (size > 0) {
4746  if (l < 20*bytesread/size)
4747  fprintf(stderr, "=");
4748  else if (l == 20*bytesread/size)
4749  fprintf(stderr, ">");
4750  else if (l > 20*bytesread/size)
4751  fprintf(stderr, ".");
4752  } else
4753  fprintf(stderr, "=");
4754  }
4755  // Allow to update the GUI while uploading files
4757  watch.Stop();
4758  Double_t lCopy_time = watch.RealTime();
4759  fprintf(stderr, "| %.02f %% [%.01f MB/s]\r",
4760  100.0*(size?(bytesread/((float)size)):1), (lCopy_time>0.)?bytesread/lCopy_time/1048576.:0.);
4761  watch.Continue();
4762 }
4763 
4764 ////////////////////////////////////////////////////////////////////////////////
4765 /// Allows to copy this file to the dst URL. Returns kTRUE in case of success,
4766 /// kFALSE otherwise.
4767 
4768 Bool_t TFile::Cp(const char *dst, Bool_t progressbar, UInt_t buffersize)
4770  Bool_t rmdestiferror = kFALSE;
4771  TStopwatch watch;
4772  Bool_t success = kFALSE;
4773 
4774  TUrl dURL(dst, kTRUE);
4775 
4776  TString oopt = "RECREATE";
4777  TString ourl = dURL.GetUrl();
4778 
4779  // Files will be open in RAW mode
4780  TString raw = "filetype=raw";
4781 
4782  // Set optimization options for the destination file
4783  TString opt = dURL.GetOptions();
4784  if (opt != "") opt += "&";
4785  opt += raw;
4786 
4787  // AliEn files need to know where the source file is
4788  if (!strcmp(dURL.GetProtocol(), "alien"))
4789  opt += TString::Format("&source=%s", GetName());
4790 
4791  dURL.SetOptions(opt);
4792 
4793  char *copybuffer = 0;
4794 
4795  TFile *sfile = this;
4796  TFile *dfile = 0;
4797 
4798  // "RECREATE" does not work always well with XROOTD
4799  // namely when some pieces of the path are missing;
4800  // we force "NEW" in such a case
4801  if (TFile::GetType(ourl, "") == TFile::kNet) {
4802  if (gSystem->AccessPathName(ourl)) {
4803  oopt = "NEW";
4804  // Force creation of the missing parts of the path
4805  opt += "&mkpath=1";
4806  dURL.SetOptions(opt);
4807  }
4808  }
4809 
4810  // Open destination file
4811  if (!(dfile = TFile::Open(dURL.GetUrl(), oopt))) {
4812  ::Error("TFile::Cp", "cannot open destination file %s", dst);
4813  goto copyout;
4814  }
4815 
4816  // Probably we created a new file
4817  // We have to remove it in case of errors
4818  rmdestiferror = kTRUE;
4819 
4820  sfile->Seek(0);
4821  dfile->Seek(0);
4822 
4823  copybuffer = new char[buffersize];
4824  if (!copybuffer) {
4825  ::Error("TFile::Cp", "cannot allocate the copy buffer");
4826  goto copyout;
4827  }
4828 
4829  Bool_t readop;
4830  Bool_t writeop;
4831  Long64_t read;
4832  Long64_t written;
4833  Long64_t totalread;
4834  Long64_t filesize;
4835  Long64_t b00;
4836  filesize = sfile->GetSize();
4837  totalread = 0;
4838  watch.Start();
4839 
4840  b00 = sfile->GetBytesRead();
4841 
4842  do {
4843  if (progressbar) CpProgress(totalread, filesize,watch);
4844 
4845  Long64_t b1 = sfile->GetBytesRead() - b00;
4846 
4847  Long64_t readsize;
4848  if (filesize - b1 > (Long64_t)buffersize) {
4849  readsize = buffersize;
4850  } else {
4851  readsize = filesize - b1;
4852  }
4853 
4854  if (readsize == 0) break;
4855 
4856  Long64_t b0 = sfile->GetBytesRead();
4857  sfile->Seek(totalread,TFile::kBeg);
4858  readop = sfile->ReadBuffer(copybuffer, (Int_t)readsize);
4859  read = sfile->GetBytesRead() - b0;
4860  if ((read <= 0) || readop) {
4861  ::Error("TFile::Cp", "cannot read from source file %s. readsize=%lld read=%lld readop=%d",
4862  sfile->GetName(), readsize, read, readop);
4863  goto copyout;
4864  }
4865 
4866  Long64_t w0 = dfile->GetBytesWritten();
4867  writeop = dfile->WriteBuffer(copybuffer, (Int_t)read);
4868  written = dfile->GetBytesWritten() - w0;
4869  if ((written != read) || writeop) {
4870  ::Error("TFile::Cp", "cannot write %lld bytes to destination file %s", read, dst);
4871  goto copyout;
4872  }
4873  totalread += read;
4874  } while (read == (Long64_t)buffersize);
4875 
4876  if (progressbar) {
4877  CpProgress(totalread, filesize,watch);
4878  fprintf(stderr, "\n");
4879  }
4880 
4881  success = kTRUE;
4882 
4883 copyout:
4884  if (dfile) dfile->Close();
4885 
4886  if (dfile) delete dfile;
4887  if (copybuffer) delete[] copybuffer;
4888 
4889  if (rmdestiferror && (success != kTRUE))
4890  gSystem->Unlink(dst);
4891 
4892  watch.Stop();
4893  watch.Reset();
4894 
4895  return success;
4896 }
4897 
4898 ////////////////////////////////////////////////////////////////////////////////
4899 /// Allows to copy file from src to dst URL. Returns kTRUE in case of success,
4900 /// kFALSE otherwise.
4901 
4902 Bool_t TFile::Cp(const char *src, const char *dst, Bool_t progressbar,
4903  UInt_t buffersize)
4904 {
4905  TUrl sURL(src, kTRUE);
4906 
4907  // Files will be open in RAW mode
4908  TString raw = "filetype=raw";
4909 
4910  // Set optimization options for the source file
4911  TString opt = sURL.GetOptions();
4912  if (opt != "") opt += "&";
4913  opt += raw;
4914  // Netx-related options:
4915  // cachesz = 4*buffersize -> 4 buffers as peak mem usage
4916  // readaheadsz = 2*buffersize -> Keep at max 4*buffersize bytes outstanding when reading
4917  // rmpolicy = 1 -> Remove from the cache the blk with the least offset
4918  opt += TString::Format("&cachesz=%d&readaheadsz=%d&rmpolicy=1", 4*buffersize, 2*buffersize);
4919  sURL.SetOptions(opt);
4920 
4921  TFile *sfile = 0;
4922 
4923  Bool_t success = kFALSE;
4924 
4925  // Open source file
4926  if (!(sfile = TFile::Open(sURL.GetUrl(), "READ"))) {
4927  ::Error("TFile::Cp", "cannot open source file %s", src);
4928  } else {
4929  success = sfile->Cp(dst, progressbar, buffersize);
4930  }
4931 
4932  if (sfile) sfile->Close();
4933  if (sfile) delete sfile;
4934 
4935  return success;
4936 }
4937 
4938 //______________________________________________________________________________
4939 //The next statement is not active anymore on Linux.
4940 //Using posix_fadvise introduces a performance penalty (10 %) on optimized files
4941 //and in addition it destroys the information of TTreePerfStats
4942 #if defined(R__neverLINUX) && !defined(R__WINGCC)
4944 {
4945  // Read specified byte range asynchronously. Actually we tell the kernel
4946  // which blocks we are going to read so it can start loading these blocks
4947  // in the buffer cache.
4948 
4949  // Shortcut to avoid having to implement dummy ReadBufferAsync() in all
4950  // I/O plugins. Override ReadBufferAsync() in plugins if async is supported.
4951  if (IsA() != TFile::Class())
4952  return kTRUE;
4953 
4954  int advice = POSIX_FADV_WILLNEED;
4955  if (len == 0) {
4956  // according POSIX spec if len is zero, all data following offset
4957  // is specified. Nevertheless ROOT uses zero to probe readahead
4958  // capabilities.
4959  advice = POSIX_FADV_NORMAL;
4960  }
4961  Double_t start = 0;
4962  if (gPerfStats != 0) start = TTimeStamp();
4963 #if defined(R__SEEK64)
4964  Int_t result = posix_fadvise64(fD, offset, len, advice);
4965 #else
4966  Int_t result = posix_fadvise(fD, offset, len, advice);
4967 #endif
4968  if (gPerfStats != 0) {
4969  gPerfStats->FileReadEvent(this, len, start);
4970  }
4971  return (result != 0);
4972 }
4973 #else
4976  // Not supported yet on non Linux systems.
4977 
4978  return kTRUE;
4979 }
4980 #endif
4981 
4982 ////////////////////////////////////////////////////////////////////////////////
4983 /// Max number of bytes to prefetch.
4984 ///
4985 /// By default this is 75% of the
4986 /// read cache size. But specific TFile implementations may need to change it
4987 
4990  TFileCacheRead *cr = 0;
4991  if ((cr = GetCacheRead())) {
4992  Int_t bytes = cr->GetBufferSize() / 4 * 3;
4993  return ((bytes < 0) ? 0 : bytes);
4994  }
4995  return 0;
4996 }
virtual Bool_t SendFileCloseEvent(TFile *)
virtual void Map()
List the contents of a file sequentially.
Definition: TFile.cxx:1454
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:47
virtual Bool_t SendFileWriteProgress(TFile *)
void SetFile(const char *file)
Definition: TUrl.h:94
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:929
virtual Int_t GetEntries() const
Definition: TCollection.h:92
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
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:1265
double read(const std::string &file_name)
reading
void frombuf(char *&buf, Bool_t *x)
Definition: Bytes.h:282
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:1877
virtual Long64_t GetSize() const
Returns the current file size.
Definition: TFile.cxx:1285
An array of TObjects.
Definition: TObjArray.h:39
virtual void ls(Option_t *option="") const
List file contents.
Definition: TFile.cxx:1367
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition: TROOT.cxx:2543
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:4308
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:421
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:405
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
ROOT::ESTLType IsSTLCont(std::string_view type)
type : type name: vector<list<classA,allocator>,allocator> result: 0 : not stl container code of cont...
static Bool_t AddRule(const char *rule)
Add a schema evolution customization rule.
Definition: TClass.cxx:1799
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:1274
long long Long64_t
Definition: RtypesCore.h:69
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:124
virtual Long64_t SysSeek(Int_t fd, Long64_t offset, Int_t whence)
Interface to system lseek.
Definition: TFile.cxx:4290
EAsyncOpenStatus
Asynchronous open request status.
Definition: TFile.h:56
virtual const char * WorkingDirectory()
Return working directory.
Definition: TSystem.cxx:866
virtual Int_t GetErrno() const
Method returning errno. Is overriden in TRFIOFile.
Definition: TFile.cxx:1186
Bool_t IsReading() const
Definition: TBuffer.h:83
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:120
Ssiz_t Length() const
Definition: TString.h:390
void Fatal(const char *location, const char *msgfmt,...)
Collectable string class.
Definition: TObjString.h:32
virtual Int_t ReOpen(Option_t *mode)
Reopen a file with a different access mode.
Definition: TFile.cxx:1991
float Float_t
Definition: RtypesCore.h:53
const Int_t kBEGIN
Definition: TFile.cxx:155
virtual void ls(Option_t *option="") const
List (ls) all objects in this collection.
Bool_t Matches(const char *name)
Return kTRUE if this async request matches the open request specified by &#39;url&#39;.
Definition: TFile.cxx:4555
static void IncrementFileCounter()
Definition: TFile.cxx:4385
virtual void ReadFree()
Read the FREE linked list.
Definition: TFile.cxx:1757
A cache when reading files over the network.
const char Option_t
Definition: RtypesCore.h:62
int GetSplit(const char *type, std::vector< std::string > &output, int &nestedLoc, EModType mode=TClassEdit::kNone)
Stores in output (after emptying it) the split type.
Definition: TClassEdit.cxx:938
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:2197
static TList * fgAsyncOpenRequests
Definition: TFile.h:111
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:2084
This class represents a WWW compatible URL.
Definition: TUrl.h:41
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
virtual void RemoveLast()
Remove the last object of the list.
Definition: TList.cxx:747
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:1363
unsigned short UShort_t
Definition: RtypesCore.h:36
Class holding info about the file being opened.
Definition: TFile.h:328
static UInt_t fgOpenTimeout
Timeout for open operations in ms - 0 corresponds to blocking i/o.
Definition: TFile.h:116
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
const char * GetProtocol() const
Definition: TUrl.h:73
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:2105
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:50
virtual Long64_t GetBytesWritten() const
Return the total number of bytes written so far to the file.
Definition: TFile.cxx:4331
static void SetFileReadCalls(Int_t readcalls=0)
Definition: TFile.cxx:4379
virtual Bool_t ReadBuffer(char *buf, Int_t len)
Read a buffer from the file.
Definition: TFile.cxx:1602
virtual const char * HomeDirectory(const char *userName=0)
Return the user&#39;s home directory.
Definition: TSystem.cxx:882
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1102
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
virtual Bool_t ChangeDirectory(const char *path)
Change directory.
Definition: TSystem.cxx:857
static TArchiveFile * Open(const char *url, TFile *file)
Return proper archive file handler depending on passed url.
#define gROOT
Definition: TROOT.h:364
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:1818
#define O_BINARY
Definition: civetweb.c:451
Bool_t IsZombie() const
Definition: TObject.h:127
virtual const TUrl * GetEndpointUrl() const
Definition: TFile.h:204
Basic string class.
Definition: TString.h:137
static Bool_t ShrinkCacheFileDir(Long64_t shrinkSize, Long_t cleanupInteval=0)
Try to shrink the cache to the desired size.
Definition: TFile.cxx:4431
virtual const char * GetClassName() const
Definition: TKey.h:77
TFile * GetFile() const
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1089
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:997
bool Bool_t
Definition: RtypesCore.h:59
Iterator of object array.
Definition: TObjArray.h:124
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:63
const Bool_t kFALSE
Definition: Rtypes.h:92
Int_t WriteBufferViaCache(const char *buf, Int_t len)
Write buffer via cache.
Definition: TFile.cxx:2351
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:497
#define gInterpreter
Definition: TInterpreter.h:515
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:169
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual void IgnoreInterrupt(Bool_t ignore=kTRUE)
If ignore is true ignore the interrupt signal, else restore previous behaviour.
Definition: TSystem.cxx:607
static void SetReadStreamerInfo(Bool_t readinfo=kTRUE)
Specify if the streamerinfos must be read at file opening.
Definition: TFile.cxx:3521
const char * Class
Definition: TXMLSetup.cxx:64
const char * GetOptions() const
Definition: TUrl.h:80
Int_t Sizeof() const
return number of bytes occupied by this TFree on permanent storage
Definition: TFree.cxx:184
Long_t ExecPlugin(int nargs, const T &...params)
static void SetReadaheadSize(Int_t bufsize=256000)
Definition: TFile.cxx:4370
TString & Insert(Ssiz_t pos, const char *s)
Definition: TString.h:592
virtual Long64_t GetSeekKey() const
Definition: TKey.h:91
Int_t GetBestBuffer() const
Return the best buffer size of objects on this file.
Definition: TFile.cxx:1128
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
virtual void FillBuffer(char *&buffer)
Encode directory header into output buffer.
R__EXTERN void **(* gThreadTsd)(void *, Int_t)
Definition: TThreadSlots.h:42
void Reset()
Definition: TCollection.h:161
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Definition: TSystem.cxx:901
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:739
Bool_t IsRaw() const
Definition: TFile.h:229
void SysError(const char *location, const char *msgfmt,...)
void SumBuffer(Int_t bufsize)
Increment statistics for buffer sizes of objects in this file.
Definition: TFile.cxx:2249
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:265
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:3871
virtual char * GetBuffer() const
Definition: TKey.h:80
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:138
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:4769
static void SetFileBytesWritten(Long64_t bytes=0)
Definition: TFile.cxx:4376
virtual TObject * Clone(const char *newname="") const
Make a clone of an collection using the Streamer facility.
const char * Data() const
Definition: TString.h:349
TFileCacheRead * GetCacheRead(TObject *tree=0) const
Return a pointer to the current read cache.
Definition: TFile.cxx:1202
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:848
#define SafeDelete(p)
Definition: RConfig.h:499
virtual int Unlink(const char *name)
Unlink, i.e. remove, a file.
Definition: TSystem.cxx:1346
Sequenceable collection abstract base class.
void Stop()
Stop the stopwatch.
Definition: TStopwatch.cxx:77
virtual Bool_t IsOpen() const
Returns kTRUE in case file is open and kFALSE if file is not open.
Definition: TFile.cxx:1379
Option_t * GetOption() const
Definition: TFile.h:209
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:2335
Service class for TFile.
Definition: TFree.h:29
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:1462
virtual void ReadBuffer(char *&buffer)
Read string from I/O buffer.
Definition: TString.cxx:1228
static Bool_t GetReadStreamerInfo()
If the streamerinfos are to be read at file opening.
Definition: TFile.cxx:3531
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition: TSystem.cxx:442
virtual void SetCompressionLevel(Int_t level=1)
See comments for function SetCompressionSettings.
Definition: TFile.cxx:2151
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:2524
virtual void WriteFree()
Write FREE linked list on the file.
Definition: TFile.cxx:2375
Int_t GetNbytes() const
Definition: TKey.h:88
static Long64_t GetFileBytesRead()
Static function returning the total number of bytes read from all files.
Definition: TFile.cxx:4339
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:4586
void Init(TClassEdit::TInterpreterLookupHelper *helper)
Definition: TClassEdit.cxx:119
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:3664
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1140
virtual Int_t GetBufferSize() const
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:4348
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1440
virtual const char * GetMakeSharedLib() const
Return the command line use to make a shared library.
Definition: TSystem.cxx:3798
void Info(const char *location, const char *msgfmt,...)
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
Definition: TClassEdit.cxx:468
TString & Append(const char *cs)
Definition: TString.h:492
std::vector< std::vector< double > > Data
Bool_t IsWritable() const
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:698
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1965
void tobuf(char *&buf, Bool_t x)
Definition: Bytes.h:59
TClass * GetClass() const
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:30
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:73
XFontStruct * id
Definition: TGX11.cxx:108
virtual TString GetNewUrl()
Definition: TFile.h:219
void Error(const char *location, const char *msgfmt,...)
Int_t GetClassVersion() const
const char * GetArchiveName() const
Definition: TArchiveFile.h:61
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:4279
virtual const char * GetFlagsDebug() const
Return the debug flags.
Definition: TSystem.cxx:3769
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:4317
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:750
A doubly linked list.
Definition: TList.h:47
static const char * what
Definition: stlLoader.cc:6
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 Int_t Sizeof() const
Return the size in bytes of the directory header.
virtual void ls(Option_t *option="") const
List Directory contents.
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:91
virtual Int_t SysClose(Int_t fd)
Interface to system close. All arguments like in POSIX close().
Definition: TFile.cxx:4262
static UInt_t GetOpenTimeout()
Returns open timeout (in ms).
Definition: TFile.cxx:4499
Int_t GetPort() const
Definition: TUrl.h:87
virtual const char * GetSoExt() const
Get the shared library extension.
Definition: TSystem.cxx:3847
virtual void ShowStreamerInfo()
Show the StreamerInfo of all classes written to this file.
Definition: TFile.cxx:3539
th1 Draw()
EFileType
File type.
Definition: TFile.h:172
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:4271
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:552
void ResetErrno()
reset errno
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:222
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2221
TObjArray * GetElements() const
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
#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:4246
#define R__RWLOCK_RELEASE_WRITE(rwlock)
virtual void WriteStreamerInfo()
Write the list of TStreamerInfo as a single object in this file The class Streamer description for al...
Definition: TFile.cxx:3581
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:2084
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:2268
Long64_t GetLast() const
Definition: TFree.h:43
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:496
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:675
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:2308
const char * GetHostFQDN() const
Return fully qualified domain name of url host.
Definition: TUrl.cxx:469
UInt_t GetCheckSum() const
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
Bool_t HasInterpreterInfo() const
Definition: TClass.h:374
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2322
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:1258
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1394
const char * GetFileAndOptions() const
Return the file and its options (the string specified behind the ?).
Definition: TUrl.cxx:501
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:121
Int_t DecrementCount()
The reference fCount is used to delete the TProcessID in the TFile destructor when fCount = 0...
Definition: TProcessID.cxx:222
TFile * GetFile() const
Definition: TFile.h:347
static std::atomic< Long64_t > fgBytesWrite
Number of bytes written by all TFile objects.
Definition: TFile.h:119
short Short_t
Definition: RtypesCore.h:35
TLine * l
Definition: textangle.C:4
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
static void CpProgress(Long64_t bytesread, Long64_t size, TStopwatch &watch)
Print file copy progress.
Definition: TFile.cxx:4741
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2614
static std::atomic< Int_t > fgReadCalls
Number of bytes read from all TFile objects.
Definition: TFile.h:122
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
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:658
virtual TList * GetStreamerInfoList()
Read the list of TStreamerInfo objects written to this file.
Definition: TFile.cxx:1325
void Build(TFile *motherFile=0, TDirectory *motherDir=0)
Initialise directory to defaults.
const char * GetAnchor() const
Definition: TUrl.h:79
static Int_t GetFileReadCalls()
Static function returning the total number of read calls from all files.
Definition: TFile.cxx:4356
Version_t GetClassVersion() const
Definition: TClass.h:382
Bool_t IsNull() const
Definition: TString.h:387
virtual TObjLink * FirstLink() const
Definition: TList.h:101
void SetName(const char *name)
Definition: TCollection.h:116
virtual TObject * ReadObjWithBuffer(char *bufferRead)
To read a TObject* from bufferRead.
Definition: TKey.cxx:869
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:52
virtual Int_t GetBytesToPrefetch() const
Max number of bytes to prefetch.
Definition: TFile.cxx:4989
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:840
Int_t ReadBufferViaCache(char *buf, Int_t len)
Read buffer via cache.
Definition: TFile.cxx:1721
static TFile *& CurrentFile()
Return the current ROOT file if any.
Definition: TFile.cxx:1021
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2241
#define Printf
Definition: TGeoToOCC.h:18
Int_t GetNumber() const
#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 char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition: TUrl.cxx:387
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:117
static Bool_t GetOnlyStaged()
Returns staged only flag.
Definition: TFile.cxx:4519
virtual void ReadStreamerInfo()
Read the list of StreamerInfo from this file.
Definition: TFile.cxx:3404
virtual Long64_t GetBytesRead() const
Definition: TFile.h:210
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:1677
void CheckInit()
Initialize fObjects.
Definition: TProcessID.cxx:176
void SetHost(const char *host)
Definition: TUrl.h:93
TString & Remove(Ssiz_t pos)
Definition: TString.h:616
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:178
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:1471
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition: TKey.cxx:1215
void SetAnchor(const char *anchor)
Definition: TUrl.h:95
virtual const char * GetIncludePath()
Get the list of include path.
Definition: TSystem.cxx:3815
virtual Int_t GetSize() const
Definition: TCollection.h:95
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
Int_t GetCompress() const
Definition: TFile.h:355
#define ClassImp(name)
Definition: Rtypes.h:279
double f(double x)
void Print(std::ostream &os, const OptionType &opt)
virtual const char * GetFlagsOpt() const
Return the optimization flags.
Definition: TSystem.cxx:3777
static Bool_t fgCacheFileForce
Indicates, to force all READ to CACHEREAD.
Definition: TFile.h:115
TFile * fFile
TFile instance of the file being opened.
Definition: TFile.h:337
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:416
Long64_t GetFirst() const
Definition: TFree.h:42
virtual Int_t ReadKeys(Bool_t forceRead=kTRUE)
Read the linked list of keys.
double Double_t
Definition: RtypesCore.h:55
virtual int Symlink(const char *from, const char *to)
Create a symbolic link from file1 to file2.
Definition: TSystem.cxx:1337
static Int_t GetReadaheadSize()
Static function returning the readahead buffer size.
Definition: TFile.cxx:4364
#define R__RWLOCK_ACQUIRE_READ(rwlock)
Describe directory structure in memory.
Definition: TDirectory.h:44
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition: TMap.h:44
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:174
virtual void Print(Option_t *option="") const
Print all objects in the file.
Definition: TFile.cxx:1538
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition: TTimeStamp.h:76
static Bool_t fgCacheFileDisconnected
Indicates, we trust in the files in the cache dir without stat on the cached file.
Definition: TFile.h:114
Int_t GetObjlen() const
Definition: TKey.h:89
Int_t GetKeylen() const
Definition: TKey.h:86
virtual Int_t Sizeof() const
Return the size in bytes of the file header.
Definition: TFile.cxx:2229
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
Definition: TProcessID.cxx:275
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:2882
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:349
const TMatches FindRules(const TString &source) const
Return all the rules that are about the given &#39;source&#39; class.
virtual Bool_t SendFileReadProgress(TFile *)
virtual void Close(Option_t *option="")
Delete all objects from memory and directory structure itself.
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:221
const TList * GetStreamerInfoCache()
Returns the cached list of StreamerInfos used in this file.
Definition: TFile.cxx:1304
virtual Int_t Sizeof() const
Return size of the TNamed part of the TObject.
Definition: TNamed.cxx:164
Mother of all ROOT objects.
Definition: TObject.h:44
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:4509
virtual void Paint(Option_t *option="")
Paint all objects in the file.
Definition: TFile.cxx:1530
virtual void SetCompressionSettings(Int_t settings=1)
Used to specify the compression level and algorithm.
Definition: TFile.cxx:2170
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition: TString.cxx:1807
static TString fgCacheFileDir
Directory where to locally stage files.
Definition: TFile.h:113
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition: TROOT.cxx:2606
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.
Definition: TFile.cxx:545
Bool_t R_ISDIR(Int_t mode)
Definition: TSystem.h:126
static TFileOpenHandle * AsyncOpen(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=1, Int_t netopt=0)
Submit an asynchronous open request.
Definition: TFile.cxx:4111
static Bool_t SetCacheFileDir(const char *cacheDir, Bool_t operateDisconnected=kTRUE, Bool_t forceCacheread=kFALSE)
Sets the directory where to locally stage/cache remote files.
Definition: TFile.cxx:4391
virtual void Add(TObject *obj)
Definition: TList.h:81
const Ssiz_t kNPOS
Definition: Rtypes.h:115
Int_t MakeProjectParProofInf(const char *packname, const char *proofinfdir)
Create BUILD.sh and SETUP.C under &#39;proofinf&#39; for PAR package &#39;pack&#39;.
Definition: TFile.cxx:3285
Wrapper for PCRE library (Perl Compatible Regular Expressions).
Definition: TPRegexp.h:103
virtual void ShowOutput(RedirectHandle_t *h)
Display the content associated with the redirection described by the opaque handle &#39;h&#39;...
Definition: TSystem.cxx:1687
virtual UShort_t WriteProcessID(TProcessID *pid)
Check if the ProcessID pidd is already in the file, if not, add it and return the index number in the...
Definition: TFile.cxx:3552
virtual Bool_t ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
Read the nbuf blocks described in arrays pos and len.
Definition: TFile.cxx:1653
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
virtual const char * GetObjExt() const
Get the object file extension.
Definition: TSystem.cxx:3855
void SetOptions(const char *opt)
Definition: TUrl.h:96
TF1 * f1
Definition: legend1.C:11
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1841
#define snprintf
Definition: civetweb.c:822
static UInt_t SetOpenTimeout(UInt_t timeout)
Sets open timeout time (in ms). Returns previous timeout value.
Definition: TFile.cxx:4489
virtual int CopyFile(const char *from, const char *to, Bool_t overwrite=kFALSE)
Copy a file.
Definition: TSystem.cxx:1310
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:831
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
virtual void SetCompressionAlgorithm(Int_t algorithm=0)
See comments for function SetCompressionSettings.
Definition: TFile.cxx:2136
ROOT::ESTLType GetCollectionType() const
Return the &#39;type&#39; of the STL the TClass is representing.
Definition: TClass.cxx:2800
#define R__RWLOCK_ACQUIRE_WRITE(rwlock)
void Reset()
Definition: TStopwatch.h:54
Definition: tree.py:1
virtual Int_t GetClassVersion() const =0
void Add(TObject *obj)
Definition: TObjArray.h:75
static void ResetErrno()
Static function resetting system error number.
Definition: TSystem.cxx:281
#define gDirectory
Definition: TDirectory.h:221
double result[121]
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4598
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1243
Definition: first.py:1
static Int_t fgReadaheadSize
Readahead buffer size.
Definition: TFile.h:123
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
virtual void WriteHeader()
Write File Header.
Definition: TFile.cxx:2416
TFileOpenHandle * fAsyncHandle
!For proper automatic cleanup
Definition: TFile.h:100
virtual void Close(Option_t *option="")
Close out any threads or asynchronous fetches used by the underlying implementation.
const char * GetClass() const
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
Abstract Interface class describing Streamer information for one class.
static void SetFileBytesRead(Long64_t bytes=0)
Definition: TFile.cxx:4373
const Bool_t kTRUE
Definition: Rtypes.h:91
void *(* GlobalFunc_t)()
Definition: TGlobal.h:56
static Long64_t GetFileCounter()
Definition: TFile.cxx:4382
const Int_t n
Definition: legend1.C:16
virtual void SetCacheWrite(TFileCacheWrite *cache)
Set a pointer to the write cache.
Definition: TFile.cxx:2220
virtual void ResetErrno() const
Method resetting the errno. Is overridden in TRFIOFile.
Definition: TFile.cxx:1194
TString fFile
Definition: TSystem.h:215
TFileCacheWrite * GetCacheWrite() const
Return a pointer to the current write cache.
Definition: TFile.cxx:1219
gr SetName("gr")
const char * GetOpt() const
Definition: TFile.h:354
char name[80]
Definition: TGX11.cxx:109
static const char * GetCacheFileDir()
Get the directory where to locally stage/cache remote files.
Definition: TFile.cxx:4419
const char * GetFile() const
Definition: TUrl.h:78
virtual TProcessID * ReadProcessID(UShort_t pidf)
The TProcessID with number pidf is read from this file.
Definition: TFile.cxx:1783
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition: TString.cxx:386
A cache when writing files over the network.
Int_t GetNetOpt() const
Definition: TFile.h:356
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
Int_t MakeProjectParMake(const char *packname, const char *filename)
Create makefile at &#39;filemake&#39; for PAR package &#39;pack&#39;.
Definition: TFile.cxx:3163
virtual Bool_t ReadBufferAsync(Long64_t offs, Int_t len)
Definition: TFile.cxx:4975
virtual void Close(Option_t *option="")
Close a file.
Definition: TFile.cxx:904
virtual Bool_t Matches(const char *name)
Return kTRUE if &#39;url&#39; matches the coordinates of this file.
Definition: TFile.cxx:4531
Array of chars or bytes (8 bits per element).
Definition: TArrayC.h:29
ECacheAction
TTreeCache flushing semantics.
Definition: TFile.h:62
Stopwatch class.
Definition: TStopwatch.h:30
virtual EAsyncOpenStatus GetAsyncOpenStatus()
Definition: TFile.h:125