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