Logo ROOT  
Reference Guide
RFile.cxx
Go to the documentation of this file.
1 /// \file v7/src/RFile.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/RFile.hxx"
17 #include "TFile.h"
18 
19 #include <memory>
20 #include <mutex>
21 #include <string>
22 
24 {
25  static RDirectory 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 RFileStorageInterface
34  Base class for RFile storage backends.
35  */
36 class RFileStorageInterface {
37 public:
38  virtual void Flush() = 0;
39  virtual void Close() = 0;
40  virtual ~RFileStorageInterface() = default;
41  virtual void WriteMemoryWithType(std::string_view name, const void *address, TClass *cl) = 0;
42 };
43 
44 // make_shared<RFile> doesn't work, as RFile() is private. Take detour
45 // through a friend instead.
46 class RFileSharedPtrCtor: public ROOT::Experimental::RFile {
47 public:
48  RFileSharedPtrCtor(std::unique_ptr<RFileStorageInterface> &&storage): RFile(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 RFile unclosed and data corrupted / not written. Instead, keep a
58 /// collection of all opened writable RFiles and close them at destruction time,
59 /// explicitly.
60 static void AddFilesToClose(std::weak_ptr<ROOT::Experimental::RFile> pFile)
61 {
62  struct CloseFiles_t {
63  std::vector<std::weak_ptr<ROOT::Experimental::RFile>> 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  RFile for a ROOT v6 storage backend.
82  */
83 class TV6Storage: public ROOT::Experimental::Internal::RFileStorageInterface {
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::RFilePtr::RFilePtr(std::shared_ptr<ROOT::Experimental::RFile> &&file): fFile(std::move(file))
103 {
104  AddFilesToClose(fFile);
105 }
106 
107 namespace {
108 static std::string GetV6RFileOpts(const char *mode, const ROOT::Experimental::RFile::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::RFileStorageInterface>
125 OpenV6RFile(std::string_view name, const char *mode, const ROOT::Experimental::RFile::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), GetV6RFileOpts(mode, opts));
147 
148  using namespace ROOT::Experimental::Internal;
149  return std::unique_ptr<RFileStorageInterface>{std::move(v6storage)};
150 }
151 } // namespace
152 
154  const Options_t &opts /*= Options_t()*/)
155 {
156  // will become delegation to RFileSystemFile, TWebFile etc.
157  using namespace Internal;
158  auto file = std::make_shared<RFileSharedPtrCtor>(OpenV6RFile(name, "READ", opts));
159  return ROOT::Experimental::RFilePtr(std::move(file));
160 }
161 
163  const Options_t &opts /*= Options_t()*/)
164 {
165  // will become delegation to RFileSystemFile, TWebFile etc.
166  using namespace Internal;
167  auto file = std::make_shared<RFileSharedPtrCtor>(OpenV6RFile(name, "CREATE", opts));
168  return ROOT::Experimental::RFilePtr(std::move(file));
169 }
170 
172  const Options_t &opts /*= Options_t()*/)
173 {
174  // will become delegation to RFileSystemFile, TWebFile etc.
175  using namespace Internal;
176  auto file = std::make_shared<RFileSharedPtrCtor>(OpenV6RFile(name, "RECREATE", opts));
177  return ROOT::Experimental::RFilePtr(std::move(file));
178 }
179 
181  const Options_t &opts /*= Options_t()*/)
182 {
183  // will become delegation to RFileSystemFile, TWebFile etc.
184  using namespace Internal;
185  auto file = std::make_shared<RFileSharedPtrCtor>(OpenV6RFile(name, "UPDATE", opts));
186  return ROOT::Experimental::RFilePtr(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 RFileStorageInterface from
205 // header.
206 ROOT::Experimental::RFile::RFile(std::unique_ptr<ROOT::Experimental::Internal::RFileStorageInterface> &&storage)
207  : fStorage(std::move(storage))
208 {}
209 
210 // Implement outlined, to hide implementation of RFileStorageInterface from
211 // header.
213 
215 {
216  fStorage->Flush();
217 }
219 {
220  fStorage->Close();
221 }
223 {
224  fStorage->WriteMemoryWithType(name, address, cl);
225 }
TFile::SetCacheFileDir
static Bool_t SetCacheFileDir(ROOT::Internal::TStringView cacheDir, Bool_t operateDisconnected=kTRUE, Bool_t forceCacheread=kFALSE)
Definition: TFile.h:324
ROOT::Experimental::RFile::Create
static RFilePtr Create(std::string_view name, const Options_t &opts=Options_t())
Open a file with name for reading and writing.
Definition: RFile.cxx:162
ROOT::Experimental::RFile::Open
static RFilePtr Open(std::string_view name, const Options_t &opts=Options_t())
Open a file with name for reading.
Definition: RFile.cxx:153
string_view
basic_string_view< char > string_view
Definition: libcpp_string_view.h:785
ROOT::Experimental::RFile::Recreate
static RFilePtr Recreate(std::string_view name, const Options_t &opts=Options_t())
Open a file with name for reading and writing.
Definition: RFile.cxx:171
ROOT::Experimental::RFile::Options_t
Options for RFile construction.
Definition: RFile.hxx:69
ROOT::Experimental::RFilePtr
Points to an object that stores or reads objects in ROOT's binary format.
Definition: RFile.hxx:196
ROOT::Experimental::RFile::Close
void Close()
Flush() and make the file non-writable: close it.
Definition: RFile.cxx:218
ROOT::Experimental::RFile::~RFile
~RFile()
Must not call Write() of all attached objects: some might not be needed to be written or writing migh...
ROOT::Experimental::RFile::SetCacheDir
static std::string SetCacheDir(std::string_view path)
Set the new directory used for cached reads, returns the old directory.
Definition: RFile.cxx:189
TFile.h
ROOT::Experimental::RFilePtr::fFile
std::shared_ptr< RFile > fFile
Definition: RFile.hxx:198
ROOT::Experimental::RDirectory
Key/value store of objects.
Definition: RDirectory.hxx:82
ROOT::Experimental::RFile
Definition: RFile.hxx:55
ROOT::Experimental::RFile::RFile
RFile(std::unique_ptr< Internal::RFileStorageInterface > &&storage)
Definition: RFile.cxx:206
ROOT::Experimental::RFile::WriteMemoryWithType
void WriteMemoryWithType(std::string_view name, const void *address, TClass *cl)
Serialize the object at address, using the object's TClass.
Definition: RFile.cxx:222
TDirectoryFile::WriteObjectAny
Int_t WriteObjectAny(const void *obj, const char *classname, const char *name, Option_t *option="", Int_t bufsize=0) override
Write object from pointer of class classname in this directory.
Definition: TDirectoryFile.cxx:1969
ROOT::Experimental::RFile::Options_t::fCachedRead
bool fCachedRead
Whether the file should be cached before reading.
Definition: RFile.hxx:82
ROOT::Experimental::RFile::OpenForUpdate
static RFilePtr OpenForUpdate(std::string_view name, const Options_t &opts=Options_t())
Open an existing file with name for reading and writing.
Definition: RFile.cxx:180
ROOT::Experimental::RFile::GetCacheDir
static std::string GetCacheDir()
Get the directory used for cached reads.
Definition: RFile.cxx:198
TFile
Definition: TFile.h:54
ROOT::Experimental::RFile::Options_t::fAsynchronousOpen
bool fAsynchronousOpen
Whether the file should be opened asynchronously, if available.
Definition: RFile.hxx:74
ROOT::Experimental::RFile::Options_t::fAsyncTimeout
int fAsyncTimeout
Timeout for asynchronous opening.
Definition: RFile.hxx:77
TClass
Definition: TClass.h:80
file
Definition: file.py:1
TFile::Close
void Close(Option_t *option="") override
Close a file.
Definition: TFile.cxx:876
TFile::GetCacheFileDir
static const char * GetCacheFileDir()
Get the directory where to locally stage/cache remote files.
Definition: TFile.cxx:4493
name
char name[80]
Definition: TGX11.cxx:110
ROOT::Experimental::Internal
Definition: RDirectoryEntry.hxx:39
ROOT::Experimental::RDirectory::Heap
static RDirectory & Heap()
Dedicated, process-wide RDirectory.
Definition: RFile.cxx:23
ROOT::Experimental::RFilePtr::RFilePtr
RFilePtr(std::shared_ptr< RFile > &&)
Constructed by Open etc.
Definition: RFile.cxx:102
ROOT::Experimental::RFile::Flush
void Flush()
Save all objects associated with this directory (including file header) to the storage medium.
Definition: RFile.cxx:214
ROOT
VSD Structures.
Definition: StringConv.hxx:21
TFile::Flush
virtual void Flush()
Synchronize a file's in-memory and on-disk states.
Definition: TFile.cxx:1058
RFile.hxx