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
29namespace ROOT {
30namespace Experimental {
31namespace Internal {
32// This will have to move to some "semi-internal" header.
33/** \class RFileStorageInterface
34 Base class for RFile storage backends.
35 */
36class RFileStorageInterface {
37public:
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.
46class RFileSharedPtrCtor: public ROOT::Experimental::RFile {
47public:
48 RFileSharedPtrCtor(std::unique_ptr<RFileStorageInterface> &&storage): RFile(std::move(storage)) {}
49};
50} // namespace Internal
51} // namespace Experimental
52} // namespace ROOT
53
54namespace {
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.
60static 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 */
83class TV6Storage: public ROOT::Experimental::Internal::RFileStorageInterface {
84 ::TFile *fOldFile;
85
86public:
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
102ROOT::Experimental::RFilePtr::RFilePtr(std::shared_ptr<ROOT::Experimental::RFile> &&file): fFile(std::move(file))
103{
104 AddFilesToClose(fFile);
105}
106
107namespace {
108static 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
118static std::mutex &GetCacheDirMutex()
119{
120 static std::mutex sMutex;
121 return sMutex;
122}
123
124static std::unique_ptr<ROOT::Experimental::Internal::RFileStorageInterface>
125OpenV6RFile(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.
206ROOT::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}
char name[80]
Definition: TGX11.cxx:109
Key/value store of objects.
Definition: RDirectory.hxx:70
static RDirectory & Heap()
Dedicated, process-wide RDirectory.
Definition: RFile.cxx:23
Points to an object that stores or reads objects in ROOT's binary format.
Definition: RFile.hxx:184
std::shared_ptr< RFile > fFile
Definition: RFile.hxx:186
RFilePtr(std::shared_ptr< RFile > &&)
Constructed by Open etc.
Definition: RFile.cxx:102
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
RFile(std::unique_ptr< Internal::RFileStorageInterface > &&storage)
Definition: RFile.cxx:206
void Flush()
Save all objects associated with this directory (including file header) to the storage medium.
Definition: RFile.cxx:214
static std::string SetCacheDir(std::string_view path)
Set the new directory used for cached reads, returns the old directory.
Definition: RFile.cxx:189
static std::string GetCacheDir()
Get the directory used for cached reads.
Definition: RFile.cxx:198
~RFile()
Must not call Write() of all attached objects: some might not be needed to be written or writing migh...
static RFilePtr Open(std::string_view name, const Options_t &opts=Options_t())
Open a file with name for reading.
Definition: RFile.cxx:153
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
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
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
void Close()
Flush() and make the file non-writable: close it.
Definition: RFile.cxx:218
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:75
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.
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format.
Definition: TFile.h:48
static const char * GetCacheFileDir()
Get the directory where to locally stage/cache remote files.
Definition: TFile.cxx:4470
static Bool_t SetCacheFileDir(ROOT::Internal::TStringView cacheDir, Bool_t operateDisconnected=kTRUE, Bool_t forceCacheread=kFALSE)
Definition: TFile.h:319
virtual void Flush()
Synchronize a file's in-memory and on-disk states.
Definition: TFile.cxx:1038
void Close(Option_t *option="") override
Close a file.
Definition: TFile.cxx:856
basic_string_view< char > string_view
VSD Structures.
Definition: StringConv.hxx:21
Definition: file.py:1
Options for RFile construction.
Definition: RFile.hxx:57
bool fCachedRead
Whether the file should be cached before reading.
Definition: RFile.hxx:70
int fAsyncTimeout
Timeout for asynchronous opening.
Definition: RFile.hxx:65
bool fAsynchronousOpen
Whether the file should be opened asynchronously, if available.
Definition: RFile.hxx:62