diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp index bd01d63daa3225b2d15cf19a1bc1b450cea6b161..6d5d374ea0236f21b67e0664933743e060ac5e21 100644 --- a/source/adios2/core/IO.cpp +++ b/source/adios2/core/IO.cpp @@ -155,11 +155,10 @@ bool IO::RemoveVariable(const std::string &name) noexcept { \ auto variableMap = GetVariableMap<T>(); \ variableMap.erase(index); \ + isRemoved = true; \ } ADIOS2_FOREACH_TYPE_1ARG(declare_type) #undef declare_type - - isRemoved = true; } if (isRemoved) @@ -170,6 +169,58 @@ bool IO::RemoveVariable(const std::string &name) noexcept return isRemoved; } +void IO::RemoveAllVariables() noexcept +{ + m_Variables.clear(); +#define declare_type(T) GetVariableMap<T>().clear(); + ADIOS2_FOREACH_TYPE_1ARG(declare_type) +#undef declare_type + m_Compound.clear(); +} + +bool IO::RemoveAttribute(const std::string &name) noexcept +{ + bool isRemoved = false; + auto itAttribute = m_Attributes.find(name); + // attribute exists + if (itAttribute != m_Attributes.end()) + { + // first remove the Variable object + const std::string type(itAttribute->second.first); + const unsigned int index(itAttribute->second.second); + + if (type.empty()) + { + // nothing to do + } +#define declare_type(T) \ + else if (type == GetType<T>()) \ + { \ + auto variableMap = GetVariableMap<T>(); \ + variableMap.erase(index); \ + isRemoved = true; \ + } + ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(declare_type) +#undef declare_type + } + + if (isRemoved) + { + m_Attributes.erase(name); + } + + return isRemoved; +} + +void IO::RemoveAllAttributes() noexcept +{ + m_Attributes.clear(); + +#define declare_type(T) GetAttributeMap<T>().clear(); + ADIOS2_FOREACH_ATTRIBUTE_TYPE_1ARG(declare_type) +#undef declare_type +} + std::map<std::string, Params> IO::GetAvailableVariables() noexcept { std::map<std::string, Params> variablesInfo; diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h index b7e75c2cef5b78d674f13ccb6e02593dbe2a626f..4bdc2983eff9f78b570a4794c2bf00a6af34f2ea 100644 --- a/source/adios2/core/IO.h +++ b/source/adios2/core/IO.h @@ -170,13 +170,29 @@ public: Attribute<T> &DefineAttribute(const std::string &name, const T &value); /** - * Removes an existing Variable previously created with DefineVariable - * @param name + * Removes an existing Variable + * @param name unique identifier input * @return true: found and removed variable, false: not found, nothing to * remove */ bool RemoveVariable(const std::string &name) noexcept; + /** Removes all existing variables in current IO object */ + void RemoveAllVariables() noexcept; + + /** + * Removes an existing Attribute. Dangerous function since references and + * pointers can be dangling after this call. + * @param name unique identifier input + * @return true: found and removed attribute, false: not found, nothing to + * remove + */ + bool RemoveAttribute(const std::string &name) noexcept; + + /** Removes all existing attributes in current IO object. Dangerous function + * since references and pointers can be dangling after this call. */ + void RemoveAllAttributes() noexcept; + /** * Map with variables info: key: name, value: type * @return populate map with current variables @@ -192,6 +208,11 @@ public: template <class T> Variable<T> *InquireVariable(const std::string &name) noexcept; + /** + * Returns the type of an existing variable as an string + * @param name input variable name + * @return type + */ std::string InquireVariableType(const std::string &name) const noexcept; /** @@ -372,7 +393,7 @@ private: noexcept; /** Checks if attribute exists, called from DefineAttribute different - * signatures */ + * signatures */ void CheckAttributeCommon(const std::string &name) const; /** diff --git a/testing/adios2/interface/TestADIOSDefineAttribute.cpp b/testing/adios2/interface/TestADIOSDefineAttribute.cpp index 11559beeca9ddcf881e99975d398839b7df0b960..bc1c1563cc0890cf93ef57d077eca4862d08a72d 100644 --- a/testing/adios2/interface/TestADIOSDefineAttribute.cpp +++ b/testing/adios2/interface/TestADIOSDefineAttribute.cpp @@ -540,6 +540,118 @@ TEST_F(ADIOSDefineAttributeTest, GetAttribute) } } +TEST_F(ADIOSDefineAttributeTest, DefineAndRemove) +{ + auto lf_CheckRemove = [&](const std::string variableName) { + + const bool isRemoved = io.RemoveAttribute(variableName); + EXPECT_EQ(isRemoved, true); + }; + + const adios2::Dims shape = {10}; + const adios2::Dims start = {0}; + const adios2::Dims count = {10}; + + io.DefineAttribute<std::string>("iString", "String Attribute"); + io.DefineAttribute<int8_t>("i8", -8); + io.DefineAttribute<int16_t>("i16", -16); + io.DefineAttribute<int32_t>("i32", -32); + io.DefineAttribute<int64_t>("i64", -64); + io.DefineAttribute<uint8_t>("u8", 8); + io.DefineAttribute<uint16_t>("u16", 16); + io.DefineAttribute<uint32_t>("u32", 32); + io.DefineAttribute<uint64_t>("u64", 64); + io.DefineAttribute<float>("r32", 32); + io.DefineAttribute<double>("r64", 64); + + lf_CheckRemove("iString"); + lf_CheckRemove("i8"); + lf_CheckRemove("i16"); + lf_CheckRemove("i32"); + lf_CheckRemove("i64"); + + lf_CheckRemove("u8"); + lf_CheckRemove("u16"); + lf_CheckRemove("u32"); + lf_CheckRemove("u64"); + + lf_CheckRemove("r32"); + lf_CheckRemove("r64"); + + auto attr_iString = io.InquireAttribute<std::string>("iString"); + auto attr_i8 = io.InquireAttribute<int8_t>("i8"); + auto attr_i16 = io.InquireAttribute<int16_t>("i16"); + auto attr_i32 = io.InquireAttribute<int32_t>("i32"); + auto attr_i64 = io.InquireAttribute<int64_t>("i64"); + auto attr_u8 = io.InquireAttribute<uint8_t>("u8"); + auto attr_u16 = io.InquireAttribute<uint16_t>("u16"); + auto attr_u32 = io.InquireAttribute<uint32_t>("u32"); + auto attr_u64 = io.InquireAttribute<uint64_t>("u64"); + auto attr_r32 = io.InquireAttribute<float>("r32"); + auto attr_r64 = io.InquireAttribute<double>("r64"); + + EXPECT_EQ(attr_iString, nullptr); + EXPECT_EQ(attr_i8, nullptr); + EXPECT_EQ(attr_i16, nullptr); + EXPECT_EQ(attr_i32, nullptr); + EXPECT_EQ(attr_i64, nullptr); + + EXPECT_EQ(attr_u8, nullptr); + EXPECT_EQ(attr_u16, nullptr); + EXPECT_EQ(attr_u32, nullptr); + EXPECT_EQ(attr_u64, nullptr); + + EXPECT_EQ(attr_r32, nullptr); + EXPECT_EQ(attr_r64, nullptr); +} + +TEST_F(ADIOSDefineAttributeTest, DefineAndRemoveAll) +{ + const adios2::Dims shape = {10}; + const adios2::Dims start = {0}; + const adios2::Dims count = {10}; + + io.DefineAttribute<std::string>("iString", "String Attribute"); + io.DefineAttribute<int8_t>("i8", -8); + io.DefineAttribute<int16_t>("i16", -16); + io.DefineAttribute<int32_t>("i32", -32); + io.DefineAttribute<int64_t>("i64", -64); + io.DefineAttribute<uint8_t>("u8", 8); + io.DefineAttribute<uint16_t>("u16", 16); + io.DefineAttribute<uint32_t>("u32", 32); + io.DefineAttribute<uint64_t>("u64", 64); + io.DefineAttribute<float>("r32", 32); + io.DefineAttribute<double>("r64", 64); + + io.RemoveAllAttributes(); + + auto attr_iString = io.InquireAttribute<std::string>("iString"); + auto attr_i8 = io.InquireAttribute<int8_t>("i8"); + auto attr_i16 = io.InquireAttribute<int16_t>("i16"); + auto attr_i32 = io.InquireAttribute<int32_t>("i32"); + auto attr_i64 = io.InquireAttribute<int64_t>("i64"); + auto attr_u8 = io.InquireAttribute<uint8_t>("u8"); + auto attr_u16 = io.InquireAttribute<uint16_t>("u16"); + auto attr_u32 = io.InquireAttribute<uint32_t>("u32"); + auto attr_u64 = io.InquireAttribute<uint64_t>("u64"); + auto attr_r32 = io.InquireAttribute<float>("r32"); + auto attr_r64 = io.InquireAttribute<double>("r64"); + + EXPECT_EQ(attr_iString, nullptr); + EXPECT_EQ(attr_i8, nullptr); + EXPECT_EQ(attr_i16, nullptr); + EXPECT_EQ(attr_i32, nullptr); + EXPECT_EQ(attr_i64, nullptr); + + EXPECT_EQ(attr_u8, nullptr); + EXPECT_EQ(attr_u16, nullptr); + EXPECT_EQ(attr_u32, nullptr); + EXPECT_EQ(attr_u64, nullptr); + + EXPECT_EQ(attr_r32, nullptr); + EXPECT_EQ(attr_r64, nullptr); +} + int main(int argc, char **argv) { #ifdef ADIOS2_HAVE_MPI diff --git a/testing/adios2/interface/TestADIOSDefineVariable.cpp b/testing/adios2/interface/TestADIOSDefineVariable.cpp index 4910db51d7a2bba693cb628ca622111fcc008b16..db627facd4da52b4cbd30e19ed383cda939e2326 100644 --- a/testing/adios2/interface/TestADIOSDefineVariable.cpp +++ b/testing/adios2/interface/TestADIOSDefineVariable.cpp @@ -418,6 +418,135 @@ TEST_F(ADIOSDefineVariableTest, DefineString) EXPECT_NO_THROW(io.DefineVariable<std::string>("validString2", {}, {}, {})); } +TEST_F(ADIOSDefineVariableTest, DefineAndRemove) +{ + auto lf_CheckRemove = [&](const std::string variableName) { + + const bool isRemoved = io.RemoveVariable(variableName); + EXPECT_EQ(isRemoved, true); + }; + + const adios2::Dims shape = {10}; + const adios2::Dims start = {0}; + const adios2::Dims count = {10}; + + io.DefineVariable<std::string>("iString"); + io.DefineVariable<int8_t>("i8", shape, start, count); + io.DefineVariable<int16_t>("i16", shape, start, count); + io.DefineVariable<int32_t>("i32", shape, start, count); + io.DefineVariable<int64_t>("i64", shape, start, count); + io.DefineVariable<uint8_t>("u8", shape, start, count); + io.DefineVariable<uint16_t>("u16", shape, start, count); + io.DefineVariable<uint32_t>("u32", shape, start, count); + io.DefineVariable<uint64_t>("u64", shape, start, count); + io.DefineVariable<float>("r32", shape, start, count); + io.DefineVariable<double>("r64", shape, start, count); + io.DefineVariable<std::complex<float>>("c32", shape, start, count); + io.DefineVariable<std::complex<double>>("c64", shape, start, count); + + lf_CheckRemove("iString"); + lf_CheckRemove("i8"); + lf_CheckRemove("i16"); + lf_CheckRemove("i32"); + lf_CheckRemove("i64"); + + lf_CheckRemove("u8"); + lf_CheckRemove("u16"); + lf_CheckRemove("u32"); + lf_CheckRemove("u64"); + + lf_CheckRemove("r32"); + lf_CheckRemove("r64"); + + lf_CheckRemove("c32"); + lf_CheckRemove("c64"); + + auto var_iString = io.InquireVariable<std::string>("iString"); + auto var_i8 = io.InquireVariable<int8_t>("i8"); + auto var_i16 = io.InquireVariable<int16_t>("i16"); + auto var_i32 = io.InquireVariable<int32_t>("i32"); + auto var_i64 = io.InquireVariable<int64_t>("i64"); + auto var_u8 = io.InquireVariable<uint8_t>("u8"); + auto var_u16 = io.InquireVariable<uint16_t>("u16"); + auto var_u32 = io.InquireVariable<uint32_t>("u32"); + auto var_u64 = io.InquireVariable<uint64_t>("u64"); + auto var_r32 = io.InquireVariable<float>("r32"); + auto var_r64 = io.InquireVariable<double>("r64"); + auto var_c32 = io.InquireVariable<std::complex<float>>("c32"); + auto var_c64 = io.InquireVariable<std::complex<double>>("c64"); + + EXPECT_EQ(var_iString, nullptr); + EXPECT_EQ(var_i8, nullptr); + EXPECT_EQ(var_i16, nullptr); + EXPECT_EQ(var_i32, nullptr); + EXPECT_EQ(var_i64, nullptr); + + EXPECT_EQ(var_u8, nullptr); + EXPECT_EQ(var_u16, nullptr); + EXPECT_EQ(var_u32, nullptr); + EXPECT_EQ(var_u64, nullptr); + + EXPECT_EQ(var_r32, nullptr); + EXPECT_EQ(var_r64, nullptr); + + EXPECT_EQ(var_c32, nullptr); + EXPECT_EQ(var_c64, nullptr); +} + +TEST_F(ADIOSDefineVariableTest, DefineAndRemoveAll) +{ + const adios2::Dims shape = {10}; + const adios2::Dims start = {0}; + const adios2::Dims count = {10}; + + io.DefineVariable<std::string>("iString"); + io.DefineVariable<int8_t>("i8", shape, start, count); + io.DefineVariable<int16_t>("i16", shape, start, count); + io.DefineVariable<int32_t>("i32", shape, start, count); + io.DefineVariable<int64_t>("i64", shape, start, count); + io.DefineVariable<uint8_t>("u8", shape, start, count); + io.DefineVariable<uint16_t>("u16", shape, start, count); + io.DefineVariable<uint32_t>("u32", shape, start, count); + io.DefineVariable<uint64_t>("u64", shape, start, count); + io.DefineVariable<float>("r32", shape, start, count); + io.DefineVariable<double>("r64", shape, start, count); + io.DefineVariable<std::complex<float>>("c32", shape, start, count); + io.DefineVariable<std::complex<double>>("c64", shape, start, count); + + io.RemoveAllVariables(); + + auto var_iString = io.InquireVariable<std::string>("iString"); + auto var_i8 = io.InquireVariable<int8_t>("i8"); + auto var_i16 = io.InquireVariable<int16_t>("i16"); + auto var_i32 = io.InquireVariable<int32_t>("i32"); + auto var_i64 = io.InquireVariable<int64_t>("i64"); + auto var_u8 = io.InquireVariable<uint8_t>("u8"); + auto var_u16 = io.InquireVariable<uint16_t>("u16"); + auto var_u32 = io.InquireVariable<uint32_t>("u32"); + auto var_u64 = io.InquireVariable<uint64_t>("u64"); + auto var_r32 = io.InquireVariable<float>("r32"); + auto var_r64 = io.InquireVariable<double>("r64"); + auto var_c32 = io.InquireVariable<std::complex<float>>("c32"); + auto var_c64 = io.InquireVariable<std::complex<double>>("c64"); + + EXPECT_EQ(var_iString, nullptr); + EXPECT_EQ(var_i8, nullptr); + EXPECT_EQ(var_i16, nullptr); + EXPECT_EQ(var_i32, nullptr); + EXPECT_EQ(var_i64, nullptr); + + EXPECT_EQ(var_u8, nullptr); + EXPECT_EQ(var_u16, nullptr); + EXPECT_EQ(var_u32, nullptr); + EXPECT_EQ(var_u64, nullptr); + + EXPECT_EQ(var_r32, nullptr); + EXPECT_EQ(var_r64, nullptr); + + EXPECT_EQ(var_c32, nullptr); + EXPECT_EQ(var_c64, nullptr); +} + int main(int argc, char **argv) { #ifdef ADIOS2_HAVE_MPI