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