@@ -6345,9 +6345,48 @@ TEST_CASE("varying_zero_pattern", "[serial]")
63456345 }
63466346}
63476347
6348+ enum class ParseMode
6349+ {
6350+ /*
6351+ * Conventional workflow. Just parse the whole thing and yield iterations
6352+ * in rising order.
6353+ */
6354+ NoSteps,
6355+ /*
6356+ * NOTE: This mode is only temporary until the topic-linear-read PR,
6357+ * no longer necessary after that.
6358+ * The Series is parsed ahead of time upon opening, but it has steps.
6359+ * Parsing ahead of time is the conventional workflow to support
6360+ * random-access.
6361+ * Reading such a Series with the streaming API is only possible if all
6362+ * steps are in ascending order, otherwise the openPMD-api has no way of
6363+ * associating IO steps with interation indices.
6364+ * Reading such a Series with the Streaming API will become possible with
6365+ * the Linear read mode to be introduced by #1291.
6366+ */
6367+ AheadOfTimeWithoutSnapshot,
6368+ /*
6369+ * A Series of the BP5 engine is not parsed ahead of time, but step-by-step,
6370+ * giving the openPMD-api a way to associate IO steps with iterations.
6371+ * No snapshot attribute exists, so the fallback mode is chosen:
6372+ * Iterations are returned in ascending order.
6373+ * If an IO step returns an iteration whose index is lower than the
6374+ * last one, it will be skipped.
6375+ * This mode of parsing will be generalized into the Linear read mode with
6376+ * PR #1291.
6377+ */
6378+ LinearWithoutSnapshot,
6379+ /*
6380+ * Snapshot attribute exists and dictates the iteration index returned by
6381+ * an IO step. Duplicate iterations will be skipped.
6382+ */
6383+ WithSnapshot
6384+ };
6385+
63486386void append_mode (
63496387 std::string const &extension,
63506388 bool variableBased,
6389+ ParseMode parseMode,
63516390 std::string jsonConfig = " {}" )
63526391{
63536392
@@ -6455,8 +6494,31 @@ void append_mode(
64556494 }
64566495 {
64576496 Series read (filename, Access::READ_ONLY);
6458- if (variableBased || extension == " bp5 " )
6497+ switch (parseMode )
64596498 {
6499+ case ParseMode::NoSteps: {
6500+ unsigned counter = 0 ;
6501+ uint64_t iterationOrder[] = {0 , 1 , 2 , 3 , 4 , 7 , 10 , 11 };
6502+ for (auto const &iteration : read.readIterations ())
6503+ {
6504+ REQUIRE (iteration.iterationIndex == iterationOrder[counter]);
6505+ ++counter;
6506+ }
6507+ REQUIRE (counter == 8 );
6508+ }
6509+ break ;
6510+ case ParseMode::LinearWithoutSnapshot: {
6511+ unsigned counter = 0 ;
6512+ uint64_t iterationOrder[] = {0 , 1 , 2 , 3 , 4 , 10 , 11 };
6513+ for (auto const &iteration : read.readIterations ())
6514+ {
6515+ REQUIRE (iteration.iterationIndex == iterationOrder[counter]);
6516+ ++counter;
6517+ }
6518+ REQUIRE (counter == 7 );
6519+ }
6520+ break ;
6521+ case ParseMode::WithSnapshot: {
64606522 // in variable-based encodings, iterations are not parsed ahead of
64616523 // time but as they go
64626524 unsigned counter = 0 ;
@@ -6470,9 +6532,22 @@ void append_mode(
64706532 // Cannot do listSeries here because the Series is already drained
64716533 REQUIRE_THROWS_AS (helper::listSeries (read), error::WrongAPIUsage);
64726534 }
6473- else
6474- {
6535+ break ;
6536+ case ParseMode::AheadOfTimeWithoutSnapshot: {
64756537 REQUIRE (read.iterations .size () == 8 );
6538+ unsigned counter = 0 ;
6539+ uint64_t iterationOrder[] = {0 , 1 , 2 , 3 , 4 , 7 , 10 , 11 };
6540+ /*
6541+ * Use conventional read API since streaming API is not possible
6542+ * without Linear read mode.
6543+ * (See also comments inside ParseMode enum).
6544+ */
6545+ for (auto const &iteration : read.iterations )
6546+ {
6547+ REQUIRE (iteration.first == iterationOrder[counter]);
6548+ ++counter;
6549+ }
6550+ REQUIRE (counter == 8 );
64766551 /*
64776552 * Roadmap: for now, reading this should work by ignoring the last
64786553 * duplicate iteration.
@@ -6482,6 +6557,8 @@ void append_mode(
64826557 */
64836558 helper::listSeries (read);
64846559 }
6560+ break ;
6561+ }
64856562 }
64866563#if 100000000 * ADIOS2_VERSION_MAJOR + 1000000 * ADIOS2_VERSION_MINOR + \
64876564 10000 * ADIOS2_VERSION_PATCH + 100 * ADIOS2_VERSION_TWEAK >= \
@@ -6518,16 +6595,47 @@ void append_mode(
65186595 }
65196596 {
65206597 Series read (filename, Access::READ_ONLY);
6521- // in variable-based encodings, iterations are not parsed ahead of
6522- // time but as they go
6523- unsigned counter = 0 ;
6524- for (auto const &iteration : read.readIterations ())
6598+ switch (parseMode)
65256599 {
6526- REQUIRE (iteration.iterationIndex == counter);
6527- ++counter;
6600+ case ParseMode::LinearWithoutSnapshot: {
6601+ uint64_t iterationOrder[] = {0 , 1 , 2 , 3 , 4 , 10 };
6602+ unsigned counter = 0 ;
6603+ for (auto const &iteration : read.readIterations ())
6604+ {
6605+ REQUIRE (
6606+ iteration.iterationIndex == iterationOrder[counter]);
6607+ ++counter;
6608+ }
6609+ REQUIRE (counter == 6 );
6610+ // Cannot do listSeries here because the Series is already
6611+ // drained
6612+ REQUIRE_THROWS_AS (
6613+ helper::listSeries (read), error::WrongAPIUsage);
6614+ }
6615+ break ;
6616+ case ParseMode::WithSnapshot: {
6617+ // in variable-based encodings, iterations are not parsed ahead
6618+ // of time but as they go
6619+ unsigned counter = 0 ;
6620+ uint64_t iterationOrder[] = {0 , 1 , 2 , 3 , 4 , 10 , 7 , 5 };
6621+ for (auto const &iteration : read.readIterations ())
6622+ {
6623+ REQUIRE (
6624+ iteration.iterationIndex == iterationOrder[counter]);
6625+ ++counter;
6626+ }
6627+ REQUIRE (counter == 8 );
6628+ // Cannot do listSeries here because the Series is already
6629+ // drained
6630+ REQUIRE_THROWS_AS (
6631+ helper::listSeries (read), error::WrongAPIUsage);
6632+ }
6633+ break ;
6634+ case ParseMode::NoSteps:
6635+ case ParseMode::AheadOfTimeWithoutSnapshot:
6636+ throw std::runtime_error (" Test configured wrong." );
6637+ break ;
65286638 }
6529- REQUIRE (counter == 6 );
6530- helper::listSeries (read);
65316639 }
65326640 }
65336641#endif
@@ -6537,9 +6645,7 @@ TEST_CASE("append_mode", "[serial]")
65376645{
65386646 for (auto const &t : testedFileExtensions ())
65396647 {
6540- if (t == " bp" || t == " bp4" || t == " bp5" )
6541- {
6542- std::string jsonConfigOld = R"END(
6648+ std::string jsonConfigOld = R"END(
65436649{
65446650 "adios2":
65456651 {
@@ -6550,7 +6656,7 @@ TEST_CASE("append_mode", "[serial]")
65506656 }
65516657 }
65526658})END" ;
6553- std::string jsonConfigNew = R"END(
6659+ std::string jsonConfigNew = R"END(
65546660{
65556661 "adios2":
65566662 {
@@ -6561,14 +6667,25 @@ TEST_CASE("append_mode", "[serial]")
65616667 }
65626668 }
65636669})END" ;
6564- append_mode (t, false , jsonConfigOld);
6565- append_mode (t, false , jsonConfigNew);
6566- append_mode (t, true , jsonConfigOld);
6567- append_mode (t, true , jsonConfigNew);
6670+ if (t == " bp5" )
6671+ {
6672+ append_mode (
6673+ t, false , ParseMode::LinearWithoutSnapshot, jsonConfigOld);
6674+ append_mode (t, false , ParseMode::WithSnapshot, jsonConfigNew);
6675+ append_mode (t, true , ParseMode::WithSnapshot, jsonConfigOld);
6676+ append_mode (t, true , ParseMode::WithSnapshot, jsonConfigNew);
6677+ }
6678+ else if (t == " bp" || t == " bp4" || t == " bp5" )
6679+ {
6680+ append_mode (
6681+ t, false , ParseMode::AheadOfTimeWithoutSnapshot, jsonConfigOld);
6682+ append_mode (t, false , ParseMode::WithSnapshot, jsonConfigNew);
6683+ append_mode (t, true , ParseMode::WithSnapshot, jsonConfigOld);
6684+ append_mode (t, true , ParseMode::WithSnapshot, jsonConfigNew);
65686685 }
65696686 else
65706687 {
6571- append_mode (t, false );
6688+ append_mode (t, false , ParseMode::NoSteps );
65726689 }
65736690 }
65746691}
0 commit comments