hdf5serie  2.0.0
HDF5 Serie
interface.h
1/* Copyright (C) 2009 Markus Friedrich
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 *
17 * Contact:
18 * friedrich.at.gc@googlemail.com
19 *
20 */
21
22#ifndef _HDF5SERIE_INTERFACE_H_
23#define _HDF5SERIE_INTERFACE_H_
24
25#include <fmatvec/atom.h>
26#include <hdf5.h>
27#include <map>
28#include <set>
29#include <utility>
30#include <vector>
31
32namespace H5 {
33
34 // The class defines all base classes of the interface for HDF5Serie.
35 // The interface has the following virtual functions which gets, started from File, calles
36 // for all created children classes recursively:
37 // - close: closes all HDF5 handles (hid_t) before File will notify other processes that the file is closed
38 // - refresh: makes the HDF5 refresh calls
39 // - flush: makes the HDF5 flush calls
40 // - enableSWMR: for type=write: closes all attributes than switches File to SWMR writing mode
41 // for type=writeWithRename: closes all elements, rename the file, reopen all elements
42 // except attributes, then switches File to SWMR writing mode
43
44 class Exception : public std::exception {
45 protected:
46 std::string path;
47 std::string msg;
48 mutable std::string whatMsg;
49 public:
50 explicit Exception(std::string path_, std::string msg_);
51 ~Exception() noexcept override;
52 const char* what() const noexcept override;
53 };
54
55 class ScopedHID {
56 protected:
57 using CloseFunc = herr_t (*)(hid_t);
58 hid_t id{-1};
59 CloseFunc closeFunc{nullptr};
60 public:
61 ScopedHID() = default;
62 ScopedHID(hid_t id_, CloseFunc closeFunc_) : id(id_), closeFunc(closeFunc_) {
63 if(id<0)
64 throw Exception("<unknown>", "Calling the HDF5 function failed.");
65 if(!closeFunc)
66 throw Exception("<unknown>", "No close function defined.");
67 }
68 ~ScopedHID() {
69 try {
70 reset();
71 }
72 catch(Exception &ex) {
73 std::cerr<<"Error in ScopedHID::dtor: "<<ex.what()<<std::endl;
74 }
75 }
76 operator hid_t() {
77 return id;
78 }
79 void reset() {
80 if(id>=0)
81 if(closeFunc(id)<0)
82 throw Exception("<unknown>", "Close function of ScopedHID failed.");
83 id=-1;
84 closeFunc=nullptr;
85 }
86 void reset(hid_t id_, CloseFunc closeFunc_) {
87 reset();
88 if(id_<0)
89 throw Exception("<unknown>", "Calling the HDF5 function failed (during reset).");
90 if(!closeFunc_)
91 throw Exception("<unknown>", "No close function defined.");
92 id=id_;
93 closeFunc=closeFunc_;
94 }
95 };
96
97 inline void checkCall(herr_t err) {
98 if(err<0)
99 throw Exception("<unknown>", "A HDF5 call failed.");
100 }
101
102 class File;
103 class GroupBase;
104 class Attribute;
105 class Object;
106 template<class Child, class Self> class Container;
107
108 enum ElementType {
109 simpleDatasetScalar,
110 simpleDatasetVector,
111 simpleDatasetMatrix,
112 vectorSerie,
113 simpleAttributeScalar,
114 simpleAttributeVector,
115 simpleAttributeMatrix
116 };
117
118 class Element : virtual public fmatvec::Atom {
119 friend class Container<Attribute, Object>;
120 friend class Container<Object, GroupBase>;
121 protected:
122 ScopedHID id;
123 std::string name;
124 Element(std::string name_);
125 ~Element() override;
126 virtual void close();
127 virtual void refresh();
128 virtual void flush();
129 virtual void enableSWMR();
130 public:
132 hid_t getID() { return id; }
133 std::string getName() { return name; }
134 };
135
136 // a container of objects of type Child which have itself a parent of type Self
137 template<class Child, class Self>
138 class Container {
139 protected:
140 Container() = default;
141 ~Container() {
142 for(auto it=childs.begin(); it!=childs.end(); ++it)
143 delete it->second;
144 }
145 void close() {
146 for(auto it=childs.begin(); it!=childs.end(); ++it)
147 it->second->close();
148 }
149 void refresh() {
150 for(auto it=childs.begin(); it!=childs.end(); ++it)
151 it->second->refresh();
152 }
153 void flush() {
154 for(auto it=childs.begin(); it!=childs.end(); ++it)
155 it->second->flush();
156 }
157 void enableSWMR() {
158 if constexpr (std::is_same_v<Child, Attribute>) {
159 // attributes must be closed if SWMR is enabled
160 for(auto it=childs.begin(); it!=childs.end(); ++it)
161 delete it->second;
162 childs.clear();
163 }
164 else {
165 // for everything else we just call enableSWMR (which usually does just nothing)
166 for(auto it=childs.begin(); it!=childs.end(); ++it)
167 {
168 it->second->enableSWMR();
169 }
170 }
171 }
172 std::map<std::string, Child*> childs;
173
174 // create a objet of class T which is derived from Child
175 template<class T>
176 class Creator {
177 protected:
178 Self *self;
179 std::string name;
180 std::map<std::string, Child*> &childs;
181 public:
182 Creator(Self *self_, std::string name_, std::map<std::string, Child*> &childs_) :
183 self(self_), name(std::move(name_)), childs(childs_) {}
184
185 template<typename... Args>
186 T* operator()(Args&&... args) {
187 auto ret=childs.insert(std::pair<std::string, Child*>(name, NULL));
188 if(!ret.second)
189 throw Exception(self->getPath(), "A element of name "+name+" already exists.");
190 try {
191 auto* r=new T(static_cast<Self*>(self), name, std::forward<Args>(args)...);
192 ret.first->second=r;
193 return r;
194 }
195 catch(...) {
196 childs.erase(name);
197 throw;
198 }
199 }
200 };
201 template<class T>
202 Creator<T> createChild(const std::string &name_) {
203 if(name_.find_first_of('/')!=std::string::npos)
204 throw Exception(static_cast<Self*>(this)->getPath(), "Internal error: must be a relative name, not absolute or a path");
205 return Creator<T>(static_cast<Self*>(this), name_, childs);
206 }
207
208 template<class T>
209 T* openChild(const std::string &name_) {
210 if(name_.find_first_of('/')!=std::string::npos)
211 throw Exception(static_cast<Self*>(this)->getPath(), "Internal error: must be a relative name, not absolute or a path");
212 std::pair<typename std::map<std::string, Child*>::iterator, bool> ret=childs.insert(std::pair<std::string, Child*>(name_, NULL));
213 if(!ret.second) {
214 auto *o=dynamic_cast<T*>(ret.first->second);
215 if(!o)
216 std::runtime_error("The element "+name_+" if of other type.");
217 return o;
218 }
219 try {
220 auto* r=new T(0, static_cast<Self*>(this), name_);
221 ret.first->second=r;
222 return r;
223 }
224 catch(...) {
225 childs.erase(name_);
226 throw;
227 }
228 }
229 };
230
231 class Object : public Element, public Container<Attribute, Object> {
232 friend class Container<Object, GroupBase>;
233 protected:
234 Object(GroupBase *parent_, const std::string &name_);
235 ~Object() override;
236 void close() override;
237 void refresh() override;
238 void flush() override;
239 void enableSWMR() override;
240 GroupBase *parent;
241 File *file;
242 Object *getFileAsObject(); // helper function used in openChildAttribute
243 Object *getAttrParent(const std::string &path, size_t pos); // helper function used in openChildAttribute
244 public:
245 template<class T>
246 Creator<T> createChildAttribute(const std::string &path) {
247 if(path[0]=='/') // absolute path -> call openChildAttribute from file
248 return getFileAsObject()->createChildAttribute<T>(path.substr(1));
249 // now its a relative path
250 size_t pos;
251 if((pos=path.find_last_of('/'))==std::string::npos) // no / included -> call openChild from Container
252 return createChild<T>(path);
253 // now its a relative path including at least one /
254 return getAttrParent(path, pos)->createChild<T>(path.substr(pos+1));
255 }
256
257 template<class T>
258 T* openChildAttribute(const std::string &path) {
259 if(path[0]=='/') // absolute path -> call openChildAttribute from file
260 return getFileAsObject()->openChildAttribute<T>(path.substr(1));
261 // now its a relative path
262 size_t pos;
263 if((pos=path.find_last_of('/'))==std::string::npos) // no / included -> call openChild from Container
264 return openChild<T>(path);
265 // now its a relative path including at least one /
266 return getAttrParent(path, pos)->openChild<T>(path.substr(pos+1));
267 }
268 Attribute *openChildAttribute(const std::string &name_, ElementType *attributeType=nullptr, hid_t *type=nullptr);
269 std::set<std::string> getChildAttributeNames();
270 bool hasChildAttribute(const std::string &name_);
271 GroupBase *getParent() { return parent; }
272 File *getFile() { return file; }
273 std::string getPath();
274 };
275
276 class Attribute : public Element {
277 friend class Container<Attribute, Object>;
278 protected:
279 Attribute(Object *parent_, const std::string &name_);
280 ~Attribute() override;
281 Object *parent;
282 File *file;
283 void close() override;
284 void refresh() override;
285 void flush() override;
286 public:
287 Object *getParent() { return parent; }
288 File *getFile() { return file; }
289 std::string getPath();
290 };
291
292 class Dataset : public Object {
293 protected:
294 Dataset(GroupBase *parent_, const std::string &name_);
295 Dataset(int dummy, GroupBase *parent_, const std::string &name_);
296 ~Dataset() override;
297 void close() override;
298 void refresh() override;
299 void flush() override;
300 void enableSWMR() override;
301 public:
302 std::vector<hsize_t> getExtentDims();
303 };
304
305}
306
307#endif
Definition: interface.h:276
Definition: interface.h:176
Definition: interface.h:138
Definition: interface.h:292
Definition: interface.h:118
hid_t getID()
Note: use the returned hid_t only temporarily since it may get invalid, at least when File::enableSWM...
Definition: interface.h:132
Definition: interface.h:44
Definition: file.h:106
Definition: group.h:31
Definition: interface.h:231
Definition: interface.h:55