Logo ROOT   6.08/07
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  Bool_t largeFile = (fEND > TFile::kStartBigFile);
2382 
2383  auto createKey = [this]() {
2384  Int_t nbytes = 0;
2385  TFree *afree;
2386  TIter next (fFree);
2387  while ((afree = (TFree*) next())) {
2388  nbytes += afree->Sizeof();
2389  }
2390  if (!nbytes) return (TKey*)nullptr;
2391 
2392  TKey *key = new TKey(fName,fTitle,IsA(),nbytes,this);
2393 
2394  if (key->GetSeekKey() == 0) {
2395  delete key;
2396  return (TKey*)nullptr;
2397  }
2398  return key;
2399  };
2400 
2401  TKey *key = createKey();
2402  if (!key) return;
2403 
2404  if (!largeFile && (fEND > TFile::kStartBigFile)) {
2405  // The free block list is large enough to bring the file to larger
2406  // than 2Gb, the references/offsets are now 64bits in the output
2407  // so we need to redo the calculattion since the list of free block
2408  // information will not fit in the original size.
2409  key->Delete();
2410  delete key;
2411 
2412  key = createKey();
2413  if (!key) return;
2414  }
2415 
2416  Int_t nbytes = key->GetObjlen();
2417  char *buffer = key->GetBuffer();
2418  char *start = buffer;
2419 
2420  TIter next (fFree);
2421  TFree *afree;
2422  while ((afree = (TFree*) next())) {
2423  // We could 'waste' time here and double check that
2424  // (buffer+afree->Sizeof() < (start+nbytes)
2425  afree->FillBuffer(buffer);
2426  }
2427  auto actualBytes = buffer-start;
2428  if ( actualBytes != nbytes ) {
2429  if (actualBytes < nbytes) {
2430  // Most likely one of the 'free' segment was used to store this
2431  // TKey, so we had one less TFree to store than we planned.
2432  memset(buffer,0,nbytes-actualBytes);
2433  } else {
2434  Error("WriteFree","The free block list TKey wrote more data than expected (%d vs %ld). Most likely there has been an out-of-bound write.",nbytes,actualBytes);
2435  }
2436  }
2437  fNbytesFree = key->GetNbytes();
2438  fSeekFree = key->GetSeekKey();
2439  key->WriteFile();
2440  delete key;
2441 }
2442 
2443 ////////////////////////////////////////////////////////////////////////////////
2444 /// Write File Header.
2445 
2446 void TFile::WriteHeader()
2448  SafeDelete(fInfoCache);
2449  TFree *lastfree = (TFree*)fFree->Last();
2450  if (lastfree) fEND = lastfree->GetFirst();
2451  const char *root = "root";
2452  char *psave = new char[fBEGIN];
2453  char *buffer = psave;
2454  Int_t nfree = fFree->GetSize();
2455  memcpy(buffer, root, 4); buffer += 4;
2456  Int_t version = fVersion;
2457  if (version <1000000 && fEND > kStartBigFile) {version += 1000000; fUnits = 8;}
2458  tobuf(buffer, version);
2459  tobuf(buffer, (Int_t)fBEGIN);
2460  if (version < 1000000) {
2461  tobuf(buffer, (Int_t)fEND);
2462  tobuf(buffer, (Int_t)fSeekFree);
2463  tobuf(buffer, fNbytesFree);
2464  tobuf(buffer, nfree);
2465  tobuf(buffer, fNbytesName);
2466  tobuf(buffer, fUnits);
2467  tobuf(buffer, fCompress);
2468  tobuf(buffer, (Int_t)fSeekInfo);
2469  tobuf(buffer, fNbytesInfo);
2470  } else {
2471  tobuf(buffer, fEND);
2472  tobuf(buffer, fSeekFree);
2473  tobuf(buffer, fNbytesFree);
2474  tobuf(buffer, nfree);
2475  tobuf(buffer, fNbytesName);
2476  tobuf(buffer, fUnits);
2477  tobuf(buffer, fCompress);
2478  tobuf(buffer, fSeekInfo);
2479  tobuf(buffer, fNbytesInfo);
2480  }
2481  fUUID.FillBuffer(buffer);
2482  Int_t nbytes = buffer - psave;
2483  Seek(0);
2484  WriteBuffer(psave, nbytes);
2485  Flush(); // Intentionally not conditional on fMustFlush, this is the 'obligatory' flush.
2486  delete [] psave;
2487 }
2488 
2489 ////////////////////////////////////////////////////////////////////////////////
2490 /// Generate source code necessary to access the objects stored in the file.
2491 ///
2492 /// Generate code in directory dirname for all classes specified in
2493 /// argument classes If classes = "*" (default and currently the
2494 /// only supported value), the function generates an include file
2495 /// for each class in the StreamerInfo list for which a TClass
2496 /// object does not exist.
2497 ///
2498 /// The code generated includes:
2499 /// - <em>dirnameProjectHeaders.h</em>, which contains one #include statement per generated header file
2500 /// - <em>dirnameProjectSource.cxx</em>,which contains all the constructors and destructors implementation.
2501 /// and one header per class that is not nested inside another class.
2502 /// The header file name is the fully qualified name of the class after all the special characters
2503 /// "<>,:" are replaced by underscored. For example for std::pair<edm::Vertex,int> the file name is
2504 /// pair_edm__Vertex_int_.h
2505 ///
2506 /// In the generated classes, map, multimap when the first template parameter is a class
2507 /// are replaced by a vector of pair. set and multiset when the tempalte parameter
2508 /// is a class are replaced by a vector. This is required since we do not have the
2509 /// code needed to order and/or compare the object of the classes.
2510 /// This is a quick explanation of the options available:
2511 /// Option | Details
2512 /// -------|--------
2513 /// new (default) | A new directory dirname is created. If dirname already exist, an error message is printed and the function returns.
2514 /// 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.
2515 /// 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".
2516 /// genreflex | Use genreflex rather than rootcint to generate the dictionary.
2517 /// 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).
2518 ///
2519 /// If, in addition to one of the 3 above options, the option "+" is specified,
2520 /// the function will generate:
2521 /// - a script called MAKEP to build the shared lib
2522 /// - a dirnameLinkDef.h file
2523 /// - rootcint will be run to generate a dirnameProjectDict.cxx file
2524 /// - dirnameProjectDict.cxx will be compiled with the current options in compiledata.h
2525 /// - a shared lib dirname.so will be created.
2526 /// If the option "++" is specified, the generated shared lib is dynamically
2527 /// linked with the current executable module.
2528 /// If the option "+" and "nocompile" are specified, the utility files are generated
2529 /// as in the option "+" but they are not executed.
2530 /// Example:
2531 /// file.MakeProject("demo","*","recreate++");
2532 /// - creates a new directory demo unless it already exist
2533 /// - clear the previous directory content
2534 /// - generate the xxx.h files for all classes xxx found in this file
2535 /// and not yet known to the CINT dictionary.
2536 /// - creates the build script MAKEP
2537 /// - creates a LinkDef.h file
2538 /// - runs rootcint generating demoProjectDict.cxx
2539 /// - compiles demoProjectDict.cxx into demoProjectDict.o
2540 /// - generates a shared lib demo.so
2541 /// - dynamically links the shared lib demo.so to the executable
2542 /// If only the option "+" had been specified, one can still link the
2543 /// shared lib to the current executable module with:
2544 ///
2545 /// gSystem->load("demo/demo.so");
2546 ///
2547 /// The following feature is not yet enabled:
2548 /// One can restrict the list of classes to be generated by using expressions like:
2549 ///
2550 /// classes = "Ali*" generate code only for classes starting with Ali
2551 /// classes = "myClass" generate code for class MyClass only.
2552 ///
2553 
2554 void TFile::MakeProject(const char *dirname, const char * /*classes*/,
2555  Option_t *option)
2556 {
2557  TString opt = option;
2558  opt.ToLower();
2559  Bool_t makepar = kFALSE;
2560  TString parname, pardir;
2561  if (opt.Contains("par")) {
2562  // Create a PAR file
2563  parname = gSystem->BaseName(dirname);
2564  if (parname.EndsWith(".par")) parname.ReplaceAll(".par","");
2565  pardir = gSystem->DirName(dirname);
2566  // Cleanup or prepare the dirs
2567  TString path, filepath;
2568  void *dir = gSystem->OpenDirectory(pardir);
2569  if (dir) {
2570  path.Form("%s/%s", pardir.Data(), parname.Data());
2571  void *dirp = gSystem->OpenDirectory(path);
2572  if (dirp) {
2573  path += "/PROOF-INF";
2574  void *dirinf = gSystem->OpenDirectory(path);
2575  const char *afile = 0;
2576  if (dirinf) {
2577  while ((afile = gSystem->GetDirEntry(dirinf))) {
2578  if (strcmp(afile,".") == 0) continue;
2579  if (strcmp(afile,"..") == 0) continue;
2580  filepath.Form("%s/%s", path.Data(), afile);
2581  if (gSystem->Unlink(filepath))
2582  Warning("MakeProject", "1: problems unlinking '%s' ('%s', '%s')", filepath.Data(), path.Data(), afile);
2583  }
2584  gSystem->FreeDirectory(dirinf);
2585  }
2586  gSystem->Unlink(path);
2587  path.Form("%s/%s", pardir.Data(), parname.Data());
2588  while ((afile = gSystem->GetDirEntry(dirp))) {
2589  if (strcmp(afile,".") == 0) continue;
2590  if (strcmp(afile,"..") == 0) continue;
2591  filepath.Form("%s/%s", path.Data(), afile);
2592  if (gSystem->Unlink(filepath))
2593  Warning("MakeProject", "2: problems unlinking '%s' ('%s', '%s')", filepath.Data(), path.Data(), afile);
2594  }
2595  gSystem->FreeDirectory(dirp);
2596  if (gSystem->Unlink(path))
2597  Warning("MakeProject", "problems unlinking '%s'", path.Data());
2598  }
2599  }
2600  // Make sure that the relevant dirs exists: this is mandatory, so we fail if unsuccessful
2601  path.Form("%s/%s/PROOF-INF", pardir.Data(), parname.Data());
2602  if (gSystem->mkdir(path, kTRUE)) {
2603  Error("MakeProject", "problems creating '%s'", path.Data());
2604  return;
2605  }
2606  makepar = kTRUE;
2607 
2608  } else {
2609  void *dir = gSystem->OpenDirectory(dirname);
2610  TString dirpath;
2611 
2612  if (opt.Contains("update")) {
2613  // check that directory exist, if not create it
2614  if (dir == 0) {
2615  gSystem->mkdir(dirname);
2616  }
2617 
2618  } else if (opt.Contains("recreate")) {
2619  // check that directory exist, if not create it
2620  if (dir == 0) {
2621  if (gSystem->mkdir(dirname) < 0) {
2622  Error("MakeProject","cannot create directory '%s'",dirname);
2623  return;
2624  }
2625  }
2626  // clear directory
2627  while (dir) {
2628  const char *afile = gSystem->GetDirEntry(dir);
2629  if (afile == 0) break;
2630  if (strcmp(afile,".") == 0) continue;
2631  if (strcmp(afile,"..") == 0) continue;
2632  dirpath.Form("%s/%s",dirname,afile);
2633  gSystem->Unlink(dirpath);
2634  }
2635 
2636  } else {
2637  // new is assumed
2638  // if directory already exist, print error message and return
2639  if (dir) {
2640  Error("MakeProject","cannot create directory %s, already existing",dirname);
2641  gSystem->FreeDirectory(dir);
2642  return;
2643  }
2644  if (gSystem->mkdir(dirname) < 0) {
2645  Error("MakeProject","cannot create directory '%s'",dirname);
2646  return;
2647  }
2648  }
2649  if (dir) {
2650  gSystem->FreeDirectory(dir);
2651  }
2652  }
2653  Bool_t genreflex = opt.Contains("genreflex");
2654 
2655  // we are now ready to generate the classes
2656  // loop on all TStreamerInfo
2657  TList *filelist = (TList*)GetStreamerInfoCache();
2658  if (filelist) filelist = (TList*)filelist->Clone();
2659  if (filelist == 0) {
2660  Error("MakeProject","file %s has no StreamerInfo", GetName());
2661  return;
2662  }
2663 
2664  TString clean_dirname(dirname);
2665  if (makepar) clean_dirname.Form("%s/%s", pardir.Data(), parname.Data());
2666  if (clean_dirname[clean_dirname.Length()-1]=='/') {
2667  clean_dirname.Remove(clean_dirname.Length()-1);
2668  } else if (clean_dirname[clean_dirname.Length()-1]=='\\') {
2669  clean_dirname.Remove(clean_dirname.Length()-1);
2670  if (clean_dirname[clean_dirname.Length()-1]=='\\') {
2671  clean_dirname.Remove(clean_dirname.Length()-1);
2672  }
2673  }
2674  TString subdirname( gSystem->BaseName(clean_dirname) );
2675  if (makepar) subdirname = parname;
2676  if (subdirname == "") {
2677  Error("MakeProject","Directory name must not be empty.");
2678  return;
2679  }
2680 
2681  // Start the source file
2682  TString spath; spath.Form("%s/%sProjectSource.cxx",clean_dirname.Data(),subdirname.Data());
2683  FILE *sfp = fopen(spath.Data(),"w");
2684  if (sfp ==0) {
2685  Error("MakeProject","Unable to create the source file %s.",spath.Data());
2686  return;
2687  }
2688  fprintf(sfp, "namespace std {}\nusing namespace std;\n");
2689  fprintf(sfp, "#include \"%sProjectHeaders.h\"\n\n",subdirname.Data() );
2690  if (!genreflex) fprintf(sfp, "#include \"%sLinkDef.h\"\n\n",subdirname.Data() );
2691  fprintf(sfp, "#include \"%sProjectDict.cxx\"\n\n",subdirname.Data() );
2692  fprintf(sfp, "struct DeleteObjectFunctor {\n");
2693  fprintf(sfp, " template <typename T>\n");
2694  fprintf(sfp, " void operator()(const T *ptr) const {\n");
2695  fprintf(sfp, " delete ptr;\n");
2696  fprintf(sfp, " }\n");
2697  fprintf(sfp, " template <typename T, typename Q>\n");
2698  fprintf(sfp, " void operator()(const std::pair<T,Q> &) const {\n");
2699  fprintf(sfp, " // Do nothing\n");
2700  fprintf(sfp, " }\n");
2701  fprintf(sfp, " template <typename T, typename Q>\n");
2702  fprintf(sfp, " void operator()(const std::pair<T,Q*> &ptr) const {\n");
2703  fprintf(sfp, " delete ptr.second;\n");
2704  fprintf(sfp, " }\n");
2705  fprintf(sfp, " template <typename T, typename Q>\n");
2706  fprintf(sfp, " void operator()(const std::pair<T*,Q> &ptr) const {\n");
2707  fprintf(sfp, " delete ptr.first;\n");
2708  fprintf(sfp, " }\n");
2709  fprintf(sfp, " template <typename T, typename Q>\n");
2710  fprintf(sfp, " void operator()(const std::pair<T*,Q*> &ptr) const {\n");
2711  fprintf(sfp, " delete ptr.first;\n");
2712  fprintf(sfp, " delete ptr.second;\n");
2713  fprintf(sfp, " }\n");
2714  fprintf(sfp, "};\n\n");
2715  fclose( sfp );
2716 
2717  // loop on all TStreamerInfo classes to check for empty classes
2718  // and enums listed either as data member or template parameters,
2719  // and filter out 'duplicates' classes/streamerInfos.
2720  TStreamerInfo *info;
2721  TIter flnext(filelist);
2722  TList extrainfos;
2723  TList *list = new TList();
2724  while ((info = (TStreamerInfo*)flnext())) {
2725  if (info->IsA() != TStreamerInfo::Class()) {
2726  continue;
2727  }
2728  if (strstr(info->GetName(),"@@")) {
2729  // Skip schema evolution support streamerInfo
2730  continue;
2731  }
2732  TClass *cl = TClass::GetClass(info->GetName());
2733  if (cl) {
2734  if (cl->HasInterpreterInfo()) continue; // skip known classes
2735  }
2736  // Find and use the proper rules for the TStreamerInfos.
2737  TMakeProject::GenerateMissingStreamerInfos( &extrainfos, info->GetName() );
2738  TIter enext( info->GetElements() );
2739  TStreamerElement *el;
2741  if (cl && cl->GetSchemaRules()) {
2742  rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
2743  }
2744  while( (el=(TStreamerElement*)enext()) ) {
2745  for(auto rule : rules) {
2746  if( rule->IsRenameRule() || rule->IsAliasRule() )
2747  continue;
2748  // Check whether this is an 'attribute' rule.
2749  if ( rule->HasTarget( el->GetName()) && rule->GetAttributes()[0] != 0 ) {
2750  TString attr( rule->GetAttributes() );
2751  attr.ToLower();
2752  if (attr.Contains("owner")) {
2753  if (attr.Contains("notowner")) {
2754  el->SetBit(TStreamerElement::kDoNotDelete);
2755  } else {
2756  el->ResetBit(TStreamerElement::kDoNotDelete);
2757  }
2758  }
2759  }
2760  }
2762  }
2763  TVirtualStreamerInfo *alternate = (TVirtualStreamerInfo*)list->FindObject(info->GetName());
2764  if (alternate) {
2765  if ((info->GetClass() && info->GetClassVersion() == info->GetClass()->GetClassVersion())
2766  || (info->GetClassVersion() > alternate->GetClassVersion()) ) {
2767  list->AddAfter(alternate, info);
2768  list->Remove(alternate);
2769  } // otherwise ignore this info as not being the official one.
2770  } else {
2771  list->Add(info);
2772  }
2773  }
2774  // Now transfer the new StreamerInfo onto the main list and
2775  // to the owning list.
2776  TIter nextextra(&extrainfos);
2777  while ((info = (TStreamerInfo*)nextextra())) {
2778  list->Add(info);
2779  filelist->Add(info);
2780  }
2781 
2782  // loop on all TStreamerInfo classes
2783  TIter next(list);
2784  Int_t ngener = 0;
2785  while ((info = (TStreamerInfo*)next())) {
2786  if (info->IsA() != TStreamerInfo::Class()) {
2787  continue;
2788  }
2789  if (info->GetClassVersion()==-4) continue; // Skip outer level namespace
2790  TIter subnext(list);
2791  TStreamerInfo *subinfo;
2792  TList subClasses;
2793  Int_t len = strlen(info->GetName());
2794  while ((subinfo = (TStreamerInfo*)subnext())) {
2795  if (subinfo->IsA() != TStreamerInfo::Class()) {
2796  continue;
2797  }
2798  if (strncmp(info->GetName(),subinfo->GetName(),len)==0) {
2799  // The 'sub' StreamerInfo start with the main StreamerInfo name,
2800  // it subinfo is likely to be a nested class.
2801  const Int_t sublen = strlen(subinfo->GetName());
2802  if ( (sublen > len) && subinfo->GetName()[len+1]==':'
2803  && !subClasses.FindObject(subinfo->GetName()) /* We need to insure uniqueness */)
2804  {
2805  subClasses.Add(subinfo);
2806  }
2807  }
2808  }
2809  ngener += info->GenerateHeaderFile(clean_dirname.Data(),&subClasses,&extrainfos);
2810  subClasses.Clear("nodelete");
2811  }
2812  TString path;
2813  path.Form("%s/%sProjectHeaders.h",clean_dirname.Data(),subdirname.Data());
2814  FILE *allfp = fopen(path,"a");
2815  if (!allfp) {
2816  Error("MakeProject","Cannot open output file:%s\n",path.Data());
2817  } else {
2818  fprintf(allfp,"#include \"%sProjectInstances.h\"\n", subdirname.Data());
2819  fclose(allfp);
2820  }
2821 
2822  printf("MakeProject has generated %d classes in %s\n",ngener,clean_dirname.Data());
2823 
2824  // generate the shared lib
2825  if (!opt.Contains("+") && !makepar) {
2826  delete list;
2827  filelist->Delete();
2828  delete filelist;
2829  return;
2830  }
2831 
2832  // Makefiles files
2833  FILE *fpMAKE = 0;
2834  if (!makepar) {
2835  // Create the MAKEP file by looping on all *.h files
2836  // delete MAKEP if it already exists
2837 #ifdef WIN32
2838  path.Form("%s/makep.cmd",clean_dirname.Data());
2839 #else
2840  path.Form("%s/MAKEP",clean_dirname.Data());
2841 #endif
2842 #ifdef R__WINGCC
2843  fpMAKE = fopen(path,"wb");
2844 #else
2845  fpMAKE = fopen(path,"w");
2846 #endif
2847  if (!fpMAKE) {
2848  Error("MakeProject", "cannot open file %s", path.Data());
2849  delete list;
2850  filelist->Delete();
2851  delete filelist;
2852  return;
2853  }
2854  }
2855 
2856  // Add rootcint/genreflex statement generating ProjectDict.cxx
2857  FILE *ifp = 0;
2858  path.Form("%s/%sProjectInstances.h",clean_dirname.Data(),subdirname.Data());
2859 #ifdef R__WINGCC
2860  ifp = fopen(path,"wb");
2861 #else
2862  ifp = fopen(path,"w");
2863 #endif
2864  if (!ifp) {
2865  Error("MakeProject", "cannot open path file %s", path.Data());
2866  delete list;
2867  filelist->Delete();
2868  delete filelist;
2869  fclose(fpMAKE);
2870  return;
2871  }
2872 
2873  if (!makepar) {
2874  if (genreflex) {
2875  fprintf(fpMAKE,"genreflex %sProjectHeaders.h -o %sProjectDict.cxx --comments --iocomments %s ",subdirname.Data(),subdirname.Data(),gSystem->GetIncludePath());
2876  path.Form("%s/%sSelection.xml",clean_dirname.Data(),subdirname.Data());
2877  } else {
2878  fprintf(fpMAKE,"rootcint -f %sProjectDict.cxx -c %s ",subdirname.Data(),gSystem->GetIncludePath());
2879  path.Form("%s/%sLinkDef.h",clean_dirname.Data(),subdirname.Data());
2880  }
2881  } else {
2882  path.Form("%s/%sLinkDef.h",clean_dirname.Data(),subdirname.Data());
2883  }
2884 
2885  // Create the LinkDef.h or xml selection file by looping on all *.h files
2886  // replace any existing file.
2887 #ifdef R__WINGCC
2888  FILE *fp = fopen(path,"wb");
2889 #else
2890  FILE *fp = fopen(path,"w");
2891 #endif
2892  if (!fp) {
2893  Error("MakeProject", "cannot open path file %s", path.Data());
2894  delete list;
2895  filelist->Delete();
2896  delete filelist;
2897  fclose(fpMAKE);
2898  fclose(ifp);
2899  return;
2900  }
2901  if (genreflex) {
2902  fprintf(fp,"<lcgdict>\n");
2903  fprintf(fp,"\n");
2904  } else {
2905  fprintf(fp,"#ifdef __CINT__\n");
2906  fprintf(fp,"\n");
2907  }
2908 
2909  TString tmp;
2910  TString instances;
2911  TString selections;
2912  next.Reset();
2913  while ((info = (TStreamerInfo*)next())) {
2914  if (info->IsA() != TStreamerInfo::Class()) {
2915  continue;
2916  }
2917  TClass *cl = TClass::GetClass(info->GetName());
2918  if (cl) {
2919  if (cl->HasInterpreterInfo()) continue; // skip known classes
2920  if (cl->GetSchemaRules()) {
2921  auto rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
2922  TString strrule;
2923  for(auto rule : rules) {
2924  strrule.Clear();
2925  if (genreflex) {
2926  rule->AsString(strrule,"x");
2927  strrule.Append("\n");
2928  if ( selections.Index(strrule) == kNPOS ) {
2929  selections.Append(strrule);
2930  }
2931  } else {
2932  rule->AsString(strrule);
2933  if (strncmp(strrule.Data(),"type=",5)==0) {
2934  strrule.Remove(0,5);
2935  }
2936  fprintf(fp,"#pragma %s;\n",strrule.Data());
2937  }
2938  }
2939  }
2940 
2941  }
2942  if ((info->GetClass() && info->GetClass()->GetCollectionType()) || TClassEdit::IsSTLCont(info->GetName())) {
2943  std::vector<std::string> inside;
2944  int nestedLoc;
2945  TClassEdit::GetSplit( info->GetName(), inside, nestedLoc, TClassEdit::kLong64 );
2946  Int_t stlkind = TClassEdit::STLKind(inside[0].c_str());
2947  TClass *key = TClass::GetClass(inside[1].c_str());
2948  if (key) {
2949  TString what;
2950  switch ( stlkind ) {
2951  case ROOT::kSTLmap:
2952  case ROOT::kSTLmultimap:
2953  if (TClass::GetClass(inside[1].c_str())) {
2954  what = "std::pair<";
2955  what += TMakeProject::UpdateAssociativeToVector( inside[1].c_str() );
2956  what += ",";
2957  what += TMakeProject::UpdateAssociativeToVector( inside[2].c_str() );
2958  if (what[what.Length()-1]=='>') {
2959  what += " >";
2960  } else {
2961  what += ">";
2962  }
2963  if (genreflex) {
2964  tmp.Form("<class name=\"%s\" />\n",what.Data());
2965  if ( selections.Index(tmp) == kNPOS ) {
2966  selections.Append(tmp);
2967  }
2968  tmp.Form("template class %s;\n",what.Data());
2969  if ( instances.Index(tmp) == kNPOS ) {
2970  instances.Append(tmp);
2971  }
2972  } else {
2973  what.ReplaceAll("std::","");
2974  TClass *paircl = TClass::GetClass(what.Data());
2975  if (paircl == 0 || !paircl->HasInterpreterInfo()) {
2976  fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
2977  }
2978  }
2979  break;
2980  }
2981  default:
2982  if (strncmp(key->GetName(),"pair<",strlen("pair<"))==0) {
2983  if (genreflex) {
2984  tmp.Form("<class name=\"%s\" />\n",key->GetName());
2985  if ( selections.Index(tmp) == kNPOS ) {
2986  selections.Append(tmp);
2987  }
2988  tmp.Form("template class %s;\n",key->GetName());
2989  if ( instances.Index(tmp) == kNPOS ) {
2990  instances.Append(tmp);
2991  }
2992  } else {
2993  what.ReplaceAll("std::","");
2994  fprintf(fp,"#pragma link C++ class %s+;\n",key->GetName());
2995  }
2996  }
2997  break;
2998  }
2999  }
3000  continue;
3001  }
3002  {
3004  if (genreflex) {
3005  tmp.Form("<class name=\"%s\" />\n",what.Data());
3006  if ( selections.Index(tmp) == kNPOS ) {
3007  selections.Append(tmp);
3008  }
3009  if (what[what.Length()-1] == '>') {
3010  tmp.Form("template class %s;\n",what.Data());
3011  if ( instances.Index(tmp) == kNPOS ) {
3012  instances.Append(tmp);
3013  }
3014  }
3015  } else {
3016  what.ReplaceAll("std::","");
3017  fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
3018  }
3019  }
3020  if (genreflex) {
3021  // Also request the dictionary for the STL container used as members ...
3022  TIter eliter( info->GetElements() );
3023  TStreamerElement *element;
3024  while( (element = (TStreamerElement*)eliter() ) ) {
3025  if (element->GetClass() && !element->GetClass()->IsLoaded() && element->GetClass()->GetCollectionProxy()) {
3026  TString what( TMakeProject::UpdateAssociativeToVector(element->GetClass()->GetName()) );
3027  tmp.Form("<class name=\"%s\" />\n",what.Data());
3028  if ( selections.Index(tmp) == kNPOS ) {
3029  selections.Append(tmp);
3030  }
3031  tmp.Form("template class %s;\n",what.Data());
3032  if ( instances.Index(tmp) == kNPOS ) {
3033  instances.Append(tmp);
3034  }
3035  }
3036  }
3037  }
3038  }
3039  if (genreflex) {
3040  fprintf(ifp,"#ifndef PROJECT_INSTANCES_H\n");
3041  fprintf(ifp,"#define PROJECT_INSTANCES_H\n");
3042  fprintf(ifp,"%s",instances.Data());
3043  fprintf(ifp,"#endif\n");
3044  fprintf(fp,"%s",selections.Data());
3045  fprintf(fp,"</lcgdict>\n");
3046  } else {
3047  fprintf(fp,"#endif\n");
3048  }
3049  fclose(fp);
3050  fclose(ifp);
3051 
3052  if (!makepar) {
3053  // add compilation line
3054  TString sdirname(subdirname);
3055 
3056  TString cmd = gSystem->GetMakeSharedLib();
3057  TString sources = TString::Format("%sProjectSource.cxx ", sdirname.Data());
3058  cmd.ReplaceAll("$SourceFiles",sources.Data());
3059  TString object = TString::Format("%sProjectSource.", sdirname.Data());
3060  object.Append( gSystem->GetObjExt() );
3061  cmd.ReplaceAll("$ObjectFiles", object.Data());
3062  cmd.ReplaceAll("$IncludePath",TString(gSystem->GetIncludePath()) + " -I" + clean_dirname.Data());
3063  cmd.ReplaceAll("$SharedLib",sdirname+"."+gSystem->GetSoExt());
3064  cmd.ReplaceAll("$LinkedLibs",gSystem->GetLibraries("","SDL"));
3065  cmd.ReplaceAll("$LibName",sdirname);
3066  cmd.ReplaceAll("$BuildDir",".");
3067  TString sOpt;
3068  TString rootbuild = ROOTBUILD;
3069  if (rootbuild.Index("debug",0,TString::kIgnoreCase)==kNPOS) {
3070  sOpt = gSystem->GetFlagsOpt();
3071  } else {
3072  sOpt = gSystem->GetFlagsDebug();
3073  }
3074  cmd.ReplaceAll("$Opt", sOpt);
3075 
3076  if (genreflex) {
3077  fprintf(fpMAKE,"-s %sSelection.xml \n",subdirname.Data());
3078  } else {
3079  fprintf(fpMAKE,"%sProjectHeaders.h ",subdirname.Data());
3080  fprintf(fpMAKE,"%sLinkDef.h \n",subdirname.Data());
3081  }
3082 
3083  fprintf(fpMAKE,"%s\n",cmd.Data());
3084 
3085  printf("%s/MAKEP file has been generated\n", clean_dirname.Data());
3086 
3087  fclose(fpMAKE);
3088 
3089  } else {
3090 
3091  // Create the Makefile
3092  TString filemake = TString::Format("%s/Makefile", clean_dirname.Data());
3093  if (MakeProjectParMake(parname, filemake.Data()) != 0) {
3094  Error("MakeProject", "problems creating PAR make file '%s'", filemake.Data());
3095  delete list;
3096  filelist->Delete();
3097  delete filelist;
3098  return;
3099  }
3100  // Get Makefile.arch
3101 #ifdef ROOTETCDIR
3102  TString mkarchsrc = TString::Format("%s/Makefile.arch", ROOTETCDIR);
3103 #else
3104  TString mkarchsrc("$(ROOTSYS)/etc/Makefile.arch");
3105 #endif
3106  if (gSystem->ExpandPathName(mkarchsrc))
3107  Warning("MakeProject", "problems expanding '%s'", mkarchsrc.Data());
3108  TString mkarchdst = TString::Format("%s/Makefile.arch", clean_dirname.Data());
3109  if (gSystem->CopyFile(mkarchsrc.Data(), mkarchdst.Data(), kTRUE) != 0) {
3110  Error("MakeProject", "problems retrieving '%s' to '%s'", mkarchsrc.Data(), mkarchdst.Data());
3111  delete list;
3112  filelist->Delete();
3113  delete filelist;
3114  return;
3115  }
3116  // Create the Makefile
3117  TString proofinf = TString::Format("%s/PROOF-INF", clean_dirname.Data());
3118  if (MakeProjectParProofInf(parname, proofinf.Data()) != 0) {
3119  Error("MakeProject", "problems creating BUILD.sh and/or SETUP.C under '%s'", proofinf.Data());
3120  delete list;
3121  filelist->Delete();
3122  delete filelist;
3123  return;
3124  }
3125 
3126  // Make sure BUILD.sh is executable and create SETUP.C
3127  TString cmod = TString::Format("chmod +x %s/PROOF-INF/BUILD.sh", clean_dirname.Data());
3128 #ifndef WIN32
3129  gSystem->Exec(cmod.Data());
3130 #else
3131  // not really needed for Windows but it would work both both Unix and NT
3132  chmod(cmod.Data(), 00700);
3133 #endif
3134  Printf("Files Makefile, Makefile.arch, PROOF-INF/BUILD.sh and"
3135  " PROOF-INF/SETUP.C have been generated under '%s'", clean_dirname.Data());
3136 
3137  // Generate the PAR file, if not Windows
3138 #ifndef WIN32
3139  TString curdir = gSystem->WorkingDirectory();
3140  if (gSystem->ChangeDirectory(pardir)) {
3141  TString cmd = TString::Format("tar czvf %s.par %s", parname.Data(), parname.Data());
3142  gSystem->Exec(cmd.Data());
3143  if (gSystem->ChangeDirectory(curdir)) {
3144  Info("MakeProject", "PAR file %s.par generated", clean_dirname.Data());
3145  } else {
3146  Warning("MakeProject", "problems changing directory back to '%s'", curdir.Data());
3147  }
3148  } else {
3149  Error("MakeProject", "problems changing directory to '%s' - skipping PAR file generation", pardir.Data());
3150  }
3151 #else
3152  Warning("MakeProject", "on Windows systems the PAR file cannot be generated out of the package directory!");
3153 #endif
3154  }
3155 
3156 
3157  if (!makepar && !opt.Contains("nocompilation")) {
3158  // now execute the generated script compiling and generating the shared lib
3159  path = gSystem->WorkingDirectory();
3160  gSystem->ChangeDirectory(clean_dirname.Data());
3161 #ifndef WIN32
3162  gSystem->Exec("chmod +x MAKEP");
3163  int res = !gSystem->Exec("./MAKEP");
3164 #else
3165  // not really needed for Windows but it would work both both Unix and NT
3166  chmod("makep.cmd",00700);
3167  int res = !gSystem->Exec("MAKEP");
3168 #endif
3169  gSystem->ChangeDirectory(path);
3170  path.Form("%s/%s.%s",clean_dirname.Data(),subdirname.Data(),gSystem->GetSoExt());
3171  if (res) printf("Shared lib %s has been generated\n",path.Data());
3172 
3173  //dynamically link the generated shared lib
3174  if (opt.Contains("++")) {
3175  res = !gSystem->Load(path);
3176  if (res) printf("Shared lib %s has been dynamically linked\n",path.Data());
3177  }
3178  }
3179 
3180  extrainfos.Clear("nodelete");
3181  // filelist->Clear("nodetele");
3182  delete list;
3183  filelist->Delete();
3184  delete filelist;
3185 }
3186 
3187 ////////////////////////////////////////////////////////////////////////////////
3188 /// Create makefile at 'filemake' for PAR package 'pack'.
3189 ///
3190 /// Called by MakeProject when option 'par' is given.
3191 /// Return 0 on success, -1 on error.
3192 
3193 Int_t TFile::MakeProjectParMake(const char *pack, const char *filemake)
3195  // Output file path must be defined
3196  if (!filemake || (filemake && strlen(filemake) <= 0)) {
3197  Error("MakeProjectParMake", "path for output file undefined!");
3198  return -1;
3199  }
3200 
3201  // Package name must be defined
3202  if (!pack || (pack && strlen(pack) <= 0)) {
3203  Error("MakeProjectParMake", "package name undefined!");
3204  return -1;
3205  }
3206 
3207 #ifdef R__WINGCC
3208  FILE *fmk = fopen(filemake, "wb");
3209 #else
3210  FILE *fmk = fopen(filemake, "w");
3211 #endif
3212  if (!fmk) {
3213  Error("MakeProjectParMake", "cannot create file '%s' (errno: %d)", filemake, TSystem::GetErrno());
3214  return -1;
3215  }
3216 
3217  // Fill the file now
3218  fprintf(fmk, "# Makefile for the ROOT test programs.\n");
3219  fprintf(fmk, "# This Makefile shows how to compile and link applications\n");
3220  fprintf(fmk, "# using the ROOT libraries on all supported platforms.\n");
3221  fprintf(fmk, "#\n");
3222  fprintf(fmk, "# Copyright (c) 2000 Rene Brun and Fons Rademakers\n");
3223  fprintf(fmk, "#\n");
3224  fprintf(fmk, "# Author: this makefile has been automatically generated via TFile::MakeProject\n");
3225  fprintf(fmk, "\n");
3226  fprintf(fmk, "include Makefile.arch\n");
3227  fprintf(fmk, "\n");
3228  fprintf(fmk, "#------------------------------------------------------------------------------\n");
3229  fprintf(fmk, "\n");
3230  fprintf(fmk, "PACKO = %sProjectSource.$(ObjSuf)\n", pack);
3231  fprintf(fmk, "PACKS = %sProjectSource.$(SrcSuf) %sProjectDict.$(SrcSuf)\n", pack, pack);
3232  fprintf(fmk, "PACKSO = lib%s.$(DllSuf)\n", pack);
3233  fprintf(fmk, "\n");
3234  fprintf(fmk, "ifeq ($(PLATFORM),win32)\n");
3235  fprintf(fmk, "PACKLIB = lib%s.lib\n", pack);
3236  fprintf(fmk, "else\n");
3237  fprintf(fmk, "PACKLIB = $(PACKSO)\n");
3238  fprintf(fmk, "endif\n");
3239  fprintf(fmk, "\n");
3240  fprintf(fmk, "OBJS = $(PACKO)\n");
3241  fprintf(fmk, "\n");
3242  fprintf(fmk, "PROGRAMS =\n");
3243  fprintf(fmk, "\n");
3244  fprintf(fmk, "#------------------------------------------------------------------------------\n");
3245  fprintf(fmk, "\n");
3246  fprintf(fmk, ".SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(DllSuf)\n");
3247  fprintf(fmk, "\n");
3248  fprintf(fmk, "all: $(PACKLIB)\n");
3249  fprintf(fmk, "\n");
3250  fprintf(fmk, "$(PACKSO): $(PACKO)\n");
3251  fprintf(fmk, "ifeq ($(ARCH),aix)\n");
3252  fprintf(fmk, "\t\t/usr/ibmcxx/bin/makeC++SharedLib $(OutPutOpt) $@ $(LIBS) -p 0 $^\n");
3253  fprintf(fmk, "else\n");
3254  fprintf(fmk, "ifeq ($(ARCH),aix5)\n");
3255  fprintf(fmk, "\t\t/usr/vacpp/bin/makeC++SharedLib $(OutPutOpt) $@ $(LIBS) -p 0 $^\n");
3256  fprintf(fmk, "else\n");
3257  fprintf(fmk, "ifeq ($(PLATFORM),macosx)\n");
3258  fprintf(fmk, "# We need to make both the .dylib and the .so\n");
3259  fprintf(fmk, "\t\t$(LD) $(SOFLAGS)$@ $(LDFLAGS) $^ $(OutPutOpt) $@ $(LIBS)\n");
3260  fprintf(fmk, "ifneq ($(subst $(MACOSX_MINOR),,1234),1234)\n");
3261  fprintf(fmk, "ifeq ($(MACOSX_MINOR),4)\n");
3262  fprintf(fmk, "\t\tln -sf $@ $(subst .$(DllSuf),.so,$@)\n");
3263  fprintf(fmk, "else\n");
3264  fprintf(fmk, "\t\t$(LD) -bundle -undefined $(UNDEFOPT) $(LDFLAGS) $^ \\\n");
3265  fprintf(fmk, "\t\t $(OutPutOpt) $(subst .$(DllSuf),.so,$@)\n");
3266  fprintf(fmk, "endif\n");
3267  fprintf(fmk, "endif\n");
3268  fprintf(fmk, "else\n");
3269  fprintf(fmk, "ifeq ($(PLATFORM),win32)\n");
3270  fprintf(fmk, "\t\tbindexplib $* $^ > $*.def\n");
3271  fprintf(fmk, "\t\tlib -nologo -MACHINE:IX86 $^ -def:$*.def \\\n");
3272  fprintf(fmk, "\t\t $(OutPutOpt)$(PACKLIB)\n");
3273  fprintf(fmk, "\t\t$(LD) $(SOFLAGS) $(LDFLAGS) $^ $*.exp $(LIBS) \\\n");
3274  fprintf(fmk, "\t\t $(OutPutOpt)$@\n");
3275  fprintf(fmk, "else\n");
3276  fprintf(fmk, "\t\t$(LD) $(SOFLAGS) $(LDFLAGS) $^ $(OutPutOpt) $@ $(LIBS) $(EXPLLINKLIBS)\n");
3277  fprintf(fmk, "endif\n");
3278  fprintf(fmk, "endif\n");
3279  fprintf(fmk, "endif\n");
3280  fprintf(fmk, "endif\n");
3281  fprintf(fmk, "\t\t@echo \"$@ done\"\n");
3282  fprintf(fmk, "\n");
3283  fprintf(fmk, "clean:\n");
3284  fprintf(fmk, "\t\t@rm -f $(OBJS) core\n");
3285  fprintf(fmk, "\n");
3286  fprintf(fmk, "distclean: clean\n");
3287  fprintf(fmk, "\t\t@rm -f $(PROGRAMS) $(PACKSO) $(PACKLIB) *Dict.* *.def *.exp \\\n");
3288  fprintf(fmk, "\t\t *.so *.lib *.dll *.d *.log .def so_locations\n");
3289  fprintf(fmk, "\t\t@rm -rf cxx_repository\n");
3290  fprintf(fmk, "\n");
3291  fprintf(fmk, "# Dependencies\n");
3292  fprintf(fmk, "\n");
3293  fprintf(fmk, "%sProjectSource.$(ObjSuf): %sProjectHeaders.h %sLinkDef.h %sProjectDict.$(SrcSuf)\n", pack, pack, pack, pack);
3294  fprintf(fmk, "\n");
3295  fprintf(fmk, "%sProjectDict.$(SrcSuf): %sProjectHeaders.h %sLinkDef.h\n", pack, pack, pack);
3296  fprintf(fmk, "\t\t@echo \"Generating dictionary $@...\"\n");
3297  fprintf(fmk, "\t\t@rootcint -f $@ -c $^\n");
3298  fprintf(fmk, "\n");
3299  fprintf(fmk, ".$(SrcSuf).$(ObjSuf):\n");
3300  fprintf(fmk, "\t\t$(CXX) $(CXXFLAGS) -c $<\n");
3301  fprintf(fmk, "\n");
3302 
3303  // Close the file
3304  fclose(fmk);
3305 
3306  // Done
3307  return 0;
3308 }
3309 
3310 ////////////////////////////////////////////////////////////////////////////////
3311 /// Create BUILD.sh and SETUP.C under 'proofinf' for PAR package 'pack'.
3312 /// Called by MakeProject when option 'par' is given.
3313 /// Return 0 on success, -1 on error.
3314 
3315 Int_t TFile::MakeProjectParProofInf(const char *pack, const char *proofinf)
3317  // Output directory path must be defined ...
3318  if (!proofinf || (proofinf && strlen(proofinf) <= 0)) {
3319  Error("MakeProjectParProofInf", "directory path undefined!");
3320  return -1;
3321  }
3322 
3323  // ... and exist and be a directory
3324  Int_t rcst = 0;
3325  FileStat_t st;
3326  if ((rcst = gSystem->GetPathInfo(proofinf, st)) != 0 || !R_ISDIR(st.fMode)) {
3327  Error("MakeProjectParProofInf", "path '%s' %s", proofinf,
3328  ((rcst == 0) ? "is not a directory" : "does not exist"));
3329  return -1;
3330  }
3331 
3332  // Package name must be defined
3333  if (!pack || (pack && strlen(pack) <= 0)) {
3334  Error("MakeProjectParProofInf", "package name undefined!");
3335  return -1;
3336  }
3337 
3338  TString path;
3339 
3340  // The BUILD.sh first
3341  path.Form("%s/BUILD.sh", proofinf);
3342 #ifdef R__WINGCC
3343  FILE *f = fopen(path.Data(), "wb");
3344 #else
3345  FILE *f = fopen(path.Data(), "w");
3346 #endif
3347  if (!f) {
3348  Error("MakeProjectParProofInf", "cannot create file '%s' (errno: %d)",
3349  path.Data(), TSystem::GetErrno());
3350  return -1;
3351  }
3352 
3353  fprintf(f, "#! /bin/sh\n");
3354  fprintf(f, "# Build libEvent library.\n");
3355  fprintf(f, "\n");
3356  fprintf(f, "#\n");
3357  fprintf(f, "# The environment variables ROOTPROOFLITE and ROOTPROOFCLIENT can be used to\n");
3358  fprintf(f, "# adapt the script to the calling environment\n");
3359  fprintf(f, "#\n");
3360  fprintf(f, "# if test ! \"x$ROOTPROOFLITE\" = \"x\"; then\n");
3361  fprintf(f, "# echo \"event-BUILD: PROOF-Lite node (session has $ROOTPROOFLITE workers)\"\n");
3362  fprintf(f, "# elif test ! \"x$ROOTPROOFCLIENT\" = \"x\"; then\n");
3363  fprintf(f, "# echo \"event-BUILD: PROOF client\"\n");
3364  fprintf(f, "# else\n");
3365  fprintf(f, "# echo \"event-BUILD: standard PROOF node\"\n");
3366  fprintf(f, "# fi\n");
3367  fprintf(f, "\n");
3368  fprintf(f, "if [ \"\" = \"clean\" ]; then\n");
3369  fprintf(f, " make distclean\n");
3370  fprintf(f, " exit 0\n");
3371  fprintf(f, "fi\n");
3372  fprintf(f, "\n");
3373  fprintf(f, "make\n");
3374  fprintf(f, "rc=$?\n");
3375  fprintf(f, "echo \"rc=$?\"\n");
3376  fprintf(f, "if [ $? != \"0\" ] ; then\n");
3377  fprintf(f, " exit 1\n");
3378  fprintf(f, "fi\n");
3379  fprintf(f, "exit 0\n");
3380 
3381  // Close the file
3382  fclose(f);
3383 
3384  // Then SETUP.C
3385  path.Form("%s/SETUP.C", proofinf);
3386 #ifdef R__WINGCC
3387  f = fopen(path.Data(), "wb");
3388 #else
3389  f = fopen(path.Data(), "w");
3390 #endif
3391  if (!f) {
3392  Error("MakeProjectParProofInf", "cannot create file '%s' (errno: %d)",
3393  path.Data(), TSystem::GetErrno());
3394  return -1;
3395  }
3396 
3397  fprintf(f, "Int_t SETUP()\n");
3398  fprintf(f, "{\n");
3399  fprintf(f, "\n");
3400  fprintf(f, "//\n");
3401  fprintf(f, "// The environment variables ROOTPROOFLITE and ROOTPROOFCLIENT can be used to\n");
3402  fprintf(f, "// adapt the macro to the calling environment\n");
3403  fprintf(f, "//\n");
3404  fprintf(f, "// if (gSystem->Getenv(\"ROOTPROOFLITE\")) {\n");
3405  fprintf(f, "// Printf(\"event-SETUP: PROOF-Lite node (session has %%s workers)\",\n");
3406  fprintf(f, "// gSystem->Getenv(\"ROOTPROOFLITE\"));\n");
3407  fprintf(f, "// } else if (gSystem->Getenv(\"ROOTPROOFCLIENT\")) {\n");
3408  fprintf(f, "// Printf(\"event-SETUP: PROOF client\");\n");
3409  fprintf(f, "// } else {\n");
3410  fprintf(f, "// Printf(\"event-SETUP: standard PROOF node\");\n");
3411  fprintf(f, "// }\n");
3412  fprintf(f, "\n");
3413  fprintf(f, " if (gSystem->Load(\"lib%s\") == -1)\n", pack);
3414  fprintf(f, " return -1;\n");
3415  fprintf(f, " return 0;\n");
3416  fprintf(f, "}\n");
3417  fprintf(f, "\n");
3418 
3419  // Close the file
3420  fclose(f);
3421 
3422  // Done
3423  return 0;
3424 }
3425 
3426 ////////////////////////////////////////////////////////////////////////////////
3427 /// Read the list of StreamerInfo from this file.
3428 ///
3429 /// The key with name holding the list of TStreamerInfo objects is read.
3430 /// The corresponding TClass objects are updated.
3431 /// Note that this function is not called if the static member fgReadInfo is false.
3432 /// (see TFile::SetReadStreamerInfo)
3433 
3436  TList *list = GetStreamerInfoList();
3437  if (!list) {
3438  MakeZombie();
3439  return;
3440  }
3441 
3442  list->SetOwner(kFALSE);
3443 
3444  if (gDebug > 0) Info("ReadStreamerInfo", "called for file %s",GetName());
3445 
3446  TStreamerInfo *info;
3447 
3448  Int_t version = fVersion;
3449  if (version > 1000000) version -= 1000000;
3450  if (version < 53419 || (59900 < version && version < 59907)) {
3451  // We need to update the fCheckSum field of the TStreamerBase.
3452 
3453  // loop on all TStreamerInfo classes
3454  TObjLink *lnk = list->FirstLink();
3455  while (lnk) {
3456  info = (TStreamerInfo*)lnk->GetObject();
3457  if (info == 0 || info->IsA() != TStreamerInfo::Class()) {
3458  lnk = lnk->Next();
3459  continue;
3460  }
3461  TIter next(info->GetElements());
3462  TStreamerElement *element;
3463  while ((element = (TStreamerElement*) next())) {
3464  TStreamerBase *base = dynamic_cast<TStreamerBase*>(element);
3465  if (!base) continue;
3466  if (base->GetBaseCheckSum() != 0) continue;
3467  TStreamerInfo *baseinfo = (TStreamerInfo*)list->FindObject(base->GetName());
3468  if (baseinfo) {
3469  base->SetBaseCheckSum(baseinfo->GetCheckSum());
3470  }
3471  }
3472  lnk = lnk->Next();
3473  }
3474  }
3475 
3476  // loop on all TStreamerInfo classes
3477  for (int mode=0;mode<2; ++mode) {
3478  // In order for the collection proxy to be initialized properly, we need
3479  // to setup the TStreamerInfo for non-stl class before the stl classes.
3480  TObjLink *lnk = list->FirstLink();
3481  while (lnk) {
3482  info = (TStreamerInfo*)lnk->GetObject();
3483  if (info == 0) {
3484  lnk = lnk->Next();
3485  continue;
3486  }
3487  if (info->IsA() != TStreamerInfo::Class()) {
3488  if (mode==1) {
3489  TObject *obj = (TObject*)info;
3490  if (strcmp(obj->GetName(),"listOfRules")==0) {
3491 #if 0
3492  // Completely ignore the rules for now.
3493  TList *listOfRules = (TList*)obj;
3494  TObjLink *rulelnk = listOfRules->FirstLink();
3495  while (rulelnk) {
3496  TObjString *rule = (TObjString*)rulelnk->GetObject();
3497  TClass::AddRule( rule->String().Data() );
3498  rulelnk = rulelnk->Next();
3499  }
3500 #endif
3501  } else {
3502  Warning("ReadStreamerInfo","%s has a %s in the list of TStreamerInfo.", GetName(), info->IsA()->GetName());
3503  }
3504  info->SetBit(kCanDelete);
3505  }
3506  lnk = lnk->Next();
3507  continue;
3508  }
3509  // This is a quick way (instead of parsing the name) to see if this is
3510  // the description of an STL container.
3511  if (info->GetElements()==0) {
3512  Warning("ReadStreamerInfo","The StreamerInfo for %s does not have a list of elements.",info->GetName());
3513  lnk = lnk->Next();
3514  continue;
3515  }
3516  TObject *element = info->GetElements()->UncheckedAt(0);
3517  Bool_t isstl = element && strcmp("This",element->GetName())==0;
3518 
3519  if ( (!isstl && mode ==0) || (isstl && mode ==1) ) {
3520  // Skip the STL container the first time around
3521  // Skip the regular classes the second time around;
3522  info->BuildCheck(this);
3523  Int_t uid = info->GetNumber();
3524  Int_t asize = fClassIndex->GetSize();
3525  if (uid >= asize && uid <100000) fClassIndex->Set(2*asize);
3526  if (uid >= 0 && uid < fClassIndex->GetSize()) fClassIndex->fArray[uid] = 1;
3527  else {
3528  printf("ReadStreamerInfo, class:%s, illegal uid=%d\n",info->GetName(),uid);
3529  }
3530  if (gDebug > 0) printf(" -class: %s version: %d info read at slot %d\n",info->GetName(), info->GetClassVersion(),uid);
3531  }
3532  lnk = lnk->Next();
3533  }
3534  }
3535  fClassIndex->fArray[0] = 0;
3536  list->Clear(); //this will delete all TStreamerInfo objects with kCanDelete bit set
3537  delete list;
3538 }
3539 
3540 ////////////////////////////////////////////////////////////////////////////////
3541 /// Specify if the streamerinfos must be read at file opening.
3542 ///
3543 /// If fgReadInfo is true (default) TFile::ReadStreamerInfo is called
3544 /// when opening the file.
3545 /// It may be interesting to set fgReadInfo to false to speedup the file
3546 /// opening time or in case libraries containing classes referenced
3547 /// by the file have not yet been loaded.
3548 /// if fgReadInfo is false, one can still read the StreamerInfo with
3549 /// myfile.ReadStreamerInfo();
3550 
3551 void TFile::SetReadStreamerInfo(Bool_t readinfo)
3553  fgReadInfo = readinfo;
3554 }
3555 
3556 ////////////////////////////////////////////////////////////////////////////////
3557 /// If the streamerinfos are to be read at file opening.
3558 ///
3559 /// See TFile::SetReadStreamerInfo for more documentation.
3560 
3563  return fgReadInfo;
3564 }
3565 
3566 ////////////////////////////////////////////////////////////////////////////////
3567 /// Show the StreamerInfo of all classes written to this file.
3568 
3571  TList *list = GetStreamerInfoList();
3572  if (!list) return;
3573 
3574  list->ls();
3575  delete list;
3576 }
3577 
3578 ////////////////////////////////////////////////////////////////////////////////
3579 /// Check if the ProcessID pidd is already in the file,
3580 /// if not, add it and return the index number in the local file list.
3581 
3584  TProcessID *pid = pidd;
3585  if (!pid) pid = TProcessID::GetPID();
3586  TObjArray *pids = GetListOfProcessIDs();
3587  Int_t npids = GetNProcessIDs();
3588  for (Int_t i=0;i<npids;i++) {
3589  if (pids->At(i) == pid) return (UShort_t)i;
3590  }
3591 
3592  this->SetBit(TFile::kHasReferences);
3593  pids->AddAtAndExpand(pid,npids);
3594  pid->IncrementCount();
3595  char name[32];
3596  snprintf(name,32,"ProcessID%d",npids);
3597  this->WriteTObject(pid,name);
3598  this->IncrementProcessIDs();
3599  if (gDebug > 0) {
3600  Info("WriteProcessID", "name=%s, file=%s", name, GetName());
3601  }
3602  return (UShort_t)npids;
3603 }
3604 
3605 
3606 ////////////////////////////////////////////////////////////////////////////////
3607 /// Write the list of TStreamerInfo as a single object in this file
3608 /// The class Streamer description for all classes written to this file
3609 /// is saved. See class TStreamerInfo.
3610 
3613  //if (!gFile) return;
3614  if (!fWritable) return;
3615  if (!fClassIndex) return;
3616  if (fIsPcmFile) return; // No schema evolution for ROOT PCM files.
3617  if (fClassIndex->fArray[0] == 0
3618  && fSeekInfo != 0) {
3619  // No need to update the index if no new classes added to the file
3620  // but write once an empty StreamerInfo list to mark that there is no need
3621  // for StreamerInfos in this file.
3622  return;
3623  }
3624  if (gDebug > 0) Info("WriteStreamerInfo", "called for file %s",GetName());
3625 
3626  SafeDelete(fInfoCache);
3627 
3628  // build a temporary list with the marked files
3629  TIter next(gROOT->GetListOfStreamerInfo());
3630  TStreamerInfo *info;
3631  TList list;
3632  TList listOfRules;
3633  listOfRules.SetOwner(kTRUE);
3634  listOfRules.SetName("listOfRules");
3635  std::set<TClass*> classSet;
3636 
3637 
3638  while ((info = (TStreamerInfo*)next())) {
3639  Int_t uid = info->GetNumber();
3640  if (fClassIndex->fArray[uid]) {
3641  list.Add(info);
3642  if (gDebug > 0) printf(" -class: %s info number %d saved\n",info->GetName(),uid);
3643 
3644  // Add the IO customization rules to the list to be saved for the underlying
3645  // class but make sure to add them only once.
3646  TClass *clinfo = info->GetClass();
3647  if (clinfo && clinfo->GetSchemaRules()) {
3648  if ( classSet.find( clinfo ) == classSet.end() ) {
3649  if (gDebug > 0) printf(" -class: %s stored the I/O customization rules\n",info->GetName());
3650 
3651  TObjArrayIter it( clinfo->GetSchemaRules()->GetRules() );
3652  ROOT::TSchemaRule *rule;
3653  while( (rule = (ROOT::TSchemaRule*)it.Next()) ) {
3654  TObjString *obj = new TObjString();
3655  rule->AsString(obj->String());
3656  listOfRules.Add(obj);
3657  }
3658  classSet.insert(clinfo);
3659  }
3660  }
3661  }
3662  }
3663 
3664  // Write the StreamerInfo list even if it is empty.
3665  fClassIndex->fArray[0] = 2; //to prevent adding classes in TStreamerInfo::TagFile
3666 
3667  if (listOfRules.GetEntries()) {
3668  // Only add the list of rules if we have something to say.
3669  list.Add(&listOfRules);
3670  }
3671 
3672  // always write with compression on
3673  Int_t compress = fCompress;
3674  fCompress = 1;
3675 
3676  //free previous StreamerInfo record
3677  if (fSeekInfo) MakeFree(fSeekInfo,fSeekInfo+fNbytesInfo-1);
3678  //Create new key
3679  TKey key(&list,"StreamerInfo",GetBestBuffer(), this);
3680  fKeys->Remove(&key);
3681  fSeekInfo = key.GetSeekKey();
3682  fNbytesInfo = key.GetNbytes();
3683  SumBuffer(key.GetObjlen());
3684  key.WriteFile(0);
3685 
3686  fClassIndex->fArray[0] = 0;
3687  fCompress = compress;
3688 
3689  list.RemoveLast(); // remove the listOfRules.
3690 }
3691 
3692 ////////////////////////////////////////////////////////////////////////////////
3693 /// Open a file for reading through the file cache.
3694 ///
3695 /// The file will be downloaded to the cache and opened from there.
3696 /// If the download fails, it will be opened remotely.
3697 /// The file will be downloaded to the directory specified by SetCacheFileDir().
3698 
3699 TFile *TFile::OpenFromCache(const char *name, Option_t *, const char *ftitle,
3700  Int_t compress, Int_t netopt)
3701 {
3702  TFile *f = 0;
3703 
3704  if (fgCacheFileDir == "") {
3705  ::Warning("TFile::OpenFromCache",
3706  "you want to read through a cache, but you have no valid cache "
3707  "directory set - reading remotely");
3708  ::Info("TFile::OpenFromCache", "set cache directory using TFile::SetCacheFileDir()");
3709  } else {
3710  TUrl fileurl(name);
3711  TUrl tagurl;
3712 
3713  if ((!strcmp(fileurl.GetProtocol(), "file"))) {
3714  // it makes no sense to read local files through a file cache
3715  if (!fgCacheFileForce)
3716  ::Warning("TFile::OpenFromCache",
3717  "you want to read through a cache, but you are reading "
3718  "local files - CACHEREAD disabled");
3719  } else {
3720  // this is a remote file and worthwhile to be put into the local cache
3721  // now create cachepath to put it
3722  TString cachefilepath;
3723  TString cachefilepathbasedir;
3724  cachefilepath = fgCacheFileDir;
3725  cachefilepath += fileurl.GetFile();
3726  cachefilepathbasedir = gSystem->DirName(cachefilepath);
3727  if ((gSystem->mkdir(cachefilepathbasedir, kTRUE) < 0) &&
3728  (gSystem->AccessPathName(cachefilepathbasedir, kFileExists))) {
3729  ::Warning("TFile::OpenFromCache","you want to read through a cache, but I "
3730  "cannot create the directory %s - CACHEREAD disabled",
3731  cachefilepathbasedir.Data());
3732  } else {
3733  // check if this should be a zip file
3734  if (strlen(fileurl.GetAnchor())) {
3735  // remove the anchor and change the target name
3736  cachefilepath += "__";
3737  cachefilepath += fileurl.GetAnchor();
3738  fileurl.SetAnchor("");
3739  }
3740  if (strstr(name,"zip=")) {
3741  // filter out this option and change the target cache name
3742  TString urloptions = fileurl.GetOptions();
3743  TString newoptions;
3744  TObjArray *objOptions = urloptions.Tokenize("&");
3745  Int_t optioncount = 0;
3746  TString zipname;
3747  for (Int_t n = 0; n < objOptions->GetEntries(); n++) {
3748  TString loption = ((TObjString*)objOptions->At(n))->GetName();
3749  TObjArray *objTags = loption.Tokenize("=");
3750  if (objTags->GetEntries() == 2) {
3751  TString key = ((TObjString*)objTags->At(0))->GetName();
3752  TString value = ((TObjString*)objTags->At(1))->GetName();
3753  if (key.CompareTo("zip", TString::kIgnoreCase)) {
3754  if (optioncount!=0) {
3755  newoptions += "&";
3756  }
3757  newoptions += key;
3758  newoptions += "=";
3759  newoptions += value;
3760  ++optioncount;
3761  } else {
3762  zipname = value;
3763  }
3764  }
3765  delete objTags;
3766  }
3767  delete objOptions;
3768  fileurl.SetOptions(newoptions.Data());
3769  cachefilepath += "__";
3770  cachefilepath += zipname;
3771  fileurl.SetAnchor("");
3772  }
3773 
3774  Bool_t need2copy = kFALSE;
3775 
3776  // check if file is in the cache
3777  Long_t id;
3778  Long64_t size;
3779  Long_t flags;
3780  Long_t modtime;
3781  if (!gSystem->GetPathInfo(cachefilepath, &id, &size, &flags, &modtime)) {
3782  // file is in the cache
3783  if (!fgCacheFileDisconnected) {
3784  char cacheblock[256];
3785  char remotblock[256];
3786  // check the remote file for it's size and compare some magic bytes
3787  TString cfurl;
3788  cfurl = cachefilepath;
3789  cfurl += "?filetype=raw";
3790  TUrl rurl(name);
3791  TString ropt = rurl.GetOptions();
3792  ropt += "&filetype=raw";
3793  rurl.SetOptions(ropt);
3794 
3795  Bool_t forcedcache = fgCacheFileForce;
3796  fgCacheFileForce = kFALSE;
3797 
3798  TFile *cachefile = TFile::Open(cfurl, "READ");
3799  TFile *remotfile = TFile::Open(rurl.GetUrl(), "READ");
3800 
3801  fgCacheFileForce = forcedcache;
3802 
3803  if (!cachefile) {
3804  need2copy = kTRUE;
3805  ::Error("TFile::OpenFromCache",
3806  "cannot open the cache file to check cache consistency");
3807  return 0;
3808  }
3809 
3810  if (!remotfile) {
3811  ::Error("TFile::OpenFromCache",
3812  "cannot open the remote file to check cache consistency");
3813  return 0;
3814  }
3815 
3816  cachefile->Seek(0);
3817  remotfile->Seek(0);
3818 
3819  if ((!cachefile->ReadBuffer(cacheblock,256)) &&
3820  (!remotfile->ReadBuffer(remotblock,256))) {
3821  if (memcmp(cacheblock, remotblock, 256)) {
3822  ::Warning("TFile::OpenFromCache", "the header of the cache file "
3823  "differs from the remote file - forcing an update");
3824  need2copy = kTRUE;
3825  }
3826  } else {
3827  ::Warning("TFile::OpenFromCache", "the header of the cache and/or "
3828  "remote file are not readable - forcing an update");
3829  need2copy = kTRUE;
3830  }
3831 
3832  delete remotfile;
3833  delete cachefile;
3834  }
3835  } else {
3836  need2copy = kTRUE;
3837  }
3838 
3839  // try to fetch the file (disable now the forced caching)
3840  Bool_t forcedcache = fgCacheFileForce;
3841  fgCacheFileForce = kFALSE;
3842  if (need2copy && !TFile::Cp(name, cachefilepath)) {
3843  ::Warning("TFile::OpenFromCache", "you want to read through a cache, but I "
3844  "cannot make a cache copy of %s - CACHEREAD disabled",
3845  cachefilepathbasedir.Data());
3846  fgCacheFileForce = forcedcache;
3847  if (fgOpenTimeout != 0)
3848  return 0;
3849  } else {
3850  fgCacheFileForce = forcedcache;
3851  ::Info("TFile::OpenFromCache", "using local cache copy of %s [%s]",
3852  name, cachefilepath.Data());
3853  // finally we have the file and can open it locally
3854  fileurl.SetProtocol("file");
3855  fileurl.SetFile(cachefilepath);
3856 
3857  tagurl = fileurl;
3858  TString tagfile;
3859  tagfile = cachefilepath;
3860  tagfile += ".ROOT.cachefile";
3861  tagurl.SetFile(tagfile);
3862  // we symlink this file as a ROOT cached file
3863  gSystem->Symlink(gSystem->BaseName(cachefilepath), tagfile);
3864  return TFile::Open(fileurl.GetUrl(), "READ", ftitle, compress, netopt);
3865  }
3866  }
3867  }
3868  }
3869 
3870  // Failed
3871  return f;
3872 }
3873 
3874 ////////////////////////////////////////////////////////////////////////////////
3875 /// Create / open a file
3876 ///
3877 /// The type of the file can be either a
3878 /// TFile, TNetFile, TWebFile or any TFile derived class for which an
3879 /// plugin library handler has been registered with the plugin manager
3880 /// (for the plugin manager see the TPluginManager class). The returned
3881 /// type of TFile depends on the file name specified by 'url'.
3882 /// If 'url' is a '|'-separated list of file URLs, the 'URLs' are tried
3883 /// sequentially in the specified order until a successful open.
3884 /// If the file starts with "root:", "roots:" or "rootk:" a TNetFile object
3885 /// will be returned, with "http:" a TWebFile, with "file:" a local TFile,
3886 /// etc. (see the list of TFile plugin handlers in $ROOTSYS/etc/system.rootrc
3887 /// for regular expressions that will be checked) and as last a local file will
3888 /// be tried.
3889 /// Before opening a file via TNetFile a check is made to see if the URL
3890 /// specifies a local file. If that is the case the file will be opened
3891 /// via a normal TFile. To force the opening of a local file via a
3892 /// TNetFile use either TNetFile directly or specify as host "localhost".
3893 /// The netopt argument is only used by TNetFile. For the meaning of the
3894 /// options and other arguments see the constructors of the individual
3895 /// file classes. In case of error returns 0.
3896 ///
3897 /// For TFile implementations supporting asynchronous file open, see
3898 /// TFile::AsyncOpen(...), it is possible to request a timeout with the
3899 /// option <b>TIMEOUT=<secs></b>: the timeout must be specified in seconds and
3900 /// it will be internally checked with granularity of one millisec.
3901 /// For remote files there is the option: <b>CACHEREAD</b> opens an existing
3902 /// file for reading through the file cache. The file will be downloaded to
3903 /// the cache and opened from there. If the download fails, it will be opened remotely.
3904 /// The file will be downloaded to the directory specified by SetCacheFileDir().
3905 
3906 TFile *TFile::Open(const char *url, Option_t *options, const char *ftitle,
3907  Int_t compress, Int_t netopt)
3908 {
3909  TPluginHandler *h;
3910  TFile *f = 0;
3911  EFileType type = kFile;
3912 
3913  // Check input
3914  if (!url || strlen(url) <= 0) {
3915  ::Error("TFile::Open", "no url specified");
3916  return f;
3917  }
3918 
3919  TString expandedUrl(url);
3920  gSystem->ExpandPathName(expandedUrl);
3921 
3922  // If a timeout has been specified extract the value and try to apply it (it requires
3923  // support for asynchronous open, though; the following is completely transparent if
3924  // such support if not available for the required protocol)
3925  TString opts(options);
3926  Int_t ito = opts.Index("TIMEOUT=");
3927  if (ito != kNPOS) {
3928  TString sto = opts(ito + strlen("TIMEOUT="), opts.Length());
3929  while (!(sto.IsDigit()) && !(sto.IsNull())) { sto.Remove(sto.Length()-1,1); }
3930  if (!(sto.IsNull())) {
3931  // Timeout in millisecs
3932  Int_t toms = sto.Atoi() * 1000;
3933  if (gDebug > 0) ::Info("TFile::Open", "timeout of %d millisec requested", toms);
3934  // Remove from the options field
3935  sto.Insert(0, "TIMEOUT=");
3936  opts.ReplaceAll(sto, "");
3937  // Asynchrounous open
3938  TFileOpenHandle *fh = TFile::AsyncOpen(expandedUrl, opts, ftitle, compress, netopt);
3939  // Check the result in steps of 1 millisec
3941  aos = TFile::GetAsyncOpenStatus(fh);
3942  Int_t xtms = toms;
3943  while (aos != TFile::kAOSNotAsync && aos == TFile::kAOSInProgress && xtms > 0) {
3944  gSystem->Sleep(1);
3945  xtms -= 1;
3946  aos = TFile::GetAsyncOpenStatus(fh);
3947  }
3948  if (aos == TFile::kAOSNotAsync || aos == TFile::kAOSSuccess) {
3949  // Do open the file now
3950  f = TFile::Open(fh);
3951  if (gDebug > 0) {
3952  if (aos == TFile::kAOSSuccess)
3953  ::Info("TFile::Open", "waited %d millisec for asynchronous open", toms - xtms);
3954  else
3955  ::Info("TFile::Open", "timeout option not supported (requires asynchronous"
3956  " open support)");
3957  }
3958  } else {
3959  if (xtms <= 0)
3960  ::Error("TFile::Open", "timeout expired while opening '%s'", expandedUrl.Data());
3961  // Cleanup the request
3962  SafeDelete(fh);
3963  }
3964  // Done
3965  return f;
3966  } else {
3967  ::Warning("TFile::Open", "incomplete 'TIMEOUT=' option specification - ignored");
3968  opts.ReplaceAll("TIMEOUT=", "");
3969  }
3970  }
3971 
3972  // We will use this from now on
3973  const char *option = opts;
3974 
3975  // Many URLs? Redirect output and print errors in case of global failure
3976  TString namelist(expandedUrl);
3977  Ssiz_t ip = namelist.Index("|");
3978  Bool_t rediroutput = (ip != kNPOS &&
3979  ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
3980  RedirectHandle_t rh;
3981  if (rediroutput) {
3982  TString outf = ".TFileOpen_";
3983  FILE *fout = gSystem->TempFileName(outf);
3984  if (fout) {
3985  fclose(fout);
3986  gSystem->RedirectOutput(outf, "w", &rh);
3987  }
3988  }
3989 
3990  // Try sequentially all names in 'names'
3991  TString name, n;
3992  Ssiz_t from = 0;
3993  while (namelist.Tokenize(n, from, "|") && !f) {
3994 
3995  // check if we read through a file cache
3996  if (!strcasecmp(option, "CACHEREAD") ||
3997  ((!strcasecmp(option,"READ") || !option[0]) && fgCacheFileForce)) {
3998  // Try opening the file from the cache
3999  if ((f = TFile::OpenFromCache(n, option, ftitle, compress, netopt)))
4000  return f;
4001  }
4002 
4003  IncrementFileCounter();
4004 
4005  // change names from e.g. /castor/cern.ch/alice/file.root to
4006  // castor:/castor/cern.ch/alice/file.root as recognized by the plugin manager
4007  TUrl urlname(n, kTRUE);
4008  name = urlname.GetUrl();
4009  // Check first if a pending async open request matches this one
4010  if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4011  TIter nxr(fgAsyncOpenRequests);
4012  TFileOpenHandle *fh = 0;
4013  while ((fh = (TFileOpenHandle *)nxr()))
4014  if (fh->Matches(name))
4015  return TFile::Open(fh);
4016  }
4017 
4018  TString urlOptions(urlname.GetOptions());
4019  if (urlOptions.BeginsWith("pmerge") || urlOptions.Contains("&pmerge") || urlOptions.Contains(" pmerge")) {
4020  type = kMerge;
4021 
4022  // Pass the full name including the url options:
4023  f = (TFile*) gROOT->ProcessLineFast(TString::Format("new TParallelMergingFile(\"%s\",\"%s\",\"%s\",%d)",n.Data(),option,ftitle,compress));
4024 
4025  } else {
4026  // Resolve the file type; this also adjusts names
4027  TString lfname = gEnv->GetValue("Path.Localroot", "");
4028  type = GetType(name, option, &lfname);
4029 
4030  if (type == kLocal) {
4031 
4032  // Local files
4033  if (lfname.IsNull()) {
4034  urlname.SetHost("");
4035  urlname.SetProtocol("file");
4036  lfname = urlname.GetUrl();
4037  }
4038  f = new TFile(lfname.Data(), option, ftitle, compress);
4039 
4040  } else if (type == kNet) {
4041 
4042  // Network files
4043  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
4044  if (h->LoadPlugin() == -1)
4045  return 0;
4046  f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
4047  }
4048 
4049  } else if (type == kWeb) {
4050 
4051  // Web files
4052  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
4053  if (h->LoadPlugin() == -1)
4054  return 0;
4055  f = (TFile*) h->ExecPlugin(2, name.Data(), option);
4056  }
4057 
4058  } else if (type == kFile) {
4059 
4060  // 'file:' protocol
4061  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4062  h->LoadPlugin() == 0) {
4063  name.ReplaceAll("file:", "");
4064  f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
4065  } else
4066  f = new TFile(name.Data(), option, ftitle, compress);
4067 
4068  } else {
4069 
4070  // no recognized specification: try the plugin manager
4071  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name.Data()))) {
4072  if (h->LoadPlugin() == -1)
4073  return 0;
4074  TClass *cl = TClass::GetClass(h->GetClass());
4075  if (cl && cl->InheritsFrom("TNetFile"))
4076  f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
4077  else
4078  f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
4079  } else {
4080  // Just try to open it locally but via TFile::Open, so that we pick-up the correct
4081  // plug-in in the case file name contains information about a special backend (e.g.
4082  // "srm://srm.cern.ch//castor/cern.ch/grid/..." should be considered a castor file
4083  // /castor/cern.ch/grid/...").
4084  f = TFile::Open(urlname.GetFileAndOptions(), option, ftitle, compress);
4085  }
4086  }
4087  }
4088 
4089  if (f && f->IsZombie()) {
4090  TString newUrl = f->GetNewUrl();
4091  delete f;
4092  if( newUrl.Length() && gEnv->GetValue("TFile.CrossProtocolRedirects", 1) )
4093  f = TFile::Open( newUrl, option, ftitle, compress );
4094  else
4095  f = 0;
4096  }
4097  }
4098 
4099  if (rediroutput) {
4100  // Restore output to stdout
4101  gSystem->RedirectOutput(0, "", &rh);
4102  // If we failed print error messages
4103  if (!f)
4104  gSystem->ShowOutput(&rh);
4105  // Remove the file
4106  gSystem->Unlink(rh.fFile);
4107  }
4108 
4109  // if the file is writable, non local, and not opened in raw mode
4110  // we create a default write cache of 512 KBytes
4111  if (type != kLocal && type != kFile &&
4112  f && f->IsWritable() && !f->IsRaw()) {
4113  new TFileCacheWrite(f, 1);
4114  }
4115 
4116  return f;
4117 }
4118 
4119 ////////////////////////////////////////////////////////////////////////////////
4120 /// Submit an asynchronous open request.
4121 
4122 /// See TFile::Open(const char *, ...) for an
4123 /// explanation of the arguments. A handler is returned which is to be passed
4124 /// to TFile::Open(TFileOpenHandle *) to get the real TFile instance once
4125 /// the file is open.
4126 /// This call never blocks and it is provided to allow parallel submission
4127 /// of file opening operations expected to take a long time.
4128 /// TFile::Open(TFileOpenHandle *) may block if the file is not yet ready.
4129 /// The sequence
4130 ///
4131 /// TFile::Open(TFile::AsyncOpen(const char *, ...))
4132 ///
4133 /// is equivalent to
4134 ///
4135 /// TFile::Open(const char *, ...)
4136 ///
4137 /// To be effective, the underlying TFile implementation must be able to
4138 /// support asynchronous open functionality. Currently, only TXNetFile
4139 /// supports it. If the functionality is not implemented, this call acts
4140 /// transparently by returning an handle with the arguments for the
4141 /// standard synchronous open run by TFile::Open(TFileOpenHandle *).
4142 /// The retuned handle will be adopted by TFile after opening completion
4143 /// in TFile::Open(TFileOpenHandle *); if opening is not finalized the
4144 /// handle must be deleted by the caller.
4145 
4146 TFileOpenHandle *TFile::AsyncOpen(const char *url, Option_t *option,
4147  const char *ftitle, Int_t compress,
4148  Int_t netopt)
4149 {
4150  TFileOpenHandle *fh = 0;
4151  TPluginHandler *h;
4152  TFile *f = 0;
4153  Bool_t notfound = kTRUE;
4154 
4155  // Check input
4156  if (!url || strlen(url) <= 0) {
4157  ::Error("TFile::AsyncOpen", "no url specified");
4158  return fh;
4159  }
4160 
4161  // Many URLs? Redirect output and print errors in case of global failure
4162  TString namelist(url);
4163  gSystem->ExpandPathName(namelist);
4164  Ssiz_t ip = namelist.Index("|");
4165  Bool_t rediroutput = (ip != kNPOS &&
4166  ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
4167  RedirectHandle_t rh;
4168  if (rediroutput) {
4169  TString outf = ".TFileAsyncOpen_";
4170  FILE *fout = gSystem->TempFileName(outf);
4171  if (fout) {
4172  fclose(fout);
4173  gSystem->RedirectOutput(outf, "w", &rh);
4174  }
4175  }
4176 
4177  // Try sequentially all names in 'names'
4178  TString name, n;
4179  Ssiz_t from = 0;
4180  while (namelist.Tokenize(n, from, "|") && !f) {
4181 
4182  // change names from e.g. /castor/cern.ch/alice/file.root to
4183  // castor:/castor/cern.ch/alice/file.root as recognized by the plugin manager
4184  TUrl urlname(n, kTRUE);
4185  name = urlname.GetUrl();
4186 
4187  // Resolve the file type; this also adjusts names
4188  EFileType type = GetType(name, option);
4189 
4190  // Here we send the asynchronous request if the functionality is implemented
4191  if (type == kNet) {
4192  // Network files
4193  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4194  (!strcmp(h->GetClass(),"TXNetFile") || !strcmp(h->GetClass(),"TNetXNGFile"))
4195  && h->LoadPlugin() == 0) {
4196  f = (TFile*) h->ExecPlugin(6, name.Data(), option, ftitle, compress, netopt, kTRUE);
4197  notfound = kFALSE;
4198  }
4199  }
4200  if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4201  !strcmp(h->GetClass(),"TAlienFile") && h->LoadPlugin() == 0) {
4202  f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, kTRUE);
4203  notfound = kFALSE;
4204  }
4205 
4206  }
4207 
4208  if (rediroutput) {
4209  // Restore output to stdout
4210  gSystem->RedirectOutput(0, "", &rh);
4211  // If we failed print error messages
4212  if (!notfound && !f)
4213  gSystem->ShowOutput(&rh);
4214  // Remove the file
4215  gSystem->Unlink(rh.fFile);
4216  }
4217 
4218  // Make sure that no error occurred
4219  if (notfound) {
4220  SafeDelete(f);
4221  // Save the arguments in the handler, so that a standard open can be
4222  // attempted later on
4223  fh = new TFileOpenHandle(name, option, ftitle, compress, netopt);
4224  } else if (f) {
4225  // Fill the opaque handler to be use to attach the file later on
4226  fh = new TFileOpenHandle(f);
4227  }
4228 
4229  // Record this request
4230  if (fh) {
4231  // Create the lst, if not done already
4232  if (!fgAsyncOpenRequests)
4233  fgAsyncOpenRequests = new TList;
4234  fgAsyncOpenRequests->Add(fh);
4235  }
4236 
4237  // We are done
4238  return fh;
4239 }
4240 
4241 ////////////////////////////////////////////////////////////////////////////////
4242 /// Waits for the completion of an asynchronous open request.
4243 ///
4244 /// Returns the pointer to the associated TFile, transferring ownership of the
4245 /// handle to the TFile instance.
4246 
4249  TFile *f = 0;
4250 
4251  // Note that the request may have failed
4252  if (fh && fgAsyncOpenRequests) {
4253  // Remove it from the pending list: we need to do it at this level to avoid
4254  // recursive calls in the standard TFile::Open
4255  fgAsyncOpenRequests->Remove(fh);
4256  // Was asynchronous open functionality implemented?
4257  if ((f = fh->GetFile()) && !(f->IsZombie())) {
4258  // Yes: wait for the completion of the open phase, if needed
4259  Bool_t cr = (!strcmp(f->GetOption(),"CREATE") ||
4260  !strcmp(f->GetOption(),"RECREATE") ||
4261  !strcmp(f->GetOption(),"NEW")) ? kTRUE : kFALSE;
4262  f->Init(cr);
4263  } else {
4264  // No: process a standard open
4265  f = TFile::Open(fh->GetName(), fh->GetOpt(), fh->GetTitle(),
4266  fh->GetCompress(), fh->GetNetOpt());
4267  }
4268 
4269  // Adopt the handle instance in the TFile instance so that it gets
4270  // automatically cleaned up
4271  if (f) f->fAsyncHandle = fh;
4272  }
4273 
4274  // We are done
4275  return f;
4276 }
4277 
4278 ////////////////////////////////////////////////////////////////////////////////
4279 /// Interface to system open. All arguments like in POSIX open().
4280 
4281 Int_t TFile::SysOpen(const char *pathname, Int_t flags, UInt_t mode)
4283 #if defined(R__WINGCC)
4284  // ALWAYS use binary mode - even cygwin text should be in unix format
4285  // although this is posix default it has to be set explicitly
4286  return ::open(pathname, flags | O_BINARY, mode);
4287 #elif defined(R__SEEK64)
4288  return ::open64(pathname, flags, mode);
4289 #else
4290  return ::open(pathname, flags, mode);
4291 #endif
4292 }
4293 
4294 ////////////////////////////////////////////////////////////////////////////////
4295 /// Interface to system close. All arguments like in POSIX close().
4296 
4299  if (fd < 0) return 0;
4300  return ::close(fd);
4301 }
4302 
4303 ////////////////////////////////////////////////////////////////////////////////
4304 /// Interface to system read. All arguments like in POSIX read().
4305 
4306 Int_t TFile::SysRead(Int_t fd, void *buf, Int_t len)
4308  return ::read(fd, buf, len);
4309 }
4310 
4311 ////////////////////////////////////////////////////////////////////////////////
4312 /// Interface to system write. All arguments like in POSIX write().
4313 
4314 Int_t TFile::SysWrite(Int_t fd, const void *buf, Int_t len)
4316  return ::write(fd, buf, len);
4317 }
4318 ////////////////////////////////////////////////////////////////////////////////
4319 /// Interface to system lseek.
4320 ///
4321 /// All arguments like in POSIX lseek()
4322 /// except that the offset and return value are of a type which are
4323 /// able to handle 64 bit file systems.
4324 
4325 Long64_t TFile::SysSeek(Int_t fd, Long64_t offset, Int_t whence)
4327 #if defined (R__SEEK64)
4328  return ::lseek64(fd, offset, whence);
4329 #elif defined(WIN32)
4330  return ::_lseeki64(fd, offset, whence);
4331 #else
4332  return ::lseek(fd, offset, whence);
4333 #endif
4334 }
4335 
4336 ////////////////////////////////////////////////////////////////////////////////
4337 /// Return file stat information.
4338 ///
4339 /// The interface and return value is
4340 /// identical to TSystem::GetPathInfo(). The function returns 0 in
4341 /// case of success and 1 if the file could not be stat'ed.
4342 
4343 Int_t TFile::SysStat(Int_t, Long_t *id, Long64_t *size, Long_t *flags,
4344  Long_t *modtime)
4345 {
4346  return gSystem->GetPathInfo(fRealName, id, size, flags, modtime);
4347 }
4348 
4349 ////////////////////////////////////////////////////////////////////////////////
4350 /// Interface to system fsync. All arguments like in POSIX fsync().
4351 
4354  if (TestBit(kDevNull)) return 0;
4355 
4356 #ifndef WIN32
4357  return ::fsync(fd);
4358 #else
4359  return ::_commit(fd);
4360 #endif
4361 }
4362 
4363 ////////////////////////////////////////////////////////////////////////////////
4364 /// Return the total number of bytes written so far to the file.
4365 
4368  return fCacheWrite ? fCacheWrite->GetBytesInCache() + fBytesWrite : fBytesWrite;
4369 }
4370 
4371 ////////////////////////////////////////////////////////////////////////////////
4372 /// Static function returning the total number of bytes read from all files.
4373 
4376  return fgBytesRead;
4377 }
4378 
4379 ////////////////////////////////////////////////////////////////////////////////
4380 /// Static function returning the total number of bytes written to all files.
4381 /// Does not take into account what might still be in the write caches.
4382 
4385  return fgBytesWrite;
4386 }
4387 
4388 ////////////////////////////////////////////////////////////////////////////////
4389 /// Static function returning the total number of read calls from all files.
4390 
4393  return fgReadCalls;
4394 }
4395 
4396 ////////////////////////////////////////////////////////////////////////////////
4397 /// Static function returning the readahead buffer size.
4398 
4401  return fgReadaheadSize;
4402 }
4403 
4404 //______________________________________________________________________________
4405 void TFile::SetReadaheadSize(Int_t bytes) { fgReadaheadSize = bytes; }
4407 //______________________________________________________________________________
4408 void TFile::SetFileBytesRead(Long64_t bytes) { fgBytesRead = bytes; }
4410 //______________________________________________________________________________
4411 void TFile::SetFileBytesWritten(Long64_t bytes) { fgBytesWrite = bytes; }
4413 //______________________________________________________________________________
4414 void TFile::SetFileReadCalls(Int_t readcalls) { fgReadCalls = readcalls; }
4416 //______________________________________________________________________________
4417 Long64_t TFile::GetFileCounter() { return fgFileCounter; }
4419 //______________________________________________________________________________
4420 void TFile::IncrementFileCounter() { fgFileCounter++; }
4422 ////////////////////////////////////////////////////////////////////////////////
4423 /// Sets the directory where to locally stage/cache remote files.
4424 /// If the directory is not writable by us return kFALSE.
4425 
4426 Bool_t TFile::SetCacheFileDir(const char *cachedir, Bool_t operatedisconnected,
4427  Bool_t forcecacheread )
4428 {
4429  TString cached = cachedir;
4430  if (!cached.EndsWith("/"))
4431  cached += "/";
4432 
4433  if (gSystem->AccessPathName(cached, kFileExists)) {
4434  // try to create it
4435  gSystem->mkdir(cached, kTRUE);
4436  if (gSystem->AccessPathName(cached, kFileExists)) {
4437  ::Error("TFile::SetCacheFileDir", "no sufficient permissions on cache directory %s or cannot create it", cachedir);
4438  fgCacheFileDir = "";
4439  return kFALSE;
4440  }
4441  gSystem->Chmod(cached, 0700);
4442  }
4443  if (gSystem->AccessPathName(cached, kWritePermission))
4444  gSystem->Chmod(cached, 0700);
4445  fgCacheFileDir = cached;
4446  fgCacheFileDisconnected = operatedisconnected;
4447  fgCacheFileForce = forcecacheread;
4448  return kTRUE;
4449 }
4450 
4451 ////////////////////////////////////////////////////////////////////////////////
4452 /// Get the directory where to locally stage/cache remote files.
4453 
4454 const char *TFile::GetCacheFileDir()
4456  return fgCacheFileDir;
4457 }
4458 
4459 ////////////////////////////////////////////////////////////////////////////////
4460 /// Try to shrink the cache to the desired size.
4461 ///
4462 /// With the clenupinterval you can specify the minimum amount of time after
4463 /// the previous cleanup before the cleanup operation is repeated in
4464 /// the cache directory
4465 
4466 Bool_t TFile::ShrinkCacheFileDir(Long64_t shrinksize, Long_t cleanupinterval)
4468  if (fgCacheFileDir == "") {
4469  return kFALSE;
4470  }
4471 
4472  // check the last clean-up in the cache
4473  Long_t id;
4474  Long64_t size;
4475  Long_t flags;
4476  Long_t modtime;
4477 
4478  TString cachetagfile = fgCacheFileDir;
4479  cachetagfile += ".tag.ROOT.cache";
4480  if (!gSystem->GetPathInfo(cachetagfile, &id, &size, &flags, &modtime)) {
4481  // check the time passed since last cache cleanup
4482  Long_t lastcleanuptime = ((Long_t)time(0) - modtime);
4483  if (lastcleanuptime < cleanupinterval) {
4484  ::Info("TFile::ShrinkCacheFileDir", "clean-up is skipped - last cleanup %lu seconds ago - you requested %lu", lastcleanuptime, cleanupinterval);
4485  return kTRUE;
4486  }
4487  }
4488 
4489  // (re-)create the cache tag file
4490  cachetagfile += "?filetype=raw";
4491  TFile *tagfile = 0;
4492 
4493  if (!(tagfile = TFile::Open(cachetagfile, "RECREATE"))) {
4494  ::Error("TFile::ShrinkCacheFileDir", "cannot create the cache tag file %s", cachetagfile.Data());
4495  return kFALSE;
4496  }
4497 
4498  // the shortest garbage collector in the world - one long line of PERL - unlinks files only,
4499  // if there is a symbolic link with '.ROOT.cachefile' for safety ;-)
4500 
4501  TString cmd;
4502 #if defined(R__WIN32)
4503  cmd = "echo <TFile::ShrinkCacheFileDir>: cleanup to be implemented";
4504 #elif defined(R__MACOSX)
4505  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);
4506 #else
4507  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);
4508 #endif
4509 
4510  tagfile->WriteBuffer(cmd, 4096);
4511  delete tagfile;
4512 
4513  if ((gSystem->Exec(cmd)) != 0) {
4514  ::Error("TFile::ShrinkCacheFileDir", "error executing clean-up script");
4515  return kFALSE;
4516  }
4517 
4518  return kTRUE;
4519 }
4520 
4521 ////////////////////////////////////////////////////////////////////////////////
4522 /// Sets open timeout time (in ms). Returns previous timeout value.
4523 
4526  UInt_t to = fgOpenTimeout;
4527  fgOpenTimeout = timeout;
4528  return to;
4529 }
4530 
4531 ////////////////////////////////////////////////////////////////////////////////
4532 /// Returns open timeout (in ms).
4533 
4536  return fgOpenTimeout;
4537 }
4538 
4539 ////////////////////////////////////////////////////////////////////////////////
4540 /// Sets only staged flag. Returns previous value of flag.
4541 /// When true we check before opening the file if it is staged, if not,
4542 /// the open fails.
4543 
4546  Bool_t f = fgOnlyStaged;
4547  fgOnlyStaged = onlystaged;
4548  return f;
4549 }
4550 
4551 ////////////////////////////////////////////////////////////////////////////////
4552 /// Returns staged only flag.
4553 
4556  return fgOnlyStaged;
4557 }
4558 
4559 ////////////////////////////////////////////////////////////////////////////////
4560 /// Return kTRUE if 'url' matches the coordinates of this file.
4561 ///
4562 /// The check is implementation dependent and may need to be overload
4563 /// by each TFile implementation relying on this check.
4564 /// The default implementation checks the file name only.
4565 
4566 Bool_t TFile::Matches(const char *url)
4568  // Check the full URL, including port and FQDN.
4569  TUrl u(url);
4570 
4571  // Check
4572  if (!strcmp(u.GetFile(), fUrl.GetFile())) {
4573  // Check ports
4574  if (u.GetPort() == fUrl.GetPort()) {
4575  if (!strcmp(u.GetHostFQDN(), fUrl.GetHostFQDN())) {
4576  // Ok, coordinates match
4577  return kTRUE;
4578  }
4579  }
4580  }
4581 
4582  // Default is not matching
4583  return kFALSE;
4584 }
4585 
4586 ////////////////////////////////////////////////////////////////////////////////
4587 /// Return kTRUE if this async request matches the open request
4588 /// specified by 'url'
4589 
4590 Bool_t TFileOpenHandle::Matches(const char *url)
4592  if (fFile) {
4593  return fFile->Matches(url);
4594  } else if (fName.Length() > 0){
4595  // Deep check of URLs
4596  TUrl u(url);
4597  TUrl uref(fName);
4598  if (!strcmp(u.GetFile(), uref.GetFile())) {
4599  // Check ports
4600  if (u.GetPort() == uref.GetPort()) {
4601  // Check also the host name
4602  if (!strcmp(u.GetHostFQDN(), uref.GetHostFQDN())) {
4603  // Ok, coordinates match
4604  return kTRUE;
4605  }
4606  }
4607  }
4608  }
4609 
4610  // Default is not matching
4611  return kFALSE;
4612 }
4613 
4614 ////////////////////////////////////////////////////////////////////////////////
4615 /// Resolve the file type as a function of the protocol field in 'name'
4616 ///
4617 /// If defined, the string 'prefix' is added when testing the locality of
4618 /// a 'name' with network-like structure (i.e. root://host//path); if the file
4619 /// is local, on return 'prefix' will contain the actual local path of the file.
4620 
4621 TFile::EFileType TFile::GetType(const char *name, Option_t *option, TString *prefix)
4624 
4625  TPMERegexp re("^(root|xroot).*", "i");
4626  if (re.Match(name)) {
4627  //
4628  // Should be a network file ...
4629  type = kNet;
4630  // ... but make sure that is not local or that a remote-like connection
4631  // is forced. Treat it as local if:
4632  // i) the url points to the localhost, the file will be opened in
4633  // readonly mode and the current user has read access;
4634  // ii) the specified user is equal to the current user then open local
4635  // TFile.
4636  Bool_t localFile = kFALSE;
4637  TUrl url(name);
4638  //
4639  // Check whether we should try to optimize for local files
4640  Bool_t forceRemote = gEnv->GetValue("Path.ForceRemote", 0);
4641  forceRemote = (forceRemote) ? kTRUE : gEnv->GetValue("TFile.ForceRemote", 0);
4642  TString opts = url.GetOptions();
4643  if (opts.Contains("remote=1"))
4644  forceRemote = kTRUE;
4645  else if (opts.Contains("remote=0"))
4646  forceRemote = kFALSE;
4647  if (!forceRemote) {
4648  // Generic locality test
4649  localFile = gSystem->IsPathLocal(name);
4650  if (localFile) {
4651  // Local path including the prefix
4652  const char *fname = url.GetFileAndOptions();
4653  TString lfname;
4654  if (fname[0] == '/') {
4655  if (prefix)
4656  lfname.Form("%s%s", prefix->Data(), fname);
4657  else
4658  lfname = fname;
4659  } else if (fname[0] == '~' || fname[0] == '$') {
4660  lfname = fname;
4661  } else {
4662  lfname.Form("%s/%s", gSystem->HomeDirectory(), fname);
4663  }
4664  // If option "READ" test existence and access
4665  TString opt = option;
4666  Bool_t read = (opt.IsNull() ||
4667  !opt.CompareTo("READ", TString::kIgnoreCase)) ? kTRUE : kFALSE;
4668  if (read) {
4669  char *fn;
4670  if ((fn = gSystem->ExpandPathName(TUrl(lfname).GetFile()))) {
4672  localFile = kFALSE;
4673  delete [] fn;
4674  }
4675  }
4676  // Return full local path if requested (and if the case)
4677  if (localFile && prefix)
4678  *prefix = lfname;
4679  }
4680  }
4681  //
4682  // Adjust the type according to findings
4683  type = (localFile) ? kLocal : type;
4684  } else if (TPMERegexp("^(http[s]?|s3http[s]?|[a]?s3|gs|gshttp[s]?){1}:", "i").Match(name)) {
4685  //
4686  // Web file
4687  type = kWeb;
4688  } else if (!strncmp(name, "file:", 5)) {
4689  //
4690  // 'file' protocol
4691  type = kFile;
4692  }
4693  // We are done
4694  return type;
4695 }
4696 
4697 ////////////////////////////////////////////////////////////////////////////////
4698 /// Get status of the async open request related to 'name'.
4699 
4702  // Check the list of pending async open requests
4703  if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4704  TIter nxr(fgAsyncOpenRequests);
4705  TFileOpenHandle *fh = 0;
4706  while ((fh = (TFileOpenHandle *)nxr()))
4707  if (fh->Matches(name))
4708  return TFile::GetAsyncOpenStatus(fh);
4709  }
4710 
4711  // Check also the list of files open
4713  TSeqCollection *of = gROOT->GetListOfFiles();
4714  if (of && (of->GetSize() > 0)) {
4715  TIter nxf(of);
4716  TFile *f = 0;
4717  while ((f = (TFile *)nxf()))
4718  if (f->Matches(name))
4719  return f->GetAsyncOpenStatus();
4720  }
4721 
4722  // Default is synchronous mode
4723  return kAOSNotAsync;
4724 }
4725 
4726 ////////////////////////////////////////////////////////////////////////////////
4727 /// Get status of the async open request related to 'handle'.
4728 
4731  if (handle && handle->fFile) {
4732  if (!handle->fFile->IsZombie())
4733  return handle->fFile->GetAsyncOpenStatus();
4734  else
4735  return TFile::kAOSFailure;
4736  }
4737 
4738  // Default is synchronous mode
4739  return TFile::kAOSNotAsync;
4740 }
4741 
4742 ////////////////////////////////////////////////////////////////////////////////
4743 /// Get final URL for file being opened asynchronously.
4744 /// Returns 0 is the information is not yet available.
4745 
4746 const TUrl *TFile::GetEndpointUrl(const char* name)
4748  // Check the list of pending async open requests
4749  if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4750  TIter nxr(fgAsyncOpenRequests);
4751  TFileOpenHandle *fh = 0;
4752  while ((fh = (TFileOpenHandle *)nxr()))
4753  if (fh->Matches(name))
4754  if (fh->fFile)
4755  return fh->fFile->GetEndpointUrl();
4756  }
4757 
4758  // Check also the list of files open
4760  TSeqCollection *of = gROOT->GetListOfFiles();
4761  if (of && (of->GetSize() > 0)) {
4762  TIter nxf(of);
4763  TFile *f = 0;
4764  while ((f = (TFile *)nxf()))
4765  if (f->Matches(name))
4766  return f->GetEndpointUrl();
4767  }
4768 
4769  // Information not yet available
4770  return (const TUrl *)0;
4771 }
4772 
4773 ////////////////////////////////////////////////////////////////////////////////
4774 /// Print file copy progress.
4775 
4776 void TFile::CpProgress(Long64_t bytesread, Long64_t size, TStopwatch &watch)
4778  fprintf(stderr, "[TFile::Cp] Total %.02f MB\t|", (Double_t)size/1048576);
4779 
4780  for (int l = 0; l < 20; l++) {
4781  if (size > 0) {
4782  if (l < 20*bytesread/size)
4783  fprintf(stderr, "=");
4784  else if (l == 20*bytesread/size)
4785  fprintf(stderr, ">");
4786  else if (l > 20*bytesread/size)
4787  fprintf(stderr, ".");
4788  } else
4789  fprintf(stderr, "=");
4790  }
4791  // Allow to update the GUI while uploading files
4793  watch.Stop();
4794  Double_t lCopy_time = watch.RealTime();
4795  fprintf(stderr, "| %.02f %% [%.01f MB/s]\r",
4796  100.0*(size?(bytesread/((float)size)):1), (lCopy_time>0.)?bytesread/lCopy_time/1048576.:0.);
4797  watch.Continue();
4798 }
4799 
4800 ////////////////////////////////////////////////////////////////////////////////
4801 /// Allows to copy this file to the dst URL. Returns kTRUE in case of success,
4802 /// kFALSE otherwise.
4803 
4804 Bool_t TFile::Cp(const char *dst, Bool_t progressbar, UInt_t buffersize)
4806  Bool_t rmdestiferror = kFALSE;
4807  TStopwatch watch;
4808  Bool_t success = kFALSE;
4809 
4810  TUrl dURL(dst, kTRUE);
4811 
4812  TString oopt = "RECREATE";
4813  TString ourl = dURL.GetUrl();
4814 
4815  // Files will be open in RAW mode
4816  TString raw = "filetype=raw";
4817 
4818  // Set optimization options for the destination file
4819  TString opt = dURL.GetOptions();
4820  if (opt != "") opt += "&";
4821  opt += raw;
4822 
4823  // AliEn files need to know where the source file is
4824  if (!strcmp(dURL.GetProtocol(), "alien"))
4825  opt += TString::Format("&source=%s", GetName());
4826 
4827  dURL.SetOptions(opt);
4828 
4829  char *copybuffer = 0;
4830 
4831  TFile *sfile = this;
4832  TFile *dfile = 0;
4833 
4834  // "RECREATE" does not work always well with XROOTD
4835  // namely when some pieces of the path are missing;
4836  // we force "NEW" in such a case
4837  if (TFile::GetType(ourl, "") == TFile::kNet) {
4838  if (gSystem->AccessPathName(ourl)) {
4839  oopt = "NEW";
4840  // Force creation of the missing parts of the path
4841  opt += "&mkpath=1";
4842  dURL.SetOptions(opt);
4843  }
4844  }
4845 
4846  // Open destination file
4847  if (!(dfile = TFile::Open(dURL.GetUrl(), oopt))) {
4848  ::Error("TFile::Cp", "cannot open destination file %s", dst);
4849  goto copyout;
4850  }
4851 
4852  // Probably we created a new file
4853  // We have to remove it in case of errors
4854  rmdestiferror = kTRUE;
4855 
4856  sfile->Seek(0);
4857  dfile->Seek(0);
4858 
4859  copybuffer = new char[buffersize];
4860  if (!copybuffer) {
4861  ::Error("TFile::Cp", "cannot allocate the copy buffer");
4862  goto copyout;
4863  }
4864 
4865  Bool_t readop;
4866  Bool_t writeop;
4867  Long64_t read;
4868  Long64_t written;
4869  Long64_t totalread;
4870  Long64_t filesize;
4871  Long64_t b00;
4872  filesize = sfile->GetSize();
4873  totalread = 0;
4874  watch.Start();
4875 
4876  b00 = sfile->GetBytesRead();
4877 
4878  do {
4879  if (progressbar) CpProgress(totalread, filesize,watch);
4880 
4881  Long64_t b1 = sfile->GetBytesRead() - b00;
4882 
4883  Long64_t readsize;
4884  if (filesize - b1 > (Long64_t)buffersize) {
4885  readsize = buffersize;
4886  } else {
4887  readsize = filesize - b1;
4888  }
4889 
4890  if (readsize == 0) break;
4891 
4892  Long64_t b0 = sfile->GetBytesRead();
4893  sfile->Seek(totalread,TFile::kBeg);
4894  readop = sfile->ReadBuffer(copybuffer, (Int_t)readsize);
4895  read = sfile->GetBytesRead() - b0;
4896  if ((read <= 0) || readop) {
4897  ::Error("TFile::Cp", "cannot read from source file %s. readsize=%lld read=%lld readop=%d",
4898  sfile->GetName(), readsize, read, readop);
4899  goto copyout;
4900  }
4901 
4902  Long64_t w0 = dfile->GetBytesWritten();
4903  writeop = dfile->WriteBuffer(copybuffer, (Int_t)read);
4904  written = dfile->GetBytesWritten() - w0;
4905  if ((written != read) || writeop) {
4906  ::Error("TFile::Cp", "cannot write %lld bytes to destination file %s", read, dst);
4907  goto copyout;
4908  }
4909  totalread += read;
4910  } while (read == (Long64_t)buffersize);
4911 
4912  if (progressbar) {
4913  CpProgress(totalread, filesize,watch);
4914  fprintf(stderr, "\n");
4915  }
4916 
4917  success = kTRUE;
4918 
4919 copyout:
4920  if (dfile) dfile->Close();
4921 
4922  if (dfile) delete dfile;
4923  if (copybuffer) delete[] copybuffer;
4924 
4925  if (rmdestiferror && (success != kTRUE))
4926  gSystem->Unlink(dst);
4927 
4928  watch.Stop();
4929  watch.Reset();
4930 
4931  return success;
4932 }
4933 
4934 ////////////////////////////////////////////////////////////////////////////////
4935 /// Allows to copy file from src to dst URL. Returns kTRUE in case of success,
4936 /// kFALSE otherwise.
4937 
4938 Bool_t TFile::Cp(const char *src, const char *dst, Bool_t progressbar,
4939  UInt_t buffersize)
4940 {
4941  TUrl sURL(src, kTRUE);
4942 
4943  // Files will be open in RAW mode
4944  TString raw = "filetype=raw";
4945 
4946  // Set optimization options for the source file
4947  TString opt = sURL.GetOptions();
4948  if (opt != "") opt += "&";
4949  opt += raw;
4950  // Netx-related options:
4951  // cachesz = 4*buffersize -> 4 buffers as peak mem usage
4952  // readaheadsz = 2*buffersize -> Keep at max 4*buffersize bytes outstanding when reading
4953  // rmpolicy = 1 -> Remove from the cache the blk with the least offset
4954  opt += TString::Format("&cachesz=%d&readaheadsz=%d&rmpolicy=1", 4*buffersize, 2*buffersize);
4955  sURL.SetOptions(opt);
4956 
4957  TFile *sfile = 0;
4958 
4959  Bool_t success = kFALSE;
4960 
4961  // Open source file
4962  if (!(sfile = TFile::Open(sURL.GetUrl(), "READ"))) {
4963  ::Error("TFile::Cp", "cannot open source file %s", src);
4964  } else {
4965  success = sfile->Cp(dst, progressbar, buffersize);
4966  }
4967 
4968  if (sfile) sfile->Close();
4969  if (sfile) delete sfile;
4970 
4971  return success;
4972 }
4973 
4974 //______________________________________________________________________________
4975 //The next statement is not active anymore on Linux.
4976 //Using posix_fadvise introduces a performance penalty (10 %) on optimized files
4977 //and in addition it destroys the information of TTreePerfStats
4978 #if defined(R__neverLINUX) && !defined(R__WINGCC)
4980 {
4981  // Read specified byte range asynchronously. Actually we tell the kernel
4982  // which blocks we are going to read so it can start loading these blocks
4983  // in the buffer cache.
4984 
4985  // Shortcut to avoid having to implement dummy ReadBufferAsync() in all
4986  // I/O plugins. Override ReadBufferAsync() in plugins if async is supported.
4987  if (IsA() != TFile::Class())
4988  return kTRUE;
4989 
4990  int advice = POSIX_FADV_WILLNEED;
4991  if (len == 0) {
4992  // according POSIX spec if len is zero, all data following offset
4993  // is specified. Nevertheless ROOT uses zero to probe readahead
4994  // capabilities.
4995  advice = POSIX_FADV_NORMAL;
4996  }
4997  Double_t start = 0;
4998  if (gPerfStats != 0) start = TTimeStamp();
4999 #if defined(R__SEEK64)
5000  Int_t result = posix_fadvise64(fD, offset, len, advice);
5001 #else
5002  Int_t result = posix_fadvise(fD, offset, len, advice);
5003 #endif
5004  if (gPerfStats != 0) {
5005  gPerfStats->FileReadEvent(this, len, start);
5006  }
5007  return (result != 0);
5008 }
5009 #else
5012  // Not supported yet on non Linux systems.
5013 
5014  return kTRUE;
5015 }
5016 #endif
5017 
5018 ////////////////////////////////////////////////////////////////////////////////
5019 /// Max number of bytes to prefetch.
5020 ///
5021 /// By default this is 75% of the
5022 /// read cache size. But specific TFile implementations may need to change it
5023 
5026  TFileCacheRead *cr = 0;
5027  if ((cr = GetCacheRead())) {
5028  Int_t bytes = cr->GetBufferSize() / 4 * 3;
5029  return ((bytes < 0) ? 0 : bytes);
5030  }
5031  return 0;
5032 }
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
virtual Int_t Sizeof() const
Return the size in bytes of the directory header.
static TProcessID * GetPID()
static: returns pointer to current TProcessID
Definition: TProcessID.cxx:313
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:929
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
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:1266
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:140
Bool_t IsReading() const
Definition: TBuffer.h:83
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
An array of TObjects.
Definition: TObjArray.h:39
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition: TROOT.cxx:2547
const char * GetArchiveName() const
Definition: TArchiveFile.h:61
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:4344
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
virtual const char * GetFlagsOpt() const
Return the optimization flags.
Definition: TSystem.cxx:3805
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:1810
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:1275
long long Long64_t
Definition: RtypesCore.h:69
Long64_t GetLast() const
Definition: TFree.h:43
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:4326
EAsyncOpenStatus
Asynchronous open request status.
Definition: TFile.h:56
virtual const char * WorkingDirectory()
Return working directory.
Definition: TSystem.cxx:866
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
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
Bool_t Matches(const char *name)
Return kTRUE if this async request matches the open request specified by &#39;url&#39;.
Definition: TFile.cxx:4591
static void IncrementFileCounter()
Definition: TFile.cxx:4421
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_t GetNetOpt() const
Definition: TFile.h:356
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
virtual char * GetBuffer() const
Definition: TKey.h:80
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:1364
unsigned short UShort_t
Definition: RtypesCore.h:36
Class holding info about the file being opened.
Definition: TFile.h:328
const char * GetProtocol() const
Definition: TUrl.h:73
static UInt_t fgOpenTimeout
Timeout for open operations in ms - 0 corresponds to blocking i/o.
Definition: TFile.h:116
virtual const char * GetClassName() const
Definition: TKey.h:77
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
TH1 * h
Definition: legend2.C:5
UInt_t GetBaseCheckSum()
virtual void Seek(Long64_t offset, ERelativeTo pos=kBeg)
Seek to a specific position in the file. Pos it either kBeg, kCur or kEnd.
Definition: TFile.cxx:2105
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:50
static void SetFileReadCalls(Int_t readcalls=0)
Definition: TFile.cxx:4415
virtual Int_t GetEntries() const
Definition: TCollection.h:92
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
Bool_t HasInterpreterInfo() const
Definition: TClass.h:374
virtual Bool_t ChangeDirectory(const char *path)
Change directory.
Definition: TSystem.cxx:857
const char * GetFileAndOptions() const
Return the file and its options (the string specified behind the ?).
Definition: TUrl.cxx:501
static TArchiveFile * Open(const char *url, TFile *file)
Return proper archive file handler depending on passed url.
#define gROOT
Definition: TROOT.h:364
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
virtual Long64_t GetBytesWritten() const
Return the total number of bytes written so far to the file.
Definition: TFile.cxx:4367
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:1819
#define O_BINARY
Definition: civetweb.c:451
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:4467
virtual Int_t Sizeof() const
Return size of the TNamed part of the TObject.
Definition: TNamed.cxx:164
void ToLower()
Change string to lower-case.
Definition: TString.cxx: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 const char * GetSoExt() const
Get the shared library extension.
Definition: TSystem.cxx:3875
#define gInterpreter
Definition: TInterpreter.h:517
const char * GetOptions() const
Definition: TUrl.h:80
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 const char * GetFlagsDebug() const
Return the debug flags.
Definition: TSystem.cxx:3797
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
TObject * At(Int_t idx) const
Definition: TObjArray.h:167
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:3552
const char * Class
Definition: TXMLSetup.cxx:64
virtual TObject * Clone(const char *newname="") const
Make a clone of an collection using the Streamer facility.
static void SetReadaheadSize(Int_t bufsize=256000)
Definition: TFile.cxx:4406
TString & Insert(Ssiz_t pos, const char *s)
Definition: TString.h:592
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
const char * GetHostFQDN() const
Return fully qualified domain name of url host.
Definition: TUrl.cxx:469
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Definition: TSystem.cxx:901
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:739
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition: TUrl.cxx:387
void SysError(const char *location, const char *msgfmt,...)
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:497
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:3907
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:4805
static void SetFileBytesWritten(Long64_t bytes=0)
Definition: TFile.cxx:4412
const char * GetFile() const
Definition: TUrl.h:78
virtual Int_t GetErrno() const
Method returning errno. Is overriden in TRFIOFile.
Definition: TFile.cxx:1186
static TObjArray * GetPIDs()
static: returns array of TProcessIDs
Definition: TProcessID.cxx:321
double sqrt(double)
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:848
#define SafeDelete(p)
Definition: RConfig.h:507
virtual int Unlink(const char *name)
Unlink, i.e. remove, a file.
Definition: TSystem.cxx:1347
virtual Int_t GetClassVersion() const =0
Sequenceable collection abstract base class.
virtual void ResetErrno() const
Method resetting the errno. Is overridden in TRFIOFile.
Definition: TFile.cxx:1194
void Stop()
Stop the stopwatch.
Definition: TStopwatch.cxx:77
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx: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:1463
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:3562
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:2555
virtual void WriteFree()
Write FREE linked list on the file.
Definition: TFile.cxx:2375
static Long64_t GetFileBytesRead()
Static function returning the total number of bytes read from all files.
Definition: TFile.cxx:4375
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:4622
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:3700
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1140
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:4384
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=0)
Write the encoded object supported by this key.
Definition: TKey.cxx:1443
void Info(const char *location, const char *msgfmt,...)
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 EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2221
const std::string ClassName(PyObject *pyobj)
Retrieve the class name from the given python object (which may be just an instance of the class)...
Definition: Utility.cxx:702
const char * GetAnchor() const
Definition: TUrl.h:79
TFile * GetFile() const
Definition: TFile.h:347
void tobuf(char *&buf, Bool_t x)
Definition: Bytes.h:59
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 void Delete(Option_t *option="")
Delete an object from the file.
Definition: TKey.cxx:534
virtual TString GetNewUrl()
Definition: TFile.h:219
void Error(const char *location, const char *msgfmt,...)
R__EXTERN TPluginManager * gPluginMgr
virtual Int_t SysWrite(Int_t fd, const void *buf, Int_t len)
Interface to system write. All arguments like in POSIX write().
Definition: TFile.cxx:4315
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:4353
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 void ls(Option_t *option="") const
List Directory contents.
virtual Int_t SysClose(Int_t fd)
Interface to system close. All arguments like in POSIX close().
Definition: TFile.cxx:4298
Int_t GetObjlen() const
Definition: TKey.h:89
static UInt_t GetOpenTimeout()
Returns open timeout (in ms).
Definition: TFile.cxx:4535
virtual void ShowStreamerInfo()
Show the StreamerInfo of all classes written to this file.
Definition: TFile.cxx:3570
th1 Draw()
EFileType
File type.
Definition: TFile.h: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:4307
const char * GetOpt() const
Definition: TFile.h:354
void ResetErrno()
reset errno
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:222
TClass * GetClass() const
R__EXTERN TSystem * gSystem
Definition: TSystem.h: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:4282
#define R__RWLOCK_RELEASE_WRITE(rwlock)
UInt_t GetCheckSum() const
virtual void WriteStreamerInfo()
Write the list of TStreamerInfo as a single object in this file The class Streamer description for al...
Definition: TFile.cxx:3612
A ROOT file is structured in Directories (like a file system).
virtual const char * GetLibraries(const char *regexp="", const char *option="", Bool_t isRegexp=kTRUE)
Return a space separated list of loaded shared libraries.
Definition: TSystem.cxx:2085
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
virtual Int_t GetBytesToPrefetch() const
Max number of bytes to prefetch.
Definition: TFile.cxx:5025
Long_t ExecPlugin(int nargs, const T &... params)
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx: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 TMatches FindRules(const TString &source) const
Return all the rules that are about the given &#39;source&#39; class.
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx: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:1261
Ssiz_t Length() const
Definition: TString.h:390
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition: TFile.cxx:1394
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
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
static void CpProgress(Long64_t bytesread, Long64_t size, TStopwatch &watch)
Print file copy progress.
Definition: TFile.cxx:4777
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition: TROOT.cxx:2618
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
ROOT::ESTLType GetCollectionType() const
Return the &#39;type&#39; of the STL the TClass is representing.
Definition: TClass.cxx:2811
void Build(TFile *motherFile=0, TDirectory *motherDir=0)
Initialise directory to defaults.
static Int_t GetFileReadCalls()
Static function returning the total number of read calls from all files.
Definition: TFile.cxx:4392
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4610
virtual const char * GetMakeSharedLib() const
Return the command line use to make a shared library.
Definition: TSystem.cxx:3826
void SetName(const char *name)
Definition: TCollection.h:116
virtual TObject * ReadObjWithBuffer(char *bufferRead)
To read a TObject* from bufferRead.
Definition: TKey.cxx:872
void Warning(const char *location, const char *msgfmt,...)
virtual void Init(Bool_t create)
Initialize a TFile object.
Definition: TFile.cxx:584
TString & String()
Definition: TObjString.h:52
Long64_t GetFirst() const
Definition: TFree.h:42
TFile * GetFile() const
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
virtual TObjLink * FirstLink() const
Definition: TList.h:101
Option_t * GetOption() const
Definition: TFile.h:209
#define Printf
Definition: TGeoToOCC.h:18
#define gPerfStats
#define R__LOCKGUARD2(mutex)
static void GenerateMissingStreamerInfos(TList *extrainfos, TStreamerElement *element)
Generate an empty StreamerInfo for types that are used in templates parameters but are not known in t...
virtual Long64_t GetBytesRead() const
Definition: TFile.h:210
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:4555
virtual void ReadStreamerInfo()
Read the list of StreamerInfo from this file.
Definition: TFile.cxx:3435
virtual Int_t RedirectOutput(const char *name, const char *mode="a", RedirectHandle_t *h=0)
Redirect standard output (stdout, stderr) to the specified file.
Definition: TSystem.cxx:1678
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:1472
Version_t GetClassVersion() const
Definition: TClass.h:382
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition: TKey.cxx:1218
void SetAnchor(const char *anchor)
Definition: TUrl.h:95
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2241
virtual const char * GetIncludePath()
Get the list of include path.
Definition: TSystem.cxx:3843
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:91
virtual Bool_t IsOpen() const
Returns kTRUE in case file is open and kFALSE if file is not open.
Definition: TFile.cxx:1379
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
#define ClassImp(name)
Definition: Rtypes.h:279
double f(double x)
void Print(std::ostream &os, const OptionType &opt)
Bool_t IsZombie() const
Definition: TObject.h:120
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
Int_t Sizeof() const
return number of bytes occupied by this TFree on permanent storage
Definition: TFree.cxx:184
virtual Int_t ReadKeys(Bool_t forceRead=kTRUE)
Read the linked list of keys.
virtual Long64_t GetSeekKey() const
Definition: TKey.h:91
double Double_t
Definition: RtypesCore.h:55
virtual void ls(Option_t *option="") const
List (ls) all objects in this collection.
virtual int Symlink(const char *from, const char *to)
Create a symbolic link from file1 to file2.
Definition: TSystem.cxx:1338
static Int_t GetReadaheadSize()
Static function returning the readahead buffer size.
Definition: TFile.cxx:4400
#define R__RWLOCK_ACQUIRE_READ(rwlock)
Describe directory structure in memory.
Definition: TDirectory.h:44
TFileCacheWrite * GetCacheWrite() const
Return a pointer to the current write cache.
Definition: TFile.cxx:1219
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition: TMap.h: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 Int_t GetBufferSize() const
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:552
virtual Long64_t GetSize() const
Returns the current file size.
Definition: TFile.cxx:1285
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition: TTimeStamp.h:76
Int_t GetNbytes() const
Definition: TKey.h:88
static Bool_t fgCacheFileDisconnected
Indicates, we trust in the files in the cache dir without stat on the cached file.
Definition: TFile.h:114
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
Definition: TProcessID.cxx:275
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition: TString.cxx:386
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:2893
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:349
Int_t GetCompress() const
Definition: TFile.h:355
virtual Bool_t SendFileReadProgress(TFile *)
virtual void Close(Option_t *option="")
Delete all objects from memory and directory structure itself.
Int_t GetPort() const
Definition: TUrl.h:87
Int_t GetKeylen() const
Definition: TKey.h:86
Bool_t IsNull() const
Definition: TString.h:387
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
Mother of all ROOT objects.
Definition: TObject.h:37
TObjArray * GetElements() const
Bool_t FlushWriteCache()
Flush the write cache if active.
Definition: TFile.cxx:1103
static Bool_t SetOnlyStaged(Bool_t onlystaged)
Sets only staged flag.
Definition: TFile.cxx:4545
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
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:2610
Int_t GetClassVersion() const
virtual const TUrl * GetEndpointUrl() const
Definition: TFile.h:204
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:4147
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:4427
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:3316
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:1688
virtual void Print(Option_t *option="") const
Print all objects in the file.
Definition: TFile.cxx:1538
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:3583
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
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
virtual Int_t Sizeof() const
Return the size in bytes of the file header.
Definition: TFile.cxx:2229
#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:4525
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
virtual int CopyFile(const char *from, const char *to, Bool_t overwrite=kFALSE)
Copy a file.
Definition: TSystem.cxx:1311
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
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1965
#define R__RWLOCK_ACQUIRE_WRITE(rwlock)
void Reset()
Definition: TStopwatch.h:54
Definition: tree.py:1
TFileCacheRead * GetCacheRead(TObject *tree=0) const
Return a pointer to the current read cache.
Definition: TFile.cxx:1202
void Add(TObject *obj)
Definition: TObjArray.h:75
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 void ResetErrno()
Static function resetting system error number.
Definition: TSystem.cxx:281
#define gDirectory
Definition: TDirectory.h:221
double result[121]
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition: TClass.cxx:1852
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1244
Definition: first.py:1
static Int_t fgReadaheadSize
Readahead buffer size.
Definition: TFile.h:123
virtual void WriteHeader()
Write File Header.
Definition: TFile.cxx:2447
Bool_t IsWritable() const
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.
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:416
virtual Int_t GetSize() const
Definition: TCollection.h:95
Abstract Interface class describing Streamer information for one class.
static void SetFileBytesRead(Long64_t bytes=0)
Definition: TFile.cxx:4409
Int_t GetNumber() const
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual void ls(Option_t *option="") const
List file contents.
Definition: TFile.cxx:1367
void *(* GlobalFunc_t)()
Definition: TGlobal.h:56
static Long64_t GetFileCounter()
Definition: TFile.cxx:4418
const Int_t n
Definition: legend1.C:16
virtual void SetCacheWrite(TFileCacheWrite *cache)
Set a pointer to the write cache.
Definition: TFile.cxx:2220
TString fFile
Definition: TSystem.h:215
virtual const char * GetObjExt() const
Get the object file extension.
Definition: TSystem.cxx:3883
gr SetName("gr")
char name[80]
Definition: TGX11.cxx:109
static const char * GetCacheFileDir()
Get the directory where to locally stage/cache remote files.
Definition: TFile.cxx:4455
virtual TProcessID * ReadProcessID(UShort_t pidf)
The TProcessID with number pidf is read from this file.
Definition: TFile.cxx:1783
A cache when writing files over the network.
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
Int_t GetBestBuffer() const
Return the best buffer size of objects on this file.
Definition: TFile.cxx:1128
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
Int_t MakeProjectParMake(const char *packname, const char *filename)
Create makefile at &#39;filemake&#39; for PAR package &#39;pack&#39;.
Definition: TFile.cxx:3194
virtual Bool_t ReadBufferAsync(Long64_t offs, Int_t len)
Definition: TFile.cxx:5011
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:4567
Bool_t IsRaw() const
Definition: TFile.h:229
const char * Data() const
Definition: TString.h:349
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
const char * GetClass() const
virtual EAsyncOpenStatus GetAsyncOpenStatus()
Definition: TFile.h:125