Skip to content

Commit aba1419

Browse files
committed
Harmonize write- and read-side API
1 parent e322ea9 commit aba1419

6 files changed

Lines changed: 196 additions & 235 deletions

File tree

examples/10_streaming_write.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ int main()
2525
// use QueueFullPolicy = Discard in order to create a situation where from
2626
// the reader's perspective steps are skipped. This tests the bug reported
2727
// in https://github.com/openPMD/openPMD-api/issues/1747.
28-
Series series = Series("electrons.sst", Access::CREATE, R"(
28+
Series series = Series("electrons.sst", Access::CREATE_LINEAR, R"(
2929
{
3030
"adios2": {
3131
"engine": {
@@ -49,7 +49,7 @@ int main()
4949
// Iterations can be accessed independently from one another. This more
5050
// restricted mode enables performance optimizations in the backends, and
5151
// more importantly is compatible with streaming I/O.
52-
auto iterations = series.snapshots(SnapshotWorkflow::Synchronous);
52+
auto iterations = series.snapshots();
5353
for (size_t i = 0; i < 100; ++i)
5454
{
5555
Iteration iteration = iterations[i];

include/openPMD/Series.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -729,8 +729,7 @@ class Series : public Attributable
729729
* in Access::CREATE and Access::APPEND. Leave unspecified in
730730
* other access modes as those support only one workflow each.
731731
*/
732-
Snapshots
733-
snapshots(std::optional<SnapshotWorkflow> snapshot_workflow = std::nullopt);
732+
Snapshots snapshots();
734733

735734
/**
736735
* @brief Parse the Series.
@@ -1007,6 +1006,9 @@ OPENPMD_private
10071006
*/
10081007
std::optional<std::vector<std::vector<IterationIndex_t>>>
10091008
preparseSnapshots();
1009+
1010+
Snapshots makeRandomAccessSnapshots();
1011+
Snapshots makeSynchronousSnapshots();
10101012
/* Should adios2::Variable<T>::SetStepSelection() be used for accessing
10111013
* steps?
10121014
*/

src/Series.cpp

Lines changed: 75 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@
4040
#include "openPMD/backend/Attributable.hpp"
4141
#include "openPMD/backend/Attribute.hpp"
4242
#include "openPMD/snapshots/ContainerImpls.hpp"
43-
#include "openPMD/snapshots/IteratorTraits.hpp"
44-
#include "openPMD/snapshots/RandomAccessIterator.hpp"
43+
#include "openPMD/snapshots/ContainerTraits.hpp"
4544
#include "openPMD/snapshots/Snapshots.hpp"
4645
#include "openPMD/snapshots/StatefulIterator.hpp"
4746
#include "openPMD/version.hpp"
@@ -3186,135 +3185,92 @@ namespace
31863185
}
31873186
} // namespace
31883187

3189-
Snapshots
3190-
Series::snapshots(std::optional<SnapshotWorkflow> const snapshot_workflow)
3188+
Snapshots Series::snapshots()
31913189
{
31923190
auto &series = get();
31933191
if (series.m_deferred_initialization.has_value())
31943192
{
31953193
runDeferredInitialization();
31963194
}
31973195
auto access = IOHandler()->m_frontendAccess;
3198-
auto guard_wrong_access_specification =
3199-
[&](SnapshotWorkflow required_access) {
3200-
if (!snapshot_workflow.has_value())
3201-
{
3202-
return required_access;
3203-
}
3204-
if (required_access != *snapshot_workflow)
3205-
{
3206-
std::stringstream error;
3207-
error << "[Series::snapshots()] Specified "
3208-
<< (*snapshot_workflow == SnapshotWorkflow::Synchronous
3209-
? "linear"
3210-
: "random-access")
3211-
<< " iteration in method parameter "
3212-
"`snapshot_workflow`, but access type "
3213-
<< access << " requires "
3214-
<< (required_access == SnapshotWorkflow::Synchronous
3215-
? "linear"
3216-
: "random-access")
3217-
<< " iteration. Please remove the parameter, there is no "
3218-
"need to specify it under "
3219-
<< access << " mode." << std::endl;
3220-
throw error::WrongAPIUsage(error.str());
3221-
}
3222-
else
3223-
{
3224-
std::cerr
3225-
<< "[Series::snapshots()] No need to explicitly specify "
3226-
"synchronous or non-synchronous access via method "
3227-
"parameter `snapshot_workflow` in mode '"
3228-
<< access << ". Will ignore." << std::endl;
3229-
}
3230-
return required_access;
3231-
};
3232-
SnapshotWorkflow usedSnapshotWorkflow{};
3196+
SnapshotWorkflow usedSnapshotWorkflow = access::random_access(access)
3197+
? SnapshotWorkflow::RandomAccess
3198+
: SnapshotWorkflow::Synchronous;
3199+
if (access == Access::READ_RANDOM_ACCESS)
32333200
{
3234-
switch (access)
3201+
// Some error checks
3202+
if (series.m_parsePreference.has_value())
32353203
{
3236-
case Access::READ_LINEAR:
3237-
usedSnapshotWorkflow =
3238-
guard_wrong_access_specification(SnapshotWorkflow::Synchronous);
3239-
break;
3240-
case Access::READ_ONLY:
3241-
usedSnapshotWorkflow = guard_wrong_access_specification(
3242-
SnapshotWorkflow::RandomAccess);
3243-
3244-
// Some error checks
3245-
if (series.m_parsePreference.has_value())
3204+
switch (series.m_parsePreference.value())
32463205
{
3247-
switch (series.m_parsePreference.value())
3248-
{
3249-
case internal::ParsePreference::UpFront:
3250-
break;
3251-
case internal::ParsePreference::PerStep:
3252-
throw error::ReadError(
3253-
error::AffectedObject::File,
3254-
error::Reason::UnexpectedContent,
3255-
std::nullopt,
3256-
"[Series::snapshots()] Series requires collective "
3257-
"processing with READ_LINEAR access mode.");
3258-
}
3259-
}
3260-
else if (iterationEncoding() != IterationEncoding::fileBased)
3261-
{
3262-
throw error::Internal(
3263-
"READ_ONLY mode and non-fileBased iteration encoding, but "
3264-
"the backend did not set a parse preference.");
3206+
case internal::ParsePreference::UpFront:
3207+
break;
3208+
case internal::ParsePreference::PerStep:
3209+
throw error::ReadError(
3210+
error::AffectedObject::File,
3211+
error::Reason::UnexpectedContent,
3212+
std::nullopt,
3213+
"[Series::snapshots()] Series requires collective "
3214+
"processing with READ_LINEAR access mode.");
32653215
}
3266-
break;
3267-
case Access::READ_WRITE:
3268-
// Our Read-Write workflows are entirely random-access based (so
3269-
// far).
3270-
// (Might be possible to allow stateful access actually, but there's
3271-
// no real use, so keep it simple.)
3272-
usedSnapshotWorkflow = guard_wrong_access_specification(
3273-
SnapshotWorkflow::RandomAccess);
3274-
break;
3275-
3276-
// TODO: Remove parameter
3277-
case Access::CREATE_RANDOM_ACCESS:
3278-
case Access::APPEND_RANDOM_ACCESS:
3279-
// Users can select.
3280-
usedSnapshotWorkflow = snapshot_workflow.value_or(
3281-
/* random-access logic by default */
3282-
SnapshotWorkflow::RandomAccess);
3283-
break;
3284-
case Access::CREATE_LINEAR:
3285-
case Access::APPEND_LINEAR:
3286-
// Users can select.
3287-
usedSnapshotWorkflow = snapshot_workflow.value_or(
3288-
/* random-access logic by default */
3289-
SnapshotWorkflow::Synchronous);
3290-
break;
3216+
}
3217+
else if (iterationEncoding() != IterationEncoding::fileBased)
3218+
{
3219+
throw error::Internal(
3220+
"READ_ONLY mode and non-fileBased iteration encoding, but "
3221+
"the backend did not set a parse preference.");
32913222
}
32923223
}
32933224

3225+
switch (usedSnapshotWorkflow)
3226+
{
3227+
case SnapshotWorkflow::RandomAccess: {
3228+
return makeRandomAccessSnapshots();
3229+
}
3230+
case SnapshotWorkflow::Synchronous: {
3231+
return makeSynchronousSnapshots();
3232+
}
3233+
}
3234+
throw std::runtime_error("unreachable!");
3235+
}
3236+
3237+
Snapshots Series::makeRandomAccessSnapshots()
3238+
{
3239+
auto &series = get();
3240+
return Snapshots(
3241+
std::shared_ptr<RandomAccessIteratorContainer>{
3242+
new RandomAccessIteratorContainer(series.iterations)},
3243+
series.iterations);
3244+
}
3245+
Snapshots Series::makeSynchronousSnapshots()
3246+
{
3247+
auto &series = get();
32943248
/*
3295-
* ADIOS2 should use variable-based encoding as a default when applicable,
3296-
* since group-based encoding has severe limitations in ADIOS2.
3297-
* The below logic checks if variable-based encoding should be used.
3249+
* ADIOS2 should use variable-based encoding as a default when
3250+
* applicable, since group-based encoding has severe limitations
3251+
* in ADIOS2. The below logic checks if variable-based encoding
3252+
* should be used.
32983253
*/
32993254

33003255
if (
33013256
// 1. No encoding has been explicitly selected by the user.
33023257
// Flag set by Series::setIterationEncoding().
33033258
series.m_iterationEncodingSetExplicitly ==
33043259
internal::default_or_explicit::default_ &&
3305-
// 2. Iteration encoding was recognized as groupBased by init()
3260+
// 2. Iteration encoding was recognized as groupBased by
3261+
// init()
33063262
// procedures (and not file-based).
33073263
series.m_iterationEncoding == IterationEncoding::groupBased &&
3308-
// 3. The IO workflow will be synchronous, necessary for writing
3309-
// variable-based data (but not for reading!).
3310-
usedSnapshotWorkflow == SnapshotWorkflow::Synchronous &&
3311-
// 4. The chosen access type is write-only, otherwise the encoding is
3264+
// 3. The chosen access type is write-only, otherwise the
3265+
// encoding is
33123266
// determined by the previous file content.
3313-
access::writeOnly(access) &&
3314-
// 5. The backend is ADIOS2 in a recent enough version to support
3267+
access::writeOnly(IOHandler()->m_frontendAccess) &&
3268+
// 4. The backend is ADIOS2 in a recent enough version to
3269+
// support
33153270
// modifiable attributes (v2.9).
33163271
IOHandler()->fullSupportForVariableBasedEncoding() &&
3317-
// 6. The Series must not yet be written, otherwise we're too late
3272+
// 5. The Series must not yet be written, otherwise we're
3273+
// too late
33183274
// for this
33193275
!this->written())
33203276
{
@@ -3323,32 +3279,20 @@ Series::snapshots(std::optional<SnapshotWorkflow> const snapshot_workflow)
33233279
internal::default_or_explicit::default_);
33243280
}
33253281

3326-
switch (usedSnapshotWorkflow)
3327-
{
3328-
case SnapshotWorkflow::RandomAccess: {
3329-
return Snapshots(
3330-
std::shared_ptr<RandomAccessIteratorContainer>{
3331-
new RandomAccessIteratorContainer(series.iterations)},
3332-
series.iterations);
3333-
}
3334-
case SnapshotWorkflow::Synchronous: {
3335-
std::function<StatefulIterator *()> begin;
3282+
std::function<StatefulIterator *()> begin;
33363283

3337-
if (access::write(IOHandler()->m_frontendAccess))
3338-
{
3339-
begin = make_writing_stateful_iterator(*this, series);
3340-
}
3341-
else
3342-
{
3343-
begin = make_reading_stateful_iterator(*this, series);
3344-
}
3345-
return Snapshots(
3346-
std::shared_ptr<StatefulSnapshotsContainer>(
3347-
new StatefulSnapshotsContainer(std::move(begin))),
3348-
series.iterations);
3284+
if (access::write(IOHandler()->m_frontendAccess))
3285+
{
3286+
begin = make_writing_stateful_iterator(*this, series);
33493287
}
3288+
else
3289+
{
3290+
begin = make_reading_stateful_iterator(*this, series);
33503291
}
3351-
throw std::runtime_error("unreachable!");
3292+
return Snapshots(
3293+
std::shared_ptr<StatefulSnapshotsContainer>(
3294+
new StatefulSnapshotsContainer(std::move(begin))),
3295+
series.iterations);
33523296
}
33533297

33543298
void Series::parseBase()
@@ -3361,14 +3305,16 @@ WriteIterations Series::writeIterations()
33613305
{
33623306
auto const access = IOHandler()->m_frontendAccess;
33633307
if (access != Access::CREATE_RANDOM_ACCESS &&
3364-
access != Access::APPEND_RANDOM_ACCESS)
3308+
access != Access::APPEND_RANDOM_ACCESS &&
3309+
access != Access::CREATE_LINEAR &&
3310+
access != Access::CREATE_RANDOM_ACCESS)
33653311
{
33663312
throw error::WrongAPIUsage(
33673313
"[Series::writeIterations()] May only be applied for access modes "
33683314
"CREATE or APPEND. Use Series::snapshots() for random-access-type "
33693315
"or for read-type workflows.");
33703316
}
3371-
return snapshots(SnapshotWorkflow::Synchronous);
3317+
return makeSynchronousSnapshots();
33723318
}
33733319

33743320
void Series::close()

src/binding/python/Series.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,6 @@ Look for the WriteIterations class for further documentation.
561561
"snapshots",
562562
&Series::snapshots,
563563
py::keep_alive<0, 1>(),
564-
py::arg("snapshot_workflow") = std::nullopt,
565564
"TODO FILL IN DOCUMENTATION");
566565

567566
add_pickle(

0 commit comments

Comments
 (0)