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