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