Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
b58d44a
Flush structural info of resetDataset() to backend immediately
franzpoeschel Mar 11, 2026
874e8e1
Erase flushMeshes/ParticlesPath
franzpoeschel Mar 11, 2026
a350eb0
Move flushing from storeChunk to resetDataset
franzpoeschel Mar 11, 2026
7fa990d
Hmm, move CREATE_DATASET task back to storeChunk
franzpoeschel Mar 12, 2026
3f1db50
Fix attribute flushing logic
franzpoeschel Mar 12, 2026
3f8aa71
flush mode helpers
franzpoeschel Jan 14, 2026
724c098
Fix dirty handling
franzpoeschel Jan 14, 2026
e6ca360
Add TODO comment
franzpoeschel Mar 12, 2026
50d0214
WIP Runtime verification of flush level
franzpoeschel Mar 12, 2026
fd97745
dont flush to IO handler yet in resetDataset
franzpoeschel Mar 13, 2026
c30b278
Revert "dont flush to IO handler yet in resetDataset"
franzpoeschel Mar 13, 2026
426a8de
Continue fixing and breaking things..
franzpoeschel Mar 13, 2026
9bf742f
Fix API call after rebase
franzpoeschel Mar 16, 2026
78ed217
Fix dirty handling filebased
franzpoeschel Mar 16, 2026
3406ad9
TMP REVERT ME: deactivate span table tests
franzpoeschel Mar 16, 2026
931e9e9
TMP REVERT ME take out hanging parallel test
franzpoeschel Mar 16, 2026
769965d
Fix ranktable logic
franzpoeschel Mar 27, 2026
f94d882
Take out the next hanging parallel test
franzpoeschel Mar 27, 2026
a572f33
Separate MPI tests by MPI barriers
franzpoeschel Mar 27, 2026
3dd8d66
Fix wrong MPI_COMM_WORLD
franzpoeschel Mar 27, 2026
665a3b1
wip: debugging state
franzpoeschel Mar 27, 2026
5eb80e5
deactivate malicious tests
franzpoeschel Mar 30, 2026
300506f
Revert "deactivate malicious tests"
franzpoeschel Mar 30, 2026
99be82c
Revert "wip: debugging state"
franzpoeschel Mar 30, 2026
f24fcdb
Revert "TMP REVERT ME take out hanging parallel test"
franzpoeschel Mar 30, 2026
e6d81c7
Revert some WIPs
franzpoeschel Mar 30, 2026
8d72468
Use an Attributable per Iteration for rankTable in filebased encoding
franzpoeschel May 19, 2026
a67f869
fix nompi builds
franzpoeschel May 20, 2026
257949e
CI fixes
franzpoeschel May 20, 2026
503e53a
Activate test again
franzpoeschel May 20, 2026
e248ab8
Guard against any internal unsetDirty operation
franzpoeschel Jul 8, 2026
e1c2670
Span API: more precise written and error checks
franzpoeschel Jul 8, 2026
000bee6
Revert the defer stuff
franzpoeschel Jul 13, 2026
c06caf5
dont enforce flush upon reset dataset
franzpoeschel Jul 13, 2026
cea11c9
keep only the false branch
franzpoeschel Jul 13, 2026
bc00986
docs
franzpoeschel Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions include/openPMD/IO/AbstractIOHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "openPMD/IterationEncoding.hpp"
#include "openPMD/config.hpp"
#include "openPMD/version.hpp"
#include <ostream>

#if openPMD_HAVE_MPI
#include <mpi.h>
Expand Down Expand Up @@ -81,6 +82,66 @@ enum class FlushLevel
CreateOrOpenFiles
};

std::ostream &operator<<(std::ostream &, FlushLevel);

