Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TFile.cxx
Go to the documentation of this file.
1// @(#)root/io:$Id: 3a19890259ad6443ee313e090166614971ad4296 $
2// Author: Rene Brun 28/11/94
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/**
13\file TFile.cxx
14\class TFile
15\ingroup IO
16\brief A 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 gSystem->FreeDirectory(dir);
2814 }
2815 // Make sure that the relevant dirs exists: this is mandatory, so we fail if unsuccessful
2816 path.Form("%s/%s/PROOF-INF", pardir.Data(), parname.Data());
2817 if (gSystem->mkdir(path, kTRUE)) {
2818 Error("MakeProject", "problems creating '%s'", path.Data());
2819 return;
2820 }
2821 makepar = kTRUE;
2822
2823 } else {
2824 void *dir = gSystem->OpenDirectory(dirname);
2826
2827 if (opt.Contains("update")) {
2828 // check that directory exist, if not create it
2829 if (!dir) {
2831 }
2832
2833 } else if (opt.Contains("recreate")) {
2834 // check that directory exist, if not create it
2835 if (!dir) {
2836 if (gSystem->mkdir(dirname) < 0) {
2837 Error("MakeProject","cannot create directory '%s'",dirname);
2838 return;
2839 }
2840 }
2841 // clear directory
2842 while (dir) {
2843 const char *afile = gSystem->GetDirEntry(dir);
2844 if (!afile) break;
2845 if (strcmp(afile,".") == 0) continue;
2846 if (strcmp(afile,"..") == 0) continue;
2847 dirpath.Form("%s/%s",dirname,afile);
2849 }
2850
2851 } else {
2852 // new is assumed
2853 // if directory already exist, print error message and return
2854 if (dir) {
2855 Error("MakeProject","cannot create directory %s, already existing",dirname);
2856 gSystem->FreeDirectory(dir);
2857 return;
2858 }
2859 if (gSystem->mkdir(dirname) < 0) {
2860 Error("MakeProject","cannot create directory '%s'",dirname);
2861 return;
2862 }
2863 }
2864 if (dir) {
2865 gSystem->FreeDirectory(dir);
2866 }
2867 }
2868 Bool_t genreflex = opt.Contains("genreflex");
2869
2870 // we are now ready to generate the classes
2871 // loop on all TStreamerInfo
2872 TList *filelist = (TList*)GetStreamerInfoCache();
2873 if (filelist) filelist = (TList*)filelist->Clone();
2874 if (!filelist) {
2875 Error("MakeProject","file %s has no StreamerInfo", GetName());
2876 return;
2877 }
2878
2880 if (makepar) clean_dirname.Form("%s/%s", pardir.Data(), parname.Data());
2881 if (clean_dirname[clean_dirname.Length()-1]=='/') {
2882 clean_dirname.Remove(clean_dirname.Length()-1);
2883 } else if (clean_dirname[clean_dirname.Length()-1]=='\\') {
2884 clean_dirname.Remove(clean_dirname.Length()-1);
2885 if (clean_dirname[clean_dirname.Length()-1]=='\\') {
2886 clean_dirname.Remove(clean_dirname.Length()-1);
2887 }
2888 }
2890 if (makepar) subdirname = parname;
2891 if (subdirname == "") {
2892 Error("MakeProject","Directory name must not be empty.");
2893 return;
2894 }
2895
2896 // Start the source file
2897 TString spath; spath.Form("%s/%sProjectSource.cxx",clean_dirname.Data(),subdirname.Data());
2898 FILE *sfp = fopen(spath.Data(),"w");
2899 if (!sfp) {
2900 Error("MakeProject","Unable to create the source file %s.",spath.Data());
2901 return;
2902 }
2903 fprintf(sfp, "namespace std {}\nusing namespace std;\n");
2904 fprintf(sfp, "#include \"%sProjectHeaders.h\"\n\n",subdirname.Data() );
2905 if (!genreflex) fprintf(sfp, "#include \"%sLinkDef.h\"\n\n",subdirname.Data() );
2906 fprintf(sfp, "#include \"%sProjectDict.cxx\"\n\n",subdirname.Data() );
2907 fprintf(sfp, "struct DeleteObjectFunctor {\n");
2908 fprintf(sfp, " template <typename T>\n");
2909 fprintf(sfp, " void operator()(const T *ptr) const {\n");
2910 fprintf(sfp, " delete ptr;\n");
2911 fprintf(sfp, " }\n");
2912 fprintf(sfp, " template <typename T, typename Q>\n");
2913 fprintf(sfp, " void operator()(const std::pair<T,Q> &) const {\n");
2914 fprintf(sfp, " // Do nothing\n");
2915 fprintf(sfp, " }\n");
2916 fprintf(sfp, " template <typename T, typename Q>\n");
2917 fprintf(sfp, " void operator()(const std::pair<T,Q*> &ptr) const {\n");
2918 fprintf(sfp, " delete ptr.second;\n");
2919 fprintf(sfp, " }\n");
2920 fprintf(sfp, " template <typename T, typename Q>\n");
2921 fprintf(sfp, " void operator()(const std::pair<T*,Q> &ptr) const {\n");
2922 fprintf(sfp, " delete ptr.first;\n");
2923 fprintf(sfp, " }\n");
2924 fprintf(sfp, " template <typename T, typename Q>\n");
2925 fprintf(sfp, " void operator()(const std::pair<T*,Q*> &ptr) const {\n");
2926 fprintf(sfp, " delete ptr.first;\n");
2927 fprintf(sfp, " delete ptr.second;\n");
2928 fprintf(sfp, " }\n");
2929 fprintf(sfp, "};\n\n");
2930 fclose( sfp );
2931
2932 // loop on all TStreamerInfo classes to check for empty classes
2933 // and enums listed either as data member or template parameters,
2934 // and filter out 'duplicates' classes/streamerInfos.
2938 TList *list = new TList();
2939 while ((info = (TStreamerInfo*)flnext())) {
2940 if (info->IsA() != TStreamerInfo::Class()) {
2941 continue;
2942 }
2943 if (strstr(info->GetName(),"@@")) {
2944 // Skip schema evolution support streamerInfo
2945 continue;
2946 }
2947 TClass *cl = TClass::GetClass(info->GetName());
2948 if (cl) {
2949 if (cl->HasInterpreterInfo()) continue; // skip known classes
2950 }
2951 // Find and use the proper rules for the TStreamerInfos.
2953 TIter enext( info->GetElements() );
2956 if (cl && cl->GetSchemaRules()) {
2957 rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
2958 }
2959 while( (el=(TStreamerElement*)enext()) ) {
2960 for(auto rule : rules) {
2961 if( rule->IsRenameRule() || rule->IsAliasRule() )
2962 continue;
2963 // Check whether this is an 'attribute' rule.
2964 if ( rule->HasTarget( el->GetName()) && rule->GetAttributes()[0] != 0 ) {
2965 TString attr( rule->GetAttributes() );
2966 attr.ToLower();
2967 if (attr.Contains("owner")) {
2968 if (attr.Contains("notowner")) {
2970 } else {
2972 }
2973 }
2974 }
2975 }
2977 }
2978 TVirtualStreamerInfo *alternate = (TVirtualStreamerInfo*)list->FindObject(info->GetName());
2979 if (alternate) {
2980 if ((info->GetClass() && info->GetClassVersion() == info->GetClass()->GetClassVersion())
2981 || (info->GetClassVersion() > alternate->GetClassVersion()) ) {
2982 list->AddAfter(alternate, info);
2983 list->Remove(alternate);
2984 } // otherwise ignore this info as not being the official one.
2985 } else {
2986 list->Add(info);
2987 }
2988 }
2989 // Now transfer the new StreamerInfo onto the main list and
2990 // to the owning list.
2992 while ((info = (TStreamerInfo*)nextextra())) {
2993 list->Add(info);
2994 filelist->Add(info);
2995 }
2996
2997 // loop on all TStreamerInfo classes
2998 TIter next(list);
2999 Int_t ngener = 0;
3000 while ((info = (TStreamerInfo*)next())) {
3001 if (info->IsA() != TStreamerInfo::Class()) {
3002 continue;
3003 }
3004 if (info->GetClassVersion()==-4) continue; // Skip outer level namespace
3005 TIter subnext(list);
3008 Int_t len = strlen(info->GetName());
3009 while ((subinfo = (TStreamerInfo*)subnext())) {
3010 if (subinfo->IsA() != TStreamerInfo::Class()) {
3011 continue;
3012 }
3013 if (strncmp(info->GetName(),subinfo->GetName(),len)==0) {
3014 // The 'sub' StreamerInfo start with the main StreamerInfo name,
3015 // it subinfo is likely to be a nested class.
3016 const Int_t sublen = strlen(subinfo->GetName());
3017 if ( (sublen > len) && subinfo->GetName()[len+1]==':'
3018 && !subClasses.FindObject(subinfo->GetName()) /* We need to insure uniqueness */)
3019 {
3020 subClasses.Add(subinfo);
3021 }
3022 }
3023 }
3024 ngener += info->GenerateHeaderFile(clean_dirname.Data(),&subClasses,&extrainfos);
3025 subClasses.Clear("nodelete");
3026 }
3027 extrainfos.Clear("nodelete"); // We are done with this list.
3028
3029 TString path;
3030 path.Form("%s/%sProjectHeaders.h",clean_dirname.Data(),subdirname.Data());
3031 FILE *allfp = fopen(path,"a");
3032 if (!allfp) {
3033 Error("MakeProject","Cannot open output file:%s\n",path.Data());
3034 } else {
3035 fprintf(allfp,"#include \"%sProjectInstances.h\"\n", subdirname.Data());
3036 fclose(allfp);
3037 }
3038
3039 printf("MakeProject has generated %d classes in %s\n",ngener,clean_dirname.Data());
3040
3041 // generate the shared lib
3042 if (!opt.Contains("+") && !makepar) {
3043 delete list;
3044 filelist->Delete();
3045 delete filelist;
3046 return;
3047 }
3048
3049 // Makefiles files
3050 FILE *fpMAKE = nullptr;
3051 if (!makepar) {
3052 // Create the MAKEP file by looping on all *.h files
3053 // delete MAKEP if it already exists
3054#ifdef WIN32
3055 path.Form("%s/makep.cmd",clean_dirname.Data());
3056#else
3057 path.Form("%s/MAKEP",clean_dirname.Data());
3058#endif
3059#ifdef R__WINGCC
3060 fpMAKE = fopen(path,"wb");
3061#else
3062 fpMAKE = fopen(path,"w");
3063#endif
3064 if (!fpMAKE) {
3065 Error("MakeProject", "cannot open file %s", path.Data());
3066 delete list;
3067 filelist->Delete();
3068 delete filelist;
3069 return;
3070 }
3071 }
3072
3073 // Add rootcint/genreflex statement generating ProjectDict.cxx
3074 FILE *ifp = nullptr;
3075 path.Form("%s/%sProjectInstances.h",clean_dirname.Data(),subdirname.Data());
3076#ifdef R__WINGCC
3077 ifp = fopen(path,"wb");
3078#else
3079 ifp = fopen(path,"w");
3080#endif
3081 if (!ifp) {
3082 Error("MakeProject", "cannot open path file %s", path.Data());
3083 delete list;
3084 filelist->Delete();
3085 delete filelist;
3086 fclose(fpMAKE);
3087 return;
3088 }
3089
3090 if (!makepar) {
3091 if (genreflex) {
3092 fprintf(fpMAKE,"genreflex %sProjectHeaders.h -o %sProjectDict.cxx --comments --iocomments %s ",subdirname.Data(),subdirname.Data(),gSystem->GetIncludePath());
3093 path.Form("%s/%sSelection.xml",clean_dirname.Data(),subdirname.Data());
3094 } else {
3095 fprintf(fpMAKE,"rootcint -v1 -f %sProjectDict.cxx %s ", subdirname.Data(), gSystem->GetIncludePath());
3096 path.Form("%s/%sLinkDef.h",clean_dirname.Data(),subdirname.Data());
3097 }
3098 } else {
3099 path.Form("%s/%sLinkDef.h",clean_dirname.Data(),subdirname.Data());
3100 }
3101
3102 // Create the LinkDef.h or xml selection file by looping on all *.h files
3103 // replace any existing file.
3104#ifdef R__WINGCC
3105 FILE *fp = fopen(path,"wb");
3106#else
3107 FILE *fp = fopen(path,"w");
3108#endif
3109 if (!fp) {
3110 Error("MakeProject", "cannot open path file %s", path.Data());
3111 delete list;
3112 filelist->Delete();
3113 delete filelist;
3114 fclose(fpMAKE);
3115 fclose(ifp);
3116 return;
3117 }
3118 if (genreflex) {
3119 fprintf(fp,"<lcgdict>\n");
3120 fprintf(fp,"\n");
3121 } else {
3122 fprintf(fp,"#ifdef __CINT__\n");
3123 fprintf(fp,"\n");
3124 }
3125
3126 TString tmp;
3129 next.Reset();
3130 while ((info = (TStreamerInfo*)next())) {
3131 if (info->IsA() != TStreamerInfo::Class()) {
3132 continue;
3133 }
3134 if (strncmp(info->GetName(), "auto_ptr<", std::char_traits<char>::length("auto_ptr<")) == 0) {
3135 continue;
3136 }
3137 TClass *cl = TClass::GetClass(info->GetName());
3138 if (cl) {
3139 if (cl->HasInterpreterInfo()) continue; // skip known classes
3140 if (cl->GetSchemaRules()) {
3141 auto rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
3143 for(auto rule : rules) {
3144 strrule.Clear();
3145 if (genreflex) {
3146 rule->AsString(strrule,"x");
3147 strrule.Append("\n");
3148 if ( selections.Index(strrule) == kNPOS ) {
3149 selections.Append(strrule);
3150 }
3151 } else {
3152 rule->AsString(strrule);
3153 if (strncmp(strrule.Data(),"type=",5)==0) {
3154 strrule.Remove(0,5);
3155 }
3156 fprintf(fp,"#pragma %s;\n",strrule.Data());
3157 }
3158 }
3159 }
3160
3161 }
3162 if ((info->GetClass() && info->GetClass()->GetCollectionType()) || TClassEdit::IsSTLCont(info->GetName())) {
3163 std::vector<std::string> inside;
3164 int nestedLoc;
3166 Int_t stlkind = TClassEdit::STLKind(inside[0]);
3167 TClass *key = TClass::GetClass(inside[1].c_str());
3168 if (key) {
3169 TString what;
3170 switch ( stlkind ) {
3171 case ROOT::kSTLmap:
3172 case ROOT::kSTLmultimap:
3173 if (TClass::GetClass(inside[1].c_str())) {
3174 what = "std::pair<";
3175 what += TMakeProject::UpdateAssociativeToVector( inside[1].c_str() );
3176 what += ",";
3177 what += TMakeProject::UpdateAssociativeToVector( inside[2].c_str() );
3178 if (what[what.Length()-1]=='>') {
3179 what += " >";
3180 } else {
3181 what += ">";
3182 }
3183 if (genreflex) {
3184 tmp.Form("<class name=\"%s\" />\n",what.Data());
3185 if ( selections.Index(tmp) == kNPOS ) {
3186 selections.Append(tmp);
3187 }
3188 tmp.Form("template class %s;\n",what.Data());
3189 if ( instances.Index(tmp) == kNPOS ) {
3190 instances.Append(tmp);
3191 }
3192 } else {
3193 what.ReplaceAll("std::","");
3195 if (!paircl || !paircl->HasInterpreterInfo()) {
3196 fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
3197 }
3198 }
3199 break;
3200 }
3201 default:
3202 if (TClassEdit::IsStdPair(key->GetName())) {
3203 if (genreflex) {
3204 tmp.Form("<class name=\"%s\" />\n",key->GetName());
3205 if ( selections.Index(tmp) == kNPOS ) {
3206 selections.Append(tmp);
3207 }
3208 tmp.Form("template class %s;\n",key->GetName());
3209 if ( instances.Index(tmp) == kNPOS ) {
3210 instances.Append(tmp);
3211 }
3212 } else {
3213 what.ReplaceAll("std::","");
3214 fprintf(fp,"#pragma link C++ class %s+;\n",key->GetName());
3215 }
3216 }
3217 break;
3218 }
3219 }
3220 continue;
3221 }
3222 {
3224 if (genreflex) {
3225 tmp.Form("<class name=\"%s\" />\n",what.Data());
3226 if ( selections.Index(tmp) == kNPOS ) {
3227 selections.Append(tmp);
3228 }
3229 if (what[what.Length()-1] == '>') {
3230 tmp.Form("template class %s;\n",what.Data());
3231 if ( instances.Index(tmp) == kNPOS ) {
3232 instances.Append(tmp);
3233 }
3234 }
3235 } else {
3236 what.ReplaceAll("std::","");
3237 fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
3238 }
3239 }
3240 if (genreflex) {
3241 // Also request the dictionary for the STL container used as members ...
3242 TIter eliter( info->GetElements() );
3244 while( (element = (TStreamerElement*)eliter() ) ) {
3245 if (element->GetClass() && !element->GetClass()->IsLoaded() && element->GetClass()->GetCollectionProxy()) {
3247 tmp.Form("<class name=\"%s\" />\n",what.Data());
3248 if ( selections.Index(tmp) == kNPOS ) {
3249 selections.Append(tmp);
3250 }
3251 tmp.Form("template class %s;\n",what.Data());
3252 if ( instances.Index(tmp) == kNPOS ) {
3253 instances.Append(tmp);
3254 }
3255 }
3256 }
3257 }
3258 }
3259 if (genreflex) {
3260 fprintf(ifp,"#ifndef PROJECT_INSTANCES_H\n");
3261 fprintf(ifp,"#define PROJECT_INSTANCES_H\n");
3262 fprintf(ifp,"%s",instances.Data());
3263 fprintf(ifp,"#endif\n");
3264 fprintf(fp,"%s",selections.Data());
3265 fprintf(fp,"</lcgdict>\n");
3266 } else {
3267 fprintf(fp,"#endif\n");
3268 }
3269 fclose(fp);
3270 fclose(ifp);
3271
3272 if (!makepar) {
3273 // add compilation line
3275
3277 TString sources = TString::Format("%sProjectSource.cxx ", sdirname.Data());
3278 cmd.ReplaceAll("$SourceFiles",sources.Data());
3279 TString object = TString::Format("%sProjectSource.", sdirname.Data());
3280 object.Append( gSystem->GetObjExt() );
3281 cmd.ReplaceAll("$ObjectFiles", object.Data());
3282 cmd.ReplaceAll("$IncludePath",TString(gSystem->GetIncludePath()) + " -I" + clean_dirname.Data());
3283 cmd.ReplaceAll("$SharedLib",sdirname+"."+gSystem->GetSoExt());
3284 cmd.ReplaceAll("$LinkedLibs",gSystem->GetLibraries("","SDL"));
3285 cmd.ReplaceAll("$LibName",sdirname);
3286 cmd.ReplaceAll("$BuildDir",".");
3287 TString sOpt;
3289 if (rootbuild.Index("debug",0,TString::kIgnoreCase)==kNPOS) {
3291 } else {
3293 }
3294 cmd.ReplaceAll("$Opt", sOpt);
3295
3296 if (genreflex) {
3297 fprintf(fpMAKE,"-s %sSelection.xml \n",subdirname.Data());
3298 } else {
3299 fprintf(fpMAKE,"%sProjectHeaders.h ",subdirname.Data());
3300 fprintf(fpMAKE,"%sLinkDef.h \n",subdirname.Data());
3301 }
3302
3303 fprintf(fpMAKE,"%s\n",cmd.Data());
3304
3305 printf("%s/MAKEP file has been generated\n", clean_dirname.Data());
3306
3307 fclose(fpMAKE);
3308
3309 } else {
3310
3311 // Create the Makefile
3312 TString filemake = TString::Format("%s/Makefile", clean_dirname.Data());
3313 if (MakeProjectParMake(parname, filemake.Data()) != 0) {
3314 Error("MakeProject", "problems creating PAR make file '%s'", filemake.Data());
3315 delete list;
3316 filelist->Delete();
3317 delete filelist;
3318 return;
3319 }
3320 // Get Makefile.arch
3321 TString mkarchsrc = TString::Format("%s/Makefile.arch", TROOT::GetEtcDir().Data());
3323 Warning("MakeProject", "problems expanding '%s'", mkarchsrc.Data());
3324 TString mkarchdst = TString::Format("%s/Makefile.arch", clean_dirname.Data());
3325 if (gSystem->CopyFile(mkarchsrc.Data(), mkarchdst.Data(), kTRUE) != 0) {
3326 Error("MakeProject", "problems retrieving '%s' to '%s'", mkarchsrc.Data(), mkarchdst.Data());
3327 delete list;
3328 filelist->Delete();
3329 delete filelist;
3330 return;
3331 }
3332 // Create the Makefile
3333 TString proofinf = TString::Format("%s/PROOF-INF", clean_dirname.Data());
3334 if (MakeProjectParProofInf(parname, proofinf.Data()) != 0) {
3335 Error("MakeProject", "problems creating BUILD.sh and/or SETUP.C under '%s'", proofinf.Data());
3336 delete list;
3337 filelist->Delete();
3338 delete filelist;
3339 return;
3340 }
3341
3342 // Make sure BUILD.sh is executable and create SETUP.C
3343 TString cmod = TString::Format("chmod +x %s/PROOF-INF/BUILD.sh", clean_dirname.Data());
3344#ifndef WIN32
3345 gSystem->Exec(cmod.Data());
3346#else
3347 // not really needed for Windows but it would work both both Unix and NT
3348 chmod(cmod.Data(), 00700);
3349#endif
3350 Printf("Files Makefile, Makefile.arch, PROOF-INF/BUILD.sh and"
3351 " PROOF-INF/SETUP.C have been generated under '%s'", clean_dirname.Data());
3352
3353 // Generate the PAR file, if not Windows
3354#ifndef WIN32
3357 TString cmd = TString::Format("tar czvf %s.par %s", parname.Data(), parname.Data());
3358 gSystem->Exec(cmd.Data());
3360 Info("MakeProject", "PAR file %s.par generated", clean_dirname.Data());
3361 } else {
3362 Warning("MakeProject", "problems changing directory back to '%s'", curdir.Data());
3363 }
3364 } else {
3365 Error("MakeProject", "problems changing directory to '%s' - skipping PAR file generation", pardir.Data());
3366 }
3367#else
3368 Warning("MakeProject", "on Windows systems the PAR file cannot be generated out of the package directory!");
3369#endif
3370 }
3371
3372
3373 if (!makepar && !opt.Contains("nocompilation")) {
3374 // now execute the generated script compiling and generating the shared lib
3375 path = gSystem->WorkingDirectory();
3377#ifndef WIN32
3378 gSystem->Exec("chmod +x MAKEP");
3379 int res = !gSystem->Exec("./MAKEP");
3380#else
3381 // not really needed for Windows but it would work both both Unix and NT
3382 chmod("makep.cmd",00700);
3383 int res = !gSystem->Exec("MAKEP");
3384#endif
3385 gSystem->ChangeDirectory(path);
3386 path.Form("%s/%s.%s",clean_dirname.Data(),subdirname.Data(),gSystem->GetSoExt());
3387 if (res) printf("Shared lib %s has been generated\n",path.Data());
3388
3389 //dynamically link the generated shared lib
3390 if (opt.Contains("++")) {
3391 res = !gSystem->Load(path);
3392 if (res) printf("Shared lib %s has been dynamically linked\n",path.Data());
3393 }
3394 }
3395
3396 delete list;
3397 filelist->Delete();
3398 delete filelist;
3399}
3400
3401////////////////////////////////////////////////////////////////////////////////
3402/// Create makefile at 'filemake' for PAR package 'pack'.
3403///
3404/// Called by MakeProject when option 'par' is given.
3405/// Return 0 on success, -1 on error.
3407Int_t TFile::MakeProjectParMake(const char *pack, const char *filemake)
3408{
3409 // Output file path must be defined
3410 if (!filemake || (filemake && strlen(filemake) <= 0)) {
3411 Error("MakeProjectParMake", "path for output file undefined!");
3412 return -1;
3413 }
3414
3415 // Package name must be defined
3416 if (!pack || (pack && strlen(pack) <= 0)) {
3417 Error("MakeProjectParMake", "package name undefined!");
3418 return -1;
3419 }
3420
3421#ifdef R__WINGCC
3422 FILE *fmk = fopen(filemake, "wb");
3423#else
3424 FILE *fmk = fopen(filemake, "w");
3425#endif
3426 if (!fmk) {
3427 Error("MakeProjectParMake", "cannot create file '%s' (errno: %d)", filemake, TSystem::GetErrno());
3428 return -1;
3429 }
3430
3431 // Fill the file now
3432 fprintf(fmk, "# Makefile for the ROOT test programs.\n");
3433 fprintf(fmk, "# This Makefile shows how to compile and link applications\n");
3434 fprintf(fmk, "# using the ROOT libraries on all supported platforms.\n");
3435 fprintf(fmk, "#\n");
3436 fprintf(fmk, "# Copyright (c) 2000 Rene Brun and Fons Rademakers\n");
3437 fprintf(fmk, "#\n");
3438 fprintf(fmk, "# Author: this makefile has been automatically generated via TFile::MakeProject\n");
3439 fprintf(fmk, "\n");
3440 fprintf(fmk, "include Makefile.arch\n");
3441 fprintf(fmk, "\n");
3442 fprintf(fmk, "#------------------------------------------------------------------------------\n");
3443 fprintf(fmk, "\n");
3444 fprintf(fmk, "PACKO = %sProjectSource.$(ObjSuf)\n", pack);
3445 fprintf(fmk, "PACKS = %sProjectSource.$(SrcSuf) %sProjectDict.$(SrcSuf)\n", pack, pack);
3446 fprintf(fmk, "PACKSO = lib%s.$(DllSuf)\n", pack);
3447 fprintf(fmk, "\n");
3448 fprintf(fmk, "ifeq ($(PLATFORM),win32)\n");
3449 fprintf(fmk, "PACKLIB = lib%s.lib\n", pack);
3450 fprintf(fmk, "else\n");
3451 fprintf(fmk, "PACKLIB = $(PACKSO)\n");
3452 fprintf(fmk, "endif\n");
3453 fprintf(fmk, "\n");
3454 fprintf(fmk, "OBJS = $(PACKO)\n");
3455 fprintf(fmk, "\n");
3456 fprintf(fmk, "PROGRAMS =\n");
3457 fprintf(fmk, "\n");
3458 fprintf(fmk, "#------------------------------------------------------------------------------\n");
3459 fprintf(fmk, "\n");
3460 fprintf(fmk, ".SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(DllSuf)\n");
3461 fprintf(fmk, "\n");
3462 fprintf(fmk, "all: $(PACKLIB)\n");
3463 fprintf(fmk, "\n");
3464 fprintf(fmk, "$(PACKSO): $(PACKO)\n");
3465 fprintf(fmk, "ifeq ($(ARCH),aix)\n");
3466 fprintf(fmk, "\t\t/usr/ibmcxx/bin/makeC++SharedLib $(OutPutOpt) $@ $(LIBS) -p 0 $^\n");
3467 fprintf(fmk, "else\n");
3468 fprintf(fmk, "ifeq ($(ARCH),aix5)\n");
3469 fprintf(fmk, "\t\t/usr/vacpp/bin/makeC++SharedLib $(OutPutOpt) $@ $(LIBS) -p 0 $^\n");
3470 fprintf(fmk, "else\n");
3471 fprintf(fmk, "ifeq ($(PLATFORM),macosx)\n");
3472 fprintf(fmk, "# We need to make both the .dylib and the .so\n");
3473 fprintf(fmk, "\t\t$(LD) $(SOFLAGS)$@ $(LDFLAGS) $^ $(OutPutOpt) $@ $(LIBS)\n");
3474 fprintf(fmk, "ifneq ($(subst $(MACOSX_MINOR),,1234),1234)\n");
3475 fprintf(fmk, "ifeq ($(MACOSX_MINOR),4)\n");
3476 fprintf(fmk, "\t\tln -sf $@ $(subst .$(DllSuf),.so,$@)\n");
3477 fprintf(fmk, "else\n");
3478 fprintf(fmk, "\t\t$(LD) -bundle -undefined $(UNDEFOPT) $(LDFLAGS) $^ \\\n");
3479 fprintf(fmk, "\t\t $(OutPutOpt) $(subst .$(DllSuf),.so,$@)\n");
3480 fprintf(fmk, "endif\n");
3481 fprintf(fmk, "endif\n");
3482 fprintf(fmk, "else\n");
3483 fprintf(fmk, "ifeq ($(PLATFORM),win32)\n");
3484 fprintf(fmk, "\t\tbindexplib $* $^ > $*.def\n");
3485 fprintf(fmk, "\t\tlib -nologo -MACHINE:IX86 $^ -def:$*.def \\\n");
3486 fprintf(fmk, "\t\t $(OutPutOpt)$(PACKLIB)\n");
3487 fprintf(fmk, "\t\t$(LD) $(SOFLAGS) $(LDFLAGS) $^ $*.exp $(LIBS) \\\n");
3488 fprintf(fmk, "\t\t $(OutPutOpt)$@\n");
3489 fprintf(fmk, "else\n");
3490 fprintf(fmk, "\t\t$(LD) $(SOFLAGS) $(LDFLAGS) $^ $(OutPutOpt) $@ $(LIBS) $(EXPLLINKLIBS)\n");
3491 fprintf(fmk, "endif\n");
3492 fprintf(fmk, "endif\n");
3493 fprintf(fmk, "endif\n");
3494 fprintf(fmk, "endif\n");
3495 fprintf(fmk, "\t\t@echo \"$@ done\"\n");
3496 fprintf(fmk, "\n");
3497 fprintf(fmk, "clean:\n");
3498 fprintf(fmk, "\t\t@rm -f $(OBJS) core\n");
3499 fprintf(fmk, "\n");
3500 fprintf(fmk, "distclean: clean\n");
3501 fprintf(fmk, "\t\t@rm -f $(PROGRAMS) $(PACKSO) $(PACKLIB) *Dict.* *.def *.exp \\\n");
3502 fprintf(fmk, "\t\t *.so *.lib *.dll *.d *.log .def so_locations\n");
3503 fprintf(fmk, "\t\t@rm -rf cxx_repository\n");
3504 fprintf(fmk, "\n");
3505 fprintf(fmk, "# Dependencies\n");
3506 fprintf(fmk, "\n");
3507 fprintf(fmk, "%sProjectSource.$(ObjSuf): %sProjectHeaders.h %sLinkDef.h %sProjectDict.$(SrcSuf)\n", pack, pack, pack, pack);
3508 fprintf(fmk, "\n");
3509 fprintf(fmk, "%sProjectDict.$(SrcSuf): %sProjectHeaders.h %sLinkDef.h\n", pack, pack, pack);
3510 fprintf(fmk, "\t\t@echo \"Generating dictionary $@...\"\n");
3511 fprintf(fmk, "\t\t@rootcint -f $@ $^\n");
3512 fprintf(fmk, "\n");
3513 fprintf(fmk, ".$(SrcSuf).$(ObjSuf):\n");
3514 fprintf(fmk, "\t\t$(CXX) $(CXXFLAGS) -c $<\n");
3515 fprintf(fmk, "\n");
3516
3517 // Close the file
3518 fclose(fmk);
3519
3520 // Done
3521 return 0;
3522}
3523
3524////////////////////////////////////////////////////////////////////////////////
3525/// Create BUILD.sh and SETUP.C under 'proofinf' for PAR package 'pack'.
3526/// Called by MakeProject when option 'par' is given.
3527/// Return 0 on success, -1 on error.
3529Int_t TFile::MakeProjectParProofInf(const char *pack, const char *proofinf)
3530{
3531 // Output directory path must be defined ...
3532 if (!proofinf || (proofinf && strlen(proofinf) <= 0)) {
3533 Error("MakeProjectParProofInf", "directory path undefined!");
3534 return -1;
3535 }
3536
3537 // ... and exist and be a directory
3538 Int_t rcst = 0;
3539 FileStat_t st;
3540 if ((rcst = gSystem->GetPathInfo(proofinf, st)) != 0 || !R_ISDIR(st.fMode)) {
3541 Error("MakeProjectParProofInf", "path '%s' %s", proofinf,
3542 ((rcst == 0) ? "is not a directory" : "does not exist"));
3543 return -1;
3544 }
3545
3546 // Package name must be defined
3547 if (!pack || (pack && strlen(pack) <= 0)) {
3548 Error("MakeProjectParProofInf", "package name undefined!");
3549 return -1;
3550 }
3551
3552 TString path;
3553
3554 // The BUILD.sh first
3555 path.Form("%s/BUILD.sh", proofinf);
3556#ifdef R__WINGCC
3557 FILE *f = fopen(path.Data(), "wb");
3558#else
3559 FILE *f = fopen(path.Data(), "w");
3560#endif
3561 if (!f) {
3562 Error("MakeProjectParProofInf", "cannot create file '%s' (errno: %d)",
3563 path.Data(), TSystem::GetErrno());
3564 return -1;
3565 }
3566
3567 fprintf(f, "#! /bin/sh\n");
3568 fprintf(f, "# Build libEvent library.\n");
3569 fprintf(f, "\n");
3570 fprintf(f, "#\n");
3571 fprintf(f, "# The environment variables ROOTPROOFLITE and ROOTPROOFCLIENT can be used to\n");
3572 fprintf(f, "# adapt the script to the calling environment\n");
3573 fprintf(f, "#\n");
3574 fprintf(f, "# if test ! \"x$ROOTPROOFLITE\" = \"x\"; then\n");
3575 fprintf(f, "# echo \"event-BUILD: PROOF-Lite node (session has $ROOTPROOFLITE workers)\"\n");
3576 fprintf(f, "# elif test ! \"x$ROOTPROOFCLIENT\" = \"x\"; then\n");
3577 fprintf(f, "# echo \"event-BUILD: PROOF client\"\n");
3578 fprintf(f, "# else\n");
3579 fprintf(f, "# echo \"event-BUILD: standard PROOF node\"\n");
3580 fprintf(f, "# fi\n");
3581 fprintf(f, "\n");
3582 fprintf(f, "if [ \"\" = \"clean\" ]; then\n");
3583 fprintf(f, " make distclean\n");
3584 fprintf(f, " exit 0\n");
3585 fprintf(f, "fi\n");
3586 fprintf(f, "\n");
3587 fprintf(f, "make\n");
3588 fprintf(f, "rc=$?\n");
3589 fprintf(f, "echo \"rc=$?\"\n");
3590 fprintf(f, "if [ $? != \"0\" ] ; then\n");
3591 fprintf(f, " exit 1\n");
3592 fprintf(f, "fi\n");
3593 fprintf(f, "exit 0\n");
3594
3595 // Close the file
3596 fclose(f);
3597
3598 // Then SETUP.C
3599 path.Form("%s/SETUP.C", proofinf);
3600#ifdef R__WINGCC
3601 f = fopen(path.Data(), "wb");
3602#else
3603 f = fopen(path.Data(), "w");
3604#endif
3605 if (!f) {
3606 Error("MakeProjectParProofInf", "cannot create file '%s' (errno: %d)",
3607 path.Data(), TSystem::GetErrno());
3608 return -1;
3609 }
3610
3611 fprintf(f, "Int_t SETUP()\n");
3612 fprintf(f, "{\n");
3613 fprintf(f, "\n");
3614 fprintf(f, "//\n");
3615 fprintf(f, "// The environment variables ROOTPROOFLITE and ROOTPROOFCLIENT can be used to\n");
3616 fprintf(f, "// adapt the macro to the calling environment\n");
3617 fprintf(f, "//\n");
3618 fprintf(f, "// if (gSystem->Getenv(\"ROOTPROOFLITE\")) {\n");
3619 fprintf(f, "// Printf(\"event-SETUP: PROOF-Lite node (session has %%s workers)\",\n");
3620 fprintf(f, "// gSystem->Getenv(\"ROOTPROOFLITE\"));\n");
3621 fprintf(f, "// } else if (gSystem->Getenv(\"ROOTPROOFCLIENT\")) {\n");
3622 fprintf(f, "// Printf(\"event-SETUP: PROOF client\");\n");
3623 fprintf(f, "// } else {\n");
3624 fprintf(f, "// Printf(\"event-SETUP: standard PROOF node\");\n");
3625 fprintf(f, "// }\n");
3626 fprintf(f, "\n");
3627 fprintf(f, " if (gSystem->Load(\"lib%s\") == -1)\n", pack);
3628 fprintf(f, " return -1;\n");
3629 fprintf(f, " return 0;\n");
3630 fprintf(f, "}\n");
3631 fprintf(f, "\n");
3632
3633 // Close the file
3634 fclose(f);
3635
3636 // Done
3637 return 0;
3638}
3639
3640////////////////////////////////////////////////////////////////////////////////
3641/// Read the list of StreamerInfo from this file.
3642///
3643/// The key with name holding the list of TStreamerInfo objects is read.
3644/// The corresponding TClass objects are updated.
3645/// Note that this function is not called if the static member fgReadInfo is false.
3646/// (see TFile::SetReadStreamerInfo)
3649{
3650 auto listRetcode = GetStreamerInfoListImpl(/*lookupSICache*/ true); // NOLINT: silence clang-tidy warnings
3651 TList *list = listRetcode.fList;
3652 auto retcode = listRetcode.fReturnCode;
3653 if (!list) {
3654 if (retcode) MakeZombie();
3655 return;
3656 }
3657
3658 list->SetOwner(kFALSE);
3659
3660 if (gDebug > 0) Info("ReadStreamerInfo", "called for file %s",GetName());
3661
3663
3664 Int_t version = fVersion;
3665 if (version > 1000000) version -= 1000000;
3666 if (version < 53419 || (59900 < version && version < 59907)) {
3667 // We need to update the fCheckSum field of the TStreamerBase.
3668
3669 // loop on all TStreamerInfo classes
3670 TObjLink *lnk = list->FirstLink();
3671 while (lnk) {
3672 info = (TStreamerInfo*)lnk->GetObject();
3673 if (!info || info->IsA() != TStreamerInfo::Class()) {
3674 lnk = lnk->Next();
3675 continue;
3676 }
3677 TIter next(info->GetElements());
3679 while ((element = (TStreamerElement*) next())) {
3680 TStreamerBase *base = dynamic_cast<TStreamerBase*>(element);
3681 if (!base) continue;
3682 if (base->GetBaseCheckSum() != 0) continue;
3683 TStreamerInfo *baseinfo = (TStreamerInfo*)list->FindObject(base->GetName());
3684 if (baseinfo) {
3685 base->SetBaseCheckSum(baseinfo->GetCheckSum());
3686 }
3687 }
3688 lnk = lnk->Next();
3689 }
3690 }
3691
3692 std::vector<Int_t> si_uids;
3693 // loop on all TStreamerInfo classes
3694 for (int mode=0;mode<2; ++mode) {
3695 // In order for the collection proxy to be initialized properly, we need
3696 // to setup the TStreamerInfo for non-stl class before the stl classes.
3697 TObjLink *lnk = list->FirstLink();
3698 while (lnk) {
3699 info = (TStreamerInfo*)lnk->GetObject();
3700 if (!info) {
3701 lnk = lnk->Next();
3702 continue;
3703 }
3704 if (info->IsA() != TStreamerInfo::Class()) {
3705 if (mode==1) {
3706 TObject *obj = (TObject*)info;
3707 if (strcmp(obj->GetName(),"listOfRules")==0) {
3708#if 0
3709 // Completely ignore the rules for now.
3710 TList *listOfRules = (TList*)obj;
3711 TObjLink *rulelnk = listOfRules->FirstLink();
3712 while (rulelnk) {
3713 TObjString *rule = (TObjString*)rulelnk->GetObject();
3714 TClass::AddRule( rule->String().Data() );
3715 rulelnk = rulelnk->Next();
3716 }
3717#endif
3718 } else {
3719 Warning("ReadStreamerInfo","%s has a %s in the list of TStreamerInfo.", GetName(), info->IsA()->GetName());
3720 }
3721 info->SetBit(kCanDelete);
3722 }
3723 lnk = lnk->Next();
3724 continue;
3725 }
3726 // This is a quick way (instead of parsing the name) to see if this is
3727 // the description of an STL container.
3728 if (info->GetElements()==0) {
3729 Warning("ReadStreamerInfo","The StreamerInfo for %s does not have a list of elements.",info->GetName());
3730 lnk = lnk->Next();
3731 continue;
3732 }
3733 TObject *element = info->GetElements()->UncheckedAt(0);
3734 Bool_t isstl = element && strcmp("This",element->GetName())==0;
3735
3736 if ( (!isstl && mode ==0) || (isstl && mode ==1) ) {
3737 // Skip the STL container the first time around
3738 // Skip the regular classes the second time around;
3739 info->BuildCheck(this);
3740 Int_t uid = info->GetNumber();
3741 Int_t asize = fClassIndex->GetSize();
3742 if (uid >= asize && uid <100000) fClassIndex->Set(2*asize);
3743 if (uid >= 0 && uid < fClassIndex->GetSize()) {
3744 si_uids.push_back(uid);
3745 fClassIndex->fArray[uid] = 1;
3746 }
3747 else if (!isstl && !info->GetClass()->IsSyntheticPair()) {
3748 printf("ReadStreamerInfo, class:%s, illegal uid=%d\n",info->GetName(),uid);
3749 }
3750 if (gDebug > 0) printf(" -class: %s version: %d info read at slot %d\n",info->GetName(), info->GetClassVersion(),uid);
3751 }
3752 lnk = lnk->Next();
3753 }
3754 }
3755 fClassIndex->fArray[0] = 0;
3756 list->Clear(); //this will delete all TStreamerInfo objects with kCanDelete bit set
3757 delete list;
3758
3759 // We are done processing the record, let future calls and other threads that it
3760 // has been done.
3761 fgTsSIHashes.Insert(listRetcode.fHash, std::move(si_uids));
3762}
3763
3764////////////////////////////////////////////////////////////////////////////////
3765/// Specify if the streamerinfos must be read at file opening.
3766///
3767/// If fgReadInfo is true (default) TFile::ReadStreamerInfo is called
3768/// when opening the file.
3769/// It may be interesting to set fgReadInfo to false to speedup the file
3770/// opening time or in case libraries containing classes referenced
3771/// by the file have not yet been loaded.
3772/// if fgReadInfo is false, one can still read the StreamerInfo with
3773/// myfile.ReadStreamerInfo();
3776{
3777 fgReadInfo = readinfo;
3778}
3779
3780////////////////////////////////////////////////////////////////////////////////
3781/// If the streamerinfos are to be read at file opening.
3782///
3783/// See TFile::SetReadStreamerInfo for more documentation.
3786{
3787 return fgReadInfo;
3788}
3789
3790////////////////////////////////////////////////////////////////////////////////
3791/// Show the StreamerInfo of all classes written to this file.
3794{
3795 TList *list = GetStreamerInfoList();
3796 if (!list) return;
3797
3798 list->ls();
3799 delete list;
3800}
3801
3802////////////////////////////////////////////////////////////////////////////////
3803/// Check if the ProcessID pidd is already in the file,
3804/// if not, add it and return the index number in the local file list.
3807{
3808 TProcessID *pid = pidd;
3809 if (!pid) pid = TProcessID::GetPID();
3810 TObjArray *pids = GetListOfProcessIDs();
3811 Int_t npids = GetNProcessIDs();
3812 for (Int_t i=0;i<npids;i++) {
3813 if (pids->At(i) == pid) return (UShort_t)i;
3814 }
3815
3816 this->SetBit(TFile::kHasReferences);
3817 pids->AddAtAndExpand(pid,npids);
3818 pid->IncrementCount();
3819 char name[32];
3820 snprintf(name,32,"ProcessID%d",npids);
3821 this->WriteTObject(pid,name);
3822 this->IncrementProcessIDs();
3823 if (gDebug > 0) {
3824 Info("WriteProcessID", "name=%s, file=%s", name, GetName());
3825 }
3826 return (UShort_t)npids;
3827}
3828
3829
3830////////////////////////////////////////////////////////////////////////////////
3831/// Write the list of TStreamerInfo as a single object in this file
3832/// The class Streamer description for all classes written to this file
3833/// is saved. See class TStreamerInfo.
3836{
3837 //if (!gFile) return;
3838 if (!fWritable) return;
3839 if (!fClassIndex) return;
3840 if (fIsPcmFile) return; // No schema evolution for ROOT PCM files.
3841 if (fClassIndex->fArray[0] == 0
3842 && fSeekInfo != 0) {
3843 // No need to update the index if no new classes added to the file
3844 // but write once an empty StreamerInfo list to mark that there is no need
3845 // for StreamerInfos in this file.
3846 return;
3847 }
3848 if (gDebug > 0) Info("WriteStreamerInfo", "called for file %s",GetName());
3849
3850 SafeDelete(fInfoCache);
3851
3852 // build a temporary list with the marked files
3853 TIter next(gROOT->GetListOfStreamerInfo());
3855 TList list;
3857 listOfRules.SetOwner(kTRUE);
3858 listOfRules.SetName("listOfRules");
3859 std::set<TClass*> classSet;
3860
3861 while ((info = (TStreamerInfo*)next())) {
3862 Int_t uid = info->GetNumber();
3863 if (fClassIndex->fArray[uid]) {
3864 list.Add(info);
3865 if (gDebug > 0) printf(" -class: %s info number %d saved\n",info->GetName(),uid);
3866
3867 // Add the IO customization rules to the list to be saved for the underlying
3868 // class but make sure to add them only once.
3869 TClass *clinfo = info->GetClass();
3870 if (clinfo && clinfo->GetSchemaRules()) {
3871 if ( classSet.find( clinfo ) == classSet.end() ) {
3872 if (gDebug > 0) printf(" -class: %s stored the I/O customization rules\n",info->GetName());
3873
3874 TObjArrayIter it( clinfo->GetSchemaRules()->GetRules() );
3876 while( (rule = (ROOT::TSchemaRule*)it.Next()) ) {
3877 TObjString *obj = new TObjString();
3878 rule->AsString(obj->String());
3879 listOfRules.Add(obj);
3880 }
3881 classSet.insert(clinfo);
3882 }
3883 }
3884 }
3885 }
3886
3887 // Write the StreamerInfo list even if it is empty.
3888 fClassIndex->fArray[0] = 2; //to prevent adding classes in TStreamerInfo::TagFile
3889
3890 if (listOfRules.GetEntries()) {
3891 // Only add the list of rules if we have something to say.
3892 list.Add(&listOfRules);
3893 }
3894
3895 //free previous StreamerInfo record
3896 if (fSeekInfo) MakeFree(fSeekInfo,fSeekInfo+fNbytesInfo-1);
3897 //Create new key
3898 TKey key(&list,"StreamerInfo",GetBestBuffer(), this);
3899 fKeys->Remove(&key);
3900 fSeekInfo = key.GetSeekKey();
3901 fNbytesInfo = key.GetNbytes();
3902 SumBuffer(key.GetObjlen());
3903 key.WriteFile(0);
3904
3905 fClassIndex->fArray[0] = 0;
3906
3907 list.RemoveLast(); // remove the listOfRules.
3908}
3909
3910////////////////////////////////////////////////////////////////////////////////
3911/// Open a file for reading through the file cache.
3912///
3913/// The file will be downloaded to the cache and opened from there.
3914/// If the download fails, it will be opened remotely.
3915/// The file will be downloaded to the directory specified by SetCacheFileDir().
3917TFile *TFile::OpenFromCache(const char *name, Option_t *, const char *ftitle,
3919{
3920 TFile *f = nullptr;
3921
3922 if (fgCacheFileDir == "") {
3923 ::Warning("TFile::OpenFromCache",
3924 "you want to read through a cache, but you have no valid cache "
3925 "directory set - reading remotely");
3926 ::Info("TFile::OpenFromCache", "set cache directory using TFile::SetCacheFileDir()");
3927 } else {
3928 TUrl fileurl(name);
3929
3930 if ((!strcmp(fileurl.GetProtocol(), "file"))) {
3931 // it makes no sense to read local files through a file cache
3932 if (!fgCacheFileForce)
3933 ::Warning("TFile::OpenFromCache",
3934 "you want to read through a cache, but you are reading "
3935 "local files - CACHEREAD disabled");
3936 } else {
3937 // this is a remote file and worthwhile to be put into the local cache
3938 // now create cachepath to put it
3941 cachefilepath = fgCacheFileDir;
3942 cachefilepath += fileurl.GetFile();
3944 if ((gSystem->mkdir(cachefilepathbasedir, kTRUE) < 0) &&
3946 ::Warning("TFile::OpenFromCache","you want to read through a cache, but I "
3947 "cannot create the directory %s - CACHEREAD disabled",
3948 cachefilepathbasedir.Data());
3949 } else {
3950 // check if this should be a zip file
3951 if (strlen(fileurl.GetAnchor())) {
3952 // remove the anchor and change the target name
3953 cachefilepath += "__";
3954 cachefilepath += fileurl.GetAnchor();
3955 fileurl.SetAnchor("");
3956 }
3957 if (strstr(name,"zip=")) {
3958 // filter out this option and change the target cache name
3959 TString urloptions = fileurl.GetOptions();
3961 TObjArray *objOptions = urloptions.Tokenize("&");
3962 Int_t optioncount = 0;
3964 for (Int_t n = 0; n < objOptions->GetEntries(); n++) {
3965 TString loption = ((TObjString*)objOptions->At(n))->GetName();
3966 TObjArray *objTags = loption.Tokenize("=");
3967 if (objTags->GetEntries() == 2) {
3968 TString key = ((TObjString*)objTags->At(0))->GetName();
3969 TString value = ((TObjString*)objTags->At(1))->GetName();
3970 if (key.CompareTo("zip", TString::kIgnoreCase)) {
3971 if (optioncount!=0) {
3972 newoptions += "&";
3973 }
3974 newoptions += key;
3975 newoptions += "=";
3976 newoptions += value;
3977 ++optioncount;
3978 } else {
3979 zipname = value;
3980 }
3981 }
3982 delete objTags;
3983 }
3984 delete objOptions;
3985 fileurl.SetOptions(newoptions.Data());
3986 cachefilepath += "__";
3988 fileurl.SetAnchor("");
3989 }
3990
3992
3993 // check if file is in the cache
3994 Long_t id;
3995 Long64_t size;
3996 Long_t flags;
3997 Long_t modtime;
3998 if (!gSystem->GetPathInfo(cachefilepath, &id, &size, &flags, &modtime)) {
3999 // file is in the cache
4000 if (!fgCacheFileDisconnected) {
4001 char cacheblock[256];
4002 char remotblock[256];
4003 // check the remote file for it's size and compare some magic bytes
4004 TString cfurl;
4006 cfurl += "?filetype=raw";
4007 TUrl rurl(name);
4008 TString ropt = rurl.GetOptions();
4009 ropt += "&filetype=raw";
4010 rurl.SetOptions(ropt);
4011
4012 Bool_t forcedcache = fgCacheFileForce;
4013 fgCacheFileForce = kFALSE;
4014
4015 TFile *cachefile = TFile::Open(cfurl, "READ");
4016 TFile *remotfile = TFile::Open(rurl.GetUrl(), "READ");
4017
4018 fgCacheFileForce = forcedcache;
4019
4020 if (!cachefile) {
4021 need2copy = kTRUE;
4022 ::Error("TFile::OpenFromCache",
4023 "cannot open the cache file to check cache consistency");
4024 return nullptr;
4025 }
4026
4027 if (!remotfile) {
4028 ::Error("TFile::OpenFromCache",
4029 "cannot open the remote file to check cache consistency");
4030 return nullptr;
4031 }
4032
4033 cachefile->Seek(0);
4034 remotfile->Seek(0);
4035
4036 if ((!cachefile->ReadBuffer(cacheblock,256)) &&
4037 (!remotfile->ReadBuffer(remotblock,256))) {
4038 if (memcmp(cacheblock, remotblock, 256)) {
4039 ::Warning("TFile::OpenFromCache", "the header of the cache file "
4040 "differs from the remote file - forcing an update");
4041 need2copy = kTRUE;
4042 }
4043 } else {
4044 ::Warning("TFile::OpenFromCache", "the header of the cache and/or "
4045 "remote file are not readable - forcing an update");
4046 need2copy = kTRUE;
4047 }
4048
4049 delete remotfile;
4050 delete cachefile;
4051 }
4052 } else {
4053 need2copy = kTRUE;
4054 }
4055
4056 // try to fetch the file (disable now the forced caching)
4057 Bool_t forcedcache = fgCacheFileForce;
4058 fgCacheFileForce = kFALSE;
4059 if (need2copy) {
4060 const auto cachefilepathtmp = cachefilepath + std::to_string(gSystem->GetPid()) + ".tmp";
4062 ::Warning("TFile::OpenFromCache",
4063 "you want to read through a cache, but I "
4064 "cannot make a cache copy of %s - CACHEREAD disabled",
4065 cachefilepathbasedir.Data());
4066 fgCacheFileForce = forcedcache;
4067 return nullptr;
4068 }
4069 if (gSystem->AccessPathName(cachefilepath)) // then file _does not_ exist (weird convention)
4071 else // another process or thread already wrote a file with the same name while we were copying it
4073 }
4074 fgCacheFileForce = forcedcache;
4075 ::Info("TFile::OpenFromCache", "using local cache copy of %s [%s]", name, cachefilepath.Data());
4076 // finally we have the file and can open it locally
4077 fileurl.SetProtocol("file");
4078 fileurl.SetFile(cachefilepath);
4079
4082 tagfile += ".ROOT.cachefile";
4083 // we symlink this file as a ROOT cached file
4085 return TFile::Open(fileurl.GetUrl(), "READ", ftitle, compress, netopt);
4086 }
4087 }
4088 }
4089
4090 // Failed
4091 return f;
4092}
4093
4094////////////////////////////////////////////////////////////////////////////////
4095/// Create / open a file
4096///
4097/// The type of the file can be either a
4098/// TFile, TNetFile, TWebFile or any TFile derived class for which an
4099/// plugin library handler has been registered with the plugin manager
4100/// (for the plugin manager see the TPluginManager class). The returned
4101/// type of TFile depends on the file name specified by 'url'.
4102/// If 'url' is a '|'-separated list of file URLs, the 'URLs' are tried
4103/// sequentially in the specified order until a successful open.
4104/// If the file starts with "root:", "roots:" or "rootk:" a TNetFile object
4105/// will be returned, with "http:" a TWebFile, with "file:" a local TFile,
4106/// etc. (see the list of TFile plugin handlers in $ROOTSYS/etc/system.rootrc
4107/// for regular expressions that will be checked) and as last a local file will
4108/// be tried.
4109/// Before opening a file via TNetFile a check is made to see if the URL
4110/// specifies a local file. If that is the case the file will be opened
4111/// via a normal TFile. To force the opening of a local file via a
4112/// TNetFile use either TNetFile directly or specify as host "localhost".
4113/// The netopt argument is only used by TNetFile. For the meaning of the
4114/// options and other arguments see the constructors of the individual
4115/// file classes. In case of error, it returns a nullptr.
4116///
4117/// For TFile implementations supporting asynchronous file open, see
4118/// TFile::AsyncOpen(...), it is possible to request a timeout with the
4119/// option <b>`TIMEOUT=<secs>`</b>: the timeout must be specified in seconds and
4120/// it will be internally checked with granularity of one millisec.
4121/// For remote files there is the option: <b>CACHEREAD</b> opens an existing
4122/// file for reading through the file cache. The file will be downloaded to
4123/// the cache and opened from there. If the download fails, it will be opened remotely.
4124/// The file will be downloaded to the directory specified by SetCacheFileDir().
4125///
4126/// *The caller is responsible for deleting the pointer.*
4127/// In READ mode, a nullptr is returned if the file does not exist or cannot be opened.
4128/// In CREATE mode, a nullptr is returned if the file already exists or cannot be created.
4129/// In RECREATE mode, a nullptr is returned if the file can not be created.
4130/// In UPDATE mode, a nullptr is returned if the file cannot be created or opened.
4132TFile *TFile::Open(const char *url, Option_t *options, const char *ftitle,
4134{
4136 TFile *f = nullptr;
4137 EFileType type = kFile;
4138
4139 // Check input
4140 if (!url || strlen(url) <= 0) {
4141 ::Error("TFile::Open", "no url specified");
4142 return f;
4143 }
4144
4147
4148#ifdef R__UNIX
4149 // If URL is a file on an EOS FUSE mount, attempt redirection to XRootD protocol.
4150 if (gEnv->GetValue("TFile.CrossProtocolRedirects", 1) == 1) {
4151 TUrl fileurl(expandedUrl, /* default is file */ kTRUE);
4152 if (strcmp(fileurl.GetProtocol(), "file") == 0) {
4153 ssize_t len = getxattr(fileurl.GetFile(), "eos.url.xroot", nullptr, 0);
4154 if (len > 0) {
4155 std::string xurl(len, 0);
4156 std::string fileNameFromUrl{fileurl.GetFile()};
4157 if (getxattr(fileNameFromUrl.c_str(), "eos.url.xroot", &xurl[0], len) == len) {
4158 // Sometimes the `getxattr` call may return an invalid URL due
4159 // to the POSIX attribute not being yet completely filled by EOS.
4160 if (auto baseName = fileNameFromUrl.substr(fileNameFromUrl.find_last_of("/") + 1);
4161 std::equal(baseName.crbegin(), baseName.crend(), xurl.crbegin())) {
4162 if ((f = TFile::Open(xurl.c_str(), options, ftitle, compress, netopt))) {
4163 if (!f->IsZombie()) {
4164 return f;
4165 } else {
4166 delete f;
4167 f = nullptr;
4168 }
4169 }
4170 }
4171 }
4172 }
4173 }
4174 }
4175#endif
4176
4177 // If a timeout has been specified extract the value and try to apply it (it requires
4178 // support for asynchronous open, though; the following is completely transparent if
4179 // such support if not available for the required protocol)
4180 TString opts(options);
4181 Int_t ito = opts.Index("TIMEOUT=");
4182 if (ito != kNPOS) {
4183 TString sto = opts(ito + std::char_traits<char>::length("TIMEOUT="), opts.Length());
4184 while (!(sto.IsDigit()) && !(sto.IsNull())) { sto.Remove(sto.Length()-1,1); }
4185 if (!(sto.IsNull())) {
4186 // Timeout in millisecs
4187 Int_t toms = sto.Atoi() * 1000;
4188 if (gDebug > 0) ::Info("TFile::Open", "timeout of %d millisec requested", toms);
4189 // Remove from the options field
4190 sto.Insert(0, "TIMEOUT=");
4191 opts.ReplaceAll(sto, "");
4192 // Asynchronous open
4194 // Check the result in steps of 1 millisec
4197 Int_t xtms = toms;
4198 while (aos == TFile::kAOSInProgress && xtms > 0) {
4199 gSystem->Sleep(1);
4200 xtms -= 1;
4202 }
4204 // Do open the file now
4205 f = TFile::Open(fh);
4206 if (gDebug > 0) {
4207 if (aos == TFile::kAOSSuccess)
4208 ::Info("TFile::Open", "waited %d millisec for asynchronous open", toms - xtms);
4209 else
4210 ::Info("TFile::Open", "timeout option not supported (requires asynchronous"
4211 " open support)");
4212 }
4213 } else {
4214 if (xtms <= 0)
4215 ::Error("TFile::Open", "timeout expired while opening '%s'", expandedUrl.Data());
4216 // Cleanup the request
4217 SafeDelete(fh);
4218 }
4219 // Done
4220 return f;
4221 } else {
4222 ::Warning("TFile::Open", "incomplete 'TIMEOUT=' option specification - ignored");
4223 opts.ReplaceAll("TIMEOUT=", "");
4224 }
4225 }
4226
4227 // We will use this from now on
4228 const char *option = opts;
4229
4230 // Many URLs? Redirect output and print errors in case of global failure
4232 Ssiz_t ip = namelist.Index("|");
4233 Bool_t rediroutput = (ip != kNPOS &&
4234 ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
4236 if (rediroutput) {
4237 TString outf = ".TFileOpen_";
4239 if (fout) {
4240 fclose(fout);
4241 gSystem->RedirectOutput(outf, "w", &rh);
4242 }
4243 }
4244
4245 // Try sequentially all names in 'names'
4246 TString name, n;
4247 Ssiz_t from = 0;
4248 while (namelist.Tokenize(n, from, "|") && !f) {
4249
4250 // check if we read through a file cache
4251 if (!strcasecmp(option, "CACHEREAD") ||
4252 ((!strcasecmp(option,"READ") || !option[0]) && fgCacheFileForce)) {
4253 // Try opening the file from the cache
4255 return f;
4256 }
4257
4258 IncrementFileCounter();
4259
4260 // change names to be recognized by the plugin manager
4261 // e.g. /protocol/path/to/file.root -> protocol:/path/to/file.root
4262 TUrl urlname(n, kTRUE);
4263 name = urlname.GetUrl();
4264 // Check first if a pending async open request matches this one
4265 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4266 TIter nxr(fgAsyncOpenRequests);
4267 TFileOpenHandle *fh = nullptr;
4268 while ((fh = (TFileOpenHandle *)nxr()))
4269 if (fh->Matches(name))
4270 return TFile::Open(fh);
4271 }
4272
4273 TString urlOptions(urlname.GetOptions());
4274 if (urlOptions.BeginsWith("pmerge") || urlOptions.Contains("&pmerge") || urlOptions.Contains(" pmerge")) {
4275 type = kMerge;
4276
4277 // Pass the full name including the url options:
4278 f = (TFile*) gROOT->ProcessLineFast(TString::Format("new TParallelMergingFile(\"%s\",\"%s\",\"%s\",%d)",n.Data(),option,ftitle,compress));
4279
4280 } else {
4281 // Resolve the file type; this also adjusts names
4282 TString lfname = gEnv->GetValue("Path.Localroot", "");
4283 type = GetType(name, option, &lfname);
4284
4285 if (type == kLocal) {
4286
4287 // Local files
4288 if (lfname.IsNull()) {
4289 urlname.SetHost("");
4290 urlname.SetProtocol("file");
4291 lfname = urlname.GetUrl();
4292 }
4293 f = new TFile(lfname.Data(), option, ftitle, compress);
4294
4295 } else if (type == kNet) {
4296
4297 // Network files
4298 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
4299 if (h->LoadPlugin() == -1)
4300 return nullptr;
4301 f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
4302 }
4303
4304 } else if (type == kWeb) {
4305
4306 // Web files
4307 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
4308 if (h->LoadPlugin() == -1)
4309 return nullptr;
4310 f = (TFile*) h->ExecPlugin(2, name.Data(), option);
4311 }
4312
4313 } else if (type == kFile) {
4314
4315 // 'file:' protocol
4316 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4317 h->LoadPlugin() == 0) {
4318 name.ReplaceAll("file:", "");
4319 f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
4320 } else
4321 f = new TFile(name.Data(), option, ftitle, compress);
4322
4323 } else {
4324
4325 // no recognized specification: try the plugin manager
4326 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name.Data()))) {
4327 if (h->LoadPlugin() == -1)
4328 return nullptr;
4329 TClass *cl = TClass::GetClass(h->GetClass());
4330 if (cl && cl->InheritsFrom("TNetFile"))
4331 f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
4332 else
4333 f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
4334 } else {
4335 // Just try to open it locally but via TFile::Open, so that we pick-up the correct
4336 // plug-in in the case file name contains information about a special backend (e.g.)
4337 if (strcmp(name, urlname.GetFileAndOptions()) != 0)
4338 f = TFile::Open(urlname.GetFileAndOptions(), option, ftitle, compress);
4339 }
4340 }
4341 }
4342
4343 if (f && f->IsZombie()) {
4344 TString newUrl = f->GetNewUrl();
4345 delete f;
4346 if( newUrl.Length() && (newUrl != name) && gEnv->GetValue("TFile.CrossProtocolRedirects", 1) )
4348 else
4349 f = nullptr;
4350 }
4351 }
4352
4353 if (rediroutput) {
4354 // Restore output to stdout
4355 gSystem->RedirectOutput(0, "", &rh);
4356 // If we failed print error messages
4357 if (!f)
4359 // Remove the file
4360 gSystem->Unlink(rh.fFile);
4361 }
4362
4363 // if the file is writable, non local, and not opened in raw mode
4364 // we create a default write cache of 512 KBytes
4365 if (type != kLocal && type != kFile &&
4366 f && f->IsWritable() && !f->IsRaw()) {
4367 new TFileCacheWrite(f, 1);
4368 }
4369
4370 return f;
4371}
4372
4373////////////////////////////////////////////////////////////////////////////////
4374/// Submit an asynchronous open request.
4375
4376/// See TFile::Open(const char *, ...) for an
4377/// explanation of the arguments. A handler is returned which is to be passed
4378/// to TFile::Open(TFileOpenHandle *) to get the real TFile instance once
4379/// the file is open.
4380/// This call never blocks and it is provided to allow parallel submission
4381/// of file opening operations expected to take a long time.
4382/// TFile::Open(TFileOpenHandle *) may block if the file is not yet ready.
4383/// The sequence
4384///
4385/// TFile::Open(TFile::AsyncOpen(const char *, ...))
4386///
4387/// is equivalent to
4388///
4389/// TFile::Open(const char *, ...)
4390///
4391/// To be effective, the underlying TFile implementation must be able to
4392/// support asynchronous open functionality. Currently, only TNetXNGFile
4393/// supports it. If the functionality is not implemented, this call acts
4394/// transparently by returning an handle with the arguments for the
4395/// standard synchronous open run by TFile::Open(TFileOpenHandle *).
4396/// The retuned handle will be adopted by TFile after opening completion
4397/// in TFile::Open(TFileOpenHandle *); if opening is not finalized the
4398/// handle must be deleted by the caller.
4400TFileOpenHandle *TFile::AsyncOpen(const char *url, Option_t *option,
4401 const char *ftitle, Int_t compress,
4402 Int_t netopt)
4403{
4404 TFileOpenHandle *fh = nullptr;
4405 TFile *f = nullptr;
4407
4408 // Check input
4409 if (!url || strlen(url) <= 0) {
4410 ::Error("TFile::AsyncOpen", "no url specified");
4411 return fh;
4412 }
4413
4414 // Many URLs? Redirect output and print errors in case of global failure
4417 Ssiz_t ip = namelist.Index("|");
4418 Bool_t rediroutput = (ip != kNPOS &&
4419 ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
4421 if (rediroutput) {
4422 TString outf = ".TFileAsyncOpen_";
4424 if (fout) {
4425 fclose(fout);
4426 gSystem->RedirectOutput(outf, "w", &rh);
4427 }
4428 }
4429
4430 // Try sequentially all names in 'names'
4431 TString name, n;
4432 Ssiz_t from = 0;
4433 while (namelist.Tokenize(n, from, "|") && !f) {
4434
4435 // change names to be recognized by the plugin manager
4436 // e.g. /protocol/path/to/file.root -> protocol:/path/to/file.root
4437 TUrl urlname(n, kTRUE);
4438 name = urlname.GetUrl();
4439
4440 // Resolve the file type; this also adjusts names
4441 EFileType type = GetType(name, option);
4442
4443 TPluginHandler *h = nullptr;
4444
4445 // Here we send the asynchronous request if the functionality is implemented
4446 if (type == kNet) {
4447 // Network files
4448 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4449 !strcmp(h->GetClass(),"TNetXNGFile")
4450 && h->LoadPlugin() == 0) {
4451 f = (TFile*) h->ExecPlugin(6, name.Data(), option, ftitle, compress, netopt, kTRUE);
4452 notfound = kFALSE;
4453 }
4454 }
4455 }
4456
4457 if (rediroutput) {
4458 // Restore output to stdout
4459 gSystem->RedirectOutput(0, "", &rh);
4460 // If we failed print error messages
4461 if (!notfound && !f)
4463 // Remove the file
4464 gSystem->Unlink(rh.fFile);
4465 }
4466
4467 // Make sure that no error occurred
4468 if (notfound) {
4469 SafeDelete(f);
4470 // Save the arguments in the handler, so that a standard open can be
4471 // attempted later on
4473 } else if (f) {
4474 // Fill the opaque handler to be use to attach the file later on
4475 fh = new TFileOpenHandle(f);
4476 }
4477
4478 // Record this request
4479 if (fh) {
4480 // Create the lst, if not done already
4481 if (!fgAsyncOpenRequests)
4482 fgAsyncOpenRequests = new TList;
4483 fgAsyncOpenRequests->Add(fh);
4484 }
4485
4486 // We are done
4487 return fh;
4488}
4489
4490////////////////////////////////////////////////////////////////////////////////
4491/// Waits for the completion of an asynchronous open request.
4492///
4493/// Returns the pointer to the associated TFile, transferring ownership of the
4494/// handle to the TFile instance.
4497{
4498 TFile *f = nullptr;
4499
4500 // Note that the request may have failed
4501 if (fh && fgAsyncOpenRequests) {
4502 // Remove it from the pending list: we need to do it at this level to avoid
4503 // recursive calls in the standard TFile::Open
4504 fgAsyncOpenRequests->Remove(fh);
4505 // Was asynchronous open functionality implemented?
4506 if ((f = fh->GetFile()) && !(f->IsZombie())) {
4507 // Yes: wait for the completion of the open phase, if needed
4508 Bool_t cr = (!strcmp(f->GetOption(),"CREATE") ||
4509 !strcmp(f->GetOption(),"RECREATE") ||
4510 !strcmp(f->GetOption(),"NEW")) ? kTRUE : kFALSE;
4511 f->Init(cr);
4512 } else {
4513 // No: process a standard open
4514 f = TFile::Open(fh->GetName(), fh->GetOpt(), fh->GetTitle(),
4515 fh->GetCompress(), fh->GetNetOpt());
4516 }
4517
4518 // Adopt the handle instance in the TFile instance so that it gets
4519 // automatically cleaned up
4520 if (f) f->fAsyncHandle = fh;
4521 }
4522
4523 // We are done
4524 return f;
4525}
4526
4527////////////////////////////////////////////////////////////////////////////////
4528/// Interface to system open. All arguments like in POSIX open().
4530Int_t TFile::SysOpen(const char *pathname, Int_t flags, UInt_t mode)
4531{
4532#if defined(R__WINGCC)
4533 // ALWAYS use binary mode - even cygwin text should be in unix format
4534 // although this is posix default it has to be set explicitly
4535 return ::open(pathname, flags | O_BINARY, mode);
4536#elif defined(R__SEEK64)
4537 return ::open64(pathname, flags, mode);
4538#else
4539 return ::open(pathname, flags, mode);
4540#endif
4541}
4542
4543////////////////////////////////////////////////////////////////////////////////
4544/// Interface to system close. All arguments like in POSIX close().
4547{
4548 if (fd < 0) return 0;
4549 return ::close(fd);
4550}
4551
4552////////////////////////////////////////////////////////////////////////////////
4553/// Interface to system read. All arguments like in POSIX read().
4555Int_t TFile::SysRead(Int_t fd, void *buf, Int_t len)
4556{
4557 return ::read(fd, buf, len);
4558}
4559
4560////////////////////////////////////////////////////////////////////////////////
4561/// Interface to system write. All arguments like in POSIX write().
4563Int_t TFile::SysWrite(Int_t fd, const void *buf, Int_t len)
4564{
4565 return ::write(fd, buf, len);
4566}
4567////////////////////////////////////////////////////////////////////////////////
4568/// Interface to system lseek.
4569///
4570/// All arguments like in POSIX lseek()
4571/// except that the offset and return value are of a type which are
4572/// able to handle 64 bit file systems.
4575{
4576#if defined (R__SEEK64)
4577 return ::lseek64(fd, offset, whence);
4578#elif defined(WIN32)
4579 return ::_lseeki64(fd, offset, whence);
4580#else
4581 return ::lseek(fd, offset, whence);
4582#endif
4583}
4584
4585////////////////////////////////////////////////////////////////////////////////
4586/// Return file stat information.
4587///
4588/// The interface and return value is
4589/// identical to TSystem::GetPathInfo(). The function returns 0 in
4590/// case of success and 1 if the file could not be stat'ed.
4593 Long_t *modtime)
4594{
4595 return gSystem->GetPathInfo(fRealName, id, size, flags, modtime);
4596}
4597
4598////////////////////////////////////////////////////////////////////////////////
4599/// Interface to system fsync. All arguments like in POSIX fsync().
4602{
4603 if (TestBit(kDevNull)) return 0;
4604
4605#ifndef WIN32
4606 return ::fsync(fd);
4607#else
4608 return ::_commit(fd);
4609#endif
4610}
4611
4612////////////////////////////////////////////////////////////////////////////////
4613/// Return the total number of bytes written so far to the file.
4616{
4617 return fCacheWrite ? fCacheWrite->GetBytesInCache() + fBytesWrite : fBytesWrite;
4618}
4619
4620////////////////////////////////////////////////////////////////////////////////
4621/// Static function returning the total number of bytes read from all files.
4624{
4625 return fgBytesRead;
4626}
4627
4628////////////////////////////////////////////////////////////////////////////////
4629/// Static function returning the total number of bytes written to all files.
4630/// Does not take into account what might still be in the write caches.
4633{
4634 return fgBytesWrite;
4635}
4636
4637////////////////////////////////////////////////////////////////////////////////
4638/// Static function returning the total number of read calls from all files.
4641{
4642 return fgReadCalls;
4643}
4644
4645////////////////////////////////////////////////////////////////////////////////
4646/// Static function returning the readahead buffer size.
4649{
4650 return fgReadaheadSize;
4651}
4652
4653//______________________________________________________________________________
4654void TFile::SetReadaheadSize(Int_t bytes) { fgReadaheadSize = bytes; }
4655
4656//______________________________________________________________________________
4657void TFile::SetFileBytesRead(Long64_t bytes) { fgBytesRead = bytes; }
4658
4659//______________________________________________________________________________
4660void TFile::SetFileBytesWritten(Long64_t bytes) { fgBytesWrite = bytes; }
4661
4662//______________________________________________________________________________
4663void TFile::SetFileReadCalls(Int_t readcalls) { fgReadCalls = readcalls; }
4664
4665//______________________________________________________________________________
4666Long64_t TFile::GetFileCounter() { return fgFileCounter; }
4667
4668//______________________________________________________________________________
4669void TFile::IncrementFileCounter() { fgFileCounter++; }
4670
4671////////////////////////////////////////////////////////////////////////////////
4672/// Sets the directory where to locally stage/cache remote files.
4673/// If the directory is not writable by us return kFALSE.
4677{
4679 if (!cached.EndsWith("/"))
4680 cached += "/";
4681
4683 // try to create it
4686 ::Error("TFile::SetCacheFileDir", "no sufficient permissions on cache directory %s or cannot create it", TString(cachedir).Data());
4687 fgCacheFileDir = "";
4688 return kFALSE;
4689 }
4690 gSystem->Chmod(cached, 0700);
4691 }
4693 gSystem->Chmod(cached, 0700);
4694 fgCacheFileDir = cached;
4695 fgCacheFileDisconnected = operatedisconnected;
4696 fgCacheFileForce = forcecacheread;
4697 return kTRUE;
4698}
4699
4700////////////////////////////////////////////////////////////////////////////////
4701/// Get the directory where to locally stage/cache remote files.
4703const char *TFile::GetCacheFileDir()
4704{
4705 return fgCacheFileDir;
4706}
4707
4708////////////////////////////////////////////////////////////////////////////////
4709/// Try to shrink the cache to the desired size.
4710///
4711/// With the clenupinterval you can specify the minimum amount of time after
4712/// the previous cleanup before the cleanup operation is repeated in
4713/// the cache directory
4716{
4717 if (fgCacheFileDir == "") {
4718 return kFALSE;
4719 }
4720
4721 // check the last clean-up in the cache
4722 Long_t id;
4723 Long64_t size;
4724 Long_t flags;
4725 Long_t modtime;
4726
4727 TString cachetagfile = fgCacheFileDir;
4728 cachetagfile += ".tag.ROOT.cache";
4729 if (!gSystem->GetPathInfo(cachetagfile, &id, &size, &flags, &modtime)) {
4730 // check the time passed since last cache cleanup
4731 Long_t lastcleanuptime = ((Long_t)time(0) - modtime);
4733 ::Info("TFile::ShrinkCacheFileDir", "clean-up is skipped - last cleanup %lu seconds ago - you requested %lu", lastcleanuptime, cleanupinterval);
4734 return kTRUE;
4735 }
4736 }
4737
4738 // (re-)create the cache tag file
4739 cachetagfile += "?filetype=raw";
4740 TFile *tagfile = nullptr;
4741
4742 if (!(tagfile = TFile::Open(cachetagfile, "RECREATE"))) {
4743 ::Error("TFile::ShrinkCacheFileDir", "cannot create the cache tag file %s", cachetagfile.Data());
4744 return kFALSE;
4745 }
4746
4747 // the shortest garbage collector in the world - one long line of PERL - unlinks files only,
4748 // if there is a symbolic link with '.ROOT.cachefile' for safety ;-)
4749
4750 TString cmd;
4751#if defined(R__WIN32)
4752 cmd = "echo <TFile::ShrinkCacheFileDir>: cleanup to be implemented";
4753#elif defined(R__MACOSX)
4754 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);
4755#else
4756 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);
4757#endif
4758
4759 tagfile->WriteBuffer(cmd, 4096);
4760 delete tagfile;
4761
4762 if ((gSystem->Exec(cmd)) != 0) {
4763 ::Error("TFile::ShrinkCacheFileDir", "error executing clean-up script");
4764 return kFALSE;
4765 }
4766
4767 return kTRUE;
4768}
4769
4770////////////////////////////////////////////////////////////////////////////////
4771/// Sets open timeout time (in ms). Returns previous timeout value.
4774{
4775 UInt_t to = fgOpenTimeout;
4776 fgOpenTimeout = timeout;
4777 return to;
4778}
4779
4780////////////////////////////////////////////////////////////////////////////////
4781/// Returns open timeout (in ms).
4784{
4785 return fgOpenTimeout;
4786}
4787
4788////////////////////////////////////////////////////////////////////////////////
4789/// Sets only staged flag. Returns previous value of flag.
4790/// When true we check before opening the file if it is staged, if not,
4791/// the open fails.
4794{
4795 Bool_t f = fgOnlyStaged;
4796 fgOnlyStaged = onlystaged;
4797 return f;
4798}
4799
4800////////////////////////////////////////////////////////////////////////////////
4801/// Returns staged only flag.
4804{
4805 return fgOnlyStaged;
4806}
4807
4808////////////////////////////////////////////////////////////////////////////////
4809/// Return kTRUE if 'url' matches the coordinates of this file.
4810///
4811/// The check is implementation dependent and may need to be overload
4812/// by each TFile implementation relying on this check.
4813/// The default implementation checks the file name only.
4815Bool_t TFile::Matches(const char *url)
4816{
4817 // Check the full URL, including port and FQDN.
4818 TUrl u(url);
4819
4820 // Check
4821 if (!strcmp(u.GetFile(), fUrl.GetFile())) {
4822 // Check ports
4823 if (u.GetPort() == fUrl.GetPort()) {
4824 if (!strcmp(u.GetHostFQDN(), fUrl.GetHostFQDN())) {
4825 // Ok, coordinates match
4826 return kTRUE;
4827 }
4828 }
4829 }
4830
4831 // Default is not matching
4832 return kFALSE;
4833}
4834
4835////////////////////////////////////////////////////////////////////////////////
4836/// Return kTRUE if this async request matches the open request
4837/// specified by 'url'
4840{
4841 if (fFile) {
4842 return fFile->Matches(url);
4843 } else if (fName.Length() > 0){
4844 // Deep check of URLs
4845 TUrl u(url);
4846 TUrl uref(fName);
4847 if (!strcmp(u.GetFile(), uref.GetFile())) {
4848 // Check ports
4849 if (u.GetPort() == uref.GetPort()) {
4850 // Check also the host name
4851 if (!strcmp(u.GetHostFQDN(), uref.GetHostFQDN())) {
4852 // Ok, coordinates match
4853 return kTRUE;
4854 }
4855 }
4856 }
4857 }
4858
4859 // Default is not matching
4860 return kFALSE;
4861}
4862
4863////////////////////////////////////////////////////////////////////////////////
4864/// Resolve the file type as a function of the protocol field in 'name'
4865///
4866/// If defined, the string 'prefix' is added when testing the locality of
4867/// a 'name' with network-like structure (i.e. root://host//path); if the file
4868/// is local, on return 'prefix' will contain the actual local path of the file.
4870TFile::EFileType TFile::GetType(const char *name, Option_t *option, TString *prefix)
4871{
4873
4874 TPMERegexp re("^(root|xroot).*", "i");
4875 if (re.Match(name)) {
4876 //
4877 // Should be a network file ...
4878 type = kNet;
4879 // ... but make sure that is not local or that a remote-like connection
4880 // is forced. Treat it as local if:
4881 // i) the url points to the localhost, the file will be opened in
4882 // readonly mode and the current user has read access;
4883 // ii) the specified user is equal to the current user then open local
4884 // TFile.
4886 TUrl url(name);
4887 //
4888 // Check whether we should try to optimize for local files
4889 Bool_t forceRemote = gEnv->GetValue("Path.ForceRemote", 0);
4890 forceRemote = (forceRemote) ? kTRUE : gEnv->GetValue("TFile.ForceRemote", 0);
4891 TString opts = url.GetOptions();
4892 if (opts.Contains("remote=1"))
4894 else if (opts.Contains("remote=0"))
4896 if (!forceRemote) {
4897 // Generic locality test
4899 if (localFile) {
4900 // Local path including the prefix
4901 const char *fname = url.GetFileAndOptions();
4903 if (fname[0] == '/') {
4904 if (prefix)
4905 lfname.Form("%s%s", prefix->Data(), fname);
4906 else
4907 lfname = fname;
4908 } else if (fname[0] == '~' || fname[0] == '$') {
4909 lfname = fname;
4910 } else {
4911 lfname.Form("%s/%s", gSystem->HomeDirectory(), fname);
4912 }
4913 // If option "READ" test existence and access
4914 TString opt = option;
4915 Bool_t read = (opt.IsNull() ||
4916 !opt.CompareTo("READ", TString::kIgnoreCase)) ? kTRUE : kFALSE;
4917 if (read) {
4919 if (!gSystem->ExpandPathName(fn)) {
4921 localFile = kFALSE;
4922 }
4923 }
4924 // Return full local path if requested (and if the case)
4925 if (localFile && prefix)
4926 *prefix = lfname;
4927 }
4928 }
4929 //
4930 // Adjust the type according to findings
4931 type = (localFile) ? kLocal : type;
4932 } else if (TPMERegexp("^(http[s]?|s3http[s]?|[a]?s3|gs|gshttp[s]?){1}:", "i").Match(name)) {
4933 //
4934 // Web file
4935 type = kWeb;
4936 } else if (!strncmp(name, "file:", 5)) {
4937 //
4938 // 'file' protocol
4939 type = kFile;
4940 }
4941 // We are done
4942 return type;
4943}
4944
4945////////////////////////////////////////////////////////////////////////////////
4946/// Get status of the async open request related to 'name'.
4949{
4950 // Check the list of pending async open requests
4951 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4952 TIter nxr(fgAsyncOpenRequests);
4953 TFileOpenHandle *fh = nullptr;
4954 while ((fh = (TFileOpenHandle *)nxr()))
4955 if (fh->Matches(name))
4956 return TFile::GetAsyncOpenStatus(fh);
4957 }
4958
4959 // Check also the list of files open
4961 TSeqCollection *of = gROOT->GetListOfFiles();
4962 if (of && (of->GetSize() > 0)) {
4963 TIter nxf(of);
4964 TFile *f = nullptr;
4965 while ((f = (TFile *)nxf()))
4966 if (f->Matches(name))
4967 return f->GetAsyncOpenStatus();
4968 }
4969
4970 // Default is synchronous mode
4971 return kAOSNotAsync;
4972}
4973
4974////////////////////////////////////////////////////////////////////////////////
4975/// Get status of the async open request related to 'handle'.
4978{
4979 if (handle && handle->fFile) {
4980 if (!handle->fFile->IsZombie())
4981 return handle->fFile->GetAsyncOpenStatus();
4982 else
4983 return TFile::kAOSFailure;
4984 }
4985
4986 // Default is synchronous mode
4987 return TFile::kAOSNotAsync;
4988}
4989
4990////////////////////////////////////////////////////////////////////////////////
4991/// Get final URL for file being opened asynchronously.
4992/// Returns 0 is the information is not yet available.
4994const TUrl *TFile::GetEndpointUrl(const char* name)
4995{
4996 // Check the list of pending async open requests
4997 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4998 TIter nxr(fgAsyncOpenRequests);
4999 TFileOpenHandle *fh = nullptr;
5000 while ((fh = (TFileOpenHandle *)nxr()))
5001 if (fh->Matches(name))
5002 if (fh->fFile)
5003 return fh->fFile->GetEndpointUrl();
5004 }
5005
5006 // Check also the list of files open
5008 TSeqCollection *of = gROOT->GetListOfFiles();
5009 if (of && (of->GetSize() > 0)) {
5010 TIter nxf(of);
5011 TFile *f = nullptr;
5012 while ((f = (TFile *)nxf()))
5013 if (f->Matches(name))
5014 return f->GetEndpointUrl();
5015 }
5016
5017 // Information not yet available
5018 return (const TUrl *)nullptr;
5019}
5020
5021////////////////////////////////////////////////////////////////////////////////
5022/// Print file copy progress.
5025{
5026 fprintf(stderr, "[TFile::Cp] Total %.02f MB\t|", (Double_t)size/1048576);
5027
5028 for (int l = 0; l < 20; l++) {
5029 if (size > 0) {
5030 if (l < 20*bytesread/size)
5031 fprintf(stderr, "=");
5032 else if (l == 20*bytesread/size)
5033 fprintf(stderr, ">");
5034 else if (l > 20*bytesread/size)
5035 fprintf(stderr, ".");
5036 } else
5037 fprintf(stderr, "=");
5038 }
5039 // Allow to update the GUI while uploading files
5041 watch.Stop();
5042 Double_t lCopy_time = watch.RealTime();
5043 fprintf(stderr, "| %.02f %% [%.01f MB/s]\r",
5044 100.0*(size?(bytesread/((float)size)):1), (lCopy_time>0.)?bytesread/lCopy_time/1048576.:0.);
5045 watch.Continue();
5046}
5047
5048////////////////////////////////////////////////////////////////////////////////
5049/// Allows to copy this file to the dst URL. Returns kTRUE in case of success,
5050/// kFALSE otherwise.
5053{
5057
5058 TUrl dURL(dst, kTRUE);
5059
5060 TString oopt = "RECREATE";
5061 TString ourl = dURL.GetUrl();
5062
5063 // Files will be open in RAW mode
5064 TString raw = "filetype=raw";
5065
5066 // Set optimization options for the destination file
5067 TString opt = dURL.GetOptions();
5068 if (opt != "") opt += "&";
5069 opt += raw;
5070
5071 // AliEn files need to know where the source file is
5072 if (!strcmp(dURL.GetProtocol(), "alien"))
5073 opt += TString::Format("&source=%s", GetName());
5074
5075 dURL.SetOptions(opt);
5076
5077 char *copybuffer = nullptr;
5078
5079 TFile *sfile = this;
5080 TFile *dfile = nullptr;
5081
5082 // "RECREATE" does not work always well with XROOTD
5083 // namely when some pieces of the path are missing;
5084 // we force "NEW" in such a case
5085 if (TFile::GetType(ourl, "") == TFile::kNet) {
5086 if (gSystem->AccessPathName(ourl)) {
5087 oopt = "NEW";
5088 // Force creation of the missing parts of the path
5089 opt += "&mkpath=1";
5090 dURL.SetOptions(opt);
5091 }
5092 }
5093
5094 // Open destination file
5095 if (!(dfile = TFile::Open(dURL.GetUrl(), oopt))) {
5096 ::Error("TFile::Cp", "cannot open destination file %s", dst);
5097 goto copyout;
5098 }
5099
5100 // Probably we created a new file
5101 // We have to remove it in case of errors
5103
5104 sfile->Seek(0);
5105 dfile->Seek(0);
5106
5107 copybuffer = new char[buffersize];
5108 if (!copybuffer) {
5109 ::Error("TFile::Cp", "cannot allocate the copy buffer");
5110 goto copyout;
5111 }
5112
5115
5116 totalread = 0;
5117 filesize = sfile->GetSize();
5118
5119 watch.Start();
5120
5121 b00 = sfile->GetBytesRead();
5122
5123 do {
5124 if (progressbar) CpProgress(totalread, filesize,watch);
5125
5126 Long64_t b1 = sfile->GetBytesRead() - b00;
5127
5129 if (filesize - b1 > (Long64_t)buffersize) {
5131 } else {
5132 readsize = filesize - b1;
5133 }
5134
5135 if (readsize == 0) break;
5136
5137 Long64_t b0 = sfile->GetBytesRead();
5139 readop = sfile->ReadBuffer(copybuffer, (Int_t)readsize);
5140 read = sfile->GetBytesRead() - b0;
5141 if ((read <= 0) || readop) {
5142 ::Error("TFile::Cp", "cannot read from source file %s. readsize=%lld read=%lld readop=%d",
5143 sfile->GetName(), readsize, read, readop);
5144 goto copyout;
5145 }
5146
5147 Long64_t w0 = dfile->GetBytesWritten();
5148 writeop = dfile->WriteBuffer(copybuffer, (Int_t)read);
5149 written = dfile->GetBytesWritten() - w0;
5150 if ((written != read) || writeop) {
5151 ::Error("TFile::Cp", "cannot write %lld bytes to destination file %s", read, dst);
5152 goto copyout;
5153 }
5154 totalread += read;
5155 } while (read == (Long64_t)buffersize);
5156
5157 if (progressbar) {
5158 CpProgress(totalread, filesize,watch);
5159 fprintf(stderr, "\n");
5160 }
5161
5162 success = kTRUE;
5163
5164copyout:
5165 if (dfile) dfile->Close();
5166
5167 if (dfile) delete dfile;
5168 if (copybuffer) delete[] copybuffer;
5169
5170 if (rmdestiferror && (success != kTRUE))
5171 gSystem->Unlink(dst);
5172
5173 watch.Stop();
5174 watch.Reset();
5175
5176 return success;
5177}
5178
5179////////////////////////////////////////////////////////////////////////////////
5180/// Allows to copy file from src to dst URL. Returns kTRUE in case of success,
5181/// kFALSE otherwise.
5183Bool_t TFile::Cp(const char *src, const char *dst, Bool_t progressbar,
5185{
5186 TUrl sURL(src, kTRUE);
5187
5188 TFile *sfile = nullptr;
5189
5191
5192 // Open source file
5193 if (!(sfile = TFile::Open(sURL.GetUrl(), "READ"))) {
5194 ::Error("TFile::Cp", "cannot open source file %s", src);
5195 } else {
5197 }
5198
5199 if (sfile) {
5200 sfile->Close();
5201 delete sfile;
5202 }
5203
5204 return success;
5205}
5206
5207//______________________________________________________________________________
5208//The next statement is not active anymore on Linux.
5209//Using posix_fadvise introduces a performance penalty (10 %) on optimized files
5210//and in addition it destroys the information of TTreePerfStats
5211#if defined(R__neverLINUX) && !defined(R__WINGCC)
5213{
5214 // Read specified byte range asynchronously. Actually we tell the kernel
5215 // which blocks we are going to read so it can start loading these blocks
5216 // in the buffer cache.
5217
5218 // Shortcut to avoid having to implement dummy ReadBufferAsync() in all
5219 // I/O plugins. Override ReadBufferAsync() in plugins if async is supported.
5220 if (IsA() != TFile::Class())
5221 return kTRUE;
5222
5224 if (len == 0) {
5225 // according POSIX spec if len is zero, all data following offset
5226 // is specified. Nevertheless ROOT uses zero to probe readahead
5227 // capabilities.
5229 }
5230 start = 0;
5231 if (TTimeStamp();
5232#if defined(R__SEEK64)
5234#else
5236#endif
5237 if (gPerfStats) {
5238 gPerfStats->FileReadEvent(this, len, start);
5239 }
5240 return (result != 0);
5241}
5242#else
5244{
5245 // Not supported yet on non Linux systems.
5246
5247 return kTRUE;
5248}
5249#endif
5250
5251////////////////////////////////////////////////////////////////////////////////
5252/// Max number of bytes to prefetch.
5253///
5254/// By default this is 75% of the
5255/// read cache size. But specific TFile implementations may need to change it
5258{
5259 TFileCacheRead *cr = nullptr;
5260 if ((cr = GetCacheRead())) {
5261 Int_t bytes = cr->GetBufferSize() / 4 * 3;
5262 return ((bytes < 0) ? 0 : bytes);
5263 }
5264 return 0;
5265}
void frombuf(char *&buf, Bool_t *x)
Definition Bytes.h:278
void tobuf(char *&buf, Bool_t x)
Definition Bytes.h:55
#define SafeDelete(p)
Definition RConfig.hxx:538
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define h(i)
Definition RSha256.hxx:106
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Definition RtypesCore.h:63
unsigned short UShort_t
Definition RtypesCore.h:40
int Int_t
Definition RtypesCore.h:45
short Version_t
Definition RtypesCore.h:65
long Long_t
Definition RtypesCore.h:54
unsigned int UInt_t
Definition RtypesCore.h:46
float Float_t
Definition RtypesCore.h:57
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:117
long long Long64_t
Definition RtypesCore.h:69
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:374
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gDirectory
Definition TDirectory.h:384
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
void SysError(const char *location, const char *msgfmt,...)
Use this function in case a system (OS or GUI) related error occurred.
Definition TError.cxx:196
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:229
const Int_t kBEGIN
Definition TFile.cxx: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
@ kCanDelete
Definition TObject.h:373
R__EXTERN TPluginManager * gPluginMgr
Long64_t fBytesRead
Definition TProof.h:171
void cd(Int_t id=-1)
TUrl fUrl
Definition TProof.h:250
void Print(Option_t *option="") const override
Int_t gDebug
Definition TROOT.cxx:622
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:414
void ReadBuffer(char *&buffer) override
TClass * IsA() const override
Definition TStringLong.h:20
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2503
@ kDefault
Definition TSystem.h:243
@ kFileExists
Definition TSystem.h:52
@ kReadPermission
Definition TSystem.h:55
@ kWritePermission
Definition TSystem.h:54
Bool_t R_ISDIR(Int_t mode)
Definition TSystem.h:123
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
R__EXTERN void **(* gThreadTsd)(void *, Int_t)
R__EXTERN TVirtualMonitoringWriter * gMonitoringWriter
#define R__LOCKGUARD(mutex)
#define gPerfStats
#define R__WRITE_LOCKGUARD(mutex)
#define R__READ_LOCKGUARD(mutex)
#define O_BINARY
Definition civetweb.c:912
#define snprintf
Definition civetweb.c:1540
std::optional< TKeyMapNode > Next()
Definition TFile.cxx: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:2038
static Bool_t AddRule(const char *rule)
Add a schema evolution customization rule.
Definition TClass.cxx:1982
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:5002
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:3074
virtual bool UseRWLock(Bool_t enable=true)
Set this collection to use a RW lock upon access, making it thread safe.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
static void GetDateTime(UInt_t datetime, Int_t &date, Int_t &time)
Static function that returns the date and time.
Definition TDatime.cxx:431
void ReadBuffer(char *&buffer)
Decode Date/Time from output buffer, used by I/O system.
Definition TDatime.cxx:278
A ROOT file is structured in Directories (like a file system).
void Close(Option_t *option="") override
Delete all objects from memory and directory structure itself.
Bool_t cd() override
Change current directory to "this" directory.
Bool_t IsWritable() const override
void Delete(const char *namecycle="") override
Delete Objects or/and keys in a directory.
Int_t ReadKeys(Bool_t forceRead=kTRUE) override
Read the linked list of keys.
TDatime fDatimeM
Date and time of last modification.
Int_t fNbytesKeys
Number of bytes for the keys.
Int_t GetNkeys() const override
Long64_t fSeekKeys
Location of Keys record on file.
Int_t Sizeof() const override
Return the size in bytes of the directory header.
Long64_t fSeekParent
Location of parent directory on file.
void BuildDirectoryFile(TFile *motherFile, TDirectory *motherDir)
Initialise directory to defaults.
Int_t Write(const char *name=nullptr, Int_t opt=0, Int_t bufsize=0) override
Write all objects in memory to disk.
Long64_t fSeekDir
Location of directory on file.
Int_t fNbytesName
Number of bytes in TNamed at creation time.
TDatime fDatimeC
Date and time when directory is created.
Bool_t fWritable
True if directory is writable.
TObject * Get(const char *namecycle) override
Return pointer to object identified by namecycle.
void FillBuffer(char *&buffer) override
Encode directory header into output buffer.
void SetWritable(Bool_t writable=kTRUE) override
Set the new value of fWritable recursively.
TList * fKeys
Pointer to keys list in memory.
void ls(Option_t *option="") const override
List Directory contents.
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
Describe directory structure in memory.
Definition TDirectory.h:45
virtual TList * GetList() const
Definition TDirectory.h:222
void SetName(const char *newname) override
Set the name for directory If the directory name is changed after the directory was written once,...
TUUID fUUID
Definition TDirectory.h:143
virtual TObject * Remove(TObject *)
Remove an object from the in-memory list.
TList * fList
Definition TDirectory.h:142
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
A cache when reading files over the network.
virtual void Close(Option_t *option="")
Close out any threads or asynchronous fetches used by the underlying implementation.
virtual void SetFile(TFile *file, TFile::ECacheAction action=TFile::kDisconnect)
Set the file using this cache and reset the current blocks (if any).
A cache when writing files over the network.
virtual Bool_t Flush()
Flush the current write buffer to the file.
Class holding info about the file being opened.
Definition TFile.h:441
TFile * fFile
TFile instance of the file being opened.
Definition TFile.h:449
Int_t GetNetOpt() const
Definition TFile.h:468
TFile * GetFile() const
Definition TFile.h:459
const char * GetOpt() const
Definition TFile.h:466
Bool_t Matches(const char *name)
Return kTRUE if this async request matches the open request specified by 'url'.
Definition TFile.cxx:4838
Int_t GetCompress() const
Definition TFile.h:467
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:4659
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:4802
static void IncrementFileCounter()
Definition TFile.cxx:4668
static Bool_t ShrinkCacheFileDir(Long64_t shrinkSize, Long_t cleanupInteval=0)
Try to shrink the cache to the desired size.
Definition TFile.cxx:4714
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:4653
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:3784
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:4600
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:3647
virtual Bool_t Matches(const char *name)
Return kTRUE if 'url' matches the coordinates of this file.
Definition TFile.cxx:4814
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:4631
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:3774
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:4656
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:4662
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:4554
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:4782
static void CpProgress(Long64_t bytesread, Long64_t size, TStopwatch &watch)
Print file copy progress.
Definition TFile.cxx:5023
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:4622
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:354
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:4647
~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:4665
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:3528
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:3805
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:4792
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:4399
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:4702
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:3834
virtual Long64_t GetBytesWritten() const
Return the total number of bytes written so far to the file.
Definition TFile.cxx:4614
ERelativeTo
Definition TFile.h:282
@ kBeg
Definition TFile.h:282
Int_t fCompress
Compression level and algorithm.
Definition TFile.h:163
static TFile *& CurrentFile()
Return the current ROOT file if any.
Definition TFile.cxx: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:318
Int_t fNbytesFree
Number of bytes for free segments structure.
Definition TFile.h:164
Int_t fD
File descriptor.
Definition TFile.h:161
static constexpr Version_t Class_Version()
Definition TFile.h:431
virtual void ResetErrno() const
Method resetting the errno.
Definition TFile.cxx: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:4545
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:4869
EFileType
File type.
Definition TFile.h:285
@ kNet
Definition TFile.h:285
virtual void ShowStreamerInfo()
Show the StreamerInfo of all classes written to this file.
Definition TFile.cxx:3792
virtual Long64_t SysSeek(Int_t fd, Long64_t offset, Int_t whence)
Interface to system lseek.
Definition TFile.cxx:4573
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:4591
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:4529
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:4772
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:5051
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:5242
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:5256
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:3406
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:4131
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:4674
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:431
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:283
static TFile * OpenFromCache(const char *name, Option_t *="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Open a file for reading through the file cache.
Definition TFile.cxx:3916
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:4562
static Int_t GetFileReadCalls()
Static function returning the total number of read calls from all files.
Definition TFile.cxx:4639
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:205
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:475
virtual void SysError(const char *method, const char *msgfmt,...) const
Issue system error message.
Definition TObject.cxx:1085
R__ALWAYS_INLINE Bool_t IsOnHeap() const
Definition TObject.h:158
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:226
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:159
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:864
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1099
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:875
void MakeZombie()
Definition TObject.h:53
Wrapper for PCRE library (Perl Compatible Regular Expressions).
Definition TPRegexp.h:97
Longptr_t ExecPlugin(int nargs)
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition TProcessID.h:74
Int_t IncrementCount()
Increase the reference count to this object.
void Clear(Option_t *option="") override
delete the TObjArray pointing to referenced objects this function is called by TFile::Close("R")
void CheckInit()
Initialize fObjects.
static TObjArray * GetPIDs()
static: returns array of TProcessIDs
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
Int_t DecrementCount()
The reference fCount is used to delete the TProcessID in the TFile destructor when fCount = 0.
static TProcessID * GetPID()
static: returns pointer to current TProcessID
static Int_t IncreaseDirLevel()
Increase the indentation level for ls().
Definition TROOT.cxx:2913
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:2921
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition TROOT.cxx:3082
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2774
Sequenceable collection abstract base class.
Stopwatch class.
Definition TStopwatch.h:28
UInt_t GetBaseCheckSum()
void SetBaseCheckSum(UInt_t cs)
Describe one element (data member) to be Streamed.
Describes a persistent version of a class.
static TClass * Class()
Basic string class.
Definition TString.h:139
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition TString.cxx:457
const char * Data() const
Definition TString.h:376
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:704
@ kIgnoreCase
Definition TString.h:277
void ToUpper()
Change string to upper case.
Definition TString.cxx:1195
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:623
Bool_t IsNull() const
Definition TString.h:414
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
virtual void ReadBuffer(char *&buffer)
Read string from I/O buffer.
Definition TString.cxx:1331
virtual FILE * TempFileName(TString &base, const char *dir=nullptr, const char *suffix=nullptr)
Create a secure temporary file by appending a unique 6 letter string to base.
Definition TSystem.cxx:1511
virtual const char * GetMakeSharedLib() const
Return the command line use to make a shared library.
Definition TSystem.cxx:3969
virtual Int_t RedirectOutput(const char *name, const char *mode="a", RedirectHandle_t *h=nullptr)
Redirect standard output (stdout, stderr) to the specified file.
Definition TSystem.cxx:1727
virtual void IgnoreInterrupt(Bool_t ignore=kTRUE)
If ignore is true ignore the interrupt signal, else restore previous behaviour.
Definition TSystem.cxx:602
virtual int Symlink(const char *from, const char *to)
Create a symbolic link from file1 to file2.
Definition TSystem.cxx:1380
static void ResetErrno()
Static function resetting system error number.
Definition TSystem.cxx:284
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1286
static Int_t GetErrno()
Static function returning system error number.
Definition TSystem.cxx:276
virtual int Chmod(const char *file, UInt_t mode)
Set the file permission bits. Returns -1 in case or error, 0 otherwise.
Definition TSystem.cxx:1520
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition TSystem.cxx:857
virtual void * OpenDirectory(const char *name)
Open a directory.
Definition TSystem.cxx:848
virtual int GetPid()
Get process id.
Definition TSystem.cxx:718
virtual int CopyFile(const char *from, const char *to, Bool_t overwrite=kFALSE)
Copy a file.
Definition TSystem.cxx:1353
virtual const char * GetIncludePath()
Get the list of include path.
Definition TSystem.cxx:3986
virtual void ShowOutput(RedirectHandle_t *h)
Display the content associated with the redirection described by the opaque handle 'h'.
Definition TSystem.cxx:1737
virtual Bool_t IsPathLocal(const char *path)
Returns TRUE if the url in 'path' points to the local file system.
Definition TSystem.cxx:1317
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Definition TSystem.cxx:918
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition TSystem.cxx:653
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1869
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition TSystem.cxx:1410
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition TSystem.cxx:1093
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1308
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition TSystem.cxx:865
virtual Bool_t ChangeDirectory(const char *path)
Change directory.
Definition TSystem.cxx:874
virtual int Rename(const char *from, const char *to)
Rename a file.
Definition TSystem.cxx:1362
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition TSystem.cxx:946
virtual const char * GetFlagsDebug() const
Return the debug flags.
Definition TSystem.cxx:3940
virtual Bool_t IsAbsoluteFileName(const char *dir)
Return true if dir is an absolute pathname.
Definition TSystem.cxx:963
virtual const char * GetObjExt() const
Get the object file extension.
Definition TSystem.cxx:4034
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition TSystem.cxx:437
virtual const char * WorkingDirectory()
Return working directory.
Definition TSystem.cxx:883
virtual const char * GetLibraries(const char *regexp="", const char *option="", Bool_t isRegexp=kTRUE)
Return a space separated list of loaded shared libraries.
Definition TSystem.cxx:2148
virtual const char * HomeDirectory(const char *userName=nullptr)
Return the user's home directory.
Definition TSystem.cxx:899
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:416
virtual const char * GetSoExt() const
Get the shared library extension.
Definition TSystem.cxx:4026
virtual TString GetDirName(const char *pathname)
Return the directory name in pathname.
Definition TSystem.cxx:1044
virtual int Unlink(const char *name)
Unlink, i.e.
Definition TSystem.cxx:1393
virtual const char * GetFlagsOpt() const
Return the optimization flags.
Definition TSystem.cxx:3948
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition TTimeStamp.h:45
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
Definition TUUID.h:42
void ReadBuffer(char *&buffer)
Stream UUID from input buffer.
Definition TUUID.cxx:291
void FillBuffer(char *&buffer)
Stream UUID into output buffer.
Definition TUUID.cxx:275
This class represents a WWW compatible URL.
Definition TUrl.h:33
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition TUrl.cxx:391
const char * GetFile() const
Definition TUrl.h:69
const char * GetValueFromOptions(const char *key) const
Return a value for a given key from the URL options.
Definition TUrl.cxx:661
const char * GetHostFQDN() const
Return fully qualified domain name of url host.
Definition TUrl.cxx:473
const char * GetOptions() const
Definition TUrl.h:71
const char * GetProtocol() const
Definition TUrl.h:64
Int_t GetPort() const
Definition TUrl.h:78
Bool_t HasOption(const char *key) const
Returns true if the given key appears in the URL options list.
Definition TUrl.cxx:684
virtual Bool_t SendFileReadProgress(TFile *)
virtual Bool_t SendFileCloseEvent(TFile *)
virtual Bool_t SendFileWriteProgress(TFile *)
Abstract Interface class describing Streamer information for one class.
std::ostream & Info()
Definition hadd.cxx:171
const Int_t n
Definition legend1.C:16
TF1 * f1
Definition legend1.C:11
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
R__EXTERN TVirtualRWMutex * gCoreMutex
@ kFileThreadSlot
@ kSTLmap
Definition ESTLType.h:33
@ kSTLmultimap
Definition ESTLType.h:34
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
bool IsStdPair(std::string_view name)
Definition TClassEdit.h:231
ROOT::ESTLType IsSTLCont(std::string_view type)
type : type name: vector<list<classA,allocator>,allocator> result: 0 : not stl container code of cont...
int GetSplit(const char *type, std::vector< std::string > &output, int &nestedLoc, EModType mode=TClassEdit::kNone)
Stores in output (after emptying it) the split type.
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123
static const char * what
Definition stlLoader.cc:5
@ kUndefined
Undefined compression algorithm (must be kept the last of the list in case a new algorithm is added).
@ kUseMin
Compression level reserved when we are not sure what to use (1 is for the fastest compression)
Definition Compression.h:72
Simple struct of the return value of GetStreamerInfoListImpl.
Definition TFile.h:224
th1 Draw()
TLine l
Definition textangle.C:4