@@ -605,6 +605,7 @@ void ADIOS2IOHandlerImpl::writeAttribute(
605605 auto prefix = filePositionToString (pos);
606606
607607 auto &filedata = getFileData (file, IfFileNotOpen::ThrowError);
608+ filedata.requireActiveStep ();
608609 filedata.invalidateAttributesMap ();
609610 m_dirty.emplace (std::move (file));
610611
@@ -703,7 +704,13 @@ void ADIOS2IOHandlerImpl::getBufferView(
703704 Writable *writable, Parameter<Operation::GET_BUFFER_VIEW> ¶meters)
704705{
705706 // @todo check access mode
706- if (m_engineType != " bp4" )
707+ std::string optInEngines[] = {" bp4" , " bp5" , " file" , " filestream" };
708+ if (std::none_of (
709+ begin (optInEngines),
710+ end (optInEngines),
711+ [this ](std::string const &engine) {
712+ return engine == this ->m_engineType ;
713+ }))
707714 {
708715 parameters.out ->backendManagedBuffer = false ;
709716 return ;
@@ -764,6 +771,7 @@ void ADIOS2IOHandlerImpl::readAttribute(
764771 auto file = refreshFileFromParent (writable, /* preferParentFile = */ false );
765772 auto pos = setAndGetFilePosition (writable);
766773 detail::BufferedActions &ba = getFileData (file, IfFileNotOpen::ThrowError);
774+ ba.requireActiveStep ();
767775 switch (attributeLayout ())
768776 {
769777 using AL = AttributeLayout;
@@ -1006,7 +1014,8 @@ void ADIOS2IOHandlerImpl::advance(
10061014{
10071015 auto file = m_files[writable];
10081016 auto &ba = getFileData (file, IfFileNotOpen::ThrowError);
1009- *parameters.status = ba.advance (parameters.mode );
1017+ *parameters.status =
1018+ ba.advance (parameters.mode , /* calledExplicitly = */ true );
10101019}
10111020
10121021void ADIOS2IOHandlerImpl::closePath (
@@ -1470,6 +1479,7 @@ namespace detail
14701479
14711480 auto &filedata = impl->getFileData (
14721481 file, ADIOS2IOHandlerImpl::IfFileNotOpen::ThrowError);
1482+ filedata.requireActiveStep ();
14731483 filedata.invalidateAttributesMap ();
14741484 adios2::IO IO = filedata.m_IO ;
14751485 impl->m_dirty .emplace (std::move (file));
@@ -2161,9 +2171,18 @@ namespace detail
21612171 {
21622172 (void )impl;
21632173 static std::set<std::string> streamingEngines = {
2164- " sst" , " insitumpi" , " inline" , " staging" , " nullcore" , " ssc" };
2174+ " sst" ,
2175+ " insitumpi" ,
2176+ " inline" ,
2177+ " staging" ,
2178+ " nullcore" ,
2179+ " ssc" ,
2180+ " filestream" ,
2181+ " bp5" };
2182+ // diskStreamingEngines is a subset of streamingEngines
2183+ static std::set<std::string> diskStreamingEngines{" bp5" , " filestream" };
21652184 static std::set<std::string> fileEngines = {
2166- " bp5 " , " bp4" , " bp3" , " hdf5" , " file" };
2185+ " bp4" , " bp3" , " hdf5" , " file" };
21672186
21682187 // step/variable-based iteration encoding requires the new schema
21692188 if (m_impl->m_iterationEncoding == IterationEncoding::variableBased)
@@ -2189,7 +2208,14 @@ namespace detail
21892208 {
21902209 isStreaming = true ;
21912210 optimizeAttributesStreaming =
2192- schema () == SupportedSchema::s_0000_00_00;
2211+ // Optimizing attributes in streaming mode is not needed in
2212+ // the variable-based ADIOS2 schema
2213+ schema () == SupportedSchema::s_0000_00_00 &&
2214+ // Also, it should only be done when truly streaming, not
2215+ // when using a disk-based engine that behaves like a
2216+ // streaming engine (otherwise attributes might vanish)
2217+ diskStreamingEngines.find (m_engineType) ==
2218+ diskStreamingEngines.end ();
21932219 streamStatus = StreamStatus::OutsideOfStep;
21942220 }
21952221 else
@@ -2206,7 +2232,6 @@ namespace detail
22062232 * file being read.
22072233 */
22082234 streamStatus = StreamStatus::Undecided;
2209- // @todo no?? should be default in both modes
22102235 delayOpeningTheFirstStep = true ;
22112236 break ;
22122237 case adios2::Mode::Write:
@@ -2511,9 +2536,22 @@ namespace detail
25112536 adios2::Engine &BufferedActions::requireActiveStep ()
25122537 {
25132538 adios2::Engine &eng = getEngine ();
2539+ /*
2540+ * If streamStatus is Parsing, do NOT open the step.
2541+ */
25142542 if (streamStatus == StreamStatus::OutsideOfStep)
25152543 {
2516- m_lastStepStatus = eng.BeginStep ();
2544+ switch (
2545+ advance (AdvanceMode::BEGINSTEP, /* calledExplicitly = */ false ))
2546+ {
2547+ case AdvanceStatus::OVER:
2548+ throw std::runtime_error (
2549+ " [ADIOS2] Operation requires active step but no step is "
2550+ " left." );
2551+ case AdvanceStatus::OK:
2552+ // pass
2553+ break ;
2554+ }
25172555 if (m_mode == adios2::Mode::Read &&
25182556 attributeLayout () == AttributeLayout::ByAdiosVariables)
25192557 {
@@ -2665,7 +2703,8 @@ namespace detail
26652703 /* flushUnconditionally = */ false );
26662704 }
26672705
2668- AdvanceStatus BufferedActions::advance (AdvanceMode mode)
2706+ AdvanceStatus
2707+ BufferedActions::advance (AdvanceMode mode, bool calledExplicitly)
26692708 {
26702709 if (streamStatus == StreamStatus::Undecided)
26712710 {
@@ -2681,8 +2720,20 @@ namespace detail
26812720 return AdvanceStatus::OK;
26822721 }
26832722
2684- m_IO.DefineAttribute <bool_representation>(
2685- ADIOS2Defaults::str_usesstepsAttribute, 1 );
2723+ /*
2724+ * If advance() is called implicitly (by requireActiveStep()), the
2725+ * Series is not necessarily using steps (logically).
2726+ * But in some ADIOS2 engines, at least one step must be opened
2727+ * (physically) to do anything.
2728+ * The usessteps tag should only be set when the Series is *logically*
2729+ * using steps.
2730+ */
2731+ if (calledExplicitly)
2732+ {
2733+ m_IO.DefineAttribute <bool_representation>(
2734+ ADIOS2Defaults::str_usesstepsAttribute, 1 );
2735+ }
2736+
26862737 switch (mode)
26872738 {
26882739 case AdvanceMode::ENDSTEP: {
@@ -2715,28 +2766,22 @@ namespace detail
27152766 return AdvanceStatus::OK;
27162767 }
27172768 case AdvanceMode::BEGINSTEP: {
2718- adios2::StepStatus adiosStatus = m_lastStepStatus ;
2769+ adios2::StepStatus adiosStatus{} ;
27192770
2720- // Step might have been opened implicitly already
2721- // by requireActiveStep()
2722- // In that case, streamStatus is DuringStep and Adios
2723- // return status is stored in m_lastStepStatus
27242771 if (streamStatus != StreamStatus::DuringStep)
27252772 {
2726- flush (
2727- FlushLevel::UserFlush,
2728- [&adiosStatus](BufferedActions &, adios2::Engine &engine) {
2729- adiosStatus = engine.BeginStep ();
2730- },
2731- /* writeAttributes = */ false ,
2732- /* flushUnconditionally = */ true );
2773+ adiosStatus = getEngine ().BeginStep ();
27332774 if (adiosStatus == adios2::StepStatus::OK &&
27342775 m_mode == adios2::Mode::Read &&
27352776 attributeLayout () == AttributeLayout::ByAdiosVariables)
27362777 {
27372778 preloadAttributes.preloadAttributes (m_IO, m_engine.value ());
27382779 }
27392780 }
2781+ else
2782+ {
2783+ adiosStatus = adios2::StepStatus::OK;
2784+ }
27402785 AdvanceStatus res = AdvanceStatus::OK;
27412786 switch (adiosStatus)
27422787 {
0 commit comments