namespace flush_level
{
inline constexpr auto global_flushpoint(FlushLevel fl)
{
switch (fl)
{
case FlushLevel::UserFlush:
return true;
case FlushLevel::InternalFlush:
case FlushLevel::SkeletonOnly:
case FlushLevel::CreateOrOpenFiles:
return false;
}
return false; // unreachable
}
// same as global_flushpoint for now, but we will soon introduce
// immediate_flush
inline constexpr auto write_datasets(FlushLevel fl)
{
switch (fl)
{
case FlushLevel::UserFlush:
return true;
case FlushLevel::InternalFlush:
case FlushLevel::SkeletonOnly:
case FlushLevel::CreateOrOpenFiles:
return false;
}
return false; // unreachable
}
inline constexpr auto write_attributes(FlushLevel fl)
{
switch (fl)
{
case FlushLevel::UserFlush:
case FlushLevel::InternalFlush:
return true;
case FlushLevel::SkeletonOnly:
case FlushLevel::CreateOrOpenFiles:
return false;
}
return false; // unreachable
}
inline constexpr auto flush_hierarchy(FlushLevel fl)
{
switch (fl)
{
case FlushLevel::UserFlush:
case FlushLevel::InternalFlush:
case FlushLevel::SkeletonOnly:
return true;
case FlushLevel::CreateOrOpenFiles:
return false;
}
return false; // unreachable
}
} // namespace flush_level

