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