@@ -6069,9 +6069,46 @@ TEST_CASE("varying_zero_pattern", "[serial]")
60696069 }
60706070}
60716071
6072+ enum class ParseMode
6073+ {
6074+ /*
6075+ * Conventional workflow. Just parse the whole thing and yield iterations
6076+ * in rising order.
6077+ */
6078+ NoSteps,
6079+ /*
6080+ * The Series is parsed ahead of time upon opening, but it has steps.
6081+ * Parsing ahead of time is the conventional workflow to support
6082+ * random-access.
6083+ * Reading such a Series with the streaming API is only possible if all
6084+ * steps are in ascending order, otherwise the openPMD-api has no way of
6085+ * associating IO steps with interation indices.
6086+ * Reading such a Series with the Streaming API will become possible with
6087+ * the Linear read mode to be introduced by #1291.
6088+ */
6089+ AheadOfTimeWithoutSnapshot,
6090+ /*
6091+ * A Series of the BP5 engine is not parsed ahead of time, but step-by-step,
6092+ * giving the openPMD-api a way to associate IO steps with iterations.
6093+ * No snapshot attribute exists, so the fallback mode is chosen:
6094+ * Iterations are returned in ascending order.
6095+ * If an IO step returns an iteration whose index is lower than the
6096+ * last one, it will be skipped.
6097+ * This mode of parsing will be generalized into the Linear read mode with
6098+ * PR #1291.
6099+ */
6100+ LinearWithoutSnapshot,
6101+ /*
6102+ * Snapshot attribute exists and dictates the iteration index returned by
6103+ * an IO step. Duplicate iterations will be skipped.
6104+ */
6105+ WithSnapshot
6106+ };
6107+
60726108void append_mode (
60736109 std::string const &extension,
60746110 bool variableBased,
6111+ ParseMode parseMode,
60756112 std::string jsonConfig = " {}" )
60766113{
60776114
@@ -6179,26 +6216,60 @@ void append_mode(
61796216 }
61806217 {
61816218 Series read (filename, Access::READ_ONLY);
6182- if (variableBased || extension == " bp5 " )
6219+ switch (parseMode )
61836220 {
6221+ case ParseMode::NoSteps: {
6222+ unsigned counter = 0 ;
6223+ uint64_t iterationOrder[] = {0 , 1 , 2 , 3 , 4 , 7 , 10 , 11 };
6224+ for (auto const &iteration : read.readIterations ())
6225+ {
6226+ REQUIRE (iteration.iterationIndex == iterationOrder[counter]);
6227+ ++counter;
6228+ }
6229+ REQUIRE (counter == 8 );
6230+ }
6231+ break ;
6232+ case ParseMode::LinearWithoutSnapshot: {
6233+ unsigned counter = 0 ;
6234+ uint64_t iterationOrder[] = {0 , 1 , 2 , 3 , 4 , 10 , 11 };
6235+ for (auto const &iteration : read.readIterations ())
6236+ {
6237+ REQUIRE (iteration.iterationIndex == iterationOrder[counter]);
6238+ ++counter;
6239+ }
6240+ REQUIRE (counter == 7 );
6241+ }
6242+ break ;
6243+ case ParseMode::WithSnapshot: {
61846244 // in variable-based encodings, iterations are not parsed ahead of
61856245 // time but as they go
61866246 unsigned counter = 0 ;
61876247 uint64_t iterationOrder[] = {0 , 1 , 2 , 3 , 4 , 10 , 7 , 11 };
61886248 for (auto const &iteration : read.readIterations ())
61896249 {
6190- std::cout << " Seeing iteration " << iteration.iterationIndex
6191- << " of series " << filename << std::endl;
61926250 REQUIRE (iteration.iterationIndex == iterationOrder[counter]);
61936251 ++counter;
61946252 }
61956253 REQUIRE (counter == 8 );
61966254 // Cannot do listSeries here because the Series is already drained
61976255 REQUIRE_THROWS_AS (helper::listSeries (read), error::WrongAPIUsage);
61986256 }
6199- else
6200- {
6257+ break ;
6258+ case ParseMode::AheadOfTimeWithoutSnapshot: {
62016259 REQUIRE (read.iterations .size () == 8 );
6260+ unsigned counter = 0 ;
6261+ uint64_t iterationOrder[] = {0 , 1 , 2 , 3 , 4 , 7 , 10 , 11 };
6262+ /*
6263+ * Use conventional read API since streaming API is not possible
6264+ * without Linear read mode.
6265+ * (See also comments inside ParseMode enum).
6266+ */
6267+ for (auto const &iteration : read.iterations )
6268+ {
6269+ REQUIRE (iteration.first == iterationOrder[counter]);
6270+ ++counter;
6271+ }
6272+ REQUIRE (counter == 8 );
62026273 /*
62036274 * Roadmap: for now, reading this should work by ignoring the last
62046275 * duplicate iteration.
@@ -6208,6 +6279,8 @@ void append_mode(
62086279 */
62096280 helper::listSeries (read);
62106281 }
6282+ break ;
6283+ }
62116284 }
62126285#if 100000000 * ADIOS2_VERSION_MAJOR + 1000000 * ADIOS2_VERSION_MINOR + \
62136286 10000 * ADIOS2_VERSION_PATCH + 100 * ADIOS2_VERSION_TWEAK >= \
@@ -6244,16 +6317,47 @@ void append_mode(
62446317 }
62456318 {
62466319 Series read (filename, Access::READ_ONLY);
6247- // in variable-based encodings, iterations are not parsed ahead of
6248- // time but as they go
6249- unsigned counter = 0 ;
6250- for (auto const &iteration : read.readIterations ())
6320+ switch (parseMode)
62516321 {
6252- REQUIRE (iteration.iterationIndex == counter);
6253- ++counter;
6322+ case ParseMode::LinearWithoutSnapshot: {
6323+ uint64_t iterationOrder[] = {0 , 1 , 2 , 3 , 4 , 10 };
6324+ unsigned counter = 0 ;
6325+ for (auto const &iteration : read.readIterations ())
6326+ {
6327+ REQUIRE (
6328+ iteration.iterationIndex == iterationOrder[counter]);
6329+ ++counter;
6330+ }
6331+ REQUIRE (counter == 6 );
6332+ // Cannot do listSeries here because the Series is already
6333+ // drained
6334+ REQUIRE_THROWS_AS (
6335+ helper::listSeries (read), error::WrongAPIUsage);
6336+ }
6337+ break ;
6338+ case ParseMode::WithSnapshot: {
6339+ // in variable-based encodings, iterations are not parsed ahead
6340+ // of time but as they go
6341+ unsigned counter = 0 ;
6342+ uint64_t iterationOrder[] = {0 , 1 , 2 , 3 , 4 , 10 , 7 , 5 };
6343+ for (auto const &iteration : read.readIterations ())
6344+ {
6345+ REQUIRE (
6346+ iteration.iterationIndex == iterationOrder[counter]);
6347+ ++counter;
6348+ }
6349+ REQUIRE (counter == 8 );
6350+ // Cannot do listSeries here because the Series is already
6351+ // drained
6352+ REQUIRE_THROWS_AS (
6353+ helper::listSeries (read), error::WrongAPIUsage);
6354+ }
6355+ break ;
6356+ case ParseMode::NoSteps:
6357+ case ParseMode::AheadOfTimeWithoutSnapshot:
6358+ throw std::runtime_error (" Test configured wrong." );
6359+ break ;
62546360 }
6255- REQUIRE (counter == 6 );
6256- helper::listSeries (read);
62576361 }
62586362 }
62596363#endif
@@ -6263,9 +6367,7 @@ TEST_CASE("append_mode", "[serial]")
62636367{
62646368 for (auto const &t : testedFileExtensions ())
62656369 {
6266- if (t == " bp" || t == " bp4" || t == " bp5" )
6267- {
6268- std::string jsonConfigOld = R"END(
6370+ std::string jsonConfigOld = R"END(
62696371{
62706372 "adios2":
62716373 {
@@ -6276,7 +6378,7 @@ TEST_CASE("append_mode", "[serial]")
62766378 }
62776379 }
62786380})END" ;
6279- std::string jsonConfigNew = R"END(
6381+ std::string jsonConfigNew = R"END(
62806382{
62816383 "adios2":
62826384 {
@@ -6287,14 +6389,25 @@ TEST_CASE("append_mode", "[serial]")
62876389 }
62886390 }
62896391})END" ;
6290- append_mode (t, false , jsonConfigOld);
6291- append_mode (t, false , jsonConfigNew);
6292- append_mode (t, true , jsonConfigOld);
6293- append_mode (t, true , jsonConfigNew);
6392+ if (t == " bp5" )
6393+ {
6394+ append_mode (
6395+ t, false , ParseMode::LinearWithoutSnapshot, jsonConfigOld);
6396+ append_mode (t, false , ParseMode::WithSnapshot, jsonConfigNew);
6397+ append_mode (t, true , ParseMode::WithSnapshot, jsonConfigOld);
6398+ append_mode (t, true , ParseMode::WithSnapshot, jsonConfigNew);
6399+ }
6400+ else if (t == " bp" || t == " bp4" || t == " bp5" )
6401+ {
6402+ append_mode (
6403+ t, false , ParseMode::AheadOfTimeWithoutSnapshot, jsonConfigOld);
6404+ append_mode (t, false , ParseMode::WithSnapshot, jsonConfigNew);
6405+ append_mode (t, true , ParseMode::WithSnapshot, jsonConfigOld);
6406+ append_mode (t, true , ParseMode::WithSnapshot, jsonConfigNew);
62946407 }
62956408 else
62966409 {
6297- append_mode (t, false );
6410+ append_mode (t, false , ParseMode::NoSteps );
62986411 }
62996412 }
63006413}
0 commit comments