Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
TFile.cxx
Go to the documentation of this file.
1// @(#)root/io:$Id: 3a19890259ad6443ee313e090166614971ad4296 $
2// Author: Rene Brun 28/11/94
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/**
13\file TFile.cxx
14\class TFile
15\ingroup IO
16\brief A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-like logical structure, possibly including subdirectory hierarchies.
17\sa \ref IO
18\sa \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
82</details>
83*/
84
85#include <ROOT/RConfig.hxx>
86
87#ifdef R__LINUX
88// for posix_fadvise
89#ifndef _XOPEN_SOURCE
90#define _XOPEN_SOURCE 600
91#endif
92#endif
93#include <fcntl.h>
94#include <errno.h>
95#include <sys/stat.h>
96#ifndef WIN32
97#include <unistd.h>
98#ifndef R__FBSD
99#include <sys/xattr.h>
100#endif
101#else
102# define ssize_t int
103# include <io.h>
104# include <sys/types.h>
105#endif
106
107#include "Bytes.h"
108#include "Compression.h"
109#include "RConfigure.h"
110#include "Strlen.h"
111#include "strlcpy.h"
112#include "snprintf.h"
113#include "TArrayC.h"
114#include "TBuffer.h"
115#include "TClass.h"
116#include "TClassEdit.h"
117#include "TClassTable.h"
118#include "TDatime.h"
119#include "TError.h"
120#include "TFile.h"
121#include "TFileCacheRead.h"
122#include "TFileCacheWrite.h"
123#include "TFree.h"
124#include "TInterpreter.h"
125#include "TKey.h"
126#include "TMakeProject.h"
127#include "TPluginManager.h"
128#include "TProcessUUID.h"
129#include "TRegexp.h"
130#include "TPRegexp.h"
131#include "TROOT.h"
132#include "TStreamerInfo.h"
133#include "TStreamerElement.h"
134#include "TSystem.h"
135#include "TTimeStamp.h"
136#include "TVirtualPerfStats.h"
137#include "TArchiveFile.h"
138#include "TEnv.h"
139#include "TVirtualMonitoring.h"
140#include "TVirtualMutex.h"
141#include "TMap.h"
142#include "TMathBase.h"
143#include "TObjString.h"
144#include "TStopwatch.h"
145#include "compiledata.h"
146#include <cmath>
147#include <iostream>
148#include <set>
149#include "TSchemaRule.h"
150#include "TSchemaRuleSet.h"
151#include "TThreadSlots.h"
152#include "TGlobal.h"
154#include <memory>
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 TXNetFile::Init for an example.
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 Int_t nb = sizeof(Int_t);
1502 char * buffer = new char[nb];
1503 char * psave = buffer;
1504 tobuf(buffer, nbytes);
1505 if (last == fEND-1) fEND = nfirst;
1506 Seek(nfirst);
1507 // We could not update the meta data for this block on the file.
1508 // This is not fatal as this only means that we won't get it 'right'
1509 // if we ever need to Recover the file before the block is actually
1510 // (attempted to be reused.
1511 // coverity[unchecked_value]
1513 if (fMustFlush) Flush();
1514 delete [] psave;
1515}
1516
1517////////////////////////////////////////////////////////////////////////////////
1518/// List the contents of a file sequentially.
1519/// For each logical record found, it prints:
1520///
1521/// Date/Time Record_Adress Logical_Record_Length ClassName CompressionFactor
1522///
1523/// Example of output
1524///
1525/// 20010404/150437 At:64 N=150 TFile
1526/// 20010404/150440 At:214 N=28326 TBasket CX = 1.13
1527/// 20010404/150440 At:28540 N=29616 TBasket CX = 1.08
1528/// 20010404/150440 At:58156 N=29640 TBasket CX = 1.08
1529/// 20010404/150440 At:87796 N=29076 TBasket CX = 1.10
1530/// 20010404/150440 At:116872 N=10151 TBasket CX = 3.15
1531/// 20010404/150441 At:127023 N=28341 TBasket CX = 1.13
1532/// 20010404/150441 At:155364 N=29594 TBasket CX = 1.08
1533/// 20010404/150441 At:184958 N=29616 TBasket CX = 1.08
1534/// 20010404/150441 At:214574 N=29075 TBasket CX = 1.10
1535/// 20010404/150441 At:243649 N=9583 TBasket CX = 3.34
1536/// 20010404/150442 At:253232 N=28324 TBasket CX = 1.13
1537/// 20010404/150442 At:281556 N=29641 TBasket CX = 1.08
1538/// 20010404/150442 At:311197 N=29633 TBasket CX = 1.08
1539/// 20010404/150442 At:340830 N=29091 TBasket CX = 1.10
1540/// 20010404/150442 At:369921 N=10341 TBasket CX = 3.09
1541/// 20010404/150442 At:380262 N=509 TH1F CX = 1.93
1542/// 20010404/150442 At:380771 N=1769 TH2F CX = 4.32
1543/// 20010404/150442 At:382540 N=1849 TProfile CX = 1.65
1544/// 20010404/150442 At:384389 N=18434 TNtuple CX = 4.51
1545/// 20010404/150442 At:402823 N=307 KeysList
1546/// 20010404/150443 At:403130 N=4548 StreamerInfo CX = 3.65
1547/// 20010404/150443 At:407678 N=86 FreeSegments
1548/// 20010404/150443 At:407764 N=1 END
1549///
1550/// If the parameter opt contains "forComp", the Date/Time is omitted
1551/// and the decompressed size is also printed.
1552///
1553/// Record_Adress Logical_Record_Length Key_Length Object_Record_Length ClassName CompressionFactor
1554///
1555/// If the parameter opt contains "extended", the name and title of the keys are added:
1556/// 20200820/155031 At:100 N=180 TFile name: hsimple.root title: Demo ROOT file with histograms
1557/// 220200820/155032 At:280 N=28880 TBasket CX = 1.11 name: random title: ntuple
1558/// 220200820/155032 At:29160 N=29761 TBasket CX = 1.08 name: px title: ntuple
1559/// 220200820/155032 At:58921 N=29725 TBasket CX = 1.08 name: py title: ntuple
1560/// 220200820/155032 At:88646 N=29209 TBasket CX = 1.10 name: pz title: ntuple
1561/// 220200820/155032 At:117855 N=10197 TBasket CX = 3.14 name: i title: ntuple
1562/// ...
1563/// 20200820/155032 At:405110 N=808 TNtuple CX = 3.53 name: ntuple title: Demo ntuple
1564/// 20200820/155706 At:405918 N=307 KeysList name: hsimple.root title: Demo ROOT file with histograms
1565/// 20200820/155032 At:406225 N=8556 StreamerInfo CX = 3.42 name: StreamerInfo title: Doubly linked list
1566/// 20200820/155708 At:414781 N=86 FreeSegments name: hsimple.root title: Demo ROOT file with histograms
1567/// 20200820/155708 At:414867 N=1 END
1568///
1569/// Note: The combined size of the classname, name and title is truncated to 476 characters (a little more for regular keys of small files)
1570///
1571
1573void TFile::Map(Option_t *opt)
1574{
1575 TString options(opt);
1576 options.ToLower();
1577 bool forComp = options.Contains("forcomp");
1578 bool extended = options.Contains("extended");
1579
1580 Short_t keylen,cycle;
1581 UInt_t datime;
1582 Int_t nbytes,date,time,objlen;
1583 date = 0;
1584 time = 0;
1586 char *buffer;
1587 char nwhc;
1589
1590 constexpr Int_t nwheader = 512;
1591
1592 char header[nwheader];
1593 char classname[512];
1594 char keyname[512];
1595 char keytitle[512];
1597
1598 unsigned char nDigits = std::log10(fEND) + 1;
1599
1600 while (idcur < fEND) {
1601 Seek(idcur);
1603 if (idcur+nread >= fEND) nread = fEND-idcur-1;
1604 if (ReadBuffer(header, nread)) {
1605 // ReadBuffer returns kTRUE in case of failure.
1606 Warning("Map","%s: failed to read the key data from disk at %lld.",
1607 GetName(),idcur);
1608 break;
1609 }
1610
1611 buffer=header;
1612 frombuf(buffer, &nbytes);
1613 if (!nbytes) {
1614 Printf("Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes);
1615 date = 0; time = 0;
1616 break;
1617 }
1618 if (nbytes < 0) {
1619 Printf("Address = %lld\tNbytes = %d\t=====G A P===========", idcur, nbytes);
1620 idcur -= nbytes;
1621 Seek(idcur);
1622 continue;
1623 }
1625 frombuf(buffer, &versionkey);
1626 frombuf(buffer, &objlen);
1627 frombuf(buffer, &datime);
1628 frombuf(buffer, &keylen);
1629 frombuf(buffer, &cycle);
1630 if (versionkey > 1000) {
1631 frombuf(buffer, &seekkey);
1632 frombuf(buffer, &seekpdir);
1633 } else {
1634 Int_t skey,sdir;
1635 frombuf(buffer, &skey); seekkey = (Long64_t)skey;
1636 frombuf(buffer, &sdir); seekpdir = (Long64_t)sdir;
1637 }
1638 frombuf(buffer, &nwhc);
1639 if ( ((buffer-header) + nwhc) > nwheader ) // Don't read past the end of the part of the key we have read.
1640 nwhc = nwheader - (buffer-header);
1641 for (int i = 0;i < nwhc; i++) frombuf(buffer, &classname[i]);
1642 classname[(int)nwhc] = '\0'; //cast to avoid warning with gcc3.4
1643 if (idcur == fSeekFree) strlcpy(classname,"FreeSegments",512);
1644 if (idcur == fSeekInfo) strlcpy(classname,"StreamerInfo",512);
1645 if (idcur == fSeekKeys) strlcpy(classname,"KeysList",512);
1646
1647 if (extended) {
1648 if ( (buffer-header) >= nwheader )
1649 nwhc = 0;
1650 else {
1651 frombuf(buffer, &nwhc);
1652 if (nwhc < 0)
1653 nwhc = 0;
1654 else if ( ((buffer-header) + nwhc) > nwheader ) // Don't read past the end of the part of the key we have read.
1655 nwhc = nwheader - (buffer-header);
1656 }
1657 for (int i = 0;i < nwhc; i++) frombuf(buffer, &keyname[i]);
1658 keyname[(int)nwhc] = '\0'; //cast to avoid warning with gcc3.4
1659
1660 if ( (buffer-header) >= nwheader )
1661 nwhc = 0;
1662 else {
1663 frombuf(buffer, &nwhc);
1664 if (nwhc < 0)
1665 nwhc = 0;
1666 else if ( ((buffer-header) + nwhc) > nwheader ) // Don't read past the end of the part of the key we have read.
1667 nwhc = nwheader - (buffer-header);
1668 }
1669 for (int i = 0;i < nwhc; i++) frombuf(buffer, &keytitle[i]);
1670 keytitle[(int)nwhc] = '\0'; //cast to avoid warning with gcc3.4
1671
1672 extrainfo.Form(" name: %-16s title: %s", keyname, keytitle);
1673 }
1674
1676 if (!forComp) {
1677 if (objlen != nbytes - keylen) {
1679 Printf("%d/%06d At:%-*lld N=%-8d %-14s CX = %5.2f %s", date, time, nDigits + 1, idcur, nbytes, classname,
1680 cx, extrainfo.Data());
1681 } else {
1682 Printf("%d/%06d At:%-*lld N=%-8d %-14s %s", date, time, nDigits + 1, idcur, nbytes, classname, extrainfo.Data());
1683 }
1684 } else {
1685 // Printing to help compare two files.
1686 if (objlen != nbytes - keylen) {
1688 Printf("At:%-*lld N=%-8d K=%-3d O=%-8d %-14s CX = %5.2f %s", nDigits+1, idcur, nbytes, keylen, objlen, classname, cx, extrainfo.Data());
1689 } else {
1690 Printf("At:%-*lld N=%-8d K=%-3d O=%-8d %-14s CX = 1 %s", nDigits+1, idcur, nbytes, keylen, objlen, classname, extrainfo.Data());
1691 }
1692 }
1693 idcur += nbytes;
1694 }
1695 if (!forComp)
1696 Printf("%d/%06d At:%-*lld N=%-8d %-14s",date,time, nDigits+1, idcur,1,"END");
1697 else
1698 Printf("At:%-*lld N=%-8d K= O= %-14s", nDigits+1, idcur,1,"END");
1699}
1700
1701////////////////////////////////////////////////////////////////////////////////
1702/// Paint all objects in the file.
1705{
1706 GetList()->R__FOR_EACH(TObject,Paint)(option);
1707}
1708
1709////////////////////////////////////////////////////////////////////////////////
1710/// Print all objects in the file.
1712void TFile::Print(Option_t *option) const
1713{
1714 Printf("TFile: name=%s, title=%s, option=%s", GetName(), GetTitle(), GetOption());
1715 GetList()->R__FOR_EACH(TObject,Print)(option);
1716}
1717
1718////////////////////////////////////////////////////////////////////////////////
1719/// Read a buffer from the file at the offset 'pos' in the file.
1720///
1721/// Returns kTRUE in case of failure.
1722/// Compared to ReadBuffer(char*, Int_t), this routine does _not_
1723/// change the cursor on the physical file representation (fD)
1724/// if the data is in this TFile's cache.
1726Bool_t TFile::ReadBuffer(char *buf, Long64_t pos, Int_t len)
1727{
1728 if (IsOpen()) {
1729
1730 SetOffset(pos);
1731
1732 Int_t st;
1733 Double_t start = 0;
1734 if (gPerfStats) start = TTimeStamp();
1735
1736 if ((st = ReadBufferViaCache(buf, len))) {
1737 if (st == 2)
1738 return kTRUE;
1739 return kFALSE;
1740 }
1741
1742 Seek(pos);
1743 ssize_t siz;
1744
1745 while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
1746 ResetErrno();
1747
1748 if (siz < 0) {
1749 SysError("ReadBuffer", "error reading from file %s", GetName());
1750 return kTRUE;
1751 }
1752 if (siz != len) {
1753 Error("ReadBuffer", "error reading all requested bytes from file %s, got %ld of %d",
1754 GetName(), (Long_t)siz, len);
1755 return kTRUE;
1756 }
1757 fBytesRead += siz;
1758 fgBytesRead += siz;
1759 fReadCalls++;
1760 fgReadCalls++;
1761
1764 if (gPerfStats) {
1765 gPerfStats->FileReadEvent(this, len, start);
1766 }
1767 return kFALSE;
1768 }
1769 return kTRUE;
1770}
1771
1772////////////////////////////////////////////////////////////////////////////////
1773/// Read a buffer from the file. This is the basic low level read operation.
1774/// Returns kTRUE in case of failure.
1777{
1778 if (IsOpen()) {
1779
1780 Int_t st;
1781 if ((st = ReadBufferViaCache(buf, len))) {
1782 if (st == 2)
1783 return kTRUE;
1784 return kFALSE;
1785 }
1786
1787 ssize_t siz;
1788 Double_t start = 0;
1789
1790 if (gPerfStats) start = TTimeStamp();
1791
1792 while ((siz = SysRead(fD, buf, len)) < 0 && GetErrno() == EINTR)
1793 ResetErrno();
1794
1795 if (siz < 0) {
1796 SysError("ReadBuffer", "error reading from file %s", GetName());
1797 return kTRUE;
1798 }
1799 if (siz != len) {
1800 Error("ReadBuffer", "error reading all requested bytes from file %s, got %ld of %d",
1801 GetName(), (Long_t)siz, len);
1802 return kTRUE;
1803 }
1804 fBytesRead += siz;
1805 fgBytesRead += siz;
1806 fReadCalls++;
1807 fgReadCalls++;
1808
1811 if (gPerfStats) {
1812 gPerfStats->FileReadEvent(this, len, start);
1813 }
1814 return kFALSE;
1815 }
1816 return kTRUE;
1817}
1818
1819////////////////////////////////////////////////////////////////////////////////
1820/// Read the nbuf blocks described in arrays pos and len.
1821///
1822/// The value pos[i] is the seek position of block i of length len[i].
1823/// Note that for nbuf=1, this call is equivalent to TFile::ReafBuffer.
1824/// This function is overloaded by TNetFile, TWebFile, etc.
1825/// Returns kTRUE in case of failure.
1828{
1829 // called with buf=0, from TFileCacheRead to pass list of readahead buffers
1830 if (!buf) {
1831 for (Int_t j = 0; j < nbuf; j++) {
1832 if (ReadBufferAsync(pos[j], len[j])) {
1833 return kTRUE;
1834 }
1835 }
1836 return kFALSE;
1837 }
1838
1839 Int_t k = 0;
1842 fCacheRead = nullptr;
1843 Long64_t curbegin = pos[0];
1844 Long64_t cur;
1845 char *buf2 = nullptr;
1846 Int_t i = 0, n = 0;
1847 while (i < nbuf) {
1848 cur = pos[i]+len[i];
1850 if (cur -curbegin < fgReadaheadSize) {n++; i++; bigRead = kFALSE;}
1851 if (bigRead || (i>=nbuf)) {
1852 if (n == 0) {
1853 //if the block to read is about the same size as the read-ahead buffer
1854 //we read the block directly
1855 Seek(pos[i]);
1856 result = ReadBuffer(&buf[k], len[i]);
1857 if (result) break;
1858 k += len[i];
1859 i++;
1860 } else {
1861 //otherwise we read all blocks that fit in the read-ahead buffer
1862 Seek(curbegin);
1863 if (!buf2) buf2 = new char[fgReadaheadSize];
1864 //we read ahead
1865 Long64_t nahead = pos[i-1]+len[i-1]-curbegin;
1867 if (result) break;
1868 //now copy from the read-ahead buffer to the cache
1869 Int_t kold = k;
1870 for (Int_t j=0;j<n;j++) {
1871 memcpy(&buf[k],&buf2[pos[i-n+j]-curbegin],len[i-n+j]);
1872 k += len[i-n+j];
1873 }
1874 Int_t nok = k-kold;
1875 Long64_t extra = nahead-nok;
1876 fBytesReadExtra += extra;
1877 fBytesRead -= extra;
1878 fgBytesRead -= extra;
1879 n = 0;
1880 }
1881 curbegin = i < nbuf ? pos[i] : 0;
1882 }
1883 }
1884 if (buf2) delete [] buf2;
1885 fCacheRead = old;
1886 return result;
1887}
1888
1889////////////////////////////////////////////////////////////////////////////////
1890/// Read buffer via cache.
1891///
1892/// Returns 0 if the requested block is not in the cache, 1 in case read via
1893/// cache was successful, 2 in case read via cache failed.
1896{
1897 Long64_t off = GetRelOffset();
1898 if (fCacheRead) {
1899 Int_t st = fCacheRead->ReadBuffer(buf, off, len);
1900 if (st < 0)
1901 return 2; // failure reading
1902 else if (st == 1) {
1903 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
1904 SetOffset(off + len);
1905 return 1;
1906 }
1907 // fOffset might have been changed via TFileCacheRead::ReadBuffer(), reset it
1908 Seek(off);
1909 } else {
1910 // if write cache is active check if data still in write cache
1911 if (fWritable && fCacheWrite) {
1912 if (fCacheWrite->ReadBuffer(buf, off, len) == 0) {
1913 SetOffset(off + len);
1914 return 1;
1915 }
1916 // fOffset might have been changed via TFileCacheWrite::ReadBuffer(), reset it
1917 SetOffset(off);
1918 }
1919 }
1920
1921 return 0;
1922}
1923
1924////////////////////////////////////////////////////////////////////////////////
1925/// Read the FREE linked list.
1926///
1927/// Every file has a linked list (fFree) of free segments.
1928/// This linked list has been written on the file via WriteFree
1929/// as a single data record.
1931void TFile::ReadFree()
1932{
1933 // Avoid problem with file corruption.
1935 fNbytesFree = 0;
1936 return;
1937 }
1938 TKey *headerfree = new TKey(fSeekFree, fNbytesFree, this);
1939 headerfree->ReadFile();
1940 char *buffer = headerfree->GetBuffer();
1941 headerfree->ReadKeyBuffer(buffer);
1942 buffer = headerfree->GetBuffer();
1943 while (1) {
1944 TFree *afree = new TFree();
1945 afree->ReadBuffer(buffer);
1946 fFree->Add(afree);
1947 if (afree->GetLast() > fEND) break;
1948 }
1949 delete headerfree;
1950}
1951
1952////////////////////////////////////////////////////////////////////////////////
1953/// The TProcessID with number pidf is read from this file.
1954///
1955/// If the object is not already entered in the gROOT list, it is added.
1958{
1959 TProcessID *pid = nullptr;
1961 if (pidf < pids->GetSize()) pid = (TProcessID *)pids->UncheckedAt(pidf);
1962 if (pid) {
1963 pid->CheckInit();
1964 return pid;
1965 }
1966
1967 //check if fProcessIDs[uid] is set in file
1968 //if not set, read the process uid from file
1969 char pidname[32];
1970 snprintf(pidname,32,"ProcessID%d",pidf);
1971 pid = (TProcessID *)Get(pidname);
1972 if (gDebug > 0) {
1973 printf("ReadProcessID, name=%s, file=%s, pid=%zx\n",pidname,GetName(),(size_t)pid);
1974 }
1975 if (!pid) {
1976 //file->Error("ReadProcessID","Cannot find %s in file %s",pidname,file->GetName());
1977 return pid;
1978 }
1979
1980 //check that a similar pid is not already registered in fgPIDs
1982 TIter next(pidslist);
1983 TProcessID *p;
1984 bool found = false;
1985
1986 {
1988 while ((p = (TProcessID*)next())) {
1989 if (!strcmp(p->GetTitle(),pid->GetTitle())) {
1990 found = true;
1991 break;
1992 }
1993 }
1994 }
1995
1996 if (found) {
1997 delete pid;
1998 pids->AddAtAndExpand(p,pidf);
1999 p->IncrementCount();
2000 return p;
2001 }
2002
2003 pids->AddAtAndExpand(pid,pidf);
2004 pid->IncrementCount();
2005
2006 {
2008 pidslist->Add(pid);
2009 Int_t ind = pidslist->IndexOf(pid);
2010 pid->SetUniqueID((UInt_t)ind);
2011 }
2012
2013 return pid;
2014}
2015
2016
2017////////////////////////////////////////////////////////////////////////////////
2018/// Attempt to recover file if not correctly closed
2019///
2020/// The function returns the number of keys that have been recovered.
2021/// If no keys can be recovered, the file will be declared Zombie by
2022/// the calling function. This function is automatically called when
2023/// opening a file.
2024/// If the file is open in read only mode, the file is not modified.
2025/// If open in update mode and the function finds something to recover,
2026/// a new directory header is written to the file. When opening the file gain
2027/// no message from Recover will be reported.
2028/// If keys have been recovered, the file is usable and you can safely
2029/// read the corresponding objects.
2030/// If the file is not usable (a zombie), you can test for this case
2031/// with code like:
2032///
2033/// ~~~{.cpp}
2034/// TFile f("myfile.root");
2035/// if (f.IsZombie()) {<actions to take if file is unusable>}
2036/// ~~~
2037///
2038/// If the file has been recovered, the bit kRecovered is set in the TFile object in memory.
2039/// You can test if the file has been recovered with
2040///
2041/// if (f.TestBit(TFile::kRecovered)) {... the file has been recovered}
2042///
2043/// When writing TTrees to a file, it is important to save the Tree header
2044/// at regular intervals (see TTree::AutoSave). If a file containing a Tree
2045/// is recovered, the last Tree header written to the file will be used.
2046/// In this case all the entries in all the branches written before writing
2047/// the header are valid entries.
2048/// One can disable the automatic recovery procedure by setting
2049///
2050/// TFile.Recover 0
2051///
2052/// in the <em>system.rootrc</em> file.
2055{
2056 Short_t keylen,cycle;
2057 UInt_t datime;
2060 char header[1024];
2061 char *buffer, *bufread;
2062 char nwhc;
2064
2065 Long64_t size;
2066 if ((size = GetSize()) == -1) { // NOLINT: silence clang-tidy warnings
2067 Error("Recover", "cannot stat the file %s", GetName());
2068 return 0;
2069 }
2070
2071 fEND = Long64_t(size);
2072
2073 if (fWritable && !fFree) fFree = new TList;
2074
2075 TKey *key;
2076 Int_t nrecov = 0;
2077 nwheader = 1024;
2079
2080 while (idcur < fEND) {
2081 Seek(idcur); // NOLINT: silence clang-tidy warnings
2082 if (idcur+nread >= fEND) nread = fEND-idcur-1;
2083 if (ReadBuffer(header, nread)) { // NOLINT: silence clang-tidy warnings
2084 // ReadBuffer returns kTRUE in case of failure.
2085 Error("Recover","%s: failed to read the key data from disk at %lld.",
2086 GetName(),idcur);
2087 break;
2088 }
2089 buffer = header;
2090 bufread = header;
2091 frombuf(buffer, &nbytes);
2092 if (!nbytes) {
2093 Error("Recover","Address = %lld\tNbytes = %d\t=====E R R O R=======", idcur, nbytes);
2094 break;
2095 }
2096 if (nbytes < 0) {
2097 idcur -= nbytes;
2098 if (fWritable) new TFree(fFree,idcur,idcur-nbytes-1);
2099 Seek(idcur);
2100 continue;
2101 }
2103 frombuf(buffer, &versionkey);
2104 frombuf(buffer, &objlen);
2105 frombuf(buffer, &datime);
2106 frombuf(buffer, &keylen);
2107 frombuf(buffer, &cycle);
2108 if (versionkey > 1000) {
2109 frombuf(buffer, &seekkey);
2110 frombuf(buffer, &seekpdir);
2111 } else {
2112 Int_t skey,sdir;
2113 frombuf(buffer, &skey); seekkey = (Long64_t)skey;
2114 frombuf(buffer, &sdir); seekpdir = (Long64_t)sdir;
2115 }
2116 frombuf(buffer, &nwhc);
2117 char *classname = nullptr;
2118 if (nwhc <= 0 || nwhc > 100) break;
2119 classname = new char[nwhc+1];
2120 int i, nwhci = nwhc;
2121 for (i = 0;i < nwhc; i++) frombuf(buffer, &classname[i]);
2122 classname[nwhci] = '\0';
2124 TClass *tclass = TClass::GetClass(classname);
2125 if (seekpdir == fSeekDir && tclass && !tclass->InheritsFrom(TFile::Class())
2126 && strcmp(classname,"TBasket")) {
2127 key = new TKey(this);
2128 key->ReadKeyBuffer(bufread);
2129 if (!strcmp(key->GetName(),"StreamerInfo")) {
2133 } else {
2134 AppendKey(key);
2135 nrecov++;
2137 Info("Recover", "%s, recovered key %s:%s at address %lld",GetName(),key->GetClassName(),key->GetName(),idcur);
2138 }
2139 }
2140 delete [] classname;
2141 idcur += nbytes;
2142 }
2143 if (fWritable) {
2145 if (max_file_size < fEND) max_file_size = fEND+1000000000;
2146 TFree *last = (TFree*)fFree->Last();
2147 if (last) {
2149 } else {
2151 }
2152 if (nrecov) Write();
2153 }
2154 return nrecov;
2155}
2156
2157////////////////////////////////////////////////////////////////////////////////
2158/// Reopen a file with a different access mode.
2159///
2160/// For example, it is possible to change from READ to
2161/// UPDATE or from NEW, CREATE, RECREATE, UPDATE to READ. Thus the
2162/// mode argument can be either "READ" or "UPDATE". The method returns
2163/// 0 in case the mode was successfully modified, 1 in case the mode
2164/// did not change (was already as requested or wrong input arguments)
2165/// and -1 in case of failure, in which case the file cannot be used
2166/// anymore. The current directory (gFile) is changed to this file.
2169{
2170 cd();
2171
2172 TString opt = mode;
2173 opt.ToUpper();
2174
2175 if (opt != "READ" && opt != "UPDATE") {
2176 Error("ReOpen", "mode must be either READ or UPDATE, not %s", opt.Data());
2177 return 1;
2178 }
2179
2180 if (opt == fOption || (opt == "UPDATE" && fOption == "CREATE"))
2181 return 1;
2182
2183 if (opt == "READ") {
2184 // switch to READ mode
2185
2186 // flush data still in the pipeline and close the file
2187 if (IsOpen() && IsWritable()) {
2189
2190 // save directory key list and header
2191 Save();
2192
2193 TFree *f1 = (TFree*)fFree->First();
2194 if (f1) {
2195 WriteFree(); // write free segments linked list
2196 WriteHeader(); // now write file header
2197 }
2198
2200
2201 // delete free segments from free list
2202 fFree->Delete();
2204
2205 SysClose(fD);
2206 fD = -1;
2207
2209 }
2210
2211 // open in READ mode
2212 fOption = opt; // set fOption before SysOpen() for TNetFile
2213#ifndef WIN32
2214 fD = SysOpen(fRealName, O_RDONLY, 0644);
2215#else
2217#endif
2218 if (fD == -1) {
2219 SysError("ReOpen", "file %s can not be opened in read mode", GetName());
2220 return -1;
2221 }
2223
2224 } else {
2225 // switch to UPDATE mode
2226
2227 // close readonly file
2228 if (IsOpen()) {
2229 SysClose(fD);
2230 fD = -1;
2231 }
2232
2233 // open in UPDATE mode
2234 fOption = opt; // set fOption before SysOpen() for TNetFile
2235#ifndef WIN32
2236 fD = SysOpen(fRealName, O_RDWR | O_CREAT, 0644);
2237#else
2239#endif
2240 if (fD == -1) {
2241 SysError("ReOpen", "file %s can not be opened in update mode", GetName());
2242 return -1;
2243 }
2245
2246 fFree = new TList;
2247 if (fSeekFree > fBEGIN)
2248 ReadFree();
2249 else
2250 Warning("ReOpen","file %s probably not closed, cannot read free segments", GetName());
2251 }
2252
2253 return 0;
2254}
2255
2256////////////////////////////////////////////////////////////////////////////////
2257/// Set position from where to start reading.
2260{
2261 switch (pos) {
2262 case kBeg:
2264 break;
2265 case kCur:
2266 fOffset += offset;
2267 break;
2268 case kEnd:
2269 // this option is not used currently in the ROOT code
2270 if (fArchiveOffset)
2271 Error("SetOffset", "seeking from end in archive is not (yet) supported");
2272 fOffset = fEND + offset; // is fEND really EOF or logical EOF?
2273 break;
2274 }
2275}
2276
2277////////////////////////////////////////////////////////////////////////////////
2278/// Seek to a specific position in the file. Pos it either kBeg, kCur or kEnd.
2281{
2282 int whence = 0;
2283 switch (pos) {
2284 case kBeg:
2285 whence = SEEK_SET;
2287 break;
2288 case kCur:
2289 whence = SEEK_CUR;
2290 break;
2291 case kEnd:
2292 whence = SEEK_END;
2293 // this option is not used currently in the ROOT code
2294 if (fArchiveOffset)
2295 Error("Seek", "seeking from end in archive is not (yet) supported");
2296 break;
2297 }
2299 if ((retpos = SysSeek(fD, offset, whence)) < 0) // NOLINT: silence clang-tidy warnings
2300 SysError("Seek", "cannot seek to position %lld in file %s, retpos=%lld",
2301 offset, GetName(), retpos);
2302
2303 // used by TFileCacheRead::ReadBuffer()
2304 fOffset = retpos;
2305}
2306
2307////////////////////////////////////////////////////////////////////////////////
2308/// See comments for function SetCompressionSettings
2309///
2320}
2321
2322////////////////////////////////////////////////////////////////////////////////
2323/// See comments for function SetCompressionSettings
2326{
2327 if (level < 0) level = 0;
2328 if (level > 99) level = 99;
2329 if (fCompress < 0) {
2330 // if the algorithm is not defined yet use 0 as a default
2331 fCompress = level;
2332 } else {
2333 int algorithm = fCompress / 100;
2335 fCompress = 100 * algorithm + level;
2336 }
2337}
2338
2339////////////////////////////////////////////////////////////////////////////////
2340/// Used to specify the compression level and algorithm.
2341///
2342/// See the TFile constructor for the details.
2347}
2348
2349////////////////////////////////////////////////////////////////////////////////
2350/// Set a pointer to the read cache.
2351///
2352/// <b>This relinquishes ownership</b> of the previous cache, so if you do not
2353/// already have a pointer to the previous cache (and there was a previous
2354/// cache), you ought to retrieve (and delete it if needed) using:
2355///
2356/// TFileCacheRead *older = myfile->GetCacheRead();
2357///
2358/// The action specifies how to behave when detaching a cache from the
2359/// the TFile. If set to (default) kDisconnect, the contents of the cache
2360/// will be flushed when it is removed from the file, and it will disconnect
2361/// the cache object from the file. In almost all cases, this is what you want.
2362/// If you want to disconnect the cache temporarily from this tree and re-attach
2363/// later to the same fil, you can set action to kDoNotDisconnect. This will allow
2364/// things like prefetching to continue in the background while it is no longer the
2365/// default cache for the TTree. Except for a few expert use cases, kDisconnect is
2366/// likely the correct setting.
2367///
2368/// WARNING: if action=kDoNotDisconnect, you MUST delete the cache before TFile.
2369///
2372{
2373 if (tree) {
2374 if (cache) fCacheReadMap->Add(tree, cache);
2375 else {
2376 // The only addition to fCacheReadMap is via an interface that takes
2377 // a TFileCacheRead* so the C-cast is safe.
2379 fCacheReadMap->Remove(tree);
2380 if (tpf && (tpf->GetFile() == this) && (action != kDoNotDisconnect)) tpf->SetFile(0, action);
2381 }
2382 }
2383 if (cache) cache->SetFile(this, action);
2384 else if (!tree && fCacheRead && (action != kDoNotDisconnect)) fCacheRead->SetFile(0, action);
2385 // For backward compatibility the last Cache set is the default cache.
2386 fCacheRead = cache;
2387}
2388
2389////////////////////////////////////////////////////////////////////////////////
2390/// Set a pointer to the write cache.
2391///
2392/// If file is null the existing write cache is deleted.
2395{
2396 if (!cache && fCacheWrite) delete fCacheWrite;
2397 fCacheWrite = cache;
2398}
2399
2400////////////////////////////////////////////////////////////////////////////////
2401/// Return the size in bytes of the file header.
2403Int_t TFile::Sizeof() const
2404{
2405 return 0;
2406}
2407
2408////////////////////////////////////////////////////////////////////////////////
2409/// Stream a TFile object.
2412{
2413 if (b.IsReading()) {
2414 b.ReadVersion(); //Version_t v = b.ReadVersion();
2415 } else {
2416 b.WriteVersion(TFile::IsA());
2417 }
2418}
2419
2420////////////////////////////////////////////////////////////////////////////////
2421/// Increment statistics for buffer sizes of objects in this file.
2424{
2425 fWritten++;
2427 fSum2Buffer += double(bufsize) * double(bufsize); // avoid reaching MAXINT for temporary
2428}
2429
2430////////////////////////////////////////////////////////////////////////////////
2431/// Write memory objects to this file.
2432///
2433/// Loop on all objects in memory (including subdirectories).
2434/// A new key is created in the KEYS linked list for each object.
2435/// The list of keys is then saved on the file (via WriteKeys)
2436/// as a single data record.
2437/// For values of opt see TObject::Write().
2438/// The directory header info is rewritten on the directory header record.
2439/// The linked list of FREE segments is written.
2440/// The file header is written (bytes 1->fBEGIN).
2442Int_t TFile::Write(const char *, Int_t opt, Int_t bufsiz)
2443{
2444 if (!IsWritable()) {
2445 if (!TestBit(kWriteError)) {
2446 // Do not print the warning if we already had a SysError.
2447 Warning("Write", "file %s not opened in write mode", GetName());
2448 }
2449 return 0;
2450 }
2451
2452 if (gDebug) {
2453 if (!GetTitle() || strlen(GetTitle()) == 0)
2454 Info("Write", "writing name = %s", GetName());
2455 else
2456 Info("Write", "writing name = %s title = %s", GetName(), GetTitle());
2457 }
2458
2460 Int_t nbytes = TDirectoryFile::Write(0, opt, bufsiz); // Write directory tree
2462 WriteFree(); // Write free segments linked list
2463 WriteHeader(); // Now write file header
2464 fMustFlush = kTRUE;
2465
2466 return nbytes;
2467}
2468
2469////////////////////////////////////////////////////////////////////////////////
2470/// One can not save a const TDirectory object.
2472Int_t TFile::Write(const char *n, Int_t opt, Int_t bufsize) const
2473{
2474 Error("Write const","A const TFile object should not be saved. We try to proceed anyway.");
2475 return const_cast<TFile*>(this)->Write(n, opt, bufsize);
2476}
2477
2478////////////////////////////////////////////////////////////////////////////////
2479/// Write a buffer to the file. This is the basic low level write operation.
2480/// Returns kTRUE in case of failure.
2482Bool_t TFile::WriteBuffer(const char *buf, Int_t len)
2483{
2484 if (IsOpen() && fWritable) {
2485
2486 Int_t st;
2487 if ((st = WriteBufferViaCache(buf, len))) {
2488 if (st == 2)
2489 return kTRUE;
2490 return kFALSE;
2491 }
2492
2493 ssize_t siz;
2495 while ((siz = SysWrite(fD, buf, len)) < 0 && GetErrno() == EINTR) // NOLINT: silence clang-tidy warnings
2496 ResetErrno(); // NOLINT: silence clang-tidy warnings
2498 if (siz < 0) {
2499 // Write the system error only once for this file
2501 SysError("WriteBuffer", "error writing to file %s (%ld)", GetName(), (Long_t)siz);
2502 return kTRUE;
2503 }
2504 if (siz != len) {
2506 Error("WriteBuffer", "error writing all requested bytes to file %s, wrote %ld of %d",
2507 GetName(), (Long_t)siz, len);
2508 return kTRUE;
2509 }
2510 fBytesWrite += siz;
2511 fgBytesWrite += siz;
2512
2515
2516 return kFALSE;
2517 }
2518 return kTRUE;
2519}
2520
2521////////////////////////////////////////////////////////////////////////////////
2522/// Write buffer via cache. Returns 0 if cache is not active, 1 in case
2523/// write via cache was successful, 2 in case write via cache failed.
2525Int_t TFile::WriteBufferViaCache(const char *buf, Int_t len)
2526{
2527 if (!fCacheWrite) return 0;
2528
2529 Int_t st;
2530 Long64_t off = GetRelOffset();
2531 if ((st = fCacheWrite->WriteBuffer(buf, off, len)) < 0) {
2533 Error("WriteBuffer", "error writing to cache");
2534 return 2;
2535 }
2536 if (st > 0) {
2537 // fOffset might have been changed via TFileCacheWrite::WriteBuffer(), reset it
2538 Seek(off + len);
2539 return 1;
2540 }
2541 return 0;
2542}
2543
2544////////////////////////////////////////////////////////////////////////////////
2545/// Write FREE linked list on the file.
2546/// The linked list of FREE segments (fFree) is written as a single data
2547/// record.
2549void TFile::WriteFree()
2550{
2551 //*-* Delete old record if it exists
2552 if (fSeekFree != 0) {
2554 }
2555
2557
2558 auto createKey = [this]() {
2559 Int_t nbytes = 0;
2560 TFree *afree;
2561 TIter next (fFree);
2562 while ((afree = (TFree*) next())) {
2563 nbytes += afree->Sizeof();
2564 }
2565 if (!nbytes) return (TKey*)nullptr;
2566
2567 TKey *key = new TKey(fName,fTitle,IsA(),nbytes,this);
2568
2569 if (key->GetSeekKey() == 0) {
2570 delete key;
2571 return (TKey*)nullptr;
2572 }
2573 return key;
2574 };
2575
2576 TKey *key = createKey();
2577 if (!key) return;
2578
2579 if (!largeFile && (fEND > TFile::kStartBigFile)) {
2580 // The free block list is large enough to bring the file to larger
2581 // than 2Gb, the references/offsets are now 64bits in the output
2582 // so we need to redo the calculation since the list of free block
2583 // information will not fit in the original size.
2584 key->Delete();
2585 delete key;
2586
2587 key = createKey();
2588 if (!key) return;
2589 }
2590
2591 Int_t nbytes = key->GetObjlen();
2592 char *buffer = key->GetBuffer();
2593 char *start = buffer;
2594
2595 TIter next (fFree);
2596 TFree *afree;
2597 while ((afree = (TFree*) next())) {
2598 // We could 'waste' time here and double check that
2599 // (buffer+afree->Sizeof() < (start+nbytes)
2600 afree->FillBuffer(buffer);
2601 }
2602 auto actualBytes = buffer-start;
2603 if ( actualBytes != nbytes ) {
2604 if (actualBytes < nbytes) {
2605 // Most likely one of the 'free' segment was used to store this
2606 // TKey, so we had one less TFree to store than we planned.
2607 memset(buffer,0,nbytes-actualBytes);
2608 } else {
2609 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);
2610 }
2611 }
2612 fNbytesFree = key->GetNbytes();
2613 fSeekFree = key->GetSeekKey();
2614 key->WriteFile();
2615 delete key;
2616}
2617
2618////////////////////////////////////////////////////////////////////////////////
2619/// Write File Header.
2621void TFile::WriteHeader()
2622{
2624 TFree *lastfree = (TFree*)fFree->Last();
2625 if (lastfree) fEND = lastfree->GetFirst();
2626 const char *root = "root";
2627 char *psave = new char[fBEGIN];
2628 char *buffer = psave;
2629 Int_t nfree = fFree->GetSize();
2630 memcpy(buffer, root, 4); buffer += 4;
2633 tobuf(buffer, version);
2634 tobuf(buffer, (Int_t)fBEGIN);
2635 if (version < 1000000) {
2636 tobuf(buffer, (Int_t)fEND);
2637 tobuf(buffer, (Int_t)fSeekFree);
2638 tobuf(buffer, fNbytesFree);
2639 tobuf(buffer, nfree);
2640 tobuf(buffer, fNbytesName);
2641 tobuf(buffer, fUnits);
2642 tobuf(buffer, fCompress);
2643 tobuf(buffer, (Int_t)fSeekInfo);
2644 tobuf(buffer, fNbytesInfo);
2645 } else {
2646 tobuf(buffer, fEND);
2647 tobuf(buffer, fSeekFree);
2648 tobuf(buffer, fNbytesFree);
2649 tobuf(buffer, nfree);
2650 tobuf(buffer, fNbytesName);
2651 tobuf(buffer, fUnits);
2652 tobuf(buffer, fCompress);
2653 tobuf(buffer, fSeekInfo);
2654 tobuf(buffer, fNbytesInfo);
2655 }
2657 TUUID("00000000-0000-0000-0000-000000000000").FillBuffer(buffer);
2658 else
2659 fUUID.FillBuffer(buffer);
2660 Int_t nbytes = buffer - psave;
2661 Seek(0); // NOLINT: silence clang-tidy warnings
2662 WriteBuffer(psave, nbytes); // NOLINT: silence clang-tidy warnings
2663 Flush(); // NOLINT: silence clang-tidy warnings, Intentionally not conditional on fMustFlush, this is the 'obligatory' flush.
2664 delete [] psave;
2665}
2666
2667////////////////////////////////////////////////////////////////////////////////
2668/// Generate source code necessary to access the objects stored in the file.
2669///
2670/// Generate code in directory dirname for all classes specified in
2671/// argument classes If classes = "*" (default and currently the
2672/// only supported value), the function generates an include file
2673/// for each class in the StreamerInfo list for which a TClass
2674/// object does not exist.
2675///
2676/// The code generated includes:
2677/// - <em>dirnameProjectHeaders.h</em>, which contains one `#include` statement per generated header file
2678/// - <em>dirnameProjectSource.cxx</em>,which contains all the constructors and destructors implementation.
2679/// and one header per class that is not nested inside another class.
2680/// The header file name is the fully qualified name of the class after all the special characters
2681/// "<>,:" are replaced by underscored. For example for std::pair<edm::Vertex,int> the file name is
2682/// pair_edm__Vertex_int_.h
2683///
2684/// In the generated classes, map, multimap when the first template parameter is a class
2685/// are replaced by a vector of pair. set and multiset when the tempalte parameter
2686/// is a class are replaced by a vector. This is required since we do not have the
2687/// code needed to order and/or compare the object of the classes.
2688/// This is a quick explanation of the options available:
2689/// Option | Details
2690/// -------|--------
2691/// new (default) | A new directory dirname is created. If dirname already exist, an error message is printed and the function returns.
2692/// 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.
2693/// 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".
2694/// genreflex | Use genreflex rather than rootcint to generate the dictionary.
2695/// 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).
2696///
2697/// If, in addition to one of the 3 above options, the option "+" is specified,
2698/// the function will generate:
2699/// - a script called MAKEP to build the shared lib
2700/// - a dirnameLinkDef.h file
2701/// - rootcint will be run to generate a dirnameProjectDict.cxx file
2702/// - dirnameProjectDict.cxx will be compiled with the current options in compiledata.h
2703/// - a shared lib dirname.so will be created.
2704/// If the option "++" is specified, the generated shared lib is dynamically
2705/// linked with the current executable module.
2706/// If the option "+" and "nocompile" are specified, the utility files are generated
2707/// as in the option "+" but they are not executed.
2708/// Example:
2709/// file.MakeProject("demo","*","recreate++");
2710/// - creates a new directory demo unless it already exist
2711/// - clear the previous directory content
2712/// - generate the xxx.h files for all classes xxx found in this file
2713/// and not yet known to the CINT dictionary.
2714/// - creates the build script MAKEP
2715/// - creates a LinkDef.h file
2716/// - runs rootcint generating demoProjectDict.cxx
2717/// - compiles demoProjectDict.cxx into demoProjectDict.o
2718/// - generates a shared lib demo.so
2719/// - dynamically links the shared lib demo.so to the executable
2720/// If only the option "+" had been specified, one can still link the
2721/// shared lib to the current executable module with:
2722///
2723/// gSystem->load("demo/demo.so");
2724///
2725/// The following feature is not yet enabled:
2726/// One can restrict the list of classes to be generated by using expressions like:
2727///
2728/// classes = "Ali*" generate code only for classes starting with Ali
2729/// classes = "myClass" generate code for class MyClass only.
2730///
2732void TFile::MakeProject(const char *dirname, const char * /*classes*/,
2734{
2735 TString opt = option;
2736 opt.ToLower();
2739 if (opt.Contains("par")) {
2740 // Create a PAR file
2742 if (parname.EndsWith(".par")) parname.ReplaceAll(".par","");
2744 // Cleanup or prepare the dirs
2745 TString path, filepath;
2746 void *dir = gSystem->OpenDirectory(pardir);
2747 if (dir) {
2748 path.Form("%s/%s", pardir.Data(), parname.Data());
2749 void *dirp = gSystem->OpenDirectory(path);
2750 if (dirp) {
2751 path += "/PROOF-INF";
2752 void *dirinf = gSystem->OpenDirectory(path);
2753 const char *afile = 0;
2754 if (dirinf) {
2755 while ((afile = gSystem->GetDirEntry(dirinf))) {
2756 if (strcmp(afile,".") == 0) continue;
2757 if (strcmp(afile,"..") == 0) continue;
2758 filepath.Form("%s/%s", path.Data(), afile);
2759 if (gSystem->Unlink(filepath))
2760 Warning("MakeProject", "1: problems unlinking '%s' ('%s', '%s')", filepath.Data(), path.Data(), afile);
2761 }
2763 }
2764 gSystem->Unlink(path);
2765 path.Form("%s/%s", pardir.Data(), parname.Data());
2766 while ((afile = gSystem->GetDirEntry(dirp))) {
2767 if (strcmp(afile,".") == 0) continue;
2768 if (strcmp(afile,"..") == 0) continue;
2769 filepath.Form("%s/%s", path.Data(), afile);
2770 if (gSystem->Unlink(filepath))
2771 Warning("MakeProject", "2: problems unlinking '%s' ('%s', '%s')", filepath.Data(), path.Data(), afile);
2772 }
2774 if (gSystem->Unlink(path))
2775 Warning("MakeProject", "problems unlinking '%s'", path.Data());
2776 }
2777 }
2778 // Make sure that the relevant dirs exists: this is mandatory, so we fail if unsuccessful
2779 path.Form("%s/%s/PROOF-INF", pardir.Data(), parname.Data());
2780 if (gSystem->mkdir(path, kTRUE)) {
2781 Error("MakeProject", "problems creating '%s'", path.Data());
2782 return;
2783 }
2784 makepar = kTRUE;
2785
2786 } else {
2787 void *dir = gSystem->OpenDirectory(dirname);
2789
2790 if (opt.Contains("update")) {
2791 // check that directory exist, if not create it
2792 if (!dir) {
2794 }
2795
2796 } else if (opt.Contains("recreate")) {
2797 // check that directory exist, if not create it
2798 if (!dir) {
2799 if (gSystem->mkdir(dirname) < 0) {
2800 Error("MakeProject","cannot create directory '%s'",dirname);
2801 return;
2802 }
2803 }
2804 // clear directory
2805 while (dir) {
2806 const char *afile = gSystem->GetDirEntry(dir);
2807 if (!afile) break;
2808 if (strcmp(afile,".") == 0) continue;
2809 if (strcmp(afile,"..") == 0) continue;
2810 dirpath.Form("%s/%s",dirname,afile);
2812 }
2813
2814 } else {
2815 // new is assumed
2816 // if directory already exist, print error message and return
2817 if (dir) {
2818 Error("MakeProject","cannot create directory %s, already existing",dirname);
2820 return;
2821 }
2822 if (gSystem->mkdir(dirname) < 0) {
2823 Error("MakeProject","cannot create directory '%s'",dirname);
2824 return;
2825 }
2826 }
2827 if (dir) {
2829 }
2830 }
2831 Bool_t genreflex = opt.Contains("genreflex");
2832
2833 // we are now ready to generate the classes
2834 // loop on all TStreamerInfo
2836 if (filelist) filelist = (TList*)filelist->Clone();
2837 if (!filelist) {
2838 Error("MakeProject","file %s has no StreamerInfo", GetName());
2839 return;
2840 }
2841
2843 if (makepar) clean_dirname.Form("%s/%s", pardir.Data(), parname.Data());
2844 if (clean_dirname[clean_dirname.Length()-1]=='/') {
2845 clean_dirname.Remove(clean_dirname.Length()-1);
2846 } else if (clean_dirname[clean_dirname.Length()-1]=='\') {
2847 clean_dirname.Remove(clean_dirname.Length()-1);
2848 if (clean_dirname[clean_dirname.Length()-1]=='\') {
2849 clean_dirname.Remove(clean_dirname.Length()-1);
2850 }
2851 }
2853 if (makepar) subdirname = parname;
2854 if (subdirname == "") {
2855 Error("MakeProject","Directory name must not be empty.");
2856 return;
2857 }
2858
2859 // Start the source file
2860 TString spath; spath.Form("%s/%sProjectSource.cxx",clean_dirname.Data(),subdirname.Data());
2861 FILE *sfp = fopen(spath.Data(),"w");
2862 if (!sfp) {
2863 Error("MakeProject","Unable to create the source file %s.",spath.Data());
2864 return;
2865 }
2866 fprintf(sfp, "namespace std {}\nusing namespace std;\n");
2867 fprintf(sfp, "#include \"%sProjectHeaders.h\"\n\n",subdirname.Data() );
2868 if (!genreflex) fprintf(sfp, "#include \"%sLinkDef.h\"\n\n",subdirname.Data() );
2869 fprintf(sfp, "#include \"%sProjectDict.cxx\"\n\n",subdirname.Data() );
2870 fprintf(sfp, "struct DeleteObjectFunctor {\n");
2871 fprintf(sfp, " template <typename T>\n");
2872 fprintf(sfp, " void operator()(const T *ptr) const {\n");
2873 fprintf(sfp, " delete ptr;\n");
2874 fprintf(sfp, " }\n");
2875 fprintf(sfp, " template <typename T, typename Q>\n");
2876 fprintf(sfp, " void operator()(const std::pair<T,Q> &) const {\n");
2877 fprintf(sfp, " // Do nothing\n");
2878 fprintf(sfp, " }\n");
2879 fprintf(sfp, " template <typename T, typename Q>\n");
2880 fprintf(sfp, " void operator()(const std::pair<T,Q*> &ptr) const {\n");
2881 fprintf(sfp, " delete ptr.second;\n");
2882 fprintf(sfp, " }\n");
2883 fprintf(sfp, " template <typename T, typename Q>\n");
2884 fprintf(sfp, " void operator()(const std::pair<T*,Q> &ptr) const {\n");
2885 fprintf(sfp, " delete ptr.first;\n");
2886 fprintf(sfp, " }\n");
2887 fprintf(sfp, " template <typename T, typename Q>\n");
2888 fprintf(sfp, " void operator()(const std::pair<T*,Q*> &ptr) const {\n");
2889 fprintf(sfp, " delete ptr.first;\n");
2890 fprintf(sfp, " delete ptr.second;\n");
2891 fprintf(sfp, " }\n");
2892 fprintf(sfp, "};\n\n");
2893 fclose( sfp );
2894
2895 // loop on all TStreamerInfo classes to check for empty classes
2896 // and enums listed either as data member or template parameters,
2897 // and filter out 'duplicates' classes/streamerInfos.
2901 TList *list = new TList();
2902 while ((info = (TStreamerInfo*)flnext())) {
2903 if (info->IsA() != TStreamerInfo::Class()) {
2904 continue;
2905 }
2906 if (strstr(info->GetName(),"@@")) {
2907 // Skip schema evolution support streamerInfo
2908 continue;
2909 }
2910 TClass *cl = TClass::GetClass(info->GetName());
2911 if (cl) {
2912 if (cl->HasInterpreterInfo()) continue; // skip known classes
2913 }
2914 // Find and use the proper rules for the TStreamerInfos.
2916 TIter enext( info->GetElements() );
2919 if (cl && cl->GetSchemaRules()) {
2920 rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
2921 }
2922 while( (el=(TStreamerElement*)enext()) ) {
2923 for(auto rule : rules) {
2924 if( rule->IsRenameRule() || rule->IsAliasRule() )
2925 continue;
2926 // Check whether this is an 'attribute' rule.
2927 if ( rule->HasTarget( el->GetName()) && rule->GetAttributes()[0] != 0 ) {
2928 TString attr( rule->GetAttributes() );
2929 attr.ToLower();
2930 if (attr.Contains("owner")) {
2931 if (attr.Contains("notowner")) {
2933 } else {
2935 }
2936 }
2937 }
2938 }
2940 }
2941 TVirtualStreamerInfo *alternate = (TVirtualStreamerInfo*)list->FindObject(info->GetName());
2942 if (alternate) {
2943 if ((info->GetClass() && info->GetClassVersion() == info->GetClass()->GetClassVersion())
2944 || (info->GetClassVersion() > alternate->GetClassVersion()) ) {
2945 list->AddAfter(alternate, info);
2946 list->Remove(alternate);
2947 } // otherwise ignore this info as not being the official one.
2948 } else {
2949 list->Add(info);
2950 }
2951 }
2952 // Now transfer the new StreamerInfo onto the main list and
2953 // to the owning list.
2955 while ((info = (TStreamerInfo*)nextextra())) {
2956 list->Add(info);
2957 filelist->Add(info);
2958 }
2959
2960 // loop on all TStreamerInfo classes
2961 TIter next(list);
2962 Int_t ngener = 0;
2963 while ((info = (TStreamerInfo*)next())) {
2964 if (info->IsA() != TStreamerInfo::Class()) {
2965 continue;
2966 }
2967 if (info->GetClassVersion()==-4) continue; // Skip outer level namespace
2968 TIter subnext(list);
2971 Int_t len = strlen(info->GetName());
2972 while ((subinfo = (TStreamerInfo*)subnext())) {
2973 if (subinfo->IsA() != TStreamerInfo::Class()) {
2974 continue;
2975 }
2976 if (strncmp(info->GetName(),subinfo->GetName(),len)==0) {
2977 // The 'sub' StreamerInfo start with the main StreamerInfo name,
2978 // it subinfo is likely to be a nested class.
2979 const Int_t sublen = strlen(subinfo->GetName());
2980 if ( (sublen > len) && subinfo->GetName()[len+1]==':'
2981 && !subClasses.FindObject(subinfo->GetName()) /* We need to insure uniqueness */)
2982 {
2983 subClasses.Add(subinfo);
2984 }
2985 }
2986 }
2987 ngener += info->GenerateHeaderFile(clean_dirname.Data(),&subClasses,&extrainfos);
2988 subClasses.Clear("nodelete");
2989 }
2990 extrainfos.Clear("nodelete"); // We are done with this list.
2991
2992 TString path;
2993 path.Form("%s/%sProjectHeaders.h",clean_dirname.Data(),subdirname.Data());
2994 FILE *allfp = fopen(path,"a");
2995 if (!allfp) {
2996 Error("MakeProject","Cannot open output file:%s\n",path.Data());
2997 } else {
2998 fprintf(allfp,"#include \"%sProjectInstances.h\"\n", subdirname.Data());
2999 fclose(allfp);
3000 }
3001
3002 printf("MakeProject has generated %d classes in %s\n",ngener,clean_dirname.Data());
3003
3004 // generate the shared lib
3005 if (!opt.Contains("+") && !makepar) {
3006 delete list;
3007 filelist->Delete();
3008 delete filelist;
3009 return;
3010 }
3011
3012 // Makefiles files
3013 FILE *fpMAKE = nullptr;
3014 if (!makepar) {
3015 // Create the MAKEP file by looping on all *.h files
3016 // delete MAKEP if it already exists
3017#ifdef WIN32
3018 path.Form("%s/makep.cmd",clean_dirname.Data());
3019#else
3020 path.Form("%s/MAKEP",clean_dirname.Data());
3021#endif
3022#ifdef R__WINGCC
3023 fpMAKE = fopen(path,"wb");
3024#else
3025 fpMAKE = fopen(path,"w");
3026#endif
3027 if (!fpMAKE) {
3028 Error("MakeProject", "cannot open file %s", path.Data());
3029 delete list;
3030 filelist->Delete();
3031 delete filelist;
3032 return;
3033 }
3034 }
3035
3036 // Add rootcint/genreflex statement generating ProjectDict.cxx
3037 FILE *ifp = nullptr;
3038 path.Form("%s/%sProjectInstances.h",clean_dirname.Data(),subdirname.Data());
3039#ifdef R__WINGCC
3040 ifp = fopen(path,"wb");
3041#else
3042 ifp = fopen(path,"w");
3043#endif
3044 if (!ifp) {
3045 Error("MakeProject", "cannot open path file %s", path.Data());
3046 delete list;
3047 filelist->Delete();
3048 delete filelist;
3049 fclose(fpMAKE);
3050 return;
3051 }
3052
3053 if (!makepar) {
3054 if (genreflex) {
3055 fprintf(fpMAKE,"genreflex %sProjectHeaders.h -o %sProjectDict.cxx --comments --iocomments %s ",subdirname.Data(),subdirname.Data(),gSystem->GetIncludePath());
3056 path.Form("%s/%sSelection.xml",clean_dirname.Data(),subdirname.Data());
3057 } else {
3058 fprintf(fpMAKE,"rootcint -v1 -f %sProjectDict.cxx %s ", subdirname.Data(), gSystem->GetIncludePath());
3059 path.Form("%s/%sLinkDef.h",clean_dirname.Data(),subdirname.Data());
3060 }
3061 } else {
3062 path.Form("%s/%sLinkDef.h",clean_dirname.Data(),subdirname.Data());
3063 }
3064
3065 // Create the LinkDef.h or xml selection file by looping on all *.h files
3066 // replace any existing file.
3067#ifdef R__WINGCC
3068 FILE *fp = fopen(path,"wb");
3069#else
3070 FILE *fp = fopen(path,"w");
3071#endif
3072 if (!fp) {
3073 Error("MakeProject", "cannot open path file %s", path.Data());
3074 delete list;
3075 filelist->Delete();
3076 delete filelist;
3077 fclose(fpMAKE);
3078 fclose(ifp);
3079 return;
3080 }
3081 if (genreflex) {
3082 fprintf(fp,"<lcgdict>\n");
3083 fprintf(fp,"\n");
3084 } else {
3085 fprintf(fp,"#ifdef __CINT__\n");
3086 fprintf(fp,"\n");
3087 }
3088
3089 TString tmp;
3092 next.Reset();
3093 while ((info = (TStreamerInfo*)next())) {
3094 if (info->IsA() != TStreamerInfo::Class()) {
3095 continue;
3096 }
3097 if (strncmp(info->GetName(), "auto_ptr<", strlen("auto_ptr<")) == 0) {
3098 continue;
3099 }
3100 TClass *cl = TClass::GetClass(info->GetName());
3101 if (cl) {
3102 if (cl->HasInterpreterInfo()) continue; // skip known classes
3103 if (cl->GetSchemaRules()) {
3104 auto rules = cl->GetSchemaRules()->FindRules(cl->GetName(), info->GetClassVersion());
3106 for(auto rule : rules) {
3107 strrule.Clear();
3108 if (genreflex) {
3109 rule->AsString(strrule,"x");
3110 strrule.Append("\n");
3111 if ( selections.Index(strrule) == kNPOS ) {
3112 selections.Append(strrule);
3113 }
3114 } else {
3115 rule->AsString(strrule);
3116 if (strncmp(strrule.Data(),"type=",5)==0) {
3117 strrule.Remove(0,5);
3118 }
3119 fprintf(fp,"#pragma %s;\n",strrule.Data());
3120 }
3121 }
3122 }
3123
3124 }
3125 if ((info->GetClass() && info->GetClass()->GetCollectionType()) || TClassEdit::IsSTLCont(info->GetName())) {
3126 std::vector<std::string> inside;
3127 int nestedLoc;
3129 Int_t stlkind = TClassEdit::STLKind(inside[0]);
3130 TClass *key = TClass::GetClass(inside[1].c_str());
3131 if (key) {
3132 TString what;
3133 switch ( stlkind ) {
3134 case ROOT::kSTLmap:
3135 case ROOT::kSTLmultimap:
3136 if (TClass::GetClass(inside[1].c_str())) {
3137 what = "std::pair<";
3138 what += TMakeProject::UpdateAssociativeToVector( inside[1].c_str() );
3139 what += ",";
3140 what += TMakeProject::UpdateAssociativeToVector( inside[2].c_str() );
3141 if (what[what.Length()-1]=='>') {
3142 what += " >";
3143 } else {
3144 what += ">";
3145 }
3146 if (genreflex) {
3147 tmp.Form("<class name=\"%s\" />\n",what.Data());
3148 if ( selections.Index(tmp) == kNPOS ) {
3149 selections.Append(tmp);
3150 }
3151 tmp.Form("template class %s;\n",what.Data());
3152 if ( instances.Index(tmp) == kNPOS ) {
3153 instances.Append(tmp);
3154 }
3155 } else {
3156 what.ReplaceAll("std::","");
3158 if (!paircl || !paircl->HasInterpreterInfo()) {
3159 fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
3160 }
3161 }
3162 break;
3163 }
3164 default:
3165 if (TClassEdit::IsStdPair(key->GetName())) {
3166 if (genreflex) {
3167 tmp.Form("<class name=\"%s\" />\n",key->GetName());
3168 if ( selections.Index(tmp) == kNPOS ) {
3169 selections.Append(tmp);
3170 }
3171 tmp.Form("template class %s;\n",key->GetName());
3172 if ( instances.Index(tmp) == kNPOS ) {
3173 instances.Append(tmp);
3174 }
3175 } else {
3176 what.ReplaceAll("std::","");
3177 fprintf(fp,"#pragma link C++ class %s+;\n",key->GetName());
3178 }
3179 }
3180 break;
3181 }
3182 }
3183 continue;
3184 }
3185 {
3187 if (genreflex) {
3188 tmp.Form("<class name=\"%s\" />\n",what.Data());
3189 if ( selections.Index(tmp) == kNPOS ) {
3190 selections.Append(tmp);
3191 }
3192 if (what[what.Length()-1] == '>') {
3193 tmp.Form("template class %s;\n",what.Data());
3194 if ( instances.Index(tmp) == kNPOS ) {
3195 instances.Append(tmp);
3196 }
3197 }
3198 } else {
3199 what.ReplaceAll("std::","");
3200 fprintf(fp,"#pragma link C++ class %s+;\n",what.Data());
3201 }
3202 }
3203 if (genreflex) {
3204 // Also request the dictionary for the STL container used as members ...
3205 TIter eliter( info->GetElements() );
3207 while( (element = (TStreamerElement*)eliter() ) ) {
3208 if (element->GetClass() && !element->GetClass()->IsLoaded() && element->GetClass()->GetCollectionProxy()) {
3210 tmp.Form("<class name=\"%s\" />\n",what.Data());
3211 if ( selections.Index(tmp) == kNPOS ) {
3212 selections.Append(tmp);
3213 }
3214 tmp.Form("template class %s;\n",what.Data());
3215 if ( instances.Index(tmp) == kNPOS ) {
3216 instances.Append(tmp);
3217 }
3218 }
3219 }
3220 }
3221 }
3222 if (genreflex) {
3223 fprintf(ifp,"#ifndef PROJECT_INSTANCES_H\n");
3224 fprintf(ifp,"#define PROJECT_INSTANCES_H\n");
3225 fprintf(ifp,"%s",instances.Data());
3226 fprintf(ifp,"#endif\n");
3227 fprintf(fp,"%s",selections.Data());
3228 fprintf(fp,"</lcgdict>\n");
3229 } else {
3230 fprintf(fp,"#endif\n");
3231 }
3232 fclose(fp);
3233 fclose(ifp);
3234
3235 if (!makepar) {
3236 // add compilation line
3238
3240 TString sources = TString::Format("%sProjectSource.cxx ", sdirname.Data());
3241 cmd.ReplaceAll("$SourceFiles",sources.Data());
3242 TString object = TString::Format("%sProjectSource.", sdirname.Data());
3243 object.Append( gSystem->GetObjExt() );
3244 cmd.ReplaceAll("$ObjectFiles", object.Data());
3245 cmd.ReplaceAll("$IncludePath",TString(gSystem->GetIncludePath()) + " -I" + clean_dirname.Data());
3246 cmd.ReplaceAll("$SharedLib",sdirname+"."+gSystem->GetSoExt());
3247 cmd.ReplaceAll("$LinkedLibs",gSystem->GetLibraries("","SDL"));
3248 cmd.ReplaceAll("$LibName",sdirname);
3249 cmd.ReplaceAll("$BuildDir",".");
3250 TString sOpt;
3252 if (rootbuild.Index("debug",0,TString::kIgnoreCase)==kNPOS) {
3254 } else {
3256 }
3257 cmd.ReplaceAll("$Opt", sOpt);
3258
3259 if (genreflex) {
3260 fprintf(fpMAKE,"-s %sSelection.xml \n",subdirname.Data());
3261 } else {
3262 fprintf(fpMAKE,"%sProjectHeaders.h ",subdirname.Data());
3263 fprintf(fpMAKE,"%sLinkDef.h \n",subdirname.Data());
3264 }
3265
3266 fprintf(fpMAKE,"%s\n",cmd.Data());
3267
3268 printf("%s/MAKEP file has been generated\n", clean_dirname.Data());
3269
3270 fclose(fpMAKE);
3271
3272 } else {
3273
3274 // Create the Makefile
3275 TString filemake = TString::Format("%s/Makefile", clean_dirname.Data());
3276 if (MakeProjectParMake(parname, filemake.Data()) != 0) {
3277 Error("MakeProject", "problems creating PAR make file '%s'", filemake.Data());
3278 delete list;
3279 filelist->Delete();
3280 delete filelist;
3281 return;
3282 }
3283 // Get Makefile.arch
3284 TString mkarchsrc = TString::Format("%s/Makefile.arch", TROOT::GetEtcDir().Data());
3286 Warning("MakeProject", "problems expanding '%s'", mkarchsrc.Data());
3287 TString mkarchdst = TString::Format("%s/Makefile.arch", clean_dirname.Data());
3288 if (gSystem->CopyFile(mkarchsrc.Data(), mkarchdst.Data(), kTRUE) != 0) {
3289 Error("MakeProject", "problems retrieving '%s' to '%s'", mkarchsrc.Data(), mkarchdst.Data());
3290 delete list;
3291 filelist->Delete();
3292 delete filelist;
3293 return;
3294 }
3295 // Create the Makefile
3296 TString proofinf = TString::Format("%s/PROOF-INF", clean_dirname.Data());
3297 if (MakeProjectParProofInf(parname, proofinf.Data()) != 0) {
3298 Error("MakeProject", "problems creating BUILD.sh and/or SETUP.C under '%s'", proofinf.Data());
3299 delete list;
3300 filelist->Delete();
3301 delete filelist;
3302 return;
3303 }
3304
3305 // Make sure BUILD.sh is executable and create SETUP.C
3306 TString cmod = TString::Format("chmod +x %s/PROOF-INF/BUILD.sh", clean_dirname.Data());
3307#ifndef WIN32
3308 gSystem->Exec(cmod.Data());
3309#else
3310 // not really needed for Windows but it would work both both Unix and NT
3311 chmod(cmod.Data(), 00700);
3312#endif
3313 Printf("Files Makefile, Makefile.arch, PROOF-INF/BUILD.sh and"
3314 " PROOF-INF/SETUP.C have been generated under '%s'", clean_dirname.Data());
3315
3316 // Generate the PAR file, if not Windows
3317#ifndef WIN32
3320 TString cmd = TString::Format("tar czvf %s.par %s", parname.Data(), parname.Data());
3321 gSystem->Exec(cmd.Data());
3323 Info("MakeProject", "PAR file %s.par generated", clean_dirname.Data());
3324 } else {
3325 Warning("MakeProject", "problems changing directory back to '%s'", curdir.Data());
3326 }
3327 } else {
3328 Error("MakeProject", "problems changing directory to '%s' - skipping PAR file generation", pardir.Data());
3329 }
3330#else
3331 Warning("MakeProject", "on Windows systems the PAR file cannot be generated out of the package directory!");
3332#endif
3333 }
3334
3335
3336 if (!makepar && !opt.Contains("nocompilation")) {
3337 // now execute the generated script compiling and generating the shared lib
3338 path = gSystem->WorkingDirectory();
3340#ifndef WIN32
3341 gSystem->Exec("chmod +x MAKEP");
3342 int res = !gSystem->Exec("./MAKEP");
3343#else
3344 // not really needed for Windows but it would work both both Unix and NT
3345 chmod("makep.cmd",00700);
3346 int res = !gSystem->Exec("MAKEP");
3347#endif
3348 gSystem->ChangeDirectory(path);
3349 path.Form("%s/%s.%s",clean_dirname.Data(),subdirname.Data(),gSystem->GetSoExt());
3350 if (res) printf("Shared lib %s has been generated\n",path.Data());
3351
3352 //dynamically link the generated shared lib
3353 if (opt.Contains("++")) {
3354 res = !gSystem->Load(path);
3355 if (res) printf("Shared lib %s has been dynamically linked\n",path.Data());
3356 }
3357 }
3358
3359 delete list;
3360 filelist->Delete();
3361 delete filelist;
3362}
3363
3364////////////////////////////////////////////////////////////////////////////////
3365/// Create makefile at 'filemake' for PAR package 'pack'.
3366///
3367/// Called by MakeProject when option 'par' is given.
3368/// Return 0 on success, -1 on error.
3370Int_t TFile::MakeProjectParMake(const char *pack, const char *filemake)
3371{
3372 // Output file path must be defined
3373 if (!filemake || (filemake && strlen(filemake) <= 0)) {
3374 Error("MakeProjectParMake", "path for output file undefined!");
3375 return -1;
3376 }
3377
3378 // Package name must be defined
3379 if (!pack || (pack && strlen(pack) <= 0)) {
3380 Error("MakeProjectParMake", "package name undefined!");
3381 return -1;
3382 }
3383
3384#ifdef R__WINGCC
3385 FILE *fmk = fopen(filemake, "wb");
3386#else
3387 FILE *fmk = fopen(filemake, "w");
3388#endif
3389 if (!fmk) {
3390 Error("MakeProjectParMake", "cannot create file '%s' (errno: %d)", filemake, TSystem::GetErrno());
3391 return -1;
3392 }
3393
3394 // Fill the file now
3395 fprintf(fmk, "# Makefile for the ROOT test programs.\n");
3396 fprintf(fmk, "# This Makefile shows how to compile and link applications\n");
3397 fprintf(fmk, "# using the ROOT libraries on all supported platforms.\n");
3398 fprintf(fmk, "#\n");
3399 fprintf(fmk, "# Copyright (c) 2000 Rene Brun and Fons Rademakers\n");
3400 fprintf(fmk, "#\n");
3401 fprintf(fmk, "# Author: this makefile has been automatically generated via TFile::MakeProject\n");
3402 fprintf(fmk, "\n");
3403 fprintf(fmk, "include Makefile.arch\n");
3404 fprintf(fmk, "\n");
3405 fprintf(fmk, "#------------------------------------------------------------------------------\n");
3406 fprintf(fmk, "\n");
3407 fprintf(fmk, "PACKO = %sProjectSource.$(ObjSuf)\n", pack);
3408 fprintf(fmk, "PACKS = %sProjectSource.$(SrcSuf) %sProjectDict.$(SrcSuf)\n", pack, pack);
3409 fprintf(fmk, "PACKSO = lib%s.$(DllSuf)\n", pack);
3410 fprintf(fmk, "\n");
3411 fprintf(fmk, "ifeq ($(PLATFORM),win32)\n");
3412 fprintf(fmk, "PACKLIB = lib%s.lib\n", pack);
3413 fprintf(fmk, "else\n");
3414 fprintf(fmk, "PACKLIB = $(PACKSO)\n");
3415 fprintf(fmk, "endif\n");
3416 fprintf(fmk, "\n");
3417 fprintf(fmk, "OBJS = $(PACKO)\n");
3418 fprintf(fmk, "\n");
3419 fprintf(fmk, "PROGRAMS =\n");
3420 fprintf(fmk, "\n");
3421 fprintf(fmk, "#------------------------------------------------------------------------------\n");
3422 fprintf(fmk, "\n");
3423 fprintf(fmk, ".SUFFIXES: .$(SrcSuf) .$(ObjSuf) .$(DllSuf)\n");
3424 fprintf(fmk, "\n");
3425 fprintf(fmk, "all: $(PACKLIB)\n");
3426 fprintf(fmk, "\n");
3427 fprintf(fmk, "$(PACKSO): $(PACKO)\n");
3428 fprintf(fmk, "ifeq ($(ARCH),aix)\n");
3429 fprintf(fmk, "\t\t/usr/ibmcxx/bin/makeC++SharedLib $(OutPutOpt) $@ $(LIBS) -p 0 $^\n");
3430 fprintf(fmk, "else\n");
3431 fprintf(fmk, "ifeq ($(ARCH),aix5)\n");
3432 fprintf(fmk, "\t\t/usr/vacpp/bin/makeC++SharedLib $(OutPutOpt) $@ $(LIBS) -p 0 $^\n");
3433 fprintf(fmk, "else\n");
3434 fprintf(fmk, "ifeq ($(PLATFORM),macosx)\n");
3435 fprintf(fmk, "# We need to make both the .dylib and the .so\n");
3436 fprintf(fmk, "\t\t$(LD) $(SOFLAGS)$@ $(LDFLAGS) $^ $(OutPutOpt) $@ $(LIBS)\n");
3437 fprintf(fmk, "ifneq ($(subst $(MACOSX_MINOR),,1234),1234)\n");
3438 fprintf(fmk, "ifeq ($(MACOSX_MINOR),4)\n");
3439 fprintf(fmk, "\t\tln -sf $@ $(subst .$(DllSuf),.so,$@)\n");
3440 fprintf(fmk, "else\n");
3441 fprintf(fmk, "\t\t$(LD) -bundle -undefined $(UNDEFOPT) $(LDFLAGS) $^ \\n");
3442 fprintf(fmk, "\t\t $(OutPutOpt) $(subst .$(DllSuf),.so,$@)\n");
3443 fprintf(fmk, "endif\n");
3444 fprintf(fmk, "endif\n");
3445 fprintf(fmk, "else\n");
3446 fprintf(fmk, "ifeq ($(PLATFORM),win32)\n");
3447 fprintf(fmk, "\t\tbindexplib $* $^ > $*.def\n");
3448 fprintf(fmk, "\t\tlib -nologo -MACHINE:IX86 $^ -def:$*.def \\n");
3449 fprintf(fmk, "\t\t $(OutPutOpt)$(PACKLIB)\n");
3450 fprintf(fmk, "\t\t$(LD) $(SOFLAGS) $(LDFLAGS) $^ $*.exp $(LIBS) \\n");
3451 fprintf(fmk, "\t\t $(OutPutOpt)$@\n");
3452 fprintf(fmk, "else\n");
3453 fprintf(fmk, "\t\t$(LD) $(SOFLAGS) $(LDFLAGS) $^ $(OutPutOpt) $@ $(LIBS) $(EXPLLINKLIBS)\n");
3454 fprintf(fmk, "endif\n");
3455 fprintf(fmk, "endif\n");
3456 fprintf(fmk, "endif\n");
3457 fprintf(fmk, "endif\n");
3458 fprintf(fmk, "\t\t@echo \"$@ done\"\n");
3459 fprintf(fmk, "\n");
3460 fprintf(fmk, "clean:\n");
3461 fprintf(fmk, "\t\t@rm -f $(OBJS) core\n");
3462 fprintf(fmk, "\n");
3463 fprintf(fmk, "distclean: clean\n");
3464 fprintf(fmk, "\t\t@rm -f $(PROGRAMS) $(PACKSO) $(PACKLIB) *Dict.* *.def *.exp \\n");
3465 fprintf(fmk, "\t\t *.so *.lib *.dll *.d *.log .def so_locations\n");
3466 fprintf(fmk, "\t\t@rm -rf cxx_repository\n");
3467 fprintf(fmk, "\n");
3468 fprintf(fmk, "# Dependencies\n");
3469 fprintf(fmk, "\n");
3470 fprintf(fmk, "%sProjectSource.$(ObjSuf): %sProjectHeaders.h %sLinkDef.h %sProjectDict.$(SrcSuf)\n", pack, pack, pack, pack);
3471 fprintf(fmk, "\n");
3472 fprintf(fmk, "%sProjectDict.$(SrcSuf): %sProjectHeaders.h %sLinkDef.h\n", pack, pack, pack);
3473 fprintf(fmk, "\t\t@echo \"Generating dictionary $@...\"\n");
3474 fprintf(fmk, "\t\t@rootcint -f $@ $^\n");
3475 fprintf(fmk, "\n");
3476 fprintf(fmk, ".$(SrcSuf).$(ObjSuf):\n");
3477 fprintf(fmk, "\t\t$(CXX) $(CXXFLAGS) -c $<\n");
3478 fprintf(fmk, "\n");
3479
3480 // Close the file
3481 fclose(fmk);
3482
3483 // Done
3484 return 0;
3485}
3486
3487////////////////////////////////////////////////////////////////////////////////
3488/// Create BUILD.sh and SETUP.C under 'proofinf' for PAR package 'pack'.
3489/// Called by MakeProject when option 'par' is given.
3490/// Return 0 on success, -1 on error.
3492Int_t TFile::MakeProjectParProofInf(const char *pack, const char *proofinf)
3493{
3494 // Output directory path must be defined ...
3495 if (!proofinf || (proofinf && strlen(proofinf) <= 0)) {
3496 Error("MakeProjectParProofInf", "directory path undefined!");
3497 return -1;
3498 }
3499
3500 // ... and exist and be a directory
3501 Int_t rcst = 0;
3502 FileStat_t st;
3503 if ((rcst = gSystem->GetPathInfo(proofinf, st)) != 0 || !R_ISDIR(st.fMode)) {
3504 Error("MakeProjectParProofInf", "path '%s' %s", proofinf,
3505 ((rcst == 0) ? "is not a directory" : "does not exist"));
3506 return -1;
3507 }
3508
3509 // Package name must be defined
3510 if (!pack || (pack && strlen(pack) <= 0)) {
3511 Error("MakeProjectParProofInf", "package name undefined!");
3512 return -1;
3513 }
3514
3515 TString path;
3516
3517 // The BUILD.sh first
3518 path.Form("%s/BUILD.sh", proofinf);
3519#ifdef R__WINGCC
3520 FILE *f = fopen(path.Data(), "wb");
3521#else
3522 FILE *f = fopen(path.Data(), "w");
3523#endif
3524 if (!f) {
3525 Error("MakeProjectParProofInf", "cannot create file '%s' (errno: %d)",
3526 path.Data(), TSystem::GetErrno());
3527 return -1;
3528 }
3529
3530 fprintf(f, "#! /bin/sh\n");
3531 fprintf(f, "# Build libEvent library.\n");
3532 fprintf(f, "\n");
3533 fprintf(f, "#\n");
3534 fprintf(f, "# The environment variables ROOTPROOFLITE and ROOTPROOFCLIENT can be used to\n");
3535 fprintf(f, "# adapt the script to the calling environment\n");
3536 fprintf(f, "#\n");
3537 fprintf(f, "# if test ! \"x$ROOTPROOFLITE\" = \"x\"; then\n");
3538 fprintf(f, "# echo \"event-BUILD: PROOF-Lite node (session has $ROOTPROOFLITE workers)\"\n");
3539 fprintf(f, "# elif test ! \"x$ROOTPROOFCLIENT\" = \"x\"; then\n");
3540 fprintf(f, "# echo \"event-BUILD: PROOF client\"\n");
3541 fprintf(f, "# else\n");
3542 fprintf(f, "# echo \"event-BUILD: standard PROOF node\"\n");
3543 fprintf(f, "# fi\n");
3544 fprintf(f, "\n");
3545 fprintf(f, "if [ \"\" = \"clean\" ]; then\n");
3546 fprintf(f, " make distclean\n");
3547 fprintf(f, " exit 0\n");
3548 fprintf(f, "fi\n");
3549 fprintf(f, "\n");
3550 fprintf(f, "make\n");
3551 fprintf(f, "rc=$?\n");
3552 fprintf(f, "echo \"rc=$?\"\n");
3553 fprintf(f, "if [ $? != \"0\" ] ; then\n");
3554 fprintf(f, " exit 1\n");
3555 fprintf(f, "fi\n");
3556 fprintf(f, "exit 0\n");
3557
3558 // Close the file
3559 fclose(f);
3560
3561 // Then SETUP.C
3562 path.Form("%s/SETUP.C", proofinf);
3563#ifdef R__WINGCC
3564 f = fopen(path.Data(), "wb");
3565#else
3566 f = fopen(path.Data(), "w");
3567#endif
3568 if (!f) {
3569 Error("MakeProjectParProofInf", "cannot create file '%s' (errno: %d)",
3570 path.Data(), TSystem::GetErrno());
3571 return -1;
3572 }
3573
3574 fprintf(f, "Int_t SETUP()\n");
3575 fprintf(f, "{\n");
3576 fprintf(f, "\n");
3577 fprintf(f, "//\n");
3578 fprintf(f, "// The environment variables ROOTPROOFLITE and ROOTPROOFCLIENT can be used to\n");
3579 fprintf(f, "// adapt the macro to the calling environment\n");
3580 fprintf(f, "//\n");
3581 fprintf(f, "// if (gSystem->Getenv(\"ROOTPROOFLITE\")) {\n");
3582 fprintf(f, "// Printf(\"event-SETUP: PROOF-Lite node (session has %%s workers)\",\n");
3583 fprintf(f, "// gSystem->Getenv(\"ROOTPROOFLITE\"));\n");
3584 fprintf(f, "// } else if (gSystem->Getenv(\"ROOTPROOFCLIENT\")) {\n");
3585 fprintf(f, "// Printf(\"event-SETUP: PROOF client\");\n");
3586 fprintf(f, "// } else {\n");
3587 fprintf(f, "// Printf(\"event-SETUP: standard PROOF node\");\n");
3588 fprintf(f, "// }\n");
3589 fprintf(f, "\n");
3590 fprintf(f, " if (gSystem->Load(\"lib%s\") == -1)\n", pack);
3591 fprintf(f, " return -1;\n");
3592 fprintf(f, " return 0;\n");
3593 fprintf(f, "}\n");
3594 fprintf(f, "\n");
3595
3596 // Close the file
3597 fclose(f);
3598
3599 // Done
3600 return 0;
3601}
3602
3603////////////////////////////////////////////////////////////////////////////////
3604/// Read the list of StreamerInfo from this file.
3605///
3606/// The key with name holding the list of TStreamerInfo objects is read.
3607/// The corresponding TClass objects are updated.
3608/// Note that this function is not called if the static member fgReadInfo is false.
3609/// (see TFile::SetReadStreamerInfo)
3612{
3613 auto listRetcode = GetStreamerInfoListImpl(/*lookupSICache*/ true); // NOLINT: silence clang-tidy warnings
3614 TList *list = listRetcode.fList;
3615 auto retcode = listRetcode.fReturnCode;
3616 if (!list) {
3617 if (retcode) MakeZombie();
3618 return;
3619 }
3620
3621 list->SetOwner(kFALSE);
3622
3623 if (gDebug > 0) Info("ReadStreamerInfo", "called for file %s",GetName());
3624
3626
3628 if (version > 1000000) version -= 1000000;
3629 if (version < 53419 || (59900 < version && version < 59907)) {
3630 // We need to update the fCheckSum field of the TStreamerBase.
3631
3632 // loop on all TStreamerInfo classes
3633 TObjLink *lnk = list->FirstLink();
3634 while (lnk) {
3635 info = (TStreamerInfo*)lnk->GetObject();
3636 if (!info || info->IsA() != TStreamerInfo::Class()) {
3637 lnk = lnk->Next();
3638 continue;
3639 }
3640 TIter next(info->GetElements());
3642 while ((element = (TStreamerElement*) next())) {
3643 TStreamerBase *base = dynamic_cast<TStreamerBase*>(element);
3644 if (!base) continue;
3645 if (base->GetBaseCheckSum() != 0) continue;
3646 TStreamerInfo *baseinfo = (TStreamerInfo*)list->FindObject(base->GetName());
3647 if (baseinfo) {
3648 base->SetBaseCheckSum(baseinfo->GetCheckSum());
3649 }
3650 }
3651 lnk = lnk->Next();
3652 }
3653 }
3654
3655 std::vector<Int_t> si_uids;
3656 // loop on all TStreamerInfo classes
3657 for (int mode=0;mode<2; ++mode) {
3658 // In order for the collection proxy to be initialized properly, we need
3659 // to setup the TStreamerInfo for non-stl class before the stl classes.
3660 TObjLink *lnk = list->FirstLink();
3661 while (lnk) {
3662 info = (TStreamerInfo*)lnk->GetObject();
3663 if (!info) {
3664 lnk = lnk->Next();
3665 continue;
3666 }
3667 if (info->IsA() != TStreamerInfo::Class()) {
3668 if (mode==1) {
3669 TObject *obj = (TObject*)info;
3670 if (strcmp(obj->GetName(),"listOfRules")==0) {
3671#if 0
3672 // Completely ignore the rules for now.
3673 TList *listOfRules = (TList*)obj;
3674 TObjLink *rulelnk = listOfRules->FirstLink();
3675 while (rulelnk) {
3676 TObjString *rule = (TObjString*)rulelnk->GetObject();
3677 TClass::AddRule( rule->String().Data() );
3678 rulelnk = rulelnk->Next();
3679 }
3680#endif
3681 } else {
3682 Warning("ReadStreamerInfo","%s has a %s in the list of TStreamerInfo.", GetName(), info->IsA()->GetName());
3683 }
3684 info->SetBit(kCanDelete);
3685 }
3686 lnk = lnk->Next();
3687 continue;
3688 }
3689 // This is a quick way (instead of parsing the name) to see if this is
3690 // the description of an STL container.
3691 if (info->GetElements()==0) {
3692 Warning("ReadStreamerInfo","The StreamerInfo for %s does not have a list of elements.",info->GetName());
3693 lnk = lnk->Next();
3694 continue;
3695 }
3696 TObject *element = info->GetElements()->UncheckedAt(0);
3697 Bool_t isstl = element && strcmp("This",element->GetName())==0;
3698
3699 if ( (!isstl && mode ==0) || (isstl && mode ==1) ) {
3700 // Skip the STL container the first time around
3701 // Skip the regular classes the second time around;
3702 info->BuildCheck(this);
3703 Int_t uid = info->GetNumber();
3705 if (uid >= asize && uid <100000) fClassIndex->Set(2*asize);
3706 if (uid >= 0 && uid < fClassIndex->GetSize()) {
3707 si_uids.push_back(uid);
3708 fClassIndex->fArray[uid] = 1;
3709 }
3710 else if (!isstl && !info->GetClass()->IsSyntheticPair()) {
3711 printf("ReadStreamerInfo, class:%s, illegal uid=%d\n",info->GetName(),uid);
3712 }
3713 if (gDebug > 0) printf(" -class: %s version: %d info read at slot %d\n",info->GetName(), info->GetClassVersion(),uid);
3714 }
3715 lnk = lnk->Next();
3716 }
3717 }
3718 fClassIndex->fArray[0] = 0;
3719 list->Clear(); //this will delete all TStreamerInfo objects with kCanDelete bit set
3720 delete list;
3721
3722 // We are done processing the record, let future calls and other threads that it
3723 // has been done.
3724 fgTsSIHashes.Insert(listRetcode.fHash, std::move(si_uids));
3725}
3726
3727////////////////////////////////////////////////////////////////////////////////
3728/// Specify if the streamerinfos must be read at file opening.
3729///
3730/// If fgReadInfo is true (default) TFile::ReadStreamerInfo is called
3731/// when opening the file.
3732/// It may be interesting to set fgReadInfo to false to speedup the file
3733/// opening time or in case libraries containing classes referenced
3734/// by the file have not yet been loaded.
3735/// if fgReadInfo is false, one can still read the StreamerInfo with
3736/// myfile.ReadStreamerInfo();
3741}
3742
3743////////////////////////////////////////////////////////////////////////////////
3744/// If the streamerinfos are to be read at file opening.
3745///
3746/// See TFile::SetReadStreamerInfo for more documentation.
3751}
3752
3753////////////////////////////////////////////////////////////////////////////////
3754/// Show the StreamerInfo of all classes written to this file.
3757{
3758 TList *list = GetStreamerInfoList();
3759 if (!list) return;
3760
3761 list->ls();
3762 delete list;
3763}
3764
3765////////////////////////////////////////////////////////////////////////////////
3766/// Check if the ProcessID pidd is already in the file,
3767/// if not, add it and return the index number in the local file list.
3770{
3771 TProcessID *pid = pidd;
3772 if (!pid) pid = TProcessID::GetPID();
3775 for (Int_t i=0;i<npids;i++) {
3776 if (pids->At(i) == pid) return (UShort_t)i;
3777 }
3778
3780 pids->AddAtAndExpand(pid,npids);
3781 pid->IncrementCount();
3782 char name[32];
3783 snprintf(name,32,"ProcessID%d",npids);
3784 this->WriteTObject(pid,name);
3785 this->IncrementProcessIDs();
3786 if (gDebug > 0) {
3787 Info("WriteProcessID", "name=%s, file=%s", name, GetName());
3788 }
3789 return (UShort_t)npids;
3790}
3791
3792
3793////////////////////////////////////////////////////////////////////////////////
3794/// Write the list of TStreamerInfo as a single object in this file
3795/// The class Streamer description for all classes written to this file
3796/// is saved. See class TStreamerInfo.
3799{
3800 //if (!gFile) return;
3801 if (!fWritable) return;
3802 if (!fClassIndex) return;
3803 if (fIsPcmFile) return; // No schema evolution for ROOT PCM files.
3804 if (fClassIndex->fArray[0] == 0
3805 && fSeekInfo != 0) {
3806 // No need to update the index if no new classes added to the file
3807 // but write once an empty StreamerInfo list to mark that there is no need
3808 // for StreamerInfos in this file.
3809 return;
3810 }
3811 if (gDebug > 0) Info("WriteStreamerInfo", "called for file %s",GetName());
3812
3814
3815 // build a temporary list with the marked files
3816 TIter next(gROOT->GetListOfStreamerInfo());
3818 TList list;
3820 listOfRules.SetOwner(kTRUE);
3821 listOfRules.SetName("listOfRules");
3822 std::set<TClass*> classSet;
3823
3824 while ((info = (TStreamerInfo*)next())) {
3825 Int_t uid = info->GetNumber();
3826 if (fClassIndex->fArray[uid]) {
3827 list.Add(info);
3828 if (gDebug > 0) printf(" -class: %s info number %d saved\n",info->GetName(),uid);
3829
3830 // Add the IO customization rules to the list to be saved for the underlying
3831 // class but make sure to add them only once.
3832 TClass *clinfo = info->GetClass();
3833 if (clinfo && clinfo->GetSchemaRules()) {
3834 if ( classSet.find( clinfo ) == classSet.end() ) {
3835 if (gDebug > 0) printf(" -class: %s stored the I/O customization rules\n",info->GetName());
3836
3837 TObjArrayIter it( clinfo->GetSchemaRules()->GetRules() );
3839 while( (rule = (ROOT::TSchemaRule*)it.Next()) ) {
3840 TObjString *obj = new TObjString();
3841 rule->AsString(obj->String());
3842 listOfRules.Add(obj);
3843 }
3844 classSet.insert(clinfo);
3845 }
3846 }
3847 }
3848 }
3849
3850 // Write the StreamerInfo list even if it is empty.
3851 fClassIndex->fArray[0] = 2; //to prevent adding classes in TStreamerInfo::TagFile
3852
3853 if (listOfRules.GetEntries()) {
3854 // Only add the list of rules if we have something to say.
3855 list.Add(&listOfRules);
3856 }
3857
3858 //free previous StreamerInfo record
3860 //Create new key
3861 TKey key(&list,"StreamerInfo",GetBestBuffer(), this);
3862 fKeys->Remove(&key);
3863 fSeekInfo = key.GetSeekKey();
3864 fNbytesInfo = key.GetNbytes();
3865 SumBuffer(key.GetObjlen());
3866 key.WriteFile(0);
3867
3868 fClassIndex->fArray[0] = 0;
3869
3870 list.RemoveLast(); // remove the listOfRules.
3871}
3872
3873////////////////////////////////////////////////////////////////////////////////
3874/// Open a file for reading through the file cache.
3875///
3876/// The file will be downloaded to the cache and opened from there.
3877/// If the download fails, it will be opened remotely.
3878/// The file will be downloaded to the directory specified by SetCacheFileDir().
3880TFile *TFile::OpenFromCache(const char *name, Option_t *, const char *ftitle,
3882{
3883 TFile *f = nullptr;
3884
3885 if (fgCacheFileDir == "") {
3886 ::Warning("TFile::OpenFromCache",
3887 "you want to read through a cache, but you have no valid cache "
3888 "directory set - reading remotely");
3889 ::Info("TFile::OpenFromCache", "set cache directory using TFile::SetCacheFileDir()");
3890 } else {
3891 TUrl fileurl(name);
3892
3893 if ((!strcmp(fileurl.GetProtocol(), "file"))) {
3894 // it makes no sense to read local files through a file cache
3895 if (!fgCacheFileForce)
3896 ::Warning("TFile::OpenFromCache",
3897 "you want to read through a cache, but you are reading "
3898 "local files - CACHEREAD disabled");
3899 } else {
3900 // this is a remote file and worthwhile to be put into the local cache
3901 // now create cachepath to put it
3905 cachefilepath += fileurl.GetFile();
3907 if ((gSystem->mkdir(cachefilepathbasedir, kTRUE) < 0) &&
3909 ::Warning("TFile::OpenFromCache","you want to read through a cache, but I "
3910 "cannot create the directory %s - CACHEREAD disabled",
3911 cachefilepathbasedir.Data());
3912 } else {
3913 // check if this should be a zip file
3914 if (strlen(fileurl.GetAnchor())) {
3915 // remove the anchor and change the target name
3916 cachefilepath += "__";
3917 cachefilepath += fileurl.GetAnchor();
3918 fileurl.SetAnchor("");
3919 }
3920 if (strstr(name,"zip=")) {
3921 // filter out this option and change the target cache name
3922 TString urloptions = fileurl.GetOptions();
3924 TObjArray *objOptions = urloptions.Tokenize("&");
3925 Int_t optioncount = 0;
3927 for (Int_t n = 0; n < objOptions->GetEntries(); n++) {
3929 TObjArray *objTags = loption.Tokenize("=");
3930 if (objTags->GetEntries() == 2) {
3931 TString key = ((TObjString*)objTags->At(0))->GetName();
3932 TString value = ((TObjString*)objTags->At(1))->GetName();
3933 if (key.CompareTo("zip", TString::kIgnoreCase)) {
3934 if (optioncount!=0) {
3935 newoptions += "&";
3936 }
3937 newoptions += key;
3938 newoptions += "=";
3939 newoptions += value;
3940 ++optioncount;
3941 } else {
3942 zipname = value;
3943 }
3944 }
3945 delete objTags;
3946 }
3947 delete objOptions;
3948 fileurl.SetOptions(newoptions.Data());
3949 cachefilepath += "__";
3951 fileurl.SetAnchor("");
3952 }
3953
3955
3956 // check if file is in the cache
3957 Long_t id;
3958 Long64_t size;
3959 Long_t flags;
3960 Long_t modtime;
3961 if (!gSystem->GetPathInfo(cachefilepath, &id, &size, &flags, &modtime)) {
3962 // file is in the cache
3964 char cacheblock[256];
3965 char remotblock[256];
3966 // check the remote file for it's size and compare some magic bytes
3967 TString cfurl;
3969 cfurl += "?filetype=raw";
3970 TUrl rurl(name);
3971 TString ropt = rurl.GetOptions();
3972 ropt += "&filetype=raw";
3973 rurl.SetOptions(ropt);
3974
3977
3978 TFile *cachefile = TFile::Open(cfurl, "READ");
3979 TFile *remotfile = TFile::Open(rurl.GetUrl(), "READ");
3980
3982
3983 if (!cachefile) {
3984 need2copy = kTRUE;
3985 ::Error("TFile::OpenFromCache",
3986 "cannot open the cache file to check cache consistency");
3987 return nullptr;
3988 }
3989
3990 if (!remotfile) {
3991 ::Error("TFile::OpenFromCache",
3992 "cannot open the remote file to check cache consistency");
3993 return nullptr;
3994 }
3995
3996 cachefile->Seek(0);
3997 remotfile->Seek(0);
3998
3999 if ((!cachefile->ReadBuffer(cacheblock,256)) &&
4000 (!remotfile->ReadBuffer(remotblock,256))) {
4001 if (memcmp(cacheblock, remotblock, 256)) {
4002 ::Warning("TFile::OpenFromCache", "the header of the cache file "
4003 "differs from the remote file - forcing an update");
4004 need2copy = kTRUE;
4005 }
4006 } else {
4007 ::Warning("TFile::OpenFromCache", "the header of the cache and/or "
4008 "remote file are not readable - forcing an update");
4009 need2copy = kTRUE;
4010 }
4011
4012 delete remotfile;
4013 delete cachefile;
4014 }
4015 } else {
4016 need2copy = kTRUE;
4017 }
4018
4019 // try to fetch the file (disable now the forced caching)
4022 if (need2copy) {
4023 const auto cachefilepathtmp = cachefilepath + std::to_string(gSystem->GetPid()) + ".tmp";
4025 ::Warning("TFile::OpenFromCache",
4026 "you want to read through a cache, but I "
4027 "cannot make a cache copy of %s - CACHEREAD disabled",
4028 cachefilepathbasedir.Data());
4030 return nullptr;
4031 }
4032 if (gSystem->AccessPathName(cachefilepath)) // then file _does not_ exist (weird convention)
4034 else // another process or thread already wrote a file with the same name while we were copying it
4036 }
4038 ::Info("TFile::OpenFromCache", "using local cache copy of %s [%s]", name, cachefilepath.Data());
4039 // finally we have the file and can open it locally
4040 fileurl.SetProtocol("file");
4041 fileurl.SetFile(cachefilepath);
4042
4045 tagfile += ".ROOT.cachefile";
4046 // we symlink this file as a ROOT cached file
4048 return TFile::Open(fileurl.GetUrl(), "READ", ftitle, compress, netopt);
4049 }
4050 }
4051 }
4052
4053 // Failed
4054 return f;
4055}
4056
4057////////////////////////////////////////////////////////////////////////////////
4058/// Create / open a file
4059///
4060/// The type of the file can be either a
4061/// TFile, TNetFile, TWebFile or any TFile derived class for which an
4062/// plugin library handler has been registered with the plugin manager
4063/// (for the plugin manager see the TPluginManager class). The returned
4064/// type of TFile depends on the file name specified by 'url'.
4065/// If 'url' is a '|'-separated list of file URLs, the 'URLs' are tried
4066/// sequentially in the specified order until a successful open.
4067/// If the file starts with "root:", "roots:" or "rootk:" a TNetFile object
4068/// will be returned, with "http:" a TWebFile, with "file:" a local TFile,
4069/// etc. (see the list of TFile plugin handlers in $ROOTSYS/etc/system.rootrc
4070/// for regular expressions that will be checked) and as last a local file will
4071/// be tried.
4072/// Before opening a file via TNetFile a check is made to see if the URL
4073/// specifies a local file. If that is the case the file will be opened
4074/// via a normal TFile. To force the opening of a local file via a
4075/// TNetFile use either TNetFile directly or specify as host "localhost".
4076/// The netopt argument is only used by TNetFile. For the meaning of the
4077/// options and other arguments see the constructors of the individual
4078/// file classes. In case of error, it returns a nullptr.
4079///
4080/// For TFile implementations supporting asynchronous file open, see
4081/// TFile::AsyncOpen(...), it is possible to request a timeout with the
4082/// option <b>`TIMEOUT=<secs>`</b>: the timeout must be specified in seconds and
4083/// it will be internally checked with granularity of one millisec.
4084/// For remote files there is the option: <b>CACHEREAD</b> opens an existing
4085/// file for reading through the file cache. The file will be downloaded to
4086/// the cache and opened from there. If the download fails, it will be opened remotely.
4087/// The file will be downloaded to the directory specified by SetCacheFileDir().
4088///
4089/// *The caller is responsible for deleting the pointer.*
4090/// In READ mode, a nullptr is returned if the file does not exist or cannot be opened.
4091/// In CREATE mode, a nullptr is returned if the file already exists or cannot be created.
4092/// In RECREATE mode, a nullptr is returned if the file can not be created.
4093/// In UPDATE mode, a nullptr is returned if the file cannot be created or opened.
4095TFile *TFile::Open(const char *url, Option_t *options, const char *ftitle,
4097{
4099 TFile *f = nullptr;
4101
4102 // Check input
4103 if (!url || strlen(url) <= 0) {
4104 ::Error("TFile::Open", "no url specified");
4105 return f;
4106 }
4107
4110
4111#ifdef R__UNIX
4112 // If URL is a file on an EOS FUSE mount, attempt redirection to XRootD protocol.
4113 if (gEnv->GetValue("TFile.CrossProtocolRedirects", 1) == 1) {
4114 TUrl fileurl(expandedUrl, /* default is file */ kTRUE);
4115 if (strcmp(fileurl.GetProtocol(), "file") == 0) {
4116 ssize_t len = getxattr(fileurl.GetFile(), "eos.url.xroot", nullptr, 0);
4117 if (len > 0) {
4118 std::string xurl(len, 0);
4119 if (getxattr(fileurl.GetFile(), "eos.url.xroot", &xurl[0], len) == len) {
4120 if ((f = TFile::Open(xurl.c_str(), options, ftitle, compress, netopt))) {
4121 if (!f->IsZombie()) {
4122 return f;
4123 } else {
4124 delete f;
4125 f = nullptr;
4126 }
4127 }
4128 }
4129 }
4130 }
4131 }
4132#endif
4133
4134 // If a timeout has been specified extract the value and try to apply it (it requires
4135 // support for asynchronous open, though; the following is completely transparent if
4136 // such support if not available for the required protocol)
4137 TString opts(options);
4138 Int_t ito = opts.Index("TIMEOUT=");
4139 if (ito != kNPOS) {
4140 TString sto = opts(ito + strlen("TIMEOUT="), opts.Length());
4141 while (!(sto.IsDigit()) && !(sto.IsNull())) { sto.Remove(sto.Length()-1,1); }
4142 if (!(sto.IsNull())) {
4143 // Timeout in millisecs
4144 Int_t toms = sto.Atoi() * 1000;
4145 if (gDebug > 0) ::Info("TFile::Open", "timeout of %d millisec requested", toms);
4146 // Remove from the options field
4147 sto.Insert(0, "TIMEOUT=");
4148 opts.ReplaceAll(sto, "");
4149 // Asynchronous open
4151 // Check the result in steps of 1 millisec
4154 Int_t xtms = toms;
4155 while (aos == TFile::kAOSInProgress && xtms > 0) {
4156 gSystem->Sleep(1);
4157 xtms -= 1;
4159 }
4161 // Do open the file now
4162 f = TFile::Open(fh);
4163 if (gDebug > 0) {
4164 if (aos == TFile::kAOSSuccess)
4165 ::Info("TFile::Open", "waited %d millisec for asynchronous open", toms - xtms);
4166 else
4167 ::Info("TFile::Open", "timeout option not supported (requires asynchronous"
4168 " open support)");
4169 }
4170 } else {
4171 if (xtms <= 0)
4172 ::Error("TFile::Open", "timeout expired while opening '%s'", expandedUrl.Data());
4173 // Cleanup the request
4174 SafeDelete(fh);
4175 }
4176 // Done
4177 return f;
4178 } else {
4179 ::Warning("TFile::Open", "incomplete 'TIMEOUT=' option specification - ignored");
4180 opts.ReplaceAll("TIMEOUT=", "");
4181 }
4182 }
4183
4184 // We will use this from now on
4185 const char *option = opts;
4186
4187 // Many URLs? Redirect output and print errors in case of global failure
4189 Ssiz_t ip = namelist.Index("|");
4190 Bool_t rediroutput = (ip != kNPOS &&
4191 ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
4193 if (rediroutput) {
4194 TString outf = ".TFileOpen_";
4196 if (fout) {
4197 fclose(fout);
4198 gSystem->RedirectOutput(outf, "w", &rh);
4199 }
4200 }
4201
4202 // Try sequentially all names in 'names'
4203 TString name, n;
4204 Ssiz_t from = 0;
4205 while (namelist.Tokenize(n, from, "|") && !f) {
4206
4207 // check if we read through a file cache
4208 if (!strcasecmp(option, "CACHEREAD") ||
4209 ((!strcasecmp(option,"READ") || !option[0]) && fgCacheFileForce)) {
4210 // Try opening the file from the cache
4212 return f;
4213 }
4214
4216
4217 // change names to be recognized by the plugin manager
4218 // e.g. /protocol/path/to/file.root -> protocol:/path/to/file.root
4219 TUrl urlname(n, kTRUE);
4220 name = urlname.GetUrl();
4221 // Check first if a pending async open request matches this one
4222 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4224 TFileOpenHandle *fh = nullptr;
4225 while ((fh = (TFileOpenHandle *)nxr()))
4226 if (fh->Matches(name))
4227 return TFile::Open(fh);
4228 }
4229
4230 TString urlOptions(urlname.GetOptions());
4231 if (urlOptions.BeginsWith("pmerge") || urlOptions.Contains("&pmerge") || urlOptions.Contains(" pmerge")) {
4232 type = kMerge;
4233
4234 // Pass the full name including the url options:
4235 f = (TFile*) gROOT->ProcessLineFast(TString::Format("new TParallelMergingFile(\"%s\",\"%s\",\"%s\",%d)",n.Data(),option,ftitle,compress));
4236
4237 } else {
4238 // Resolve the file type; this also adjusts names
4239 TString lfname = gEnv->GetValue("Path.Localroot", "");
4241
4242 if (type == kLocal) {
4243
4244 // Local files
4245 if (lfname.IsNull()) {
4246 urlname.SetHost("");
4247 urlname.SetProtocol("file");
4248 lfname = urlname.GetUrl();
4249 }
4250 f = new TFile(lfname.Data(), option, ftitle, compress);
4251
4252 } else if (type == kNet) {
4253
4254 // Network files
4255 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
4256 if (h->LoadPlugin() == -1)
4257 return nullptr;
4258 f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
4259 }
4260
4261 } else if (type == kWeb) {
4262
4263 // Web files
4264 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name))) {
4265 if (h->LoadPlugin() == -1)
4266 return nullptr;
4267 f = (TFile*) h->ExecPlugin(2, name.Data(), option);
4268 }
4269
4270 } else if (type == kFile) {
4271
4272 // 'file:' protocol
4273 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4274 h->LoadPlugin() == 0) {
4275 name.ReplaceAll("file:", "");
4276 f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
4277 } else
4278 f = new TFile(name.Data(), option, ftitle, compress);
4279
4280 } else {
4281
4282 // no recognized specification: try the plugin manager
4283 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name.Data()))) {
4284 if (h->LoadPlugin() == -1)
4285 return nullptr;
4286 TClass *cl = TClass::GetClass(h->GetClass());
4287 if (cl && cl->InheritsFrom("TNetFile"))
4288 f = (TFile*) h->ExecPlugin(5, name.Data(), option, ftitle, compress, netopt);
4289 else
4290 f = (TFile*) h->ExecPlugin(4, name.Data(), option, ftitle, compress);
4291 } else {
4292 // Just try to open it locally but via TFile::Open, so that we pick-up the correct
4293 // plug-in in the case file name contains information about a special backend (e.g.)
4294 if (strcmp(name, urlname.GetFileAndOptions()) != 0)
4295 f = TFile::Open(urlname.GetFileAndOptions(), option, ftitle, compress);
4296 }
4297 }
4298 }
4299
4300 if (f && f->IsZombie()) {
4301 TString newUrl = f->GetNewUrl();
4302 delete f;
4303 if( newUrl.Length() && (newUrl != name) && gEnv->GetValue("TFile.CrossProtocolRedirects", 1) )
4305 else
4306 f = nullptr;
4307 }
4308 }
4309
4310 if (rediroutput) {
4311 // Restore output to stdout
4312 gSystem->RedirectOutput(0, "", &rh);
4313 // If we failed print error messages
4314 if (!f)
4316 // Remove the file
4317 gSystem->Unlink(rh.fFile);
4318 }
4319
4320 // if the file is writable, non local, and not opened in raw mode
4321 // we create a default write cache of 512 KBytes
4322 if (type != kLocal && type != kFile &&
4323 f && f->IsWritable() && !f->IsRaw()) {
4324 new TFileCacheWrite(f, 1);
4325 }
4326
4327 return f;
4328}
4329
4330////////////////////////////////////////////////////////////////////////////////
4331/// Submit an asynchronous open request.
4332
4333/// See TFile::Open(const char *, ...) for an
4334/// explanation of the arguments. A handler is returned which is to be passed
4335/// to TFile::Open(TFileOpenHandle *) to get the real TFile instance once
4336/// the file is open.
4337/// This call never blocks and it is provided to allow parallel submission
4338/// of file opening operations expected to take a long time.
4339/// TFile::Open(TFileOpenHandle *) may block if the file is not yet ready.
4340/// The sequence
4341///
4342/// TFile::Open(TFile::AsyncOpen(const char *, ...))
4343///
4344/// is equivalent to
4345///
4346/// TFile::Open(const char *, ...)
4347///
4348/// To be effective, the underlying TFile implementation must be able to
4349/// support asynchronous open functionality. Currently, only TXNetFile
4350/// supports it. If the functionality is not implemented, this call acts
4351/// transparently by returning an handle with the arguments for the
4352/// standard synchronous open run by TFile::Open(TFileOpenHandle *).
4353/// The retuned handle will be adopted by TFile after opening completion
4354/// in TFile::Open(TFileOpenHandle *); if opening is not finalized the
4355/// handle must be deleted by the caller.
4358 const char *ftitle, Int_t compress,
4359 Int_t netopt)
4360{
4361 TFileOpenHandle *fh = nullptr;
4362 TFile *f = nullptr;
4364
4365 // Check input
4366 if (!url || strlen(url) <= 0) {
4367 ::Error("TFile::AsyncOpen", "no url specified");
4368 return fh;
4369 }
4370
4371 // Many URLs? Redirect output and print errors in case of global failure
4374 Ssiz_t ip = namelist.Index("|");
4375 Bool_t rediroutput = (ip != kNPOS &&
4376 ip != namelist.Length()-1 && gDebug <= 0) ? kTRUE : kFALSE;
4378 if (rediroutput) {
4379 TString outf = ".TFileAsyncOpen_";
4381 if (fout) {
4382 fclose(fout);
4383 gSystem->RedirectOutput(outf, "w", &rh);
4384 }
4385 }
4386
4387 // Try sequentially all names in 'names'
4388 TString name, n;
4389 Ssiz_t from = 0;
4390 while (namelist.Tokenize(n, from, "|") && !f) {
4391
4392 // change names to be recognized by the plugin manager
4393 // e.g. /protocol/path/to/file.root -> protocol:/path/to/file.root
4394 TUrl urlname(n, kTRUE);
4395 name = urlname.GetUrl();
4396
4397 // Resolve the file type; this also adjusts names
4399
4400 TPluginHandler *h = nullptr;
4401
4402 // Here we send the asynchronous request if the functionality is implemented
4403 if (type == kNet) {
4404 // Network files
4405 if ((h = gROOT->GetPluginManager()->FindHandler("TFile", name)) &&
4406 (!strcmp(h->GetClass(),"TXNetFile") || !strcmp(h->GetClass(),"TNetXNGFile"))
4407 && h->LoadPlugin() == 0) {
4408 f = (TFile*) h->ExecPlugin(6, name.Data(), option, ftitle, compress, netopt, kTRUE);
4409 notfound = kFALSE;
4410 }
4411 }
4412 }
4413
4414 if (rediroutput) {
4415 // Restore output to stdout
4416 gSystem->RedirectOutput(0, "", &rh);
4417 // If we failed print error messages
4418 if (!notfound && !f)
4420 // Remove the file
4421 gSystem->Unlink(rh.fFile);
4422 }
4423
4424 // Make sure that no error occurred
4425 if (notfound) {
4426 SafeDelete(f);
4427 // Save the arguments in the handler, so that a standard open can be
4428 // attempted later on
4430 } else if (f) {
4431 // Fill the opaque handler to be use to attach the file later on
4432 fh = new TFileOpenHandle(f);
4433 }
4434
4435 // Record this request
4436 if (fh) {
4437 // Create the lst, if not done already
4440 fgAsyncOpenRequests->Add(fh);
4441 }
4442
4443 // We are done
4444 return fh;
4445}
4446
4447////////////////////////////////////////////////////////////////////////////////
4448/// Waits for the completion of an asynchronous open request.
4449///
4450/// Returns the pointer to the associated TFile, transferring ownership of the
4451/// handle to the TFile instance.
4454{
4455 TFile *f = nullptr;
4456
4457 // Note that the request may have failed
4458 if (fh && fgAsyncOpenRequests) {
4459 // Remove it from the pending list: we need to do it at this level to avoid
4460 // recursive calls in the standard TFile::Open
4461 fgAsyncOpenRequests->Remove(fh);
4462 // Was asynchronous open functionality implemented?
4463 if ((f = fh->GetFile()) && !(f->IsZombie())) {
4464 // Yes: wait for the completion of the open phase, if needed
4465 Bool_t cr = (!strcmp(f->GetOption(),"CREATE") ||
4466 !strcmp(f->GetOption(),"RECREATE") ||
4467 !strcmp(f->GetOption(),"NEW")) ? kTRUE : kFALSE;
4468 f->Init(cr);
4469 } else {
4470 // No: process a standard open
4471 f = TFile::Open(fh->GetName(), fh->GetOpt(), fh->GetTitle(),
4472 fh->GetCompress(), fh->GetNetOpt());
4473 }
4474
4475 // Adopt the handle instance in the TFile instance so that it gets
4476 // automatically cleaned up
4477 if (f) f->fAsyncHandle = fh;
4478 }
4479
4480 // We are done
4481 return f;
4482}
4483
4484////////////////////////////////////////////////////////////////////////////////
4485/// Interface to system open. All arguments like in POSIX open().
4487Int_t TFile::SysOpen(const char *pathname, Int_t flags, UInt_t mode)
4488{
4489#if defined(R__WINGCC)
4490 // ALWAYS use binary mode - even cygwin text should be in unix format
4491 // although this is posix default it has to be set explicitly
4492 return ::open(pathname, flags | O_BINARY, mode);
4493#elif defined(R__SEEK64)
4494 return ::open64(pathname, flags, mode);
4495#else
4496 return ::open(pathname, flags, mode);
4497#endif
4498}
4499
4500////////////////////////////////////////////////////////////////////////////////
4501/// Interface to system close. All arguments like in POSIX close().
4504{
4505 if (fd < 0) return 0;
4506 return ::close(fd);
4507}
4508
4509////////////////////////////////////////////////////////////////////////////////
4510/// Interface to system read. All arguments like in POSIX read().
4512Int_t TFile::SysRead(Int_t fd, void *buf, Int_t len)
4513{
4514 return ::read(fd, buf, len);
4515}
4516
4517////////////////////////////////////////////////////////////////////////////////
4518/// Interface to system write. All arguments like in POSIX write().
4520Int_t TFile::SysWrite(Int_t fd, const void *buf, Int_t len)
4521{
4522 return ::write(fd, buf, len);
4523}
4524////////////////////////////////////////////////////////////////////////////////
4525/// Interface to system lseek.
4526///
4527/// All arguments like in POSIX lseek()
4528/// except that the offset and return value are of a type which are
4529/// able to handle 64 bit file systems.
4532{
4533#if defined (R__SEEK64)
4534 return ::lseek64(fd, offset, whence);
4535#elif defined(WIN32)
4536 return ::_lseeki64(fd, offset, whence);
4537#else
4538 return ::lseek(fd, offset, whence);
4539#endif
4540}
4541
4542////////////////////////////////////////////////////////////////////////////////
4543/// Return file stat information.
4544///
4545/// The interface and return value is
4546/// identical to TSystem::GetPathInfo(). The function returns 0 in
4547/// case of success and 1 if the file could not be stat'ed.
4550 Long_t *modtime)
4551{
4552 return gSystem->GetPathInfo(fRealName, id, size, flags, modtime);
4553}
4554
4555////////////////////////////////////////////////////////////////////////////////
4556/// Interface to system fsync. All arguments like in POSIX fsync().
4559{
4560 if (TestBit(kDevNull)) return 0;
4561
4562#ifndef WIN32
4563 return ::fsync(fd);
4564#else
4565 return ::_commit(fd);
4566#endif
4567}
4568
4569////////////////////////////////////////////////////////////////////////////////
4570/// Return the total number of bytes written so far to the file.
4575}
4576
4577////////////////////////////////////////////////////////////////////////////////
4578/// Static function returning the total number of bytes read from all files.
4583}
4584
4585////////////////////////////////////////////////////////////////////////////////
4586/// Static function returning the total number of bytes written to all files.
4587/// Does not take into account what might still be in the write caches.
4592}
4593
4594////////////////////////////////////////////////////////////////////////////////
4595/// Static function returning the total number of read calls from all files.
4600}
4601
4602////////////////////////////////////////////////////////////////////////////////
4603/// Static function returning the readahead buffer size.
4608}
4609
4610//______________________________________________________________________________
4612
4613//______________________________________________________________________________
4615
4616//______________________________________________________________________________
4618
4619//______________________________________________________________________________
4621
4622//______________________________________________________________________________
4624
4625//______________________________________________________________________________
4627
4628////////////////////////////////////////////////////////////////////////////////
4629/// Sets the directory where to locally stage/cache remote files.
4630/// If the directory is not writable by us return kFALSE.
4634{
4636 if (!cached.EndsWith("/"))
4637 cached += "/";
4638
4640 // try to create it
4643 ::Error("TFile::SetCacheFileDir", "no sufficient permissions on cache directory %s or cannot create it", TString(cachedir).Data());
4644 fgCacheFileDir = "";
4645 return kFALSE;
4646 }
4647 gSystem->Chmod(cached, 0700);
4648 }
4650 gSystem->Chmod(cached, 0700);
4654 return kTRUE;
4655}
4656
4657////////////////////////////////////////////////////////////////////////////////
4658/// Get the directory where to locally stage/cache remote files.
4660const char *TFile::GetCacheFileDir()
4661{
4662 return fgCacheFileDir;
4663}
4664
4665////////////////////////////////////////////////////////////////////////////////
4666/// Try to shrink the cache to the desired size.
4667///
4668/// With the clenupinterval you can specify the minimum amount of time after
4669/// the previous cleanup before the cleanup operation is repeated in
4670/// the cache directory
4673{
4674 if (fgCacheFileDir == "") {
4675 return kFALSE;
4676 }
4677
4678 // check the last clean-up in the cache
4679 Long_t id;
4680 Long64_t size;
4681 Long_t flags;
4682 Long_t modtime;
4683
4685 cachetagfile += ".tag.ROOT.cache";
4686 if (!gSystem->GetPathInfo(cachetagfile, &id, &size, &flags, &modtime)) {
4687 // check the time passed since last cache cleanup
4688 Long_t lastcleanuptime = ((Long_t)time(0) - modtime);
4690 ::Info("TFile::ShrinkCacheFileDir", "clean-up is skipped - last cleanup %lu seconds ago - you requested %lu", lastcleanuptime, cleanupinterval);
4691 return kTRUE;
4692 }
4693 }
4694
4695 // (re-)create the cache tag file
4696 cachetagfile += "?filetype=raw";
4697 TFile *tagfile = nullptr;
4698
4699 if (!(tagfile = TFile::Open(cachetagfile, "RECREATE"))) {
4700 ::Error("TFile::ShrinkCacheFileDir", "cannot create the cache tag file %s", cachetagfile.Data());
4701 return kFALSE;
4702 }
4703
4704 // the shortest garbage collector in the world - one long line of PERL - unlinks files only,
4705 // if there is a symbolic link with '.ROOT.cachefile' for safety ;-)
4706
4707 TString cmd;
4708#if defined(R__WIN32)
4709 cmd = "echo <TFile::ShrinkCacheFileDir>: cleanup to be implemented";
4710#elif defined(R__MACOSX)
4711 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);
4712#else
4713 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);
4714#endif
4715
4716 tagfile->WriteBuffer(cmd, 4096);
4717 delete tagfile;
4718
4719 if ((gSystem->Exec(cmd)) != 0) {
4720 ::Error("TFile::ShrinkCacheFileDir", "error executing clean-up script");
4721 return kFALSE;
4722 }
4723
4724 return kTRUE;
4725}
4726
4727////////////////////////////////////////////////////////////////////////////////
4728/// Sets open timeout time (in ms). Returns previous timeout value.
4735}
4736
4737////////////////////////////////////////////////////////////////////////////////
4738/// Returns open timeout (in ms).
4743}
4744
4745////////////////////////////////////////////////////////////////////////////////
4746/// Sets only staged flag. Returns previous value of flag.
4747/// When true we check before opening the file if it is staged, if not,
4748/// the open fails.
4755}
4756
4757////////////////////////////////////////////////////////////////////////////////
4758/// Returns staged only flag.
4761{
4762 return fgOnlyStaged;
4763}
4764
4765////////////////////////////////////////////////////////////////////////////////
4766/// Return kTRUE if 'url' matches the coordinates of this file.
4767///
4768/// The check is implementation dependent and may need to be overload
4769/// by each TFile implementation relying on this check.
4770/// The default implementation checks the file name only.
4772Bool_t TFile::Matches(const char *url)
4773{
4774 // Check the full URL, including port and FQDN.
4775 TUrl u(url);
4776
4777 // Check
4778 if (!strcmp(u.GetFile(), fUrl.GetFile())) {
4779 // Check ports
4780 if (u.GetPort() == fUrl.GetPort()) {
4781 if (!strcmp(u.GetHostFQDN(), fUrl.GetHostFQDN())) {
4782 // Ok, coordinates match
4783 return kTRUE;
4784 }
4785 }
4786 }
4787
4788 // Default is not matching
4789 return kFALSE;
4790}
4791
4792////////////////////////////////////////////////////////////////////////////////
4793/// Return kTRUE if this async request matches the open request
4794/// specified by 'url'
4797{
4798 if (fFile) {
4799 return fFile->Matches(url);
4800 } else if (fName.Length() > 0){
4801 // Deep check of URLs
4802 TUrl u(url);
4803 TUrl uref(fName);
4804 if (!strcmp(u.GetFile(), uref.GetFile())) {
4805 // Check ports
4806 if (u.GetPort() == uref.GetPort()) {
4807 // Check also the host name
4808 if (!strcmp(u.GetHostFQDN(), uref.GetHostFQDN())) {
4809 // Ok, coordinates match
4810 return kTRUE;
4811 }
4812 }
4813 }
4814 }
4815
4816 // Default is not matching
4817 return kFALSE;
4818}
4819
4820////////////////////////////////////////////////////////////////////////////////
4821/// Resolve the file type as a function of the protocol field in 'name'
4822///
4823/// If defined, the string 'prefix' is added when testing the locality of
4824/// a 'name' with network-like structure (i.e. root://host//path); if the file
4825/// is local, on return 'prefix' will contain the actual local path of the file.
4828{
4830
4831 TPMERegexp re("^(root|xroot).*", "i");
4832 if (re.Match(name)) {
4833 //
4834 // Should be a network file ...
4835 type = kNet;
4836 // ... but make sure that is not local or that a remote-like connection
4837 // is forced. Treat it as local if:
4838 // i) the url points to the localhost, the file will be opened in
4839 // readonly mode and the current user has read access;
4840 // ii) the specified user is equal to the current user then open local
4841 // TFile.
4843 TUrl url(name);
4844 //
4845 // Check whether we should try to optimize for local files
4846 Bool_t forceRemote = gEnv->GetValue("Path.ForceRemote", 0);
4847 forceRemote = (forceRemote) ? kTRUE : gEnv->GetValue("TFile.ForceRemote", 0);
4848 TString opts = url.GetOptions();
4849 if (opts.Contains("remote=1"))
4851 else if (opts.Contains("remote=0"))
4853 if (!forceRemote) {
4854 // Generic locality test
4856 if (localFile) {
4857 // Local path including the prefix
4858 const char *fname = url.GetFileAndOptions();
4860 if (fname[0] == '/') {
4861 if (prefix)
4862 lfname.Form("%s%s", prefix->Data(), fname);
4863 else
4864 lfname = fname;
4865 } else if (fname[0] == '~' || fname[0] == '$') {
4866 lfname = fname;
4867 } else {
4868 lfname.Form("%s/%s", gSystem->HomeDirectory(), fname);
4869 }
4870 // If option "READ" test existence and access
4871 TString opt = option;
4872 Bool_t read = (opt.IsNull() ||
4873 !opt.CompareTo("READ", TString::kIgnoreCase)) ? kTRUE : kFALSE;
4874 if (read) {
4876 if (!gSystem->ExpandPathName(fn)) {
4878 localFile = kFALSE;
4879 }
4880 }
4881 // Return full local path if requested (and if the case)
4882 if (localFile && prefix)
4883 *prefix = lfname;
4884 }
4885 }
4886 //
4887 // Adjust the type according to findings
4888 type = (localFile) ? kLocal : type;
4889 } else if (TPMERegexp("^(http[s]?|s3http[s]?|[a]?s3|gs|gshttp[s]?){1}:", "i").Match(name)) {
4890 //
4891 // Web file
4892 type = kWeb;
4893 } else if (!strncmp(name, "file:", 5)) {
4894 //
4895 // 'file' protocol
4896 type = kFile;
4897 }
4898 // We are done
4899 return type;
4900}
4901
4902////////////////////////////////////////////////////////////////////////////////
4903/// Get status of the async open request related to 'name'.
4906{
4907 // Check the list of pending async open requests
4908 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4910 TFileOpenHandle *fh = nullptr;
4911 while ((fh = (TFileOpenHandle *)nxr()))
4912 if (fh->Matches(name))
4913 return TFile::GetAsyncOpenStatus(fh);
4914 }
4915
4916 // Check also the list of files open
4918 TSeqCollection *of = gROOT->GetListOfFiles();
4919 if (of && (of->GetSize() > 0)) {
4920 TIter nxf(of);
4921 TFile *f = nullptr;
4922 while ((f = (TFile *)nxf()))
4923 if (f->Matches(name))
4924 return f->GetAsyncOpenStatus();
4925 }
4926
4927 // Default is synchronous mode
4928 return kAOSNotAsync;
4929}
4930
4931////////////////////////////////////////////////////////////////////////////////
4932/// Get status of the async open request related to 'handle'.
4935{
4936 if (handle && handle->fFile) {
4937 if (!handle->fFile->IsZombie())
4938 return handle->fFile->GetAsyncOpenStatus();
4939 else
4940 return TFile::kAOSFailure;
4941 }
4942
4943 // Default is synchronous mode
4944 return TFile::kAOSNotAsync;
4945}
4946
4947////////////////////////////////////////////////////////////////////////////////
4948/// Get final URL for file being opened asynchronously.
4949/// Returns 0 is the information is not yet available.
4951const TUrl *TFile::GetEndpointUrl(const char* name)
4952{
4953 // Check the list of pending async open requests
4954 if (fgAsyncOpenRequests && (fgAsyncOpenRequests->GetSize() > 0)) {
4956 TFileOpenHandle *fh = nullptr;
4957 while ((fh = (TFileOpenHandle *)nxr()))
4958 if (fh->Matches(name))
4959 if (fh->fFile)
4960 return fh->fFile->GetEndpointUrl();
4961 }
4962
4963 // Check also the list of files open
4965 TSeqCollection *of = gROOT->GetListOfFiles();
4966 if (of && (of->GetSize() > 0)) {
4967 TIter nxf(of);
4968 TFile *f = nullptr;
4969 while ((f = (TFile *)nxf()))
4970 if (f->Matches(name))
4971 return f->GetEndpointUrl();
4972 }
4973
4974 // Information not yet available
4975 return (const TUrl *)nullptr;
4976}
4977
4978////////////////////////////////////////////////////////////////////////////////
4979/// Print file copy progress.
4982{
4983 fprintf(stderr, "[TFile::Cp] Total %.02f MB\t|", (Double_t)size/1048576);
4984
4985 for (int l = 0; l < 20; l++) {
4986 if (size > 0) {
4987 if (l < 20*bytesread/size)
4988 fprintf(stderr, "=");
4989 else if (l == 20*bytesread/size)
4990 fprintf(stderr, ">");
4991 else if (l > 20*bytesread/size)
4992 fprintf(stderr, ".");
4993 } else
4994 fprintf(stderr, "=");
4995 }
4996 // Allow to update the GUI while uploading files
4998 watch.Stop();
4999 Double_t lCopy_time = watch.RealTime();
5000 fprintf(stderr, "| %.02f %% [%.01f MB/s]\r",
5001 100.0*(size?(bytesread/((float)size)):1), (lCopy_time>0.)?bytesread/lCopy_time/1048576.:0.);
5002 watch.Continue();
5003}
5004
5005////////////////////////////////////////////////////////////////////////////////
5006/// Allows to copy this file to the dst URL. Returns kTRUE in case of success,
5007/// kFALSE otherwise.
5010{
5014
5015 TUrl dURL(dst, kTRUE);
5016
5017 TString oopt = "RECREATE";
5018 TString ourl = dURL.GetUrl();
5019
5020 // Files will be open in RAW mode
5021 TString raw = "filetype=raw";
5022
5023 // Set optimization options for the destination file
5024 TString opt = dURL.GetOptions();
5025 if (opt != "") opt += "&";
5026 opt += raw;
5027
5028 // AliEn files need to know where the source file is
5029 if (!strcmp(dURL.GetProtocol(), "alien"))
5030 opt += TString::Format("&source=%s", GetName());
5031
5032 dURL.SetOptions(opt);
5033
5034 char *copybuffer = nullptr;
5035
5036 TFile *sfile = this;
5037 TFile *dfile = nullptr;
5038
5039 // "RECREATE" does not work always well with XROOTD
5040 // namely when some pieces of the path are missing;
5041 // we force "NEW" in such a case
5042 if (TFile::GetType(ourl, "") == TFile::kNet) {
5043 if (gSystem->AccessPathName(ourl)) {
5044 oopt = "NEW";
5045 // Force creation of the missing parts of the path
5046 opt += "&mkpath=1";
5047 dURL.SetOptions(opt);
5048 }
5049 }
5050
5051 // Open destination file
5052 if (!(dfile = TFile::Open(dURL.GetUrl(), oopt))) {
5053 ::Error("TFile::Cp", "cannot open destination file %s", dst);
5054 goto copyout;
5055 }
5056
5057 // Probably we created a new file
5058 // We have to remove it in case of errors
5060
5061 sfile->Seek(0);
5062 dfile->Seek(0);
5063
5064 copybuffer = new char[buffersize];
5065 if (!copybuffer) {
5066 ::Error("TFile::Cp", "cannot allocate the copy buffer");
5067 goto copyout;
5068 }
5069
5072
5073 totalread = 0;
5074 filesize = sfile->GetSize();
5075
5076 watch.Start();
5077
5078 b00 = sfile->GetBytesRead();
5079
5080 do {
5082
5083 Long64_t b1 = sfile->GetBytesRead() - b00;
5084
5086 if (filesize - b1 > (Long64_t)buffersize) {
5088 } else {
5089 readsize = filesize - b1;
5090 }
5091
5092 if (readsize == 0) break;
5093
5094 Long64_t b0 = sfile->GetBytesRead();
5096 readop = sfile->ReadBuffer(copybuffer, (Int_t)readsize);
5097 read = sfile->GetBytesRead() - b0;
5098 if ((read <= 0) || readop) {
5099 ::Error("TFile::Cp", "cannot read from source file %s. readsize=%lld read=%lld readop=%d",
5100 sfile->GetName(), readsize, read, readop);
5101 goto copyout;
5102 }
5103
5104 Long64_t w0 = dfile->GetBytesWritten();
5105 writeop = dfile->WriteBuffer(copybuffer, (Int_t)read);
5106 written = dfile->GetBytesWritten() - w0;
5107 if ((written != read) || writeop) {
5108 ::Error("TFile::Cp", "cannot write %lld bytes to destination file %s", read, dst);
5109 goto copyout;
5110 }
5111 totalread += read;
5112 } while (read == (Long64_t)buffersize);
5113
5114 if (progressbar) {
5116 fprintf(stderr, "\n");
5117 }
5118
5119 success = kTRUE;
5120
5121copyout:
5122 if (dfile) dfile->Close();
5123
5124 if (dfile) delete dfile;
5125 if (copybuffer) delete[] copybuffer;
5126
5127 if (rmdestiferror && (success != kTRUE))
5128 gSystem->Unlink(dst);
5129
5130 watch.Stop();
5131 watch.Reset();
5132
5133 return success;
5134}
5135
5136////////////////////////////////////////////////////////////////////////////////
5137/// Allows to copy file from src to dst URL. Returns kTRUE in case of success,
5138/// kFALSE otherwise.
5140Bool_t TFile::Cp(const char *src, const char *dst, Bool_t progressbar,
5142{
5143 TUrl sURL(src, kTRUE);
5144
5145 // Files will be open in RAW mode
5146 TString raw = "filetype=raw";
5147
5148 // Set optimization options for the source file
5149 TString opt = sURL.GetOptions();
5150 if (opt != "") opt += "&";
5151 opt += raw;
5152 // Netx-related options:
5153 // cachesz = 4*buffersize -> 4 buffers as peak mem usage
5154 // readaheadsz = 2*buffersize -> Keep at max 4*buffersize bytes outstanding when reading
5155 // rmpolicy = 1 -> Remove from the cache the blk with the least offset
5156 opt += TString::Format("&cachesz=%d&readaheadsz=%d&rmpolicy=1", 4*buffersize, 2*buffersize);
5157 sURL.SetOptions(opt);
5158
5159 TFile *sfile = nullptr;
5160
5162
5163 // Open source file
5164 if (!(sfile = TFile::Open(sURL.GetUrl(), "READ"))) {
5165 ::Error("TFile::Cp", "cannot open source file %s", src);
5166 } else {
5168 }
5169
5170 if (sfile) {
5171 sfile->Close();
5172 delete sfile;
5173 }
5174
5175 return success;
5176}
5177
5178//______________________________________________________________________________
5179//The next statement is not active anymore on Linux.
5180//Using posix_fadvise introduces a performance penalty (10 %) on optimized files
5181//and in addition it destroys the information of TTreePerfStats
5182#if defined(R__neverLINUX) && !defined(R__WINGCC)
5184{
5185 // Read specified byte range asynchronously. Actually we tell the kernel
5186 // which blocks we are going to read so it can start loading these blocks
5187 // in the buffer cache.
5188
5189 // Shortcut to avoid having to implement dummy ReadBufferAsync() in all
5190 // I/O plugins. Override ReadBufferAsync() in plugins if async is supported.
5191 if (IsA() != TFile::Class())
5192 return kTRUE;
5193
5195 if (len == 0) {
5196 // according POSIX spec if len is zero, all data following offset
5197 // is specified. Nevertheless ROOT uses zero to probe readahead
5198 // capabilities.
5200 }
5201 Double_t start = 0;
5202 if (gPerfStats) start = TTimeStamp();
5203#if defined(R__SEEK64)
5205#else
5207#endif
5208 if (gPerfStats) {
5209 gPerfStats->FileReadEvent(this, len, start);
5210 }
5211 return (result != 0);
5212}
5213#else
5215{
5216 // Not supported yet on non Linux systems.
5217
5218 return kTRUE;
5219}
5220#endif
5221
5222////////////////////////////////////////////////////////////////////////////////
5223/// Max number of bytes to prefetch.
5224///
5225/// By default this is 75% of the
5226/// read cache size. But specific TFile implementations may need to change it
5229{
5230 TFileCacheRead *cr = nullptr;
5231 if ((cr = GetCacheRead())) {
5232 Int_t bytes = cr->GetBufferSize() / 4 * 3;
5233 return ((bytes < 0) ? 0 : bytes);
5234 }
5235 return 0;
5236}
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:525
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define h(i)
Definition RSha256.hxx:106
virtual RooAbsTestStatistic * create(const char *name, const char *title, RooAbsReal &real, RooAbsData &data, const RooArgSet &projDeps, Configuration const &cfg)=0
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:101
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:124
long long Long64_t
Definition RtypesCore.h:80
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
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
const Int_t kBEGIN
Definition TFile.cxx:183
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
R__EXTERN TPluginManager * gPluginMgr
Int_t gDebug
Definition TROOT.cxx:597
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:406
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2503
@ 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:566
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
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
void Set(Int_t n) override
Set size of this array to n chars.
Definition TArrayC.cxx:105
Int_t GetSize() const
Definition TArray.h:47
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:81
Bool_t HasInterpreterInfo() const
Definition TClass.h:410
const ROOT::Detail::TSchemaRuleSet * GetSchemaRules() const
Return the set of the schema rules if any.
Definition TClass.cxx:1932
static Bool_t AddRule(const char *rule)
Add a schema evolution customization rule.
Definition TClass.cxx:1890
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4874
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:2968
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 AppendKey(TKey *key) override
Insert key in the linked list of keys of this directory.
Int_t ReadKeys(Bool_t forceRead=kTRUE) override
Read the linked list of keys.
TDatime fDatimeM
Date and time of last modification.
void Save() override
Save recursively all directory keys and headers.
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.
Int_t WriteTObject(const TObject *obj, const char *name=nullptr, Option_t *option="", Int_t bufsize=0) override
Write object obj to this directory.
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
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 Int_t ReadBuffer(char *buf, Long64_t pos, Int_t len)
Read buffer at position pos.
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.
virtual Int_t ReadBuffer(char *buf, Long64_t pos, Int_t len)
Called by the read cache to check if the requested data is not in the write cache buffer.
virtual Int_t GetBytesInCache() const
virtual Int_t WriteBuffer(const char *buf, Long64_t pos, Int_t len)
Write buffer at position pos in the write buffer.
Class holding info about the file being opened.
Definition TFile.h:354
TFile * fFile
TFile instance of the file being opened.
Definition TFile.h:362
Int_t GetNetOpt() const
Definition TFile.h:381
TFile * GetFile() const
Definition TFile.h:372
const char * GetOpt() const
Definition TFile.h:379
Bool_t Matches(const char *name)
Return kTRUE if this async request matches the open request specified by 'url'.
Definition TFile.cxx:4795
Int_t GetCompress() const
Definition TFile.h:380
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:53
static std::atomic< Long64_t > fgBytesRead
Number of bytes read by all TFile objects.
Definition TFile.h:161
Int_t fReadCalls
Number of read calls ( not counting the cache calls )
Definition TFile.h:89
static void SetFileBytesWritten(Long64_t bytes=0)
Definition TFile.cxx:4616
static Bool_t fgCacheFileForce
Indicates, to force all READ to CACHEREAD.
Definition TFile.h:126
Long64_t fBytesRead
Number of bytes read from this file.
Definition TFile.h:76
virtual TProcessID * ReadProcessID(UShort_t pidf)
The TProcessID with number pidf is read from this file.
Definition TFile.cxx:1956
void ls(Option_t *option="") const override
List file contents.
Definition TFile.cxx:1462
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:2279
static Bool_t GetOnlyStaged()
Returns staged only flag.
Definition TFile.cxx:4759
static void IncrementFileCounter()
Definition TFile.cxx:4625
static Bool_t ShrinkCacheFileDir(Long64_t shrinkSize, Long_t cleanupInteval=0)
Try to shrink the cache to the desired size.
Definition TFile.cxx:4671
Long64_t fSeekFree
Location on disk of free segments structure.
Definition TFile.h:80
static Int_t fgReadaheadSize
Readahead buffer size.
Definition TFile.h:134
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:74
static void SetReadaheadSize(Int_t bufsize=256000)
Definition TFile.cxx:4610
static Bool_t fgCacheFileDisconnected
Indicates, we trust in the files in the cache dir without stat on the cached file.
Definition TFile.h:125
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:3747
TArchiveFile * fArchive
!Archive file from which we read this file
Definition TFile.h:97
virtual Int_t SysSync(Int_t fd)
Interface to system fsync. All arguments like in POSIX fsync().
Definition TFile.cxx:4557
static TClass * Class()
virtual Int_t ReOpen(Option_t *mode)
Reopen a file with a different access mode.
Definition TFile.cxx:2167
virtual void ReadStreamerInfo()
Read the list of StreamerInfo from this file.
Definition TFile.cxx:3610
virtual Bool_t Matches(const char *name)
Return kTRUE if 'url' matches the coordinates of this file.
Definition TFile.cxx:4771
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=nullptr, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition TFile.cxx:2370
TArrayC * fClassIndex
!Index of TStreamerInfo classes written to this file
Definition TFile.h:94
static Long64_t GetFileBytesWritten()
Static function returning the total number of bytes written to all files.
Definition TFile.cxx:4588
virtual InfoListRet GetStreamerInfoListImpl(bool lookupSICache)
See documentation of GetStreamerInfoList for more details.
Definition TFile.cxx:1381
@ kStartBigFile
Definition TFile.h:200
static void SetReadStreamerInfo(Bool_t readinfo=kTRUE)
Specify if the streamerinfos must be read at file opening.
Definition TFile.cxx:3737
Bool_t fNoAnchorInName
!True if we don't want to force the anchor to be appended to the file name
Definition TFile.h:103
static void SetFileBytesRead(Long64_t bytes=0)
Definition TFile.cxx:4613
Long64_t fSeekInfo
Location on disk of StreamerInfo record.
Definition TFile.h:81
void Paint(Option_t *option="") override
Paint all objects in the file.
Definition TFile.cxx:1703
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:113
virtual void SetCompressionLevel(Int_t level=ROOT::RCompressionSetting::ELevel::kUseMin)
See comments for function SetCompressionSettings.
Definition TFile.cxx:2324
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:4619
static TString fgCacheFileDir
Directory where to locally stage files.
Definition TFile.h:124
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:4511
Int_t fVersion
File format version.
Definition TFile.h:83
void Print(Option_t *option="") const override
Print all objects in the file.
Definition TFile.cxx:1711
static std::atomic< Long64_t > fgFileCounter
Counter for all opened files.
Definition TFile.h:163
virtual EAsyncOpenStatus GetAsyncOpenStatus()
Definition TFile.h:137
void Streamer(TBuffer &) override
Stream a TFile object.
Definition TFile.cxx:2410
static UInt_t GetOpenTimeout()
Returns open timeout (in ms).
Definition TFile.cxx:4739
static void CpProgress(Long64_t bytesread, Long64_t size, TStopwatch &watch)
Print file copy progress.
Definition TFile.cxx:4980
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:128
virtual Int_t GetNProcessIDs() const
Definition TFile.h:239
Bool_t fMustFlush
!True if the file buffers must be flushed
Definition TFile.h:106
TUrl fUrl
!URL of file
Definition TFile.h:110
Int_t WriteBufferViaCache(const char *buf, Int_t len)
Write buffer via cache.
Definition TFile.cxx:2524
static Long64_t GetFileBytesRead()
Static function returning the total number of bytes read from all files.
Definition TFile.cxx:4579
Int_t ReadBufferViaCache(char *buf, Int_t len)
Read buffer via cache.
Definition TFile.cxx:1894
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:267
virtual void WriteFree()
Write FREE linked list on the file.
Definition TFile.cxx:2548
static Int_t GetReadaheadSize()
Static function returning the readahead buffer size.
Definition TFile.cxx:4604
~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:1826
static Long64_t GetFileCounter()
Definition TFile.cxx:4622
TMap * fCacheReadMap
!Pointer to the read cache (if any)
Definition TFile.h:99
Long64_t fBEGIN
First used byte in file.
Definition TFile.h:78
Int_t MakeProjectParProofInf(const char *packname, const char *proofinfdir)
Create BUILD.sh and SETUP.C under 'proofinf' for PAR package 'pack'.
Definition TFile.cxx:3491
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:3768
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:2731
Long64_t fArchiveOffset
!Offset at which file starts in archive
Definition TFile.h:101
@ kEternalTimeout
Definition TFile.h:67
Int_t fNbytesInfo
Number of bytes for StreamerInfo record.
Definition TFile.h:86
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:108
static Bool_t SetOnlyStaged(Bool_t onlystaged)
Sets only staged flag.
Definition TFile.cxx:4749
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:2343
static Bool_t fgReadInfo
if true (default) ReadStreamerInfo is called when opening a file
Definition TFile.h:135
virtual void Init(Bool_t create)
Initialize a TFile object.
Definition TFile.cxx:613
Long64_t GetRelOffset() const
Definition TFile.h:251
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:4356
virtual void SetCacheWrite(TFileCacheWrite *cache)
Set a pointer to the write cache.
Definition TFile.cxx:2393
TString fOption
File options.
Definition TFile.h:91
virtual Bool_t WriteBuffer(const char *buf, Int_t len)
Write a buffer to the file.
Definition TFile.cxx:2481
void SumBuffer(Int_t bufsize)
Increment statistics for buffer sizes of objects in this file.
Definition TFile.cxx:2422
static const char * GetCacheFileDir()
Get the directory where to locally stage/cache remote files.
Definition TFile.cxx:4659
EAsyncOpenStatus
Asynchronous open request status.
Definition TFile.h:64
@ kAOSSuccess
Definition TFile.h:65
@ kAOSNotAsync
Definition TFile.h:64
@ kAOSInProgress
Definition TFile.h:65
@ kAOSFailure
Definition TFile.h:64
virtual void WriteStreamerInfo()
Write the list of TStreamerInfo as a single object in this file The class Streamer description for al...
Definition TFile.cxx:3797
virtual Long64_t GetBytesWritten() const
Return the total number of bytes written so far to the file.
Definition TFile.cxx:4571
ERelativeTo
Definition TFile.h:199
@ kCur
Definition TFile.h:199
@ kBeg
Definition TFile.h:199
@ kEnd
Definition TFile.h:199
Int_t fCompress
Compression level and algorithm.
Definition TFile.h:84
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:2310
virtual const TUrl * GetEndpointUrl() const
Definition TFile.h:235
Int_t fNbytesFree
Number of bytes for free segments structure.
Definition TFile.h:85
Int_t fD
File descriptor.
Definition TFile.h:82
static constexpr Version_t Class_Version()
Definition TFile.h:344
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:2402
Bool_t FlushWriteCache()
Flush the write cache if active.
Definition TFile.cxx:1163
virtual void IncrementProcessIDs()
Definition TFile.h:257
Bool_t fIsPcmFile
!True if the file is a ROOT pcm file.
Definition TFile.h:107
TFileCacheRead * fCacheRead
!Pointer to the read cache (if any)
Definition TFile.h:98
virtual Int_t SysClose(Int_t fd)
Interface to system close. All arguments like in POSIX close().
Definition TFile.cxx:4502
TFile()
File default Constructor.
Definition TFile.cxx:201
Char_t fUnits
Number of bytes for file pointers.
Definition TFile.h:92
TObjArray * fProcessIDs
!Array of pointers to TProcessIDs
Definition TFile.h:95
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:4826
EFileType
File type.
Definition TFile.h:202
@ kWeb
Definition TFile.h:202
@ kDefault
Definition TFile.h:202
@ kLocal
Definition TFile.h:202
@ kMerge
Definition TFile.h:202
@ kNet
Definition TFile.h:202
@ kFile
Definition TFile.h:202
virtual void ShowStreamerInfo()
Show the StreamerInfo of all classes written to this file.
Definition TFile.cxx:3755
virtual Long64_t SysSeek(Int_t fd, Long64_t offset, Int_t whence)
Interface to system lseek.
Definition TFile.cxx:4530
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:4548
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:4486
ECacheAction
TTreeCache flushing semantics.
Definition TFile.h:70
@ kDoNotDisconnect
Definition TFile.h:70
static UInt_t SetOpenTimeout(UInt_t timeout)
Sets open timeout time (in ms). Returns previous timeout value.
Definition TFile.cxx:4729
virtual void ReadFree()
Read the FREE linked list.
Definition TFile.cxx:1930
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:5008
static ROOT::Internal::RConcurrentHashColl fgTsSIHashes
!TS Set of hashes built from read streamer infos
Definition TFile.h:120
Long64_t fBytesReadExtra
Number of extra bytes (overhead) read by the readahead buffer.
Definition TFile.h:77
Long64_t fBytesWrite
Number of bytes written to this file.
Definition TFile.h:75
Bool_t fIsRootFile
!True is this is a ROOT file, raw file otherwise
Definition TFile.h:104
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:93
virtual Bool_t ReadBufferAsync(Long64_t offs, Int_t len)
Definition TFile.cxx:5213
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:105
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:100
TString fRealName
Effective real file name (not original url)
Definition TFile.h:90
virtual void SetOffset(Long64_t offset, ERelativeTo pos=kBeg)
Set position from where to start reading.
Definition TFile.cxx:2258
Long64_t fOffset
!Seek offset cache
Definition TFile.h:96
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:112
virtual Int_t GetBytesToPrefetch() const
Max number of bytes to prefetch.
Definition TFile.cxx:5227
static UInt_t fgOpenTimeout
Timeout for open operations in ms - 0 corresponds to blocking i/o.
Definition TFile.h:127
Int_t MakeProjectParMake(const char *packname, const char *filename)
Create makefile at 'filemake' for PAR package 'pack'.
Definition TFile.cxx:3369
Long64_t fEND
Last used byte in file.
Definition TFile.h:79
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:4094
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:4631
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:2441
EAsyncOpenStatus fAsyncOpenStatus
!Status of an asynchronous open request
Definition TFile.h:109
bool fGlobalRegistration
! if true, bypass use of global lists
Definition TFile.h:115
Double_t fSumBuffer
Sum of buffer sizes of objects written so far.
Definition TFile.h:73
Bool_t fIsArchive
!True if this is a pure archive file
Definition TFile.h:102
TObjArray * GetListOfProcessIDs() const
Definition TFile.h:236
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:344
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:2053
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:2620
@ kRecovered
Definition TFile.h:191
@ kReproducible
Definition TFile.h:197
@ kDevNull
Definition TFile.h:193
@ kHasReferences
Definition TFile.h:192
@ k630forwardCompatibility
Definition TFile.h:190
@ kWriteError
Definition TFile.h:194
@ kBinaryFile
Definition TFile.h:195
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:3879
Int_t fNProcessIDs
Number of TProcessID written to this file.
Definition TFile.h:88
Int_t fWritten
Number of objects written so far.
Definition TFile.h:87
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:1775
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:4519
static Int_t GetFileReadCalls()
Static function returning the total number of read calls from all files.
Definition TFile.cxx:4596
TFileCacheRead * GetCacheRead(const TObject *tree=nullptr) const
Return a pointer to the current read cache.
Definition TFile.cxx:1267
Option_t * GetOption() const override
Definition TFile.h:240
static TList * fgAsyncOpenRequests
Definition TFile.h:122
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:542
virtual Long64_t GetSeekKey() const
Definition TKey.h:89
Int_t GetKeylen() const
Definition TKey.h:84
Int_t GetObjlen() const
Definition TKey.h:87
Int_t GetNbytes() const
Definition TKey.h:86
virtual const char * GetClassName() const
Definition TKey.h:75
void ReadKeyBuffer(char *&buffer)
Decode input buffer.
Definition TKey.cxx:1234
virtual Int_t WriteFile(Int_t cycle=1, TFile *f=nullptr)
Write the encoded object supported by this key.
Definition TKey.cxx:1462
virtual char * GetBuffer() const
Definition TKey.h:78
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:83
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:820
TObject * Last() const override
Return the last object in the list. Returns 0 when list is empty.
Definition TList.cxx:691
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
void Add(TObject *obj) override
This function may not be used (but we need to provide it since it is a pure virtual in TCollection).
Definition TMap.cxx:54
TObject * Remove(TObject *key) override
Remove the (key,value) pair with key from the map.
Definition TMap.cxx:296
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:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
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:173
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
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
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:439
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition TObject.cxx:457
virtual void SysError(const char *method, const char *msgfmt,...) const
Issue system error message.
Definition TObject.cxx:1001
R__ALWAYS_INLINE Bool_t IsOnHeap() const
Definition TObject.h:152
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:207
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:973
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:153
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:780
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1015
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition TObject.cxx:791
void MakeZombie()
Definition TObject.h:53
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:62
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:961
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:2883
static void IndentLevel()
Functions used by ls() to indent an object hierarchy.
Definition TROOT.cxx:2891
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition TROOT.cxx:3052
static Int_t DecreaseDirLevel()
Decrease the indentation level for ls().
Definition TROOT.cxx:2746
Sequenceable collection abstract base class.
Stopwatch class.
Definition TStopwatch.h:28
UInt_t GetBaseCheckSum()
void SetBaseCheckSum(UInt_t cs)
Describes a persistent version of a class.
static TClass * Class()
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition TString.cxx:457
const char * Data() const
Definition TString.h:376
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:704
@ kIgnoreCase
Definition TString.h:277
void ToUpper()
Change string to upper case.
Definition TString.cxx:1195
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:623
Bool_t IsNull() const
Definition TString.h:414
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
virtual void ReadBuffer(char *&buffer)
Read string from I/O buffer.
Definition TString.cxx:1331
virtual FILE * TempFileName(TString &base, const char *dir=nullptr, const char *suffix=nullptr)
Create a secure temporary file by appending a unique 6 letter string to base.
Definition TSystem.cxx:1499
virtual const char * GetMakeSharedLib() const
Return the command line use to make a shared library.
Definition TSystem.cxx:3956
virtual Int_t RedirectOutput(const char *name, const char *mode="a", RedirectHandle_t *h=nullptr)
Redirect standard output (stdout, stderr) to the specified file.
Definition TSystem.cxx:1715
virtual void IgnoreInterrupt(Bool_t ignore=kTRUE)
If ignore is true ignore the interrupt signal, else restore previous behaviour.
Definition TSystem.cxx:602
virtual int Symlink(const char *from, const char *to)
Create a symbolic link from file1 to file2.
Definition TSystem.cxx:1368
static void ResetErrno()
Static function resetting system error number.
Definition TSystem.cxx:284
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1274
static Int_t GetErrno()
Static function returning system error number.
Definition TSystem.cxx:276
virtual int Chmod(const char *file, UInt_t mode)
Set the file permission bits. Returns -1 in case or error, 0 otherwise.
Definition TSystem.cxx:1508
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition TSystem.cxx:845
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition TSystem.cxx:836
virtual int GetPid()
Get process id.
Definition TSystem.cxx:707
virtual int CopyFile(const char *from, const char *to, Bool_t overwrite=kFALSE)
Copy a file.
Definition TSystem.cxx:1341
virtual const char * GetIncludePath()
Get the list of include path.
Definition TSystem.cxx:3973
virtual void ShowOutput(RedirectHandle_t *h)
Display the content associated with the redirection described by the opaque handle 'h'.
Definition TSystem.cxx:1725
virtual Bool_t IsPathLocal(const char *path)
Returns TRUE if the url in 'path' points to the local file system.
Definition TSystem.cxx:1305
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Definition TSystem.cxx:906
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition TSystem.cxx:653
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1857
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition TSystem.cxx:1398
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition TSystem.cxx:1081
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1296
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition TSystem.cxx:853
virtual Bool_t ChangeDirectory(const char *path)
Change directory.
Definition TSystem.cxx:862
virtual int Rename(const char *from, const char *to)
Rename a file.
Definition TSystem.cxx:1350
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition TSystem.cxx:934
virtual const char * GetFlagsDebug() const
Return the debug flags.
Definition TSystem.cxx:3927
virtual Bool_t IsAbsoluteFileName(const char *dir)
Return true if dir is an absolute pathname.
Definition TSystem.cxx:951
virtual const char * GetObjExt() const
Get the object file extension.
Definition TSystem.cxx:4021
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition TSystem.cxx:437
virtual const char * WorkingDirectory()
Return working directory.
Definition TSystem.cxx:871
virtual const char * GetLibraries(const char *regexp="", const char *option="", Bool_t isRegexp=kTRUE)
Return a space separated list of loaded shared libraries.
Definition TSystem.cxx:2136
virtual const char * HomeDirectory(const char *userName=nullptr)
Return the user's home directory.
Definition TSystem.cxx:887
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:416
virtual const char * GetSoExt() const
Get the shared library extension.
Definition TSystem.cxx:4013
virtual TString GetDirName(const char *pathname)
Return the directory name in pathname.
Definition TSystem.cxx:1032
virtual int Unlink(const char *name)
Unlink, i.e.
Definition TSystem.cxx:1381
virtual const char * GetFlagsOpt() const
Return the optimization flags.
Definition TSystem.cxx:3935
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:390
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:660
const char * GetHostFQDN() const
Return fully qualified domain name of url host.
Definition TUrl.cxx:472
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:683
virtual Bool_t SendFileReadProgress(TFile *)
virtual Bool_t SendFileCloseEvent(TFile *)
virtual Bool_t SendFileWriteProgress(TFile *)
Abstract Interface class describing Streamer information for one class.
const Int_t n
Definition legend1.C:16
TF1 * f1
Definition legend1.C:11
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
R__EXTERN TVirtualRWMutex * gCoreMutex
@ kFileThreadSlot
@ kSTLmap
Definition ESTLType.h:33
@ kSTLmultimap
Definition ESTLType.h:34
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
bool IsStdPair(std::string_view name)
Definition TClassEdit.h:184
ROOT::ESTLType IsSTLCont(std::string_view type)
type : type name: vector<list<classA,allocator>,allocator> result: 0 : not stl container code of cont...
int GetSplit(const char *type, std::vector< std::string > &output, int &nestedLoc, EModType mode=TClassEdit::kNone)
Stores in output (after emptying it) the split type.
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123
static const char * what
Definition stlLoader.cc:5
@ kUndefined
Undefined compression algorithm (must be kept the last of the list in case a new algorithm is added).
@ kUseMin
Compression level reserved when we are not sure what to use (1 is for the fastest compression)
Definition Compression.h:70
Simple struct of the return value of GetStreamerInfoListImpl.
Definition TFile.h:145
th1 Draw()
TLine l
Definition textangle.C:4