Skip to content

Commit a6df22f

Browse files
committed
Documentation
1 parent b2dacb8 commit a6df22f

File tree

9 files changed

+77
-42
lines changed

9 files changed

+77
-42
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ if(openPMD_BUILD_TESTING)
783783
macro(additional_testing_sources test_name out_list)
784784
if(${test_name} STREQUAL "SerialIO")
785785
list(APPEND ${out_list}
786-
test/Files_SerialIO/close_iteration_test.cpp
786+
test/Files_SerialIO/close_and_reopen_test.cpp
787787
test/Files_SerialIO/filebased_write_test.cpp
788788
)
789789
endif()

examples/10_streaming_read.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@ int main()
1818
return 0;
1919
}
2020

21+
// Access the Series linearly. This means that upon opening the Series, no
22+
// data is accessed yet. Instead, the single Iterations are processed
23+
// collectively, one after the other, and data access only happens upon
24+
// explicitly accessing an Iteration from `Series::snapshots()`. Note that
25+
// the Container API of `Series::snapshots()` will work in a restricted mode
26+
// compared to the `READ_RANDOM_ACCESS` access type, refer also to the
27+
// documentation of the `Snapshots` class in `snapshots/Snapshots.hpp`. This
28+
// restricted workflow enables performance optimizations in the backends,
29+
// and more importantly is compatible with streaming I/O.
2130
Series series = Series("electrons.sst", Access::READ_LINEAR, R"(
2231
{
2332
"adios2": {
@@ -29,11 +38,6 @@ int main()
2938
}
3039
})");
3140

