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