From 4a4375a41c49d981e93cb5ce9d170803babc82b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20P=C3=B6schel?= Date: Mon, 30 Nov 2020 12:36:34 +0100 Subject: [PATCH] Some documentation and disallow shrinking or changing the dimensionality --- include/openPMD/Dataset.hpp | 8 ++++++++ include/openPMD/RecordComponent.hpp | 21 ++++++++++++++++++++- src/Dataset.cpp | 8 ++++++-- src/RecordComponent.cpp | 20 +++++++++++++++++--- test/SerialIOTest.cpp | 19 +++++++++---------- 5 files changed, 60 insertions(+), 16 deletions(-) diff --git a/include/openPMD/Dataset.hpp b/include/openPMD/Dataset.hpp index fa0bca9a00..a2638411f3 100644 --- a/include/openPMD/Dataset.hpp +++ b/include/openPMD/Dataset.hpp @@ -40,6 +40,14 @@ class Dataset public: Dataset(Datatype, Extent); + /** + * @brief Constructor that sets the datatype to undefined. + * + * Helpful for resizing datasets, since datatypes need not be given twice. + * + */ + Dataset( Extent ); + Dataset& extend(Extent newExtent); Dataset& setChunkSize(Extent const&); Dataset& setCompression(std::string const&, uint8_t const); diff --git a/include/openPMD/RecordComponent.hpp b/include/openPMD/RecordComponent.hpp index 1765b2f9ae..f697aca629 100644 --- a/include/openPMD/RecordComponent.hpp +++ b/include/openPMD/RecordComponent.hpp @@ -100,7 +100,26 @@ class RecordComponent : public BaseRecordComponent RecordComponent& setUnitSI(double); - RecordComponent& resetDataset(Dataset); + /** + * @brief Declare the dataset's type and extent. + * + * Calling this again after flushing will require resizing the dataset. + * Support for this depends on the backend. + * Unsupported are: + * * Changing the datatype. + * * Shrinking any dimension's extent. + * * Changing the number of dimensions. + * + * Backend support for resizing datasets: + * * JSON: Supported + * * ADIOS1: Unsupported + * * ADIOS2: (Currently) unsupported + * * HDF5: (Currently) unsupported. + * Will be probably supported as soon as chunking is supported in HDF5. + * + * @return RecordComponent& + */ + RecordComponent & resetDataset( Dataset ); uint8_t getDimensionality() const; Extent getExtent() const; diff --git a/src/Dataset.cpp b/src/Dataset.cpp index 0c8e829576..4958bc23b1 100644 --- a/src/Dataset.cpp +++ b/src/Dataset.cpp @@ -33,8 +33,12 @@ Dataset::Dataset(Datatype d, Extent e) chunkSize{e} { } -Dataset& -Dataset::extend(Extent newExtents) +Dataset::Dataset( Extent e ) : Dataset( Datatype::UNDEFINED, std::move( e ) ) +{ +} + +Dataset & +Dataset::extend( Extent newExtents ) { if( newExtents.size() != rank ) throw std::runtime_error("Dimensionality of extended Dataset must match the original dimensionality"); diff --git a/src/RecordComponent.cpp b/src/RecordComponent.cpp index b3f5d07edc..ca231210d3 100644 --- a/src/RecordComponent.cpp +++ b/src/RecordComponent.cpp @@ -77,7 +77,16 @@ RecordComponent::resetDataset( Dataset d ) else *m_isEmpty = false; - *m_dataset = std::move( d ); + if( written() ) + { + m_dataset->extend( std::move( d.extent ) ); + } + else + { + *m_dataset = std::move( d ); + } + + dirty() = true; return *this; } @@ -141,13 +150,18 @@ RecordComponent::makeEmpty( Dataset d ) throw std::runtime_error( "Cannot change the datatype of a dataset." ); } + m_dataset->extend( std::move( d.extent ) ); *m_hasBeenExtended = true; } - if( d.extent.size() == 0 ) + else + { + *m_dataset = std::move( d ); + } + + if( m_dataset->extent.size() == 0 ) throw std::runtime_error( "Dataset extent must be at least 1D." ); *m_isEmpty = true; - *m_dataset = std::move( d ); dirty() = true; if( !written() ) { diff --git a/test/SerialIOTest.cpp b/test/SerialIOTest.cpp index 7347e7a761..7d2f0d3d89 100644 --- a/test/SerialIOTest.cpp +++ b/test/SerialIOTest.cpp @@ -2924,8 +2924,10 @@ extendDataset( std::string const & ext ) // empty record component -> empty record component // should work + // this does not make a lot of sense since we don't allow shrinking, + // but let's just reset it to itself auto E_z = write.iterations[ 0 ].meshes[ "E" ][ "z" ]; - E_z.makeEmpty< int >( 5 ); + E_z.makeEmpty< int >( 3 ); write.flush(); E_z.makeEmpty< int >( 3 ); @@ -2935,29 +2937,28 @@ extendDataset( std::string const & ext ) // (created by resetDataset) // should work auto E_a = write.iterations[ 0 ].meshes[ "E" ][ "a" ]; - E_a.makeEmpty< int >( 5 ); + E_a.makeEmpty< int >( 3 ); write.flush(); E_a.resetDataset( Dataset( Datatype::UNDEFINED, { 0, 1, 2 } ) ); write.flush(); // constant record component -> empty record component - // should work + // should fail, since this implies shrinking auto E_b = write.iterations[ 0 ].meshes[ "E" ][ "b" ]; E_b.resetDataset( ds1 ); E_b.makeConstant( 10 ); write.flush(); - E_b.makeEmpty< int >( 3 ); - write.flush(); + REQUIRE_THROWS( E_b.makeEmpty< int >( 2 ) ); // empty record component -> constant record component // should work auto E_c = write.iterations[ 0 ].meshes[ "E" ][ "c" ]; - E_c.makeEmpty< int >( 5 ); + E_c.makeEmpty< int >( 3 ); write.flush(); - E_c.resetDataset( Dataset( Datatype::UNDEFINED, { 1, 1, 2 } ) ); + E_c.resetDataset( Dataset( { 1, 1, 2 } ) ); write.flush(); // array record component -> constant record component @@ -3000,9 +3001,7 @@ extendDataset( std::string const & ext ) auto E_a = read.iterations[ 0 ].meshes[ "E" ][ "a" ]; REQUIRE( E_a.getExtent() == Extent{ 0, 1, 2 } ); - auto E_b = read.iterations[ 0 ].meshes[ "E" ][ "b" ]; - REQUIRE( E_b.getExtent() == Extent{ 0, 0, 0 } ); - REQUIRE( E_b.empty() ); + // E_b could not be changed auto E_c = read.iterations[ 0 ].meshes[ "E" ][ "c" ]; REQUIRE( E_c.getExtent() == Extent{ 1, 1, 2 } );