Logo ROOT   6.16/01
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
29namespace ROOT {
30namespace Experimental {
31namespace Internal {
32// This will have to move to some "semi-internal" header.
33/** \class TFileStorageInterface
34 Base class for TFile storage backends.
35 */
36class TFileStorageInterface {
37public:
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.
46class TFileSharedPtrCtor: public ROOT::Experimental::TFile {
47public:
48 TFileSharedPtrCtor(std::unique_ptr<TFileStorageInterface> &&storage): TFile(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 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.
60static 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 */
83class TV6Storage: public ROOT::Experimental::Internal::TFileStorageInterface {
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::TFilePtr::TFilePtr(std::shared_ptr<ROOT::Experimental::TFile> &&file): fFile(std::move(file))
103{
104 AddFilesToClose(fFile);
105}
106
107namespace {
108static 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
118static std::mutex &GetCacheDirMutex()
119{
120 static std::mutex sMutex;
121 return sMutex;
122}
123
124static std::unique_ptr<ROOT::Experimental::Internal::TFileStorageInterface>
125OpenV6TFile(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.
206ROOT::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}
Key/value store of objects.
Definition: TDirectory.hxx:70
static TDirectory & Heap()
Dedicated, process-wide TDirectory.
Definition: TFile.cxx:23
Points to an object that stores or reads objects in ROOT's binary format.
Definition: TFile.hxx:186
TFilePtr(std::shared_ptr< TFile > &&)
Constructed by Open etc.
Definition: TFile.cxx:102
std::shared_ptr< TFile > fFile
Definition: TFile.hxx:188
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
TFile(std::unique_ptr< Internal::TFileStorageInterface > &&storage)
Definition: TFile.cxx:206
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
void WriteMemoryWithType(std::string_view name, const void *address, TClass *cl)
Serialize the object at address, using the object's TClass.
Definition: TFile.cxx:222
void Close()
Flush() and make the file non-writable: close it.
Definition: TFile.cxx:218
static std::string GetCacheDir()
Get the directory used for cached reads.
Definition: TFile.cxx:198
static TFilePtr Open(std::string_view name, const Options_t &opts=Options_t())
Open a file with name for reading.
Definition: TFile.cxx:153
~TFile()
Must not call Write() of all attached objects: some might not be needed to be written or writing migh...
void Flush()
Save all objects associated with this directory (including file header) to the storage medium.
Definition: TFile.cxx:214
static std::string SetCacheDir(std::string_view path)
Set the new directory used for cached reads, returns the old directory.
Definition: TFile.cxx:189
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
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
virtual Int_t WriteObjectAny(const void *obj, const char *classname, const char *name, Option_t *option="", Int_t bufsize=0)
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
virtual void Close(Option_t *option="")
Close a file.
Definition: TFile.cxx:912
static const char * GetCacheFileDir()
Get the directory where to locally stage/cache remote files.
Definition: TFile.cxx:4523
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
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
Definition: file.py:1
STL namespace.
basic_string_view< char > string_view
Definition: RStringView.hxx:35
Options for TFile construction.
Definition: TFile.hxx:59
bool fCachedRead
Whether the file should be cached before reading.
Definition: TFile.hxx:72
int fAsyncTimeout
Timeout for asynchronous opening.
Definition: TFile.hxx:67
bool fAsynchronousOpen
Whether the file should be opened asynchronously, if available.
Definition: TFile.hxx:64