openPMD-api
ADIOS2IOHandler.hpp
1 /* Copyright 2017-2020 Fabian Koller and 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 #pragma once
22 
23 #include "openPMD/IO/AbstractIOHandler.hpp"
24 #include "openPMD/IO/AbstractIOHandlerImpl.hpp"
25 #include "openPMD/IO/AbstractIOHandlerImplCommon.hpp"
26 #include "openPMD/IO/ADIOS/ADIOS2Auxiliary.hpp"
27 #include "openPMD/IO/ADIOS/ADIOS2FilePosition.hpp"
28 #include "openPMD/IO/IOTask.hpp"
29 #include "openPMD/IO/InvalidatableFile.hpp"
30 #include "openPMD/auxiliary/JSON.hpp"
31 #include "openPMD/auxiliary/Option.hpp"
32 #include "openPMD/backend/Writable.hpp"
33 #include "openPMD/config.hpp"
34 
35 #if openPMD_HAVE_ADIOS2
36 # include <adios2.h>
37 #endif
38 #if openPMD_HAVE_MPI
39 # include <mpi.h>
40 #endif
41 #include <nlohmann/json.hpp>
42 
43 #include <array>
44 #include <exception>
45 #include <future>
46 #include <iostream>
47 #include <memory> // shared_ptr
48 #include <set>
49 #include <string>
50 #include <unordered_map>
51 #include <utility> // pair
52 #include <vector>
53 
54 
55 namespace openPMD
56 {
57 #if openPMD_HAVE_ADIOS2
58 
59 class ADIOS2IOHandler;
60 
61 namespace detail
62 {
63  template < typename, typename > struct DatasetHelper;
64  struct DatasetReader;
65  struct AttributeReader;
66  struct AttributeWriter;
67  template < typename > struct AttributeTypes;
68  struct DatasetOpener;
69  template < typename > struct DatasetTypes;
70  struct WriteDataset;
71  struct BufferedActions;
72  struct BufferedPut;
73  struct BufferedGet;
74  struct BufferedAttributeRead;
75 } // namespace detail
76 
77 
79 : public AbstractIOHandlerImplCommon< ADIOS2FilePosition >
80 {
81  template < typename, typename > friend struct detail::DatasetHelper;
82  friend struct detail::DatasetReader;
83  friend struct detail::AttributeReader;
84  friend struct detail::AttributeWriter;
85  template < typename > friend struct detail::AttributeTypes;
86  friend struct detail::DatasetOpener;
87  template < typename > friend struct detail::DatasetTypes;
88  friend struct detail::WriteDataset;
89  friend struct detail::BufferedActions;
90  friend struct detail::BufferedAttributeRead;
91 
92  static constexpr bool ADIOS2_DEBUG_MODE = false;
93 
94 
95 public:
96 
97 #if openPMD_HAVE_MPI
98 
101  MPI_Comm,
102  nlohmann::json config,
103  std::string engineType );
104 
105 #endif // openPMD_HAVE_MPI
106 
107  explicit ADIOS2IOHandlerImpl(
109  nlohmann::json config,
110  std::string engineType );
111 
112 
113  ~ADIOS2IOHandlerImpl() override;
114 
115  std::future< void > flush( ) override;
116 
117  void createFile( Writable *,
118  Parameter< Operation::CREATE_FILE > const & ) override;
119 
120  void createPath( Writable *,
121  Parameter< Operation::CREATE_PATH > const & ) override;
122 
123  void
124  createDataset( Writable *,
125  Parameter< Operation::CREATE_DATASET > const & ) override;
126 
127  void
128  extendDataset( Writable *,
129  Parameter< Operation::EXTEND_DATASET > const & ) override;
130 
131  void openFile( Writable *,
132  Parameter< Operation::OPEN_FILE > const & ) override;
133 
134  void closeFile( Writable *,
135  Parameter< Operation::CLOSE_FILE > const & ) override;
136 
137  void openPath( Writable *,
138  Parameter< Operation::OPEN_PATH > const & ) override;
139 
140  void closePath( Writable *,
141  Parameter< Operation::CLOSE_PATH > const & ) override;
142 
143  void openDataset( Writable *,
145 
146  void deleteFile( Writable *,
147  Parameter< Operation::DELETE_FILE > const & ) override;
148 
149  void deletePath( Writable *,
150  Parameter< Operation::DELETE_PATH > const & ) override;
151 
152  void
153  deleteDataset( Writable *,
154  Parameter< Operation::DELETE_DATASET > const & ) override;
155 
156  void deleteAttribute( Writable *,
157  Parameter< Operation::DELETE_ATT > const & ) override;
158 
159  void writeDataset( Writable *,
160  Parameter< Operation::WRITE_DATASET > const & ) override;
161 
162  void writeAttribute( Writable *,
163  Parameter< Operation::WRITE_ATT > const & ) override;
164 
165  void readDataset( Writable *,
167 
168  void readAttribute( Writable *,
170 
171  void listPaths( Writable *, Parameter< Operation::LIST_PATHS > & ) override;
172 
173  void listDatasets( Writable *,
175 
176  void
177  listAttributes( Writable *,
178  Parameter< Operation::LIST_ATTS > & parameters ) override;
179 
180  void
181  advance( Writable*, Parameter< Operation::ADVANCE > & ) override;
182 
183  void
184  availableChunks( Writable*,
190  adios2::Mode adios2AccessMode( std::string const & fullPath );
191 
192 private:
193  adios2::ADIOS m_ADIOS;
197  std::string m_engineType;
198 
199  struct ParameterizedOperator
200  {
201  adios2::Operator op;
202  adios2::Params params;
203  };
204 
205  std::vector< ParameterizedOperator > defaultOperators;
206 
207  auxiliary::TracingJSON m_config;
208  static auxiliary::TracingJSON nullvalue;
209 
210  void
211  init( nlohmann::json config );
212 
213  template< typename Key >
215  config( Key && key, auxiliary::TracingJSON & cfg )
216  {
217  if( cfg.json().is_object() && cfg.json().contains( key ) )
218  {
219  return cfg[ key ];
220  }
221  else
222  {
223  return nullvalue;
224  }
225  }
226 
227  template< typename Key >
229  config( Key && key )
230  {
231  return config< Key >( std::forward< Key >( key ), m_config );
232  }
233 
242  getOperators( auxiliary::TracingJSON config );
243 
244  // use m_config
246  getOperators();
247 
248  std::string
249  fileSuffix() const;
250 
251  /*
252  * We need to give names to IO objects. These names are irrelevant
253  * within this application, since:
254  * 1) The name of the file written to is decided by the opened Engine's
255  * name.
256  * 2) The IOs are managed by the unordered_map m_fileData, so we do not
257  * need the ADIOS2 internal management.
258  * Since within one m_ADIOS object, the same IO name cannot be used more
259  * than once, we ensure different names by using the name counter.
260  * This allows to overwrite a file later without error.
261  */
262  int nameCounter{0};
263 
264  /*
265  * IO-heavy actions are deferred to a later point. This map stores for
266  * each open file (identified by an InvalidatableFile object) an object
267  * that manages IO-heavy actions, as well as its ADIOS2 objects, i.e.
268  * IO and Engine object.
269  * Not to be accessed directly, use getFileData().
270  */
271  std::unordered_map< InvalidatableFile,
272  std::unique_ptr< detail::BufferedActions >
273  > m_fileData;
274 
275  std::map< std::string, adios2::Operator > m_operators;
276 
277  // Overrides from AbstractIOHandlerImplCommon.
278 
279  std::string
280  filePositionToString( std::shared_ptr< ADIOS2FilePosition > ) override;
281 
282  std::shared_ptr< ADIOS2FilePosition >
283  extendFilePosition( std::shared_ptr< ADIOS2FilePosition > const & pos,
284  std::string extend ) override;
285 
286  // Helper methods.
287 
289  getCompressionOperator( std::string const & compression );
290 
291  /*
292  * The name of the ADIOS2 variable associated with this Writable.
293  * To be used for Writables that represent a dataset.
294  */
295  std::string nameOfVariable( Writable * writable );
296 
306  std::string nameOfAttribute( Writable * writable, std::string attribute );
307 
308  /*
309  * Figure out whether the Writable corresponds with a
310  * group or a dataset.
311  */
312  ADIOS2FilePosition::GD groupOrDataset( Writable * );
313 
314  detail::BufferedActions & getFileData( InvalidatableFile file );
315 
316  void dropFileData( InvalidatableFile file );
317 
318  /*
319  * Prepare a variable that already exists for an IO
320  * operation, including:
321  * (1) checking that its datatype matches T.
322  * (2) the offset and extent match the variable's shape
323  * (3) setting the offset and extent (ADIOS lingo: start
324  * and count)
325  */
326  template < typename T >
327  adios2::Variable< T > verifyDataset( Offset const & offset,
328  Extent const & extent, adios2::IO & IO,
329  std::string const & var );
330 }; // ADIOS2IOHandlerImpl
331 
332 /*
333  * The following strings are used during parsing of the JSON configuration
334  * string for the ADIOS2 backend.
335  */
336 namespace ADIOS2Defaults
337 {
338  using const_str = char const * const;
339  constexpr const_str str_engine = "engine";
340  constexpr const_str str_type = "type";
341  constexpr const_str str_params = "parameters";
342  constexpr const_str str_usesteps = "usesteps";
343  constexpr const_str str_usesstepsAttribute = "__openPMD_internal/useSteps";
344 } // namespace ADIOS2Defaults
345 
346 namespace detail
347 {
348  // Helper structs for calls to the switchType function
349 
351  {
353 
354 
355  explicit DatasetReader( openPMD::ADIOS2IOHandlerImpl * impl );
356 
357 
358  template < typename T >
359  void operator( )( BufferedGet & bp, adios2::IO & IO,
360  adios2::Engine & engine,
361  std::string const & fileName );
362 
363  template < int T, typename... Params > void operator( )( Params &&... );
364  };
365 
367  {
368  template < typename T >
369  Datatype operator( )( adios2::IO & IO, std::string name,
370  std::shared_ptr< Attribute::resource > resource );
371 
372  template < int n, typename... Params >
373  Datatype operator( )( Params &&... );
374  };
375 
377  {
378  template < typename T >
379  void
380  operator( )( ADIOS2IOHandlerImpl * impl, Writable * writable,
381  const Parameter< Operation::WRITE_ATT > & parameters );
382 
383 
384  template < int n, typename... Params > void operator( )( Params &&... );
385  };
386 
388  {
389  ADIOS2IOHandlerImpl * m_impl;
390 
391 
392  explicit DatasetOpener( ADIOS2IOHandlerImpl * impl );
393 
394 
395  template < typename T >
396  void operator( )( InvalidatableFile, const std::string & varName,
398 
399 
400  template < int n, typename... Params > void operator( )( Params &&... );
401  };
402 
404  {
405  ADIOS2IOHandlerImpl * m_handlerImpl;
406 
407 
408  WriteDataset( ADIOS2IOHandlerImpl * handlerImpl );
409 
410 
411  template < typename T >
412  void operator( )( BufferedPut & bp, adios2::IO & IO,
413  adios2::Engine & engine );
414 
415  template < int n, typename... Params > void operator( )( Params &&... );
416  };
417 
419  {
420  // Parameters such as DatasetHelper< T >::defineVariable
421  template < typename T, typename... Params >
422  void operator( )( Params &&... params );
423 
424  template< int n, typename... Params >
425  void
426  operator()( Params &&... );
427  };
428 
430  {
431  template < typename T, typename... Params >
432  void operator( )( Params &&... );
433 
434  template < int n, typename... Params >
435  void operator( )( Params &&... );
436  };
437 
438  // Helper structs to help distinguish valid attribute/variable
439  // datatypes from invalid ones
440 
441  /*
442  * This struct's purpose is to have specialisations
443  * for vector and array types, as well as the boolean
444  * type (which is not natively supported by ADIOS).
445  */
446  template < typename T > struct AttributeTypes
447  {
448  using Attr = adios2::Attribute< T >;
449  using BasicType = T;
450 
451  static Attr createAttribute( adios2::IO & IO, std::string name,
452  BasicType value );
453 
454  static void
455  readAttribute( adios2::IO & IO, std::string name,
456  std::shared_ptr< Attribute::resource > resource );
457 
462  static bool
463  attributeUnchanged( adios2::IO & IO, std::string name, BasicType val )
464  {
465  auto attr = IO.InquireAttribute< BasicType >( name );
466  if( !attr )
467  {
468  return false;
469  }
470  std::vector< BasicType > data = attr.Data();
471  if( data.size() != 1 )
472  {
473  return false;
474  }
475  return data[ 0 ] == val;
476  }
477  };
478 
479  template< > struct AttributeTypes< std::complex< long double > >
480  {
481  using Attr = adios2::Attribute< std::complex< double > >;
482  using BasicType = double;
483 
484  static Attr createAttribute( adios2::IO &, std::string,
485  std::complex< long double > )
486  {
487  throw std::runtime_error(
488  "[ADIOS2] Internal error: no support for long double complex attribute types" );
489  }
490 
491  static void
492  readAttribute( adios2::IO &, std::string,
493  std::shared_ptr< Attribute::resource > )
494  {
495  throw std::runtime_error(
496  "[ADIOS2] Internal error: no support for long double complex attribute types" );
497  }
498 
499  static bool
500  attributeUnchanged(
501  adios2::IO &, std::string, std::complex< long double > )
502  {
503  throw std::runtime_error(
504  "[ADIOS2] Internal error: no support for long double complex attribute types" );
505  }
506  };
507 
508  template< > struct AttributeTypes< std::vector< std::complex< long double > > >
509  {
510  using Attr = adios2::Attribute< std::complex< double > >;
511  using BasicType = double;
512 
513  static Attr createAttribute( adios2::IO &, std::string,
514  const std::vector< std::complex< long double > > & )
515  {
516  throw std::runtime_error(
517  "[ADIOS2] Internal error: no support for long double complex vector attribute types" );
518  }
519 
520  static void
521  readAttribute( adios2::IO &, std::string,
522  std::shared_ptr< Attribute::resource > )
523  {
524  throw std::runtime_error(
525  "[ADIOS2] Internal error: no support for long double complex vector attribute types" );
526  }
527 
528  static bool
529  attributeUnchanged(
530  adios2::IO &,
531  std::string,
532  std::vector< std::complex< long double > > )
533  {
534  throw std::runtime_error(
535  "[ADIOS2] Internal error: no support for long double complex vector attribute types" );
536  }
537  };
538 
539  template < typename T > struct AttributeTypes< std::vector< T > >
540  {
541  using Attr = adios2::Attribute< T >;
542  using BasicType = T;
543 
544  static Attr createAttribute( adios2::IO & IO, std::string name,
545  const std::vector< T > & value );
546 
547  static void
548  readAttribute( adios2::IO & IO, std::string name,
549  std::shared_ptr< Attribute::resource > resource );
550 
551  static bool
552  attributeUnchanged(
553  adios2::IO & IO,
554  std::string name,
555  std::vector< T > val )
556  {
557  auto attr = IO.InquireAttribute< BasicType >( name );
558  if( !attr )
559  {
560  return false;
561  }
562  std::vector< BasicType > data = attr.Data();
563  if( data.size() != val.size() )
564  {
565  return false;
566  }
567  for( size_t i = 0; i < val.size(); ++i )
568  {
569  if( data[ i ] != val[ i ] )
570  {
571  return false;
572  }
573  }
574  return true;
575  }
576  };
577 
578  template < typename T, size_t n >
579  struct AttributeTypes< std::array< T, n > >
580  {
581  using Attr = adios2::Attribute< T >;
582  using BasicType = T;
583 
584  static Attr createAttribute( adios2::IO & IO, std::string name,
585  const std::array< T, n > & value );
586 
587  static void
588  readAttribute( adios2::IO & IO, std::string name,
589  std::shared_ptr< Attribute::resource > resource );
590 
591  static bool
592  attributeUnchanged(
593  adios2::IO & IO,
594  std::string name,
595  std::array< T, n > val )
596  {
597  auto attr = IO.InquireAttribute< BasicType >( name );
598  if( !attr )
599  {
600  return false;
601  }
602  std::vector< BasicType > data = attr.Data();
603  if( data.size() != n )
604  {
605  return false;
606  }
607  for( size_t i = 0; i < n; ++i )
608  {
609  if( data[ i ] != val[ i ] )
610  {
611  return false;
612  }
613  }
614  return true;
615  }
616  };
617 
618  template <> struct AttributeTypes< bool >
619  {
620  using rep = detail::bool_representation;
621  using Attr = adios2::Attribute< rep >;
622  using BasicType = rep;
623 
624  static Attr createAttribute( adios2::IO & IO, std::string name,
625  bool value );
626 
627  static void
628  readAttribute( adios2::IO & IO, std::string name,
629  std::shared_ptr< Attribute::resource > resource );
630 
631 
632  static constexpr rep toRep( bool b )
633  {
634  return b ? 1U : 0U;
635  }
636 
637 
638  static constexpr bool fromRep( rep r )
639  {
640  return r != 0;
641  }
642 
643  static bool
644  attributeUnchanged( adios2::IO & IO, std::string name, bool val )
645  {
646  auto attr = IO.InquireAttribute< BasicType >( name );
647  if( !attr )
648  {
649  return false;
650  }
651  std::vector< BasicType > data = attr.Data();
652  if( data.size() != 1 )
653  {
654  return false;
655  }
656  return data[ 0 ] == toRep( val );
657  }
658  };
659 
660 
666  template < typename T > struct DatasetTypes
667  {
668  static constexpr bool validType = true;
669  };
670 
671  template < typename T > struct DatasetTypes< std::vector< T > >
672  {
673  static constexpr bool validType = false;
674  };
675 
676  template <> struct DatasetTypes< bool >
677  {
678  static constexpr bool validType = false;
679  };
680 
681  // missing std::complex< long double > type in ADIOS2 v2.6.0
682  template <> struct DatasetTypes< std::complex< long double > >
683  {
684  static constexpr bool validType = false;
685  };
686 
687  template < typename T, size_t n > struct DatasetTypes< std::array< T, n > >
688  {
689  static constexpr bool validType = false;
690  };
691 
692  /*
693  * This struct's purpose is to have exactly two specialisations:
694  * (1) for types that are legal to use in a dataset
695  * (2) for types that are not legal to use in a dataset
696  * The methods in the latter specialisation will fail at runtime.
697  */
698  template < typename, typename = void > struct DatasetHelper;
699 
700  template < typename T >
702  T, typename std::enable_if< DatasetTypes< T >::validType >::type >
703  {
705 
706 
707  explicit DatasetHelper( openPMD::ADIOS2IOHandlerImpl * impl );
708 
709 
710  void openDataset( InvalidatableFile, const std::string & varName,
712 
713  void readDataset( BufferedGet &, adios2::IO &, adios2::Engine &,
714  std::string const & fileName );
715 
731  static void
732  defineVariable(
733  adios2::IO & IO,
734  std::string const & name,
735  std::vector< ADIOS2IOHandlerImpl::ParameterizedOperator > const &
736  compressions,
737  adios2::Dims const & shape = adios2::Dims(),
738  adios2::Dims const & start = adios2::Dims(),
739  adios2::Dims const & count = adios2::Dims(),
740  bool const constantDims = false );
741 
742  void writeDataset( BufferedPut &, adios2::IO &, adios2::Engine & );
743 
744  static void
745  blocksInfo(
747  adios2::IO & IO,
748  adios2::Engine & engine,
749  std::string const & varName );
750  };
751 
752  template < typename T >
754  T, typename std::enable_if< !DatasetTypes< T >::validType >::type >
755  {
756  explicit DatasetHelper( openPMD::ADIOS2IOHandlerImpl * impl );
757 
758 
759  static void throwErr( );
760 
761  template < typename... Params > void openDataset( Params &&... );
762 
763  template < typename... Params > void readDataset( Params &&... );
764 
765  template < typename... Params >
766  static void defineVariable( Params &&... );
767 
768  template < typename... Params > void writeDataset( Params &&... );
769 
770  template < typename... Params > static void blocksInfo( Params &&... );
771  };
772 
773  // Other datatypes used in the ADIOS2IOHandler implementation
774 
775 
776  struct BufferedActions;
777 
778  /*
779  * IO-heavy action to be executed upon flushing.
780  */
782  {
783  virtual ~BufferedAction( ) = default;
784 
785  virtual void run( BufferedActions & ) = 0;
786  };
787 
789  {
790  std::string name;
792 
793  void run( BufferedActions & ) override;
794  };
795 
797  {
798  std::string name;
800 
801  void run( BufferedActions & ) override;
802  };
803 
805  {
807  std::string name;
808 
809  void run( BufferedActions & ) override;
810  };
811 
812  /*
813  * Manages per-file information about
814  * (1) the file's IO and Engine objects
815  * (2) the file's deferred IO-heavy actions
816  */
818  {
819  BufferedActions( BufferedActions const & ) = delete;
820 
828  std::string m_file;
847  std::string const m_IOName;
848  adios2::ADIOS & m_ADIOS;
849  adios2::IO m_IO;
850  std::vector< std::unique_ptr< BufferedAction > > m_buffer;
851  adios2::Mode m_mode;
852  detail::WriteDataset const m_writeDataset;
853  detail::DatasetReader const m_readDataset;
854  detail::AttributeReader const m_attributeReader;
855 
856  /*
857  * We call an attribute committed if the step during which it was
858  * written has been closed.
859  * A committed attribute cannot be modified.
860  */
861  std::set< std::string > uncommittedAttributes;
862 
863  /*
864  * The openPMD API will generally create new attributes for each
865  * iteration. This results in a growing number of attributes over time.
866  * In streaming-based modes, these will be completely sent anew in each
867  * iteration. If the following boolean is true, old attributes will be
868  * removed upon CLOSE_GROUP.
869  * Should not be set to true in persistent backends.
870  * Will be automatically set by BufferedActions::configure_IO depending
871  * on chosen ADIOS2 engine and can not be explicitly overridden by user.
872  */
873  bool optimizeAttributesStreaming = false;
874 
875  using AttributeMap_t = std::map< std::string, adios2::Params >;
876 
878 
879  ~BufferedActions( );
880 
885  void
886  finalize();
887 
888  adios2::Engine & getEngine( );
889  adios2::Engine & requireActiveStep( );
890 
891  template < typename BA > void enqueue( BA && ba );
892 
893  template < typename BA > void enqueue( BA && ba, decltype( m_buffer ) & );
894 
908  template< typename F >
909  void
910  flush( F && performPutsGets, bool flushUnconditionally );
911 
917  void
918  flush();
919 
927  advance( AdvanceMode mode );
928 
929  /*
930  * Delete all buffered actions without running them.
931  */
932  void drop( );
933 
934  AttributeMap_t const &
935  availableAttributes();
936 
937  std::vector< std::string >
938  availableAttributesPrefixed( std::string const & prefix );
939 
940  /*
941  * See description below.
942  */
943  void
944  invalidateAttributesMap();
945 
946  AttributeMap_t const &
947  availableVariables();
948 
949  std::vector< std::string >
950  availableVariablesPrefixed( std::string const & prefix );
951 
952  /*
953  * See description below.
954  */
955  void
956  invalidateVariablesMap();
957 
958  private:
960 
963  std::string m_engineType;
964  /*
965  * streamStatus is NoStream for file-based ADIOS engines.
966  * This is relevant for the method BufferedActions::requireActiveStep,
967  * where a step is only opened if the status is OutsideOfStep, but not
968  * if NoStream. The rationale behind this is that parsing a Series
969  * works differently for file-based and for stream-based engines:
970  * * stream-based: Iterations are parsed as they arrive. For parsing an
971  * iteration, the iteration must be awaited.
972  * BufferedActions::requireActiveStep takes care of this.
973  * * file-based: The Series is parsed up front. If no step has been
974  * opened yet, ADIOS2 gives access to all variables and attributes
975  * from all steps. Upon opening a step, only the variables from that
976  * step are shown which hinders parsing. So, until a step is
977  * explicitly opened via ADIOS2IOHandlerImpl::advance, do not open
978  * one.
979  * (This is a workaround for the fact that attributes
980  * are not associated with steps in ADIOS -- seeing all attributes
981  * from all steps in file-based engines, but only the current
982  * variables breaks parsing otherwise.)
983  *
984  */
985  enum class StreamStatus
986  {
990  DuringStep,
994  OutsideOfStep,
998  StreamOver,
1010  NoStream,
1025  Parsing,
1031  Undecided
1032  };
1033  StreamStatus streamStatus = StreamStatus::OutsideOfStep;
1034  adios2::StepStatus m_lastStepStatus = adios2::StepStatus::OK;
1035 
1041  bool delayOpeningTheFirstStep = false;
1042 
1043  /*
1044  * ADIOS2 does not give direct access to its internal attribute and
1045  * variable maps, but will instead give access to copies of them.
1046  * In order to avoid unnecessary copies, we buffer the returned map.
1047  * The downside of this is that we need to pay attention to invalidate
1048  * the map whenever an attribute/variable is altered. In that case, we
1049  * fetch the map anew.
1050  * If empty, the buffered map has been invalidated and needs to be
1051  * queried from ADIOS2 again. If full, the buffered map is equivalent to
1052  * the map that would be returned by a call to
1053  * IO::Available(Attributes|Variables).
1054  */
1055  auxiliary::Option< AttributeMap_t > m_availableAttributes;
1056  auxiliary::Option< AttributeMap_t > m_availableVariables;
1057 
1058  /*
1059  * finalize() will set this true to avoid running twice.
1060  */
1061  bool finalized = false;
1062 
1063  void
1064  configure_IO( ADIOS2IOHandlerImpl & impl );
1065  };
1066 
1067 
1068 } // namespace detail
1069 #endif // openPMD_HAVE_ADIOS2
1070 
1071 
1073 {
1074 #if openPMD_HAVE_ADIOS2
1075 
1076 friend class ADIOS2IOHandlerImpl;
1077 
1078 private:
1079  ADIOS2IOHandlerImpl m_impl;
1080 
1081 public:
1082  ~ADIOS2IOHandler( ) override
1083  {
1084  // we must not throw in a destructor
1085  try
1086  {
1087  this->flush( );
1088  }
1089  catch( std::exception const & ex )
1090  {
1091  std::cerr << "[~ADIOS2IOHandler] An error occurred: " << ex.what() << std::endl;
1092  }
1093  catch( ... )
1094  {
1095  std::cerr << "[~ADIOS2IOHandler] An error occurred." << std::endl;
1096  }
1097  }
1098 
1099 #else
1100 public:
1101 #endif
1102 
1103 #if openPMD_HAVE_MPI
1104 
1106  std::string path,
1107  Access,
1108  MPI_Comm,
1109  nlohmann::json options,
1110  std::string engineType );
1111 
1112 #endif
1113 
1115  std::string path,
1116  Access,
1117  nlohmann::json options,
1118  std::string engineType );
1119 
1120  std::string backendName() const override { return "ADIOS2"; }
1121 
1122  std::future< void > flush( ) override;
1123 }; // ADIOS2IOHandler
1124 } // namespace openPMD
Definition: ADIOS2IOHandler.hpp:63
Wrapper around a shared pointer to:
Definition: InvalidatableFile.hpp:45
Definition: ADIOS2IOHandler.hpp:429
Definition: ADIOS2IOHandler.hpp:804
Definition: ADIOS2IOHandler.hpp:366
Access
File access mode to use during IO.
Definition: Access.hpp:28
static bool attributeUnchanged(adios2::IO &IO, std::string name, BasicType val)
Is the attribute given by parameters name and val already defined exactly in that way within the give...
Definition: ADIOS2IOHandler.hpp:463
Definition: ADIOS2IOHandler.hpp:418
STL namespace.
std::string m_file
The full path to the file created on disk, including the containing directory and the file extension...
Definition: ADIOS2IOHandler.hpp:828
Definition: ADIOS2IOHandler.hpp:78
Definition: ADIOS2IOHandler.hpp:817
Definition: ADIOS2IOHandler.hpp:796
AdvanceStatus
In step-based mode (i.e.
Definition: Streaming.hpp:20
This struct&#39;s only field indicates whether the template parameter is a valid datatype to use for a da...
Definition: ADIOS2IOHandler.hpp:69
AdvanceMode
In step-based mode (i.e.
Definition: Streaming.hpp:33
std::string const m_IOName
ADIOS requires giving names to instances of adios2::IO.
Definition: ADIOS2IOHandler.hpp:847
Definition: ADIOS2IOHandler.hpp:788
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:42
Definition: Container.cpp:51
Interface for communicating between logical and physically persistent data.
Definition: AbstractIOHandler.hpp:68
Simple Option type based on variantSrc::variant.
Definition: Option.hpp:47
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
Definition: ADIOS2IOHandler.hpp:1072
Definition: ADIOS2IOHandler.hpp:403
std::string backendName() const override
The currently used backend.
Definition: ADIOS2IOHandler.hpp:1120
Definition: ADIOS2IOHandler.hpp:376
Extend nlohmann::json with tracing of which keys have been accessed by operator[]().
Definition: JSON.hpp:48
Definition: Writable.hpp:43
Definition: ADIOS2IOHandler.hpp:387
Definition: ADIOS2IOHandler.hpp:350
nlohmann::json & json()
Access the underlying JSON value.
Definition: JSON.hpp:60
Definition: ADIOS2IOHandler.hpp:67
Definition: ADIOS2IOHandler.hpp:781