Skip to content

Commit c7f896a

Browse files
committed
Add further safety guards to createDataset and extendDataset tasks
1 parent b4af694 commit c7f896a

File tree

6 files changed

+77
-14
lines changed

6 files changed

+77
-14
lines changed

include/openPMD/IO/IOTask.hpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,13 @@ struct OPENPMDAPI_EXPORT AbstractParameter
116116
std::string const &currentBackendName,
117117
std::string const &warningMessage);
118118

119+
// Used as a tag in some constructors to make callsites explicitly
120+
// acknowledge that joined dimensions will not be automatically resolved
121+
struct I_dont_want_to_use_joined_dimensions_t
122+
{};
123+
constexpr static I_dont_want_to_use_joined_dimensions_t
124+
I_dont_want_to_use_joined_dimensions{};
125+
119126
protected:
120127
// avoid object slicing
121128
// by allow only child classes to use these things for defining their own
@@ -359,7 +366,17 @@ template <>
359366
struct OPENPMDAPI_EXPORT Parameter<Operation::CREATE_DATASET>
360367
: public AbstractParameter
361368
{
362-
Parameter() = default;
369+
Parameter(Dataset const &ds)
370+
: extent(ds.extent)
371+
, dtype(ds.dtype)
372+
, options(ds.options)
373+
, joinedDimension(ds.joinedDimension())
374+
{}
375+
376+
// default constructor, but callsites need to explicitly acknowledge that
377+
// joined dimensions will not be automatically configured when using it
378+
Parameter(I_dont_want_to_use_joined_dimensions_t)
379+
{}
363380
Parameter(Parameter &&) = default;
364381
Parameter(Parameter const &) = default;
365382
Parameter &operator=(Parameter &&) = default;

include/openPMD/RecordComponent.tpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -356,18 +356,14 @@ RecordComponent::storeChunk(Offset o, Extent e, F &&createBuffer)
356356
if (!written())
357357
{
358358
auto &rc = get();
359-
Parameter<Operation::CREATE_DATASET> dCreate;
360-
dCreate.name = rc.m_name;
361-
dCreate.extent = getExtent();
362-
dCreate.dtype = getDatatype();
363-
dCreate.joinedDimension = joinedDimension();
364359
if (!rc.m_dataset.has_value())
365360
{
366361
throw error::WrongAPIUsage(
367362
"[RecordComponent] Must specify dataset type and extent before "
368363
"using storeChunk() (see RecordComponent::resetDataset()).");
369364
}
370-
dCreate.options = rc.m_dataset.value().options;
365+
Parameter<Operation::CREATE_DATASET> dCreate(rc.m_dataset.value());
366+
dCreate.name = rc.m_name;
371367
IOHandler()->enqueue(IOTask(this, dCreate));
372368
}
373369
Parameter<Operation::GET_BUFFER_VIEW> getBufferView;

src/IO/ADIOS/ADIOS2IOHandler.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,57 @@ namespace detail
888888
{
889889
dims.push_back(ext);
890890
}
891+
auto joinedDim = joinedDimension(var.Shape());
892+
auto make_runtime_error = [&](char const *message) {
893+
std::stringstream s;
894+
s << "[ADIOS2IOHandlerImpl::extendDataset()] " << message
895+
<< "\nNote: Variable '" << variable << "' has old shape ";
896+
auxiliary::write_vec_to_stream(s, var.Shape());
897+
if (joinedDim.has_value())
898+
{
899+
s << " (joined dimension on index " << *joinedDim << ").";
900+
}
901+
else
902+
{
903+
s << " (no joined dimension)";
904+
}
905+
s << " and is extended to new shape ";
906+
auxiliary::write_vec_to_stream(s, newShape) << ".";
907+
return std::runtime_error(s.str());
908+
};
909+
if (joinedDim.has_value() ||
910+
var.ShapeID() == adios2::ShapeID::JoinedArray)
911+
{
912+
if (!joinedDim.has_value())
913+
{
914+
throw make_runtime_error(
915+
"Inconsistent state of variable: Has shape ID "
916+
"JoinedArray, but its shape contains no value "
917+
"adios2::JoinedDim.");
918+
}
919+
if (newShape.at(*joinedDim) != Dataset::JOINED_DIMENSION)
920+
{
921+
throw make_runtime_error(
922+
"Variable was previously configured with a joined "
923+
"dimension, so the new dataset extent must keep the "
924+
"joined dimension on that index.");
925+
}
926+
dims[*joinedDim] = adios2::JoinedDim;
927+
}
928+
else
929+
{
930+
for (auto s : newShape)
931+
{
932+
if (s == Dataset::JOINED_DIMENSION)
933+
{
934+
throw make_runtime_error(
935+
"Variable was not previously configured with a "
936+
"joined dimension, but is now requested to change "
937+
"extent to a joined array.");
938+
}
939+
}
940+
}
941+
891942
var.SetShape(dims);
892943
}
893944

src/RecordComponent.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,12 +312,9 @@ void RecordComponent::flush(
312312
}
313313
else
314314
{
315-
Parameter<Operation::CREATE_DATASET> dCreate;
315+
Parameter<Operation::CREATE_DATASET> dCreate(
316+
rc.m_dataset.value());
316317
dCreate.name = name;
317-
dCreate.extent = getExtent();
318-
dCreate.dtype = getDatatype();
319-
dCreate.options = rc.m_dataset.value().options;
320-
dCreate.joinedDimension = joinedDimension();
321318
IOHandler()->enqueue(IOTask(this, dCreate));
322319
}
323320
}

src/Series.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,8 @@ void Series::flushRankTable()
415415
{
416416
return;
417417
}
418-
Parameter<Operation::CREATE_DATASET> param;
418+
Parameter<Operation::CREATE_DATASET> param(
419+
AbstractParameter::I_dont_want_to_use_joined_dimensions);
419420
param.name = "rankTable";
420421
param.dtype = Datatype::CHAR;
421422
param.extent = {uint64_t(size), uint64_t(maxSize)};

src/backend/BaseRecordComponent.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "openPMD/backend/BaseRecordComponent.hpp"
2222
#include "openPMD/Error.hpp"
2323
#include "openPMD/Iteration.hpp"
24+
#include <optional>
2425

2526
namespace openPMD
2627
{
@@ -75,7 +76,7 @@ std::optional<size_t> BaseRecordComponent::joinedDimension() const
7576
}
7677
else
7778
{
78-
return false;
79+
return std::nullopt;
7980
}
8081
}
8182

0 commit comments

Comments
 (0)