Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RFile.hxx
Go to the documentation of this file.
1 /// \file ROOT/RFile.h
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 #ifndef ROOT7_RFile
17 #define ROOT7_RFile
18 
19 #include "ROOT/RDirectory.hxx"
20 #include "ROOT/RStringView.hxx"
21 
22 #include "TClass.h"
23 #include <memory>
24 
25 namespace ROOT {
26 namespace Experimental {
27 
28 class RFilePtr;
29 
30 namespace Internal {
31 class RFileStorageInterface;
32 class RFileSharedPtrCtor;
33 } // namespace Internal
34 
35 /** \class ROOT::Experimental::RFile
36  A ROOT file.
37 
38  A ROOT file is an object store: it can serialize any
39  object for which ROOT I/O is available (generally: an object which has a
40  dictionary), and it stores the object's data under a key name.
41 
42  */
43 class RFile: public RDirectory {
44 private:
45  std::unique_ptr<Internal::RFileStorageInterface> fStorage; ///< Storage backend.
46 
47  RFile(std::unique_ptr<Internal::RFileStorageInterface> &&storage);
48 
49  /// Serialize the object at address, using the object's TClass.
50  // FIXME: what about `cl` "pointing" to a base class?
51  void WriteMemoryWithType(std::string_view name, const void *address, TClass *cl);
52 
53  friend Internal::RFileSharedPtrCtor;
54 
55 public:
56  /// Options for RFile construction.
57  struct Options_t {
58  /// Default constructor needed for member inits.
59  Options_t() {}
60 
61  /// Whether the file should be opened asynchronously, if available.
62  bool fAsynchronousOpen = false;
63 
64  /// Timeout for asynchronous opening.
65  int fAsyncTimeout = 0;
66 
67  /// Whether the file should be cached before reading. Only available for
68  /// "remote" file protocols. If the download fails, the file will be opened
69  /// remotely.
70  bool fCachedRead = false;
71 
72  /// Where to cache the file. If empty, defaults to RFilePtr::GetCacheDir().
73  std::string fCacheDir;
74  };
75 
76  ///\name Generator functions
77  ///\{
78 
79  /// Open a file with `name` for reading.
80  ///
81  /// \note: Synchronizes multi-threaded accesses through locks.
82  static RFilePtr Open(std::string_view name, const Options_t &opts = Options_t());
83 
84  /// Open an existing file with `name` for reading and writing. If a file with
85  /// that name does not exist, an invalid RFilePtr will be returned.
86  ///
87  /// \note: Synchronizes multi-threaded accesses through locks.
88  static RFilePtr OpenForUpdate(std::string_view name, const Options_t &opts = Options_t());
89 
90  /// Open a file with `name` for reading and writing. Fail (return an invalid
91  /// `RFilePtr`) if a file with this name already exists.
92  ///
93  /// \note: Synchronizes multi-threaded accesses through locks.
94  static RFilePtr Create(std::string_view name, const Options_t &opts = Options_t());
95 
96  /// Open a file with `name` for reading and writing. If a file with this name
97  /// already exists, delete it and create a new one. Else simply create a new file.
98  ///
99  /// \note: Synchronizes multi-threaded accesses through locks.
100  static RFilePtr Recreate(std::string_view name, const Options_t &opts = Options_t());
101 
102  ///\}
103 
104  /// Set the new directory used for cached reads, returns the old directory.
105  ///
106  /// \note: Synchronizes multi-threaded accesses through locks.
107  static std::string SetCacheDir(std::string_view path);
108 
109  /// Get the directory used for cached reads.
110  static std::string GetCacheDir();
111 
112  /// Must not call Write() of all attached objects:
113  /// some might not be needed to be written or writing might be aborted due to
114  /// an exception; require explicit Write().
115  ~RFile();
116 
117  /// Save all objects associated with this directory (including file header) to
118  /// the storage medium.
119  void Flush();
120 
121  /// Flush() and make the file non-writable: close it.
122  void Close();
123 
124  /// Read the object for a key. `T` must be the object's type.
125  /// This will re-read the object for each call, returning a new copy; whether
126  /// the `RDirectory` is managing an object attached to this key or not.
127  /// \returns a `unique_ptr` to the object.
128  /// \throws RDirectoryUnknownKey if no object is stored under this name.
129  /// \throws RDirectoryTypeMismatch if the object stored under this name is of
130  /// a type different from `T`.
131  template <class T>
132  std::unique_ptr<T> Read(std::string_view name)
133  {
134  // FIXME: need separate collections for a RDirectory's key/value and registered objects. Here, we want to emit a
135  // read and must look through the key/values without attaching an object to the RDirectory.
136  // FIXME: do not register read object in RDirectory
137  // FIXME: implement actual read
138  // FIXME: for now, copy out of whatever the RDirectory manages.
139  return std::make_unique<T>(*Get<T>(name));
140  }
141 
142  /// Write an object that is not lifetime managed by this RFileImplBase.
143  template <class T>
144  void Write(std::string_view name, const T &obj)
145  {
146  WriteMemoryWithType(name, &obj, TClass::GetClass<T>());
147  }
148 
149  /// Write an object that is not lifetime managed by this RFileImplBase.
150  template <class T>
151  void Write(std::string_view name, const T *obj)
152  {
153  WriteMemoryWithType(name, obj, TClass::GetClass<T>());
154  }
155 
156  /// Write an object that is already lifetime managed by this RFileImplBase.
157  void Write(std::string_view name)
158  {
159  auto dep = Find(name);
160  WriteMemoryWithType(name, dep.GetPointer().get(), dep.GetType());
161  }
162 
163  /// Hand over lifetime management of an object to this RFileImplBase, and
164  /// write it.
165  template <class T>
166  void Write(std::string_view name, std::shared_ptr<T> &&obj)
167  {
168  Add(name, obj);
169  // FIXME: use an iterator from the insertion to write instead of a second name lookup.
170  Write(name);
171  }
172 };
173 
174 /**
175  \class RFilePtr
176  \brief Points to an object that stores or reads objects in ROOT's binary
177  format.
178 
179  FIXME: implement async open; likely using std::future, possibly removing the
180  Option_t element.
181 
182  */
183 
184 class RFilePtr {
185 private:
186  std::shared_ptr<RFile> fFile;
187 
188  /// Constructed by Open etc.
189  RFilePtr(std::shared_ptr<RFile> &&);
190 
191  friend class RFile;
192 
193 public:
194  /// Dereference the file pointer, giving access to the RFileImplBase object.
195  RFile *operator->() { return fFile.get(); }
196 
197  /// Dereference the file pointer, giving access to the RFileImplBase object.
198  /// const overload.
199  const RFile *operator->() const { return fFile.get(); }
200 
201  /// Check the validity of the file pointer.
202  operator bool() const { return fFile.get(); }
203 };
204 
205 } // namespace Experimental
206 } // namespace ROOT
207 #endif