Skip to content

Commit

Permalink
Prepare internal representation to be aware of steps
Browse files Browse the repository at this point in the history
  • Loading branch information
franzpoeschel committed Feb 14, 2024
1 parent 11e47ed commit ab0991d
Show file tree
Hide file tree
Showing 3 changed files with 350 additions and 125 deletions.
200 changes: 183 additions & 17 deletions include/openPMD/snapshots/StatefulIterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "openPMD/Error.hpp"
#include "openPMD/Iteration.hpp"
#include "openPMD/Series.hpp"
#include "openPMD/Streaming.hpp"
#include "openPMD/auxiliary/Variant.hpp"
#include "openPMD/backend/ParsePreference.hpp"
#include "openPMD/snapshots/IteratorTraits.hpp"

Expand All @@ -41,21 +43,173 @@ namespace internal

namespace detail
{
namespace seek_types
// namespace seek_types
// {
// struct InitNonFileBased_t
// {};
// struct Next_t
// {};
// using seek_impl = std::variant<InitNonFileBased_t, Next_t>;
// } // namespace seek_types
// struct Seek : seek_types::seek_impl
// {
// using InitNonFileBased_t = seek_types::InitNonFileBased_t;
// using Next_t = seek_types::Next_t;

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

// constexpr static InitNonFileBased_t InitNonFileBased{};
// constexpr static Next_t Next{};
// };

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.
namespace step_status_types
{
struct InitNonFileBased_t
struct Before_t
{};
struct Next_t
struct During_t
{
size_t idx;
std::optional<Iteration::IterationIndex_t> iteration_idx;
};
// struct Between_t
// {
// size_t prev_idx;
// };

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.
struct After_t
{};
using seek_impl = std::variant<InitNonFileBased_t, Next_t>;
} // namespace seek_types
struct Seek : seek_types::seek_impl
} // namespace step_status_types
struct CurrentStep
: std::variant<
step_status_types::Before_t,
step_status_types::During_t,
// step_status_types::Between_t,
step_status_types::After_t>
{
using InitNonFileBased_t = seek_types::InitNonFileBased_t;
using Next_t = seek_types::Next_t;

constexpr static InitNonFileBased_t InitNonFileBased{};
constexpr static Next_t Next{};
using Before_t = step_status_types::Before_t;
constexpr static Before_t Before{};
using During_t = step_status_types::During_t;
constexpr static During_t During{};
// using Between_t = step_status_types::Between_t;
// constexpr static Between_t Between{};

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.
using After_t = step_status_types::After_t;
constexpr static After_t After{};

using variant_t = std::variant<
step_status_types::Before_t,
step_status_types::During_t,
// step_status_types::Between_t,
step_status_types::After_t>;

using variant_t::operator=;

template <typename V>
auto get_variant() -> std::optional<V *>
{
auto res = std::get_if<V>(this);
if (res)
{
return std::make_optional<V *>(res);
}
else
{
return std::nullopt;
}
}

template <typename V>
auto get_variant() const -> std::optional<V const *>
{
auto res = std::get_if<V>(*this);
if (res)
{
return {res};
}
else
{
return std::nullopt;
}
}

inline auto get_iteration_index() const
-> std::optional<Iteration::IterationIndex_t const *>
{
using res_t = std::optional<Iteration::IterationIndex_t const *>;
return std::visit(
auxiliary::overloaded{
[](auto const &) -> res_t { return std::nullopt; },
[](During_t const &during) -> res_t {
if (during.iteration_idx.has_value())
{
return std::make_optional<
Iteration::IterationIndex_t const *>(
&*during.iteration_idx);
}
else
{
return std::nullopt;
}
}},
*this);
}
inline auto get_iteration_index()
-> std::optional<Iteration::IterationIndex_t *>
{
auto res =
static_cast<CurrentStep const *>(this)->get_iteration_index();
if (res.has_value())
{
return const_cast<Iteration::IterationIndex_t *>(*res);
}
else
{
return std::nullopt;
}
}
inline auto get_step_index() const -> std::optional<size_t>
{
using res_t = std::optional<size_t>;
return std::visit(
auxiliary::overloaded{
[](During_t const &during) -> res_t { return during.idx; },
[](auto const &) -> res_t { return std::nullopt; }},
*this);
}

enum class AtTheEdge
{
Begin,
End
};

template <typename F, typename G>
inline auto map_during_t(F &&map, G &&create_new)
{
std::visit(
auxiliary::overloaded{
[&](During_t &during) { std::forward<F>(map)(during); },
[&](Before_t const &) {
std::optional<variant_t> res =
std::forward<G>(create_new)(AtTheEdge::Begin);
if (res.has_value())
{
this->swap(*res);
}
},
[&](After_t const &) {
std::optional<variant_t> res =
std::forward<G>(create_new)(AtTheEdge::Begin);
if (res.has_value())
{
this->swap(*res);
}
}},
*this);
}

template <typename F>
inline auto map_during_t(F &&map)
{
map_during_t(std::forward<F>(map), [](auto const &) {
return std::nullopt;
});
}
};
} // namespace detail

