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