@@ -215,6 +215,38 @@ Series &Series::setMeshesPath(std::string const &mp)
215215 return *this ;
216216}
217217
218+ std::vector<std::string> Series::availableDatasets ()
219+ {
220+ if (iterationEncoding () == IterationEncoding::variableBased &&
221+ IOHandler ()->m_backendAccess == Access::READ_RANDOM_ACCESS)
222+ {
223+ Parameter<Operation::ADVANCE> advance;
224+ advance.mode =
225+ Parameter<Operation::ADVANCE>::StepSelection{std::nullopt };
226+ IOHandler ()->enqueue (IOTask (this , std::move (advance)));
227+ }
228+ Parameter<Operation::LIST_DATASETS> listDatasets;
229+ IOHandler ()->enqueue (IOTask (this , listDatasets));
230+ IOHandler ()->flush (internal::defaultFlushParams);
231+ return std::move (*listDatasets.datasets );
232+ }
233+
234+ bool Series::hasRankTableRead ()
235+ {
236+ if (access::writeOnly (IOHandler ()->m_frontendAccess ))
237+ {
238+ return false ;
239+ }
240+ auto &series = get ();
241+ if (series.m_rankTable .m_bufferedRead .has_value ())
242+ {
243+ return true ;
244+ }
245+ auto datasets = availableDatasets ();
246+ return std::find (datasets.begin (), datasets.end (), " rankTable" ) !=
247+ datasets.end ();
248+ }
249+
218250#if openPMD_HAVE_MPI
219251chunk_assignment::RankMeta Series::rankTable (bool collective)
220252#else
@@ -245,21 +277,9 @@ chunk_assignment::RankMeta Series::rankTable([[maybe_unused]] bool collective)
245277 IOHandler()->enqueue(IOTask(this, openFile));
246278#endif
247279 }
248- if (iterationEncoding () == IterationEncoding::variableBased &&
249- IOHandler ()->m_backendAccess == Access::READ_RANDOM_ACCESS)
250- {
251- Parameter<Operation::ADVANCE> advance;
252- advance.mode =
253- Parameter<Operation::ADVANCE>::StepSelection{std::nullopt };
254- IOHandler ()->enqueue (IOTask (this , std::move (advance)));
255- }
256- Parameter<Operation::LIST_DATASETS> listDatasets;
257- IOHandler ()->enqueue (IOTask (this , listDatasets));
258- IOHandler ()->flush (internal::defaultFlushParams);
259- if (std::none_of (
260- listDatasets.datasets ->begin (),
261- listDatasets.datasets ->end (),
262- [](std::string const &str) { return str == " rankTable" ; }))
280+ auto datasets = availableDatasets ();
281+ if (std::find (datasets.begin (), datasets.end (), " rankTable" ) ==
282+ datasets.end ())
263283 {
264284 rankTable.m_bufferedRead = chunk_assignment::RankMeta{};
265285 return {};
@@ -3119,18 +3139,25 @@ namespace internal
31193139 {
31203140 this ->m_sharedStatefulIterator ->close ();
31213141 }
3122- /*
3123- * Scenario: A user calls `Series::flush()` but does not check for
3124- * thrown exceptions. The exception will propagate further up,
3125- * usually thereby popping the stack frame that holds the `Series`
3126- * object. `Series::~Series()` will run. This check avoids that the
3127- * `Series` is needlessly flushed a second time. Otherwise, error
3128- * messages can get very confusing.
3129- */
31303142 Series impl;
31313143 impl.setData ({this , [](auto const *) {}});
3132- if (auto IOHandler = impl.IOHandler ();
3133- IOHandler && IOHandler->m_lastFlushSuccessful )
3144+ if (auto IOHandler = impl.IOHandler (); IOHandler &&
3145+ /*
3146+ * Scenario: A user calls `Series::flush()` but does not check for
3147+ * thrown exceptions. The exception will propagate further up,
3148+ * usually thereby popping the stack frame that holds the `Series`
3149+ * object. `Series::~Series()` will run. This check avoids that the
3150+ * `Series` is needlessly flushed a second time. Otherwise, error
3151+ * messages can get very confusing.
3152+ */
3153+
3154+ IOHandler->m_lastFlushSuccessful &&
3155+ /*
3156+ * If a read-only Series is opened without any backend access, then
3157+ * don't go there now. Just peacefully close.
3158+ */
3159+ !(access::readOnly (IOHandler->m_frontendAccess ) &&
3160+ !(*this )->m_writable .written ))
31343161 {
31353162 impl.flush ();
31363163 /*
0 commit comments