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