diff --git a/include/openPMD/Iteration.hpp b/include/openPMD/Iteration.hpp index 8fe2c545f9..5dc5448879 100644 --- a/include/openPMD/Iteration.hpp +++ b/include/openPMD/Iteration.hpp @@ -204,12 +204,19 @@ class Iteration : public Attributable /** * @brief Has the iteration been closed? - * A closed iteration may not (yet) be reopened. * * @return Whether the iteration has been closed. */ bool closed() const; + /** + * @brief Has the iteration been parsed yet? + If not, it will contain no structure yet. + * + * @return Whether the iteration has been parsed. + */ + bool parsed() const; + /** * @brief Has the iteration been closed by the writer? * Background: Upon calling Iteration::close(), the openPMD API diff --git a/src/Iteration.cpp b/src/Iteration.cpp index 0022469fae..7a5c91e894 100644 --- a/src/Iteration.cpp +++ b/src/Iteration.cpp @@ -177,6 +177,20 @@ bool Iteration::closed() const throw std::runtime_error("Unreachable!"); } +bool Iteration::parsed() const +{ + switch (get().m_closed) + { + case CloseStatus::ParseAccessDeferred: + return false; + case CloseStatus::Open: + case CloseStatus::ClosedInFrontend: + case CloseStatus::Closed: + return true; + } + throw std::runtime_error("Unreachable!"); +} + bool Iteration::closedByWriter() const { using bool_type = unsigned char; diff --git a/src/helper/list_series.cpp b/src/helper/list_series.cpp index 3e68bac039..7782573b11 100644 --- a/src/helper/list_series.cpp +++ b/src/helper/list_series.cpp @@ -118,7 +118,10 @@ std::ostream &listSeries(Series &series, bool const longer, std::ostream &out) for (auto &[index, i] : series.snapshots()) { - i.open(); + if (!i.parsed()) + { + i.open(); + } if (longer) out << index << " "; @@ -135,6 +138,10 @@ std::ostream &listSeries(Series &series, bool const longer, std::ostream &out) [](std::pair const &p) { return p.first; }); + if (!i.closed()) + { + i.close(); + } } if (longer) diff --git a/test/SerialIOTest.cpp b/test/SerialIOTest.cpp index 73e574e3e7..c5fe76208b 100644 --- a/test/SerialIOTest.cpp +++ b/test/SerialIOTest.cpp @@ -37,6 +37,7 @@ #ifdef __unix__ #include #include +#include #include #include #include @@ -153,6 +154,13 @@ TEST_CASE("char_roundtrip", "[serial]") void write_and_read_many_iterations( std::string const &ext, bool intermittentFlushes) { +#ifdef __unix__ + struct rlimit rlim; + getrlimit(RLIMIT_NOFILE, &rlim); + auto old_soft_limit = rlim.rlim_cur; + rlim.rlim_cur = 512; + setrlimit(RLIMIT_NOFILE, &rlim); +#endif // the idea here is to trigger the maximum allowed number of file handles, // e.g., the upper limit in "ulimit -n" (default: often 1024). Once this // is reached, files should be closed automatically for open iterations @@ -165,6 +173,7 @@ void write_and_read_many_iterations( auxiliary::getEnvNum("OPENPMD_TEST_NFILES_MAX", 1030); std::string filename = "../samples/many_iterations/many_iterations_%T." + ext; + // std::cout << "WRITE " << filename << std::endl; std::vector data(10); std::iota(data.begin(), data.end(), 0.); @@ -187,6 +196,7 @@ void write_and_read_many_iterations( } // ~Series intentionally not yet called + // std::cout << "READ " << filename << std::endl; Series read( filename, Access::READ_ONLY, "{\"defer_iteration_parsing\": true}"); for (auto iteration : read.iterations) @@ -212,6 +222,10 @@ void write_and_read_many_iterations( Series list(filename, Access::READ_ONLY); helper::listSeries(list); +#ifdef __unix__ + rlim.rlim_cur = old_soft_limit; + setrlimit(RLIMIT_NOFILE, &rlim); +#endif } TEST_CASE("write_and_read_many_iterations", "[serial]")