enum class OpenpmdStandard
{
v_1_0_0,
Expand Down Expand Up @@ -121,6 +182,7 @@ namespace internal
* To be used for reading
*/
FlushParams const defaultFlushParams{};
FlushParams const publicFlush{FlushLevel::UserFlush};

struct ParsedFlushParams;

Expand Down
2 changes: 1 addition & 1 deletion include/openPMD/IO/AbstractIOHandlerImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class AbstractIOHandlerImpl

virtual ~AbstractIOHandlerImpl() = default;

std::future<void> flush();
std::future<void> flush(FlushLevel);

/**
* Close the file corresponding with the writable and release file handles.
Expand Down
3 changes: 3 additions & 0 deletions include/openPMD/IO/IOTask.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <cstddef>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <utility>
#include <variant>
Expand Down Expand Up @@ -89,6 +90,8 @@ OPENPMDAPI_EXPORT_ENUM_CLASS(Operation){
}; // note: if you change the enum members here, please update
// docs/source/dev/design.rst

std::ostream &operator<<(std::ostream &os, Operation op);

namespace internal
{
/*
Expand Down
2 changes: 1 addition & 1 deletion include/openPMD/IO/JSON/JSONIOHandlerImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ class JSONIOHandlerImpl : public AbstractIOHandlerImpl

void touch(Writable *, Parameter<Operation::TOUCH> const &) override;

std::future<void> flush();
std::future<void> flush(internal::ParsedFlushParams &params);

private:
#if openPMD_HAVE_MPI
Expand Down
17 changes: 10 additions & 7 deletions include/openPMD/Iteration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "openPMD/backend/Attributable.hpp"
#include "openPMD/backend/Container.hpp"
#include "openPMD/backend/HierarchyVisitor.hpp"
#include "openPMD/backend/PerIterationData.hpp"
#include "openPMD/backend/scientific_defaults/ScientificDefaults.hpp"

#include <cstdint>
Expand Down Expand Up @@ -122,14 +123,16 @@ namespace internal
*/
bool allow_reopening_implicitly = false;

/**
* Whether a step is currently active for this iteration.
* Used for file-based iteration layout, see Series.hpp for
* group-based layout.
* Access via stepStatus() method to automatically select the correct
* one among both flags.
/*
* This stores data items that are:
*
* 1. global in group and variable encodings
* 2. per-iteration in file encoding
*
* The struct is stored as part of the Series and as part of each
* Iteration. Access must be distinguished by iteration encoding.
*/
StepStatus m_stepStatus = StepStatus::NoStep;
PerIterationData m_perIterationData;

/**
* Cached copy of the key under which this Iteration lives in
Expand Down
8 changes: 6 additions & 2 deletions include/openPMD/RecordComponent.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ RecordComponent::storeChunk(Offset o, Extent e, F &&createBuffer)
{
size *= ext;
}

/*
* Flushing the skeleton does not create datasets,
* so we might need to do it now.
Expand Down Expand Up @@ -121,15 +122,18 @@ RecordComponent::storeChunk(Offset o, Extent e, F &&createBuffer)
// restriction
// TODO: Add some form of collective ::commitDefinitions() call to
// RecordComponents to be called by users before the Span API
if (!written())
if (!writable().parent || !writable().parent->written)
{
/*
* The openPMD backend might not yet know about this dataset.
* Flush the openPMD hierarchy to the backend without flushing any
* actual data yet.
*/
seriesFlush_impl</* flush_entire_series = */ false>(
{FlushLevel::SkeletonOnly});
{FlushLevel::SkeletonOnly}, /*flush_io_handler=*/false);
}
if (!this->written())
{
Parameter<Operation::CREATE_DATASET> dCreate(rc.m_dataset.value());
dCreate.name = Attributable::get().m_writable.ownKeyWithinParent;
IOHandler()->enqueue(IOTask(this, dCreate));
Expand Down
28 changes: 16 additions & 12 deletions include/openPMD/Series.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "openPMD/backend/Container.hpp"
#include "openPMD/backend/HierarchyVisitor.hpp"
#include "openPMD/backend/ParsePreference.hpp"
#include "openPMD/backend/PerIterationData.hpp"
#include "openPMD/config.hpp"
#include "openPMD/snapshots/Snapshots.hpp"
#include "openPMD/version.hpp"
Expand Down Expand Up @@ -205,14 +206,18 @@ namespace internal
* Detected IO format (backend).
*/
Format m_format;
/**
* Whether a step is currently active for this iteration.
* Used for group-based iteration layout, see SeriesData.hpp for
* iteration-based layout.
* Access via stepStatus() method to automatically select the correct
* one among both flags.

/*
* This stores data items that are:
*
* 1. global in group and variable encodings
* 2. per-iteration in file encoding
*
* The struct is stored as part of the Series and as part of each
* Iteration. Access must be distinguished by iteration encoding.
*/
StepStatus m_stepStatus = StepStatus::NoStep;
PerIterationData m_perIterationData;

/**
* True if a user opts into lazy parsing.
*/
Expand Down Expand Up @@ -261,7 +266,6 @@ namespace internal

struct RankTableData
{
Attributable m_attributable;
std::variant<
NoSourceSpecified,
SourceSpecifiedViaJSON,
Expand Down Expand Up @@ -900,9 +904,7 @@ OPENPMD_private
iterations_iterator end,
internal::FlushParams const &flushParams,
bool flushIOHandler = true);
void flushMeshesPath();
void flushParticlesPath();
void flushRankTable();
void flushRankTable(FlushLevel, Attributable &attributable);
/* Parameter `read_only_this_single_iteration` used for reopening an
* Iteration after closing it.
*/
Expand Down Expand Up @@ -985,8 +987,10 @@ OPENPMD_private
* least one step was written.
*
* @param doFlush If true, flush the IO handler.
* @param l This operation must only run at flush level write_datasets,
* Noop otherwise.
*/
void flushStep(bool doFlush);
void flushStep(bool doFlush, FlushLevel l);

/*
* setIterationEncoding() should only be called by users of our public API,
Expand Down
30 changes: 29 additions & 1 deletion include/openPMD/backend/Attributable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ OPENPMD_protected
/** @} */

template <bool flush_entire_series>
void seriesFlush_impl(internal::FlushParams const &);
void seriesFlush_impl(internal::FlushParams const &, bool flush_io_handler);

void flushAttributes(internal::FlushParams const &);

Expand Down Expand Up @@ -606,6 +606,34 @@ OPENPMD_protected
{
return writable().dirtyRecursive;
}
void determineUnsetDirty(FlushLevel fl)
{
switch (fl)
{
case FlushLevel::UserFlush:
setDirty(false);
break;
// FlushLevel::InternalFlush is only used for directly calling the IO
// handler and should not bother with middle-end state manipulations
case FlushLevel::InternalFlush:
// Used for parsing
if (IOHandler()->m_seriesStatus == internal::SeriesStatus::Parsing)
{
throw error::Internal(
"Parsing procedures should directly unset dirty.");
}
else
{
throw error::Internal(
"Internal flushes should not unset dirty flags.");
}
break;
case FlushLevel::SkeletonOnly:
case FlushLevel::CreateOrOpenFiles:
// noop
break;
}
}
void setDirty(bool dirty_in)
{
auto &w = writable();
Expand Down
54 changes: 54 additions & 0 deletions include/openPMD/backend/PerIterationData.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#pragma once

#include "openPMD/ChunkInfo.hpp"
#include "openPMD/Streaming.hpp"
#include "openPMD/backend/Attributable.hpp"

#include <variant>

namespace openPMD::internal
{
struct NoSourceSpecified
{};
struct SourceSpecifiedViaJSON
{
std::string value;
};
struct SourceSpecifiedManually
{
std::string value;
};

struct RankTableData
{
Attributable m_attributable;
std::variant<
NoSourceSpecified,
SourceSpecifiedViaJSON,
SourceSpecifiedManually>
m_rankTableSource;
std::optional<chunk_assignment::RankMeta> m_bufferedRead;
};

/*
* This stores data items that are:
*
* 1. global in group and variable encodings
* 2. per-iteration in file encoding
*
* The struct is stored as part of the Series and as part of each Iteration.
* Access must be distinguished by iteration encoding.
*/
struct PerIterationData
{
/**
* Whether a step is currently active for this iteration.
* Used for group-based iteration layout, see SeriesData.hpp for
* iteration-based layout.
* Access via stepStatus() method to automatically select the correct
* one among both flags.
*/
StepStatus m_stepStatus = StepStatus::NoStep;
Attributable m_rankTableAttributable;
};
} // namespace openPMD::internal
5 changes: 3 additions & 2 deletions include/openPMD/backend/Writable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,15 @@ class Writable final
* it.
*/
template <bool flush_entire_series>
void seriesFlush(std::string backendConfig = "{}");
void
seriesFlush(std::string backendConfig = "{}", bool flush_io_handler = true);

// clang-format off
OPENPMD_private
// clang-format on

template <bool flush_entire_series>
void seriesFlush(internal::FlushParams const &);
void seriesFlush(internal::FlushParams const &, bool flush_io_handler);
/*
* These members need to be shared pointers since distinct instances of
* Writable may share them.
Expand Down
18 changes: 4 additions & 14 deletions src/IO/ADIOS/ADIOS2File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1049,25 +1049,16 @@ void ADIOS2File::flush_impl(
drainedUniquePtrPuts.swap(m_uniquePtrPuts);
}

if (readOnly(m_mode))
if (readOnly(m_mode) || flush_level::write_datasets(level))
{
level = FlushLevel::UserFlush;
}

switch (level)
{
case FlushLevel::UserFlush:
performPutGets(*this, eng);
m_updateSpans.clear();
m_buffer.clear();
m_alreadyEnqueued.clear();
drainedUniquePtrPuts.clear();

break;

case FlushLevel::InternalFlush:
case FlushLevel::SkeletonOnly:
case FlushLevel::CreateOrOpenFiles:
}
else
{
/*
* Tasks have been given to ADIOS2, but we don't flush them
* yet. So, move everything to m_alreadyEnqueued to avoid
Expand All @@ -1084,7 +1075,6 @@ void ADIOS2File::flush_impl(
"wrong time.");
}
m_buffer.clear();
break;
}
}

Expand Down
Loading
Loading