@@ -732,11 +732,16 @@ void Series::flushFileBased(
732732 switch (openIterationIfDirty (it->first , it->second ))
733733 {
734734 using IO = IterationOpened;
735+ case IO::RemainsClosed:
736+ // we might need to proceed further if the close status is
737+ // ClosedInFrontend
738+ // hence no continue here
739+ // otherwise, we might forget to close files physically
740+ break ;
735741 case IO::HasBeenOpened:
742+ // continue below
736743 it->second .flush (flushParams);
737744 break ;
738- case IO::RemainsClosed:
739- break ;
740745 }
741746
742747 // Phase 2
@@ -769,13 +774,21 @@ void Series::flushFileBased(
769774 case IO::HasBeenOpened: {
770775 /* as there is only one series,
771776 * emulate the file belonging to each iteration as not yet
772- * written
777+ * written, even if the iteration itself is already written
778+ * (to ensure that the Series gets reassociated with the
779+ * current iteration)
773780 */
774781 written () = false ;
775782 series.iterations .written () = false ;
776783
777784 dirty () |= it->second .dirty ();
778785 std::string filename = iterationFilename (it->first );
786+
787+ if (!it->second .written ())
788+ {
789+ series.m_currentlyActiveIterations .emplace (it->first );
790+ }
791+
779792 it->second .flushFileBased (filename, it->first , flushParams);
780793
781794 series.iterations .flush (
@@ -831,11 +844,15 @@ void Series::flushGorVBased(
831844 switch (openIterationIfDirty (it->first , it->second ))
832845 {
833846 using IO = IterationOpened;
847+ case IO::RemainsClosed:
848+ // we might need to proceed further if the close status is
849+ // ClosedInFrontend
850+ // hence no continue here
851+ break ;
834852 case IO::HasBeenOpened:
853+ // continue below
835854 it->second .flush (flushParams);
836855 break ;
837- case IO::RemainsClosed:
838- break ;
839856 }
840857
841858 // Phase 2
@@ -895,6 +912,7 @@ void Series::flushGorVBased(
895912 if (!it->second .written ())
896913 {
897914 it->second .parent () = getWritable (&series.iterations );
915+ series.m_currentlyActiveIterations .emplace (it->first );
898916 }
899917 switch (iterationEncoding ())
900918 {
@@ -1458,9 +1476,15 @@ AdvanceStatus Series::advance(
14581476 * opening an iteration's file by beginning a step on it.
14591477 * So, return now.
14601478 */
1479+ iteration.get ().m_closed = internal::CloseStatus::ClosedInBackend;
14611480 return AdvanceStatus::OK;
14621481 }
14631482
1483+ if (mode == AdvanceMode::ENDSTEP)
1484+ {
1485+ flushStep (/* doFlush = */ false );
1486+ }
1487+
14641488 Parameter<Operation::ADVANCE> param;
14651489 if (itData.m_closed == internal::CloseStatus::ClosedTemporarily &&
14661490 series.m_iterationEncoding == IterationEncoding::fileBased)
@@ -1517,6 +1541,32 @@ AdvanceStatus Series::advance(
15171541 return *param.status ;
15181542}
15191543
1544+ void Series::flushStep (bool doFlush)
1545+ {
1546+ auto &series = get ();
1547+ if (!series.m_currentlyActiveIterations .empty ())
1548+ {
1549+ /*
1550+ * Warning: changing attribute extents over time (probably) unsupported
1551+ * by this so far.
1552+ * Not (yet) needed as there is no way to pack several iterations within
1553+ * one IO step.
1554+ */
1555+ Parameter<Operation::WRITE_ATT> wAttr;
1556+ wAttr.changesOverSteps = true ;
1557+ wAttr.name = " snapshot" ;
1558+ wAttr.resource = std::vector<unsigned long long >{
1559+ series.m_currentlyActiveIterations .begin (),
1560+ series.m_currentlyActiveIterations .end ()};
1561+ wAttr.dtype = Datatype::VEC_ULONGLONG;
1562+ IOHandler ()->enqueue (IOTask (&series.iterations , wAttr));
1563+ if (doFlush)
1564+ {
1565+ IOHandler ()->flush (internal::defaultFlushParams);
1566+ }
1567+ }
1568+ }
1569+
15201570auto Series::openIterationIfDirty (uint64_t index, Iteration iteration)
15211571 -> IterationOpened
15221572{
@@ -1795,6 +1845,7 @@ namespace internal
17951845 {
17961846 Series impl{{this , [](auto const *) {}}};
17971847 impl.flush ();
1848+ impl.flushStep (/* doFlush = */ true );
17981849 }
17991850 if (m_writeIterations.has_value ())
18001851 {
0 commit comments