openPMD-api
AbstractIOHandlerImplCommon.hpp
1 /* Copyright 2018-2020 Franz Poeschel
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 
25 #include "openPMD/IO/AbstractFilePosition.hpp"
26 #include "openPMD/IO/AbstractIOHandler.hpp"
27 #include "openPMD/IO/AbstractIOHandlerImpl.hpp"
28 #include "openPMD/IO/InvalidatableFile.hpp"
29 #include "openPMD/auxiliary/StringManip.hpp"
30 #include "openPMD/backend/Writable.hpp"
31 
32 #include <unordered_map>
33 #include <unordered_set>
34 
35 
36 
37 namespace openPMD
38 {
39 template < typename FilePositionType = AbstractFilePosition >
40 class AbstractIOHandlerImplCommon : public AbstractIOHandlerImpl
41 {
42  // friend struct detail::BufferedActions;
43 public:
44  explicit AbstractIOHandlerImplCommon( AbstractIOHandler * handler );
45 
46  ~AbstractIOHandlerImplCommon( ) override;
47 
48 protected:
53  std::unordered_map< Writable *, InvalidatableFile > m_files;
54  std::unordered_set< InvalidatableFile > m_dirty;
55 
56  enum PossiblyExisting
57  {
58  PE_InvalidatableFile = 0,
59  PE_Iterator,
60  PE_NewlyCreated,
61  };
62 
63  std::tuple< InvalidatableFile,
64  std::unordered_map< Writable *, InvalidatableFile >::iterator,
65  bool
66  > getPossiblyExisting( std::string file );
67 
68  void associateWithFile( Writable * writable, InvalidatableFile file );
69 
74  std::string fullPath( InvalidatableFile );
75 
76  std::string fullPath( std::string );
77 
85  InvalidatableFile refreshFileFromParent( Writable * writable );
86 
94  std::shared_ptr< FilePositionType >
95  setAndGetFilePosition( Writable * writable, bool write = true );
96 
103  virtual std::shared_ptr< FilePositionType >
104  setAndGetFilePosition( Writable * writable, std::string extend );
105 
109  virtual std::string
110  filePositionToString( std::shared_ptr< FilePositionType > ) = 0;
111 
115  virtual std::shared_ptr< FilePositionType >
116  extendFilePosition( std::shared_ptr< FilePositionType > const &,
117  std::string ) = 0;
118 };
119 
120 template < typename FilePositionType >
122  AbstractIOHandler * handler )
123 : AbstractIOHandlerImpl{handler}
124 {
125 }
126 
127 
128 template < typename FilePositionType >
130  FilePositionType >::~AbstractIOHandlerImplCommon( ) = default;
131 
132 
133 template < typename FilePositionType >
134 std::tuple< InvalidatableFile,
135  std::unordered_map< Writable *, InvalidatableFile >::iterator,
136  bool >
138  std::string file )
139 {
140 
141  auto it = std::find_if(
142  m_files.begin( ), m_files.end( ),
143  [file]( std::unordered_map<
144  Writable *, InvalidatableFile >::value_type const & entry ) {
145  return *entry.second == file && entry.second.valid( );
146  } );
147 
148  bool newlyCreated;
149  InvalidatableFile name;
150  if ( it == m_files.end( ) )
151  {
152  name = file;
153  newlyCreated = true;
154  }
155  else
156  {
157  name = it->second;
158  newlyCreated = false;
159  }
160  return std::tuple<
161  InvalidatableFile,
162  std::unordered_map< Writable *, InvalidatableFile >::iterator, bool >(
163  std::move( name ), it, newlyCreated );
164 }
165 
166 
167 template < typename FilePositionType >
169  Writable * writable, InvalidatableFile file )
170 {
171  // make sure to overwrite
172  m_files[writable] = std::move( file );
173 }
174 
175 
176 template < typename FilePositionType >
178  InvalidatableFile fileName )
179 {
180  return fullPath( *fileName );
181 }
182 
183 
184 template < typename FilePositionType >
186  std::string fileName )
187 {
188  if ( auxiliary::ends_with( m_handler->directory, "/" ) )
189  {
190  return m_handler->directory + fileName;
191  }
192  else
193  {
194  return m_handler->directory + "/" + fileName;
195  }
196 }
197 
198 
199 template < typename FilePositionType >
200 InvalidatableFile
202  Writable * writable )
203 {
204  if ( writable->parent )
205  {
206  auto file = m_files.find( writable->parent )->second;
207  associateWithFile( writable, file );
208  return file;
209  }
210  else
211  {
212  return m_files.find( writable )->second;
213  }
214 }
215 
216 
217 template < typename FilePositionType >
218 std::shared_ptr< FilePositionType >
220  Writable * writable, bool write )
221 {
222  std::shared_ptr< AbstractFilePosition > res;
223 
224  if ( writable->abstractFilePosition )
225  {
226  res = writable->abstractFilePosition;
227  }
228  else if ( writable->parent )
229  {
230  res = writable->parent->abstractFilePosition;
231  }
232  else
233  { // we are root
234  res = std::make_shared< FilePositionType >( );
235  }
236  if ( write )
237  {
238  writable->abstractFilePosition = res;
239  }
240  return std::dynamic_pointer_cast< FilePositionType >( res );
241 }
242 
243 
244 template < typename FilePositionType >
245 std::shared_ptr< FilePositionType >
247  Writable * writable, std::string extend )
248 {
249  if ( !auxiliary::starts_with( extend, '/' ) )
250  {
251  extend = "/" + extend;
252  }
253  auto oldPos = setAndGetFilePosition( writable, false );
254  auto res = extendFilePosition( oldPos, extend );
255 
256  writable->abstractFilePosition = res;
257  return res;
258 }
259 } // namespace openPMD
std::shared_ptr< FilePositionType > setAndGetFilePosition(Writable *writable, bool write=true)
Figure out the file position of the writable.
Definition: AbstractIOHandlerImplCommon.hpp:219
Wrapper around a shared pointer to:
Definition: InvalidatableFile.hpp:45
virtual std::shared_ptr< FilePositionType > extendFilePosition(std::shared_ptr< FilePositionType > const &, std::string)=0
Interface for communicating between logical and physically persistent data.
Definition: AbstractIOHandler.hpp:68
Public definitions of openPMD-api.
Definition: Date.cpp:29
Layer to mirror structure of logical data and persistent data in file.
Definition: Writable.hpp:55
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:53
Definition: Writable.hpp:43
virtual std::string filePositionToString(std::shared_ptr< FilePositionType >)=0
InvalidatableFile refreshFileFromParent(Writable *writable)
Get the writable&#39;s containing file.
Definition: AbstractIOHandlerImplCommon.hpp:201
Definition: AbstractIOHandlerImpl.hpp:35
std::string fullPath(InvalidatableFile)
Definition: AbstractIOHandlerImplCommon.hpp:177