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