openPMD-api
ReadIterations.hpp
1 /* Copyright 2021 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/Iteration.hpp"
24 #include "openPMD/Series.hpp"
25 #include "openPMD/backend/ParsePreference.hpp"
26 
27 #include <deque>
28 #include <iostream>
29 #include <optional>
30 #include <set>
31 
32 namespace openPMD
33 {
39 {
40  friend class SeriesIterator;
41 
42 public:
43  using iterations_t = decltype(internal::SeriesData::iterations);
44  using index_t = iterations_t::key_type;
45  index_t const iterationIndex;
46 
47 private:
48  template <typename Iteration_t>
49  IndexedIteration(Iteration_t &&it, index_t index)
50  : Iteration(std::forward<Iteration_t>(it)), iterationIndex(index)
51  {}
52 };
53 
55 {
56  using iteration_index_t = IndexedIteration::index_t;
57 
58  using maybe_series_t = std::optional<Series>;
59 
60  struct SharedData
61  {
62  SharedData() = default;
63  SharedData(SharedData const &) = delete;
64  SharedData(SharedData &&) = delete;
65  SharedData &operator=(SharedData const &) = delete;
66  SharedData &operator=(SharedData &&) = delete;
67 
68  maybe_series_t series;
69  std::deque<iteration_index_t> iterationsInCurrentStep;
70  uint64_t currentIteration{};
71  std::optional<internal::ParsePreference> parsePreference;
72  /*
73  * Necessary because in the old ADIOS2 schema, old iterations' metadata
74  * will leak into new steps, making the frontend think that the groups
75  * are still there and the iterations can be parsed again.
76  */
77  std::set<Iteration::IterationIndex_t> ignoreIterations;
78  };
79 
80  std::shared_ptr<SharedData> m_data;
81 
82 public:
84  explicit SeriesIterator();
85 
87  Series, std::optional<internal::ParsePreference> parsePreference);
88 
89  SeriesIterator &operator++();
90 
91  IndexedIteration operator*();
92 
93  bool operator==(SeriesIterator const &other) const;
94 
95  bool operator!=(SeriesIterator const &other) const;
96 
97  static SeriesIterator end();
98 
99 private:
100  inline bool setCurrentIteration()
101  {
102  auto &data = *m_data;
103  if (data.iterationsInCurrentStep.empty())
104  {
105  std::cerr << "[ReadIterations] Encountered a step without "
106  "iterations. Closing the Series."
107  << std::endl;
108  *this = end();
109  return false;
110  }
111  data.currentIteration = *data.iterationsInCurrentStep.begin();
112  return true;
113  }
114 
115  inline std::optional<uint64_t> peekCurrentIteration()
116  {
117  auto &data = *m_data;
118  if (data.iterationsInCurrentStep.empty())
119  {
120  return std::nullopt;
121  }
122  else
123  {
124  return {*data.iterationsInCurrentStep.begin()};
125  }
126  }
127 
128  std::optional<SeriesIterator *> nextIterationInStep();
129 
130  /*
131  * When a step cannot successfully be opened, the method nextStep() calls
132  * itself again recursively.
133  * (Recursion massively simplifies the logic here, and it only happens
134  * in case of error.)
135  * After successfully beginning a step, this methods needs to remember, how
136  * many broken steps have been skipped. In case the Series does not use
137  * the /data/snapshot attribute, this helps figuring out which iteration
138  * is now active. Hence, recursion_depth.
139  */
140  std::optional<SeriesIterator *> nextStep(size_t recursion_depth);
141 
142  std::optional<SeriesIterator *> loopBody();
143 
144  void deactivateDeadIteration(iteration_index_t);
145 
146  void initSeriesInLinearReadMode();
147 };
148 
166 {
167  friend class Series;
168 
169 private:
170  using iterations_t = decltype(internal::SeriesData::iterations);
171  using iterator_t = SeriesIterator;
172 
173  Series m_series;
174  std::optional<SeriesIterator> alreadyOpened;
175  std::optional<internal::ParsePreference> m_parsePreference;
176 
178  Series,
179  Access,
180  std::optional<internal::ParsePreference> parsePreference);
181 
182 public:
183  iterator_t begin();
184 
185  iterator_t end();
186 };
187 } // namespace openPMD
Subclass of Iteration that knows its own index withing the containing Series.
Definition: ReadIterations.hpp:38
Access
File access mode to use during IO.
Definition: Access.hpp:29
Logical compilation of data from one snapshot (e.g.
Definition: Iteration.hpp:126
Reading side of the streaming API.
Definition: ReadIterations.hpp:165
Implementation for the root level of the openPMD hierarchy.
Definition: Series.hpp:186
Public definitions of openPMD-api.
Definition: ReadIterations.hpp:54