From 18acc793e88ebc510809d1690872be3dfa30a664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20P=C3=B6schel?= Date: Thu, 16 Nov 2023 17:54:26 +0100 Subject: [PATCH] Move BufferedActions struct to own file ADIOS2File.hpp --- include/openPMD/IO/ADIOS/ADIOS2Auxiliary.hpp | 17 + include/openPMD/IO/ADIOS/ADIOS2File.hpp | 437 +++++++++++++++++++ include/openPMD/IO/ADIOS/ADIOS2IOHandler.hpp | 414 +----------------- src/IO/ADIOS/ADIOS2IOHandler.cpp | 27 +- 4 files changed, 474 insertions(+), 421 deletions(-) create mode 100644 include/openPMD/IO/ADIOS/ADIOS2File.hpp diff --git a/include/openPMD/IO/ADIOS/ADIOS2Auxiliary.hpp b/include/openPMD/IO/ADIOS/ADIOS2Auxiliary.hpp index 97a3f5539a..4419863dee 100644 --- a/include/openPMD/IO/ADIOS/ADIOS2Auxiliary.hpp +++ b/include/openPMD/IO/ADIOS/ADIOS2Auxiliary.hpp @@ -46,6 +46,23 @@ enum class GroupOrDataset DATASET }; +namespace adios_defs +{ + enum class FlushTarget : unsigned char + { + Buffer, + Buffer_Override, + Disk, + Disk_Override + }; + + enum class UseGroupTable + { + Yes, + No + }; +} // namespace adios_defs + #if openPMD_HAVE_ADIOS2 namespace detail { diff --git a/include/openPMD/IO/ADIOS/ADIOS2File.hpp b/include/openPMD/IO/ADIOS/ADIOS2File.hpp new file mode 100644 index 0000000000..c58d1f69f5 --- /dev/null +++ b/include/openPMD/IO/ADIOS/ADIOS2File.hpp @@ -0,0 +1,437 @@ +/* Copyright 2023 Franz Poeschel + * + * This file is part of openPMD-api. + * + * openPMD-api is free software: you can redistribute it and/or modify + * it under the terms of of either the GNU General Public License or + * the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * openPMD-api is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser General Public License along with openPMD-api. + * If not, see . + */ +#pragma once + +#include "openPMD/IO/ADIOS/ADIOS2Auxiliary.hpp" +#include "openPMD/IO/AbstractIOHandler.hpp" +#include "openPMD/IO/IOTask.hpp" + +#include + +#include "openPMD/IO/InvalidatableFile.hpp" +#include "openPMD/config.hpp" + +#if openPMD_HAVE_ADIOS2 +#include +#endif +#if openPMD_HAVE_MPI +#include +#endif + +namespace openPMD +{ +class ADIOS2IOHandlerImpl; +} + +namespace openPMD::detail +{ +class BufferedActions; + +/* + * IO-heavy action to be executed upon flushing. + */ +struct BufferedAction +{ + explicit BufferedAction() = default; + virtual ~BufferedAction() = default; + + BufferedAction(BufferedAction const &other) = delete; + BufferedAction(BufferedAction &&other) = default; + + BufferedAction &operator=(BufferedAction const &other) = delete; + BufferedAction &operator=(BufferedAction &&other) = default; + + virtual void run(BufferedActions &) = 0; +}; + +struct BufferedGet : BufferedAction +{ + std::string name; + Parameter param; + + void run(BufferedActions &) override; +}; + +struct BufferedPut : BufferedAction +{ + std::string name; + Parameter param; + + void run(BufferedActions &) override; +}; + +struct BufferedUniquePtrPut +{ + std::string name; + Offset offset; + Extent extent; + UniquePtrWithLambda data; + Datatype dtype = Datatype::UNDEFINED; + + void run(BufferedActions &); +}; + +struct I_UpdateSpan +{ + virtual void *update() = 0; + virtual ~I_UpdateSpan() = default; +}; + +template +struct UpdateSpan : I_UpdateSpan +{ + adios2::detail::Span span; + + UpdateSpan(adios2::detail::Span); + + void *update() override; +}; + +/* + * Manages per-file information about + * (1) the file's IO and Engine objects + * (2) the file's deferred IO-heavy actions + */ +class BufferedActions +{ + friend struct BufferedGet; + friend struct BufferedPut; + friend struct RunUniquePtrPut; + friend struct WriteDataset; + + using UseGroupTable = adios_defs::UseGroupTable; + using FlushTarget = adios_defs::FlushTarget; + +public: + BufferedActions(BufferedActions const &) = delete; + + /** + * The full path to the file created on disk, including the + * containing directory and the file extension, as determined + * by ADIOS2IOHandlerImpl::fileSuffix(). + * (Meaning, in case of the SST engine, no file suffix since the + * SST engine automatically adds its suffix unconditionally) + */ + std::string m_file; + /** + * ADIOS requires giving names to instances of adios2::IO. + * We make them different from the actual file name, because of the + * possible following workflow: + * + * 1. create file foo.bp + * -> would create IO object named foo.bp + * 2. delete that file + * (let's ignore that we don't support deletion yet and call it + * preplanning) + * 3. create file foo.bp a second time + * -> would create another IO object named foo.bp + * -> craash + * + * So, we just give out names based on a counter for IO objects. + * Hence, next to the actual file name, also store the name for the + * IO. + */ + std::string m_IOName; + adios2::ADIOS &m_ADIOS; + adios2::IO m_IO; + /** + * The default queue for deferred actions. + * Drained upon BufferedActions::flush(). + */ + std::vector> m_buffer; + /** + * When receiving a unique_ptr, we know that the buffer is ours and + * ours alone. So, for performance reasons, show the buffer to ADIOS2 as + * late as possible and avoid unnecessary data copies in BP5 triggered + * by PerformDataWrites(). + */ + std::vector m_uniquePtrPuts; + /** + * This contains deferred actions that have already been enqueued into + * ADIOS2, but not yet performed in ADIOS2. + * We must store them somewhere until the next PerformPuts/Gets, EndStep + * or Close in ADIOS2 to avoid use after free conditions. + */ + std::vector> m_alreadyEnqueued; + adios2::Mode m_mode; + /** + * The base pointer of an ADIOS2 span might change after reallocations. + * The frontend will ask the backend for those updated base pointers. + * Spans given out by the ADIOS2 backend to the frontend are hence + * identified by an unsigned integer and stored in this member for later + * retrieval of the updated base pointer. + * This map is cleared upon flush points. + */ + std::map> m_updateSpans; + + /* + * We call an attribute committed if the step during which it was + * written has been closed. + * A committed attribute cannot be modified. + */ + std::set uncommittedAttributes; + + /* + * The openPMD API will generally create new attributes for each + * iteration. This results in a growing number of attributes over time. + * In streaming-based modes, these will be completely sent anew in each + * iteration. If the following boolean is true, old attributes will be + * removed upon CLOSE_GROUP. + * Should not be set to true in persistent backends. + * Will be automatically set by BufferedActions::configure_IO depending + * on chosen ADIOS2 engine and can not be explicitly overridden by user. + */ + bool optimizeAttributesStreaming = false; + + using ParsePreference = Parameter::ParsePreference; + ParsePreference parsePreference = ParsePreference::UpFront; + + using AttributeMap_t = std::map; + + BufferedActions(ADIOS2IOHandlerImpl &impl, InvalidatableFile file); + + ~BufferedActions(); + + /** + * Implementation of destructor, will only run once. + * + */ + void finalize(); + + UseGroupTable detectGroupTable(); + + adios2::Engine &getEngine(); + + template + void enqueue(BA &&ba); + + template + void enqueue(BA &&ba, decltype(m_buffer) &); + + template + void flush(Args &&...args); + + struct ADIOS2FlushParams + { + /* + * Only execute performPutsGets if UserFlush. + */ + FlushLevel level; + FlushTarget flushTarget = FlushTarget::Disk; + + ADIOS2FlushParams(FlushLevel level_in) : level(level_in) + {} + + ADIOS2FlushParams(FlushLevel level_in, FlushTarget flushTarget_in) + : level(level_in), flushTarget(flushTarget_in) + {} + }; + + /** + * Flush deferred IO actions. + * + * @param flushParams Flush level and target. + * @param performPutsGets A functor that takes as parameters (1) *this + * and (2) the ADIOS2 engine. + * Its task is to ensure that ADIOS2 performs Put/Get operations. + * Several options for this: + * * adios2::Engine::EndStep + * * adios2::Engine::Perform(Puts|Gets) + * * adios2::Engine::Close + * @param writeLatePuts Deferred until right before + * Engine::EndStep() or Engine::Close(): + * Running unique_ptr Put()s. + * @param flushUnconditionally Whether to run the functor even if no + * deferred IO tasks had been queued. + */ + template + void flush_impl( + ADIOS2FlushParams flushParams, + F &&performPutsGets, + bool writeLatePuts, + bool flushUnconditionally); + + /** + * Overload of flush() that uses adios2::Engine::Perform(Puts|Gets) + * and does not flush unconditionally. + * + */ + void flush_impl(ADIOS2FlushParams, bool writeLatePuts = false); + + /** + * @brief Begin or end an ADIOS step. + * + * @param mode Whether to begin or end a step. + * @param calledExplicitly True if called due to a public API call. + * False if called from requireActiveStep. + * Some engines (BP5) require that every interaction happens within + * an active step, meaning that we need to call advance() + * implicitly at times. When doing that, do not tag the dataset + * with __openPMD_internal/useSteps (yet). + * @return AdvanceStatus + */ + AdvanceStatus advance(AdvanceMode mode, bool calledExplicitly); + + /* + * Delete all buffered actions without running them. + */ + void drop(); + + AttributeMap_t const &availableAttributes(); + + std::vector + availableAttributesPrefixed(std::string const &prefix); + + /* + * See description below. + */ + void invalidateAttributesMap(); + + AttributeMap_t const &availableVariables(); + + std::vector + availableVariablesPrefixed(std::string const &prefix); + + /* + * See description below. + */ + void invalidateVariablesMap(); + + void markActive(Writable *); + + // bool isActive(std::string const & path); + + /* + * streamStatus is NoStream for file-based ADIOS engines. + * This is relevant for the method BufferedActions::requireActiveStep, + * where a step is only opened if the status is OutsideOfStep, but not + * if NoStream. The rationale behind this is that parsing a Series + * works differently for file-based and for stream-based engines: + * * stream-based: Iterations are parsed as they arrive. For parsing an + * iteration, the iteration must be awaited. + * BufferedActions::requireActiveStep takes care of this. + * * file-based: The Series is parsed up front. If no step has been + * opened yet, ADIOS2 gives access to all variables and attributes + * from all steps. Upon opening a step, only the variables from that + * step are shown which hinders parsing. So, until a step is + * explicitly opened via ADIOS2IOHandlerImpl::advance, do not open + * one. + * This is to enable use of ADIOS files without the Streaming API + * (i.e. all iterations should be visible to the user upon opening + * the Series.) + * @todo Add a workflow without up-front parsing of all iterations + * for file-based engines. + * (This would merely be an optimization since the streaming + * API still works with files as intended.) + * + */ + enum class StreamStatus + { + /** + * A step is currently active. + */ + DuringStep, + /** + * A stream is active, but no step. + */ + OutsideOfStep, + /** + * Stream has ended. + */ + StreamOver, + /** + * File is not written is streaming fashion. + * Begin/EndStep will be replaced by simple flushes. + * Used for: + * 1) Writing BP4 files without steps despite using the Streaming + * API. This is due to the fact that ADIOS2.6.0 requires using + * steps to read BP4 files written with steps, so using steps + * is opt-in for now. + * Notice that while the openPMD API requires ADIOS >= 2.7.0, + * the resulting files need to be readable from ADIOS 2.6.0 as + * well. This workaround is hence staying until switching to + * a new ADIOS schema. + * 2) Reading with the Streaming API any file that has been written + * without steps. This is not a workaround since not using steps, + * while inefficient in ADIOS2, is something that we support. + */ + ReadWithoutStream, + /** + * The stream status of a file-based engine will be decided upon + * opening the engine if in read mode. Up until then, this right + * here is the status. + */ + Undecided + }; + StreamStatus streamStatus = StreamStatus::OutsideOfStep; + + size_t currentStep(); + +private: + ADIOS2IOHandlerImpl *m_impl; + std::optional m_engine; //! ADIOS engine + /** + * The ADIOS2 engine type, to be passed to adios2::IO::SetEngine + */ + std::string m_engineType; + + /* + * Not all engines support the CurrentStep() call, so we have to + * implement this manually. + */ + size_t m_currentStep = 0; + + /* + * ADIOS2 does not give direct access to its internal attribute and + * variable maps, but will instead give access to copies of them. + * In order to avoid unnecessary copies, we buffer the returned map. + * The downside of this is that we need to pay attention to invalidate + * the map whenever an attribute/variable is altered. In that case, we + * fetch the map anew. + * If empty, the buffered map has been invalidated and needs to be + * queried from ADIOS2 again. If full, the buffered map is equivalent to + * the map that would be returned by a call to + * IO::Available(Attributes|Variables). + */ + std::optional m_availableAttributes; + std::optional m_availableVariables; + + std::set m_pathsMarkedAsActive; + + /* + * Cannot write attributes right after opening the engine + * https://github.com/ornladios/ADIOS2/issues/3433 + */ + bool initializedDefaults = false; + /* + * finalize() will set this true to avoid running twice. + */ + bool finalized = false; + + UseGroupTable useGroupTable() const; + + void create_IO(); + + void configure_IO(); + void configure_IO_Read(); + void configure_IO_Write(); +}; +} // namespace openPMD::detail diff --git a/include/openPMD/IO/ADIOS/ADIOS2IOHandler.hpp b/include/openPMD/IO/ADIOS/ADIOS2IOHandler.hpp index 42c3830447..048daf5acf 100644 --- a/include/openPMD/IO/ADIOS/ADIOS2IOHandler.hpp +++ b/include/openPMD/IO/ADIOS/ADIOS2IOHandler.hpp @@ -84,12 +84,6 @@ namespace detail struct RunUniquePtrPut; } // namespace detail -enum class UseGroupTable -{ - Yes, - No -}; - class ADIOS2IOHandlerImpl : public AbstractIOHandlerImplCommon { @@ -112,6 +106,9 @@ class ADIOS2IOHandlerImpl friend struct detail::BufferedAttributeRead; friend struct detail::RunUniquePtrPut; + using UseGroupTable = adios_defs::UseGroupTable; + using FlushTarget = adios_defs::FlushTarget; + public: #if openPMD_HAVE_MPI @@ -210,14 +207,6 @@ class ADIOS2IOHandlerImpl */ adios2::Mode adios2AccessMode(std::string const &fullPath); - enum class FlushTarget : unsigned char - { - Buffer, - Buffer_Override, - Disk, - Disk_Override - }; - FlushTarget m_flushTarget = FlushTarget::Disk; private: @@ -741,403 +730,6 @@ namespace detail return data[0] == toRep(val); } }; - - // Other datatypes used in the ADIOS2IOHandler implementation - - struct BufferedActions; - - /* - * IO-heavy action to be executed upon flushing. - */ - struct BufferedAction - { - explicit BufferedAction() = default; - virtual ~BufferedAction() = default; - - BufferedAction(BufferedAction const &other) = delete; - BufferedAction(BufferedAction &&other) = default; - - BufferedAction &operator=(BufferedAction const &other) = delete; - BufferedAction &operator=(BufferedAction &&other) = default; - - virtual void run(BufferedActions &) = 0; - }; - - struct BufferedGet : BufferedAction - { - std::string name; - Parameter param; - - void run(BufferedActions &) override; - }; - - struct BufferedPut : BufferedAction - { - std::string name; - Parameter param; - - void run(BufferedActions &) override; - }; - - struct BufferedUniquePtrPut - { - std::string name; - Offset offset; - Extent extent; - UniquePtrWithLambda data; - Datatype dtype = Datatype::UNDEFINED; - - void run(BufferedActions &); - }; - - struct I_UpdateSpan - { - virtual void *update() = 0; - virtual ~I_UpdateSpan() = default; - }; - - template - struct UpdateSpan : I_UpdateSpan - { - adios2::detail::Span span; - - UpdateSpan(adios2::detail::Span); - - void *update() override; - }; - - /* - * Manages per-file information about - * (1) the file's IO and Engine objects - * (2) the file's deferred IO-heavy actions - */ - struct BufferedActions - { - friend struct BufferedGet; - friend struct BufferedPut; - friend struct RunUniquePtrPut; - friend struct WriteDataset; - - using FlushTarget = ADIOS2IOHandlerImpl::FlushTarget; - - BufferedActions(BufferedActions const &) = delete; - - /** - * The full path to the file created on disk, including the - * containing directory and the file extension, as determined - * by ADIOS2IOHandlerImpl::fileSuffix(). - * (Meaning, in case of the SST engine, no file suffix since the - * SST engine automatically adds its suffix unconditionally) - */ - std::string m_file; - /** - * ADIOS requires giving names to instances of adios2::IO. - * We make them different from the actual file name, because of the - * possible following workflow: - * - * 1. create file foo.bp - * -> would create IO object named foo.bp - * 2. delete that file - * (let's ignore that we don't support deletion yet and call it - * preplanning) - * 3. create file foo.bp a second time - * -> would create another IO object named foo.bp - * -> craash - * - * So, we just give out names based on a counter for IO objects. - * Hence, next to the actual file name, also store the name for the - * IO. - */ - std::string m_IOName; - adios2::ADIOS &m_ADIOS; - adios2::IO m_IO; - /** - * The default queue for deferred actions. - * Drained upon BufferedActions::flush(). - */ - std::vector> m_buffer; - /** - * When receiving a unique_ptr, we know that the buffer is ours and - * ours alone. So, for performance reasons, show the buffer to ADIOS2 as - * late as possible and avoid unnecessary data copies in BP5 triggered - * by PerformDataWrites(). - */ - std::vector m_uniquePtrPuts; - /** - * This contains deferred actions that have already been enqueued into - * ADIOS2, but not yet performed in ADIOS2. - * We must store them somewhere until the next PerformPuts/Gets, EndStep - * or Close in ADIOS2 to avoid use after free conditions. - */ - std::vector> m_alreadyEnqueued; - adios2::Mode m_mode; - /** - * The base pointer of an ADIOS2 span might change after reallocations. - * The frontend will ask the backend for those updated base pointers. - * Spans given out by the ADIOS2 backend to the frontend are hence - * identified by an unsigned integer and stored in this member for later - * retrieval of the updated base pointer. - * This map is cleared upon flush points. - */ - std::map> m_updateSpans; - - /* - * We call an attribute committed if the step during which it was - * written has been closed. - * A committed attribute cannot be modified. - */ - std::set uncommittedAttributes; - - /* - * The openPMD API will generally create new attributes for each - * iteration. This results in a growing number of attributes over time. - * In streaming-based modes, these will be completely sent anew in each - * iteration. If the following boolean is true, old attributes will be - * removed upon CLOSE_GROUP. - * Should not be set to true in persistent backends. - * Will be automatically set by BufferedActions::configure_IO depending - * on chosen ADIOS2 engine and can not be explicitly overridden by user. - */ - bool optimizeAttributesStreaming = false; - - using ParsePreference = - Parameter::ParsePreference; - ParsePreference parsePreference = ParsePreference::UpFront; - - using AttributeMap_t = std::map; - - BufferedActions(ADIOS2IOHandlerImpl &impl, InvalidatableFile file); - - ~BufferedActions(); - - /** - * Implementation of destructor, will only run once. - * - */ - void finalize(); - - UseGroupTable detectGroupTable(); - - adios2::Engine &getEngine(); - - template - void enqueue(BA &&ba); - - template - void enqueue(BA &&ba, decltype(m_buffer) &); - - template - void flush(Args &&...args); - - struct ADIOS2FlushParams - { - /* - * Only execute performPutsGets if UserFlush. - */ - FlushLevel level; - FlushTarget flushTarget = FlushTarget::Disk; - - ADIOS2FlushParams(FlushLevel level_in) : level(level_in) - {} - - ADIOS2FlushParams(FlushLevel level_in, FlushTarget flushTarget_in) - : level(level_in), flushTarget(flushTarget_in) - {} - }; - - /** - * Flush deferred IO actions. - * - * @param flushParams Flush level and target. - * @param performPutsGets A functor that takes as parameters (1) *this - * and (2) the ADIOS2 engine. - * Its task is to ensure that ADIOS2 performs Put/Get operations. - * Several options for this: - * * adios2::Engine::EndStep - * * adios2::Engine::Perform(Puts|Gets) - * * adios2::Engine::Close - * @param writeLatePuts Deferred until right before - * Engine::EndStep() or Engine::Close(): - * Running unique_ptr Put()s. - * @param flushUnconditionally Whether to run the functor even if no - * deferred IO tasks had been queued. - */ - template - void flush_impl( - ADIOS2FlushParams flushParams, - F &&performPutsGets, - bool writeLatePuts, - bool flushUnconditionally); - - /** - * Overload of flush() that uses adios2::Engine::Perform(Puts|Gets) - * and does not flush unconditionally. - * - */ - void flush_impl(ADIOS2FlushParams, bool writeLatePuts = false); - - /** - * @brief Begin or end an ADIOS step. - * - * @param mode Whether to begin or end a step. - * @param calledExplicitly True if called due to a public API call. - * False if called from requireActiveStep. - * Some engines (BP5) require that every interaction happens within - * an active step, meaning that we need to call advance() - * implicitly at times. When doing that, do not tag the dataset - * with __openPMD_internal/useSteps (yet). - * @return AdvanceStatus - */ - AdvanceStatus advance(AdvanceMode mode, bool calledExplicitly); - - /* - * Delete all buffered actions without running them. - */ - void drop(); - - AttributeMap_t const &availableAttributes(); - - std::vector - availableAttributesPrefixed(std::string const &prefix); - - /* - * See description below. - */ - void invalidateAttributesMap(); - - AttributeMap_t const &availableVariables(); - - std::vector - availableVariablesPrefixed(std::string const &prefix); - - /* - * See description below. - */ - void invalidateVariablesMap(); - - void markActive(Writable *); - - // bool isActive(std::string const & path); - - /* - * streamStatus is NoStream for file-based ADIOS engines. - * This is relevant for the method BufferedActions::requireActiveStep, - * where a step is only opened if the status is OutsideOfStep, but not - * if NoStream. The rationale behind this is that parsing a Series - * works differently for file-based and for stream-based engines: - * * stream-based: Iterations are parsed as they arrive. For parsing an - * iteration, the iteration must be awaited. - * BufferedActions::requireActiveStep takes care of this. - * * file-based: The Series is parsed up front. If no step has been - * opened yet, ADIOS2 gives access to all variables and attributes - * from all steps. Upon opening a step, only the variables from that - * step are shown which hinders parsing. So, until a step is - * explicitly opened via ADIOS2IOHandlerImpl::advance, do not open - * one. - * This is to enable use of ADIOS files without the Streaming API - * (i.e. all iterations should be visible to the user upon opening - * the Series.) - * @todo Add a workflow without up-front parsing of all iterations - * for file-based engines. - * (This would merely be an optimization since the streaming - * API still works with files as intended.) - * - */ - enum class StreamStatus - { - /** - * A step is currently active. - */ - DuringStep, - /** - * A stream is active, but no step. - */ - OutsideOfStep, - /** - * Stream has ended. - */ - StreamOver, - /** - * File is not written is streaming fashion. - * Begin/EndStep will be replaced by simple flushes. - * Used for: - * 1) Writing BP4 files without steps despite using the Streaming - * API. This is due to the fact that ADIOS2.6.0 requires using - * steps to read BP4 files written with steps, so using steps - * is opt-in for now. - * Notice that while the openPMD API requires ADIOS >= 2.7.0, - * the resulting files need to be readable from ADIOS 2.6.0 as - * well. This workaround is hence staying until switching to - * a new ADIOS schema. - * 2) Reading with the Streaming API any file that has been written - * without steps. This is not a workaround since not using steps, - * while inefficient in ADIOS2, is something that we support. - */ - ReadWithoutStream, - /** - * The stream status of a file-based engine will be decided upon - * opening the engine if in read mode. Up until then, this right - * here is the status. - */ - Undecided - }; - StreamStatus streamStatus = StreamStatus::OutsideOfStep; - - size_t currentStep(); - - private: - ADIOS2IOHandlerImpl *m_impl; - std::optional m_engine; //! ADIOS engine - /** - * The ADIOS2 engine type, to be passed to adios2::IO::SetEngine - */ - std::string m_engineType; - - /* - * Not all engines support the CurrentStep() call, so we have to - * implement this manually. - */ - size_t m_currentStep = 0; - - /* - * ADIOS2 does not give direct access to its internal attribute and - * variable maps, but will instead give access to copies of them. - * In order to avoid unnecessary copies, we buffer the returned map. - * The downside of this is that we need to pay attention to invalidate - * the map whenever an attribute/variable is altered. In that case, we - * fetch the map anew. - * If empty, the buffered map has been invalidated and needs to be - * queried from ADIOS2 again. If full, the buffered map is equivalent to - * the map that would be returned by a call to - * IO::Available(Attributes|Variables). - */ - std::optional m_availableAttributes; - std::optional m_availableVariables; - - std::set m_pathsMarkedAsActive; - - /* - * Cannot write attributes right after opening the engine - * https://github.com/ornladios/ADIOS2/issues/3433 - */ - bool initializedDefaults = false; - /* - * finalize() will set this true to avoid running twice. - */ - bool finalized = false; - - [[nodiscard]] inline UseGroupTable useGroupTable() const - { - return m_impl->useGroupTable(); - } - - void create_IO(); - - void configure_IO(ADIOS2IOHandlerImpl &impl); - void configure_IO_Read(); - void configure_IO_Write(); - }; - } // namespace detail #endif // openPMD_HAVE_ADIOS2 diff --git a/src/IO/ADIOS/ADIOS2IOHandler.cpp b/src/IO/ADIOS/ADIOS2IOHandler.cpp index ea562cfd85..cb0fdf50df 100644 --- a/src/IO/ADIOS/ADIOS2IOHandler.cpp +++ b/src/IO/ADIOS/ADIOS2IOHandler.cpp @@ -20,6 +20,7 @@ */ #include "openPMD/IO/ADIOS/ADIOS2IOHandler.hpp" +#include "openPMD/IO/ADIOS/ADIOS2File.hpp" #include "openPMD/Datatype.hpp" #include "openPMD/Error.hpp" @@ -421,7 +422,7 @@ std::string ADIOS2IOHandlerImpl::fileSuffix(bool verbose) const } } -using FlushTarget = ADIOS2IOHandlerImpl::FlushTarget; +using FlushTarget = adios_defs::FlushTarget; static FlushTarget flushTargetFromString(std::string const &str) { if (str == "buffer") @@ -2213,10 +2214,15 @@ namespace detail } else { - configure_IO(impl); + configure_IO(); } } + auto BufferedActions::useGroupTable() const -> UseGroupTable + { + return m_impl->useGroupTable(); + } + void BufferedActions::create_IO() { m_IOName = std::to_string(m_impl->nameCounter++); @@ -2447,7 +2453,7 @@ namespace detail streamStatus = StreamStatus::OutsideOfStep; } - void BufferedActions::configure_IO(ADIOS2IOHandlerImpl &impl) + void BufferedActions::configure_IO() { // step/variable-based iteration encoding requires use of group tables // but the group table feature is available only in ADIOS2 >= v2.9 @@ -2538,10 +2544,11 @@ namespace detail // set engine parameters std::set alreadyConfigured; bool wasTheFlushTargetSpecifiedViaJSON = false; - auto engineConfig = impl.config(ADIOS2Defaults::str_engine); + auto engineConfig = m_impl->config(ADIOS2Defaults::str_engine); if (!engineConfig.json().is_null()) { - auto params = impl.config(ADIOS2Defaults::str_params, engineConfig); + auto params = + m_impl->config(ADIOS2Defaults::str_params, engineConfig); params.declareFullyRead(); if (params.json().is_object()) { @@ -2565,7 +2572,7 @@ namespace detail } } auto _useAdiosSteps = - impl.config(ADIOS2Defaults::str_usesteps, engineConfig); + m_impl->config(ADIOS2Defaults::str_usesteps, engineConfig); if (!_useAdiosSteps.json().is_null() && writeOnly(m_mode)) { std::cerr << "[ADIOS2 backend] WARNING: Parameter " @@ -2590,10 +2597,10 @@ namespace detail } } - auto shadow = impl.m_config.invertShadow(); + auto shadow = m_impl->m_config.invertShadow(); if (shadow.size() > 0) { - switch (impl.m_config.originallySpecifiedAs) + switch (m_impl->m_config.originallySpecifiedAs) { case json::SupportedLanguages::JSON: std::cerr << "Warning: parts of the backend configuration for " @@ -2756,7 +2763,7 @@ namespace detail getEngine(); } - UseGroupTable BufferedActions::detectGroupTable() + auto BufferedActions::detectGroupTable() -> UseGroupTable { auto const &attributes = availableAttributes(); auto lower_bound = @@ -2849,7 +2856,7 @@ namespace detail m_impl->m_useGroupTable = UseGroupTable::No; } } - case openPMD::UseGroupTable::No: + case UseGroupTable::No: break; } }