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