Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TFile.cxx
Go to the documentation of this file.
1// @(#)root/io:$Id: 3a19890259ad6443ee313e090166614971ad4296 $
2// Author: Rene Brun 28/11/94
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/**
13\file TFile.cxx
14\class TFile
15\ingroup io_files
16\brief A file, usually with extension .root, that stores data and code in the form of serialized objects in a
17file-system-like logical structure, possibly including subdirectory hierarchies.
18\note ROOT files contain data, and executable code, for example through TExec, TMacro, and TFormula instances. As for
19all files, **do not open ROOT files from an unknown origin!**
20\note See also \ref IO
21\note See also \ref rootio (or `io/doc/TFile` folder in your codebase)
22
23ROOT files a are an efficient mean to store C++ class instances, e.g. data,
24both as individual objects, in a so called *row-wise fashion*, and in a
25*so-called columnar fashion*. Also executable code can be stored in ROOT files,
26for example in the form of TMacro, TExec or TFormula instances, and the
27related federation of classes.
28
29For example, a TCanvas or TPad instance may rely on TExec instances stored in
30their *list of executables* to obtain certain graphics effects: in this case,
31code will be executed upon drawing. A TH1 or a TGraph instance, as well as
32their multidimensional counterparts and derived classes, may also execute code
33upon drawing through TExec instances stored in their *list of functions*.
34Another example of code which is executable is represented by TFormula
35instances, that are the "computational workhorse" of function classes such as
36TF1, its multidimensional counterparts, and related classes. There, jitted C++
37code is executed for example upon evaluation, for example during fits or
38drawing operations, to obtain maximum runtime performance.
39
40
41<details>
42<summary>ROOT file data format specification</summary>
43
44A ROOT file is composed of a header, followed by consecutive data records
45(TKey instances) with a well defined format.
46
47The first data record starts at byte fBEGIN (currently set to kBEGIN).
48Bytes 1->kBEGIN contain the file description, when fVersion >= 1000000
49it is a large file (> 2 GB) and the offsets will be 8 bytes long and
50fUnits will be set to 8:
51
52Byte Range | Record Name | Description
53----------------|-------------|------------
541->4 | "root" | Root file identifier
555->8 | fVersion | File format version
569->12 | fBEGIN | Pointer to first data record
5713->16 [13->20] | fEND | Pointer to first free word at the EOF
5817->20 [21->28] | fSeekFree | Pointer to FREE data record
5921->24 [29->32] | fNbytesFree | Number of bytes in FREE data record
6025->28 [33->36] | nfree | Number of free data records
6129->32 [37->40] | fNbytesName | Number of bytes in TNamed at creation time
6233->33 [41->41] | fUnits | Number of bytes for file pointers
6334->37 [42->45] | fCompress | Compression level and algorithm
6438->41 [46->53] | fSeekInfo | Pointer to TStreamerInfo record
6542->45 [54->57] | fNbytesInfo | Number of bytes in TStreamerInfo record
6646->63 [58->75] | fUUID | Universal Unique ID
67
68For the purpose of magic bytes in the context of ROOT files' MIME definition,
69the following additional requirements are introduced:
70- The value of `fBEGIN` is fixed at 100.
71- The four bytes starting at position 96 are reserved and must be 0.
72If any changes to this need to be made, `media-types@iana.org` needs to be
73notified in accordance with RFC 6838.
74
75The key structure is as follows; if a key is located past the 32 bit file
76limit (> 2 GB) then some fields will be 8 instead of 4 bytes (see parts marked
77with square brackets below):
78
79Byte Range | Member Name | Description
80----------------|-----------|--------------
811->4 | Nbytes | Length of compressed object (in bytes)
825->6 | Version | TKey version identifier
837->10 | ObjLen | Length of uncompressed object
8411->14 | Datime | Date and time when object was written to file
8515->16 | KeyLen | Length of the key structure (in bytes)
8617->18 | Cycle | Cycle of key
8719->22 [19->26] | SeekKey | Pointer to record itself (consistency check)
8823->26 [27->34] | SeekPdir | Pointer to directory header
8927->27 [35->35] | lname | Number of bytes in the class name
9028->.. [36->..] | ClassName | Object Class Name
91..->.. | lname | Number of bytes in the object name
92..->.. | Name | lName bytes with the name of the object
93..->.. | lTitle | Number of bytes in the object title
94..->.. | Title | Title of the object
95-----> | DATA | Data bytes associated to the object
96
97Begin_Macro
98../../../tutorials/io/file.C
99End_Macro
100
101The structure of a directory is shown in TDirectoryFile::TDirectoryFile
102</details>
103*/
104
105#include <ROOT/RConfig.hxx>
106
107#ifdef R__LINUX
108// for posix_fadvise
109#ifndef _XOPEN_SOURCE
110#define _XOPEN_SOURCE 600
111#endif
112#endif
113#include <fcntl.h>
114#include <cerrno>
115#include <sys/stat.h>
116#ifndef WIN32
117#include <unistd.h>
118#ifndef R__FBSD
119#include <sys/xattr.h>
120#endif
121#else
122# define ssize_t int
123# include <io.h>
124# include <sys/types.h>
125#endif
126
127#include "Bytes.h"
128#include "Compression.h"
129#include "RConfigure.h"
130#include "strlcpy.h"
131#include "TArrayC.h"
132#include "TBuffer.h"
133#include "TClass.h"
134#include "TClassEdit.h"
135#include "TClassTable.h"
136#include "TDatime.h"
137#include "TError.h"
138#include "TFile.h"
139#include "TFileCacheRead.h"
140#include "TFileCacheWrite.h"
141#include "TFree.h"
142#include "TInterpreter.h"
143#include "TKey.h"
144#include "TMakeProject.h"
145#include "TPluginManager.h"
146#include "TProcessUUID.h"
147#include "TRegexp.h"
148#include "TPRegexp.h"
149#include "TROOT.h"
150#include "TStreamerInfo.h"
151#include "TStreamerElement.h"
152#include "TSystem.h"
153#include "TTimeStamp.h"
154#include "TVirtualPerfStats.h"
155#include "TArchiveFile.h"
156#include "TEnv.h"
157#include "TVirtualMonitoring.h"
158#include "TVirtualMutex.h"
159#include "TMap.h"
160#include "TMathBase.h"
161#include "TObjString.h"
162#include "TStopwatch.h"
163#include "compiledata.h"
164#include "TSchemaRule.h"
165#include "TSchemaRuleSet.h"
166#include "TThreadSlots.h"
167#include "TGlobal.h"
169#include "ROOT/InternalIOUtils.hxx"
170
171#include <cinttypes>
172#include <cmath>
173#include <cstdio>
174#include <cstring>
175#include <iostream>
176#include <memory>
177#include <set>
178
179#ifdef R__FBSD
180#include <sys/extattr.h>
181#endif
182
183using std::sqrt;
184
185std::atomic<Long64_t> TFile::fgBytesRead{0};
186std::atomic<Long64_t> TFile::fgBytesWrite{0};
187std::atomic<Long64_t> TFile::fgFileCounter{0};
188std::atomic<Int_t> TFile::fgReadCalls{0};
198
199#ifdef R__MACOSX
200/* On macOS getxattr takes two extra arguments that should be set to 0 */
201#define getxattr(path, name, value, size) getxattr(path, name, value, size, 0u, 0)
202#endif
203#ifdef R__FBSD
204#define getxattr(path, name, value, size) extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, value, size)
205#endif
207const Int_t kBEGIN = 100;
208
209
210//*-*x17 macros/layout_file
211// Needed to add the "fake" global gFile to the list of globals.
212namespace {
213static struct AddPseudoGlobals {
214AddPseudoGlobals() {
215 // User "gCling" as synonym for "libCore static initialization has happened".
216 // This code here must not trigger it.
218}
220}
221////////////////////////////////////////////////////////////////////////////////
222/// File default Constructor.
224TFile::TFile() : TDirectoryFile(), fCompress(ROOT::RCompressionSetting::EAlgorithm::kUseGlobal)
225{
226 fCacheReadMap = new TMap();
228
229 if (gDebug)
230 Info("TFile", "default ctor");
231}
232
233////////////////////////////////////////////////////////////////////////////////
234/// Opens or creates a local ROOT file.
235///
236/// \param[in] fname1 The name of the file
237/// \param[in] option Specifies the mode in which the file is opened
238/// \param[in] ftitle The title of the file
239/// \param[in] compress Specifies the compression algorithm and level
240///
241/// It is recommended to specify fname1 as "<file>.root". The suffix ".root"
242/// will be used by object browsers to automatically identify the file as
243/// a ROOT file. If the constructor fails in any way IsZombie() will
244/// return true. Use IsOpen() to check if the file is (still) open.
245/// To open non-local files use the static TFile::Open() method, that
246/// will take care of opening the files using the correct remote file
247/// access plugin.
248///
249/// Option | Description
250/// -------|------------
251/// NEW or CREATE | Create a new file and open it for writing, if the file already exists the file
252/// is not opened. RECREATE | Create a new file, if the file already exists it will be
253/// overwritten. UPDATE | Open an existing file for writing. If no file exists, it is
254/// created. READ | Open an existing file for reading (default). NET | Used by derived
255/// remote file access classes, not a user callable option. WEB | Used by derived remote
256/// http access class, not a user callable option. READ_WITHOUT_GLOBALREGISTRATION | Used by TTreeProcessorMT, not a
257/// user callable option.
258///
259/// If option = "" (default), READ is assumed.
260/// \note Even in READ mode, if the file is the current directory `cd()`, and you create e.g. a new histogram in your
261/// code, the histogram will be appended (but not written) to this directory, and automatically deleted when closing the
262/// file. To avoid this behavior, call hist->SetDirectory(nullptr); after creating it.
263///
264/// The file can be specified as a URL of the form:
265///
266/// file:///user/rdm/bla.root or file:/user/rdm/bla.root
267///
268/// The file can also be a member of an archive, in which case it is
269/// specified as:
270///
271/// multi.zip#file.root or multi.zip#0
272///
273/// which will open file.root which is a member of the file multi.zip
274/// archive or member 1 from the archive. For more on archive file
275/// support see the TArchiveFile class.
276/// TFile and its remote access plugins can also be used to open any
277/// file, i.e. also non ROOT files, using:
278///
279/// file.tar?filetype=raw
280///
281/// This can be convenient because the many file access plugins allow
282/// easy access to remote endpoints, e.g. mass storage pools.
283/// The title of the file (ftitle) will be shown by the ROOT browsers.
284/// A ROOT file (like a Unix file system) may contain objects and
285/// directories, as well as executable code. There are no restrictions
286/// for the number of levels of directories.
287/// A ROOT file is designed such that one can write in the file in pure
288/// sequential mode (case of BATCH jobs). In this case, the file may be
289/// read sequentially again without using the file index written
290/// at the end of the file. In case of a job crash, all the information
291/// on the file is therefore protected.
292/// A ROOT file can be used interactively. In this case, one has the
293/// possibility to delete existing objects and add new ones.
294/// When an object is deleted from the file, the freed space is added
295/// into the FREE linked list (fFree). The FREE list consists of a chain
296/// of consecutive free segments on the file. At the same time, the first
297/// 4 bytes of the freed record on the file are overwritten by GAPSIZE
298/// where GAPSIZE = -(Number of bytes occupied by the record).
299/// Option compress is used to specify the compression level and algorithm:
300///
301/// compress = 100 * algorithm + level
302///
303/// Level | Explanation
304/// ------|-------------
305/// 0 | objects written to this file will not be compressed.
306/// 1 | minimal compression level but fast.
307/// ... | ....
308/// 9 | maximal compression level but slower and might use more memory.
309/// (For the currently supported algorithms, the maximum level is 9)
310/// If compress is negative it indicates the compression level is not set yet.
311/// The enumeration ROOT::RCompressionSetting::EAlgorithm associates each
312/// algorithm with a number. There is a utility function to help
313/// to set the value of compress. For example,
314///
315/// ROOT::CompressionSettings(ROOT::kLZMA, 1)
316///
317/// will build an integer which will set the compression to use
318/// the LZMA algorithm and compression level 1. These are defined
319/// in the header file <em>Compression.h</em>.
320/// Note that the compression settings may be changed at any time.
321/// The new compression settings will only apply to branches created
322/// or attached after the setting is changed and other objects written
323/// after the setting is changed.
324/// In case the file does not exist or is not a valid ROOT file,
325/// it is made a Zombie. One can detect this situation with a code like:
326/// ~~~{.cpp}
327/// TFile f("file.root");
328/// if (f.IsZombie()) {
329/// std::cout << "Error opening file" << std::endl;
330/// exit(-1);
331/// }
332/// ~~~
333/// If you open a file instead with TFile::Open("file.root") use rather
334/// the following code as a nullptr is returned.
335/// ~~~{.cpp}
336/// TFile* f = TFile::Open("file.root");
337/// if (!f) {
338/// std::cout << "Error opening file" << std::endl;
339/// exit(-1);
340/// }
341/// ~~~
342/// When opening the file, the system checks the validity of this directory.
343/// If something wrong is detected, an automatic recovery is performed. In
344/// this case, the file is scanned sequentially reading all logical blocks
345/// and attempting to rebuild a correct directory (see TFile::Recover).
346/// One can disable the automatic recovery procedure when reading one
347/// or more files by setting the environment variable "TFile.Recover: 0"
348/// in the system.rootrc file.
349///
350/// A bit `TFile::kReproducible` can be enabled specifying
351/// the `"reproducible"` url option when creating the file:
352/// ~~~{.cpp}
353/// TFile *f = TFile::Open("name.root?reproducible","RECREATE","File title");
354/// ~~~
355/// Unlike regular `TFile`s, the content of such file has reproducible binary
356/// content when writing exactly same data. This achieved by writing pre-defined
357/// values for creation and modification date of TKey/TDirectory objects and
358/// null value for TUUID objects inside TFile. As drawback, TRef objects stored
359/// in such file cannot be read correctly.
360///
361/// In case the name of the file is not reproducible either (in case of
362/// creating temporary filenames) a value can be passed to the reproducible
363/// option to replace the name stored in the file.
364/// ~~~{.cpp}
365/// TFile *f = TFile::Open("tmpname.root?reproducible=fixedname","RECREATE","File title");
366/// ~~~
367///
368/// To check for the health status of a TFile and detect corruption, you can perform the following checks after opening it:
369/// ~~~{.cpp}
370/// std::unique_ptr<TFile> f{TFile::Open("name.root", "READ")};
371/// auto bad_input = (f == nullptr); // File could not be open, e.g. if input url was incorrect or incorrect permissions.
372/// auto bad_initalization = (f && f->IsZombie()); // something went wrong in the constructor, for example when TFile is corrupt
373/// auto bad_storage = (f && f->TestBit(TFile::kRecovered)); // The TFile had to run the recovery mechanism when opening the file; often due to the file being incorrectly closed.
374/// ~~~
376TFile::TFile(const char *fname1, Option_t *option, const char *ftitle, Int_t compress)
377 : TDirectoryFile(), fCompress(compress), fUrl(fname1,kTRUE)
378{
379 if (!gROOT)
380 ::Fatal("TFile::TFile", "ROOT system not initialized");
381
382 auto zombify = [this] {
383 // error in file opening occurred, make this object a zombie
386 gROOT->GetListOfClosedObjects()->Add(this);
387 }
388 MakeZombie();
390 };
391
392 fOption = option;
394
395 if (strlen(fUrl.GetProtocol()) != 0 && strcmp(fUrl.GetProtocol(), "file") != 0 && !fOption.BeginsWith("NET") &&
396 !fOption.BeginsWith("WEB")) {
397 Error("TFile",
398 "please use TFile::Open to access remote files:\n\tauto f = std::unique_ptr<TFile>{TFile::Open(\"%s\")};",
399 fname1);
400 zombify();
401 return;
402 }
403
404 // store name without the options as name and title
406 if (sfname1.Index("?") != kNPOS) {
407 TString s = sfname1(0, sfname1.Index("?"));
408 SetName(s);
410 } else
412
414
415 // accept also URL like "file:..." syntax
416 fname1 = fUrl.GetFile();
417
418 // if option contains filetype=raw then go into raw file mode
419 if (strstr(fUrl.GetOptions(), "filetype=raw"))
421
422 // if option contains filetype=pcm then go into ROOT PCM file mode
423 if (strstr(fUrl.GetOptions(), "filetype=pcm"))
425
426 if (fUrl.HasOption("reproducible"))
428
429 // We are opening synchronously
431
432 BuildDirectoryFile(this, nullptr);
433
434 fVersion = gROOT->GetVersionInt(); //ROOT version in integer format
435 fUnits = 4;
436 fCacheReadMap = new TMap();
438
439 if (fIsRootFile && !fIsPcmFile && fOption != "NEW" && fOption != "CREATE"
440 && fOption != "RECREATE") {
441 // If !gPluginMgr then we are at startup and cannot handle plugins
442 // as TArchiveFile yet.
443 fArchive = gPluginMgr ? TArchiveFile::Open(fUrl.GetUrl(), this) : nullptr;
444 if (fArchive) {
446 // if no archive member is specified then this TFile is just used
447 // to read the archive contents
450 }
451 }
452
453 if (fOption.Contains("_WITHOUT_GLOBALREGISTRATION")) {
454 fOption = fOption.ReplaceAll("_WITHOUT_GLOBALREGISTRATION", "");
455 fGlobalRegistration = false;
456 if (fList) {
457 fList->UseRWLock(false);
458 }
459 }
460
461 if (fOption == "NET")
462 return;
463
464 if (fOption == "WEB") {
465 fOption = "READ";
467 return;
468 }
469
470 if (fOption == "NEW")
471 fOption = "CREATE";
472
473 Bool_t create = (fOption == "CREATE") ? kTRUE : kFALSE;
474 Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE;
475 Bool_t update = (fOption == "UPDATE") ? kTRUE : kFALSE;
476 Bool_t read = (fOption == "READ") ? kTRUE : kFALSE;
477 if (!create && !recreate && !update && !read) {
478 read = kTRUE;
479 fOption = "READ";
480 }
481
483
484 if (!fname1 || !fname1[0]) {
485 Error("TFile", "file name is not specified");
486 zombify();
487 return;
488 }
489
490 // support dumping to /dev/null on UNIX
491 if (!strcmp(fname1, "/dev/null") &&
493 devnull = kTRUE;
494 create = kTRUE;
496 update = kFALSE;
497 read = kFALSE;
498 fOption = "CREATE";
500 }
501
504 SetName(fname.Data());
505 fRealName = GetName();
508 }
509 fname = fRealName.Data();
510 } else {
511 Error("TFile", "error expanding path %s", fname1);
512 zombify();
513 return;
514 }
515
516 // If the user supplied a value to the option take it as the name to set for
517 // the file instead of the actual filename
518 if (TestBit(kReproducible)) {
519 if(auto name=fUrl.GetValueFromOptions("reproducible")) {
520 SetName(name);
521 }
522 }
523
524 if (recreate) {
525 if (!gSystem->AccessPathName(fname.Data(), kFileExists)) {
526 if (gSystem->Unlink(fname.Data()) != 0) {
527 SysError("TFile", "could not delete %s (errno: %d)",
528 fname.Data(), gSystem->GetErrno());
529 zombify();
530 return;
531 }
532 }
534 create = kTRUE;
535 fOption = "CREATE";
536 }
537 if (create && !devnull && !gSystem->AccessPathName(fname.Data(), kFileExists)) {
538 Error("TFile", "file %s already exists", fname.Data());
539 zombify();
540 return;
541 }
542 if (update) {
543 if (gSystem->AccessPathName(fname.Data(), kFileExists)) {
544 update = kFALSE;
545 create = kTRUE;
546 }
548 Error("TFile", "no write permission, could not open file %s", fname.Data());
549 zombify();
550 return;
551 }
552 }
553 if (read) {
554 if (gSystem->AccessPathName(fname.Data(), kFileExists)) {
555 Error("TFile", "file %s does not exist", fname.Data());
556 zombify();
557 return;
558 }
560 Error("TFile", "no read permission, could not open file %s", fname.Data());
561 zombify();
562 return;
563 }
564 }
565
566 // Connect to file system stream
567 if (create || update) {
568#ifndef WIN32
569 fD = TFile::SysOpen(fname.Data(), O_RDWR | O_CREAT, 0666);
570#else
572#endif
573 if (fD == -1) {
574 SysError("TFile", "file %s can not be opened", fname.Data());
575 zombify();
576 return;
577 }
579 } else {
580#ifndef WIN32
581 fD = TFile::SysOpen(fname.Data(), O_RDONLY, 0666);
582#else
584#endif
585 if (fD == -1) {
586 SysError("TFile", "file %s can not be opened for reading", fname.Data());
587 zombify();
588 return;
589 }
591 }
592
593 // calling virtual methods from constructor not a good idea, but it is how code was developed
594 TFile::Init(create); // NOLINT: silence clang-tidy warnings
595}
596
597////////////////////////////////////////////////////////////////////////////////
598/// File destructor.
601{
602 Close(); // NOLINT: silence clang-tidy warnings
603
604 // In case where the TFile is still open at 'tear-down' time the order of operation will be
605 // call Close("nodelete")
606 // then later call delete TFile
607 // which means that at this point we might still have object held and those
608 // might requires a 'valid' TFile object in their destructor (for example,
609 // TTree call's GetReadCache which expects a non-null fCacheReadMap).
610 // So delete the objects (if any) now.
611
612 if (fList)
613 fList->Delete("slow");
614
624
627 gROOT->GetListOfClosedObjects()->Remove(this);
628 gROOT->GetUUIDs()->RemoveUUID(GetUniqueID());
629 }
630
631 if (IsOnHeap()) {
632 // Delete object from Cling symbol table so it can not be used anymore.
633 // Cling objects are always on the heap.
634 gInterpreter->ResetGlobalVar(this);
635 }
636
637 if (gDebug)
638 Info("~TFile", "dtor called for %s [%zx]", GetName(),(size_t)this);
639}
640
641////////////////////////////////////////////////////////////////////////////////
642/// Initialize a TFile object.
643///
644/// \param[in] create Create a new file.
645///
646/// TFile implementations providing asynchronous open functionality need to
647/// override this method to run the appropriate checks before calling this
648/// standard initialization part. See TNetXNGFile::Init for an example.
650void TFile::Init(Bool_t create)
651{
652 if (fInitDone)
653 // Already called once
654 return;
656
657 if (!fIsRootFile) {
659 return;
660 }
661
662 if (fArchive) {
663 if (fOption != "READ") {
664 Error("Init", "archive %s can only be opened in read mode", GetName());
665 delete fArchive;
666 fArchive = nullptr;
668 goto zombie;
669 }
670
672
673 if (fIsArchive) return;
674
675 // Make sure the anchor is in the name
676 if (!fNoAnchorInName)
677 if (!strchr(GetName(),'#'))
679
680 if (fArchive->SetCurrentMember() != -1)
682 else {
683 Error("Init", "member %s not found in archive %s",
685 delete fArchive;
686 fArchive = nullptr;
688 goto zombie;
689 }
690 }
691
692 Int_t nfree;
693 fBEGIN = (Long64_t)kBEGIN; //First used word in file following the file header
694
695 // make newly opened file the current file and directory
696 cd();
697
698 if (create) {
699 //*-*---------------NEW file
700 fFree = new TList;
701 fEND = fBEGIN; //Pointer to end of file
702 new TFree(fFree, fBEGIN, Long64_t(kStartBigFile)); //Create new free list
703
704 //*-* -------------Check if we need to enable forward compatible with version
705 //*-* -------------prior to v6.30
706 if (gEnv->GetValue("TFile.v630forwardCompatibility", 0) == 1)
708
709 //*-* Write Directory info
712 TKey *key = new TKey(fName, fTitle, IsA(), nbytes, this);
713 fNbytesName = key->GetKeylen() + namelen;
714 fSeekDir = key->GetSeekKey();
715 fSeekFree = 0;
716 fNbytesFree = 0;
717 WriteHeader();
718 char *buffer = key->GetBuffer();
719 TNamed::FillBuffer(buffer);
721 key->WriteFile();
722 delete key;
723 } else {
724 //*-*----------------UPDATE
725 //char *header = new char[kBEGIN];
726 char *header = new char[kBEGIN+200];
727 Seek(0); // NOLINT: silence clang-tidy warnings
728 //ReadBuffer(header, kBEGIN);
729 if (ReadBuffer(header, kBEGIN+200)) { // NOLINT: silence clang-tidy warnings
730 // ReadBuffer returns kTRUE in case of failure.
731 Error("Init","%s failed to read the file type data.",
732 GetName());
733 delete [] header;
734 goto zombie;
735 }
736
737 // make sure this is a ROOT file
738 if (strncmp(header, "root", 4)) {
739 Error("Init", "%s not a ROOT file", GetName());
740 delete [] header;
741 goto zombie;
742 }
743
744 char *buffer = header + 4; // skip the "root" file identifier
745 frombuf(buffer, &fVersion);
747 frombuf(buffer, &headerLength);
749 if (fVersion < 1000000) { //small file
751 frombuf(buffer, &send); fEND = (Long64_t)send;
752 frombuf(buffer, &sfree); fSeekFree= (Long64_t)sfree;
753 frombuf(buffer, &fNbytesFree);
754 frombuf(buffer, &nfree);
755 frombuf(buffer, &fNbytesName);
756 frombuf(buffer, &fUnits );
757 frombuf(buffer, &fCompress);
758 frombuf(buffer, &sinfo); fSeekInfo = (Long64_t)sinfo;
759 frombuf(buffer, &fNbytesInfo);
760 } else { // new format to support large files
761 frombuf(buffer, &fEND);
762 frombuf(buffer, &fSeekFree);
763 frombuf(buffer, &fNbytesFree);
764 frombuf(buffer, &nfree);
765 frombuf(buffer, &fNbytesName);
766 frombuf(buffer, &fUnits );
767 frombuf(buffer, &fCompress);
768 frombuf(buffer, &fSeekInfo);
769 frombuf(buffer, &fNbytesInfo);
770 }
772 // humm fBEGIN is wrong ....
773 Error("Init","file %s has an incorrect header length (%lld) or incorrect end of file length (%lld)",
775 delete [] header;
776 goto zombie;
777 }
779 //*-*-------------Read Free segments structure if file is writable
780 if (fWritable) {
781 fFree = new TList;
782 if (fSeekFree > fBEGIN) {
783 ReadFree(); // NOLINT: silence clang-tidy warnings
784 } else {
785 Warning("Init","file %s probably not closed, cannot read free segments",GetName());
786 }
787 }
788 //*-*-------------Read directory info
789 // buffer_keyloc is the start of the key record.
790 char *buffer_keyloc = nullptr;
791
793 if ( (nbytes + fBEGIN) > fEND) {
794 // humm fBEGIN is wrong ....
795 Error("Init","file %s has an incorrect header length (%lld) or incorrect end of file length (%lld)",
797 delete [] header;
798 goto zombie;
799 }
800 if (nbytes+fBEGIN > kBEGIN+200) {
801 delete [] header;
802 header = new char[nbytes];
803 buffer = header;
804 Seek(fBEGIN); // NOLINT: silence clang-tidy warnings
805 if (ReadBuffer(buffer,nbytes)) { // NOLINT: silence clang-tidy warnings
806 // ReadBuffer returns kTRUE in case of failure.
807 Error("Init","%s failed to read the file header information at %lld (size=%d)",
809 delete [] header;
810 goto zombie;
811 }
812 buffer = header+fNbytesName;
813 buffer_keyloc = header;
814 } else {
815 buffer = header+fBEGIN+fNbytesName;
816 buffer_keyloc = header+fBEGIN;
817 }
819 frombuf(buffer,&version); versiondir = version%1000;
820 fDatimeC.ReadBuffer(buffer);
821 fDatimeM.ReadBuffer(buffer);
822 frombuf(buffer, &fNbytesKeys);
823 frombuf(buffer, &fNbytesName);
824 if (version > 1000) {
825 frombuf(buffer, &fSeekDir);
826 frombuf(buffer, &fSeekParent);
827 frombuf(buffer, &fSeekKeys);
828 } else {
830 frombuf(buffer, &sdir); fSeekDir = (Long64_t)sdir;
832 frombuf(buffer, &skeys); fSeekKeys = (Long64_t)skeys;
833 }
834 if (versiondir > 1) fUUID.ReadBuffer(buffer);
835
836 //*-*---------read TKey::FillBuffer info
837 buffer_keyloc += sizeof(Int_t); // Skip NBytes;
840 // Skip ObjLen, DateTime, KeyLen, Cycle, SeekKey, SeekPdir
841 if (keyversion > 1000) {
842 // Large files
843 buffer_keyloc += 2*sizeof(Int_t)+2*sizeof(Short_t)+2*sizeof(Long64_t);
844 } else {
845 buffer_keyloc += 2*sizeof(Int_t)+2*sizeof(Short_t)+2*sizeof(Int_t);
846 }
848 cname.ReadBuffer(buffer_keyloc);
849 cname.ReadBuffer(buffer_keyloc); // fName.ReadBuffer(buffer); file may have been renamed
851 delete [] header;
853 Error("Init","cannot read directory info of file %s", GetName());
854 goto zombie;
855 }
856
857 //*-* -------------Check if file is truncated
859 if ((size = GetSize()) == -1) { // NOLINT: silence clang-tidy warnings
860 Error("Init", "cannot stat the file %s", GetName());
861 goto zombie;
862 }
863
864 //*-* -------------Check if, in case of inconsistencies, we are requested to
865 //*-* -------------attempt recovering the file
866 Bool_t tryrecover = (gEnv->GetValue("TFile.Recover", 1) == 1) ? kTRUE : kFALSE;
867
868 //*-* -------------Check if we need to enable forward compatible with version
869 //*-* -------------prior to v6.30
870 if (gEnv->GetValue("TFile.v630forwardCompatibility", 0) == 1)
872
873 //*-* -------------Read keys of the top directory
874 if (fSeekKeys > fBEGIN && fEND <= size) {
875 //normal case. Recover only if file has no keys
877 gDirectory = this;
878 if (!GetNkeys()) {
879 if (tryrecover) {
880 Recover(); // NOLINT: silence clang-tidy warnings
881 } else {
882 Error("Init", "file %s has no keys", GetName());
883 goto zombie;
884 }
885 }
886 } else if ((fBEGIN+nbytes == fEND) && (fEND == size)) {
887 //the file might be open by another process and nothing written to the file yet
888 Warning("Init","file %s has no keys", GetName());
889 gDirectory = this;
890 } else {
891 //something had been written to the file. Trailer is missing, must recover
892 if (fEND > size) {
893 if (tryrecover) {
894 Error("Init","file %s is truncated at %lld bytes: should be %lld, "
895 "trying to recover", GetName(), size, fEND);
896 } else {
897 Error("Init","file %s is truncated at %lld bytes: should be %lld",
898 GetName(), size, fEND);
899 goto zombie;
900 }
901 } else {
902 if (tryrecover) {
903 Warning("Init","file %s probably not closed, "
904 "trying to recover", GetName());
905 } else {
906 Warning("Init","file %s probably not closed", GetName());
907 goto zombie;
908 }
909 }
910 Int_t nrecov = Recover(); // NOLINT: silence clang-tidy warnings
911 if (nrecov) {
912 Warning("Init", "successfully recovered %d keys", nrecov);
913 } else {
914 Warning("Init", "no keys recovered, file has been made a Zombie");
915 goto zombie;
916 }
917 }
918 }
919
922 gROOT->GetListOfFiles()->Add(this);
923 gROOT->GetUUIDs()->AddUUID(fUUID, this);
924 }
925
926 // Create StreamerInfo index
927 {
928 Int_t lenIndex = gROOT->GetListOfStreamerInfo()->GetSize()+1;
929 if (lenIndex < 5000) lenIndex = 5000;
931 if (fgReadInfo) {
932 if (fSeekInfo > fBEGIN) {
933 ReadStreamerInfo(); // NOLINT: silence clang-tidy warnings
934 if (IsZombie()) {
936 gROOT->GetListOfFiles()->Remove(this);
937 goto zombie;
938 }
939 } else if (fVersion != gROOT->GetVersionInt() && fVersion > 30000) {
940 // Don't complain about missing streamer info for empty files.
941 if (fKeys->GetSize()) {
942 // #14068: we take into account the different way of expressing the version
943 const auto separator = fVersion < 63200 ? "/" : ".";
944 const auto thisVersion = gROOT->GetVersionInt();
945 const auto msg = "no StreamerInfo found in %s therefore preventing schema evolution when reading this file. "
946 "The file was produced with ROOT version %d.%02d%s%02d, "
947 "while the current version is %d.%02d.%02d";
948 Warning("Init", msg,
949 GetName(),
950 fVersion / 10000, (fVersion / 100) % (100), separator, fVersion % 100,
951 thisVersion / 10000, (thisVersion / 100) % (100), thisVersion % 100);
952 }
953 }
954 }
955 }
956
957 // Count number of TProcessIDs in this file
958 {
959 TIter next(fKeys);
960 TKey *key;
961 while ((key = (TKey*)next())) {
962 if (!strcmp(key->GetClassName(),"TProcessID")) fNProcessIDs++;
963 }
965 }
966
967 return;
968
969zombie:
972 gROOT->GetListOfClosedObjects()->Add(this);
973 }
974 // error in file opening occurred, make this object a zombie
976 MakeZombie();
978}
979
980////////////////////////////////////////////////////////////////////////////////
981/// Close a file.
982///
983/// \param[in] option If option == "R", all TProcessIDs referenced by this file are deleted.
984///
985/// Calling TFile::Close("R") might be necessary in case one reads a long list
986/// of files having TRef, writing some of the referenced objects or TRef
987/// to a new file. If the TRef or referenced objects of the file being closed
988/// will not be referenced again, it is possible to minimize the size
989/// of the TProcessID data structures in memory by forcing a delete of
990/// the unused TProcessID.
993{
994 TString opt = option;
995
996 opt.ToLower();
997
998 if (!IsOpen()) return;
999
1000 if (fIsArchive || !fIsRootFile) {
1002 SysClose(fD);
1003 fD = -1;
1004
1007
1008 return;
1009 }
1010
1011 if (IsWritable()) {
1013 }
1014
1015 // Finish any concurrent I/O operations before we close the file handles.
1016 if (fCacheRead) fCacheRead->Close();
1017 {
1018 TIter iter(fCacheReadMap);
1019 TObject *key = nullptr;
1020 while ((key = iter()) != nullptr) {
1021 TFileCacheRead *cache = dynamic_cast<TFileCacheRead *>(fCacheReadMap->GetValue(key));
1022 cache->Close();
1023 }
1024 }
1025
1026 // Delete all supported directories structures from memory
1027 // If gDirectory points to this object or any of the nested
1028 // TDirectoryFile, TDirectoryFile::Close will induce the proper cd.
1029 fMustFlush = kFALSE; // Make sure there is only one Flush.
1031
1032 if (IsWritable()) {
1033 TFree *f1 = (TFree*)fFree->First();
1034 if (f1) {
1035 WriteFree(); //*-*- Write free segments linked list
1036 WriteHeader(); //*-*- Now write file header ; this forces a Flush/fsync
1037 } else {
1038 Flush();
1039 }
1040 }
1041 fMustFlush = kTRUE;
1042
1044
1047
1048 delete fClassIndex;
1049 fClassIndex = nullptr;
1050
1051 // Delete free segments from free list (but don't delete list header)
1052 if (fFree) {
1053 fFree->Delete();
1054 }
1055
1056 if (IsOpen()) {
1057 SysClose(fD);
1058 fD = -1;
1059 }
1060
1061 fWritable = kFALSE;
1062
1063 // delete the TProcessIDs
1065 TIter next(fProcessIDs);
1066 TProcessID *pid;
1067 while ((pid = (TProcessID*)next())) {
1068 if (!pid->DecrementCount()) {
1070 } else if(opt.Contains("r")) {
1071 pid->Clear();
1072 }
1073 }
1074 pidDeleted.Delete();
1075
1076 if (!IsZombie() && fGlobalRegistration) {
1078 gROOT->GetListOfFiles()->Remove(this);
1079 gROOT->GetListOfBrowsers()->RecursiveRemove(this);
1080 gROOT->GetListOfClosedObjects()->Add(this);
1081 } else {
1082 // If we are a zombie, we are already in the list of closed objects.
1083 }
1084}
1085
1086////////////////////////////////////////////////////////////////////////////////
1087/// Creates key for object and converts data to buffer.
1089TKey* TFile::CreateKey(TDirectory* mother, const TObject* obj, const char* name, Int_t bufsize)
1090{
1091 return new TKey(obj, name, bufsize, mother);
1092}
1093
1094////////////////////////////////////////////////////////////////////////////////
1095/// Creates key for object and converts data to buffer.
1097TKey* TFile::CreateKey(TDirectory* mother, const void* obj, const TClass* cl, const char* name, Int_t bufsize)
1098{
1099 return new TKey(obj, cl, name, bufsize, mother);
1100}
1101
1102////////////////////////////////////////////////////////////////////////////////
1103/// Return the current ROOT file if any.
1104///
1105/// Note that if 'cd' has been called on a TDirectory that does not belong to a file,
1106/// gFile will be unchanged and still points to the file of the previous current
1107/// directory that was a file.
1110{
1111 static TFile *currentFile = nullptr;
1112 if (!gThreadTsd)
1113 return currentFile;
1114 else
1116}
1117
1118////////////////////////////////////////////////////////////////////////////////
1119/// \copydoc TDirectoryFile::Delete
1121void TFile::Delete(const char *namecycle)
1122{
1123 if (gDebug)
1124 Info("Delete", "deleting name = %s", namecycle);
1125
1127}
1128
1129////////////////////////////////////////////////////////////////////////////////
1130/// Fill Graphics Structure and Paint.
1131///
1132/// Loop on all objects (memory or file) and all subdirectories.
1135{
1136 GetList()->R__FOR_EACH(TObject,Draw)(option);
1137}
1138
1139////////////////////////////////////////////////////////////////////////////////
1140/// Draw map of objects in this file. The map drawing is handled by TFileDrawMap.
1141/// Once the map is drawn, turn on the TCanvas option "View->Event Statusbar". Then, when
1142/// moving the mouse in the canvas, the "Event Status" panels shows the object corresponding
1143/// to the mouse position.
1144///
1145/// Example:
1146/// ~~~{.cpp}
1147/// auto f = new TFile("myfile.root");
1148/// f->DrawMap();
1149/// ~~~
1151void TFile::DrawMap(const char *keys, Option_t *option)
1152{
1154 if ((h = gROOT->GetPluginManager()->FindHandler("TFileDrawMap"))) {
1155 if (h->LoadPlugin() == -1) {
1156 ::Error("TFile::Open", "Failed to load plugin TFileDrawMap");
1157 return;
1158 }
1159 h->ExecPlugin(3, this, keys, option);
1160 }
1161}
1162
1163////////////////////////////////////////////////////////////////////////////////
1164/// Synchronize a file's in-memory and on-disk states.
1166void TFile::Flush()
1167{
1168 if (IsOpen() && fWritable) {
1170 if (SysSync(fD) < 0) {
1171 // Write the system error only once for this file
1173 SysError("Flush", "error flushing file %s", GetName());
1174 }
1175 }
1176}
1177
1178////////////////////////////////////////////////////////////////////////////////
1179/// Flush the write cache if active.
1180///
1181/// Return kTRUE in case of error
1184{
1185 if (fCacheWrite && IsOpen() && fWritable)
1186 return fCacheWrite->Flush();
1187 return kFALSE;
1188}
1189
1190////////////////////////////////////////////////////////////////////////////////
1191/// Encode file output buffer.
1192///
1193/// The file output buffer contains only the FREE data record.
1195void TFile::FillBuffer(char *&buffer)
1196{
1198 tobuf(buffer, version);
1199}
1200
1201////////////////////////////////////////////////////////////////////////////////
1202/// Return the best buffer size of objects on this file.
1203///
1204/// The best buffer size is estimated based on the current mean value
1205/// and standard deviation of all objects written so far to this file.
1206/// Returns mean value + one standard deviation.
1209{
1210 if (!fWritten) return TBuffer::kInitialSize;
1213 Double_t result = mean + sqrt(rms2);
1214 if (result >= (double)std::numeric_limits<Int_t>::max()) {
1215 return std::numeric_limits<Int_t>::max() -1;
1216 } else {
1217 return (Int_t)result;
1218 }
1219}
1220
1221////////////////////////////////////////////////////////////////////////////////
1222/// Return the file compression factor.
1223///
1224/// Add total number of compressed/uncompressed bytes for each key.
1225/// Returns the ratio of the two.
1228{
1230 UInt_t datime;
1231 Int_t nbytes, objlen, nwh = 64;
1232 char *header = new char[fBEGIN];
1233 char *buffer;
1236 comp = uncomp = fBEGIN;
1237
1238 while (idcur < fEND-100) {
1239 Seek(idcur);
1240 if (ReadBuffer(header, nwh)) {
1241 // ReadBuffer returns kTRUE in case of failure.
1242// Error("GetCompressionFactor","%s failed to read the key header information at %lld (size=%d).",
1243// GetName(),idcur,nwh);
1244 break;
1245 }
1246 buffer=header;
1247 frombuf(buffer, &nbytes);
1248 if (nbytes < 0) {
1249 idcur -= nbytes;
1250 Seek(idcur);
1251 continue;
1252 }
1253 if (nbytes == 0) break; //this may happen when the file is corrupted
1255 frombuf(buffer, &versionkey);
1256 frombuf(buffer, &objlen);
1257 frombuf(buffer, &datime);
1258 frombuf(buffer, &keylen);
1259 if (!objlen) objlen = nbytes-keylen;
1260 comp += nbytes;
1261 uncomp += keylen + objlen;
1262 idcur += nbytes;
1263 }
1264 delete [] header;
1265 return uncomp/comp;
1266}
1267
1268////////////////////////////////////////////////////////////////////////////////
1269/// Method returning errno.
1271Int_t TFile::GetErrno() const
1272{
1273 return TSystem::GetErrno();
1274}
1275
1276////////////////////////////////////////////////////////////////////////////////
1277/// Method resetting the errno.
1279void TFile::ResetErrno() const
1280{
1282}
1283
1284////////////////////////////////////////////////////////////////////////////////
1285/// Return a pointer to the current read cache.
1287TFileCacheRead *TFile::GetCacheRead(const TObject* tree) const
1288{
1289 if (!tree) {
1290 if (!fCacheRead && fCacheReadMap->GetSize() == 1) {
1291 TIter next(fCacheReadMap);
1292 return (TFileCacheRead *)fCacheReadMap->GetValue(next());
1293 }
1294 return fCacheRead;
1295 }
1297 if (!cache) return fCacheRead;
1298 return cache;
1299}
1300
1301////////////////////////////////////////////////////////////////////////////////
1302/// Return a pointer to the current write cache.
1305{
1306 return fCacheWrite;
1307}
1308
1309////////////////////////////////////////////////////////////////////////////////
1310/// Read the logical record header starting at a certain postion.
1311///
1312/// \param[in] buf pointer to buffer
1313/// \param[in] first read offset
1314/// \param[in] maxbytes Bytes which are read into buf.
1315/// \param[out] nbytes Number of bytes in record if negative, this is a deleted
1316/// record if 0, cannot read record, wrong value of argument first
1317/// \param[out] objlen Uncompressed object size
1318/// \param[out] keylen Length of logical record header
1319///
1320/// The function reads nread bytes
1321/// where nread is the minimum of maxbytes and the number of bytes
1322/// before the end of file. The function returns nread.
1323/// Note that the arguments objlen and keylen are returned only
1324/// if maxbytes >=16
1327{
1328 nbytes = 0;
1329 objlen = 0;
1330 keylen = 0;
1331 if (first < fBEGIN) return 0;
1332 if (first > fEND) return 0;
1333 Seek(first);
1335 if (first+maxbytes > fEND) nread = fEND-maxbytes;
1336 if (nread < 4) {
1337 Warning("GetRecordHeader","%s: parameter maxbytes = %d must be >= 4",
1338 GetName(), nread);
1339 return nread;
1340 }
1341 if (ReadBuffer(buf,nread)) {
1342 // ReadBuffer return kTRUE in case of failure.
1343 Warning("GetRecordHeader","%s: failed to read header data (maxbytes = %d)",
1344 GetName(), nread);
1345 return nread;
1346 }
1348 Short_t klen;
1349 UInt_t datime;
1350 Int_t nb,olen;
1351 char *buffer = buf;
1352 frombuf(buffer,&nb);
1353 nbytes = nb;
1354 if (nb < 0) return nread;
1355 // const Int_t headerSize = Int_t(sizeof(nb) +sizeof(versionkey) +sizeof(olen) +sizeof(datime) +sizeof(klen));
1356 const Int_t headerSize = 16;
1357 if (nread < headerSize) return nread;
1358 frombuf(buffer, &versionkey);
1359 frombuf(buffer, &olen);
1360 frombuf(buffer, &datime);
1361 frombuf(buffer, &klen);
1362 if (!olen) olen = nbytes-klen;
1363 objlen = olen;
1364 keylen = klen;
1365 return nread;
1366}
1367
1368////////////////////////////////////////////////////////////////////////////////
1369/// Returns the current file size. Returns -1 in case the file could not
1370/// be stat'ed.
1373{
1374 Long64_t size;
1375
1376 if (fArchive && fArchive->GetMember()) {
1378 } else {
1379 Long_t id, flags, modtime;
1380 if (const_cast<TFile*>(this)->SysStat(fD, &id, &size, &flags, &modtime)) { // NOLINT: silence clang-tidy warnings
1381 Error("GetSize", "cannot stat the file %s", GetName());
1382 return -1;
1383 }
1384 }
1385 return size;
1386}
1387
1388////////////////////////////////////////////////////////////////////////////////
1389/// Returns the cached list of StreamerInfos used in this file.
1394}
1395
1396////////////////////////////////////////////////////////////////////////////////
1397/// See documentation of GetStreamerInfoList for more details.
1398/// This is an internal method which returns the list of streamer infos and also
1399/// information about the success of the operation.
1402{
1404
1405 if (fIsPcmFile) return {nullptr, 1, hash}; // No schema evolution for ROOT PCM files.
1406
1407 TList *list = nullptr;
1408 if (fSeekInfo) {
1409 TDirectory::TContext ctxt(this); // gFile and gDirectory used in ReadObj
1410 auto key = std::make_unique<TKey>(this);
1411 auto buffer = std::make_unique<char[]>(fNbytesInfo+1);
1412 auto buf = buffer.get();
1413 Seek(fSeekInfo); // NOLINT: silence clang-tidy warnings
1414 if (ReadBuffer(buf,fNbytesInfo)) { // NOLINT: silence clang-tidy warnings
1415 // ReadBuffer returns kTRUE in case of failure.
1416 Warning("GetRecordHeader","%s: failed to read the StreamerInfo data from disk.",
1417 GetName());
1418 return {nullptr, 1, hash};
1419 }
1420
1421 if (lookupSICache) {
1422 // key data must be excluded from the hash, otherwise the timestamp will
1423 // always lead to unique hashes for each file
1424 hash = fgTsSIHashes.Hash(buf + key->GetKeylen(), fNbytesInfo - key->GetKeylen());
1425 auto si_uids = fgTsSIHashes.Find(hash);
1426 if (si_uids) {
1427 if (gDebug > 0)
1428 Info("GetStreamerInfo", "The streamer info record for file %s has already been treated, skipping it.", GetName());
1429 for(auto uid : *si_uids)
1430 fClassIndex->fArray[uid] = 1;
1431 return {nullptr, 0, hash};
1432 }
1433 }
1434 if (!key->ReadKeyBuffer(buf, fNbytesInfo))
1435 return {nullptr, 1, hash};
1436 list = dynamic_cast<TList*>(key->ReadObjWithBuffer(buffer.get()));
1437 if (list) list->SetOwner();
1438 } else {
1439 list = (TList*)Get("StreamerInfo"); //for versions 2.26 (never released)
1440 }
1441
1442 if (!list) {
1443 Info("GetStreamerInfoList", "cannot find the StreamerInfo record in file %s",
1444 GetName());
1445 return {nullptr, 1, hash};
1446 }
1447
1448 return {list, 0, hash};
1449}
1450
1451////////////////////////////////////////////////////////////////////////////////
1452/// Read the list of TStreamerInfo objects written to this file.
1453///
1454/// The function returns a TList. It is the user's responsibility
1455/// to delete the list created by this function.
1456///
1457/// Note the list, in addition to TStreamerInfo object, contains sometimes
1458/// a TList named 'listOfRules' and containing the schema evolution rules
1459/// related to the file's content.
1460///
1461/// Using the list, one can access additional information, e.g.:
1462/// ~~~{.cpp}
1463/// TFile f("myfile.root");
1464/// auto list = f.GetStreamerInfoList();
1465/// auto info = dynamic_cast<TStreamerInfo*>(list->FindObject("MyClass"));
1466/// if (info) auto classversionid = info->GetClassVersion();
1467/// delete list;
1468/// ~~~
1469///
1472{
1473 return GetStreamerInfoListImpl(/*lookupSICache*/ false).fList;
1474}
1475
1476////////////////////////////////////////////////////////////////////////////////
1477/// List file contents.
1478///
1479/// Indentation is used to identify the file tree.
1480/// Subdirectories are listed first, then objects in memory,
1481/// then objects on the file.
1483void TFile::ls(Option_t *option) const
1484{
1486 std::cout <<ClassName()<<"**\t\t"<<GetName()<<"\t"<<GetTitle()<<std::endl;
1490}
1491
1492////////////////////////////////////////////////////////////////////////////////
1493/// Returns kTRUE in case file is open and kFALSE if file is not open.
1495Bool_t TFile::IsOpen() const
1496{
1497 return fD == -1 ? kFALSE : kTRUE;
1498}
1499
1500////////////////////////////////////////////////////////////////////////////////
1501/// Mark unused bytes on the file.
1502///
1503/// The list of free segments is in the fFree linked list.
1504/// When an object is deleted from the file, the freed space is added
1505/// into the FREE linked list (fFree). The FREE list consists of a chain
1506/// of consecutive free segments on the file. At the same time, the first
1507/// 4 bytes of the freed record on the file are overwritten by GAPSIZE
1508/// where GAPSIZE = -(Number of bytes occupied by the record).
1510void TFile::MakeFree(Long64_t first, Long64_t last)
1511{
1512 TFree *f1 = (TFree*)fFree->First();
1513 if (!f1) return;
1514 TFree *newfree = f1->AddFree(fFree,first,last);
1515 if(!newfree) return;
1516 Long64_t nfirst = newfree->GetFirst();
1517 Long64_t nlast = newfree->GetLast();
1519 if (nbytesl > 2000000000) nbytesl = 2000000000;
1521 char buffer[sizeof(Int_t)];
1522 char *pbuffer = buffer;
1524 if (last == fEND-1) fEND = nfirst;
1525 Seek(nfirst);
1526 // We could not update the meta data for this block on the file.
1527 // This is not fatal as this only means that we won't get it 'right'
1528 // if we ever need to Recover the file before the block is actually
1529 // (attempted to be reused.
1530 // coverity[unchecked_value]
1531 WriteBuffer(buffer, sizeof(buffer));
1532 if (fMustFlush) Flush();
1533}
1534
1535////////////////////////////////////////////////////////////////////////////////
1536/// List the contents of a file sequentially.
1537/// For each logical record found, it prints:
1538///
1539/// Date/Time Record_Adress Logical_Record_Length ClassName CompressionFactor
1540///
1541/// Example of output
1542///
1543/// 20010404/150437 At:64 N=150 TFile
1544/// 20010404/150440 At:214 N=28326 TBasket CX = 1.13
1545/// 20010404/150440 At:28540 N=29616 TBasket CX = 1.08
1546/// 20010404/150440 At:58156 N=29640 TBasket CX = 1.08
1547/// 20010404/150440 At:87796 N=29076 TBasket CX = 1.10
1548/// 20010404/150440 At:116872 N=10151 TBasket CX = 3.15
1549/// 20010404/150441 At:127023 N=28341 TBasket CX = 1.13
1550/// 20010404/150441 At:155364 N=29594 TBasket CX = 1.08
1551/// 20010404/150441 At:184958 N=29616 TBasket CX = 1.08
1552/// 20010404/150441 At:214574 N=29075 TBasket CX = 1.10
1553/// 20010404/150441 At:243649 N=9583 TBasket CX = 3.34
1554/// 20010404/150442 At:253232 N=28324 TBasket CX = 1.13
1555/// 20010404/150442 At:281556 N=29641 TBasket CX = 1.08
1556/// 20010404/150442 At:311197 N=29633 TBasket CX = 1.08
1557/// 20010404/150442 At:340830 N=29091 TBasket CX = 1.10
1558/// 20010404/150442 At:369921 N=10341 TBasket CX = 3.09
1559/// 20010404/150442 At:380262 N=509 TH1F CX = 1.93
1560/// 20010404/150442 At:380771 N=1769 TH2F CX = 4.32
1561/// 20010404/150442 At:382540 N=1849 TProfile CX = 1.65
1562/// 20010404/150442 At:384389 N=18434 TNtuple CX = 4.51
1563/// 20010404/150442 At:402823 N=307 KeysList
1564/// 20010404/150443 At:403130 N=4548 StreamerInfo CX = 3.65
1565/// 20010404/150443 At:407678 N=86 FreeSegments
1566/// 20010404/150443 At:407764 N=1 END
1567///
1568/// If the parameter opt contains "forComp", the Date/Time is omitted
1569/// and the decompressed size is also printed.
1570///
1571/// Record_Adress Logical_Record_Length Key_Length Object_Record_Length ClassName CompressionFactor
1572///
1573/// If the parameter opt contains "extended", the name and title of the keys are added:
1574/// 20200820/155031 At:100 N=180 TFile name: hsimple.root title: Demo ROOT file with histograms
1575/// 220200820/155032 At:280 N=28880 TBasket CX = 1.11 name: random title: ntuple
1576/// 220200820/155032 At:29160 N=29761 TBasket CX = 1.08 name: px title: ntuple
1577/// 220200820/155032 At:58921 N=29725 TBasket CX = 1.08 name: py title: ntuple
1578/// 220200820/155032 At:88646 N=29209 TBasket CX = 1.10 name: pz title: ntuple
1579/// 220200820/155032 At:117855 N=10197 TBasket CX = 3.14 name: i title: ntuple
1580/// ...
1581/// 20200820/155032 At:405110 N=808 TNtuple CX = 3.53 name: ntuple title: Demo ntuple
1582/// 20200820/155706 At:405918 N=307 KeysList name: hsimple.root title: Demo ROOT file with histograms
1583/// 20200820/155032 At:406225 N=8556 StreamerInfo CX = 3.42 name: StreamerInfo title: Doubly linked list
1584/// 20200820/155708 At:414781 N=86 FreeSegments name: hsimple.root title: Demo ROOT file with histograms
1585/// 20200820/155708 At:414867 N=1 END
1586///
1587/// Note: The combined size of the classname, name and title is truncated to 476 characters (a little more for regular keys of small files)
1588///
1589
1591void TFile::Map(Option_t *opt)
1592{
1593 TString options(opt);
1594 options.ToLower();
1595 const bool forComp = options.Contains("forcomp");
1596 const bool extended = options.Contains("extended");
1597
1598 const unsigned char nDigits = std::log10(fEND) + 1;
1599
1600 std::optional<ROOT::Detail::TKeyMapNode> lastNode;
1601 const auto tkeyInfos = WalkTKeys();
1602 for (const auto &key : tkeyInfos) {
1603 lastNode = key;
1604 switch (key.fType) {
1606 Printf("Address = %" PRIu64 "\tNbytes = %u\t=====E R R O R=======", key.fAddr, key.fLen);
1607 break;
1608
1610 Printf("Address = %" PRIu64 "\tNbytes = %d\t=====G A P===========", key.fAddr, -key.fLen);
1611 break;
1612
1615 if (extended)
1616 extrainfo.Form(" name: %-16s title: %s", key.fKeyName.c_str(), key.fKeyTitle.c_str());
1617
1618 if (forComp) {
1619 // Printing to help compare two files.
1620 if (key.fObjLen != static_cast<Int_t>(key.fLen) - key.fKeyLen) {
1621 Float_t cx = static_cast<float>(key.fObjLen + key.fKeyLen) / key.fLen;
1622 Printf("At:%-*" PRIu64 " N=%-8u K=%-3d O=%-8d %-14s CX = %5.2f %s", nDigits + 1, key.fAddr, key.fLen,
1623 key.fKeyLen, key.fObjLen, key.fClassName.c_str(), cx, extrainfo.Data());
1624 } else {
1625 Printf("At:%-*" PRIu64 " N=%-8u K=%-3d O=%-8d %-14s CX = 1 %s", nDigits + 1, key.fAddr, key.fLen,
1626 key.fKeyLen, key.fObjLen, key.fClassName.c_str(), extrainfo.Data());
1627 }
1628 } else {
1629 Int_t date, time;
1630 TDatime::GetDateTime(key.fDatime, date, time);
1631 if (key.fObjLen != static_cast<Int_t>(key.fLen) - key.fKeyLen) {
1632 Float_t cx = static_cast<float>(key.fObjLen + key.fKeyLen) / key.fLen;
1633 Printf("%d/%06d At:%-*" PRIu64 " N=%-8u %-14s CX = %5.2f %s", date, time, nDigits + 1, key.fAddr,
1634 key.fLen, key.fClassName.c_str(), cx, extrainfo.Data());
1635 } else {
1636 Printf("%d/%06d At:%-*" PRIu64 " N=%-8u %-14s %s", date, time, nDigits + 1, key.fAddr,
1637 key.fLen, key.fClassName.c_str(), extrainfo.Data());
1638 }
1639 }
1640 }
1641 }
1642
1643 if (!forComp) {
1644 Int_t datime = lastNode ? lastNode->fDatime : 0;
1645 Int_t date, time;
1647 Printf("%d/%06d At:%-*lld N=%-8d %-14s", date, time, nDigits + 1, fEND, 1, "END");
1648 } else {
1649 Printf("At:%-*lld N=%-8d K= O= %-14s", nDigits + 1, fEND, 1, "END");
1650 }
1651}
1656}
1658ROOT::Detail::TKeyMapIterable::TIterator::TIterator(TFile *file, std::uint64_t addr) : fFile(file), fCurAddr(addr)
1659{
1660 if (addr == 0)
1662 Advance();
1663}
1665std::optional<ROOT::Detail::TKeyMapNode> ROOT::Detail::TKeyMapIterable::TIterator::Next()
1666{
1667 static constexpr int headerSize = 512;
1668
1669 const std::uint64_t idcur = fCurAddr;
1670 const std::uint64_t end = fFile->fEND;
1671 if (idcur >= end)
1672 return std::nullopt;
1673
1674 fFile->Seek(idcur);
1675 auto nread = headerSize;
1676 if (idcur + nread >= end)
1677 nread = end - idcur - 1;
1678
1679 char header[headerSize];
1680 if (fFile->ReadBuffer(header, nread)) {
1681 // ReadBuffer returns kTRUE in case of failure.
1683 fCurAddr = end;
1684 return node;
1685 }
1686
1687 char *buffer = header;
1688 Int_t nbytes;
1689 frombuf(buffer, &nbytes);
1690 if (!nbytes) {
1692 fCurAddr = end;
1693 return node;
1694 }
1695
1696 if (nbytes < 0) {
1697 // free slot
1698 auto node =
1700 fCurAddr -= nbytes;
1701 return node;
1702 }
1703
1704 auto node = ROOT::Detail::TKeyMapNode{idcur, ROOT::Detail::TKeyMapNode::kKey, static_cast<std::uint32_t>(nbytes)};
1705 frombuf(buffer, &node.fKeyVersion);
1706 frombuf(buffer, &node.fObjLen);
1707 frombuf(buffer, &node.fDatime);
1708 frombuf(buffer, &node.fKeyLen);
1709 frombuf(buffer, &node.fCycle);
1710 if (node.fKeyVersion > 1000) {
1711 frombuf(buffer, &node.fSeekKey);
1712 frombuf(buffer, &node.fSeekPdir);
1713 } else {
1714 Int_t skey, sdir;
1715 frombuf(buffer, &skey);
1716 frombuf(buffer, &sdir);
1717 node.fSeekKey = static_cast<Long64_t>(skey);
1718 node.fSeekPdir = static_cast<Long64_t>(sdir);
1719 }
1720
1721 const auto readString = [&buffer, &header](bool skipCheck = false) {
1722 std::uint8_t stringLenShort;
1723 std::uint32_t stringLen;
1724 if (!skipCheck && ((buffer - header) >= headerSize)) {
1725 stringLen = 0;
1726 } else {
1727 frombuf(buffer, &stringLenShort);
1728 if (stringLenShort == 0xFF)
1729 frombuf(buffer, &stringLen);
1730 else
1732
1733 if ((buffer - header) + stringLen > headerSize)
1734 stringLen = headerSize - (buffer - header);
1735 }
1736
1737 std::string str;
1738 if (stringLen)
1739 str = std::string(buffer, stringLen);
1740 buffer += stringLen;
1741
1742 return str;
1743 };
1744
1745 node.fClassName = readString(true);
1746
1747 if (idcur == static_cast<std::uint64_t>(fFile->fSeekFree))
1748 node.fClassName = "FreeSegments";
1749 else if (idcur == static_cast<std::uint64_t>(fFile->fSeekInfo))
1750 node.fClassName = "StreamerInfo";
1751 else if (idcur == static_cast<std::uint64_t>(fFile->fSeekKeys))
1752 node.fClassName = "KeysList";
1753
1754 node.fKeyName = readString();
1755 node.fKeyTitle = readString();
1756
1757 fCurAddr += nbytes;
1758
1759 return node;
1760}
1761
1762////////////////////////////////////////////////////////////////////////////////
1763/// Paint all objects in the file.
1766{
1767 GetList()->R__FOR_EACH(TObject,Paint)(option);
1768}
1769
1770////////////////////////////////////////////////////////////////////////////////
1771/// Print all objects in the file.
1773void TFile::Print(Option_t *option) const
1774{
1775 Printf("TFile: name=%s, title=%s, option=%s", GetName(), GetTitle(), GetOption());
1776 GetList()->R__FOR_EACH(TObject,Print)(option);
1777}
1778
1779////////////////////////////////////////////////////////////////////////////////
1780/// Read a buffer from the file at the offset 'pos' in the file.
1781///
1782/// Returns kTRUE in case of failure.
1783/// Compared to ReadBuffer(char*, Int_t), this routine does _not_
1784/// change the cursor on the physical file representation (fD)
1785/// if the data is in this TFile's cache.
1788{
1789 if (IsOpen()) {
1790
1791 SetOffset(pos);
1792
1793 Int_t st;
1794 Double_t start = 0;
1795 if (gPerfStats) start = TTimeStamp();
1796
1797 if ((st = ReadBufferViaCache(buf, len))) {
1798 if (st == 2)
1799 return kTRUE;
1800 return kFALSE;
1801 }
1802
1803 Seek(pos);
1804 ssize_t siz;
1805
1806 while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
1807 ResetErrno();
1808
1809 if (siz < 0) {
1810 SysError("ReadBuffer", "error reading from file %s", GetName());
1811 return kTRUE;
1812 }
1813 if (siz != len) {
1814 Error("ReadBuffer", "error reading all requested bytes from file %s, got %ld of %d",
1815 GetName(), (Long_t)siz, len);
1816 return kTRUE;
1817 }
1818 fBytesRead += siz;
1819 fgBytesRead += siz;
1820 fReadCalls++;
1821 fgReadCalls++;
1822
1825 if (gPerfStats) {
1826 gPerfStats->FileReadEvent(this, len, start);
1827 }
1828 return kFALSE;
1829 }
1830 return kTRUE;
1831}
1832
1833////////////////////////////////////////////////////////////////////////////////
1834/// Read a buffer from the file. This is the basic low level read operation.
1835/// Returns kTRUE in case of failure.
1838{
1839 if (IsOpen()) {
1840
1841 Int_t st;
1842 if ((st = ReadBufferViaCache(buf, len))) {
1843 if (st == 2)
1844 return kTRUE;
1845 return kFALSE;
1846 }
1847
1848 ssize_t siz;
1849 Double_t start = 0;
1850
1851 if (gPerfStats) start = TTimeStamp();
1852
1853 while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
1854 ResetErrno();
1855
1856 if (siz < 0) {
1857 SysError("ReadBuffer", "error reading from file %s", GetName());
1858 return kTRUE;
1859 }
1860 if (siz != len) {
1861 Error("ReadBuffer", "error reading all requested bytes from file %s, got %ld of %d",
1862 GetName(), (Long_t)siz, len);
1863 return kTRUE;
1864 }
1865 fBytesRead += siz;
1866 fgBytesRead += siz;
1867 fReadCalls++;
1868 fgReadCalls++;
1869
1872 if (gPerfStats) {
1873 gPerfStats->FileReadEvent(this, len, start);
1874 }
1875 return kFALSE;
1876 }
1877 return kTRUE;
1878}
1879
1880////////////////////////////////////////////////////////////////////////////////
1881/// Read the nbuf blocks described in arrays pos and len.
1882///
1883/// The value pos[i] is the seek position of block i of length len[i].
1884/// Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer.
1885/// Returns kTRUE in case of failure.
1888{
1889 // called with buf=0, from TFileCacheRead to pass list of readahead buffers
1890 if (!buf) {
1891 for (Int_t j = 0; j < nbuf; j++) {
1892 if (ReadBufferAsync(pos[j], len[j])) {
1893 return kTRUE;
1894 }
1895 }
1896 return kFALSE;
1897 }
1898
1899 Int_t k = 0;
1901 TFileCacheRead *old = fCacheRead;
1902 fCacheRead = nullptr;
1903 Long64_t curbegin = pos[0];
1904 Long64_t cur;
1905 char *buf2 = nullptr;
1906 Int_t i = 0, n = 0;
1907 while (i < nbuf) {
1908 cur = pos[i]+len[i];
1910 if (cur -curbegin < fgReadaheadSize) {n++; i++; bigRead = kFALSE;}
1911 if (bigRead || (i>=nbuf)) {
1912 if (n == 0) {
1913 //if the block to read is about the same size as the read-ahead buffer
1914 //we read the block directly
1915 Seek(pos[i]);
1916 result = ReadBuffer(&buf[k], len[i]);
1917 if (result) break;
1918 k += len[i];
1919 i++;
1920 } else {
1921 //otherwise we read all blocks that fit in the read-ahead buffer
1922 Seek(curbegin);
1923 if (!buf2) buf2 = new char[fgReadaheadSize];
1924 //we read ahead
1925 Long64_t nahead = pos[i-1]+len[i-1]-curbegin;
1927 if (result) break;
1928 //now copy from the read-ahead buffer to the cache
1929 Int_t kold = k;
1930 for (Int_t j=0;j<n;j++) {
1931 memcpy(&buf[k],&buf2[pos[i-n+j]-curbegin],len[i-n+j]);
1932 k += len[i-n+j];
1933 }
1934 Int_t nok = k-kold;
1935 Long64_t extra = nahead-nok;
1936 fBytesReadExtra += extra;
1937 fBytesRead -= extra;
1938 fgBytesRead -= extra;
1939 n = 0;
1940 }
1941 curbegin = i < nbuf ? pos[i] : 0;
1942 }
1943 }
1944 if (buf2) delete [] buf2;
1945 fCacheRead = old;
1946 return result;
1947}
1948
1949////////////////////////////////////////////////////////////////////////////////
1950/// Read buffer via cache.
1951///
1952/// Returns 0 if the requested block is not in the cache, 1 in case read via
1953/// cache was successful, 2 in case read via cache failed.
1956{
1957 Long64_t off = GetRelOffset();
1958 if (fCacheRead) {
1959 Int_t st = fCacheRead->ReadBuffer(buf, off, len);
1960 if (st < 0)
1961 return 2; // failure reading
1962 else if (st == 1) {
1963 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
1964 SetOffset(off + len);
1965 return 1;
1966 }
1967 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
1968 Seek(off);
1969 } else {
1970 // if write cache is active check if data still in write cache
1971 if (fWritable && fCacheWrite) {
1972 if (fCacheWrite->ReadBuffer(buf, off, len) == 0) {
1973 SetOffset(off + len);
1974 return 1;
1975 }
1976 // fOffset might have been changed via TFileCacheWrite::ReadBuffer(), reset it
1977 SetOffset(off);
1978 }
1979 }
1980
1981 return 0;
1982}
1983
1984////////////////////////////////////////////////////////////////////////////////
1985/// Read the FREE linked list.
1986///
1987/// Every file has a linked list (fFree) of free segments.
1988/// This linked list has been written on the file via WriteFree
1989/// as a single data record.
1991void TFile::ReadFree()
1992{
1993 // Avoid problem with file corruption.
1995 fNbytesFree = 0;
1996 return;
1997 }
1998 TKey *headerfree = new TKey(fSeekFree, fNbytesFree, this);
1999 headerfree->ReadFile();
2000 char *buffer = headerfree->GetBuffer();
2001 headerfree->ReadKeyBuffer(buffer);
2002 buffer = headerfree->GetBuffer();
2003 while (1) {
2004 TFree *afree = new TFree();
2005 afree->ReadBuffer(buffer);
2006 fFree->Add(afree);
2007 if (afree->GetLast() > fEND) break;
2008 }
2009 delete headerfree;
2010}
2011
2012////////////////////////////////////////////////////////////////////////////////
2013/// The TProcessID with number pidf is read from this file.
2014///
2015/// If the object is not already entered in the gROOT list, it is added.
2018{
2019 TProcessID *pid = nullptr;
2020 TObjArray *pids = GetListOfProcessIDs();
2021 if (pidf < pids->GetSize()) pid = (TProcessID *)pids->UncheckedAt(pidf);
2022 if (pid) {
2023 pid->CheckInit();
2024 return pid;
2025 }
2026
2027 //check if fProcessIDs[uid] is set in file
2028 //if not set, read the process uid from file
2029 char pidname[32];
2030 snprintf(pidname,32,"ProcessID%d",pidf);
2031 pid = (TProcessID *)Get(pidname);
2032 if (gDebug > 0) {
2033 printf("ReadProcessID, name=%s, file=%s, pid=%zx\n",pidname,GetName(),(size_t)pid);
2034 }
2035 if (!pid) {
2036 //file->Error("ReadProcessID","Cannot find %s in file %s",pidname,file->GetName());
2037 return pid;
2038 }
2039
2040 //check that a similar pid is not already registered in fgPIDs
2042 TIter next(pidslist);
2043 TProcessID *p;
2044 bool found = false;
2045
2046 {
2048 while ((p = (TProcessID*)next())) {
2049 if (!strcmp(p->GetTitle(),pid->GetTitle())) {
2050 found = true;
2051 break;
2052 }
2053 }
2054 }
2055
2056 if (found) {
2057 delete pid;
2058 pids->AddAtAndExpand(p,pidf);
2059 p->IncrementCount();
2060 return p;
2061 }
2062
2063 pids->AddAtAndExpand(pid,pidf);
2064 pid->IncrementCount();
2065
2066 {
2068 pidslist->Add(pid);
2069 Int_t ind = pidslist->IndexOf(pid);
2070 pid->SetUniqueID((UInt_t)ind);
2071 }
2072
2073 return pid;
2074}
2075
2076
2077////////////////////////////////////////////////////////////////////////////////
2078/// Attempt to recover file if not correctly closed
2079///
2080/// The function returns the number of keys that have been recovered.
2081/// If no keys can be recovered, the file will be declared Zombie by
2082/// the calling function. This function is automatically called when
2083/// opening a file.
2084/// If the file is open in read only mode, the file is not modified.
2085/// If open in update mode and the function finds something to recover,
2086/// a new directory header is written to the file. When opening the file gain
2087/// no message from Recover will be reported.
2088/// If keys have been recovered, the file is usable and you can safely
2089/// read the corresponding objects.
2090/// If the file is not usable (a zombie), you can test for this case
2091/// with code like:
2092///
2093/// ~~~{.cpp}
2094/// TFile f("myfile.root");
2095/// if (f.IsZombie()) {<actions to take if file is unusable>}
2096/// ~~~
2097///
2098/// If the file has been recovered, the bit kRecovered is set in the TFile object in memory.
2099/// You can test if the file has been recovered with
2100///
2101/// if (f.TestBit(TFile::kRecovered)) {... the file has been recovered}
2102///
2103/// When writing TTrees to a file, it is important to save the Tree header
2104/// at regular intervals (see TTree::AutoSave). If a file containing a Tree
2105/// is recovered, the last Tree header written to the file will be used.
2106/// In this case all the entries in all the branches written before writing
2107/// the header are valid entries.
2108/// One can disable the automatic recovery procedure by setting
2109///
2110/// TFile.Recover 0
2111///
2112/// in the <em>system.rootrc</em> file.
2115{
2116 Long64_t idcur = fBEGIN;
2117
2118 Long64_t size;
2119 if ((size = GetSize()) == -1) { // NOLINT: silence clang-tidy warnings
2120 Error("Recover", "cannot stat the file %s", GetName());
2121 return 0;
2122 }
2123
2124 fEND = Long64_t(size);
2125
2126 if (fWritable && !fFree) fFree = new TList;
2127
2128 Int_t nrecov = 0;
2129
2130 while (idcur < fEND) {
2131 char header[1024];
2132 int nread = sizeof(header);
2133
2134 Seek(idcur); // NOLINT: silence clang-tidy warnings
2135 if (idcur+nread >= fEND) nread = fEND-idcur-1;
2136 if (ReadBuffer(header, nread)) { // NOLINT: silence clang-tidy warnings
2137 // ReadBuffer returns kTRUE in case of failure.
2138 Error("Recover","%s: failed to read the key data from disk at %lld.",
2139 GetName(),idcur);
2140 break;
2141 }
2142 char *buffer = header;
2143 Int_t nbytes;
2144 frombuf(buffer, &nbytes);
2145 if (!nbytes) {
2146 Error("Recover","Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes);
2147 break;
2148 }
2149 if (nbytes < 0) {
2150 idcur -= nbytes;
2151 if (fWritable) new TFree(fFree,idcur,idcur-nbytes-1);
2152 Seek(idcur);
2153 continue;
2154 }
2156 frombuf(buffer, &versionkey);
2157 Int_t objlen;
2158 frombuf(buffer, &objlen);
2159 UInt_t datime;
2160 frombuf(buffer, &datime);
2162 frombuf(buffer, &keylen);
2163 Short_t cycle;
2164 frombuf(buffer, &cycle);
2166 if (versionkey > 1000) {
2167 frombuf(buffer, &seekkey);
2168 frombuf(buffer, &seekpdir);
2169 } else {
2170 Int_t skey,sdir;
2171 frombuf(buffer, &skey); seekkey = (Long64_t)skey;
2172 frombuf(buffer, &sdir); seekpdir = (Long64_t)sdir;
2173 }
2174 char classnameLen;
2175 frombuf(buffer, &classnameLen);
2176 char classname[101];
2177 if (classnameLen <= 0 || classnameLen > (Int_t)sizeof(classname))
2178 break;
2179 memcpy(classname, buffer, classnameLen);
2180 buffer += classnameLen;
2181 classname[static_cast<std::size_t>(classnameLen)] = '\0';
2182 Int_t date, time;
2184 TClass *tclass = TClass::GetClass(classname);
2185 if (seekpdir == fSeekDir && tclass && !tclass->InheritsFrom(TFile::Class())
2186 && strcmp(classname,"TBasket")) {
2187 TKey *key = new TKey(this);
2188 char *bufread = header;
2189 bool keyRead = key->ReadKeyBuffer(bufread, sizeof(header));
2190 if (!keyRead || !strcmp(key->GetName(), "StreamerInfo")) {
2191 fSeekInfo = seekkey;
2192 SafeDelete(fInfoCache);
2193 fNbytesInfo = nbytes;
2194 delete key;
2195 } else {
2196 AppendKey(key); // ownership transferred, do not to delete key here
2197 nrecov++;
2198 SetBit(kRecovered);
2199 Info("Recover", "%s, recovered key %s:%s at address %lld",GetName(),key->GetClassName(),key->GetName(),idcur);
2200 }
2201 }
2202 idcur += nbytes;
2203 }
2204 if (fWritable) {
2205 Long64_t max_file_size = Long64_t(kStartBigFile);
2206 if (max_file_size < fEND) max_file_size = fEND+1000000000;
2207 TFree *last = (TFree*)fFree->Last();
2208 if (last) {
2209 last->AddFree(fFree,fEND,max_file_size);
2210 } else {
2211 new TFree(fFree,fEND,max_file_size);
2212 }
2213 if (nrecov) Write();
2214 }
2215 return nrecov;
2216}
2217
2218////////////////////////////////////////////////////////////////////////////////
2219/// Reopen a file with a different access mode.
2220///
2221/// For example, it is possible to change from READ to
2222/// UPDATE or from NEW, CREATE, RECREATE, UPDATE to READ. Thus the
2223/// mode argument can be either "READ" or "UPDATE". The method returns
2224/// 0 in case the mode was successfully modified, 1 in case the mode
2225/// did not change (was already as requested or wrong input arguments)
2226/// and -1 in case of failure, in which case the file cannot be used
2227/// anymore. The current directory (gFile) is changed to this file.
2230{
2231 cd();
2232
2233 TString opt = mode;
2234 opt.ToUpper();
2235
2236 if (opt != "READ" && opt != "UPDATE") {
2237 Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data());
2238 return 1;
2239 }
2240
2241 if (opt == fOption || (opt == "UPDATE" && fOption == "CREATE"))
2242 return 1;
2243
2244 if (opt == "READ") {
2245 // switch to READ mode
2246
2247 // flush data still in the pipeline and close the file
2248 if (IsOpen() && IsWritable()) {
2249 WriteStreamerInfo();
2250
2251 // save directory key list and header
2252 Save();
2253
2254 TFree *f1 = (TFree*)fFree->First();
2255 if (f1) {
2256 WriteFree(); // write free segments linked list
2257 WriteHeader(); // now write file header
2258 }
2259
2260 FlushWriteCache();
2261
2262 // delete free segments from free list
2263 fFree->Delete();
2264 SafeDelete(fFree);
2265
2266 SysClose(fD);
2267 fD = -1;
2268
2269 SetWritable(kFALSE);
2270 }
2271
2272 // open in READ mode
2273 fOption = opt; // set fOption before SysOpen() for TNetFile
2274#ifndef WIN32
2275 fD = SysOpen(fRealName, O_RDONLY, 0666);
2276#else
2277 fD = SysOpen(fRealName, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
2278#endif
2279 if (fD == -1) {
2280 SysError("ReOpen", "file %s can not be opened in read mode", GetName());
2281 return -1;
2282 }
2283 SetWritable(kFALSE);
2284
2285 } else {
2286 // switch to UPDATE mode
2287
2288 // close readonly file
2289 if (IsOpen()) {
2290 SysClose(fD);
2291 fD = -1;
2292 }
2293
2294 // open in UPDATE mode
2295 fOption = opt; // set fOption before SysOpen() for TNetFile
2296#ifndef WIN32
2297 fD = SysOpen(fRealName, O_RDWR | O_CREAT, 0666);
2298#else
2299 fD = SysOpen(fRealName, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
2300#endif
2301 if (fD == -1) {
2302 SysError("ReOpen", "file %s can not be opened in update mode", GetName());
2303 return -1;
2304 }
2305 SetWritable(kTRUE);
2306
2307 fFree = new TList;
2308 if (fSeekFree > fBEGIN)
2309 ReadFree();
2310 else
2311 Warning("ReOpen","file %s probably not closed, cannot read free segments", GetName());
2312 }
2313
2314 return 0;
2315}
2316
2317////////////////////////////////////////////////////////////////////////////////
2318/// Set position from where to start reading.
2321{
2322 switch (pos) {
2323 case kBeg:
2324 fOffset = offset + fArchiveOffset;
2325 break;
2326 case kCur:
2327 fOffset += offset;
2328 break;
2329 case kEnd:
2330 // this option is not used currently in the ROOT code
2331 if (fArchiveOffset)
2332 Error("SetOffset", "seeking from end in archive is not (yet) supported");
2333 fOffset = fEND + offset; // is fEND really EOF or logical EOF?
2334 break;
2335 }
2336}
2337
2338////////////////////////////////////////////////////////////////////////////////
2339/// Seek to a specific position in the file. Pos it either kBeg, kCur or kEnd.
2342{
2343 int whence = 0;
2344 switch (pos) {
2345 case kBeg:
2346 whence = SEEK_SET;
2347 offset += fArchiveOffset;
2348 break;
2349 case kCur:
2350 whence = SEEK_CUR;
2351 break;
2352 case kEnd:
2353 whence = SEEK_END;
2354 // this option is not used currently in the ROOT code
2355 if (fArchiveOffset)
2356 Error("Seek", "seeking from end in archive is not (yet) supported");
2357 break;
2358 }
2360 if ((retpos = SysSeek(fD, offset, whence)) < 0) // NOLINT: silence clang-tidy warnings
2361 SysError("Seek", "cannot seek to position %lld in file %s, retpos=%lld",
2362 offset, GetName(), retpos);
2363
2364 // used by TFileCacheRead::ReadBuffer()
2365 fOffset = retpos;
2366}
2367
2368////////////////////////////////////////////////////////////////////////////////
2369/// See comments for function SetCompressionSettings
2370///
2373{
2375 if (fCompress < 0) {
2377 } else {
2378 int level = fCompress % 100;
2379 fCompress = 100 * algorithm + level;
2380 }
2381}
2382
2383////////////////////////////////////////////////////////////////////////////////
2384/// See comments for function SetCompressionSettings
2387{
2388 if (level < 0) level = 0;
2389 if (level > 99) level = 99;
2390 if (fCompress < 0) {
2391 // if the algorithm is not defined yet use 0 as a default
2392 fCompress = level;
2393 } else {
2394 int algorithm = fCompress / 100;
2396 fCompress = 100 * algorithm + level;
2397 }
2398}
2399
2400////////////////////////////////////////////////////////////////////////////////
2401/// Used to specify the compression level and algorithm.
2402///
2403/// See the TFile constructor for the details.
2406{
2407 fCompress = settings;
2408}
2409
2410////////////////////////////////////////////////////////////////////////////////
2411/// Set a pointer to the read cache.
2412///
2413/// <b>This relinquishes ownership</b> of the previous cache, so if you do not
2414/// already have a pointer to the previous cache (and there was a previous
2415/// cache), you ought to retrieve (and delete it if needed) using:
2416///
2417/// TFileCacheRead *older = myfile->GetCacheRead();
2418///
2419/// The action specifies how to behave when detaching a cache from the
2420/// the TFile. If set to (default) kDisconnect, the contents of the cache
2421/// will be flushed when it is removed from the file, and it will disconnect
2422/// the cache object from the file. In almost all cases, this is what you want.
2423/// If you want to disconnect the cache temporarily from this tree and re-attach
2424/// later to the same fil, you can set action to kDoNotDisconnect. This will allow
2425/// things like prefetching to continue in the background while it is no longer the
2426/// default cache for the TTree. Except for a few expert use cases, kDisconnect is
2427/// likely the correct setting.
2428///
2429/// WARNING: if action=kDoNotDisconnect, you MUST delete the cache before TFile.
2430///
2433{
2434 if (tree) {
2435 if (cache) fCacheReadMap->Add(tree, cache);
2436 else {
2437 // The only addition to fCacheReadMap is via an interface that takes
2438 // a TFileCacheRead* so the C-cast is safe.
2439 TFileCacheRead* tpf = (TFileCacheRead *)fCacheReadMap->GetValue(tree);
2440 fCacheReadMap->Remove(tree);
2441 if (tpf && (tpf->GetFile() == this) && (action != kDoNotDisconnect)) tpf->SetFile(0, action);
2442 }
2443 }
2444 if (cache) cache->SetFile(this, action);
2445 else if (!tree && fCacheRead && (action != kDoNotDisconnect)) fCacheRead->SetFile(0, action);
2446 // For backward compatibility the last Cache set is the default cache.
2447 fCacheRead = cache;
2448}
2449
2450////////////////////////////////////////////////////////////////////////////////
2451/// Set a pointer to the write cache.
2452///
2453/// If file is null the existing write cache is deleted.
2456{
2457 if (!cache && fCacheWrite) delete fCacheWrite;
2458 fCacheWrite = cache;
2459}
2460
2461////////////////////////////////////////////////////////////////////////////////
2462/// Return the size in bytes of the file header.
2464Int_t TFile::Sizeof() const
2465{
2466 return 0;
2467}
2468
2469////////////////////////////////////////////////////////////////////////////////
2470/// Stream a TFile object.
2473{
2474 if (b.IsReading()) {
2475 b.ReadVersion(); //Version_t v = b.ReadVersion();
2476 } else {
2477 b.WriteVersion(TFile::IsA());
2478 }
2479}
2480
2481////////////////////////////////////////////////////////////////////////////////
2482/// Increment statistics for buffer sizes of objects in this file.
2485{
2486 fWritten++;
2487 fSumBuffer += double(bufsize);
2488 fSum2Buffer += double(bufsize) * double(bufsize); // avoid reaching MAXINT for temporary
2489}
2490
2491////////////////////////////////////////////////////////////////////////////////
2492/// Write memory objects to this file.
2493///
2494/// Loop on all objects in memory (including subdirectories).
2495/// A new key is created in the KEYS linked list for each object.
2496/// The list of keys is then saved on the file (via WriteKeys)
2497/// as a single data record.
2498/// For values of opt see TObject::Write().
2499/// The directory header info is rewritten on the directory header record.
2500/// The linked list of FREE segments is written.
2501/// The file header is written (bytes 1->fBEGIN).
2503Int_t TFile::Write(const char *, Int_t opt, Int_t bufsize)
2504{
2505 if (!IsWritable()) {
2506 if (!TestBit(kWriteError)) {
2507 // Do not print the warning if we already had a SysError.
2508 Warning("Write", "file %s not opened in write mode", GetName());
2509 }
2510 return 0;
2511 }
2512
2513 if (gDebug) {
2514 if (!GetTitle() || strlen(GetTitle()) == 0)
2515 Info("Write", "writing name = %s", GetName());
2516 else
2517 Info("Write", "writing name = %s title = %s", GetName(), GetTitle());
2518 }
2519
2520 fMustFlush = kFALSE;
2521 Int_t nbytes = TDirectoryFile::Write(0, opt, bufsize); // Write directory tree
2522 WriteStreamerInfo();
2523 WriteFree(); // Write free segments linked list
2524 WriteHeader(); // Now write file header
2525 fMustFlush = kTRUE;
2526
2527 return nbytes;
2528}
2529
2530////////////////////////////////////////////////////////////////////////////////
2531/// One can not save a const TDirectory object.
2533Int_t TFile::Write(const char *n, Int_t opt, Int_t bufsize) const
2534{
2535 Error("Write const","A const TFile object should not be saved. We try to proceed anyway.");
2536 return const_cast<TFile*>(this)->Write(n, opt, bufsize);
2537}
2538
2539////////////////////////////////////////////////////////////////////////////////
2540/// Write a buffer to the file. This is the basic low level write operation.
2541/// Returns kTRUE in case of failure.
2544{
2545 if (IsOpen() && fWritable) {
2546
2547 Int_t st;
2548 if ((st = WriteBufferViaCache(buf, len))) {
2549 if (st == 2)
2550 return kTRUE;
2551 return kFALSE;
2552 }
2553
2554 ssize_t siz;
2556 while ((siz = SysWrite(fD, buf, len)) < 0 && GetErrno() == EINTR) // NOLINT: silence clang-tidy warnings
2557 ResetErrno(); // NOLINT: silence clang-tidy warnings
2559 if (siz < 0) {
2560 // Write the system error only once for this file
2561 SetBit(kWriteError); SetWritable(kFALSE);
2562 SysError("WriteBuffer", "error writing to file %s (%ld)", GetName(), (Long_t)siz);
2563 return kTRUE;
2564 }
2565 if (siz != len) {
2566 SetBit(kWriteError);
2567 Error("WriteBuffer", "error writing all requested bytes to file %s, wrote %ld of %d",
2568 GetName(), (Long_t)siz, len);
2569 return kTRUE;
2570 }
2571 fBytesWrite += siz;
2572 fgBytesWrite += siz;
2573
2576
2577 return kFALSE;
2578 }
2579 return kTRUE;
2580}
2581
2582////////////////////////////////////////////////////////////////////////////////
2583/// Write buffer via cache. Returns 0 if cache is not active, 1 in case
2584/// write via cache was successful, 2 in case write via cache failed.
2587{
2588 if (!fCacheWrite) return 0;
2589
2590 Int_t st;
2591 Long64_t off = GetRelOffset();
2592 if ((st = fCacheWrite->WriteBuffer(buf, off, len)) < 0) {
2593 SetBit(kWriteError);
2594 Error("WriteBuffer", "error writing to cache");
2595 return 2;
2596 }
2597 if (st > 0) {
2598 // fOffset might have been changed via TFileCacheWrite::WriteBuffer(), reset it
2599 Seek(off + len);
2600 return 1;
2601 }
2602 return 0;
2603}
2604
2605////////////////////////////////////////////////////////////////////////////////
2606/// Write FREE linked list on the file.
2607/// The linked list of FREE segments (fFree) is written as a single data
2608/// record.
2610void TFile::WriteFree()
2611{
2612 //*-* Delete old record if it exists
2613 if (fSeekFree != 0) {
2614 MakeFree(fSeekFree, fSeekFree + fNbytesFree -1);
2615 }
2616
2618
2619 auto createKey = [this]() {
2620 Int_t nbytes = 0;
2621 TFree *afree;
2622 TIter next (fFree);
2623 while ((afree = (TFree*) next())) {
2624 nbytes += afree->Sizeof();
2625 }
2626 if (!nbytes) return (TKey*)nullptr;
2627
2628 TKey *key = new TKey(fName,fTitle,IsA(),nbytes,this);
2629
2630 if (key->GetSeekKey() == 0) {
2631 delete key;
2632 return (TKey*)nullptr;
2633 }
2634 return key;
2635 };
2636
2637 TKey *key = createKey();
2638 if (!key) return;
2639
2640 if (!largeFile && (fEND > TFile::kStartBigFile)) {
2641 // The free block list is large enough to bring the file to larger
2642 // than 2Gb, the references/offsets are now 64bits in the output
2643 // so we need to redo the calculation since the list of free block
2644 // information will not fit in the original size.
2645 key->Delete();
2646 delete key;
2647
2648 key = createKey();
2649 if (!key) return;
2650 }
2651
2652 Int_t nbytes = key->GetObjlen();
2653 char *buffer = key->GetBuffer();
2654 char *start = buffer;
2655
2656 TIter next (fFree);
2657 TFree *afree;
2658 while ((afree = (TFree*) next())) {
2659 // We could 'waste' time here and double check that
2660 // (buffer+afree->Sizeof() < (start+nbytes)
2661 afree->FillBuffer(buffer);
2662 }
2663 auto actualBytes = buffer-start;
2664 if ( actualBytes != nbytes ) {
2665 if (actualBytes < nbytes) {
2666 // Most likely one of the 'free' segment was used to store this
2667 // TKey, so we had one less TFree to store than we planned.
2668 memset(buffer,0,nbytes-actualBytes);
2669 } else {
2670 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);
2671 }
2672 }
2673 fNbytesFree = key->GetNbytes();
2674 fSeekFree = key->GetSeekKey();
2675 key->WriteFile();
2676 delete key;
2677}
2678
2679////////////////////////////////////////////////////////////////////////////////
2680/// Write File Header.
2682void TFile::WriteHeader()
2683{
2684 SafeDelete(fInfoCache);
2685 TFree *lastfree = (TFree*)fFree->Last();
2686 if (lastfree) fEND = lastfree->GetFirst();
2687 const char *root = "root";
2688 char *psave = new char[fBEGIN];
2689 char *buffer = psave;
2690 Int_t nfree = fFree->GetSize();
2691 memcpy(buffer, root, 4); buffer += 4;
2692 Int_t version = fVersion;
2693 if (version <1000000 && fEND > kStartBigFile) {version += 1000000; fUnits = 8;}
2694 tobuf(buffer, version);
2695 tobuf(buffer, (Int_t)fBEGIN);
2696 if (version < 1000000) {
2697 tobuf(buffer, (Int_t)fEND);
2698 tobuf(buffer, (Int_t)fSeekFree);
2699 tobuf(buffer, fNbytesFree);
2700 tobuf(buffer, nfree);
2701 tobuf(buffer, fNbytesName);
2702 tobuf(buffer, fUnits);
2703 tobuf(buffer, fCompress);
2704 tobuf(buffer, (Int_t)fSeekInfo);
2705 tobuf(buffer, fNbytesInfo);
2706 } else {
2707 tobuf(buffer, fEND);
2708 tobuf(buffer, fSeekFree);
2709 tobuf(buffer, fNbytesFree);
2710 tobuf(buffer, nfree);
2711 tobuf(buffer, fNbytesName);
2712 tobuf(buffer, fUnits);
2713 tobuf(buffer, fCompress);
2714 tobuf(buffer, fSeekInfo);
2715 tobuf(buffer, fNbytesInfo);
2716 }
2717 if (TestBit(kReproducible))
2718 TUUID("00000000-0000-0000-0000-000000000000").FillBuffer(buffer);
2719 else
2720 fUUID.FillBuffer(buffer);
2721 Int_t nbytes = buffer - psave;
2722 Seek(0); // NOLINT: silence clang-tidy warnings
2723 WriteBuffer(psave, nbytes); // NOLINT: silence clang-tidy warnings
2724 Flush(); // NOLINT: silence clang-tidy warnings, Intentionally not conditional on fMustFlush, this is the 'obligatory' flush.
2725 delete [] psave;
2726}
2727
2728////////////////////////////////////////////////////////////////////////////////
2729/// Generate source code necessary to access the objects stored in the file.
2730///
2731/// Generate code in directory dirname for all classes specified in
2732/// argument classes If classes = "*" (default and currently the
2733/// only supported value), the function generates an include file
2734/// for each class in the StreamerInfo list for which a TClass
2735/// object does not exist.
2736///
2737/// The code generated includes:
2738/// - <em>dirnameProjectHeaders.h</em>, which contains one `#include` statement per generated header file
2739/// - <em>dirnameProjectSource.cxx</em>,which contains all the constructors and destructors implementation.
2740/// and one header per class that is not nested inside another class.
2741/// The header file name is the fully qualified name of the class after all the special characters
2742/// "<>,:" are replaced by underscored. For example for std::pair<edm::Vertex,int> the file name is
2743/// pair_edm__Vertex_int_.h
2744///
2745/// In the generated classes, map, multimap when the first template parameter is a class
2746/// are replaced by a vector of pair. set and multiset when the tempalte parameter
2747/// is a class are replaced by a vector. This is required since we do not have the
2748/// code needed to order and/or compare the object of the classes.
2749/// This is a quick explanation of the options available:
2750/// Option | Details
2751/// -------|--------
2752/// new (default) | A new directory dirname is created. If dirname already exist, an error message is printed and the function returns.
2753/// 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.
2754/// 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".
2755/// genreflex | Use genreflex rather than rootcling to generate the dictionary.
2756/// 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).
2757///
2758/// If, in addition to one of the 3 above options, the option "+" is specified,
2759/// the function will generate:
2760/// - a script called MAKEP to build the shared lib
2761/// - a dirnameLinkDef.h file
2762/// - rootcling will be run to generate a dirnameProjectDict.cxx file
2763/// - dirnameProjectDict.cxx will be compiled with the current options in compiledata.h
2764/// - a shared lib dirname.so will be created.
2765/// If the option "++" is specified, the generated shared lib is dynamically
2766/// linked with the current executable module.
2767/// If the option "+" and "nocompile" are specified, the utility files are generated
2768/// as in the option "+" but they are not executed.
2769/// Example:
2770/// file.MakeProject("demo","*","recreate++");
2771/// - creates a new directory demo unless it already exist
2772/// - clear the previous directory content
2773/// - generate the xxx.h files for all classes xxx found in this file
2774/// and not yet known to the Cling dictionary.
2775/// - creates the build script MAKEP
2776/// - creates a LinkDef.h file
2777/// - runs rootcling generating demoProjectDict.cxx
2778/// - compiles demoProjectDict.cxx into demoProjectDict.o
2779/// - generates a shared lib demo.so
2780/// - dynamically links the shared lib demo.so to the executable
2781/// If only the option "+" had been specified, one can still link the
2782/// shared lib to the current executable module with:
2783///
2784/// gSystem->load("demo/demo.so");
2785///
2786/// The following feature is not yet enabled:
2787/// One can restrict the list of classes to be generated by using expressions like:
2788///
2789/// classes = "Ali*" generate code only for classes starting with Ali
2790/// classes = "myClass" generate code for class MyClass only.
2791///
2793void TFile::MakeProject(const char *dirname, const char * /*classes*/,
2795{
2796 TString opt = option;
2797 opt.ToLower();
2798
2799 void *dir = gSystem->OpenDirectory(dirname);
2801
2802 if (opt.Contains("update")) {
2803 // check that directory exist, if not create it
2804 if (!dir) {
2806 }
2807
2808 } else if (opt.Contains("recreate")) {
2809 // check that directory exist, if not create it
2810 if (!dir) {
2811 if (gSystem->mkdir(dirname) < 0) {
2812 Error("MakeProject","cannot create directory '%s'",dirname);
2813 return;
2814 }
2815 }
2816 // clear directory
2817 while (dir) {
2818 const char *afile = gSystem->GetDirEntry(dir);
2819 if (!afile) break;
2820 if (strcmp(afile,".") == 0) continue;
2821 if (strcmp(afile,"..") == 0) continue;
2822 dirpath.Form("%s/%s",dirname,afile);
2824 }
2825
2826 } else {
2827 // new is assumed
2828 // if directory already exist, print error message and return
2829 if (dir) {
2830 Error("MakeProject","cannot create directory %s, already existing",dirname);
2831 gSystem->FreeDirectory(dir);
2832 return;
2833 }
2834 if (gSystem->mkdir(dirname) < 0) {
2835 Error("MakeProject","cannot create directory '%s'",dirname);
2836 return;
2837 }
2838 }
2839 if (dir) {
2840 gSystem->FreeDirectory(dir);
2841 }
2842
2843 Bool_t genreflex = opt.Contains("genreflex");
2844
2845 // we are now ready to generate the classes
2846 // loop on all TStreamerInfo
2847 TList *filelist = (TList*)GetStreamerInfoCache();
2848 if (filelist) filelist = (TList*)filelist->Clone();
2849 if (!filelist) {
2850 Error("MakeProject","file %s has no StreamerInfo", GetName());
2851 return;
2852 }
2853
2855 if (clean_dirname[clean_dirname.Length()-1]=='/') {
2856 clean_dirname.Remove(clean_dirname.Length()-1);
2857 } else if (clean_dirname[clean_dirname.Length()-1]=='\\') {
2858 clean_dirname.Remove(clean_dirname.Length()-1);
2859 if (clean_dirname[clean_dirname.Length()-1]=='\\') {
2860 clean_dirname.Remove(clean_dirname.Length()-1);
2861 }
2862 }
2864 if (subdirname == "") {
2865 Error("MakeProject","Directory name must not be empty.");
2866 return;
2867 }
2868
2869 // Start the source file
2870 TString spath; spath.Form("%s/%sProjectSource.cxx",clean_dirname.Data(),subdirname.Data());
2871 FILE *sfp = fopen(spath.Data(),"w");
2872 if (!sfp) {
2873 Error("MakeProject","Unable to create the source file %s.",spath.Data());
2874 return;
2875 }
2876 fprintf(sfp, "namespace std {}\nusing namespace std;\n");
2877 fprintf(sfp, "#include \"%sProjectHeaders.h\"\n\n",subdirname.Data() );
2878 if (!genreflex) fprintf(sfp, "#include \"%sLinkDef.h\"\n\n",subdirname.Data() );
2879 fprintf(sfp, "#include \"%sProjectDict.cxx\"\n\n",subdirname.Data() );
2880 fprintf(sfp, "struct DeleteObjectFunctor {\n");
2881 fprintf(sfp, " template <typename T>\n");
2882 fprintf(sfp, " void operator()(const T *ptr) const {\n");
2883 fprintf(sfp, " delete ptr;\n");
2884 fprintf(sfp, " }\n");
2885 fprintf(sfp, " template <typename T, typename Q>\n");
2886 fprintf(sfp, " void operator()(const std::pair<T,Q> &) const {\n");
2887 fprintf(sfp, " // Do nothing\n");
2888 fprintf(sfp, " }\n");
2889 fprintf(sfp, " template <typename T, typename Q>\n");
2890 fprintf(sfp, " void operator()(const std::pair<T,Q*> &ptr) const {\n");
2891 fprintf(sfp, " delete ptr.second;\n");
2892 fprintf(sfp, " }\n");
2893 fprintf(sfp, " template <typename T, typename Q>\n");
2894 fprintf(sfp, " void operator()(const std::pair<T*,Q> &ptr) const {\n");
2895 fprintf(sfp, " delete ptr.first;\n");
2896 fprintf(sfp, " }\n");
2897 fprintf(sfp, " template <typename T, typename Q>\n");
2898 fprintf(sfp, " void operator()(const std::pair<T*,Q*> &ptr) const {\n");
2899 fprintf(sfp, " delete ptr.first;\n");
2900 fprintf(sfp, " delete ptr.second;\n");
2901 fprintf(sfp, " }\n");
2902 fprintf(sfp, "};\n\n");
2903 fclose( sfp );
2904
2905 // loop on all TStreamerInfo classes to check for empty classes
2906 // and enums listed either as data member or template parameters,
2907 // and filter out 'duplicates' classes/streamerInfos.
2911 TList *list = new TList();
2912 while ((info = (TStreamerInfo*)flnext())) {
2913 if (info->IsA() != TStreamerInfo::Class()) {
2914 continue;
2915 }
2916 if (strstr(info->GetName(),"@@")) {
2917 // Skip schema evolution support streamerInfo
2918 continue;
2919 }
2920 TClass *cl = TClass::GetClass(info->GetName());
2921 if (cl) {
2922 if (cl->HasInterpreterInfo()) continue; // skip known classes
2923 }
2924 // Find and use the proper rules for the TStreamerInfos.
2926 TIter enext( info->GetElements() );
2929 if (cl && cl->GetSchemaRules()) {
2930 rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
2931 }
2932 while( (el=(TStreamerElement*)enext()) ) {
2933 for(auto rule : rules) {
2934 if( rule->IsRenameRule() || rule->IsAliasRule() )
2935 continue;
2936 // Check whether this is an 'attribute' rule.
2937 if ( rule->HasTarget( el->GetName()) && rule->GetAttributes()[0] != 0 ) {
2938 TString attr( rule->GetAttributes() );
2939 attr.ToLower();
2940 if (attr.Contains("owner")) {
2941 if (attr.Contains("notowner")) {
2943 } else {
2945 }
2946 }
2947 }
2948 }
2950 }
2951 TVirtualStreamerInfo *alternate = (TVirtualStreamerInfo*)list->FindObject(info->GetName());
2952 if (alternate) {
2953 if ((info->GetClass() && info->GetClassVersion() == info->GetClass()->GetClassVersion())
2954 || (info->GetClassVersion() > alternate->GetClassVersion()) ) {
2955 list->AddAfter(alternate, info);
2956 list->Remove(alternate);
2957 } // otherwise ignore this info as not being the official one.
2958 } else {
2959 list->Add(info);
2960 }
2961 }
2962 // Now transfer the new StreamerInfo onto the main list and
2963 // to the owning list.
2965 while ((info = (TStreamerInfo*)nextextra())) {
2966 list->Add(info);
2967 filelist->Add(info);
2968 }
2969
2970 // loop on all TStreamerInfo classes
2971 TIter next(list);
2972 Int_t ngener = 0;
2973 while ((info = (TStreamerInfo*)next())) {
2974 if (info->IsA() != TStreamerInfo::Class()) {
2975 continue;
2976 }
2977 if (info->GetClassVersion()==-4) continue; // Skip outer level namespace
2978 TIter subnext(list);
2981 Int_t len = strlen(info->GetName());
2982 while ((subinfo = (TStreamerInfo*)subnext())) {
2983 if (subinfo->IsA() != TStreamerInfo::Class()) {
2984 continue;
2985 }
2986 if (strncmp(info->GetName(),subinfo->GetName(),len)==0) {
2987 // The 'sub' StreamerInfo start with the main StreamerInfo name,
2988 // it subinfo is likely to be a nested class.
2989 const Int_t sublen = strlen(subinfo->GetName());
2990 if ( (sublen > len) && subinfo->GetName()[len+1]==':'
2991 && !subClasses.FindObject(subinfo->GetName()) /* We need to insure uniqueness */)
2992 {
2993 subClasses.Add(subinfo);
2994 }
2995 }
2996 }
2997 ngener += info->GenerateHeaderFile(clean_dirname.Data(),&subClasses,&extrainfos);
2998 subClasses.Clear("nodelete");
2999 }
3000 extrainfos.Clear("nodelete"); // We are done with this list.
3001
3002 TString path;
3003 path.Form("%s/%sProjectHeaders.h",clean_dirname.Data(),subdirname.Data());
3004 FILE *allfp = fopen(path,"a");
3005 if (!allfp) {
3006 Error("MakeProject","Cannot open output file:%s\n",path.Data());
3007 } else {
3008 fprintf(allfp,"#include \"%sProjectInstances.h\"\n", subdirname.Data());
3009 fclose(allfp);
3010 }
3011
3012 printf("MakeProject has generated %d classes in %s\n",ngener,clean_dirname.Data());
3013
3014 // generate the shared lib
3015 if (!opt.Contains("+")) {
3016 delete list;
3017 filelist->Delete();
3018 delete filelist;
3019 return;
3020 }
3021
3022 // Makefiles files
3023 FILE *fpMAKE = nullptr;
3024 // Create the MAKEP file by looping on all *.h files
3025 // delete MAKEP if it already exists
3026#ifdef WIN32
3027 path.Form("%s/makep.cmd",clean_dirname.Data());
3028#else
3029 path.Form("%s/MAKEP",clean_dirname.Data());
3030#endif
3031#ifdef R__WINGCC
3032 fpMAKE = fopen(path,"wb");
3033#else
3034 fpMAKE = fopen(path,"w");
3035#endif
3036 if (!fpMAKE) {
3037 Error("MakeProject", "cannot open file %s", path.Data());
3038 delete list;
3039 filelist->Delete();
3040 delete filelist;
3041 return;
3042 }
3043
3044 // Add rootcling/genreflex statement generating ProjectDict.cxx
3045 FILE *ifp = nullptr;
3046 path.Form("%s/%sProjectInstances.h",clean_dirname.Data(),subdirname.Data());
3047#ifdef R__WINGCC
3048 ifp = fopen(path,"wb");
3049#else
3050 ifp = fopen(path,"w");
3051#endif
3052 if (!ifp) {
3053 Error("MakeProject", "cannot open path file %s", path.Data());
3054 delete list;
3055 filelist->Delete();
3056 delete filelist;
3057 fclose(fpMAKE);
3058 return;
3059 }
3060
3061 if (genreflex) {
3062 fprintf(fpMAKE,"genreflex %sProjectHeaders.h -o %sProjectDict.cxx --comments --iocomments %s ",subdirname.Data(),subdirname.Data(),gSystem->GetIncludePath());
3063 path.Form("%s/%sSelection.xml",clean_dirname.Data(),subdirname.Data());
3064 } else {
3065 fprintf(fpMAKE,"rootcling -v1 -f %sProjectDict.cxx %s ", subdirname.Data(), gSystem->GetIncludePath());
3066 path.Form("%s/%sLinkDef.h",clean_dirname.Data(),subdirname.Data());
3067 }
3068
3069 // Create the LinkDef.h or xml selection file by looping on all *.h files
3070 // replace any existing file.
3071#ifdef R__WINGCC
3072 FILE *fp = fopen(path,"wb");
3073#else
3074 FILE *fp = fopen(path,"w");
3075#endif
3076 if (!fp) {
3077 Error("MakeProject", "cannot open path file %s", path.Data());
3078 delete list;
3079 filelist->Delete();
3080 delete filelist;
3081 fclose(fpMAKE);
3082 fclose(ifp);
3083 return;
3084 }
3085 if (genreflex) {
3086 fprintf(fp,"<lcgdict>\n");
3087 fprintf(fp,"\n");
3088 } else {
3089 fprintf(fp,"#ifdef __CLING__\n");
3090 fprintf(fp,"\n");
3091 }
3092
3093 TString tmp;
3096 next.Reset();
3097 while ((info = (TStreamerInfo*)next())) {
3098 if (info->IsA() != TStreamerInfo::Class()) {
3099 continue;
3100 }
3101 if (strncmp(info->GetName(), "auto_ptr<", std::char_traits<char>::length("auto_ptr<")) == 0) {
3102 continue;
3103 }
3104 TClass *cl = TClass::GetClass(info->GetName());
3105 if (cl) {
3106 if (cl->HasInterpreterInfo()) continue; // skip known classes
3107 if (cl->GetSchemaRules()) {
3108 auto rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
3110 for(auto rule : rules) {
3111 strrule.Clear();
3112 if (genreflex) {
3113 rule->AsString(strrule,"x");
3114 strrule.Append("\n");
3115 if ( selections.Index(strrule) == kNPOS ) {
3116 selections.Append(strrule);
3117 }
3118 } else {
3119 rule->AsString(strrule);
3120 if (strncmp(strrule.Data(),"type=",5)==0) {
3121 strrule.Remove(0,5);
3122 }
3123 fprintf(fp,"#pragma %s;\n",strrule.Data());
3124 }
3125 }
3126 }
3127
3128 }
3129 if ((info->GetClass() && info->GetClass()->GetCollectionType()) || TClassEdit::IsSTLCont(info->GetName())) {
3130 std::vector<std::string> inside;
3131 int nestedLoc;
3133 Int_t stlkind = TClassEdit::STLKind(inside[0]);
3134 TClass *key = TClass::GetClass(inside[1].c_str());
3135 if (key) {
3136 TString what;
3137 switch ( stlkind ) {
3138 case ROOT::kSTLmap:
3139 case ROOT::kSTLmultimap:
3140 if (TClass::GetClass(inside[1].c_str())) {
3141 what = "std::pair<";
3142 what += TMakeProject::UpdateAssociativeToVector( inside[1].c_str() );
3143 what += ",";
3144 what += TMakeProject::UpdateAssociativeToVector( inside[2].c_str() );
3145 if (what[what.Length()-1]=='>') {
3146 what += " >";
3147 } else {
3148 what += ">";
3149 }
3150 if (genreflex) {
3151 tmp.Form("<class name=\"%s\" />\n",what.Data());
3152 if ( selections.Index(tmp) == kNPOS ) {
3153 selections.Append(tmp);
3154 }
3155 tmp.Form("template class %s;\n",what.Data());
3156 if ( instances.Index(tmp) == kNPOS ) {
3157 instances.Append(tmp);
3158 }
3159 } else {
3160 what.ReplaceAll("std::","");
3162 if (!paircl || !paircl->HasInterpreterInfo()) {
3163 fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
3164 }
3165 }
3166 break;
3167 }
3168 default:
3169 if (TClassEdit::IsStdPair(key->GetName())) {
3170 if (genreflex) {
3171 tmp.Form("<class name=\"%s\" />\n",key->GetName());
3172 if ( selections.Index(tmp) == kNPOS ) {
3173 selections.Append(tmp);
3174 }
3175 tmp.Form("template class %s;\n",key->GetName());
3176 if ( instances.Index(tmp) == kNPOS ) {
3177 instances.Append(tmp);
3178 }
3179 } else {
3180 what.ReplaceAll("std::","");
3181 fprintf(fp,"#pragma link C++ class %s+;\n",key->GetName());
3182 }
3183 }
3184 break;
3185 }
3186 }
3187 continue;
3188 }
3189 {
3191 if (genreflex) {
3192 tmp.Form("<class name=\"%s\" />\n",what.Data());
3193 if ( selections.Index(tmp) == kNPOS ) {
3194 selections.Append(tmp);
3195 }
3196 if (what[what.Length()-1] == '>') {
3197 tmp.Form("template class %s;\n",what.Data());
3198 if ( instances.Index(tmp) == kNPOS ) {
3199 instances.Append(tmp);
3200 }
3201 }
3202 } else {
3203 what.ReplaceAll("std::","");
3204 fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
3205 }
3206 }
3207 if (genreflex) {
3208 // Also request the dictionary for the STL container used as members ...
3209 TIter eliter( info->GetElements() );
3211 while( (element = (TStreamerElement*)eliter() ) ) {
3212 if (element->GetClass() && !element->GetClass()->IsLoaded() && element->GetClass()->GetCollectionProxy()) {
3214 tmp.Form("<class name=\"%s\" />\n",what.Data());
3215 if ( selections.Index(tmp) == kNPOS ) {
3216 selections.Append(tmp);
3217 }
3218 tmp.Form("template class %s;\n",what.Data());
3219 if ( instances.Index(tmp) == kNPOS ) {
3220 instances.Append(tmp);
3221 }
3222 }
3223 }
3224 }
3225 }
3226 if (genreflex) {
3227 fprintf(ifp,"#ifndef PROJECT_INSTANCES_H\n");
3228 fprintf(ifp,"#define PROJECT_INSTANCES_H\n");
3229 fprintf(ifp,"%s",instances.Data());
3230 fprintf(ifp,"#endif\n");
3231 fprintf(fp,"%s",selections.Data());
3232 fprintf(fp,"</lcgdict>\n");
3233 } else {
3234 fprintf(fp,"#endif\n");
3235 }
3236 fclose(fp);
3237 fclose(ifp);
3238
3239 // add compilation line
3241
3243 TString sources = TString::Format("%sProjectSource.cxx ", sdirname.Data());
3244 cmd.ReplaceAll("$SourceFiles",sources.Data());
3245 TString object = TString::Format("%sProjectSource.", sdirname.Data());
3246 object.Append( gSystem->GetObjExt() );
3247 cmd.ReplaceAll("$ObjectFiles", object.Data());
3248 cmd.ReplaceAll("$IncludePath",TString(gSystem->GetIncludePath()) + " -I" + clean_dirname.Data());
3249 cmd.ReplaceAll("$SharedLib",sdirname+"."+gSystem->GetSoExt());
3250 cmd.ReplaceAll("$LinkedLibs",gSystem->GetLibraries("","SDL"));
3251 cmd.ReplaceAll("$LibName",sdirname);
3252 cmd.ReplaceAll("$BuildDir",".");
3253 cmd.ReplaceAll("$RPath", "-Wl,-rpath," + gROOT->GetSharedLibDir());
3254 TString sOpt;
3256 if (rootbuild.Index("debug",0,TString::kIgnoreCase)==kNPOS) {
3258 } else {
3260 }
3261#if defined(_MSC_VER) && defined(_DEBUG)
3262 // if ROOT is build in debug mode, ACLiC must also build in debug mode
3263 // for compatibility reasons
3265#endif
3266 cmd.ReplaceAll("$Opt", sOpt);
3267
3268 if (genreflex) {
3269 fprintf(fpMAKE,"-s %sSelection.xml \n",subdirname.Data());
3270 } else {
3271 fprintf(fpMAKE,"%sProjectHeaders.h ",subdirname.Data());
3272 fprintf(fpMAKE,"%sLinkDef.h \n",subdirname.Data());
3273 }
3274
3275 fprintf(fpMAKE,"%s\n",cmd.Data());
3276
3277 printf("%s/MAKEP file has been generated\n", clean_dirname.Data());
3278
3279 fclose(fpMAKE);
3280
3281
3282 if (!opt.Contains("nocompilation")) {
3283 // now execute the generated script compiling and generating the shared lib
3284 path = gSystem->WorkingDirectory();
3286#ifndef WIN32
3287 gSystem->Exec("chmod +x MAKEP");
3288 int res = !gSystem->Exec("./MAKEP");
3289#else
3290 // not really needed for Windows but it would work both both Unix and NT
3291 chmod("makep.cmd",00700);
3292 int res = !gSystem->Exec("MAKEP");
3293#endif
3294 gSystem->ChangeDirectory(path);
3295 path.Form("%s/%s.%s",clean_dirname.Data(),subdirname.Data(),gSystem->GetSoExt());
3296 if (res) printf("Shared lib %s has been generated\n",path.Data());
3297
3298 //dynamically link the generated shared lib
3299 if (opt.Contains("++")) {
3300 res = !gSystem->Load(path);
3301 if (res) printf("Shared lib %s has been dynamically linked\n",path.Data());
3302 }
3303 }
3304
3305 delete list;
3306 filelist->Delete();
3307 delete filelist;
3308}
3309
3310////////////////////////////////////////////////////////////////////////////////
3311/// Read the list of StreamerInfo from this file.
3312///
3313/// The key with name holding the list of TStreamerInfo objects is read.
3314/// The corresponding TClass objects are updated.
3315/// Note that this function is not called if the static member fgReadInfo is false.
3316/// (see TFile::SetReadStreamerInfo)
3319{
3320 auto listRetcode = GetStreamerInfoListImpl(/*lookupSICache*/ true); // NOLINT: silence clang-tidy warnings
3321 TList *list = listRetcode.fList;
3322 auto retcode = listRetcode.fReturnCode;
3323 if (!list) {
3324 if (retcode) MakeZombie();
3325 return;
3326 }
3327
3328 list->SetOwner(kFALSE);
3329
3330 if (gDebug > 0) Info("ReadStreamerInfo", "called for file %s",GetName());
3331
3333
3334 Int_t version = fVersion;
3335 if (version > 1000000) version -= 1000000;
3336 if (version < 53419 || (59900 < version && version < 59907)) {
3337 // We need to update the fCheckSum field of the TStreamerBase.
3338
3339 // loop on all TStreamerInfo classes
3340 TObjLink *lnk = list->FirstLink();
3341 while (lnk) {
3342 info = (TStreamerInfo*)lnk->GetObject();
3343 if (!info || info->IsA() != TStreamerInfo::Class()) {
3344 lnk = lnk->Next();
3345 continue;
3346 }
3347 TIter next(info->GetElements());
3349 while ((element = (TStreamerElement*) next())) {
3350 TStreamerBase *base = dynamic_cast<TStreamerBase*>(element);
3351 if (!base) continue;
3352 if (base->GetBaseCheckSum() != 0) continue;
3353 TStreamerInfo *baseinfo = (TStreamerInfo*)list->FindObject(base->GetName());
3354 if (baseinfo) {
3355 base->SetBaseCheckSum(baseinfo->GetCheckSum());
3356 }
3357 }
3358 lnk = lnk->Next();
3359 }
3360 }
3361
3362 std::vector<Int_t> si_uids;
3363 // loop on all TStreamerInfo classes
3364 for (int mode=0;mode<2; ++mode) {
3365 // In order for the collection proxy to be initialized properly, we need
3366 // to setup the TStreamerInfo for non-stl class before the stl classes.
3367 TObjLink *lnk = list->FirstLink();
3368 while (lnk) {
3369 info = (TStreamerInfo*)lnk->GetObject();
3370 if (!info) {
3371 lnk = lnk->Next();
3372 continue;
3373 }
3374 if (info->IsA() != TStreamerInfo::Class()) {
3375 if (mode==1) {
3376 TObject *obj = (TObject*)info;
3377 if (strcmp(obj->GetName(),"listOfRules")==0) {
3378#if 0
3379 // Completely ignore the rules for now.
3380 TList *listOfRules = (TList*)obj;
3381 TObjLink *rulelnk = listOfRules->FirstLink();
3382 while (rulelnk) {
3383 TObjString *rule = (TObjString*)rulelnk->GetObject();
3384 TClass::AddRule( rule->String().Data() );
3385 rulelnk = rulelnk->Next();
3386 }
3387#endif
3388 } else {
3389 Warning("ReadStreamerInfo","%s has a %s in the list of TStreamerInfo.", GetName(), info->IsA()->GetName());
3390 }
3391 info->SetBit(kCanDelete);
3392 }
3393 lnk = lnk->Next();
3394 continue;
3395 }
3396 // This is a quick way (instead of parsing the name) to see if this is
3397 // the description of an STL container.
3398 if (info->GetElements()==0) {
3399 Warning("ReadStreamerInfo","The StreamerInfo for %s does not have a list of elements.",info->GetName());
3400 lnk = lnk->Next();
3401 continue;
3402 }
3403 TObject *element = info->GetElements()->UncheckedAt(0);
3404 Bool_t isstl = element && strcmp("This",element->GetName())==0;
3405
3406 if ( (!isstl && mode ==0) || (isstl && mode ==1) ) {
3407 // Skip the STL container the first time around
3408 // Skip the regular classes the second time around;
3409 info->BuildCheck(this);
3410 Int_t uid = info->GetNumber();
3411 Int_t asize = fClassIndex->GetSize();
3412 if (uid >= asize && uid <100000) fClassIndex->Set(2*asize);
3413 if (uid >= 0 && uid < fClassIndex->GetSize()) {
3414 si_uids.push_back(uid);
3415 fClassIndex->fArray[uid] = 1;
3416 }
3417 else if (!isstl && !info->GetClass()->IsSyntheticPair()) {
3418 printf("ReadStreamerInfo, class:%s, illegal uid=%d\n",info->GetName(),uid);
3419 }
3420 if (gDebug > 0) printf(" -class: %s version: %d info read at slot %d\n",info->GetName(), info->GetClassVersion(),uid);
3421 }
3422 lnk = lnk->Next();
3423 }
3424 }
3425 fClassIndex->fArray[0] = 0;
3426 list->Clear(); //this will delete all TStreamerInfo objects with kCanDelete bit set
3427 delete list;
3428
3429 // We are done processing the record, let future calls and other threads that it
3430 // has been done.
3431 fgTsSIHashes.Insert(listRetcode.fHash, std::move(si_uids));
3432}
3433
3434////////////////////////////////////////////////////////////////////////////////
3435/// Specify if the streamerinfos must be read at file opening.
3436///
3437/// If fgReadInfo is true (default) TFile::ReadStreamerInfo is called
3438/// when opening the file.
3439/// It may be interesting to set fgReadInfo to false to speedup the file
3440/// opening time or in case libraries containing classes referenced
3441/// by the file have not yet been loaded.
3442/// if fgReadInfo is false, one can still read the StreamerInfo with
3443/// myfile.ReadStreamerInfo();
3446{
3447 fgReadInfo = readinfo;
3448}
3449
3450////////////////////////////////////////////////////////////////////////////////
3451/// If the streamerinfos are to be read at file opening.
3452///
3453/// See TFile::SetReadStreamerInfo for more documentation.
3456{
3457 return fgReadInfo;
3458}
3459
3460////////////////////////////////////////////////////////////////////////////////
3461/// Show the StreamerInfo of all classes written to this file.
3464{
3465 TList *list = GetStreamerInfoList();
3466 if (!list) return;
3467
3468 list->ls();
3469 delete list;
3470}
3471
3472////////////////////////////////////////////////////////////////////////////////
3473/// Check if the ProcessID pidd is already in the file,
3474/// if not, add it and return the index number in the local file list.
3477{
3478 TProcessID *pid = pidd;
3479 if (!pid) pid = TProcessID::GetPID();
3480 TObjArray *pids = GetListOfProcessIDs();
3481 Int_t npids = GetNProcessIDs();
3482 for (Int_t i=0;i<npids;i++) {
3483 if (pids->At(i) == pid) return (UShort_t)i;
3484 }
3485
3486 this->SetBit(TFile::kHasReferences);
3487 pids->AddAtAndExpand(pid,npids);
3488 pid->IncrementCount();
3489 char name[32];
3490 snprintf(name,32,"ProcessID%d",npids);
3491 this->WriteTObject(pid,name);
3492 this->IncrementProcessIDs();
3493 if (gDebug > 0) {
3494 Info("WriteProcessID", "name=%s, file=%s", name, GetName());
3495 }
3496 return (UShort_t)npids;
3497}
3498
3499
3500////////////////////////////////////////////////////////////////////////////////
3501/// Write the list of TStreamerInfo as a single object in this file
3502/// The class Streamer description for all classes written to this file
3503/// is saved. See class TStreamerInfo.
3506{
3507 //if (!gFile) return;
3508 if (!fWritable) return;
3509 if (!fClassIndex) return;
3510 if (fIsPcmFile) return; // No schema evolution for ROOT PCM files.
3511 if (fClassIndex->fArray[0] == 0
3512 && fSeekInfo != 0) {
3513 // No need to update the index if no new classes added to the file
3514 // but write once an empty StreamerInfo list to mark that there is no need
3515 // for StreamerInfos in this file.
3516 return;
3517 }
3518 if (gDebug > 0) Info("WriteStreamerInfo", "called for file %s",GetName());
3519
3520 SafeDelete(fInfoCache);
3521
3522 // build a temporary list with the marked files
3523 TIter next(gROOT->GetListOfStreamerInfo());
3525 TList list;
3527 listOfRules.SetOwner(kTRUE);
3528 listOfRules.SetName("listOfRules");
3529 std::set<TClass*> classSet;
3530
3531 while ((info = (TStreamerInfo*)next())) {
3532 Int_t uid = info->GetNumber();
3533 if (fClassIndex->fArray[uid]) {
3534 list.Add(info);
3535 if (gDebug > 0) printf(" -class: %s info number %d saved\n",info->GetName(),uid);
3536
3537 // Add the IO customization rules to the list to be saved for the underlying
3538 // class but make sure to add them only once.
3539 TClass *clinfo = info->GetClass();
3540 if (clinfo && clinfo->GetSchemaRules()) {
3541 if ( classSet.find( clinfo ) == classSet.end() ) {
3542 if (gDebug > 0) printf(" -class: %s stored the I/O customization rules\n",info->GetName());
3543
3544 TObjArrayIter it( clinfo->GetSchemaRules()->GetRules() );
3546 while( (rule = (ROOT::TSchemaRule*)it.Next()) ) {
3547 TObjString *obj = new TObjString();
3548 rule->AsString(obj->String());
3549 listOfRules.Add(obj);
3550 }
3551 classSet.insert(clinfo);
3552 }
3553 }
3554 }
3555 }
3556
3557 // Write the StreamerInfo list even if it is empty.
3558 fClassIndex->fArray[0] = 2; //to prevent adding classes in TStreamerInfo::TagFile
3559
3560 if (listOfRules.GetEntries()) {
3561 // Only add the list of rules if we have something to say.
3562 list.Add(&listOfRules);
3563 }
3564
3565 //free previous StreamerInfo record
3566 if (fSeekInfo) MakeFree(fSeekInfo,fSeekInfo+fNbytesInfo-1);
3567 //Create new key
3568 TKey key(&list,"StreamerInfo",GetBestBuffer(), this);
3569 fKeys->Remove(&key);
3570 fSeekInfo = key.GetSeekKey();
3571 fNbytesInfo = key.GetNbytes();
3572 SumBuffer(key.GetObjlen());
3573 key.WriteFile(0);
3574
3575 fClassIndex->fArray[0] = 0;
3576
3577 list.RemoveLast(); // remove the listOfRules.
3578}
3579
3580////////////////////////////////////////////////////////////////////////////////
3581/// Open a file for reading through the file cache.
3582///
3583/// The file will be downloaded to the cache and opened from there.
3584/// If the download fails, it will be opened remotely.
3585/// The file will be downloaded to the directory specified by SetCacheFileDir().
3587TFile *TFile::OpenFromCache(const char *name, Option_t *, const char *ftitle,
3589{
3590 TFile *f = nullptr;
3591
3592 if (fgCacheFileDir == "") {
3593 ::Warning("TFile::OpenFromCache",
3594 "you want to read through a cache, but you have no valid cache "
3595 "directory set - reading remotely");
3596 ::Info("TFile::OpenFromCache", "set cache directory using TFile::SetCacheFileDir()");
3597 } else {
3598 TUrl fileurl(name);
3599
3600 if ((!strcmp(fileurl.GetProtocol(), "file"))) {
3601 // it makes no sense to read local files through a file cache
3602 if (!fgCacheFileForce)
3603 ::Warning("TFile::OpenFromCache",
3604 "you want to read through a cache, but you are reading "
3605 "local files - CACHEREAD disabled");
3606 } else {
3607 // this is a remote file and worthwhile to be put into the local cache
3608 // now create cachepath to put it
3611 cachefilepath = fgCacheFileDir;
3612 cachefilepath += fileurl.GetFile();
3614 if ((gSystem->mkdir(cachefilepathbasedir, kTRUE) < 0) &&
3616 ::Warning("TFile::OpenFromCache","you want to read through a cache, but I "
3617 "cannot create the directory %s - CACHEREAD disabled",
3618 cachefilepathbasedir.Data());
3619 } else {
3620 // check if this should be a zip file
3621 if (strlen(fileurl.GetAnchor())) {
3622 // remove the anchor and change the target name
3623 cachefilepath += "__";
3624 cachefilepath += fileurl.GetAnchor();
3625 fileurl.SetAnchor("");
3626 }
3627 if (strstr(name,"zip=")) {
3628 // filter out this option and change the target cache name
3629 TString urloptions = fileurl.GetOptions();
3631 TObjArray *objOptions = urloptions.Tokenize("&");
3632 Int_t optioncount = 0;
3634 for (Int_t n = 0; n < objOptions->GetEntries(); n++) {
3635 TString loption = ((TObjString*)objOptions->At(n))->GetName();
3636 TObjArray *objTags = loption.Tokenize("=");
3637 if (objTags->GetEntries() == 2) {
3638 TString key = ((TObjString*)objTags->At(0))->GetName();
3639 TString value = ((TObjString*)objTags->At(1))->GetName();
3640 if (key.CompareTo("zip", TString::kIgnoreCase)) {
3641 if (optioncount!=0) {
3642 newoptions += "&";
3643 }
3644 newoptions += key;
3645 newoptions += "=";
3646 newoptions += value;
3647 ++optioncount;
3648 } else {
3649 zipname = value;
3650 }
3651 }
3652 delete objTags;
3653 }
3654 delete objOptions;
3655 fileurl.SetOptions(newoptions.Data());
3656 cachefilepath += "__";
3658 fileurl.SetAnchor("");
3659 }
3660
3662
3663 // check if file is in the cache
3664 Long_t id;
3665 Long64_t size;
3666 Long_t flags;
3667 Long_t modtime;
3668 if (!gSystem->GetPathInfo(cachefilepath, &id, &size, &flags, &modtime)) {
3669 // file is in the cache
3670 if (!fgCacheFileDisconnected) {
3671 char cacheblock[256];
3672 char remotblock[256];
3673 // check the remote file for it's size and compare some magic bytes
3674 TString cfurl;
3676 cfurl += "?filetype=raw";
3677 TUrl rurl(name);
3678 TString ropt = rurl.GetOptions();
3679 ropt += "&filetype=raw";
3680 rurl.SetOptions(ropt);
3681
3682 Bool_t forcedcache = fgCacheFileForce;
3683 fgCacheFileForce = kFALSE;
3684
3685 TFile *cachefile = TFile::Open(cfurl, "READ");
3686 TFile *remotfile = TFile::Open(rurl.GetUrl(), "READ");
3687
3688 fgCacheFileForce = forcedcache;
3689
3690 if (!cachefile) {
3691 need2copy = kTRUE;
3692 ::Error("TFile::OpenFromCache",
3693 "cannot open the cache file to check cache consistency");
3694 return nullptr;
3695 }
3696
3697 if (!remotfile) {
3698 ::Error("TFile::OpenFromCache",
3699 "cannot open the remote file to check cache consistency");
3700 return nullptr;
3701 }
3702
3703 cachefile->Seek(0);
3704 remotfile->Seek(0);
3705
3706 if ((!cachefile->ReadBuffer(cacheblock,256)) &&
3707 (!remotfile->ReadBuffer(remotblock,256))) {
3708 if (memcmp(cacheblock, remotblock, 256)) {
3709 ::Warning("TFile::OpenFromCache", "the header of the cache file "
3710 "differs from the remote file - forcing an update");
3711 need2copy = kTRUE;
3712 }
3713 } else {
3714 ::Warning("TFile::OpenFromCache", "the header of the cache and/or "
3715 "remote file are not readable - forcing an update");
3716 need2copy = kTRUE;
3717 }
3718
3719 delete remotfile;
3720 delete cachefile;
3721 }
3722 } else {
3723 need2copy = kTRUE;
3724 }
3725
3726 // try to fetch the file (disable now the forced caching)
3727 Bool_t forcedcache = fgCacheFileForce;
3728 fgCacheFileForce = kFALSE;
3729 if (need2copy) {
3730 const auto cachefilepathtmp = cachefilepath + std::to_string(gSystem->GetPid()) + ".tmp";
3732 ::Warning("TFile::OpenFromCache",
3733 "you want to read through a cache, but I "
3734 "cannot make a cache copy of %s - CACHEREAD disabled",
3735 cachefilepathbasedir.Data());
3736 fgCacheFileForce = forcedcache;
3737 return nullptr;
3738 }
3739 if (gSystem->AccessPathName(cachefilepath)) // then file _does not_ exist (weird convention)
3741 else // another process or thread already wrote a file with the same name while we were copying it
3743 }
3744 fgCacheFileForce = forcedcache;
3745 ::Info("TFile::OpenFromCache", "using local cache copy of %s [%s]", name, cachefilepath.Data());
3746 // finally we have the file and can open it locally
3747 fileurl.SetProtocol("file");
3748 fileurl.SetFile(cachefilepath);
3749
3752 tagfile += ".ROOT.cachefile";
3753 // we symlink this file as a ROOT cached file
3755 return TFile::Open(fileurl.GetUrl(), "READ", ftitle, compress, netopt);
3756 }
3757 }
3758 }
3759
3760 // Failed
3761 return f;
3762}
3763
3764////////////////////////////////////////////////////////////////////////////////
3765/// Create / open a file
3766///
3767/// The type of the file can be either a
3768/// TFile or any TFile derived class for which an
3769/// plugin library handler has been registered with the plugin manager
3770/// (for the plugin manager see the TPluginManager class). The returned
3771/// type of TFile depends on the file name specified by 'url'.
3772/// If 'url' is a '|'-separated list of file URLs, the 'URLs' are tried
3773/// sequentially in the specified order until a successful open.
3774/// If the file starts with "root:", "roots:" or "rootk:" an XRootD-backed file
3775/// will be returned, with "http:" a curl-based file, with "file:" a local TFile,
3776/// etc. (see the list of TFile plugin handlers in $ROOTSYS/etc/system.rootrc
3777/// for regular expressions that will be checked) and as last a local file will
3778/// be tried.
3779/// Before opening a file via a remote API, a check is made to see if the URL
3780/// specifies a local file. If that is the case the file will be opened
3781/// via a normal TFile. To force the opening of a local file via a
3782/// specify as host "localhost".
3783/// The netopt argument is not used, any more. For the meaning of the
3784/// options and other arguments see the constructors of the individual
3785/// file classes. In case of error, it returns a nullptr.
3786///
3787/// For TFile implementations supporting asynchronous file open, see
3788/// TFile::AsyncOpen(...), it is possible to request a timeout with the
3789/// option <b>`TIMEOUT=<secs>`</b>: the timeout must be specified in seconds and
3790/// it will be internally checked with granularity of one millisec.
3791/// For remote files there is the option: <b>CACHEREAD</b> opens an existing
3792/// file for reading through the file cache. The file will be downloaded to
3793/// the cache and opened from there. If the download fails, it will be opened remotely.
3794/// The file will be downloaded to the directory specified by SetCacheFileDir().
3795///
3796/// *The caller is responsible for deleting the pointer.*
3797/// In READ mode, a nullptr is returned if the file does not exist or cannot be opened.
3798/// In CREATE mode, a nullptr is returned if the file already exists or cannot be created.
3799/// In RECREATE mode, a nullptr is returned if the file can not be created.
3800/// In UPDATE mode, a nullptr is returned if the file cannot be created or opened.
3802TFile *TFile::Open(const char *url, Option_t *options, const char *ftitle,
3804{
3806 TFile *f = nullptr;
3807 EFileType type = kFile;
3808
3809 // Check input
3810 if (!url || strlen(url) <= 0) {
3811 ::Error("TFile::Open", "no url specified");
3812 return f;
3813 }
3814
3817
3818 if (auto xurl = ROOT::Internal::GetEOSRedirectedXRootURL(expandedUrl)) {
3819 if ((f = TFile::Open(xurl->c_str(), options, ftitle, compress, netopt))) {
3820 if (!f->IsZombie()) {
3821 return f;
3822 } else {
3823 delete f;
3824 f = nullptr;
3825 }
3826 }
3827 }
3828
3829 // If a timeout has been specified extract the value and try to apply it (it requires
3830 // support for asynchronous open, though; the following is completely transparent if
3831 // such support if not available for the required protocol)
3832 TString opts(options);
3833 opts.ToUpper();
3834 Int_t ito = opts.Index("TIMEOUT=");
3835 if (ito != kNPOS) {
3836 TString sto = opts(ito + std::char_traits<char>::length("TIMEOUT="), opts.Length());
3837 while (!(sto.IsDigit()) && !(sto.IsNull())) { sto.Remove(sto.Length()-1,1); }
3838 if (!(sto.IsNull())) {
3839 // Timeout in millisecs
3840 Int_t toms = sto.Atoi() * 1000;
3841 if (gDebug > 0) ::Info("TFile::Open", "timeout of %d millisec requested", toms);
3842 // Remove from the options field
3843 sto.Insert(0, "TIMEOUT=");
3844 opts.ReplaceAll(sto, "");
3845 // Asynchronous open
3847 // Check the result in steps of 1 millisec
3850 Int_t xtms = toms;
3851 while (aos == TFile::kAOSInProgress && xtms > 0) {
3852 gSystem->Sleep(1);
3853 xtms -= 1;
3855 }
3857 // Do open the file now
3858 f = TFile::Open(fh);
3859 if (gDebug > 0) {
3860 if (aos == TFile::kAOSSuccess)
3861 ::Info("TFile::Open", "waited %d millisec for asynchronous open", toms - xtms);
3862 else
3863 ::Info("TFile::Open", "timeout option not supported (requires asynchronous"
3864 " open support)");
3865 }
3866 } else {
3867 if (xtms <= 0)
3868 ::Error("TFile::Open", "timeout expired while opening '%s'", expandedUrl.Data());
3869 // Cleanup the request
3870 SafeDelete(fh);
3871 }
3872 // Done
3873 return f;
3874 } else {
3875 ::Warning("TFile::Open", "incomplete 'TIMEOUT=' option specification - ignored");
3876 opts.ReplaceAll("TIMEOUT=", "");
3877 }
3878 }
3879
3880 // We will use this from now on
3881 const char *option = opts;
3882
3883 // Many URLs? Redirect output and print errors in case of global failure
3885 Ssiz_t ip = namelist.Index("|");
3886 Bool_t rediroutput = (ip != kNPOS &&
3887 ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
3889 if (rediroutput) {
3890 TString outf = ".TFileOpen_";
3892 if (fout) {
3893 fclose(fout);
3894 gSystem->RedirectOutput(outf, "w", &rh);
3895 }
3896 }
3897
3898 // Try sequentially all names in 'names'
3899 TString name, n;
3900 Ssiz_t from = 0;
3901 while (namelist.Tokenize(n, from, "|") && !f) {
3902
3903 // check if we read through a file cache
3904 if (!strcasecmp(option, "CACHEREAD") ||
3905 ((!strcasecmp(option, "READ") || !strcasecmp(option, "READ_WITHOUT_GLOBALREGISTRATION") || !option[0]) &&
3906 fgCacheFileForce)) {
3907 // Try opening the file from the cache
3909 return f;
3910 }
3911
3912 IncrementFileCounter();
3913
3914 // change names to be recognized by the plugin manager
3915 // e.g. /protocol/path/to/file.root -> protocol:/path/to/file.root
3916 TUrl urlname(n, kTRUE);
3917 name = urlname.GetUrl();
3918 // Check first if a pending async open request matches this one
3919 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
3920 TIter nxr(fgAsyncOpenRequests);
3921 TFileOpenHandle *fh = nullptr;
3922 while ((fh = (TFileOpenHandle *)nxr()))
3923 if (fh->Matches(name))
3924 return TFile::Open(fh);
3925 }
3926
3927 TString urlOptions(urlname.GetOptions());
3928 if (urlOptions.BeginsWith("pmerge") || urlOptions.Contains("&pmerge") || urlOptions.Contains(" pmerge")) {
3929 type = kMerge;
3930
3931 // Pass the full name including the url options:
3932 f = (TFile*) gROOT->ProcessLineFast(TString::Format("new TParallelMergingFile(\"%s\",\"%s\",\"%s\",%d)",n.Data(),option,ftitle,compress));
3933
3934 } else {
3935 // Resolve the file type; this also adjusts names
3936 TString lfname = gEnv->GetValue("Path.Localroot", "");
3937 type = GetType(name, option, &lfname);
3938
3939 if (type == kLocal) {
3940
3941 // Local files
3942 if (lfname.IsNull()) {
3943 urlname.SetHost("");
3944 urlname.SetProtocol("file");
3945 lfname = urlname.GetUrl();
3946 }
3947 f = new TFile(lfname.Data(), option, ftitle, compress);
3948
3949 } else if (type == kNet) {
3950
3951 // Network files
3952 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
3953 if (h->LoadPlugin() == -1) {
3954 ::Error("TFile::Open", "Failed to load plugin %s", name.Data());
3955 return nullptr;
3956 }
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 ::Error("TFile::Open", "Failed to load plugin %s", name.Data());
3966 return nullptr;
3967 }
3968 f = (TFile*) h->ExecPlugin(2, name.Data(), option);
3969 }
3970
3971 } else if (type == kFile) {
3972
3973 // 'file:' protocol
3974 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
3975 h->LoadPlugin() == 0) {
3976 name.ReplaceAll("file:", "");
3977 f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
3978 } else
3979 f = new TFile(name.Data(), option, ftitle, compress);
3980
3981 } else {
3982
3983 // no recognized specification: try the plugin manager
3984 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name.Data()))) {
3985 if (h->LoadPlugin() == -1) {
3986 ::Error("TFile::Open", "Failed to load plugin %s", name.Data());
3987 return nullptr;
3988 }
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.
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().
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, cmd.Sizeof());
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.
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 // Set optimization options for the destination file
4721 TString opt = dURL.GetOptions();
4722 if (opt != "")
4723 opt += "&";
4724 // Files will be open in RAW mode
4725 opt += "filetype=raw";
4726
4727 dURL.SetOptions(opt);
4728
4729 char *copybuffer = nullptr;
4730
4731 TFile *sfile = this;
4732 TFile *dfile = nullptr;
4733
4734 // "RECREATE" does not work always well with XROOTD
4735 // namely when some pieces of the path are missing;
4736 // we force "NEW" in such a case
4737 if (TFile::GetType(ourl, "") == TFile::kNet) {
4738 if (gSystem->AccessPathName(ourl)) {
4739 oopt = "NEW";
4740 // Force creation of the missing parts of the path
4741 opt += "&mkpath=1";
4742 dURL.SetOptions(opt);
4743 }
4744 }
4745
4746 // Open destination file
4747 if (!(dfile = TFile::Open(dURL.GetUrl(), oopt))) {
4748 ::Error("TFile::Cp", "cannot open destination file %s", dst);
4749 goto copyout;
4750 }
4751
4752 // Probably we created a new file
4753 // We have to remove it in case of errors
4755
4756 sfile->Seek(0);
4757 dfile->Seek(0);
4758
4759 copybuffer = new char[bufsize];
4760 if (!copybuffer) {
4761 ::Error("TFile::Cp", "cannot allocate the copy buffer");
4762 goto copyout;
4763 }
4764
4767
4768 totalread = 0;
4769 filesize = sfile->GetSize();
4770
4771 watch.Start();
4772
4773 b00 = sfile->GetBytesRead();
4774
4775 do {
4776 if (progressbar) CpProgress(totalread, filesize,watch);
4777
4778 Long64_t b1 = sfile->GetBytesRead() - b00;
4779
4781 if (filesize - b1 > (Long64_t)bufsize) {
4782 readsize = bufsize;
4783 } else {
4784 readsize = filesize - b1;
4785 }
4786
4787 if (readsize == 0) break;
4788
4789 Long64_t b0 = sfile->GetBytesRead();
4791 readop = sfile->ReadBuffer(copybuffer, (Int_t)readsize);
4792 read = sfile->GetBytesRead() - b0;
4793 if ((read <= 0) || readop) {
4794 ::Error("TFile::Cp", "cannot read from source file %s. readsize=%lld read=%lld readop=%d",
4795 sfile->GetName(), readsize, read, readop);
4796 goto copyout;
4797 }
4798
4799 Long64_t w0 = dfile->GetBytesWritten();
4800 writeop = dfile->WriteBuffer(copybuffer, (Int_t)read);
4801 written = dfile->GetBytesWritten() - w0;
4802 if ((written != read) || writeop) {
4803 ::Error("TFile::Cp", "cannot write %lld bytes to destination file %s", read, dst);
4804 goto copyout;
4805 }
4806 totalread += read;
4807 } while (read == (Long64_t)bufsize);
4808
4809 if (progressbar) {
4810 CpProgress(totalread, filesize,watch);
4811 fprintf(stderr, "\n");
4812 }
4813
4814 success = kTRUE;
4815
4816copyout:
4817 if (dfile) dfile->Close();
4818
4819 if (dfile) delete dfile;
4820 if (copybuffer) delete[] copybuffer;
4821
4822 if (rmdestiferror && (success != kTRUE))
4823 gSystem->Unlink(dst);
4824
4825 watch.Stop();
4826 watch.Reset();
4827
4828 return success;
4829}
4830
4831////////////////////////////////////////////////////////////////////////////////
4832/// Allows to copy file from src to dst URL. Returns kTRUE in case of success,
4833/// kFALSE otherwise.
4835Bool_t TFile::Cp(const char *src, const char *dst, Bool_t progressbar,
4837{
4838 TUrl sURL(src, kTRUE);
4839
4840 TFile *sfile = nullptr;
4841
4843
4844 // Open source file
4845 if (!(sfile = TFile::Open(sURL.GetUrl(), "READ"))) {
4846 ::Error("TFile::Cp", "cannot open source file %s", src);
4847 } else {
4849 }
4850
4851 if (sfile) {
4852 sfile->Close();
4853 delete sfile;
4854 }
4855
4856 return success;
4857}
4858
4859//______________________________________________________________________________
4860//The next statement is not active anymore on Linux.
4861//Using posix_fadvise introduces a performance penalty (10 %) on optimized files
4862//and in addition it destroys the information of TTreePerfStats
4863#if defined(R__neverLINUX) && !defined(R__WINGCC)
4865{
4866 // Read specified byte range asynchronously. Actually we tell the kernel
4867 // which blocks we are going to read so it can start loading these blocks
4868 // in the buffer cache.
4869
4870 // Shortcut to avoid having to implement dummy ReadBufferAsync() in all
4871 // I/O plugins. Override ReadBufferAsync() in plugins if async is supported.
4872 if (IsA() != TFile::Class())
4873 return kTRUE;
4874
4876 if (len == 0) {
4877 // according POSIX spec if len is zero, all data following offset
4878 // is specified. Nevertheless ROOT uses zero to probe readahead
4879 // capabilities.
4881 }
4882 Double_t start = 0;
4883 if (gPerfStats) start = TTimeStamp();
4884#if defined(R__SEEK64)
4886#else
4888#endif
4889 if (gPerfStats) {
4890 gPerfStats->FileReadEvent(this, len, start);
4891 }
4892 return (result != 0);
4893}
4894#else
4896{
4897 // Not supported yet on non Linux systems.
4898
4899 return kTRUE;
4900}
4901#endif
4902
4903////////////////////////////////////////////////////////////////////////////////
4904/// Max number of bytes to prefetch.
4905///
4906/// By default this is 75% of the
4907/// read cache size. But specific TFile implementations may need to change it
4910{
4911 TFileCacheRead *cr = nullptr;
4912 if ((cr = GetCacheRead())) {
4913 Int_t bytes = cr->GetBufferSize() / 4 * 3;
4914 return ((bytes < 0) ? 0 : bytes);
4915 }
4916 return 0;
4917}
void frombuf(char *&buf, Bool_t *x)
Definition Bytes.h:270
void tobuf(char *&buf, Bool_t x)
Definition Bytes.h:55
T ReadBuffer(TBufferFile *buf)
One of the template functions used to read objects from messages.
Definition MPSendRecv.h:158
#define SafeDelete(p)
Definition RConfig.hxx:507
#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)
double * dst
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:78
unsigned short UShort_t
Unsigned Short integer 2 bytes (unsigned short)
Definition RtypesCore.h:55
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Version_t
Class version identifier (short)
Definition RtypesCore.h:80
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:69
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:54
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:132
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:84
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gDirectory
Definition TDirectory.h:385
R__EXTERN TEnv * gEnv
Definition TEnv.h:126
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
void SysError(const char *location, const char *msgfmt,...)
Use this function in case a system (OS or GUI) related error occurred.
Definition TError.cxx:219
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
const Int_t kBEGIN
Definition TFile.cxx:206
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:142
#define gInterpreter
@ kCanDelete
Definition TObject.h:375
R__EXTERN TPluginManager * gPluginMgr
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:792
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:417
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2585
@ kDefault
Definition TSystem.h:243
@ kFileExists
Definition TSystem.h:52
@ kReadPermission
Definition TSystem.h:55
@ kWritePermission
Definition TSystem.h:54
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
R__EXTERN void **(* gThreadTsd)(void *, Int_t)
R__EXTERN TVirtualMonitoringWriter * gMonitoringWriter
#define R__LOCKGUARD(mutex)
#define gPerfStats
#define R__WRITE_LOCKGUARD(mutex)
#define R__READ_LOCKGUARD(mutex)
std::optional< TKeyMapNode > Next()
Definition TFile.cxx:1664
TIterator(TFile *file, std::uint64_t addr)
Definition TFile.cxx:1657
TIterator end() const
Definition TFile.h:125
This class is a thread-safe associative collection connecting a 256 bits digest/hash to a collection ...
const_iterator end() const
const char * GetMemberName() const
virtual Int_t SetCurrentMember()=0
const char * GetArchiveName() const
TArchiveMember * GetMember() const
static TArchiveFile * Open(const char *url, TFile *file)
Return proper archive file handler depending on passed url.
Long64_t GetMemberFilePosition() const
Return position in archive of current member.
virtual Int_t OpenArchive()=0
Long64_t GetDecompressedSize() const
Array of chars or bytes (8 bits per element).
Definition TArrayC.h:27
Char_t * fArray
Definition TArrayC.h:30
Buffer base class used for serializing objects.
Definition TBuffer.h:43
@ kInitialSize
Definition TBuffer.h:78
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
Bool_t HasInterpreterInfo() const
Definition TClass.h:424
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition TClass.cxx:1939
static Bool_t AddRule(const char *rule)
Add a schema evolution customization rule.
Definition TClass.cxx:1883
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4995
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:2999
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:427
void ReadBuffer(char *&buffer)
Decode Date/Time from output buffer, used by I/O system.
Definition TDatime.cxx:274
A ROOT file is structured in Directories (like a file system).
void Close(Option_t *option="") override
Delete all objects from memory and directory structure itself.
Bool_t cd() override
Change current directory to "this" directory.
Bool_t IsWritable() const override
void Delete(const char *namecycle="") override
Delete Objects or/and keys in the current directory.
Int_t ReadKeys(Bool_t forceRead=kTRUE) override
Read the linked list of keys.
TDatime fDatimeM
Date and time of last modification.
Int_t fNbytesKeys
Number of bytes for the keys.
Int_t GetNkeys() const override
Long64_t fSeekKeys
Location of Keys record on file.
Int_t Sizeof() const override
Return the size in bytes of the directory header.
Long64_t fSeekParent
Location of parent directory on file.
void BuildDirectoryFile(TFile *motherFile, TDirectory *motherDir)
Initialise directory to defaults.
Int_t Write(const char *name=nullptr, Int_t opt=0, Int_t bufsize=0) override
Write all objects in memory to disk.
Long64_t fSeekDir
Location of directory on file.
Int_t fNbytesName
Number of bytes in TNamed at creation time.
TDatime fDatimeC
Date and time when directory is created.
Bool_t fWritable
True if directory is writable.
TObject * Get(const char *namecycle) override
Return pointer to object identified by namecycle.
void FillBuffer(char *&buffer) override
Encode directory header into output buffer.
void SetWritable(Bool_t writable=kTRUE) override
Set the new value of fWritable recursively.
TList * fKeys
Pointer to keys list in memory.
void ls(Option_t *option="") const override
List Directory contents.
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
Describe directory structure in memory.
Definition TDirectory.h:45
virtual TList * GetList() const
Definition TDirectory.h:223
void SetName(const char *newname) override
Set the name for directory If the directory name is changed after the directory was written once,...
TUUID fUUID
Unique identifier.
Definition TDirectory.h:143
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
TList * fList
List of objects in memory.
Definition TDirectory.h:142
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:511
A cache when reading files over the network.
virtual void Close(Option_t *option="")
Close out any threads or asynchronous fetches used by the underlying implementation.
virtual void SetFile(TFile *file, TFile::ECacheAction action=TFile::kDisconnect)
Set the file using this cache and reset the current blocks (if any).
A cache when writing files over the network.
virtual Bool_t Flush()
Flush the current write buffer to the file.
Class holding info about the file being opened.
Definition TFile.h:446
TFile * fFile
TFile instance of the file being opened.
Definition TFile.h:454
Int_t GetNetOpt() const
Definition TFile.h:473
TFile * GetFile() const
Definition TFile.h:464
const char * GetOpt() const
Definition TFile.h:471
Bool_t Matches(const char *name)
Return kTRUE if this async request matches the open request specified by 'url'.
Definition TFile.cxx:4494
Int_t GetCompress() const
Definition TFile.h:472
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:130
static std::atomic< Long64_t > fgBytesRead
Number of bytes read by all TFile objects.
Definition TFile.h:184
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:2016
void ls(Option_t *option="") const override
List file contents.
Definition TFile.cxx:1482
ROOT::Detail::TKeyMapIterable WalkTKeys()
Traverses all TKeys in the TFile and returns information about them.
Definition TFile.cxx:1652
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:2340
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:1194
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:1390
static Bool_t GetReadStreamerInfo()
If the streamerinfos are to be read at file opening.
Definition TFile.cxx:3454
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:2228
virtual void ReadStreamerInfo()
Read the list of StreamerInfo from this file.
Definition TFile.cxx:3317
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:2431
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:1400
static void SetReadStreamerInfo(Bool_t readinfo=kTRUE)
Specify if the streamerinfos must be read at file opening.
Definition TFile.cxx:3444
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:1764
Int_t GetBestBuffer() const
Return the best buffer size of objects on this file.
Definition TFile.cxx:1207
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:2385
TFileCacheWrite * GetCacheWrite() const
Return a pointer to the current write cache.
Definition TFile.cxx:1303
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:1772
static std::atomic< Long64_t > fgFileCounter
Counter for all opened files.
Definition TFile.h:186
virtual EAsyncOpenStatus GetAsyncOpenStatus()
Definition TFile.h:215
void Streamer(TBuffer &) override
Stream a TFile object.
Definition TFile.cxx:2471
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:2585
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:1954
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:1088
virtual void Map()
Definition TFile.h:359
virtual void WriteFree()
Write FREE linked list on the file.
Definition TFile.cxx:2609
static Int_t GetReadaheadSize()
Static function returning the readahead buffer size.
Definition TFile.cxx:4303
~TFile() override
File destructor.
Definition TFile.cxx:599
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:1886
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:3475
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:2792
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:1371
virtual Bool_t IsOpen() const
Returns kTRUE in case file is open and kFALSE if file is not open.
Definition TFile.cxx:1494
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:2502
virtual Int_t GetErrno() const
Method returning errno.
Definition TFile.cxx:1270
virtual void SetCompressionSettings(Int_t settings=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault)
Used to specify the compression level and algorithm.
Definition TFile.cxx:2404
@ kStartBigFile
Definition TFile.h:278
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:649
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:2454
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:2542
void SumBuffer(Int_t bufsize)
Increment statistics for buffer sizes of objects in this file.
Definition TFile.cxx:2483
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:3504
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:1108
virtual void SetCompressionAlgorithm(Int_t algorithm=ROOT::RCompressionSetting::EAlgorithm::kUseGlobal)
See comments for function SetCompressionSettings.
Definition TFile.cxx:2371
virtual const TUrl * GetEndpointUrl() const
Definition TFile.h:323
Int_t fNbytesFree
Number of bytes for free segments structure.
Definition TFile.h:163
Int_t fD
File descriptor.
Definition TFile.h:160
static constexpr Version_t Class_Version()
Definition TFile.h:436
virtual void ResetErrno() const
Method resetting the errno.
Definition TFile.cxx:1278
Int_t Sizeof() const override
Return the size in bytes of the file header.
Definition TFile.cxx:2463
Bool_t FlushWriteCache()
Flush the write cache if active.
Definition TFile.cxx:1182
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:223
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:290
virtual void ShowStreamerInfo()
Show the StreamerInfo of all classes written to this file.
Definition TFile.cxx:3462
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:1990
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:1165
TList * fFree
Free segments linked list table.
Definition TFile.h:171
virtual Bool_t ReadBufferAsync(Long64_t offs, Int_t len)
Definition TFile.cxx:4894
void Delete(const char *namecycle="") override
Delete Objects or/and keys in the current directory.
Definition TFile.cxx:1120
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:1150
virtual void MakeFree(Long64_t first, Long64_t last)
Mark unused bytes on the file.
Definition TFile.cxx:1509
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:2319
static std::atomic< Long64_t > fgBytesWrite
Number of bytes written by all TFile objects.
Definition TFile.h:185
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:4908
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:3801
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:1133
void Close(Option_t *option="") override
Close a file.
Definition TFile.cxx:991
TClass * IsA() const override
Definition TFile.h:436
static std::atomic< Int_t > fgReadCalls
Number of bytes read from all TFile objects.
Definition TFile.h:187
virtual Int_t Recover()
Attempt to recover file if not correctly closed.
Definition TFile.cxx:2113
virtual TList * GetStreamerInfoList() final
Read the list of TStreamerInfo objects written to this file.
Definition TFile.cxx:1470
virtual void WriteHeader()
Write File Header.
Definition TFile.cxx:2681
@ kReproducible
Definition TFile.h:271
@ kDevNull
Definition TFile.h:267
@ kHasReferences
Definition TFile.h:266
@ k630forwardCompatibility
Definition TFile.h:264
@ kWriteError
Definition TFile.h:268
@ kBinaryFile
Definition TFile.h:269
static TFile * OpenFromCache(const char *name, Option_t *="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Open a file for reading through the file cache.
Definition TFile.cxx:3586
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:1325
virtual Bool_t ReadBuffer(char *buf, Int_t len)
Read a buffer from the file.
Definition TFile.cxx:1836
Float_t GetCompressionFactor()
Return the file compression factor.
Definition TFile.cxx:1226
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:1286
static TList * fgAsyncOpenRequests
Definition TFile.h:200
Service class for TFile.
Definition TFree.h:27
TFree * AddFree(TList *lfree, Long64_t first, Long64_t last)
Add a new free segment to the list of free segments.
Definition TFree.cxx:66
static void MakeFunctor(const char *name, const char *type, GlobFunc &func)
Definition TGlobal.h:73
void Reset()
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
void Delete(Option_t *option="") override
Delete an object from the file.
Definition TKey.cxx:584
virtual Long64_t GetSeekKey() const
Definition TKey.h:91
Int_t GetKeylen() const
Definition TKey.h:86
Int_t GetObjlen() const
Definition TKey.h:89
Int_t GetNbytes() const
Definition TKey.h:88
virtual const char * GetClassName() const
Definition TKey.h:77
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition TKey.cxx:1227
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1614
virtual char * GetBuffer() const
Definition TKey.h:80
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:81
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:789
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:600
static void GenerateMissingStreamerInfos(TList *extrainfos, TStreamerElement *element)
Generate an empty StreamerInfo for types that are used in templates parameters but are not known in t...
static TString UpdateAssociativeToVector(const char *name)
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition TMap.h:40
TObject * GetValue(const char *keyname) const
Returns a pointer to the value associated with keyname as name of the key.
Definition TMap.cxx:235
virtual void FillBuffer(char *&buffer)
Encode TNamed into output buffer.
Definition TNamed.cxx:103
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
TString fTitle
Definition TNamed.h:33
TString fName
Definition TNamed.h:32
virtual Int_t Sizeof() const
Return size of the TNamed part of the TObject.
Definition TNamed.cxx:182
Iterator of object array.
Definition TObjArray.h:123
TObject * Next() override
Return next object in array. Returns 0 when no more objects in array.
An array of TObjects.
Definition TObjArray.h:31
Collectable string class.
Definition TObjString.h:28
TString & String()
Definition TObjString.h:48
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:461
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:479
virtual void SysError(const char *method, const char *msgfmt,...) const
Issue system error message.
Definition TObject.cxx:1110
R__ALWAYS_INLINE Bool_t IsOnHeap() const
Definition TObject.h:160
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1082
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:161
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1124
void MakeZombie()
Definition TObject.h:55
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1070
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
static TObjArray * GetPIDs()
static: returns array of TProcessIDs
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
static TProcessID * GetPID()
static: returns pointer to current TProcessID
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition TROOT.cxx:3059
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:3067
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2916
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:137
void ToLower()
Change string to lower-case.
Definition TString.cxx:1190
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition TString.cxx:465
const char * Data() const
Definition TString.h:385
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:714
@ kIgnoreCase
Definition TString.h:284
void ToUpper()
Change string to upper case.
Definition TString.cxx:1203
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:633
Bool_t IsNull() const
Definition TString.h:423
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:2460
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2438
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:642
virtual void ReadBuffer(char *&buffer)
Read string from I/O buffer.
Definition TString.cxx:1338
virtual FILE * TempFileName(TString &base, const char *dir=nullptr, const char *suffix=nullptr)
Create a secure temporary file by appending a unique 6 letter string to base.
Definition TSystem.cxx:1514
virtual const char * GetMakeSharedLib() const
Return the command line use to make a shared library.
Definition TSystem.cxx:4039
virtual Int_t RedirectOutput(const char *name, const char *mode="a", RedirectHandle_t *h=nullptr)
Redirect standard output (stdout, stderr) to the specified file.
Definition TSystem.cxx:1730
virtual void IgnoreInterrupt(Bool_t ignore=kTRUE)
If ignore is true ignore the interrupt signal, else restore previous behaviour.
Definition TSystem.cxx:604
virtual int Symlink(const char *from, const char *to)
Create a symbolic link from file1 to file2.
Definition TSystem.cxx:1383
static void ResetErrno()
Static function resetting system error number.
Definition TSystem.cxx:286
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1289
static Int_t GetErrno()
Static function returning system error number.
Definition TSystem.cxx:278
virtual int Chmod(const char *file, UInt_t mode)
Set the file permission bits. Returns -1 in case or error, 0 otherwise.
Definition TSystem.cxx:1523
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition TSystem.cxx:859
virtual void * OpenDirectory(const char *name)
Open a directory.
Definition TSystem.cxx:850
virtual int GetPid()
Get process id.
Definition TSystem.cxx:720
virtual const char * GetIncludePath()
Get the list of include path.
Definition TSystem.cxx:4056
virtual void ShowOutput(RedirectHandle_t *h)
Display the content associated with the redirection described by the opaque handle 'h'.
Definition TSystem.cxx:1740
virtual Bool_t IsPathLocal(const char *path)
Returns TRUE if the url in 'path' points to the local file system.
Definition TSystem.cxx:1320
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Definition TSystem.cxx:920
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition TSystem.cxx:655
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1872
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition TSystem.cxx:1413
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition TSystem.cxx:1096
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1311
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition TSystem.cxx:867
virtual Bool_t ChangeDirectory(const char *path)
Change directory.
Definition TSystem.cxx:876
virtual int Rename(const char *from, const char *to)
Rename a file.
Definition TSystem.cxx:1365
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition TSystem.cxx:948
virtual const char * GetFlagsDebug() const
Return the debug flags.
Definition TSystem.cxx:4010
virtual Bool_t IsAbsoluteFileName(const char *dir)
Return true if dir is an absolute pathname.
Definition TSystem.cxx:965
virtual const char * GetObjExt() const
Get the object file extension.
Definition TSystem.cxx:4104
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition TSystem.cxx:439
virtual const char * WorkingDirectory()
Return working directory.
Definition TSystem.cxx:885
virtual const char * GetLibraries(const char *regexp="", const char *option="", Bool_t isRegexp=kTRUE)
Return a space separated list of loaded shared libraries.
Definition TSystem.cxx:2151
virtual const char * HomeDirectory(const char *userName=nullptr)
Return the user's home directory.
Definition TSystem.cxx:901
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:418
virtual const char * GetSoExt() const
Get the shared library extension.
Definition TSystem.cxx:4096
virtual TString GetDirName(const char *pathname)
Return the directory name in pathname.
Definition TSystem.cxx:1046
virtual int Unlink(const char *name)
Unlink, i.e.
Definition TSystem.cxx:1396
virtual const char * GetFlagsOpt() const
Return the optimization flags.
Definition TSystem.cxx:4018
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition TTimeStamp.h:45
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
Definition TUUID.h:42
void ReadBuffer(char *&buffer)
Stream UUID from input buffer.
Definition TUUID.cxx:322
void FillBuffer(char *&buffer)
Stream UUID into output buffer.
Definition TUUID.cxx:306
This class represents a WWW compatible URL.
Definition TUrl.h:33
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition TUrl.cxx:395
const char * GetFile() const
Definition TUrl.h:69
const char * GetValueFromOptions(const char *key) const
Return a value for a given key from the URL options.
Definition TUrl.cxx:662
const char * GetOptions() const
Definition TUrl.h:71
const char * GetProtocol() const
Definition TUrl.h:64
Bool_t HasOption(const char *key) const
Returns true if the given key appears in the URL options list.
Definition TUrl.cxx:685
virtual Bool_t SendFileReadProgress(TFile *)
virtual Bool_t SendFileCloseEvent(TFile *)
virtual Bool_t SendFileWriteProgress(TFile *)
Abstract Interface class describing Streamer information for one class.
const Int_t n
Definition legend1.C:16
TF1 * f1
Definition legend1.C:11
R__EXTERN TVirtualRWMutex * gCoreMutex
@ kFileThreadSlot
@ kSTLmap
Definition ESTLType.h:33
@ kSTLmultimap
Definition ESTLType.h:34
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
bool IsStdPair(std::string_view name)
Definition TClassEdit.h:231
ROOT::ESTLType IsSTLCont(std::string_view type)
type : type name: vector<list<classA,allocator>,allocator> result: 0 : not stl container code of cont...
int GetSplit(const char *type, std::vector< std::string > &output, int &nestedLoc, EModType mode=TClassEdit::kNone)
Stores in output (after emptying it) the split type.
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
static const char * what
Definition stlLoader.cc:5
@ kUndefined
Undefined compression algorithm (must be kept the last of the list in case a new algorithm is added).
@ kUseMin
Compression level reserved when we are not sure what to use (1 is for the fastest compression)
Definition Compression.h:72
Simple struct of the return value of GetStreamerInfoListImpl.
Definition TFile.h:223
th1 Draw()
TLine l
Definition textangle.C:4