32-
// `Series::writeIterations()` and `Series::readIterations()` are
33-
// intentionally restricted APIs that ensure a workflow which also works
34-
// in streaming setups, e.g. an iteration cannot be opened again once
35-
// it has been closed.
36-
// `Series::iterations` can be directly accessed in random-access workflows.
3741
for (auto &[index, iteration] : series.snapshots())
3842
{
3943
std::cout << "Current iteration: " << index << std::endl;

examples/10_streaming_write.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ int main()
4040
std::shared_ptr<position_t> local_data(
4141
new position_t[length], [](position_t const *ptr) { delete[] ptr; });
4242

43-
// `Series::writeIterations()` and `Series::readIterations()` are
44-
// intentionally restricted APIs that ensure a workflow which also works
45-
// in streaming setups, e.g. an iteration cannot be opened again once
46-
// it has been closed.
47-
// `Series::iterations` can be directly accessed in random-access workflows.
43+
// Create the Series with synchronous snapshots, i.e. one Iteration after
44+
// the other. The alternative would be random-access where multiple
45+
// Iterations can be accessed independently from one another. This more
46+
// restricted mode enables performance optimizations in the backends, and
47+
// more importantly is compatible with streaming I/O.
4848
auto iterations = series.snapshots(SnapshotWorkflow::Synchronous);
4949
for (size_t i = 0; i < 100; ++i)
5050
{

include/openPMD/ReadIterations.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class LegacyIteratorAdaptor
3838
* This is a feature-restricted subset for the functionality of
3939
* `Series::snapshots()`, prefer using that. The compatibility layer is needed
4040
* due to the different value_type for `Series::readIterations()`-based
41-
* iteration (`IterationIndex` instead of `std::pair<uint64_t, Iteration>`).
41+
* iteration (`IndexedIteration` instead of `std::pair<uint64_t, Iteration>`).
4242
*
4343
* Create instance via Series::readIterations().
4444
* For use in a C++11-style foreach loop over iterations.

include/openPMD/Series.hpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,8 @@ class Series : public Attributable
708708
*
709709
* Conversely, the Access::CREATE and Access::APPEND access modes both
710710
* resolve to random-access by default, but can be specified to use
711-
* Synchronous workflow if needed.
711+
* Synchronous workflow if needed. A shorthand for Synchronous workflows can
712+
* be found with Series::writeIterations().
712713
*
713714
* @param snapshot_workflow Specify the intended workflow
714715
* in Access::CREATE and Access::APPEND. Leave unspecified in
@@ -736,17 +737,9 @@ class Series : public Attributable
736737
/**
737738
* @brief Entry point to the writing end of the streaming API.
738739
*
739-
* Creates and returns an instance of the WriteIterations class which is an
740-
* intentionally restricted container of iterations that takes care of
741-
* streaming semantics, e.g. ensuring that an iteration cannot be reopened
742-
* once closed.
743-
* For a less restrictive API in non-streaming situations,
744-
* `Series::iterations` can be accessed directly.
745-
* The created object is stored as member of the Series object, hence this
746-
* method may be called as many times as a user wishes.
747-
* There is only one shared iterator state per Series, even when calling
748-
* this method twice.
749-
* Look for the WriteIterations class for further documentation.
740+
* Shorthand for `Series::snapshots()` for access types CREATE and APPEND
741+
* called with parameter SnapshotWorkflow::Synchronous, i.e. for
742+
* streaming-aware data producers.
750743
*
751744
* @return WriteIterations
752745
*/

src/Iteration.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,13 @@ Iteration &Iteration::open()
145145
auto &it = get();
146146
// figure out my iteration number
147147
auto begin = s.indexOf(*this);
148-
// ensure that files are accessed
148+
if (it.m_closed == internal::CloseStatus::ClosedInFrontend)
149+
{
150+
// Iteration is only logically closed, we can simply unmark it
151+
it.m_closed = internal::CloseStatus::Open;
152+
}
153+
// Ensure that files are accessed.
154+
// If the close status was Closed, this will open it.
149155
s.openIteration(begin->first, *this);
150156
if (it.m_closed == CloseStatus::ParseAccessDeferred)
151157
{

src/Series.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2705,9 +2705,27 @@ void Series::openIteration(IterationIndex_t index, Iteration &iteration)
27052705
{
27062706
auto oldStatus = iteration.get().m_closed;
27072707
using CL = internal::CloseStatus;
2708+
/*
2709+
* Closed and ClosedInFrontend need to be treated different here.
2710+
* Closed means that the Iteration is actually closed, but we need it again,
2711+
* so it should be opened again.
2712+
* ClosedInFrontend means that the Iteration is about to be closed, but
2713+
* still open. Nothing needs to be done, the enqueued operations can be
2714+
* performed, and the Iteration will be closed afterwards.
2715+
*/
27082716
switch (oldStatus)
27092717
{
27102718
case CL::Closed:
2719+
if (access::writeOnly(IOHandler()->m_frontendAccess))
2720+
{
2721+
std::cerr << &R"(
2722+
[Series::openIteration]
2723+
Warning: Reopening closed Iterations in write modes is currently experimental.
2724+
Note that an ADIOS2 step/file cannot be modified once closed, just appended
2725+
to with a new step. Support for this is not yet feature-complete (pre-alpha).
2726+
)"[1];
2727+
}
2728+
[[fallthrough]];
27112729
case CL::Open:
27122730
iteration.get().m_closed = CL::Open;
27132731
break;
@@ -3188,14 +3206,15 @@ void Series::parseBase()
31883206

31893207
WriteIterations Series::writeIterations()
31903208
{
3191-
auto &series = get();
3192-
if (series.m_deferred_initialization.has_value())
3209+
auto const access = IOHandler()->m_frontendAccess;
3210+
if (access != Access::CREATE && access != Access::APPEND)
31933211
{
3194-
runDeferredInitialization();
3212+
throw error::WrongAPIUsage(
3213+
"[Series::writeIterations()] May only be applied for access modes "
3214+
"CREATE or APPEND. Use Series::snapshots() for random-access-type "
3215+
"or for read-type workflows.");
31953216
}
3196-
auto begin = make_writing_stateful_iterator(*this, series);
3197-
return Snapshots(std::shared_ptr<StatefulSnapshotsContainer>(
3198-
new StatefulSnapshotsContainer(std::move(begin))));
3217+
return snapshots(SnapshotWorkflow::Synchronous);
31993218
}
32003219

32013220
void Series::close()
File renamed without changes.

test/Files_SerialIO/filebased_write_test.cpp

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ namespace filebased_write_test
55
{
66
using namespace openPMD;
77

8+
#define OPENPMD_TEST_VERBOSE 0
9+
10+
namespace
11+
{
12+
template <typename... Args>
13+
auto write_to_stdout([[maybe_unused]] Args &&...args) -> void
14+
{
15+
#if OPENPMD_TEST_VERBOSE
16+
(std::cout << ... << args);
17+
#endif
18+
}
19+
} // namespace
20+
821
auto close_and_reopen_iterations(
922
const std::string &filename,
1023
openPMD::Access access,
@@ -18,32 +31,32 @@ auto close_and_reopen_iterations(
1831
auto chunk = component.loadChunkVariant();
1932
iteration.seriesFlush();
2033
auto num_particles = component.getExtent()[0];
21-
std::cout << "Particles: ";
34+
write_to_stdout("Particles: ");
2235
if (num_particles > 0)
2336
{
2437
std::visit(
2538
[&](auto const &shared_ptr) {
2639
auto it = shared_ptr.get();
2740
auto end = it + num_particles;
28-
std::cout << '[' << *it++;
41+
write_to_stdout('[', *it++);
2942
for (; it != end; ++it)
3043
{
31-
std::cout << ", " << *it;
44+
write_to_stdout(", ", *it);
3245
}
3346
},
3447
chunk);
35-
std::cout << "]";
48+
write_to_stdout("]");
3649
}
3750
else
3851
{
39-
std::cout << "[]";
52+
write_to_stdout("[]");
4053
}
41-
std::cout << std::endl;
54+
write_to_stdout('\n');
4255
};
4356

4457
for (auto &[idx, iteration] : list.snapshots())
4558
{
46-
std::cout << "Seeing iteration " << idx << std::endl;
59+
write_to_stdout("Seeing iteration ", idx, '\n');
4760
if (need_to_explitly_open_iterations)
4861
{
4962
iteration.open();
@@ -52,20 +65,20 @@ auto close_and_reopen_iterations(
5265
{
5366
test_read(iteration);
5467
}
55-
std::cout << "Closing iteration " << idx << std::endl;
68+
write_to_stdout("Closing iteration ", idx, '\n');
5669
iteration.close();
5770
}
58-
std::cout << "Trying to read iteration 3 out of line" << std::endl;
71+
write_to_stdout("Trying to read iteration 3 out of line", '\n');
5972
if (need_to_explitly_open_iterations || access == Access::READ_ONLY)
6073
{
6174
list.snapshots()[3].open();
6275
}
6376
test_read(list.snapshots()[3]);
6477

65-
std::cout << "----------\nGoing again\n----------" << std::endl;
78+
write_to_stdout("----------\nGoing again\n----------", '\n');
6679
for (auto &[idx, iteration] : list.snapshots())
6780
{
68-
std::cout << "Seeing iteration " << idx << std::endl;
81+
write_to_stdout("Seeing iteration ", idx, '\n');
6982
if (need_to_explitly_open_iterations || access == Access::READ_ONLY)
7083
{
7184
iteration.open();

0 commit comments

Comments
 (0)