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