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