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