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