Logo ROOT   6.14/05
Reference Guide
TFile.cxx
Go to the documentation of this file.
1 /// \file v7/src/TFile.cxx
2 /// \ingroup Base ROOT7
3 /// \author Axel Naumann <axel@cern.ch>
4 /// \date 2015-07-31
5 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6 /// is welcome!
7 
8 /*************************************************************************
9  * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers. *
10  * All rights reserved. *
11  * *
12  * For the licensing terms see $ROOTSYS/LICENSE. *
13  * For the list of contributors see $ROOTSYS/README/CREDITS. *
14  *************************************************************************/
15 
16 #include "ROOT/TFile.hxx"
17 #include "TFile.h"
18 
19 #include <memory>
20 #include <mutex>
21 #include <string>
22 
24 {
25  static TDirectory heapDir;
26  return heapDir;
27 }
28 
29 namespace ROOT {
30 namespace Experimental {
31 namespace Internal {
32 // This will have to move to some "semi-internal" header.
33 /** \class TFileStorageInterface
34  Base class for TFile storage backends.
35  */
36 class TFileStorageInterface {
37 public:
38  virtual void Flush() = 0;
39  virtual void Close() = 0;
40  virtual ~TFileStorageInterface() = default;
41  virtual void WriteMemoryWithType(std::string_view name, const void *address, TClass *cl) = 0;
42 };
43 
44 // make_shared<TFile> doesn't work, as TFile() is private. Take detour
45 // through a friend instead.
46 class TFileSharedPtrCtor: public ROOT::Experimental::TFile {
47 public:
48  TFileSharedPtrCtor(std::unique_ptr<TFileStorageInterface> &&storage): TFile(std::move(storage)) {}
49 };
50 } // namespace Internal
51 } // namespace Experimental
52 } // namespace ROOT
53 
54 namespace {
55 /// We cannot afford users not closing their files. Yes, we return a unique_ptr -
56 /// but that might be stored in an object that itself leaks. That would leave
57 /// the TFile unclosed and data corrupted / not written. Instead, keep a
58 /// collection of all opened writable TFiles and close them at destruction time,
59 /// explicitly.
60 static void AddFilesToClose(std::weak_ptr<ROOT::Experimental::TFile> pFile)
61 {
62  struct CloseFiles_t {
63  std::vector<std::weak_ptr<ROOT::Experimental::TFile>> fFiles;
64  std::mutex fMutex;
65  ~CloseFiles_t()
66  {
67  for (auto &wFile: fFiles) {
68  if (auto sFile = wFile.lock()) {
69  sFile->Flush(); // or Close()? but what if there's still a Write()?
70  }
71  }
72  }
73  };
74  static CloseFiles_t closer;
75 
76  std::lock_guard<std::mutex> lock(closer.fMutex);
77  closer.fFiles.emplace_back(pFile);
78 }
79 
80 /** \class TV6Storage
81  TFile for a ROOT v6 storage backend.
82  */
83 class TV6Storage: public ROOT::Experimental::Internal::TFileStorageInterface {
84  ::TFile *fOldFile;
85 
86 public:
87  TV6Storage(const std::string &name, const std::string &mode): fOldFile(::TFile::Open(name.c_str(), mode.c_str())) {}
88 
89  void Flush() final { fOldFile->Flush(); }
90 
91  void Close() final { fOldFile->Close(); }
92 
93  ~TV6Storage() { delete fOldFile; }
94 
95  void WriteMemoryWithType(std::string_view name, const void *address, TClass *cl) final
96  {
97  fOldFile->WriteObjectAny(address, cl, std::string(name).c_str());
98  }
99 };
100 } // namespace
101 
102 ROOT::Experimental::TFilePtr::TFilePtr(std::shared_ptr<ROOT::Experimental::TFile> &&file): fFile(std::move(file))
103 {
104  AddFilesToClose(fFile);
105 }
106 
107 namespace {
108 static std::string GetV6TFileOpts(const char *mode, const ROOT::Experimental::TFile::Options_t &opts)
109 {
110  std::string ret(mode);
111  if (opts.fCachedRead)
112  ret += " CACHEREAD ";
113  if (opts.fAsynchronousOpen && opts.fAsyncTimeout > 0)
114  ret += " TIMEOUT=" + std::to_string(opts.fAsyncTimeout) + " ";
115  return ret;
116 }
117 
118 static std::mutex &GetCacheDirMutex()
119 {
120  static std::mutex sMutex;
121  return sMutex;
122 }
123 
124 static std::unique_ptr<ROOT::Experimental::Internal::TFileStorageInterface>
125 OpenV6TFile(std::string_view name, const char *mode, const ROOT::Experimental::TFile::Options_t &opts)
126 {
127  // Set and re-set the cache dir.
128  // FIXME: do not modify a static here, pass this to the underlying Open.
129  struct SetCacheDirRAII_t {
130  std::string fOldCacheDir;
131  std::lock_guard<std::mutex> fLock;
132 
133  SetCacheDirRAII_t(bool need): fLock(GetCacheDirMutex())
134  {
135  if (need)
136  fOldCacheDir = TFile::GetCacheFileDir();
137  }
138 
139  ~SetCacheDirRAII_t()
140  {
141  if (!fOldCacheDir.empty())
142  TFile::SetCacheFileDir(fOldCacheDir.c_str());
143  }
144  } setCacheDirRAII(opts.fCachedRead);
145 
146  auto v6storage = std::make_unique<TV6Storage>(std::string(name), GetV6TFileOpts(mode, opts));
147 
148  using namespace ROOT::Experimental::Internal;
149  return std::unique_ptr<TFileStorageInterface>{std::move(v6storage)};
150 }
151 } // namespace
152 
154  const Options_t &opts /*= Options_t()*/)
155 {
156  // will become delegation to TFileSystemFile, TWebFile etc.
157  using namespace Internal;
158  auto file = std::make_shared<TFileSharedPtrCtor>(OpenV6TFile(name, "READ", opts));
159  return ROOT::Experimental::TFilePtr(std::move(file));
160 }
161 
163  const Options_t &opts /*= Options_t()*/)
164 {
165  // will become delegation to TFileSystemFile, TWebFile etc.
166  using namespace Internal;
167  auto file = std::make_shared<TFileSharedPtrCtor>(OpenV6TFile(name, "CREATE", opts));
168  return ROOT::Experimental::TFilePtr(std::move(file));
169 }
170 
172  const Options_t &opts /*= Options_t()*/)
173 {
174  // will become delegation to TFileSystemFile, TWebFile etc.
175  using namespace Internal;
176  auto file = std::make_shared<TFileSharedPtrCtor>(OpenV6TFile(name, "RECREATE", opts));
177  return ROOT::Experimental::TFilePtr(std::move(file));
178 }
179 
181  const Options_t &opts /*= Options_t()*/)
182 {
183  // will become delegation to TFileSystemFile, TWebFile etc.
184  using namespace Internal;
185  auto file = std::make_shared<TFileSharedPtrCtor>(OpenV6TFile(name, "UPDATE", opts));
186  return ROOT::Experimental::TFilePtr(std::move(file));
187 }
188 
190 {
191  std::lock_guard<std::mutex> lock(GetCacheDirMutex());
192 
193  std::string ret = ::TFile::GetCacheFileDir();
194  ::TFile::SetCacheFileDir(std::string(path).c_str());
195  return ret;
196 }
197 
199 {
200  std::lock_guard<std::mutex> lock(GetCacheDirMutex());
201  return ::TFile::GetCacheFileDir();
202 }
203 
204 // Implement outlined, to hide implementation of TFileStorageInterface from
205 // header.
206 ROOT::Experimental::TFile::TFile(std::unique_ptr<ROOT::Experimental::Internal::TFileStorageInterface> &&storage)
207  : fStorage(std::move(storage))
208 {}
209 
210 // Implement outlined, to hide implementation of TFileStorageInterface from
211 // header.
213 
215 {
216  fStorage->Flush();
217 }
219 {
220  fStorage->Close();
221 }
223 {
224  fStorage->WriteMemoryWithType(name, address, cl);
225 }
int fAsyncTimeout
Timeout for asynchronous opening.
Definition: TFile.hxx:67
std::unique_ptr< Internal::TFileStorageInterface > fStorage
Storage backend.
Definition: TFile.hxx:47
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
~TFile()
Must not call Write() of all attached objects: some might not be needed to be written or writing migh...
Options for TFile construction.
Definition: TFile.hxx:59
static TFilePtr OpenForUpdate(std::string_view name, const Options_t &opts=Options_t())
Open an existing file with name for reading and writing.
Definition: TFile.cxx:180
static Bool_t SetCacheFileDir(ROOT::Internal::TStringView cacheDir, Bool_t operateDisconnected=kTRUE, Bool_t forceCacheread=kFALSE)
Definition: TFile.h:315
STL namespace.
static TFilePtr Create(std::string_view name, const Options_t &opts=Options_t())
Open a file with name for reading and writing.
Definition: TFile.cxx:162
static std::string GetCacheDir()
Get the directory used for cached reads.
Definition: TFile.cxx:198
void Flush()
Save all objects associated with this directory (including file header) to the storage medium...
Definition: TFile.cxx:214
static TDirectory & Heap()
Dedicated, process-wide TDirectory.
Definition: TFile.cxx:23
bool fCachedRead
Whether the file should be cached before reading.
Definition: TFile.hxx:72
static TFilePtr Open(std::string_view name, const Options_t &opts=Options_t())
Open a file with name for reading.
Definition: TFile.cxx:153
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
static TFilePtr Recreate(std::string_view name, const Options_t &opts=Options_t())
Open a file with name for reading and writing.
Definition: TFile.cxx:171
std::shared_ptr< TFile > fFile
Definition: TFile.hxx:188
void WriteMemoryWithType(std::string_view name, const void *address, TClass *cl)
Serialize the object at address, using the object&#39;s TClass.
Definition: TFile.cxx:222
Points to an object that stores or reads objects in ROOT&#39;s binary format.
Definition: TFile.hxx:186
basic_string_view< char > string_view
Definition: RStringView.hxx:35
Definition: file.py:1
Key/value store of objects.
Definition: TDirectory.hxx:70
static std::string SetCacheDir(std::string_view path)
Set the new directory used for cached reads, returns the old directory.
Definition: TFile.cxx:189
void Close()
Flush() and make the file non-writable: close it.
Definition: TFile.cxx:218
A ROOT file.
Definition: TFile.hxx:45
TFile(std::unique_ptr< Internal::TFileStorageInterface > &&storage)
Definition: TFile.cxx:206
TFilePtr(std::shared_ptr< TFile > &&)
Constructed by Open etc.
Definition: TFile.cxx:102
char name[80]
Definition: TGX11.cxx:109
static const char * GetCacheFileDir()
Get the directory where to locally stage/cache remote files.
Definition: TFile.cxx:4524
bool fAsynchronousOpen
Whether the file should be opened asynchronously, if available.
Definition: TFile.hxx:64