Expand All @@ -72,6 +226,8 @@ class StatefulIterator

using maybe_series_t = std::optional<Series>;

using CurrentStep = detail::CurrentStep;

struct SharedData
{
SharedData() = default;
Expand All @@ -84,15 +240,24 @@ class StatefulIterator

Series series;
std::vector<iteration_index_t> iterationsInCurrentStep;
// nullopt <-> currently out of step
std::optional<iteration_index_t> currentIteration{};
CurrentStep currentStep = {CurrentStep::Before};
std::optional<internal::ParsePreference> parsePreference;
/*
* Necessary because in the old ADIOS2 schema, old iterations' metadata
* will leak into new steps, making the frontend think that the groups
* are still there and the iterations can be parsed again.
*/
std::set<Iteration::IterationIndex_t> ignoreIterations;

inline std::optional<Iteration::IterationIndex_t *> currentIteration()
{
return currentStep.get_iteration_index();
}
inline std::optional<Iteration::IterationIndex_t const *>
currentIteration() const
{
return currentStep.get_iteration_index();
}
};

/*
Expand All @@ -110,7 +275,6 @@ class StatefulIterator
using value_type =
typename Container<Iteration, Iteration::IterationIndex_t>::value_type;
using typename parent_t ::difference_type;
using Seek = detail::Seek;
//! construct the end() iterator
explicit StatefulIterator();

Expand Down Expand Up @@ -160,17 +324,19 @@ class StatefulIterator
* the /data/snapshot attribute, this helps figuring out which iteration
* is now active. Hence, recursion_depth.
*/
std::optional<StatefulIterator *> nextStep(Seek const &);
std::optional<StatefulIterator *> nextStep(size_t recursion_depth);

std::optional<StatefulIterator *> loopBody();

std::optional<StatefulIterator *> loopBody(Seek const &);
void initIteratorFilebased();

void deactivateDeadIteration(iteration_index_t);

void initSeriesInLinearReadMode();

void close();

auto resetCurrentIterationToBegin() -> bool;
auto resetCurrentIterationToBegin(size_t num_skipped_iterations) -> void;
auto peekCurrentlyOpenIteration() const
-> std::optional<value_type const *>;
auto peekCurrentlyOpenIteration() -> std::optional<value_type *>;
Expand Down
17 changes: 16 additions & 1 deletion src/snapshots/ContainerImpls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,22 @@ auto StatefulSnapshotsContainer::operator[](key_type const &key)
lastIteration_v->second.close(); // continue below
}
}
s.currentIteration = key;
s.currentStep.map_during_t(
[&](auto &during) {
++during.idx;
during.iteration_idx = key;
},
[&](detail::CurrentStep::AtTheEdge whereAmI) {
switch (whereAmI)
{
case detail::CurrentStep::AtTheEdge::Begin:
return detail::CurrentStep::During_t{0, key};
case detail::CurrentStep::AtTheEdge::End:
throw error::WrongAPIUsage(
"Creating a new step on a Series that is closed.");
}
throw std::runtime_error("Unreachable!");
});
if (std::find(
s.iterationsInCurrentStep.begin(),
s.iterationsInCurrentStep.end(),
Expand Down
Loading

0 comments on commit ab0991d

Please sign in to comment.