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