openPMD-api
 
Loading...
Searching...
No Matches
AbstractIOHandlerImplCommon.hpp
1/* Copyright 2018-2025 Franz Poeschel, Axel Huebl
2 *
3 * This file is part of openPMD-api.
4 *
5 * openPMD-api is free software: you can redistribute it and/or modify
6 * it under the terms of of either the GNU General Public License or
7 * the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * openPMD-api is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License and the GNU Lesser General Public License
15 * for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * and the GNU Lesser General Public License along with openPMD-api.
19 * If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#pragma once
23
24#include "openPMD/IO/AbstractFilePosition.hpp"
25#include "openPMD/IO/AbstractIOHandler.hpp"
26#include "openPMD/IO/AbstractIOHandlerImpl.hpp"
27#include "openPMD/IO/InvalidatableFile.hpp"
28#include "openPMD/auxiliary/StringManip.hpp"
29#include "openPMD/backend/Writable.hpp"
30
31#include <stdexcept>
32#include <string>
33#include <unordered_map>
34#include <unordered_set>
35
36namespace openPMD
37{
38template <typename FilePositionType = AbstractFilePosition>
39class AbstractIOHandlerImplCommon : public AbstractIOHandlerImpl
40{
41 // friend struct detail::BufferedActions;
42public:
43 explicit AbstractIOHandlerImplCommon(AbstractIOHandler *handler);
44
45 ~AbstractIOHandlerImplCommon() override;
46
47protected:
52 std::unordered_map<Writable *, InvalidatableFile> m_files;
53 std::unordered_set<InvalidatableFile> m_dirty;
54
55 enum PossiblyExisting
56 {
57 PE_InvalidatableFile = 0,
58 PE_Iterator,
59 PE_NewlyCreated,
60 };
61
62 std::tuple<
64 std::unordered_map<Writable *, InvalidatableFile>::iterator,
65 bool>
66 getPossiblyExisting(std::string file);
67
68 void associateWithFile(Writable *writable, InvalidatableFile file);
69
75
76 std::string fullPath(std::string);
77
90 refreshFileFromParent(Writable *writable, bool preferParentFile);
91
99 std::shared_ptr<FilePositionType>
100 setAndGetFilePosition(Writable *writable, bool write = true);
101
108 virtual std::shared_ptr<FilePositionType>
109 setAndGetFilePosition(Writable *writable, std::string extend);
110
114 virtual std::string
115 filePositionToString(std::shared_ptr<FilePositionType>) = 0;
116
120 virtual std::shared_ptr<FilePositionType> extendFilePosition(
121 std::shared_ptr<FilePositionType> const &, std::string) = 0;
122};
123
124template <typename FilePositionType>
125AbstractIOHandlerImplCommon<FilePositionType>::AbstractIOHandlerImplCommon(
126 AbstractIOHandler *handler)
127 : AbstractIOHandlerImpl{handler}
128{}
129
130template <typename FilePositionType>
131AbstractIOHandlerImplCommon<FilePositionType>::~AbstractIOHandlerImplCommon() =
132 default;
133
134template <typename FilePositionType>
135std::tuple<
136 InvalidatableFile,
137 std::unordered_map<Writable *, InvalidatableFile>::iterator,
138 bool>
139AbstractIOHandlerImplCommon<FilePositionType>::getPossiblyExisting(
140 std::string file)
141{
142
143 auto it = std::find_if(
144 m_files.begin(),
145 m_files.end(),
146 [file](
147 std::unordered_map<Writable *, InvalidatableFile>::value_type const
148 &entry) {
149 return *entry.second == file && entry.second.valid();
150 });
151
152 bool newlyCreated;
153 InvalidatableFile name;
154 if (it == m_files.end())
155 {
156 name = file;
157 newlyCreated = true;
158 }
159 else
160 {
161 name = it->second;
162 newlyCreated = false;
163 }
164 return std::tuple<
166 std::unordered_map<Writable *, InvalidatableFile>::iterator,
167 bool>(std::move(name), it, newlyCreated);
168}
169
170template <typename FilePositionType>
171void AbstractIOHandlerImplCommon<FilePositionType>::associateWithFile(
172 Writable *writable, InvalidatableFile file)
173{
174 // make sure to overwrite
175 m_files[writable] = std::move(file);
176}
177
178template <typename FilePositionType>
180 InvalidatableFile fileName)
181{
182 return fullPath(*fileName);
183}
184
185template <typename FilePositionType>
186std::string
188{
189 if (auxiliary::ends_with(m_handler->directory, "/"))
190 {
191 return m_handler->directory + fileName;
192 }
193 else
194 {
195 return m_handler->directory + "/" + fileName;
196 }
197}
198
199template <typename FilePositionType>
202 Writable *writable, bool preferParentFile)
203{
204 auto getFileFromParent = [writable, this]() {
205 auto file_it = m_files.find(writable->parent);
206 if (file_it == m_files.end())
207 {
208 std::stringstream s;
209 s << "Parent Writable " << writable->parent << " of Writable "
210 << writable << " has no associated file.";
211 throw std::runtime_error(s.str());
212 }
213 auto file = m_files.find(writable->parent)->second;
214 associateWithFile(writable, file);
215 return file;
216 };
217 if (preferParentFile && writable->parent)
218 {
219 return getFileFromParent();
220 }
221 else
222 {
223 auto it = m_files.find(writable);
224 if (it != m_files.end())
225 {
226 return m_files.find(writable)->second;
227 }
228 else if (writable->parent)
229 {
230 return getFileFromParent();
231 }
232 else
233 {
234 throw std::runtime_error(
235 "Internal error: Root object must be opened explicitly.");
236 }
237 }
238}
239
240template <typename FilePositionType>
241std::shared_ptr<FilePositionType>
243 Writable *writable, bool write)
244{
245 std::shared_ptr<AbstractFilePosition> res;
246
247 if (writable->abstractFilePosition)
248 {
249 res = writable->abstractFilePosition;
250 }
251 else if (writable->parent)
252 {
253 res = writable->parent->abstractFilePosition;
254 }
255 else
256 { // we are root
257 res = std::make_shared<FilePositionType>();
258 }
259 if (write)
260 {
261 writable->abstractFilePosition = res;
262 }
263 return std::dynamic_pointer_cast<FilePositionType>(res);
264}
265
266template <typename FilePositionType>
267std::shared_ptr<FilePositionType>
269 Writable *writable, std::string extend)
270{
271 if (!auxiliary::starts_with(extend, '/'))
272 {
273 extend = "/" + extend;
274 }
275 auto oldPos = setAndGetFilePosition(writable, false);
276 auto res = extendFilePosition(oldPos, extend);
277
278 writable->abstractFilePosition = res;
279 return res;
280}
281} // namespace openPMD
Interface for communicating between logical and physically persistent data.
Definition AbstractIOHandler.hpp:206
std::unordered_map< Writable *, InvalidatableFile > m_files
map each Writable to its associated file contains only the filename, without the OS path
Definition AbstractIOHandlerImplCommon.hpp:52
std::string fullPath(InvalidatableFile)
Definition AbstractIOHandlerImplCommon.hpp:179
InvalidatableFile refreshFileFromParent(Writable *writable, bool preferParentFile)
Get the writable's containing file.
Definition AbstractIOHandlerImplCommon.hpp:201
virtual std::shared_ptr< FilePositionType > setAndGetFilePosition(Writable *writable, std::string extend)
Figure out the file position of the writable and extend it.
Definition AbstractIOHandlerImplCommon.hpp:268
virtual std::shared_ptr< FilePositionType > extendFilePosition(std::shared_ptr< FilePositionType > const &, std::string)=0
virtual std::string filePositionToString(std::shared_ptr< FilePositionType >)=0
std::shared_ptr< FilePositionType > setAndGetFilePosition(Writable *writable, bool write=true)
Figure out the file position of the writable.
Definition AbstractIOHandlerImplCommon.hpp:242
Definition AbstractIOHandlerImpl.hpp:36
Layer to mirror structure of logical data and persistent data in file.
Definition Writable.hpp:76
Public definitions of openPMD-api.
Definition Date.cpp:29
Wrapper around a shared pointer to:
Definition InvalidatableFile.hpp:44