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 auto buffer = std::make_unique<char[]>(fNbytesInfo+1);
1408 auto buf = buffer.get();
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 if (!key->ReadKeyBuffer(buf, fNbytesInfo))
1431 return {nullptr, 1, hash};
1432 list = dynamic_cast<TList*>(key->ReadObjWithBuffer(buffer.get()));
1433 if (list) list->SetOwner();
1434 } else {
1435 list = (TList*)Get("StreamerInfo"); //for versions 2.26 (never released)
1436 }
1437
1438 if (!list) {
1439 Info("GetStreamerInfoList", "cannot find the StreamerInfo record in file %s",
1440 GetName());
1441 return {nullptr, 1, hash};
1442 }
1443
1444 return {list, 0, hash};
1445}
1446
1447////////////////////////////////////////////////////////////////////////////////
1448/// Read the list of TStreamerInfo objects written to this file.
1449///
1450/// The function returns a TList. It is the user's responsibility
1451/// to delete the list created by this function.
1452///
1453/// Note the list, in addition to TStreamerInfo object, contains sometimes
1454/// a TList named 'listOfRules' and containing the schema evolution rules
1455/// related to the file's content.
1456///
1457/// Using the list, one can access additional information, e.g.:
1458/// ~~~{.cpp}
1459/// TFile f("myfile.root");
1460/// auto list = f.GetStreamerInfoList();
1461/// auto info = dynamic_cast<TStreamerInfo*>(list->FindObject("MyClass"));
1462/// if (info) auto classversionid = info->GetClassVersion();
1463/// delete list;
1464/// ~~~
1465///
1468{
1469 return GetStreamerInfoListImpl(/*lookupSICache*/ false).fList;
1470}
1471
1472////////////////////////////////////////////////////////////////////////////////
1473/// List file contents.
1474///
1475/// Indentation is used to identify the file tree.
1476/// Subdirectories are listed first, then objects in memory,
1477/// then objects on the file.
1479void TFile::ls(Option_t *option) const
1480{
1482 std::cout <<ClassName()<<"**\t\t"<<GetName()<<"\t"<<GetTitle()<<std::endl;
1486}
1487
1488////////////////////////////////////////////////////////////////////////////////
1489/// Returns kTRUE in case file is open and kFALSE if file is not open.
1491Bool_t TFile::IsOpen() const
1492{
1493 return fD == -1 ? kFALSE : kTRUE;
1494}
1495
1496////////////////////////////////////////////////////////////////////////////////
1497/// Mark unused bytes on the file.
1498///
1499/// The list of free segments is in the fFree linked list.
1500/// When an object is deleted from the file, the freed space is added
1501/// into the FREE linked list (fFree). The FREE list consists of a chain
1502/// of consecutive free segments on the file. At the same time, the first
1503/// 4 bytes of the freed record on the file are overwritten by GAPSIZE
1504/// where GAPSIZE = -(Number of bytes occupied by the record).
1506void TFile::MakeFree(Long64_t first, Long64_t last)
1507{
1508 TFree *f1 = (TFree*)fFree->First();
1509 if (!f1) return;
1510 TFree *newfree = f1->AddFree(fFree,first,last);
1511 if(!newfree) return;
1512 Long64_t nfirst = newfree->GetFirst();
1513 Long64_t nlast = newfree->GetLast();
1515 if (nbytesl > 2000000000) nbytesl = 2000000000;
1517 char buffer[sizeof(Int_t)];
1518 char *pbuffer = buffer;
1520 if (last == fEND-1) fEND = nfirst;
1521 Seek(nfirst);
1522 // We could not update the meta data for this block on the file.
1523 // This is not fatal as this only means that we won't get it 'right'
1524 // if we ever need to Recover the file before the block is actually
1525 // (attempted to be reused.
1526 // coverity[unchecked_value]
1527 WriteBuffer(buffer, sizeof(buffer));
1528 if (fMustFlush) Flush();
1529}
1530
1531////////////////////////////////////////////////////////////////////////////////
1532/// List the contents of a file sequentially.
1533/// For each logical record found, it prints:
1534///
1535/// Date/Time Record_Adress Logical_Record_Length ClassName CompressionFactor
1536///
1537/// Example of output
1538///
1539/// 20010404/150437 At:64 N=150 TFile
1540/// 20010404/150440 At:214 N=28326 TBasket CX = 1.13
1541/// 20010404/150440 At:28540 N=29616 TBasket CX = 1.08
1542/// 20010404/150440 At:58156 N=29640 TBasket CX = 1.08
1543/// 20010404/150440 At:87796 N=29076 TBasket CX = 1.10
1544/// 20010404/150440 At:116872 N=10151 TBasket CX = 3.15
1545/// 20010404/150441 At:127023 N=28341 TBasket CX = 1.13
1546/// 20010404/150441 At:155364 N=29594 TBasket CX = 1.08
1547/// 20010404/150441 At:184958 N=29616 TBasket CX = 1.08
1548/// 20010404/150441 At:214574 N=29075 TBasket CX = 1.10
1549/// 20010404/150441 At:243649 N=9583 TBasket CX = 3.34
1550/// 20010404/150442 At:253232 N=28324 TBasket CX = 1.13
1551/// 20010404/150442 At:281556 N=29641 TBasket CX = 1.08
1552/// 20010404/150442 At:311197 N=29633 TBasket CX = 1.08
1553/// 20010404/150442 At:340830 N=29091 TBasket CX = 1.10
1554/// 20010404/150442 At:369921 N=10341 TBasket CX = 3.09
1555/// 20010404/150442 At:380262 N=509 TH1F CX = 1.93
1556/// 20010404/150442 At:380771 N=1769 TH2F CX = 4.32
1557/// 20010404/150442 At:382540 N=1849 TProfile CX = 1.65
1558/// 20010404/150442 At:384389 N=18434 TNtuple CX = 4.51
1559/// 20010404/150442 At:402823 N=307 KeysList
1560/// 20010404/150443 At:403130 N=4548 StreamerInfo CX = 3.65
1561/// 20010404/150443 At:407678 N=86 FreeSegments
1562/// 20010404/150443 At:407764 N=1 END
1563///
1564/// If the parameter opt contains "forComp", the Date/Time is omitted
1565/// and the decompressed size is also printed.
1566///
1567/// Record_Adress Logical_Record_Length Key_Length Object_Record_Length ClassName CompressionFactor
1568///
1569/// If the parameter opt contains "extended", the name and title of the keys are added:
1570/// 20200820/155031 At:100 N=180 TFile name: hsimple.root title: Demo ROOT file with histograms
1571/// 220200820/155032 At:280 N=28880 TBasket CX = 1.11 name: random title: ntuple
1572/// 220200820/155032 At:29160 N=29761 TBasket CX = 1.08 name: px title: ntuple
1573/// 220200820/155032 At:58921 N=29725 TBasket CX = 1.08 name: py title: ntuple
1574/// 220200820/155032 At:88646 N=29209 TBasket CX = 1.10 name: pz title: ntuple
1575/// 220200820/155032 At:117855 N=10197 TBasket CX = 3.14 name: i title: ntuple
1576/// ...
1577/// 20200820/155032 At:405110 N=808 TNtuple CX = 3.53 name: ntuple title: Demo ntuple
1578/// 20200820/155706 At:405918 N=307 KeysList name: hsimple.root title: Demo ROOT file with histograms
1579/// 20200820/155032 At:406225 N=8556 StreamerInfo CX = 3.42 name: StreamerInfo title: Doubly linked list
1580/// 20200820/155708 At:414781 N=86 FreeSegments name: hsimple.root title: Demo ROOT file with histograms
1581/// 20200820/155708 At:414867 N=1 END
1582///
1583/// Note: The combined size of the classname, name and title is truncated to 476 characters (a little more for regular keys of small files)
1584///
1585
1587void TFile::Map(Option_t *opt)
1588{
1589 TString options(opt);
1590 options.ToLower();
1591 const bool forComp = options.Contains("forcomp");
1592 const bool extended = options.Contains("extended");
1593
1594 const unsigned char nDigits = std::log10(fEND) + 1;
1595
1596 std::optional<ROOT::Detail::TKeyMapNode> lastNode;
1597 const auto tkeyInfos = WalkTKeys();
1598 for (const auto &key : tkeyInfos) {
1599 lastNode = key;
1600 switch (key.fType) {
1602 Printf("Address = %" PRIu64 "\tNbytes = %u\t=====E R R O R=======", key.fAddr, key.fLen);
1603 break;
1604
1606 Printf("Address = %" PRIu64 "\tNbytes = %d\t=====G A P===========", key.fAddr, -key.fLen);
1607 break;
1608
1611 if (extended)
1612 extrainfo.Form(" name: %-16s title: %s", key.fKeyName.c_str(), key.fKeyTitle.c_str());
1613
1614 if (forComp) {
1615 // Printing to help compare two files.
1616 if (key.fObjLen != static_cast<Int_t>(key.fLen) - key.fKeyLen) {
1617 Float_t cx = static_cast<float>(key.fObjLen + key.fKeyLen) / key.fLen;
1618 Printf("At:%-*" PRIu64 " N=%-8u K=%-3d O=%-8d %-14s CX = %5.2f %s", nDigits + 1, key.fAddr, key.fLen,
1619 key.fKeyLen, key.fObjLen, key.fClassName.c_str(), cx, extrainfo.Data());
1620 } else {
1621 Printf("At:%-*" PRIu64 " N=%-8u K=%-3d O=%-8d %-14s CX = 1 %s", nDigits + 1, key.fAddr, key.fLen,
1622 key.fKeyLen, key.fObjLen, key.fClassName.c_str(), extrainfo.Data());
1623 }
1624 } else {
1625 Int_t date, time;
1626 TDatime::GetDateTime(key.fDatime, date, time);
1627 if (key.fObjLen != static_cast<Int_t>(key.fLen) - key.fKeyLen) {
1628 Float_t cx = static_cast<float>(key.fObjLen + key.fKeyLen) / key.fLen;
1629 Printf("%d/%06d At:%-*" PRIu64 " N=%-8u %-14s CX = %5.2f %s", date, time, nDigits + 1, key.fAddr,
1630 key.fLen, key.fClassName.c_str(), cx, extrainfo.Data());
1631 } else {
1632 Printf("%d/%06d At:%-*" PRIu64 " N=%-8u %-14s %s", date, time, nDigits + 1, key.fAddr,
1633 key.fLen, key.fClassName.c_str(), extrainfo.Data());
1634 }
1635 }
1636 }
1637 }
1638
1639 if (!forComp) {
1640 Int_t datime = lastNode ? lastNode->fDatime : 0;
1641 Int_t date, time;
1643 Printf("%d/%06d At:%-*lld N=%-8d %-14s", date, time, nDigits + 1, fEND, 1, "END");
1644 } else {
1645 Printf("At:%-*lld N=%-8d K= O= %-14s", nDigits + 1, fEND, 1, "END");
1646 }
1647}
1652}
1654ROOT::Detail::TKeyMapIterable::TIterator::TIterator(TFile *file, std::uint64_t addr) : fFile(file), fCurAddr(addr)
1655{
1656 if (addr == 0)
1658 Advance();
1659}
1661std::optional<ROOT::Detail::TKeyMapNode> ROOT::Detail::TKeyMapIterable::TIterator::Next()
1662{
1663 static constexpr int headerSize = 512;
1664
1665 const std::uint64_t idcur = fCurAddr;
1666 const std::uint64_t end = fFile->fEND;
1667 if (idcur >= end)
1668 return std::nullopt;
1669
1670 fFile->Seek(idcur);
1671 auto nread = headerSize;
1672 if (idcur + nread >= end)
1673 nread = end - idcur - 1;
1674
1675 char header[headerSize];
1676 if (fFile->ReadBuffer(header, nread)) {
1677 // ReadBuffer returns kTRUE in case of failure.
1679 fCurAddr = end;
1680 return node;
1681 }
1682
1683 char *buffer = header;
1684 Int_t nbytes;
1685 frombuf(buffer, &nbytes);
1686 if (!nbytes) {
1688 fCurAddr = end;
1689 return node;
1690 }
1691
1692 if (nbytes < 0) {
1693 // free slot
1694 auto node =
1696 fCurAddr -= nbytes;
1697 return node;
1698 }
1699
1700 auto node = ROOT::Detail::TKeyMapNode{idcur, ROOT::Detail::TKeyMapNode::kKey, static_cast<std::uint32_t>(nbytes)};
1701 frombuf(buffer, &node.fKeyVersion);
1702 frombuf(buffer, &node.fObjLen);
1703 frombuf(buffer, &node.fDatime);
1704 frombuf(buffer, &node.fKeyLen);
1705 frombuf(buffer, &node.fCycle);
1706 if (node.fKeyVersion > 1000) {
1707 frombuf(buffer, &node.fSeekKey);
1708 frombuf(buffer, &node.fSeekPdir);
1709 } else {
1710 Int_t skey, sdir;
1711 frombuf(buffer, &skey);
1712 frombuf(buffer, &sdir);
1713 node.fSeekKey = static_cast<Long64_t>(skey);
1714 node.fSeekPdir = static_cast<Long64_t>(sdir);
1715 }
1716
1717 const auto readString = [&buffer, &header](bool skipCheck = false) {
1718 std::uint8_t stringLenShort;
1719 std::uint32_t stringLen;
1720 if (!skipCheck && ((buffer - header) >= headerSize)) {
1721 stringLen = 0;
1722 } else {
1723 frombuf(buffer, &stringLenShort);
1724 if (stringLenShort == 0xFF)
1725 frombuf(buffer, &stringLen);
1726 else
1728
1729 if ((buffer - header) + stringLen > headerSize)
1730 stringLen = headerSize - (buffer - header);
1731 }
1732
1733 std::string str;
1734 if (stringLen)
1735 str = std::string(buffer, stringLen);
1736 buffer += stringLen;
1737
1738 return str;
1739 };
1740
1741 node.fClassName = readString(true);
1742
1743 if (idcur == static_cast<std::uint64_t>(fFile->fSeekFree))
1744 node.fClassName = "FreeSegments";
1745 else if (idcur == static_cast<std::uint64_t>(fFile->fSeekInfo))
1746 node.fClassName = "StreamerInfo";
1747 else if (idcur == static_cast<std::uint64_t>(fFile->fSeekKeys))
1748 node.fClassName = "KeysList";
1749
1750 node.fKeyName = readString();
1751 node.fKeyTitle = readString();
1752
1753 fCurAddr += nbytes;
1754
1755 return node;
1756}
1757
1758////////////////////////////////////////////////////////////////////////////////
1759/// Paint all objects in the file.
1761void TFile::Paint(Option_t *option)
1762{
1763 GetList()->R__FOR_EACH(TObject,Paint)(option);
1764}
1765
1766////////////////////////////////////////////////////////////////////////////////
1767/// Print all objects in the file.
1769void TFile::Print(Option_t *option) const
1770{
1771 Printf("TFile: name=%s, title=%s, option=%s", GetName(), GetTitle(), GetOption());
1772 GetList()->R__FOR_EACH(TObject,Print)(option);
1773}
1774
1775////////////////////////////////////////////////////////////////////////////////
1776/// Read a buffer from the file at the offset 'pos' in the file.
1777///
1778/// Returns kTRUE in case of failure.
1779/// Compared to ReadBuffer(char*, Int_t), this routine does _not_
1780/// change the cursor on the physical file representation (fD)
1781/// if the data is in this TFile's cache.
1783Bool_t TFile::ReadBuffer(char *buf, Long64_t pos, Int_t len)
1784{
1785 if (IsOpen()) {
1786
1787 SetOffset(pos);
1788
1789 Int_t st;
1790 Double_t start = 0;
1791 if (gPerfStats) start = TTimeStamp();
1792
1793 if ((st = ReadBufferViaCache(buf, len))) {
1794 if (st == 2)
1795 return kTRUE;
1796 return kFALSE;
1797 }
1798
1799 Seek(pos);
1800 ssize_t siz;
1801
1802 while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
1803 ResetErrno();
1804
1805 if (siz < 0) {
1806 SysError("ReadBuffer", "error reading from file %s", GetName());
1807 return kTRUE;
1808 }
1809 if (siz != len) {
1810 Error("ReadBuffer", "error reading all requested bytes from file %s, got %ld of %d",
1811 GetName(), (Long_t)siz, len);
1812 return kTRUE;
1813 }
1814 fBytesRead += siz;
1815 fgBytesRead += siz;
1816 fReadCalls++;
1817 fgReadCalls++;
1818
1821 if (gPerfStats) {
1822 gPerfStats->FileReadEvent(this, len, start);
1823 }
1824 return kFALSE;
1825 }
1826 return kTRUE;
1827}
1828
1829////////////////////////////////////////////////////////////////////////////////
1830/// Read a buffer from the file. This is the basic low level read operation.
1831/// Returns kTRUE in case of failure.
1834{
1835 if (IsOpen()) {
1836
1837 Int_t st;
1838 if ((st = ReadBufferViaCache(buf, len))) {
1839 if (st == 2)
1840 return kTRUE;
1841 return kFALSE;
1842 }
1843
1844 ssize_t siz;
1845 Double_t start = 0;
1846
1847 if (gPerfStats) start = TTimeStamp();
1848
1849 while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
1850 ResetErrno();
1851
1852 if (siz < 0) {
1853 SysError("ReadBuffer", "error reading from file %s", GetName());
1854 return kTRUE;
1855 }
1856 if (siz != len) {
1857 Error("ReadBuffer", "error reading all requested bytes from file %s, got %ld of %d",
1858 GetName(), (Long_t)siz, len);
1859 return kTRUE;
1860 }
1861 fBytesRead += siz;
1862 fgBytesRead += siz;
1863 fReadCalls++;
1864 fgReadCalls++;
1865
1868 if (gPerfStats) {
1869 gPerfStats->FileReadEvent(this, len, start);
1870 }
1871 return kFALSE;
1872 }
1873 return kTRUE;
1874}
1875
1876////////////////////////////////////////////////////////////////////////////////
1877/// Read the nbuf blocks described in arrays pos and len.
1878///
1879/// The value pos[i] is the seek position of block i of length len[i].
1880/// Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer.
1881/// Returns kTRUE in case of failure.
1884{
1885 // called with buf=0, from TFileCacheRead to pass list of readahead buffers
1886 if (!buf) {
1887 for (Int_t j = 0; j < nbuf; j++) {
1888 if (ReadBufferAsync(pos[j], len[j])) {
1889 return kTRUE;
1890 }
1891 }
1892 return kFALSE;
1893 }
1894
1895 Int_t k = 0;
1897 TFileCacheRead *old = fCacheRead;
1898 fCacheRead = nullptr;
1899 Long64_t curbegin = pos[0];
1900 Long64_t cur;
1901 char *buf2 = nullptr;
1902 Int_t i = 0, n = 0;
1903 while (i < nbuf) {
1904 cur = pos[i]+len[i];
1906 if (cur -curbegin < fgReadaheadSize) {n++; i++; bigRead = kFALSE;}
1907 if (bigRead || (i>=nbuf)) {
1908 if (n == 0) {
1909 //if the block to read is about the same size as the read-ahead buffer
1910 //we read the block directly
1911 Seek(pos[i]);
1912 result = ReadBuffer(&buf[k], len[i]);
1913 if (result) break;
1914 k += len[i];
1915 i++;
1916 } else {
1917 //otherwise we read all blocks that fit in the read-ahead buffer
1918 Seek(curbegin);
1919 if (!buf2) buf2 = new char[fgReadaheadSize];
1920 //we read ahead
1921 Long64_t nahead = pos[i-1]+len[i-1]-curbegin;
1923 if (result) break;
1924 //now copy from the read-ahead buffer to the cache
1925 Int_t kold = k;
1926 for (Int_t j=0;j<n;j++) {
1927 memcpy(&buf[k],&buf2[pos[i-n+j]-curbegin],len[i-n+j]);
1928 k += len[i-n+j];
1929 }
1930 Int_t nok = k-kold;
1931 Long64_t extra = nahead-nok;
1932 fBytesReadExtra += extra;
1933 fBytesRead -= extra;
1934 fgBytesRead -= extra;
1935 n = 0;
1936 }
1937 curbegin = i < nbuf ? pos[i] : 0;
1938 }
1939 }
1940 if (buf2) delete [] buf2;
1941 fCacheRead = old;
1942 return result;
1943}
1944
1945////////////////////////////////////////////////////////////////////////////////
1946/// Read buffer via cache.
1947///
1948/// Returns 0 if the requested block is not in the cache, 1 in case read via
1949/// cache was successful, 2 in case read via cache failed.
1952{
1953 Long64_t off = GetRelOffset();
1954 if (fCacheRead) {
1955 Int_t st = fCacheRead->ReadBuffer(buf, off, len);
1956 if (st < 0)
1957 return 2; // failure reading
1958 else if (st == 1) {
1959 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
1960 SetOffset(off + len);
1961 return 1;
1962 }
1963 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
1964 Seek(off);
1965 } else {
1966 // if write cache is active check if data still in write cache
1967 if (fWritable && fCacheWrite) {
1968 if (fCacheWrite->ReadBuffer(buf, off, len) == 0) {
1969 SetOffset(off + len);
1970 return 1;
1971 }
1972 // fOffset might have been changed via TFileCacheWrite::ReadBuffer(), reset it
1973 SetOffset(off);
1974 }
1975 }
1976
1977 return 0;
1978}
1979
1980////////////////////////////////////////////////////////////////////////////////
1981/// Read the FREE linked list.
1982///
1983/// Every file has a linked list (fFree) of free segments.
1984/// This linked list has been written on the file via WriteFree
1985/// as a single data record.
1987void TFile::ReadFree()
1988{
1989 // Avoid problem with file corruption.
1991 fNbytesFree = 0;
1992 return;
1993 }
1994 TKey *headerfree = new TKey(fSeekFree, fNbytesFree, this);
1995 headerfree->ReadFile();
1996 char *buffer = headerfree->GetBuffer();
1997 headerfree->ReadKeyBuffer(buffer);
1998 buffer = headerfree->GetBuffer();
1999 while (1) {
2000 TFree *afree = new TFree();
2001 afree->ReadBuffer(buffer);
2002 fFree->Add(afree);
2003 if (afree->GetLast() > fEND) break;
2004 }
2005 delete headerfree;
2006}
2007
2008////////////////////////////////////////////////////////////////////////////////
2009/// The TProcessID with number pidf is read from this file.
2010///
2011/// If the object is not already entered in the gROOT list, it is added.
2014{
2015 TProcessID *pid = nullptr;
2016 TObjArray *pids = GetListOfProcessIDs();
2017 if (pidf < pids->GetSize()) pid = (TProcessID *)pids->UncheckedAt(pidf);
2018 if (pid) {
2019 pid->CheckInit();
2020 return pid;
2021 }
2022
2023 //check if fProcessIDs[uid] is set in file
2024 //if not set, read the process uid from file
2025 char pidname[32];
2026 snprintf(pidname,32,"ProcessID%d",pidf);
2027 pid = (TProcessID *)Get(pidname);
2028 if (gDebug > 0) {
2029 printf("ReadProcessID, name=%s, file=%s, pid=%zx\n",pidname,GetName(),(size_t)pid);
2030 }
2031 if (!pid) {
2032 //file->Error("ReadProcessID","Cannot find %s in file %s",pidname,file->GetName());
2033 return pid;
2034 }
2035
2036 //check that a similar pid is not already registered in fgPIDs
2038 TIter next(pidslist);
2039 TProcessID *p;
2040 bool found = false;
2041
2042 {
2044 while ((p = (TProcessID*)next())) {
2045 if (!strcmp(p->GetTitle(),pid->GetTitle())) {
2046 found = true;
2047 break;
2048 }
2049 }
2050 }
2051
2052 if (found) {
2053 delete pid;
2054 pids->AddAtAndExpand(p,pidf);
2055 p->IncrementCount();
2056 return p;
2057 }
2058
2059 pids->AddAtAndExpand(pid,pidf);
2060 pid->IncrementCount();
2061
2062 {
2064 pidslist->Add(pid);
2065 Int_t ind = pidslist->IndexOf(pid);
2066 pid->SetUniqueID((UInt_t)ind);
2067 }
2068
2069 return pid;
2070}
2071
2072
2073////////////////////////////////////////////////////////////////////////////////
2074/// Attempt to recover file if not correctly closed
2075///
2076/// The function returns the number of keys that have been recovered.
2077/// If no keys can be recovered, the file will be declared Zombie by
2078/// the calling function. This function is automatically called when
2079/// opening a file.
2080/// If the file is open in read only mode, the file is not modified.
2081/// If open in update mode and the function finds something to recover,
2082/// a new directory header is written to the file. When opening the file gain
2083/// no message from Recover will be reported.
2084/// If keys have been recovered, the file is usable and you can safely
2085/// read the corresponding objects.
2086/// If the file is not usable (a zombie), you can test for this case
2087/// with code like:
2088///
2089/// ~~~{.cpp}
2090/// TFile f("myfile.root");
2091/// if (f.IsZombie()) {<actions to take if file is unusable>}
2092/// ~~~
2093///
2094/// If the file has been recovered, the bit kRecovered is set in the TFile object in memory.
2095/// You can test if the file has been recovered with
2096///
2097/// if (f.TestBit(TFile::kRecovered)) {... the file has been recovered}
2098///
2099/// When writing TTrees to a file, it is important to save the Tree header
2100/// at regular intervals (see TTree::AutoSave). If a file containing a Tree
2101/// is recovered, the last Tree header written to the file will be used.
2102/// In this case all the entries in all the branches written before writing
2103/// the header are valid entries.
2104/// One can disable the automatic recovery procedure by setting
2105///
2106/// TFile.Recover 0
2107///
2108/// in the <em>system.rootrc</em> file.
2111{
2112 Long64_t idcur = fBEGIN;
2113
2114 Long64_t size;
2115 if ((size = GetSize()) == -1) { // NOLINT: silence clang-tidy warnings
2116 Error("Recover", "cannot stat the file %s", GetName());
2117 return 0;
2118 }
2119
2120 fEND = Long64_t(size);
2121
2122 if (fWritable && !fFree) fFree = new TList;
2123
2124 Int_t nrecov = 0;
2125
2126 while (idcur < fEND) {
2127 char header[1024];
2128 int nread = sizeof(header);
2129
2130 Seek(idcur); // NOLINT: silence clang-tidy warnings
2131 if (idcur+nread >= fEND) nread = fEND-idcur-1;
2132 if (ReadBuffer(header, nread)) { // NOLINT: silence clang-tidy warnings
2133 // ReadBuffer returns kTRUE in case of failure.
2134 Error("Recover","%s: failed to read the key data from disk at %lld.",
2135 GetName(),idcur);
2136 break;
2137 }
2138 char *buffer = header;
2139 Int_t nbytes;
2140 frombuf(buffer, &nbytes);
2141 if (!nbytes) {
2142 Error("Recover","Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes);
2143 break;
2144 }
2145 if (nbytes < 0) {
2146 idcur -= nbytes;
2147 if (fWritable) new TFree(fFree,idcur,idcur-nbytes-1);
2148 Seek(idcur);
2149 continue;
2150 }
2152 frombuf(buffer, &versionkey);
2153 Int_t objlen;
2154 frombuf(buffer, &objlen);
2155 UInt_t datime;
2156 frombuf(buffer, &datime);
2158 frombuf(buffer, &keylen);
2159 Short_t cycle;
2160 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 char classnameLen;
2171 frombuf(buffer, &classnameLen);
2172 char classname[101];
2173 if (classnameLen <= 0 || classnameLen > (Int_t)sizeof(classname))
2174 break;
2175 memcpy(classname, buffer, classnameLen);
2176 buffer += classnameLen;
2177 classname[static_cast<std::size_t>(classnameLen)] = '\0';
2178 Int_t date, time;
2180 TClass *tclass = TClass::GetClass(classname);
2181 if (seekpdir == fSeekDir && tclass && !tclass->InheritsFrom(TFile::Class())
2182 && strcmp(classname,"TBasket")) {
2183 TKey *key = new TKey(this);
2184 char *bufread = header;
2185 bool keyRead = key->ReadKeyBuffer(bufread, sizeof(header));
2186 if (!keyRead || !strcmp(key->GetName(), "StreamerInfo")) {
2187 fSeekInfo = seekkey;
2188 SafeDelete(fInfoCache);
2189 fNbytesInfo = nbytes;
2190 delete key;
2191 } else {
2192 AppendKey(key); // ownership transferred, do not to delete key here
2193 nrecov++;
2194 SetBit(kRecovered);
2195 Info("Recover", "%s, recovered key %s:%s at address %lld",GetName(),key->GetClassName(),key->GetName(),idcur);
2196 }
2197 }
2198 idcur += nbytes;
2199 }
2200 if (fWritable) {
2201 Long64_t max_file_size = Long64_t(kStartBigFile);
2202 if (max_file_size < fEND) max_file_size = fEND+1000000000;
2203 TFree *last = (TFree*)fFree->Last();
2204 if (last) {
2205 last->AddFree(fFree,fEND,max_file_size);
2206 } else {
2207 new TFree(fFree,fEND,max_file_size);
2208 }
2209 if (nrecov) Write();
2210 }
2211 return nrecov;
2212}
2213
2214////////////////////////////////////////////////////////////////////////////////
2215/// Reopen a file with a different access mode.
2216///
2217/// For example, it is possible to change from READ to
2218/// UPDATE or from NEW, CREATE, RECREATE, UPDATE to READ. Thus the
2219/// mode argument can be either "READ" or "UPDATE". The method returns
2220/// 0 in case the mode was successfully modified, 1 in case the mode
2221/// did not change (was already as requested or wrong input arguments)
2222/// and -1 in case of failure, in which case the file cannot be used
2223/// anymore. The current directory (gFile) is changed to this file.
2226{
2227 cd();
2228
2229 TString opt = mode;
2230 opt.ToUpper();
2231
2232 if (opt != "READ" && opt != "UPDATE") {
2233 Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data());
2234 return 1;
2235 }
2236
2237 if (opt == fOption || (opt == "UPDATE" && fOption == "CREATE"))
2238 return 1;
2239
2240 if (opt == "READ") {
2241 // switch to READ mode
2242
2243 // flush data still in the pipeline and close the file
2244 if (IsOpen() && IsWritable()) {
2245 WriteStreamerInfo();
2246
2247 // save directory key list and header
2248 Save();
2249
2250 TFree *f1 = (TFree*)fFree->First();
2251 if (f1) {
2252 WriteFree(); // write free segments linked list
2253 WriteHeader(); // now write file header
2254 }
2255
2256 FlushWriteCache();
2257
2258 // delete free segments from free list
2259 fFree->Delete();
2260 SafeDelete(fFree);
2261
2262 SysClose(fD);
2263 fD = -1;
2264
2265 SetWritable(kFALSE);
2266 }
2267
2268 // open in READ mode
2269 fOption = opt; // set fOption before SysOpen() for TNetFile
2270#ifndef WIN32
2271 fD = SysOpen(fRealName, O_RDONLY, 0666);
2272#else
2273 fD = SysOpen(fRealName, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
2274#endif
2275 if (fD == -1) {
2276 SysError("ReOpen", "file %s can not be opened in read mode", GetName());
2277 return -1;
2278 }
2279 SetWritable(kFALSE);
2280
2281 } else {
2282 // switch to UPDATE mode
2283
2284 // close readonly file
2285 if (IsOpen()) {
2286 SysClose(fD);
2287 fD = -1;
2288 }
2289
2290 // open in UPDATE mode
2291 fOption = opt; // set fOption before SysOpen() for TNetFile
2292#ifndef WIN32
2293 fD = SysOpen(fRealName, O_RDWR | O_CREAT, 0666);
2294#else
2295 fD = SysOpen(fRealName, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
2296#endif
2297 if (fD == -1) {
2298 SysError("ReOpen", "file %s can not be opened in update mode", GetName());
2299 return -1;
2300 }
2301 SetWritable(kTRUE);
2302
2303 fFree = new TList;
2304 if (fSeekFree > fBEGIN)
2305 ReadFree();
2306 else
2307 Warning("ReOpen","file %s probably not closed, cannot read free segments", GetName());
2308 }
2309
2310 return 0;
2311}
2312
2313////////////////////////////////////////////////////////////////////////////////
2314/// Set position from where to start reading.
2317{
2318 switch (pos) {
2319 case kBeg:
2320 fOffset = offset + fArchiveOffset;
2321 break;
2322 case kCur:
2323 fOffset += offset;
2324 break;
2325 case kEnd:
2326 // this option is not used currently in the ROOT code
2327 if (fArchiveOffset)
2328 Error("SetOffset", "seeking from end in archive is not (yet) supported");
2329 fOffset = fEND + offset; // is fEND really EOF or logical EOF?
2330 break;
2331 }
2332}
2333
2334////////////////////////////////////////////////////////////////////////////////
2335/// Seek to a specific position in the file. Pos it either kBeg, kCur or kEnd.
2338{
2339 int whence = 0;
2340 switch (pos) {
2341 case kBeg:
2342 whence = SEEK_SET;
2343 offset += fArchiveOffset;
2344 break;
2345 case kCur:
2346 whence = SEEK_CUR;
2347 break;
2348 case kEnd:
2349 whence = SEEK_END;
2350 // this option is not used currently in the ROOT code
2351 if (fArchiveOffset)
2352 Error("Seek", "seeking from end in archive is not (yet) supported");
2353 break;
2354 }
2356 if ((retpos = SysSeek(fD, offset, whence)) < 0) // NOLINT: silence clang-tidy warnings
2357 SysError("Seek", "cannot seek to position %lld in file %s, retpos=%lld",
2358 offset, GetName(), retpos);
2359
2360 // used by TFileCacheRead::ReadBuffer()
2361 fOffset = retpos;
2362}
2363
2364////////////////////////////////////////////////////////////////////////////////
2365/// See comments for function SetCompressionSettings
2366///
2369{
2371 if (fCompress < 0) {
2373 } else {
2374 int level = fCompress % 100;
2375 fCompress = 100 * algorithm + level;
2376 }
2377}
2378
2379////////////////////////////////////////////////////////////////////////////////
2380/// See comments for function SetCompressionSettings
2383{
2384 if (level < 0) level = 0;
2385 if (level > 99) level = 99;
2386 if (fCompress < 0) {
2387 // if the algorithm is not defined yet use 0 as a default
2388 fCompress = level;
2389 } else {
2390 int algorithm = fCompress / 100;
2392 fCompress = 100 * algorithm + level;
2393 }
2394}
2395
2396////////////////////////////////////////////////////////////////////////////////
2397/// Used to specify the compression level and algorithm.
2398///
2399/// See the TFile constructor for the details.
2402{
2403 fCompress = settings;
2404}
2405
2406////////////////////////////////////////////////////////////////////////////////
2407/// Set a pointer to the read cache.
2408///
2409/// <b>This relinquishes ownership</b> of the previous cache, so if you do not
2410/// already have a pointer to the previous cache (and there was a previous
2411/// cache), you ought to retrieve (and delete it if needed) using:
2412///
2413/// TFileCacheRead *older = myfile->GetCacheRead();
2414///
2415/// The action specifies how to behave when detaching a cache from the
2416/// the TFile. If set to (default) kDisconnect, the contents of the cache
2417/// will be flushed when it is removed from the file, and it will disconnect
2418/// the cache object from the file. In almost all cases, this is what you want.
2419/// If you want to disconnect the cache temporarily from this tree and re-attach
2420/// later to the same fil, you can set action to kDoNotDisconnect. This will allow
2421/// things like prefetching to continue in the background while it is no longer the
2422/// default cache for the TTree. Except for a few expert use cases, kDisconnect is
2423/// likely the correct setting.
2424///
2425/// WARNING: if action=kDoNotDisconnect, you MUST delete the cache before TFile.
2426///
2429{
2430 if (tree) {
2431 if (cache) fCacheReadMap->Add(tree, cache);
2432 else {
2433 // The only addition to fCacheReadMap is via an interface that takes
2434 // a TFileCacheRead* so the C-cast is safe.
2435 TFileCacheRead* tpf = (TFileCacheRead *)fCacheReadMap->GetValue(tree);
2436 fCacheReadMap->Remove(tree);
2437 if (tpf && (tpf->GetFile() == this) && (action != kDoNotDisconnect)) tpf->SetFile(0, action);
2438 }
2439 }
2440 if (cache) cache->SetFile(this, action);
2441 else if (!tree && fCacheRead && (action != kDoNotDisconnect)) fCacheRead->SetFile(0, action);
2442 // For backward compatibility the last Cache set is the default cache.
2443 fCacheRead = cache;
2444}
2445
2446////////////////////////////////////////////////////////////////////////////////
2447/// Set a pointer to the write cache.
2448///
2449/// If file is null the existing write cache is deleted.
2452{
2453 if (!cache && fCacheWrite) delete fCacheWrite;
2454 fCacheWrite = cache;
2455}
2456
2457////////////////////////////////////////////////////////////////////////////////
2458/// Return the size in bytes of the file header.
2460Int_t TFile::Sizeof() const
2461{
2462 return 0;
2463}
2464
2465////////////////////////////////////////////////////////////////////////////////
2466/// Stream a TFile object.
2469{
2470 if (b.IsReading()) {
2471 b.ReadVersion(); //Version_t v = b.ReadVersion();
2472 } else {
2473 b.WriteVersion(TFile::IsA());
2474 }
2475}
2476
2477////////////////////////////////////////////////////////////////////////////////
2478/// Increment statistics for buffer sizes of objects in this file.
2481{
2482 fWritten++;
2483 fSumBuffer += double(bufsize);
2484 fSum2Buffer += double(bufsize) * double(bufsize); // avoid reaching MAXINT for temporary
2485}
2486
2487////////////////////////////////////////////////////////////////////////////////
2488/// Write memory objects to this file.
2489///
2490/// Loop on all objects in memory (including subdirectories).
2491/// A new key is created in the KEYS linked list for each object.
2492/// The list of keys is then saved on the file (via WriteKeys)
2493/// as a single data record.
2494/// For values of opt see TObject::Write().
2495/// The directory header info is rewritten on the directory header record.
2496/// The linked list of FREE segments is written.
2497/// The file header is written (bytes 1->fBEGIN).
2499Int_t TFile::Write(const char *, Int_t opt, Int_t bufsize)
2500{
2501 if (!IsWritable()) {
2502 if (!TestBit(kWriteError)) {
2503 // Do not print the warning if we already had a SysError.
2504 Warning("Write", "file %s not opened in write mode", GetName());
2505 }
2506 return 0;
2507 }
2508
2509 if (gDebug) {
2510 if (!GetTitle() || strlen(GetTitle()) == 0)
2511 Info("Write", "writing name = %s", GetName());
2512 else
2513 Info("Write", "writing name = %s title = %s", GetName(), GetTitle());
2514 }
2515
2516 fMustFlush = kFALSE;
2517 Int_t nbytes = TDirectoryFile::Write(0, opt, bufsize); // Write directory tree
2518 WriteStreamerInfo();
2519 WriteFree(); // Write free segments linked list
2520 WriteHeader(); // Now write file header
2521 fMustFlush = kTRUE;
2522
2523 return nbytes;
2524}
2525
2526////////////////////////////////////////////////////////////////////////////////
2527/// One can not save a const TDirectory object.
2529Int_t TFile::Write(const char *n, Int_t opt, Int_t bufsize) const
2530{
2531 Error("Write const","A const TFile object should not be saved. We try to proceed anyway.");
2532 return const_cast<TFile*>(this)->Write(n, opt, bufsize);
2533}
2534
2535////////////////////////////////////////////////////////////////////////////////
2536/// Write a buffer to the file. This is the basic low level write operation.
2537/// Returns kTRUE in case of failure.
2539Bool_t TFile::WriteBuffer(const char *buf, Int_t len)
2540{
2541 if (IsOpen() && fWritable) {
2542
2543 Int_t st;
2544 if ((st = WriteBufferViaCache(buf, len))) {
2545 if (st == 2)
2546 return kTRUE;
2547 return kFALSE;
2548 }
2549
2550 ssize_t siz;
2552 while ((siz = SysWrite(fD, buf, len)) < 0 && GetErrno() == EINTR) // NOLINT: silence clang-tidy warnings
2553 ResetErrno(); // NOLINT: silence clang-tidy warnings
2555 if (siz < 0) {
2556 // Write the system error only once for this file
2557 SetBit(kWriteError); SetWritable(kFALSE);
2558 SysError("WriteBuffer", "error writing to file %s (%ld)", GetName(), (Long_t)siz);
2559 return kTRUE;
2560 }
2561 if (siz != len) {
2562 SetBit(kWriteError);
2563 Error("WriteBuffer", "error writing all requested bytes to file %s, wrote %ld of %d",
2564 GetName(), (Long_t)siz, len);
2565 return kTRUE;
2566 }
2567 fBytesWrite += siz;
2568 fgBytesWrite += siz;
2569
2572
2573 return kFALSE;
2574 }
2575 return kTRUE;
2576}
2577
2578////////////////////////////////////////////////////////////////////////////////
2579/// Write buffer via cache. Returns 0 if cache is not active, 1 in case
2580/// write via cache was successful, 2 in case write via cache failed.
2582Int_t TFile::WriteBufferViaCache(const char *buf, Int_t len)
2583{
2584 if (!fCacheWrite) return 0;
2585
2586 Int_t st;
2587 Long64_t off = GetRelOffset();
2588 if ((st = fCacheWrite->WriteBuffer(buf, off, len)) < 0) {
2589 SetBit(kWriteError);
2590 Error("WriteBuffer", "error writing to cache");
2591 return 2;
2592 }
2593 if (st > 0) {
2594 // fOffset might have been changed via TFileCacheWrite::WriteBuffer(), reset it
2595 Seek(off + len);
2596 return 1;
2597 }
2598 return 0;
2599}
2600
2601////////////////////////////////////////////////////////////////////////////////
2602/// Write FREE linked list on the file.
2603/// The linked list of FREE segments (fFree) is written as a single data
2604/// record.
2606void TFile::WriteFree()
2607{
2608 //*-* Delete old record if it exists
2609 if (fSeekFree != 0) {
2610 MakeFree(fSeekFree, fSeekFree + fNbytesFree -1);
2611 }
2612
2614
2615 auto createKey = [this]() {
2616 Int_t nbytes = 0;
2617 TFree *afree;
2618 TIter next (fFree);
2619 while ((afree = (TFree*) next())) {
2620 nbytes += afree->Sizeof();
2621 }
2622 if (!nbytes) return (TKey*)nullptr;
2623
2624 TKey *key = new TKey(fName,fTitle,IsA(),nbytes,this);
2625
2626 if (key->GetSeekKey() == 0) {
2627 delete key;
2628 return (TKey*)nullptr;
2629 }
2630 return key;
2631 };
2632
2633 TKey *key = createKey();
2634 if (!key) return;
2635
2636 if (!largeFile && (fEND > TFile::kStartBigFile)) {
2637 // The free block list is large enough to bring the file to larger
2638 // than 2Gb, the references/offsets are now 64bits in the output
2639 // so we need to redo the calculation since the list of free block
2640 // information will not fit in the original size.
2641 key->Delete();
2642 delete key;
2643
2644 key = createKey();
2645 if (!key) return;
2646 }
2647
2648 Int_t nbytes = key->GetObjlen();
2649 char *buffer = key->GetBuffer();
2650 char *start = buffer;
2651
2652 TIter next (fFree);
2653 TFree *afree;
2654 while ((afree = (TFree*) next())) {
2655 // We could 'waste' time here and double check that
2656 // (buffer+afree->Sizeof() < (start+nbytes)
2657 afree->FillBuffer(buffer);
2658 }
2659 auto actualBytes = buffer-start;
2660 if ( actualBytes != nbytes ) {
2661 if (actualBytes < nbytes) {
2662 // Most likely one of the 'free' segment was used to store this
2663 // TKey, so we had one less TFree to store than we planned.
2664 memset(buffer,0,nbytes-actualBytes);
2665 } else {
2666 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);
2667 }
2668 }
2669 fNbytesFree = key->GetNbytes();
2670 fSeekFree = key->GetSeekKey();
2671 key->WriteFile();
2672 delete key;
2673}
2674
2675////////////////////////////////////////////////////////////////////////////////
2676/// Write File Header.
2678void TFile::WriteHeader()
2679{
2680 SafeDelete(fInfoCache);
2681 TFree *lastfree = (TFree*)fFree->Last();
2682 if (lastfree) fEND = lastfree->GetFirst();
2683 const char *root = "root";
2684 char *psave = new char[fBEGIN];
2685 char *buffer = psave;
2686 Int_t nfree = fFree->GetSize();
2687 memcpy(buffer, root, 4); buffer += 4;
2688 Int_t version = fVersion;
2689 if (version <1000000 && fEND > kStartBigFile) {version += 1000000; fUnits = 8;}
2690 tobuf(buffer, version);
2691 tobuf(buffer, (Int_t)fBEGIN);
2692 if (version < 1000000) {
2693 tobuf(buffer, (Int_t)fEND);
2694 tobuf(buffer, (Int_t)fSeekFree);
2695 tobuf(buffer, fNbytesFree);
2696 tobuf(buffer, nfree);
2697 tobuf(buffer, fNbytesName);
2698 tobuf(buffer, fUnits);
2699 tobuf(buffer, fCompress);
2700 tobuf(buffer, (Int_t)fSeekInfo);
2701 tobuf(buffer, fNbytesInfo);
2702 } else {
2703 tobuf(buffer, fEND);
2704 tobuf(buffer, fSeekFree);
2705 tobuf(buffer, fNbytesFree);
2706 tobuf(buffer, nfree);
2707 tobuf(buffer, fNbytesName);
2708 tobuf(buffer, fUnits);
2709 tobuf(buffer, fCompress);
2710 tobuf(buffer, fSeekInfo);
2711 tobuf(buffer, fNbytesInfo);
2712 }
2713 if (TestBit(kReproducible))
2714 TUUID("00000000-0000-0000-0000-000000000000").FillBuffer(buffer);
2715 else
2716 fUUID.FillBuffer(buffer);
2717 Int_t nbytes = buffer - psave;
2718 Seek(0); // NOLINT: silence clang-tidy warnings
2719 WriteBuffer(psave, nbytes); // NOLINT: silence clang-tidy warnings
2720 Flush(); // NOLINT: silence clang-tidy warnings, Intentionally not conditional on fMustFlush, this is the 'obligatory' flush.
2721 delete [] psave;
2722}
2723
2724////////////////////////////////////////////////////////////////////////////////
2725/// Generate source code necessary to access the objects stored in the file.
2726///
2727/// Generate code in directory dirname for all classes specified in
2728/// argument classes If classes = "*" (default and currently the
2729/// only supported value), the function generates an include file
2730/// for each class in the StreamerInfo list for which a TClass
2731/// object does not exist.
2732///
2733/// The code generated includes:
2734/// - <em>dirnameProjectHeaders.h</em>, which contains one `#include` statement per generated header file
2735/// - <em>dirnameProjectSource.cxx</em>,which contains all the constructors and destructors implementation.
2736/// and one header per class that is not nested inside another class.
2737/// The header file name is the fully qualified name of the class after all the special characters
2738/// "<>,:" are replaced by underscored. For example for std::pair<edm::Vertex,int> the file name is
2739/// pair_edm__Vertex_int_.h
2740///
2741/// In the generated classes, map, multimap when the first template parameter is a class
2742/// are replaced by a vector of pair. set and multiset when the tempalte parameter
2743/// is a class are replaced by a vector. This is required since we do not have the
2744/// code needed to order and/or compare the object of the classes.
2745/// This is a quick explanation of the options available:
2746/// Option | Details
2747/// -------|--------
2748/// new (default) | A new directory dirname is created. If dirname already exist, an error message is printed and the function returns.
2749/// 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.
2750/// 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".
2751/// genreflex | Use genreflex rather than rootcling to generate the dictionary.
2752/// 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).
2753///
2754/// If, in addition to one of the 3 above options, the option "+" is specified,
2755/// the function will generate:
2756/// - a script called MAKEP to build the shared lib
2757/// - a dirnameLinkDef.h file
2758/// - rootcling will be run to generate a dirnameProjectDict.cxx file
2759/// - dirnameProjectDict.cxx will be compiled with the current options in compiledata.h
2760/// - a shared lib dirname.so will be created.
2761/// If the option "++" is specified, the generated shared lib is dynamically
2762/// linked with the current executable module.
2763/// If the option "+" and "nocompile" are specified, the utility files are generated
2764/// as in the option "+" but they are not executed.
2765/// Example:
2766/// file.MakeProject("demo","*","recreate++");
2767/// - creates a new directory demo unless it already exist
2768/// - clear the previous directory content
2769/// - generate the xxx.h files for all classes xxx found in this file
2770/// and not yet known to the Cling dictionary.
2771/// - creates the build script MAKEP
2772/// - creates a LinkDef.h file
2773/// - runs rootcling generating demoProjectDict.cxx
2774/// - compiles demoProjectDict.cxx into demoProjectDict.o
2775/// - generates a shared lib demo.so
2776/// - dynamically links the shared lib demo.so to the executable
2777/// If only the option "+" had been specified, one can still link the
2778/// shared lib to the current executable module with:
2779///
2780/// gSystem->load("demo/demo.so");
2781///
2782/// The following feature is not yet enabled:
2783/// One can restrict the list of classes to be generated by using expressions like:
2784///
2785/// classes = "Ali*" generate code only for classes starting with Ali
2786/// classes = "myClass" generate code for class MyClass only.
2787///
2789void TFile::MakeProject(const char *dirname, const char * /*classes*/,
2790 Option_t *option)
2791{
2792 TString opt = option;
2793 opt.ToLower();
2794
2795 void *dir = gSystem->OpenDirectory(dirname);
2797
2798 if (opt.Contains("update")) {
2799 // check that directory exist, if not create it
2800 if (!dir) {
2802 }
2803
2804 } else if (opt.Contains("recreate")) {
2805 // check that directory exist, if not create it
2806 if (!dir) {
2807 if (gSystem->mkdir(dirname) < 0) {
2808 Error("MakeProject","cannot create directory '%s'",dirname);
2809 return;
2810 }
2811 }
2812 // clear directory
2813 while (dir) {
2814 const char *afile = gSystem->GetDirEntry(dir);
2815 if (!afile) break;
2816 if (strcmp(afile,".") == 0) continue;
2817 if (strcmp(afile,"..") == 0) continue;
2818 dirpath.Form("%s/%s",dirname,afile);
2820 }
2821
2822 } else {
2823 // new is assumed
2824 // if directory already exist, print error message and return
2825 if (dir) {
2826 Error("MakeProject","cannot create directory %s, already existing",dirname);
2827 gSystem->FreeDirectory(dir);
2828 return;
2829 }
2830 if (gSystem->mkdir(dirname) < 0) {
2831 Error("MakeProject","cannot create directory '%s'",dirname);
2832 return;
2833 }
2834 }
2835 if (dir) {
2836 gSystem->FreeDirectory(dir);
2837 }
2838
2839 Bool_t genreflex = opt.Contains("genreflex");
2840
2841 // we are now ready to generate the classes
2842 // loop on all TStreamerInfo
2843 TList *filelist = (TList*)GetStreamerInfoCache();
2844 if (filelist) filelist = (TList*)filelist->Clone();
2845 if (!filelist) {
2846 Error("MakeProject","file %s has no StreamerInfo", GetName());
2847 return;
2848 }
2849
2851 if (clean_dirname[clean_dirname.Length()-1]=='/') {
2852 clean_dirname.Remove(clean_dirname.Length()-1);
2853 } else if (clean_dirname[clean_dirname.Length()-1]=='\\') {
2854 clean_dirname.Remove(clean_dirname.Length()-1);
2855 if (clean_dirname[clean_dirname.Length()-1]=='\\') {
2856 clean_dirname.Remove(clean_dirname.Length()-1);
2857 }
2858 }
2860 if (subdirname == "") {
2861 Error("MakeProject","Directory name must not be empty.");
2862 return;
2863 }
2864
2865 // Start the source file
2866 TString spath; spath.Form("%s/%sProjectSource.cxx",clean_dirname.Data(),subdirname.Data());
2867 FILE *sfp = fopen(spath.Data(),"w");
2868 if (!sfp) {
2869 Error("MakeProject","Unable to create the source file %s.",spath.Data());
2870 return;
2871 }
2872 fprintf(sfp, "namespace std {}\nusing namespace std;\n");
2873 fprintf(sfp, "#include \"%sProjectHeaders.h\"\n\n",subdirname.Data() );
2874 if (!genreflex) fprintf(sfp, "#include \"%sLinkDef.h\"\n\n",subdirname.Data() );
2875 fprintf(sfp, "#include \"%sProjectDict.cxx\"\n\n",subdirname.Data() );
2876 fprintf(sfp, "struct DeleteObjectFunctor {\n");
2877 fprintf(sfp, " template <typename T>\n");
2878 fprintf(sfp, " void operator()(const T *ptr) const {\n");
2879 fprintf(sfp, " delete ptr;\n");
2880 fprintf(sfp, " }\n");
2881 fprintf(sfp, " template <typename T, typename Q>\n");
2882 fprintf(sfp, " void operator()(const std::pair<T,Q> &) const {\n");
2883 fprintf(sfp, " // Do nothing\n");
2884 fprintf(sfp, " }\n");
2885 fprintf(sfp, " template <typename T, typename Q>\n");
2886 fprintf(sfp, " void operator()(const std::pair<T,Q*> &ptr) const {\n");
2887 fprintf(sfp, " delete ptr.second;\n");
2888 fprintf(sfp, " }\n");
2889 fprintf(sfp, " template <typename T, typename Q>\n");
2890 fprintf(sfp, " void operator()(const std::pair<T*,Q> &ptr) const {\n");
2891 fprintf(sfp, " delete ptr.first;\n");
2892 fprintf(sfp, " }\n");
2893 fprintf(sfp, " template <typename T, typename Q>\n");
2894 fprintf(sfp, " void operator()(const std::pair<T*,Q*> &ptr) const {\n");
2895 fprintf(sfp, " delete ptr.first;\n");
2896 fprintf(sfp, " delete ptr.second;\n");
2897 fprintf(sfp, " }\n");
2898 fprintf(sfp, "};\n\n");
2899 fclose( sfp );
2900
2901 // loop on all TStreamerInfo classes to check for empty classes
2902 // and enums listed either as data member or template parameters,
2903 // and filter out 'duplicates' classes/streamerInfos.
2907 TList *list = new TList();
2908 while ((info = (TStreamerInfo*)flnext())) {
2909 if (info->IsA() != TStreamerInfo::Class()) {
2910 continue;
2911 }
2912 if (strstr(info->GetName(),"@@")) {
2913 // Skip schema evolution support streamerInfo
2914 continue;
2915 }
2916 TClass *cl = TClass::GetClass(info->GetName());
2917 if (cl) {
2918 if (cl->HasInterpreterInfo()) continue; // skip known classes
2919 }
2920 // Find and use the proper rules for the TStreamerInfos.
2922 TIter enext( info->GetElements() );
2925 if (cl && cl->GetSchemaRules()) {
2926 rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
2927 }
2928 while( (el=(TStreamerElement*)enext()) ) {
2929 for(auto rule : rules) {
2930 if( rule->IsRenameRule() || rule->IsAliasRule() )
2931 continue;
2932 // Check whether this is an 'attribute' rule.
2933 if ( rule->HasTarget( el->GetName()) && rule->GetAttributes()[0] != 0 ) {
2934 TString attr( rule->GetAttributes() );
2935 attr.ToLower();
2936 if (attr.Contains("owner")) {
2937 if (attr.Contains("notowner")) {
2939 } else {
2941 }
2942 }
2943 }
2944 }
2946 }
2947 TVirtualStreamerInfo *alternate = (TVirtualStreamerInfo*)list->FindObject(info->GetName());
2948 if (alternate) {
2949 if ((info->GetClass() && info->GetClassVersion() == info->GetClass()->GetClassVersion())
2950 || (info->GetClassVersion() > alternate->GetClassVersion()) ) {
2951 list->AddAfter(alternate, info);
2952 list->Remove(alternate);
2953 } // otherwise ignore this info as not being the official one.
2954 } else {
2955 list->Add(info);
2956 }
2957 }
2958 // Now transfer the new StreamerInfo onto the main list and
2959 // to the owning list.
2961 while ((info = (TStreamerInfo*)nextextra())) {
2962 list->Add(info);
2963 filelist->Add(info);
2964 }
2965
2966 // loop on all TStreamerInfo classes
2967 TIter next(list);
2968 Int_t ngener = 0;
2969 while ((info = (TStreamerInfo*)next())) {
2970 if (info->IsA() != TStreamerInfo::Class()) {
2971 continue;
2972 }
2973 if (info->GetClassVersion()==-4) continue; // Skip outer level namespace
2974 TIter subnext(list);
2977 Int_t len = strlen(info->GetName());
2978 while ((subinfo = (TStreamerInfo*)subnext())) {
2979 if (subinfo->IsA() != TStreamerInfo::Class()) {
2980 continue;
2981 }
2982 if (strncmp(info->GetName(),subinfo->GetName(),len)==0) {
2983 // The 'sub' StreamerInfo start with the main StreamerInfo name,
2984 // it subinfo is likely to be a nested class.
2985 const Int_t sublen = strlen(subinfo->GetName());
2986 if ( (sublen > len) && subinfo->GetName()[len+1]==':'
2987 && !subClasses.FindObject(subinfo->GetName()) /* We need to insure uniqueness */)
2988 {
2989 subClasses.Add(subinfo);
2990 }
2991 }
2992 }
2993 ngener += info->GenerateHeaderFile(clean_dirname.Data(),&subClasses,&extrainfos);
2994 subClasses.Clear("nodelete");
2995 }
2996 extrainfos.Clear("nodelete"); // We are done with this list.
2997
2998 TString path;
2999 path.Form("%s/%sProjectHeaders.h",clean_dirname.Data(),subdirname.Data());
3000 FILE *allfp = fopen(path,"a");
3001 if (!allfp) {
3002 Error("MakeProject","Cannot open output file:%s\n",path.Data());
3003 } else {
3004 fprintf(allfp,"#include \"%sProjectInstances.h\"\n", subdirname.Data());
3005 fclose(allfp);
3006 }
3007
3008 printf("MakeProject has generated %d classes in %s\n",ngener,clean_dirname.Data());
3009
3010 // generate the shared lib
3011 if (!opt.Contains("+")) {
3012 delete list;
3013 filelist->Delete();
3014 delete filelist;
3015 return;
3016 }
3017
3018 // Makefiles files
3019 FILE *fpMAKE = nullptr;
3020 // Create the MAKEP file by looping on all *.h files
3021 // delete MAKEP if it already exists
3022#ifdef WIN32
3023 path.Form("%s/makep.cmd",clean_dirname.Data());
3024#else
3025 path.Form("%s/MAKEP",clean_dirname.Data());
3026#endif
3027#ifdef R__WINGCC
3028 fpMAKE = fopen(path,"wb");
3029#else
3030 fpMAKE = fopen(path,"w");
3031#endif
3032 if (!fpMAKE) {
3033 Error("MakeProject", "cannot open file %s", path.Data());
3034 delete list;
3035 filelist->Delete();
3036 delete filelist;
3037 return;
3038 }
3039
3040 // Add rootcling/genreflex statement generating ProjectDict.cxx
3041 FILE *ifp = nullptr;
3042 path.Form("%s/%sProjectInstances.h",clean_dirname.Data(),subdirname.Data());
3043#ifdef R__WINGCC
3044 ifp = fopen(path,"wb");
3045#else
3046 ifp = fopen(path,"w");
3047#endif
3048 if (!ifp) {
3049 Error("MakeProject", "cannot open path file %s", path.Data());
3050 delete list;
3051 filelist->Delete();
3052 delete filelist;
3053 fclose(fpMAKE);
3054 return;
3055 }
3056
3057 if (genreflex) {
3058 fprintf(fpMAKE,"genreflex %sProjectHeaders.h -o %sProjectDict.cxx --comments --iocomments %s ",subdirname.Data(),subdirname.Data(),gSystem->GetIncludePath());
3059 path.Form("%s/%sSelection.xml",clean_dirname.Data(),subdirname.Data());
3060 } else {
3061 fprintf(fpMAKE,"rootcling -v1 -f %sProjectDict.cxx %s ", subdirname.Data(), gSystem->GetIncludePath());
3062 path.Form("%s/%sLinkDef.h",clean_dirname.Data(),subdirname.Data());
3063 }
3064
3065 // Create the LinkDef.h or xml selection file by looping on all *.h files
3066 // replace any existing file.
3067#ifdef R__WINGCC
3068 FILE *fp = fopen(path,"wb");
3069#else
3070 FILE *fp = fopen(path,"w");
3071#endif
3072 if (!fp) {
3073 Error("MakeProject", "cannot open path file %s", path.Data());
3074 delete list;
3075 filelist->Delete();
3076 delete filelist;
3077 fclose(fpMAKE);
3078 fclose(ifp);
3079 return;
3080 }
3081 if (genreflex) {
3082 fprintf(fp,"<lcgdict>\n");
3083 fprintf(fp,"\n");
3084 } else {
3085 fprintf(fp,"#ifdef __CLING__\n");
3086 fprintf(fp,"\n");
3087 }
3088
3089 TString tmp;
3092 next.Reset();
3093 while ((info = (TStreamerInfo*)next())) {
3094 if (info->IsA() != TStreamerInfo::Class()) {
3095 continue;
3096 }
3097 if (strncmp(info->GetName(), "auto_ptr<", std::char_traits<char>::length("auto_ptr<")) == 0) {
3098 continue;
3099 }
3100 TClass *cl = TClass::GetClass(info->GetName());
3101 if (cl) {
3102 if (cl->HasInterpreterInfo()) continue; // skip known classes
3103 if (cl->GetSchemaRules()) {
3104 auto rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
3106 for(auto rule : rules) {
3107 strrule.Clear();
3108 if (genreflex) {
3109 rule->AsString(strrule,"x");
3110 strrule.Append("\n");
3111 if ( selections.Index(strrule) == kNPOS ) {
3112 selections.Append(strrule);
3113 }
3114 } else {
3115 rule->AsString(strrule);
3116 if (strncmp(strrule.Data(),"type=",5)==0) {
3117 strrule.Remove(0,5);
3118 }
3119 fprintf(fp,"#pragma %s;\n",strrule.Data());
3120 }
3121 }
3122 }
3123
3124 }
3125 if ((info->GetClass() && info->GetClass()->GetCollectionType()) || TClassEdit::IsSTLCont(info->GetName())) {
3126 std::vector<std::string> inside;
3127 int nestedLoc;
3129 Int_t stlkind = TClassEdit::STLKind(inside[0]);
3130 TClass *key = TClass::GetClass(inside[1].c_str());
3131 if (key) {
3132 TString what;
3133 switch ( stlkind ) {
3134 case ROOT::kSTLmap:
3135 case ROOT::kSTLmultimap:
3136 if (TClass::GetClass(inside[1].c_str())) {
3137 what = "std::pair<";
3138 what += TMakeProject::UpdateAssociativeToVector( inside[1].c_str() );
3139 what += ",";
3140 what += TMakeProject::UpdateAssociativeToVector( inside[2].c_str() );
3141 if (what[what.Length()-1]=='>') {
3142 what += " >";
3143 } else {
3144 what += ">";
3145 }
3146 if (genreflex) {
3147 tmp.Form("<class name=\"%s\" />\n",what.Data());
3148 if ( selections.Index(tmp) == kNPOS ) {
3149 selections.Append(tmp);
3150 }
3151 tmp.Form("template class %s;\n",what.Data());
3152 if ( instances.Index(tmp) == kNPOS ) {
3153 instances.Append(tmp);
3154 }
3155 } else {
3156 what.ReplaceAll("std::","");
3158 if (!paircl || !paircl->HasInterpreterInfo()) {
3159 fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
3160 }
3161 }
3162 break;
3163 }
3164 default:
3165 if (TClassEdit::IsStdPair(key->GetName())) {
3166 if (genreflex) {
3167 tmp.Form("<class name=\"%s\" />\n",key->GetName());
3168 if ( selections.Index(tmp) == kNPOS ) {
3169 selections.Append(tmp);
3170 }
3171 tmp.Form("template class %s;\n",key->GetName());
3172 if ( instances.Index(tmp) == kNPOS ) {
3173 instances.Append(tmp);
3174 }
3175 } else {
3176 what.ReplaceAll("std::","");
3177 fprintf(fp,"#pragma link C++ class %s+;\n",key->GetName());
3178 }
3179 }
3180 break;
3181 }
3182 }
3183 continue;
3184 }
3185 {
3187 if (genreflex) {
3188 tmp.Form("<class name=\"%s\" />\n",what.Data());
3189 if ( selections.Index(tmp) == kNPOS ) {
3190 selections.Append(tmp);
3191 }
3192 if (what[what.Length()-1] == '>') {
3193 tmp.Form("template class %s;\n",what.Data());
3194 if ( instances.Index(tmp) == kNPOS ) {
3195 instances.Append(tmp);
3196 }
3197 }
3198 } else {
3199 what.ReplaceAll("std::","");
3200 fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
3201 }
3202 }
3203 if (genreflex) {
3204 // Also request the dictionary for the STL container used as members ...
3205 TIter eliter( info->GetElements() );
3207 while( (element = (TStreamerElement*)eliter() ) ) {
3208 if (element->GetClass() && !element->GetClass()->IsLoaded() && element->GetClass()->GetCollectionProxy()) {
3210 tmp.Form("<class name=\"%s\" />\n",what.Data());
3211 if ( selections.Index(tmp) == kNPOS ) {
3212 selections.Append(tmp);
3213 }
3214 tmp.Form("template class %s;\n",what.Data());
3215 if ( instances.Index(tmp) == kNPOS ) {
3216 instances.Append(tmp);
3217 }
3218 }
3219 }
3220 }
3221 }
3222 if (genreflex) {
3223 fprintf(ifp,"#ifndef PROJECT_INSTANCES_H\n");
3224 fprintf(ifp,"#define PROJECT_INSTANCES_H\n");
3225 fprintf(ifp,"%s",instances.Data());
3226 fprintf(ifp,"#endif\n");
3227 fprintf(fp,"%s",selections.Data());
3228 fprintf(fp,"</lcgdict>\n");
3229 } else {
3230 fprintf(fp,"#endif\n");
3231 }
3232 fclose(fp);
3233 fclose(ifp);
3234
3235 // add compilation line
3237
3239 TString sources = TString::Format("%sProjectSource.cxx ", sdirname.Data());
3240 cmd.ReplaceAll("$SourceFiles",sources.Data());
3241 TString object = TString::Format("%sProjectSource.", sdirname.Data());
3242 object.Append( gSystem->GetObjExt() );
3243 cmd.ReplaceAll("$ObjectFiles", object.Data());
3244 cmd.ReplaceAll("$IncludePath",TString(gSystem->GetIncludePath()) + " -I" + clean_dirname.Data());
3245 cmd.ReplaceAll("$SharedLib",sdirname+"."+gSystem->GetSoExt());
3246 cmd.ReplaceAll("$LinkedLibs",gSystem->GetLibraries("","SDL"));
3247 cmd.ReplaceAll("$LibName",sdirname);
3248 cmd.ReplaceAll("$BuildDir",".");
3249 cmd.ReplaceAll("$RPath", "-Wl,-rpath," + gROOT->GetSharedLibDir());
3250 TString sOpt;
3252 if (rootbuild.Index("debug",0,TString::kIgnoreCase)==kNPOS) {
3254 } else {
3256 }
3257#if defined(_MSC_VER) && defined(_DEBUG)
3258 // if ROOT is build in debug mode, ACLiC must also build in debug mode
3259 // for compatibility reasons
3261#endif
3262 cmd.ReplaceAll("$Opt", sOpt);
3263
3264 if (genreflex) {
3265 fprintf(fpMAKE,"-s %sSelection.xml \n",subdirname.Data());
3266 } else {
3267 fprintf(fpMAKE,"%sProjectHeaders.h ",subdirname.Data());
3268 fprintf(fpMAKE,"%sLinkDef.h \n",subdirname.Data());
3269 }
3270
3271 fprintf(fpMAKE,"%s\n",cmd.Data());
3272
3273 printf("%s/MAKEP file has been generated\n", clean_dirname.Data());
3274
3275 fclose(fpMAKE);
3276
3277
3278 if (!opt.Contains("nocompilation")) {
3279 // now execute the generated script compiling and generating the shared lib
3280 path = gSystem->WorkingDirectory();
3282#ifndef WIN32
3283 gSystem->Exec("chmod +x MAKEP");
3284 int res = !gSystem->Exec("./MAKEP");
3285#else
3286 // not really needed for Windows but it would work both both Unix and NT
3287 chmod("makep.cmd",00700);
3288 int res = !gSystem->Exec("MAKEP");
3289#endif
3290 gSystem->ChangeDirectory(path);
3291 path.Form("%s/%s.%s",clean_dirname.Data(),subdirname.Data(),gSystem->GetSoExt());
3292 if (res) printf("Shared lib %s has been generated\n",path.Data());
3293
3294 //dynamically link the generated shared lib
3295 if (opt.Contains("++")) {
3296 res = !gSystem->Load(path);
3297 if (res) printf("Shared lib %s has been dynamically linked\n",path.Data());
3298 }
3299 }
3300
3301 delete list;
3302 filelist->Delete();
3303 delete filelist;
3304}
3305
3306////////////////////////////////////////////////////////////////////////////////
3307/// Read the list of StreamerInfo from this file.
3308///
3309/// The key with name holding the list of TStreamerInfo objects is read.
3310/// The corresponding TClass objects are updated.
3311/// Note that this function is not called if the static member fgReadInfo is false.
3312/// (see TFile::SetReadStreamerInfo)
3315{
3316 auto listRetcode = GetStreamerInfoListImpl(/*lookupSICache*/ true); // NOLINT: silence clang-tidy warnings
3317 TList *list = listRetcode.fList;
3318 auto retcode = listRetcode.fReturnCode;
3319 if (!list) {
3320 if (retcode) MakeZombie();
3321 return;
3322 }
3323
3324 list->SetOwner(kFALSE);
3325
3326 if (gDebug > 0) Info("ReadStreamerInfo", "called for file %s",GetName());
3327
3329
3330 Int_t version = fVersion;
3331 if (version > 1000000) version -= 1000000;
3332 if (version < 53419 || (59900 < version && version < 59907)) {
3333 // We need to update the fCheckSum field of the TStreamerBase.
3334
3335 // loop on all TStreamerInfo classes
3336 TObjLink *lnk = list->FirstLink();
3337 while (lnk) {
3338 info = (TStreamerInfo*)lnk->GetObject();
3339 if (!info || info->IsA() != TStreamerInfo::Class()) {
3340 lnk = lnk->Next();
3341 continue;
3342 }
3343 TIter next(info->GetElements());
3345 while ((element = (TStreamerElement*) next())) {
3346 TStreamerBase *base = dynamic_cast<TStreamerBase*>(element);
3347 if (!base) continue;
3348 if (base->GetBaseCheckSum() != 0) continue;
3349 TStreamerInfo *baseinfo = (TStreamerInfo*)list->FindObject(base->GetName());
3350 if (baseinfo) {
3351 base->SetBaseCheckSum(baseinfo->GetCheckSum());
3352 }
3353 }
3354 lnk = lnk->Next();
3355 }
3356 }
3357
3358 std::vector<Int_t> si_uids;
3359 // loop on all TStreamerInfo classes
3360 for (int mode=0;mode<2; ++mode) {
3361 // In order for the collection proxy to be initialized properly, we need
3362 // to setup the TStreamerInfo for non-stl class before the stl classes.
3363 TObjLink *lnk = list->FirstLink();
3364 while (lnk) {
3365 info = (TStreamerInfo*)lnk->GetObject();
3366 if (!info) {
3367 lnk = lnk->Next();
3368 continue;
3369 }
3370 if (info->IsA() != TStreamerInfo::Class()) {
3371 if (mode==1) {
3372 TObject *obj = (TObject*)info;
3373 if (strcmp(obj->GetName(),"listOfRules")==0) {
3374#if 0
3375 // Completely ignore the rules for now.
3376 TList *listOfRules = (TList*)obj;
3377 TObjLink *rulelnk = listOfRules->FirstLink();
3378 while (rulelnk) {
3379 TObjString *rule = (TObjString*)rulelnk->GetObject();
3380 TClass::AddRule( rule->String().Data() );
3381 rulelnk = rulelnk->Next();
3382 }
3383#endif
3384 } else {
3385 Warning("ReadStreamerInfo","%s has a %s in the list of TStreamerInfo.", GetName(), info->IsA()->GetName());
3386 }
3387 info->SetBit(kCanDelete);
3388 }
3389 lnk = lnk->Next();
3390 continue;
3391 }
3392 // This is a quick way (instead of parsing the name) to see if this is
3393 // the description of an STL container.
3394 if (info->GetElements()==0) {
3395 Warning("ReadStreamerInfo","The StreamerInfo for %s does not have a list of elements.",info->GetName());
3396 lnk = lnk->Next();
3397 continue;
3398 }
3399 TObject *element = info->GetElements()->UncheckedAt(0);
3400 Bool_t isstl = element && strcmp("This",element->GetName())==0;
3401
3402 if ( (!isstl && mode ==0) || (isstl && mode ==1) ) {
3403 // Skip the STL container the first time around
3404 // Skip the regular classes the second time around;
3405 info->BuildCheck(this);
3406 Int_t uid = info->GetNumber();
3407 Int_t asize = fClassIndex->GetSize();
3408 if (uid >= asize && uid <100000) fClassIndex->Set(2*asize);
3409 if (uid >= 0 && uid < fClassIndex->GetSize()) {
3410 si_uids.push_back(uid);
3411 fClassIndex->fArray[uid] = 1;
3412 }
3413 else if (!isstl && !info->GetClass()->IsSyntheticPair()) {
3414 printf("ReadStreamerInfo, class:%s, illegal uid=%d\n",info->GetName(),uid);
3415 }
3416 if (gDebug > 0) printf(" -class: %s version: %d info read at slot %d\n",info->GetName(), info->GetClassVersion(),uid);
3417 }
3418 lnk = lnk->Next();
3419 }
3420 }
3421 fClassIndex->fArray[0] = 0;
3422 list->Clear(); //this will delete all TStreamerInfo objects with kCanDelete bit set
3423 delete list;
3424
3425 // We are done processing the record, let future calls and other threads that it
3426 // has been done.
3427 fgTsSIHashes.Insert(listRetcode.fHash, std::move(si_uids));
3428}
3429
3430////////////////////////////////////////////////////////////////////////////////
3431/// Specify if the streamerinfos must be read at file opening.
3432///
3433/// If fgReadInfo is true (default) TFile::ReadStreamerInfo is called
3434/// when opening the file.
3435/// It may be interesting to set fgReadInfo to false to speedup the file
3436/// opening time or in case libraries containing classes referenced
3437/// by the file have not yet been loaded.
3438/// if fgReadInfo is false, one can still read the StreamerInfo with
3439/// myfile.ReadStreamerInfo();
3442{
3443 fgReadInfo = readinfo;
3444}
3445
3446////////////////////////////////////////////////////////////////////////////////
3447/// If the streamerinfos are to be read at file opening.
3448///
3449/// See TFile::SetReadStreamerInfo for more documentation.
3452{
3453 return fgReadInfo;
3454}
3455
3456////////////////////////////////////////////////////////////////////////////////
3457/// Show the StreamerInfo of all classes written to this file.
3460{
3461 TList *list = GetStreamerInfoList();
3462 if (!list) return;
3463
3464 list->ls();
3465 delete list;
3466}
3467
3468////////////////////////////////////////////////////////////////////////////////
3469/// Check if the ProcessID pidd is already in the file,
3470/// if not, add it and return the index number in the local file list.
3473{
3474 TProcessID *pid = pidd;
3475 if (!pid) pid = TProcessID::GetPID();
3476 TObjArray *pids = GetListOfProcessIDs();
3477 Int_t npids = GetNProcessIDs();
3478 for (Int_t i=0;i<npids;i++) {
3479 if (pids->At(i) == pid) return (UShort_t)i;
3480 }
3481
3482 this->SetBit(TFile::kHasReferences);
3483 pids->AddAtAndExpand(pid,npids);
3484 pid->IncrementCount();
3485 char name[32];
3486 snprintf(name,32,"ProcessID%d",npids);
3487 this->WriteTObject(pid,name);
3488 this->IncrementProcessIDs();
3489 if (gDebug > 0) {
3490 Info("WriteProcessID", "name=%s, file=%s", name, GetName());
3491 }
3492 return (UShort_t)npids;
3493}
3494
3495
3496////////////////////////////////////////////////////////////////////////////////
3497/// Write the list of TStreamerInfo as a single object in this file
3498/// The class Streamer description for all classes written to this file
3499/// is saved. See class TStreamerInfo.
3502{
3503 //if (!gFile) return;
3504 if (!fWritable) return;
3505 if (!fClassIndex) return;
3506 if (fIsPcmFile) return; // No schema evolution for ROOT PCM files.
3507 if (fClassIndex->fArray[0] == 0
3508 && fSeekInfo != 0) {
3509 // No need to update the index if no new classes added to the file
3510 // but write once an empty StreamerInfo list to mark that there is no need
3511 // for StreamerInfos in this file.
3512 return;
3513 }
3514 if (gDebug > 0) Info("WriteStreamerInfo", "called for file %s",GetName());
3515
3516 SafeDelete(fInfoCache);
3517
3518 // build a temporary list with the marked files
3519 TIter next(gROOT->GetListOfStreamerInfo());
3521 TList list;
3523 listOfRules.SetOwner(kTRUE);
3524 listOfRules.SetName("listOfRules");
3525 std::set<TClass*> classSet;
3526
3527 while ((info = (TStreamerInfo*)next())) {
3528 Int_t uid = info->GetNumber();
3529 if (fClassIndex->fArray[uid]) {
3530 list.Add(info);
3531 if (gDebug > 0) printf(" -class: %s info number %d saved\n",info->GetName(),uid);
3532
3533 // Add the IO customization rules to the list to be saved for the underlying
3534 // class but make sure to add them only once.
3535 TClass *clinfo = info->GetClass();
3536 if (clinfo && clinfo->GetSchemaRules()) {
3537 if ( classSet.find( clinfo ) == classSet.end() ) {
3538 if (gDebug > 0) printf(" -class: %s stored the I/O customization rules\n",info->GetName());
3539
3540 TObjArrayIter it( clinfo->GetSchemaRules()->GetRules() );
3542 while( (rule = (ROOT::TSchemaRule*)it.Next()) ) {
3543 TObjString *obj = new TObjString();
3544 rule->AsString(obj->String());
3545 listOfRules.Add(obj);
3546 }
3547 classSet.insert(clinfo);
3548 }
3549 }
3550 }
3551 }
3552
3553 // Write the StreamerInfo list even if it is empty.
3554 fClassIndex->fArray[0] = 2; //to prevent adding classes in TStreamerInfo::TagFile
3555
3556 if (listOfRules.GetEntries()) {
3557 // Only add the list of rules if we have something to say.
3558 list.Add(&listOfRules);
3559 }
3560
3561 //free previous StreamerInfo record
3562 if (fSeekInfo) MakeFree(fSeekInfo,fSeekInfo+fNbytesInfo-1);
3563 //Create new key
3564 TKey key(&list,"StreamerInfo",GetBestBuffer(), this);
3565 fKeys->Remove(&key);
3566 fSeekInfo = key.GetSeekKey();
3567 fNbytesInfo = key.GetNbytes();
3568 SumBuffer(key.GetObjlen());
3569 key.WriteFile(0);
3570
3571 fClassIndex->fArray[0] = 0;
3572
3573 list.RemoveLast(); // remove the listOfRules.
3574}
3575
3576////////////////////////////////////////////////////////////////////////////////
3577/// Open a file for reading through the file cache.
3578///
3579/// The file will be downloaded to the cache and opened from there.
3580/// If the download fails, it will be opened remotely.
3581/// The file will be downloaded to the directory specified by SetCacheFileDir().
3583TFile *TFile::OpenFromCache(const char *name, Option_t *, const char *ftitle,
3585{
3586 TFile *f = nullptr;
3587
3588 if (fgCacheFileDir == "") {
3589 ::Warning("TFile::OpenFromCache",
3590 "you want to read through a cache, but you have no valid cache "
3591 "directory set - reading remotely");
3592 ::Info("TFile::OpenFromCache", "set cache directory using TFile::SetCacheFileDir()");
3593 } else {
3594 TUrl fileurl(name);
3595
3596 if ((!strcmp(fileurl.GetProtocol(), "file"))) {
3597 // it makes no sense to read local files through a file cache
3598 if (!fgCacheFileForce)
3599 ::Warning("TFile::OpenFromCache",
3600 "you want to read through a cache, but you are reading "
3601 "local files - CACHEREAD disabled");
3602 } else {
3603 // this is a remote file and worthwhile to be put into the local cache
3604 // now create cachepath to put it
3607 cachefilepath = fgCacheFileDir;
3608 cachefilepath += fileurl.GetFile();
3610 if ((gSystem->mkdir(cachefilepathbasedir, kTRUE) < 0) &&
3612 ::Warning("TFile::OpenFromCache","you want to read through a cache, but I "
3613 "cannot create the directory %s - CACHEREAD disabled",
3614 cachefilepathbasedir.Data());
3615 } else {
3616 // check if this should be a zip file
3617 if (strlen(fileurl.GetAnchor())) {
3618 // remove the anchor and change the target name
3619 cachefilepath += "__";
3620 cachefilepath += fileurl.GetAnchor();
3621 fileurl.SetAnchor("");
3622 }
3623 if (strstr(name,"zip=")) {
3624 // filter out this option and change the target cache name
3625 TString urloptions = fileurl.GetOptions();
3627 TObjArray *objOptions = urloptions.Tokenize("&");
3628 Int_t optioncount = 0;
3630 for (Int_t n = 0; n < objOptions->GetEntries(); n++) {
3631 TString loption = ((TObjString*)objOptions->At(n))->GetName();
3632 TObjArray *objTags = loption.Tokenize("=");
3633 if (objTags->GetEntries() == 2) {
3634 TString key = ((TObjString*)objTags->At(0))->GetName();
3635 TString value = ((TObjString*)objTags->At(1))->GetName();
3636 if (key.CompareTo("zip", TString::kIgnoreCase)) {
3637 if (optioncount!=0) {
3638 newoptions += "&";
3639 }
3640 newoptions += key;
3641 newoptions += "=";
3642 newoptions += value;
3643 ++optioncount;
3644 } else {
3645 zipname = value;
3646 }
3647 }
3648 delete objTags;
3649 }
3650 delete objOptions;
3651 fileurl.SetOptions(newoptions.Data());
3652 cachefilepath += "__";
3654 fileurl.SetAnchor("");
3655 }
3656
3658
3659 // check if file is in the cache
3660 Long_t id;
3661 Long64_t size;
3662 Long_t flags;
3663 Long_t modtime;
3664 if (!gSystem->GetPathInfo(cachefilepath, &id, &size, &flags, &modtime)) {
3665 // file is in the cache
3666 if (!fgCacheFileDisconnected) {
3667 char cacheblock[256];
3668 char remotblock[256];
3669 // check the remote file for it's size and compare some magic bytes
3670 TString cfurl;
3672 cfurl += "?filetype=raw";
3673 TUrl rurl(name);
3674 TString ropt = rurl.GetOptions();
3675 ropt += "&filetype=raw";
3676 rurl.SetOptions(ropt);
3677
3678 Bool_t forcedcache = fgCacheFileForce;
3679 fgCacheFileForce = kFALSE;
3680
3681 TFile *cachefile = TFile::Open(cfurl, "READ");
3682 TFile *remotfile = TFile::Open(rurl.GetUrl(), "READ");
3683
3684 fgCacheFileForce = forcedcache;
3685
3686 if (!cachefile) {
3687 need2copy = kTRUE;
3688 ::Error("TFile::OpenFromCache",
3689 "cannot open the cache file to check cache consistency");
3690 return nullptr;
3691 }
3692
3693 if (!remotfile) {
3694 ::Error("TFile::OpenFromCache",
3695 "cannot open the remote file to check cache consistency");
3696 return nullptr;
3697 }
3698
3699 cachefile->Seek(0);
3700 remotfile->Seek(0);
3701
3702 if ((!cachefile->ReadBuffer(cacheblock,256)) &&
3703 (!remotfile->ReadBuffer(remotblock,256))) {
3704 if (memcmp(cacheblock, remotblock, 256)) {
3705 ::Warning("TFile::OpenFromCache", "the header of the cache file "
3706 "differs from the remote file - forcing an update");
3707 need2copy = kTRUE;
3708 }
3709 } else {
3710 ::Warning("TFile::OpenFromCache", "the header of the cache and/or "
3711 "remote file are not readable - forcing an update");
3712 need2copy = kTRUE;
3713 }
3714
3715 delete remotfile;
3716 delete cachefile;
3717 }
3718 } else {
3719 need2copy = kTRUE;
3720 }
3721
3722 // try to fetch the file (disable now the forced caching)
3723 Bool_t forcedcache = fgCacheFileForce;
3724 fgCacheFileForce = kFALSE;
3725 if (need2copy) {
3726 const auto cachefilepathtmp = cachefilepath + std::to_string(gSystem->GetPid()) + ".tmp";
3728 ::Warning("TFile::OpenFromCache",
3729 "you want to read through a cache, but I "
3730 "cannot make a cache copy of %s - CACHEREAD disabled",
3731 cachefilepathbasedir.Data());
3732 fgCacheFileForce = forcedcache;
3733 return nullptr;
3734 }
3735 if (gSystem->AccessPathName(cachefilepath)) // then file _does not_ exist (weird convention)
3737 else // another process or thread already wrote a file with the same name while we were copying it
3739 }
3740 fgCacheFileForce = forcedcache;
3741 ::Info("TFile::OpenFromCache", "using local cache copy of %s [%s]", name, cachefilepath.Data());
3742 // finally we have the file and can open it locally
3743 fileurl.SetProtocol("file");
3744 fileurl.SetFile(cachefilepath);
3745
3748 tagfile += ".ROOT.cachefile";
3749 // we symlink this file as a ROOT cached file
3751 return TFile::Open(fileurl.GetUrl(), "READ", ftitle, compress, netopt);
3752 }
3753 }
3754 }
3755
3756 // Failed
3757 return f;
3758}
3759
3760////////////////////////////////////////////////////////////////////////////////
3761/// Create / open a file
3762///
3763/// The type of the file can be either a
3764/// TFile or any TFile derived class for which an
3765/// plugin library handler has been registered with the plugin manager
3766/// (for the plugin manager see the TPluginManager class). The returned
3767/// type of TFile depends on the file name specified by 'url'.
3768/// If 'url' is a '|'-separated list of file URLs, the 'URLs' are tried
3769/// sequentially in the specified order until a successful open.
3770/// If the file starts with "root:", "roots:" or "rootk:" an XRootD-backed file
3771/// will be returned, with "http:" a curl-based file, with "file:" a local TFile,
3772/// etc. (see the list of TFile plugin handlers in $ROOTSYS/etc/system.rootrc
3773/// for regular expressions that will be checked) and as last a local file will
3774/// be tried.
3775/// Before opening a file via a remote API, a check is made to see if the URL
3776/// specifies a local file. If that is the case the file will be opened
3777/// via a normal TFile. To force the opening of a local file via a
3778/// specify as host "localhost".
3779/// The netopt argument is not used, any more. For the meaning of the
3780/// options and other arguments see the constructors of the individual
3781/// file classes. In case of error, it returns a nullptr.
3782///
3783/// For TFile implementations supporting asynchronous file open, see
3784/// TFile::AsyncOpen(...), it is possible to request a timeout with the
3785/// option <b>`TIMEOUT=<secs>`</b>: the timeout must be specified in seconds and
3786/// it will be internally checked with granularity of one millisec.
3787/// For remote files there is the option: <b>CACHEREAD</b> opens an existing
3788/// file for reading through the file cache. The file will be downloaded to
3789/// the cache and opened from there. If the download fails, it will be opened remotely.
3790/// The file will be downloaded to the directory specified by SetCacheFileDir().
3791///
3792/// *The caller is responsible for deleting the pointer.*
3793/// In READ mode, a nullptr is returned if the file does not exist or cannot be opened.
3794/// In CREATE mode, a nullptr is returned if the file already exists or cannot be created.
3795/// In RECREATE mode, a nullptr is returned if the file can not be created.
3796/// In UPDATE mode, a nullptr is returned if the file cannot be created or opened.
3798TFile *TFile::Open(const char *url, Option_t *options, const char *ftitle,
3800{
3802 TFile *f = nullptr;
3803 EFileType type = kFile;
3804
3805 // Check input
3806 if (!url || strlen(url) <= 0) {
3807 ::Error("TFile::Open", "no url specified");
3808 return f;
3809 }
3810
3813
3814#ifdef R__UNIX
3815 // If URL is a file on an EOS FUSE mount, attempt redirection to XRootD protocol.
3816 if (gEnv->GetValue("TFile.CrossProtocolRedirects", 1) == 1) {
3817 TUrl fileurl(expandedUrl, /* default is file */ kTRUE);
3818 if (strcmp(fileurl.GetProtocol(), "file") == 0) {
3819 ssize_t len = getxattr(fileurl.GetFile(), "eos.url.xroot", nullptr, 0);
3820 if (len > 0) {
3821 std::string xurl(len, 0);
3822 std::string fileNameFromUrl{fileurl.GetFile()};
3823 if (getxattr(fileNameFromUrl.c_str(), "eos.url.xroot", &xurl[0], len) == len) {
3824 // Sometimes the `getxattr` call may return an invalid URL due
3825 // to the POSIX attribute not being yet completely filled by EOS.
3826 if (auto baseName = fileNameFromUrl.substr(fileNameFromUrl.find_last_of("/") + 1);
3827 std::equal(baseName.crbegin(), baseName.crend(), xurl.crbegin())) {
3828 if ((f = TFile::Open(xurl.c_str(), options, ftitle, compress, netopt))) {
3829 if (!f->IsZombie()) {
3830 return f;
3831 } else {
3832 delete f;
3833 f = nullptr;
3834 }
3835 }
3836 }
3837 }
3838 }
3839 }
3840 }
3841#endif
3842
3843 // If a timeout has been specified extract the value and try to apply it (it requires
3844 // support for asynchronous open, though; the following is completely transparent if
3845 // such support if not available for the required protocol)
3846 TString opts(options);
3847 opts.ToUpper();
3848 Int_t ito = opts.Index("TIMEOUT=");
3849 if (ito != kNPOS) {
3850 TString sto = opts(ito + std::char_traits<char>::length("TIMEOUT="), opts.Length());
3851 while (!(sto.IsDigit()) && !(sto.IsNull())) { sto.Remove(sto.Length()-1,1); }
3852 if (!(sto.IsNull())) {
3853 // Timeout in millisecs
3854 Int_t toms = sto.Atoi() * 1000;
3855 if (gDebug > 0) ::Info("TFile::Open", "timeout of %d millisec requested", toms);
3856 // Remove from the options field
3857 sto.Insert(0, "TIMEOUT=");
3858 opts.ReplaceAll(sto, "");
3859 // Asynchronous open
3861 // Check the result in steps of 1 millisec
3864 Int_t xtms = toms;
3865 while (aos == TFile::kAOSInProgress && xtms > 0) {
3866 gSystem->Sleep(1);
3867 xtms -= 1;
3869 }
3871 // Do open the file now
3872 f = TFile::Open(fh);
3873 if (gDebug > 0) {
3874 if (aos == TFile::kAOSSuccess)
3875 ::Info("TFile::Open", "waited %d millisec for asynchronous open", toms - xtms);
3876 else
3877 ::Info("TFile::Open", "timeout option not supported (requires asynchronous"
3878 " open support)");
3879 }
3880 } else {
3881 if (xtms <= 0)
3882 ::Error("TFile::Open", "timeout expired while opening '%s'", expandedUrl.Data());
3883 // Cleanup the request
3884 SafeDelete(fh);
3885 }
3886 // Done
3887 return f;
3888 } else {
3889 ::Warning("TFile::Open", "incomplete 'TIMEOUT=' option specification - ignored");
3890 opts.ReplaceAll("TIMEOUT=", "");
3891 }
3892 }
3893
3894 // We will use this from now on
3895 const char *option = opts;
3896
3897 // Many URLs? Redirect output and print errors in case of global failure
3899 Ssiz_t ip = namelist.Index("|");
3900 Bool_t rediroutput = (ip != kNPOS &&
3901 ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
3903 if (rediroutput) {
3904 TString outf = ".TFileOpen_";
3906 if (fout) {
3907 fclose(fout);
3908 gSystem->RedirectOutput(outf, "w", &rh);
3909 }
3910 }
3911
3912 // Try sequentially all names in 'names'
3913 TString name, n;
3914 Ssiz_t from = 0;
3915 while (namelist.Tokenize(n, from, "|") && !f) {
3916
3917 // check if we read through a file cache
3918 if (!strcasecmp(option, "CACHEREAD") ||
3919 ((!strcasecmp(option, "READ") || !strcasecmp(option, "READ_WITHOUT_GLOBALREGISTRATION") || !option[0]) &&
3920 fgCacheFileForce)) {
3921 // Try opening the file from the cache
3923 return f;
3924 }
3925
3926 IncrementFileCounter();
3927
3928 // change names to be recognized by the plugin manager
3929 // e.g. /protocol/path/to/file.root -> protocol:/path/to/file.root
3930 TUrl urlname(n, kTRUE);
3931 name = urlname.GetUrl();
3932 // Check first if a pending async open request matches this one
3933 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
3934 TIter nxr(fgAsyncOpenRequests);
3935 TFileOpenHandle *fh = nullptr;
3936 while ((fh = (TFileOpenHandle *)nxr()))
3937 if (fh->Matches(name))
3938 return TFile::Open(fh);
3939 }
3940
3941 TString urlOptions(urlname.GetOptions());
3942 if (urlOptions.BeginsWith("pmerge") || urlOptions.Contains("&pmerge") || urlOptions.Contains(" pmerge")) {
3943 type = kMerge;
3944
3945 // Pass the full name including the url options:
3946 f = (TFile*) gROOT->ProcessLineFast(TString::Format("new TParallelMergingFile(\"%s\",\"%s\",\"%s\",%d)",n.Data(),option,ftitle,compress));
3947
3948 } else {
3949 // Resolve the file type; this also adjusts names
3950 TString lfname = gEnv->GetValue("Path.Localroot", "");
3951 type = GetType(name, option, &lfname);
3952
3953 if (type == kLocal) {
3954
3955 // Local files
3956 if (lfname.IsNull()) {
3957 urlname.SetHost("");
3958 urlname.SetProtocol("file");
3959 lfname = urlname.GetUrl();
3960 }
3961 f = new TFile(lfname.Data(), option, ftitle, compress);
3962
3963 } else if (type == kNet) {
3964
3965 // Network files
3966 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
3967 if (h->LoadPlugin() == -1)
3968 return nullptr;
3969 f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
3970 }
3971
3972 } else if (type == kWeb) {
3973
3974 // Web files
3975 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
3976 if (h->LoadPlugin() == -1)
3977 return nullptr;
3978 f = (TFile*) h->ExecPlugin(2, name.Data(), option);
3979 }
3980
3981 } else if (type == kFile) {
3982
3983 // 'file:' protocol
3984 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
3985 h->LoadPlugin() == 0) {
3986 name.ReplaceAll("file:", "");
3987 f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
3988 } else
3989 f = new TFile(name.Data(), option, ftitle, compress);
3990
3991 } else {
3992
3993 // no recognized specification: try the plugin manager
3994 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name.Data()))) {
3995 if (h->LoadPlugin() == -1)
3996 return nullptr;
3997 f = (TFile *)h->ExecPlugin(4, name.Data(), option, ftitle, compress);
3998 } else {
3999 // Just try to open it locally but via TFile::Open, so that we pick-up the correct
4000 // plug-in in the case file name contains information about a special backend (e.g.)
4001 if (strcmp(name, urlname.GetFileAndOptions()) != 0)
4002 f = TFile::Open(urlname.GetFileAndOptions(), option, ftitle, compress);
4003 }
4004 }
4005 }
4006
4007 if (f && f->IsZombie()) {
4008 TString newUrl = f->GetNewUrl();
4009 delete f;
4010 if( newUrl.Length() && (newUrl != name) && gEnv->GetValue("TFile.CrossProtocolRedirects", 1) )
4012 else
4013 f = nullptr;
4014 }
4015 }
4016
4017 if (rediroutput) {
4018 // Restore output to stdout
4019 gSystem->RedirectOutput(0, "", &rh);
4020 // If we failed print error messages
4021 if (!f)
4023 // Remove the file
4024 gSystem->Unlink(rh.fFile);
4025 }
4026
4027 // if the file is writable, non local, and not opened in raw mode
4028 // we create a default write cache of 512 KBytes
4029 if (type != kLocal && type != kFile &&
4030 f && f->IsWritable() && !f->IsRaw()) {
4031 new TFileCacheWrite(f, 1);
4032 }
4033
4034 return f;
4035}
4036
4037////////////////////////////////////////////////////////////////////////////////
4038/// Submit an asynchronous open request.
4039
4040/// See TFile::Open(const char *, ...) for an
4041/// explanation of the arguments. A handler is returned which is to be passed
4042/// to TFile::Open(TFileOpenHandle *) to get the real TFile instance once
4043/// the file is open.
4044/// This call never blocks and it is provided to allow parallel submission
4045/// of file opening operations expected to take a long time.
4046/// TFile::Open(TFileOpenHandle *) may block if the file is not yet ready.
4047/// The sequence
4048///
4049/// TFile::Open(TFile::AsyncOpen(const char *, ...))
4050///
4051/// is equivalent to
4052///
4053/// TFile::Open(const char *, ...)
4054///
4055/// To be effective, the underlying TFile implementation must be able to
4056/// support asynchronous open functionality. Currently, only TNetXNGFile
4057/// supports it. If the functionality is not implemented, this call acts
4058/// transparently by returning an handle with the arguments for the
4059/// standard synchronous open run by TFile::Open(TFileOpenHandle *).
4060/// The retuned handle will be adopted by TFile after opening completion
4061/// in TFile::Open(TFileOpenHandle *); if opening is not finalized the
4062/// handle must be deleted by the caller.
4064TFileOpenHandle *TFile::AsyncOpen(const char *url, Option_t *option,
4065 const char *ftitle, Int_t compress,
4066 Int_t netopt)
4067{
4068 TFileOpenHandle *fh = nullptr;
4069 TFile *f = nullptr;
4071
4072 // Check input
4073 if (!url || strlen(url) <= 0) {
4074 ::Error("TFile::AsyncOpen", "no url specified");
4075 return fh;
4076 }
4077
4078 // Many URLs? Redirect output and print errors in case of global failure
4081 Ssiz_t ip = namelist.Index("|");
4082 Bool_t rediroutput = (ip != kNPOS &&
4083 ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
4085 if (rediroutput) {
4086 TString outf = ".TFileAsyncOpen_";
4088 if (fout) {
4089 fclose(fout);
4090 gSystem->RedirectOutput(outf, "w", &rh);
4091 }
4092 }
4093
4094 // Try sequentially all names in 'names'
4095 TString name, n;
4096 Ssiz_t from = 0;
4097 while (namelist.Tokenize(n, from, "|") && !f) {
4098
4099 // change names to be recognized by the plugin manager
4100 // e.g. /protocol/path/to/file.root -> protocol:/path/to/file.root
4101 TUrl urlname(n, kTRUE);
4102 name = urlname.GetUrl();
4103
4104 // Resolve the file type; this also adjusts names
4105 EFileType type = GetType(name, option);
4106
4107 TPluginHandler *h = nullptr;
4108
4109 // Here we send the asynchronous request if the functionality is implemented
4110 if (type == kNet) {
4111 // Network files
4112 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4113 !strcmp(h->GetClass(),"TNetXNGFile")
4114 && h->LoadPlugin() == 0) {
4115 f = (TFile*) h->ExecPlugin(6, name.Data(), option, ftitle, compress, netopt, kTRUE);
4116 notfound = kFALSE;
4117 }
4118 }
4119 }
4120
4121 if (rediroutput) {
4122 // Restore output to stdout
4123 gSystem->RedirectOutput(0, "", &rh);
4124 // If we failed print error messages
4125 if (!notfound && !f)
4127 // Remove the file
4128 gSystem->Unlink(rh.fFile);
4129 }
4130
4131 // Make sure that no error occurred
4132 if (notfound) {
4133 SafeDelete(f);
4134 // Save the arguments in the handler, so that a standard open can be
4135 // attempted later on
4137 } else if (f) {
4138 // Fill the opaque handler to be use to attach the file later on
4139 fh = new TFileOpenHandle(f);
4140 }
4141
4142 // Record this request
4143 if (fh) {
4144 // Create the lst, if not done already
4145 if (!fgAsyncOpenRequests)
4146 fgAsyncOpenRequests = new TList;
4147 fgAsyncOpenRequests->Add(fh);
4148 }
4149
4150 // We are done
4151 return fh;
4152}
4153
4154////////////////////////////////////////////////////////////////////////////////
4155/// Waits for the completion of an asynchronous open request.
4156///
4157/// Returns the pointer to the associated TFile, transferring ownership of the
4158/// handle to the TFile instance.
4161{
4162 TFile *f = nullptr;
4163
4164 // Note that the request may have failed
4165 if (fh && fgAsyncOpenRequests) {
4166 // Remove it from the pending list: we need to do it at this level to avoid
4167 // recursive calls in the standard TFile::Open
4168 fgAsyncOpenRequests->Remove(fh);
4169 // Was asynchronous open functionality implemented?
4170 if ((f = fh->GetFile()) && !(f->IsZombie())) {
4171 // Yes: wait for the completion of the open phase, if needed
4172 Bool_t cr = (!strcmp(f->GetOption(),"CREATE") ||
4173 !strcmp(f->GetOption(),"RECREATE") ||
4174 !strcmp(f->GetOption(),"NEW")) ? kTRUE : kFALSE;
4175 f->Init(cr);
4176 } else {
4177 // No: process a standard open
4178 f = TFile::Open(fh->GetName(), fh->GetOpt(), fh->GetTitle(),
4179 fh->GetCompress(), fh->GetNetOpt());
4180 }
4181
4182 // Adopt the handle instance in the TFile instance so that it gets
4183 // automatically cleaned up
4184 if (f) f->fAsyncHandle = fh;
4185 }
4186
4187 // We are done
4188 return f;
4189}
4190
4191////////////////////////////////////////////////////////////////////////////////
4192/// Interface to system open. All arguments like in POSIX open().
4194Int_t TFile::SysOpen(const char *pathname, Int_t flags, UInt_t mode)
4195{
4196#if defined(R__WINGCC)
4197 // ALWAYS use binary mode - even cygwin text should be in unix format
4198 // although this is posix default it has to be set explicitly
4199 return ::open(pathname, flags | O_BINARY, mode);
4200#elif defined(R__SEEK64)
4201 return ::open64(pathname, flags, mode);
4202#else
4203 return ::open(pathname, flags, mode);
4204#endif
4205}
4206
4207////////////////////////////////////////////////////////////////////////////////
4208/// Interface to system close. All arguments like in POSIX close().
4211{
4212 if (fd < 0) return 0;
4213 return ::close(fd);
4214}
4215
4216////////////////////////////////////////////////////////////////////////////////
4217/// Interface to system read. All arguments like in POSIX read().
4219Int_t TFile::SysRead(Int_t fd, void *buf, Int_t len)
4220{
4221 return ::read(fd, buf, len);
4222}
4223
4224////////////////////////////////////////////////////////////////////////////////
4225/// Interface to system write. All arguments like in POSIX write().
4227Int_t TFile::SysWrite(Int_t fd, const void *buf, Int_t len)
4228{
4229 return ::write(fd, buf, len);
4230}
4231////////////////////////////////////////////////////////////////////////////////
4232/// Interface to system lseek.
4233///
4234/// All arguments like in POSIX lseek()
4235/// except that the offset and return value are of a type which are
4236/// able to handle 64 bit file systems.
4239{
4240#if defined (R__SEEK64)
4241 return ::lseek64(fd, offset, whence);
4242#elif defined(WIN32)
4243 return ::_lseeki64(fd, offset, whence);
4244#else
4245 return ::lseek(fd, offset, whence);
4246#endif
4247}
4248
4249////////////////////////////////////////////////////////////////////////////////
4250/// Return file stat information.
4251///
4252/// The interface and return value is
4253/// identical to TSystem::GetPathInfo(). The function returns 0 in
4254/// case of success and 1 if the file could not be stat'ed.
4257 Long_t *modtime)
4258{
4259 return gSystem->GetPathInfo(fRealName, id, size, flags, modtime);
4260}
4261
4262////////////////////////////////////////////////////////////////////////////////
4263/// Interface to system fsync. All arguments like in POSIX fsync().
4266{
4267 if (TestBit(kDevNull)) return 0;
4268
4269#ifndef WIN32
4270 return ::fsync(fd);
4271#else
4272 return ::_commit(fd);
4273#endif
4274}
4275
4276////////////////////////////////////////////////////////////////////////////////
4277/// Return the total number of bytes written so far to the file.
4280{
4281 return fCacheWrite ? fCacheWrite->GetBytesInCache() + fBytesWrite : fBytesWrite;
4282}
4283
4284////////////////////////////////////////////////////////////////////////////////
4285/// Static function returning the total number of bytes read from all files.
4288{
4289 return fgBytesRead;
4290}
4291
4292////////////////////////////////////////////////////////////////////////////////
4293/// Static function returning the total number of bytes written to all files.
4294/// Does not take into account what might still be in the write caches.
4297{
4298 return fgBytesWrite;
4299}
4300
4301////////////////////////////////////////////////////////////////////////////////
4302/// Static function returning the total number of read calls from all files.
4305{
4306 return fgReadCalls;
4307}
4308
4309////////////////////////////////////////////////////////////////////////////////
4310/// Static function returning the readahead buffer size.
4313{
4314 return fgReadaheadSize;
4315}
4316
4317//______________________________________________________________________________
4318void TFile::SetReadaheadSize(Int_t bytes) { fgReadaheadSize = bytes; }
4319
4320//______________________________________________________________________________
4321void TFile::SetFileBytesRead(Long64_t bytes) { fgBytesRead = bytes; }
4322
4323//______________________________________________________________________________
4324void TFile::SetFileBytesWritten(Long64_t bytes) { fgBytesWrite = bytes; }
4325
4326//______________________________________________________________________________
4327void TFile::SetFileReadCalls(Int_t readcalls) { fgReadCalls = readcalls; }
4328
4329//______________________________________________________________________________
4330Long64_t TFile::GetFileCounter() { return fgFileCounter; }
4331
4332//______________________________________________________________________________
4333void TFile::IncrementFileCounter() { fgFileCounter++; }
4334
4335////////////////////////////////////////////////////////////////////////////////
4336/// Sets the directory where to locally stage/cache remote files.
4337/// If the directory is not writable by us return kFALSE.
4341{
4343 if (!cached.EndsWith("/"))
4344 cached += "/";
4345
4347 // try to create it
4350 ::Error("TFile::SetCacheFileDir", "no sufficient permissions on cache directory %s or cannot create it", TString(cachedir).Data());
4351 fgCacheFileDir = "";
4352 return kFALSE;
4353 }
4354 gSystem->Chmod(cached, 0700);
4355 }
4357 gSystem->Chmod(cached, 0700);
4358 fgCacheFileDir = cached;
4359 fgCacheFileDisconnected = operatedisconnected;
4360 fgCacheFileForce = forcecacheread;
4361 return kTRUE;
4362}
4363
4364////////////////////////////////////////////////////////////////////////////////
4365/// Get the directory where to locally stage/cache remote files.
4367const char *TFile::GetCacheFileDir()
4368{
4369 return fgCacheFileDir;
4370}
4371
4372////////////////////////////////////////////////////////////////////////////////
4373/// Try to shrink the cache to the desired size.
4374///
4375/// With the clenupinterval you can specify the minimum amount of time after
4376/// the previous cleanup before the cleanup operation is repeated in
4377/// the cache directory
4380{
4381 if (fgCacheFileDir == "") {
4382 return kFALSE;
4383 }
4384
4385 // check the last clean-up in the cache
4386 Long_t id;
4387 Long64_t size;
4388 Long_t flags;
4389 Long_t modtime;
4390
4391 TString cachetagfile = fgCacheFileDir;
4392 cachetagfile += ".tag.ROOT.cache";
4393 if (!gSystem->GetPathInfo(cachetagfile, &id, &size, &flags, &modtime)) {
4394 // check the time passed since last cache cleanup
4395 Long_t lastcleanuptime = ((Long_t)time(0) - modtime);
4397 ::Info("TFile::ShrinkCacheFileDir", "clean-up is skipped - last cleanup %lu seconds ago - you requested %lu", lastcleanuptime, cleanupinterval);
4398 return kTRUE;
4399 }
4400 }
4401
4402 // (re-)create the cache tag file
4403 cachetagfile += "?filetype=raw";
4404 TFile *tagfile = nullptr;
4405
4406 if (!(tagfile = TFile::Open(cachetagfile, "RECREATE"))) {
4407 ::Error("TFile::ShrinkCacheFileDir", "cannot create the cache tag file %s", cachetagfile.Data());
4408 return kFALSE;
4409 }
4410
4411 // the shortest garbage collector in the world - one long line of PERL - unlinks files only,
4412 // if there is a symbolic link with '.ROOT.cachefile' for safety ;-)
4413
4414 TString cmd;
4415#if defined(R__WIN32)
4416 cmd = "echo <TFile::ShrinkCacheFileDir>: cleanup to be implemented";
4417#elif defined(R__MACOSX)
4418 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);
4419#else
4420 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);
4421#endif
4422
4423 tagfile->WriteBuffer(cmd, cmd.Sizeof());
4424 delete tagfile;
4425
4426 if ((gSystem->Exec(cmd)) != 0) {
4427 ::Error("TFile::ShrinkCacheFileDir", "error executing clean-up script");
4428 return kFALSE;
4429 }
4430
4431 return kTRUE;
4432}
4433
4434////////////////////////////////////////////////////////////////////////////////
4435/// Sets open timeout time (in ms). Returns previous timeout value.
4438{
4439 UInt_t to = fgOpenTimeout;
4440 fgOpenTimeout = timeout;
4441 return to;
4442}
4443
4444////////////////////////////////////////////////////////////////////////////////
4445/// Returns open timeout (in ms).
4448{
4449 return fgOpenTimeout;
4450}
4451
4452////////////////////////////////////////////////////////////////////////////////
4453/// Sets only staged flag. Returns previous value of flag.
4454/// When true we check before opening the file if it is staged, if not,
4455/// the open fails.
4458{
4459 Bool_t f = fgOnlyStaged;
4460 fgOnlyStaged = onlystaged;
4461 return f;
4462}
4463
4464////////////////////////////////////////////////////////////////////////////////
4465/// Returns staged only flag.
4468{
4469 return fgOnlyStaged;
4470}
4471
4472////////////////////////////////////////////////////////////////////////////////
4473/// Return kTRUE if 'url' matches the coordinates of this file.
4474///
4475/// The check is implementation dependent and may need to be overload
4476/// by each TFile implementation relying on this check.
4477/// The default implementation checks the file name only.
4479Bool_t TFile::Matches(const char *url)
4480{
4481 // Check the full URL, including port and FQDN.
4482 TUrl u(url);
4483
4484 // Check
4485 if (!strcmp(u.GetFile(), fUrl.GetFile())) {
4486 // Check ports
4487 if (u.GetPort() == fUrl.GetPort()) {
4488 if (!strcmp(u.GetHostFQDN(), fUrl.GetHostFQDN())) {
4489 // Ok, coordinates match
4490 return kTRUE;
4491 }
4492 }
4493 }
4494
4495 // Default is not matching
4496 return kFALSE;
4497}
4498
4499////////////////////////////////////////////////////////////////////////////////
4500/// Return kTRUE if this async request matches the open request
4501/// specified by 'url'
4504{
4505 if (fFile) {
4506 return fFile->Matches(url);
4507 } else if (fName.Length() > 0){
4508 // Deep check of URLs
4509 TUrl u(url);
4510 TUrl uref(fName);
4511 if (!strcmp(u.GetFile(), uref.GetFile())) {
4512 // Check ports
4513 if (u.GetPort() == uref.GetPort()) {
4514 // Check also the host name
4515 if (!strcmp(u.GetHostFQDN(), uref.GetHostFQDN())) {
4516 // Ok, coordinates match
4517 return kTRUE;
4518 }
4519 }
4520 }
4521 }
4522
4523 // Default is not matching
4524 return kFALSE;
4525}
4526
4527////////////////////////////////////////////////////////////////////////////////
4528/// Resolve the file type as a function of the protocol field in 'name'
4529///
4530/// If defined, the string 'prefix' is added when testing the locality of
4531/// a 'name' with network-like structure (i.e. root://host//path); if the file
4532/// is local, on return 'prefix' will contain the actual local path of the file.
4534TFile::EFileType TFile::GetType(const char *name, Option_t *option, TString *prefix)
4535{
4537
4538 TPMERegexp re("^(root|xroot).*", "i");
4539 if (re.Match(name)) {
4540 //
4541 // Should be a network file ...
4542 type = kNet;
4543 // ... but make sure that is not local or that a remote-like connection
4544 // is forced. Treat it as local if:
4545 // i) the url points to the localhost, the file will be opened in
4546 // readonly mode and the current user has read access;
4547 // ii) the specified user is equal to the current user then open local
4548 // TFile.
4550 TUrl url(name);
4551 //
4552 // Check whether we should try to optimize for local files
4553 Bool_t forceRemote = gEnv->GetValue("Path.ForceRemote", 0);
4554 forceRemote = (forceRemote) ? kTRUE : gEnv->GetValue("TFile.ForceRemote", 0);
4555 TString opts = url.GetOptions();
4556 if (opts.Contains("remote=1"))
4558 else if (opts.Contains("remote=0"))
4560 if (!forceRemote) {
4561 // Generic locality test
4563 if (localFile) {
4564 // Local path including the prefix
4565 const char *fname = url.GetFileAndOptions();
4567 if (fname[0] == '/') {
4568 if (prefix)
4569 lfname.Form("%s%s", prefix->Data(), fname);
4570 else
4571 lfname = fname;
4572 } else if (fname[0] == '~' || fname[0] == '$') {
4573 lfname = fname;
4574 } else {
4575 lfname.Form("%s/%s", gSystem->HomeDirectory(), fname);
4576 }
4577 // If option "READ" test existence and access
4578 TString opt = option;
4579 opt.ToUpper();
4580 Bool_t read = (opt.IsNull() ||
4581 opt == "READ") ? kTRUE : kFALSE;
4582 if (read) {
4584 if (!gSystem->ExpandPathName(fn)) {
4586 localFile = kFALSE;
4587 }
4588 }
4589 // Return full local path if requested (and if the case)
4590 if (localFile && prefix)
4591 *prefix = lfname;
4592 }
4593 }
4594 //
4595 // Adjust the type according to findings
4596 type = (localFile) ? kLocal : type;
4597 } else if (TPMERegexp("^(http[s]?|s3http[s]?|[a]?s3|gs|gshttp[s]?){1}:", "i").Match(name)) {
4598 //
4599 // Web file
4600 type = kWeb;
4601 } else if (!strncmp(name, "file:", 5)) {
4602 //
4603 // 'file' protocol
4604 type = kFile;
4605 }
4606 // We are done
4607 return type;
4608}
4609
4610////////////////////////////////////////////////////////////////////////////////
4611/// Get status of the async open request related to 'name'.
4614{
4615 // Check the list of pending async open requests
4616 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4617 TIter nxr(fgAsyncOpenRequests);
4618 TFileOpenHandle *fh = nullptr;
4619 while ((fh = (TFileOpenHandle *)nxr()))
4620 if (fh->Matches(name))
4621 return TFile::GetAsyncOpenStatus(fh);
4622 }
4623
4624 // Check also the list of files open
4626 TSeqCollection *of = gROOT->GetListOfFiles();
4627 if (of && (of->GetSize() > 0)) {
4628 TIter nxf(of);
4629 TFile *f = nullptr;
4630 while ((f = (TFile *)nxf()))
4631 if (f->Matches(name))
4632 return f->GetAsyncOpenStatus();
4633 }
4634
4635 // Default is synchronous mode
4636 return kAOSNotAsync;
4637}
4638
4639////////////////////////////////////////////////////////////////////////////////
4640/// Get status of the async open request related to 'handle'.
4643{
4644 if (handle && handle->fFile) {
4645 if (!handle->fFile->IsZombie())
4646 return handle->fFile->GetAsyncOpenStatus();
4647 else
4648 return TFile::kAOSFailure;
4649 }
4650
4651 // Default is synchronous mode
4652 return TFile::kAOSNotAsync;
4653}
4654
4655////////////////////////////////////////////////////////////////////////////////
4656/// Get final URL for file being opened asynchronously.
4657/// Returns 0 is the information is not yet available.
4659const TUrl *TFile::GetEndpointUrl(const char* name)
4660{
4661 // Check the list of pending async open requests
4662 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4663 TIter nxr(fgAsyncOpenRequests);
4664 TFileOpenHandle *fh = nullptr;
4665 while ((fh = (TFileOpenHandle *)nxr()))
4666 if (fh->Matches(name))
4667 if (fh->fFile)
4668 return fh->fFile->GetEndpointUrl();
4669 }
4670
4671 // Check also the list of files open
4673 TSeqCollection *of = gROOT->GetListOfFiles();
4674 if (of && (of->GetSize() > 0)) {
4675 TIter nxf(of);
4676 TFile *f = nullptr;
4677 while ((f = (TFile *)nxf()))
4678 if (f->Matches(name))
4679 return f->GetEndpointUrl();
4680 }
4681
4682 // Information not yet available
4683 return (const TUrl *)nullptr;
4684}
4685
4686////////////////////////////////////////////////////////////////////////////////
4687/// Print file copy progress.
4690{
4691 fprintf(stderr, "[TFile::Cp] Total %.02f MB\t|", (Double_t)size/1048576);
4692
4693 for (int l = 0; l < 20; l++) {
4694 if (size > 0) {
4695 if (l < 20*bytesread/size)
4696 fprintf(stderr, "=");
4697 else if (l == 20*bytesread/size)
4698 fprintf(stderr, ">");
4699 else if (l > 20*bytesread/size)
4700 fprintf(stderr, ".");
4701 } else
4702 fprintf(stderr, "=");
4703 }
4704 // Allow to update the GUI while uploading files
4706 watch.Stop();
4707 Double_t lCopy_time = watch.RealTime();
4708 fprintf(stderr, "| %.02f %% [%.01f MB/s]\r",
4709 100.0*(size?(bytesread/((float)size)):1), (lCopy_time>0.)?bytesread/lCopy_time/1048576.:0.);
4710 watch.Continue();
4711}
4712
4713////////////////////////////////////////////////////////////////////////////////
4714/// Allows to copy this file to the dst URL. Returns kTRUE in case of success,
4715/// kFALSE otherwise.
4718{
4722
4723 TUrl dURL(dst, kTRUE);
4724
4725 TString oopt = "RECREATE";
4726 TString ourl = dURL.GetUrl();
4727
4728 // Set optimization options for the destination file
4729 TString opt = dURL.GetOptions();
4730 if (opt != "")
4731 opt += "&";
4732 // Files will be open in RAW mode
4733 opt += "filetype=raw";
4734
4735 dURL.SetOptions(opt);
4736
4737 char *copybuffer = nullptr;
4738
4739 TFile *sfile = this;
4740 TFile *dfile = nullptr;
4741
4742 // "RECREATE" does not work always well with XROOTD
4743 // namely when some pieces of the path are missing;
4744 // we force "NEW" in such a case
4745 if (TFile::GetType(ourl, "") == TFile::kNet) {
4746 if (gSystem->AccessPathName(ourl)) {
4747 oopt = "NEW";
4748 // Force creation of the missing parts of the path
4749 opt += "&mkpath=1";
4750 dURL.SetOptions(opt);
4751 }
4752 }
4753
4754 // Open destination file
4755 if (!(dfile = TFile::Open(dURL.GetUrl(), oopt))) {
4756 ::Error("TFile::Cp", "cannot open destination file %s", dst);
4757 goto copyout;
4758 }
4759
4760 // Probably we created a new file
4761 // We have to remove it in case of errors
4763
4764 sfile->Seek(0);
4765 dfile->Seek(0);
4766
4767 copybuffer = new char[bufsize];
4768 if (!copybuffer) {
4769 ::Error("TFile::Cp", "cannot allocate the copy buffer");
4770 goto copyout;
4771 }
4772
4775
4776 totalread = 0;
4777 filesize = sfile->GetSize();
4778
4779 watch.Start();
4780
4781 b00 = sfile->GetBytesRead();
4782
4783 do {
4784 if (progressbar) CpProgress(totalread, filesize,watch);
4785
4786 Long64_t b1 = sfile->GetBytesRead() - b00;
4787
4789 if (filesize - b1 > (Long64_t)bufsize) {
4790 readsize = bufsize;
4791 } else {
4792 readsize = filesize - b1;
4793 }
4794
4795 if (readsize == 0) break;
4796
4797 Long64_t b0 = sfile->GetBytesRead();
4799 readop = sfile->ReadBuffer(copybuffer, (Int_t)readsize);
4800 read = sfile->GetBytesRead() - b0;
4801 if ((read <= 0) || readop) {
4802 ::Error("TFile::Cp", "cannot read from source file %s. readsize=%lld read=%lld readop=%d",
4803 sfile->GetName(), readsize, read, readop);
4804 goto copyout;
4805 }
4806
4807 Long64_t w0 = dfile->GetBytesWritten();
4808 writeop = dfile->WriteBuffer(copybuffer, (Int_t)read);
4809 written = dfile->GetBytesWritten() - w0;
4810 if ((written != read) || writeop) {
4811 ::Error("TFile::Cp", "cannot write %lld bytes to destination file %s", read, dst);
4812 goto copyout;
4813 }
4814 totalread += read;
4815 } while (read == (Long64_t)bufsize);
4816
4817 if (progressbar) {
4818 CpProgress(totalread, filesize,watch);
4819 fprintf(stderr, "\n");
4820 }
4821
4822 success = kTRUE;
4823
4824copyout:
4825 if (dfile) dfile->Close();
4826
4827 if (dfile) delete dfile;
4828 if (copybuffer) delete[] copybuffer;
4829
4830 if (rmdestiferror && (success != kTRUE))
4831 gSystem->Unlink(dst);
4832
4833 watch.Stop();
4834 watch.Reset();
4835
4836 return success;
4837}
4838
4839////////////////////////////////////////////////////////////////////////////////
4840/// Allows to copy file from src to dst URL. Returns kTRUE in case of success,
4841/// kFALSE otherwise.
4843Bool_t TFile::Cp(const char *src, const char *dst, Bool_t progressbar,
4845{
4846 TUrl sURL(src, kTRUE);
4847
4848 TFile *sfile = nullptr;
4849
4851
4852 // Open source file
4853 if (!(sfile = TFile::Open(sURL.GetUrl(), "READ"))) {
4854 ::Error("TFile::Cp", "cannot open source file %s", src);
4855 } else {
4857 }
4858
4859 if (sfile) {
4860 sfile->Close();
4861 delete sfile;
4862 }
4863
4864 return success;
4865}
4866
4867//______________________________________________________________________________
4868//The next statement is not active anymore on Linux.
4869//Using posix_fadvise introduces a performance penalty (10 %) on optimized files
4870//and in addition it destroys the information of TTreePerfStats
4871#if defined(R__neverLINUX) && !defined(R__WINGCC)
4873{
4874 // Read specified byte range asynchronously. Actually we tell the kernel
4875 // which blocks we are going to read so it can start loading these blocks
4876 // in the buffer cache.
4877
4878 // Shortcut to avoid having to implement dummy ReadBufferAsync() in all
4879 // I/O plugins. Override ReadBufferAsync() in plugins if async is supported.
4880 if (IsA() != TFile::Class())
4881 return kTRUE;
4882
4884 if (len == 0) {
4885 // according POSIX spec if len is zero, all data following offset
4886 // is specified. Nevertheless ROOT uses zero to probe readahead
4887 // capabilities.
4889 }
4890 Double_t start = 0;
4891 if (gPerfStats) start = TTimeStamp();
4892#if defined(R__SEEK64)
4894#else
4896#endif
4897 if (gPerfStats) {
4898 gPerfStats->FileReadEvent(this, len, start);
4899 }
4900 return (result != 0);
4901}
4902#else
4904{
4905 // Not supported yet on non Linux systems.
4906
4907 return kTRUE;
4908}
4909#endif
4910
4911////////////////////////////////////////////////////////////////////////////////
4912/// Max number of bytes to prefetch.
4913///
4914/// By default this is 75% of the
4915/// read cache size. But specific TFile implementations may need to change it
4918{
4919 TFileCacheRead *cr = nullptr;
4920 if ((cr = GetCacheRead())) {
4921 Int_t bytes = cr->GetBufferSize() / 4 * 3;
4922 return ((bytes < 0) ? 0 : bytes);
4923 }
4924 return 0;
4925}
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:2584
@ 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:1660
TIterator(TFile *file, std::uint64_t addr)
Definition TFile.cxx:1653
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:4502
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:4323
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:2012
void ls(Option_t *option="") const override
List file contents.
Definition TFile.cxx:1478
ROOT::Detail::TKeyMapIterable WalkTKeys()
Traverses all TKeys in the TFile and returns information about them.
Definition TFile.cxx:1648
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:2336
static Bool_t GetOnlyStaged()
Returns staged only flag.
Definition TFile.cxx:4466
static void IncrementFileCounter()
Definition TFile.cxx:4332
static Bool_t ShrinkCacheFileDir(Long64_t shrinkSize, Long_t cleanupInteval=0)
Try to shrink the cache to the desired size.
Definition TFile.cxx:4378
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:4317
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:3450
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:4264
static TClass * Class()
virtual Int_t ReOpen(Option_t *mode)
Reopen a file with a different access mode.
Definition TFile.cxx:2224
virtual void ReadStreamerInfo()
Read the list of StreamerInfo from this file.
Definition TFile.cxx:3313
virtual Bool_t Matches(const char *name)
Return kTRUE if 'url' matches the coordinates of this file.
Definition TFile.cxx:4478
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=nullptr, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition TFile.cxx:2427
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:4295
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:3440
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:4320
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:1760
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:2381
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:4326
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:4218
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:1768
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:2467
static UInt_t GetOpenTimeout()
Returns open timeout (in ms).
Definition TFile.cxx:4446
static void CpProgress(Long64_t bytesread, Long64_t size, TStopwatch &watch)
Print file copy progress.
Definition TFile.cxx:4688
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:2581
static Long64_t GetFileBytesRead()
Static function returning the total number of bytes read from all files.
Definition TFile.cxx:4286
Int_t ReadBufferViaCache(char *buf, Int_t len)
Read buffer via cache.
Definition TFile.cxx:1950
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:2605
static Int_t GetReadaheadSize()
Static function returning the readahead buffer size.
Definition TFile.cxx:4311
~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:1882
static Long64_t GetFileCounter()
Definition TFile.cxx:4329
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:3471
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:2788
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:1490
TFileOpenHandle * fAsyncHandle
!For proper automatic cleanup
Definition TFile.h:186
static Bool_t SetOnlyStaged(Bool_t onlystaged)
Sets only staged flag.
Definition TFile.cxx:4456
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:4716
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:2498
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:2400
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:4063
virtual void SetCacheWrite(TFileCacheWrite *cache)
Set a pointer to the write cache.
Definition TFile.cxx:2450
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:2538
void SumBuffer(Int_t bufsize)
Increment statistics for buffer sizes of objects in this file.
Definition TFile.cxx:2479
static const char * GetCacheFileDir()
Get the directory where to locally stage/cache remote files.
Definition TFile.cxx:4366
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:3500
virtual Long64_t GetBytesWritten() const
Return the total number of bytes written so far to the file.
Definition TFile.cxx:4278
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:2367
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:2459
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:4209
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:4533
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:3458
virtual Long64_t SysSeek(Int_t fd, Long64_t offset, Int_t whence)
Interface to system lseek.
Definition TFile.cxx:4237
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:4255
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:4193
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:4436
virtual void ReadFree()
Read the FREE linked list.
Definition TFile.cxx:1986
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:4902
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:1505
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:2315
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:4916
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:3797
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:4338
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:2109
virtual TList * GetStreamerInfoList() final
Read the list of TStreamerInfo objects written to this file.
Definition TFile.cxx:1466
virtual void WriteHeader()
Write File Header.
Definition TFile.cxx:2677
@ 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:3582
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:1832
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:4226
static Int_t GetFileReadCalls()
Static function returning the total number of read calls from all files.
Definition TFile.cxx:4303
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:1614
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:386
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:715
@ 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:634
Bool_t IsNull() const
Definition TString.h:424
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:2459
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2437
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:643
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