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