Do refactoring to get rid of using data converters in SMF. The work includes 02 parts:
1) Part #1 (This patch): apply the approach to into the demo application - testing CCB handling (test_ccbhdl.cc). 2) Part #2: apply the approach into SMF code. --- src/smf/Makefile.am | 11 +- .../smfd/imm_modify_config/imm_ccb_handle.cc | 242 +++++++++ .../smfd/imm_modify_config/imm_ccb_handle.h | 491 ++++++++++++++++++ src/smf/smfd/imm_modify_demo/test_ccbhdl.cc | 464 ++++------------- src/smf/smfd/imm_om_ccapi/common/common.h | 7 +- .../smfd/imm_om_ccapi/common/imm_attribute.cc | 35 +- .../smfd/imm_om_ccapi/common/imm_attribute.h | 176 +++---- .../smfd/imm_om_ccapi/common/imm_cpp_type.h | 380 ++++++++++++++ 8 files changed, 1340 insertions(+), 466 deletions(-) create mode 100644 src/smf/smfd/imm_modify_config/imm_ccb_handle.cc create mode 100644 src/smf/smfd/imm_modify_config/imm_ccb_handle.h create mode 100644 src/smf/smfd/imm_om_ccapi/common/imm_cpp_type.h diff --git a/src/smf/Makefile.am b/src/smf/Makefile.am index 5eed2e683..372597866 100644 --- a/src/smf/Makefile.am +++ b/src/smf/Makefile.am @@ -119,11 +119,14 @@ noinst_HEADERS += \ noinst_HEADERS += \ src/smf/smfd/imm_modify_config/attribute.h \ src/smf/smfd/imm_modify_config/add_operation_to_ccb.h \ - src/smf/smfd/imm_modify_config/immccb.h + src/smf/smfd/imm_modify_config/immccb.h \ + src/smf/smfd/imm_modify_config/imm_ccb_handle.h + # IMM OM C++ APIs noinst_HEADERS += \ src/smf/smfd/imm_om_ccapi/common/common.h \ + src/smf/smfd/imm_om_ccapi/common/imm_cpp_type.h \ src/smf/smfd/imm_om_ccapi/common/imm_attribute.h \ src/smf/smfd/imm_om_ccapi/om_admin_owner_clear.h \ src/smf/smfd/imm_om_ccapi/om_admin_owner_handle.h \ @@ -211,7 +214,9 @@ bin_osafsmfd_SOURCES = \ bin_osafsmfd_SOURCES += \ src/smf/smfd/imm_modify_config/attribute.cc \ src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc \ - src/smf/smfd/imm_modify_config/immccb.cc + src/smf/smfd/imm_modify_config/immccb.cc \ + src/smf/smfd/imm_modify_config/imm_ccb_handle.cc + # IMM OM C++ APIs bin_osafsmfd_SOURCES += \ @@ -400,7 +405,7 @@ bin_test_ccbhdl_SOURCES = \ bin_test_ccbhdl_SOURCES += \ src/smf/smfd/imm_modify_config/attribute.cc \ src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc \ - src/smf/smfd/imm_modify_config/immccb.cc + src/smf/smfd/imm_modify_config/imm_ccb_handle.cc # IMM OM C++ APIs bin_test_ccbhdl_SOURCES += \ diff --git a/src/smf/smfd/imm_modify_config/imm_ccb_handle.cc b/src/smf/smfd/imm_modify_config/imm_ccb_handle.cc new file mode 100644 index 000000000..6dcc5cc70 --- /dev/null +++ b/src/smf/smfd/imm_modify_config/imm_ccb_handle.cc @@ -0,0 +1,242 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2008 The OpenSAF Foundation + * Copyright Ericsson AB 2018 - All Rights Reserved. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +#include "smf/smfd/imm_modify_config/imm_ccb_handle.h" +#include "smf/smfd/imm_om_ccapi/common/common.h" + +namespace modelmodify { + +static bool IsResorceAbort(SaImmCcbHandleT ccb_handle) { + TRACE_ENTER(); + bool rc = false; + const SaStringT *err_out = nullptr; + SaAisErrorT ais = saImmOmCcbGetErrorStrings(ccb_handle, &err_out); + if ((ais == SA_AIS_OK) && (err_out != nullptr)) { + LOG_NO("%s: Error string: '%s'", __func__, err_out[0]); + std::string err_str(err_out[0]); + if (err_str.find("IMM: Resource abort: ") != std::string::npos) { + rc = true; + } + } + return rc; +} + +// Judge the state based on the input @ais code only. +static EJobState job_state(SaAisErrorT ais) { + if (ais == SA_AIS_OK) return EJobState::kOk; + bool bad_hdl = (ais == SA_AIS_ERR_BAD_HANDLE); + return bad_hdl ? EJobState::kRestart : EJobState::kFail; +} + +// Judge the state based on both the input @ais and if the +// CCB is aborted with error message "resource is aborted". +static EJobState job_state(SaImmCcbHandleT h, SaAisErrorT ais) { + EJobState state = job_state(ais); + if (ais == SA_AIS_ERR_FAILED_OPERATION) { + state = (IsResorceAbort(h) ? EJobState::kRestart : EJobState::kFail); + } + return state; +} + +// Judge the state based on three inputs: @ais code, and if that code +// is tolerated or not, the last one is if the CCB is aborted with error +// message "resource is aborted" +static EJobState job_state(JobBase* job, SaImmCcbHandleT h, SaAisErrorT ais) { + EJobState state = job_state(h, ais); + assert(job && "invalid pointer"); + if (job->is_ais_code_ignored(ais)) state = EJobState::kOk; + return state; +} + +static EJobState job_state(JobBase* job, SaAisErrorT ais) { + EJobState state = job_state(ais); + assert(job && "invalid pointer"); + if (job->is_ais_code_ignored(ais)) state = EJobState::kOk; + return state; +} + +//============================================================================== +// CcbCreateJob/CcbModifyJob/CcbDeleteJob class +//============================================================================== +ErrInfo CcbCreateJob::DoJob() { + ccb_create_obj_.AddObjectCreateToCcb(); + SaAisErrorT ais = ccb_create_obj_.ais_error(); + return {job_state(this, ccb_handle_, ais), ais, __PRETTY_FUNCTION__}; +} + +ErrInfo CcbModifyJob::DoJob() { + ccb_modify_obj_.AddObjectModifyToCcb(); + SaAisErrorT ais = ccb_modify_obj_.ais_error(); + return {job_state(this, ccb_handle_, ais), ais, __PRETTY_FUNCTION__}; +} + +ErrInfo CcbDeleteJob::DoJob() { + ccb_delete_obj_.AddObjectDeleteToCcb(obj_name_); + SaAisErrorT ais = ccb_delete_obj_.ais_error(); + return {job_state(this, ccb_handle_, ais), ais, __PRETTY_FUNCTION__}; +} + +//============================================================================== +// JobExecutor class +//============================================================================== +ErrInfo JobExecutor::InitializeOmHandle() { + TRACE_ENTER(); + ImmBase::RetryControl RetryTiming; + RetryTiming.interval = base::kFourtyMilliseconds; + RetryTiming.timeout = 60000; + handle_obj_.ChangeDefaultRetryControl(RetryTiming); + bool ret = handle_obj_.InitializeHandle(); + EJobState state = ret ? EJobState::kOk : EJobState::kFail; + return {state, handle_obj_.ais_error(), __PRETTY_FUNCTION__}; +} + +ErrInfo JobExecutor::InitializeAdminOwnerHandle() { + TRACE_ENTER(); + SaImmHandleT om_handle = handle_obj_.GetHandle(); + ao_handle_obj_.ReleaseOwnershipOnFinalize(); + ao_handle_obj_.InitializeHandle(om_handle); + SaAisErrorT ais = ao_handle_obj_.ais_error(); + return {job_state(ais), ais, __PRETTY_FUNCTION__}; +} + +ErrInfo JobExecutor::SetAdminOwner() { + TRACE_ENTER(); + SaImmAdminOwnerHandleT ao_handle = ao_handle_obj_.GetHandle(); + SaImmScopeT scope = SA_IMM_ONE; + SaAisErrorT ais = SA_AIS_OK; + + ao_set_obj_.UpdateHandle(ao_handle); + for (const auto& job : job_list_) { + std::string obj = job->object(); + TRACE("object = %s", obj.c_str()); + if (obj == "") continue; + if (job->job_type() == EJobType::kCcbDelete) { + scope = SA_IMM_SUBTREE; + } + ao_set_obj_.ClearObjectNames(); + ao_set_obj_.AddObjectName(obj); + base::Timer timer(kExistTimeout); + bool ret = false; + while (timer.is_timeout() == false && ret == false) { + ret = ao_set_obj_.SetAdminOwner(scope); + ais = ao_set_obj_.ais_error(); + if (ais == SA_AIS_ERR_EXIST) { + base::Sleep(base::MillisToTimespec(kExistWait)); + continue; + } + break; + } + if (ret == false && job_state(job, ais) != EJobState::kOk) + return {job_state(ais), ais, __PRETTY_FUNCTION__}; + } + return {EJobState::kOk, ais, __PRETTY_FUNCTION__}; +} + +ErrInfo JobExecutor::InitializeCcbHandle() { + TRACE_ENTER(); + SaImmAdminOwnerHandleT ao_handle = ao_handle_obj_.GetHandle(); + ccb_handle_obj_.InitializeHandle(ao_handle); + SaAisErrorT ais = ccb_handle_obj_.ais_error(); + return {job_state(ais), ais, __PRETTY_FUNCTION__}; +} + +ErrInfo JobExecutor::DoJobs() { + TRACE_ENTER(); + ErrInfo info = {EJobState::kOk, SA_AIS_OK, __PRETTY_FUNCTION__}; + for (auto& job : job_list_) { + job->UpdateHandle(ccb_handle_obj_.GetHandle()); + info = job->Execute(); + if (info.result != EJobState::kOk) { + return info; + } + } + return info; +} + +ErrInfo JobExecutor::ApplyCcb() { + TRACE_ENTER(); + ccb_handle_obj_.ApplyCcb(); + SaAisErrorT ais = ccb_handle_obj_.ais_error(); + SaImmCcbHandleT ccb_handle = ccb_handle_obj_.GetHandle(); + return {job_state(ccb_handle, ais), ais, __PRETTY_FUNCTION__}; + +} + +ErrInfo JobExecutor::FinalizeHandles() { + ErrInfo info = {EJobState::kOk, SA_AIS_OK, __PRETTY_FUNCTION__}; + ccb_handle_obj_.FinalizeHandle(); + ao_handle_obj_.FinalizeHandle(); + handle_obj_.FinalizeHandle(); + return info; +} + +bool JobExecutor::Execute() { + TRACE_ENTER(); + uint64_t timeout = 120000; + base::Timer timer{timeout}; + bool ret = false; + ErrInfo info; + // Keep below elements in the right order is important. + using PreExeMethods = ErrInfo (JobExecutor::*)(); + PreExeMethods methods[] = { + // Pre-processings (setup handles) + &JobExecutor::InitializeOmHandle, + &JobExecutor::InitializeAdminOwnerHandle, + &JobExecutor::InitializeCcbHandle, + &JobExecutor::SetAdminOwner, + // Do jobs + &JobExecutor::DoJobs, + // Post-processing (commit) + &JobExecutor::ApplyCcb + }; + + while (timer.is_timeout() == false) { + FinalizeHandles(); + + bool restart = false, stop = false; + for (auto& f : methods) { + info = (this->*f)(); + if (info.result == EJobState::kFail) { + LOG_NO("Failed at the function: %s, reason: %s", + info.at.c_str(), saf_error(info.ais)); + stop = true; + break; + } else if (info.result == EJobState::kRestart) { + TRACE("Restart the CCB. Fail at %s, reason: %s", + info.at.c_str(), saf_error(info.ais)); + restart = true; + break; + } + } + + if (stop) break; + if (restart) continue; + + ret = true; + break; + } + + // All handles are just released when JobExecutor object is destroyed + // or run out of its scope. This make JobExecutor reusable + + // FinalizeHandles(); + error_info_ = info; + return ret; +} + +} // namespace modelmodify diff --git a/src/smf/smfd/imm_modify_config/imm_ccb_handle.h b/src/smf/smfd/imm_modify_config/imm_ccb_handle.h new file mode 100644 index 000000000..1f7e793a7 --- /dev/null +++ b/src/smf/smfd/imm_modify_config/imm_ccb_handle.h @@ -0,0 +1,491 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2008 The OpenSAF Foundation + * Copyright Ericsson AB 2018 - All Rights Reserved. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +#ifndef SMF_SMFD_IMM_MODIFY_CONFIG_IMM_CCB_HANDLE_H_ +#define SMF_SMFD_IMM_MODIFY_CONFIG_IMM_CCB_HANDLE_H_ + +#include <string> +#include <vector> +#include <set> + +#include "ais/include/saImm.h" +#include "ais/include/saAis.h" + +#include "smf/smfd/imm_om_ccapi/om_handle.h" +#include "smf/smfd/imm_om_ccapi/om_admin_owner_handle.h" +#include "smf/smfd/imm_om_ccapi/om_ccb_handle.h" +#include "smf/smfd/imm_om_ccapi/om_ccb_object_create.h" +#include "smf/smfd/imm_om_ccapi/om_ccb_object_modify.h" +#include "smf/smfd/imm_om_ccapi/om_ccb_object_delete.h" +#include "smf/smfd/imm_om_ccapi/om_admin_owner_set.h" + +// Last input of JobExecutor constructor +enum EJobMode { + // CCB is only allowed if IMM obj(s) has OI(s) attached to. + kOiRequired = 0, + // Allow CCB to proceed despite missing OIs + kNoOiRequired, + // Allow if there is no OI attached + kOiRequiredIfAny +}; + +// First input of CcbModifyJob::SetAttributeValue() +enum EModifyType { + // Same as SA_IMM_ATTR_VALUES_ADD + kReplace = 0, + // Same as SA_IMM_ATTR_VALUES_DELETE + kDelete, + // Same as SA_IMM_ATTR_VALUES_ADD + kAdd +}; + +namespace modelmodify { + +const uint64_t kExistTimeout = 30000; // 30 sec +const uint64_t kExistWait = 2000; // 2 sec + +enum EJobState { + // No error happens or err is tolerated. It is ok to continue. + kOk, + // CCB is aborted and able to restart. + kRestart, + // CCB is aborted and unable to restart. + kFail +}; + +struct ErrInfo { + EJobState result; + SaAisErrorT ais; + std::string at; +}; + +// Job types: CCB create, CCB modify, or CCB delete +enum EJobType { + kCcbCreate = 0, + kCcbModify, + kCcbDelete, + kUnknown +}; + +//============================================================================== +// JobBase class +//============================================================================== +class JobBase { + public: + virtual ~JobBase() {} + + ErrInfo Execute() { return DoJob(); } + + // To give list of ais codes to be ignored (considered as SA_AIS_OK) + void ignore_ais_code(const std::vector<SaAisErrorT>& ignore_list) { + ignore_list_ = ignore_list; + } + + void ignore_ais_code(SaAisErrorT ignore_ais) { + ignore_list_.push_back(ignore_ais); + } + + bool is_ais_code_ignored(SaAisErrorT ais) { + for (auto code : ignore_list_) { + if (code == ais) return true; + } + return false; + } + + virtual void UpdateHandle(const SaImmCcbHandleT& ccb_handle) = 0; + virtual const std::string& object() const = 0; + virtual EJobType job_type() const = 0; + + protected: + JobBase() : ignore_list_{} {} + + private: + virtual ErrInfo DoJob() = 0; + std::vector<SaAisErrorT> ignore_list_; +}; + +//============================================================================== +// CcbCreateJob class represents IMM object creation job. +// +// Example of seting up the job: +// CcbCreateJob create_job{"TestClass"}; +// create_job.SetParentName("a=b"); +// create_job.SetAttributeValue("dn", &dn_obj); +// create_job.SetAttributeValue("uint32_attr", &uint32_value); +// create_job.SetAttributeValue<SaUint64T>("multi_uint64", {1, 2, 3}); +//============================================================================== +class CcbCreateJob : public JobBase { + public: + explicit CcbCreateJob(const std::string& class_name) + : parent_dn_{} + , ccb_create_obj_{0} { + ccb_create_obj_.SetClassName(class_name); + } + + ~CcbCreateJob() {} + + void UpdateHandle(const SaImmCcbHandleT& ccb_handle) { + ccb_handle_ = ccb_handle; + ccb_create_obj_.UpdateHandle(ccb_handle); + } + + CcbCreateJob& SetParentName(const std::string& parent) { + ccb_create_obj_.SetParentName(parent); + parent_dn_ = parent; + return *this; + } + + // Two way of giving attribute value to an attribute name: + // 1) Pass pointer to lvalue(s). + // E.g: std::string value{"hello"}; + // SetAttributeValue("Attr1", &value); + + // 2) Pass rvalue(s) + // E.g: SetAttributeValue<SaUint32T>("uint32tattr", 10); + template <typename T> + CcbCreateJob& SetAttributeValue(const std::string& name, + T* ptr_to_value = nullptr); + template <typename T> + CcbCreateJob& SetAttributeValue(const std::string& name, + const std::vector<T*>& ptr_to_values); + template <typename T> + CcbCreateJob& SetAttributeValue(const std::string& name, T value); + + template <typename T> + CcbCreateJob& SetAttributeValue(const std::string& name, + const std::vector<T>& values); + + const std::string& object() const { return parent_dn_; } + EJobType job_type() const { return EJobType::kCcbCreate; } + + private: + ErrInfo DoJob(); + + std::string parent_dn_; + SaImmCcbHandleT ccb_handle_; + immom::ImmOmCcbObjectCreate ccb_create_obj_; +}; + +//============================================================================== +// CcbModifyJob class represents IMM object modification job. +// +// Example of seting up the job: +// CcbModifyJob modify_job{"obj=dn"}; +// modify_job.SetAttributeValue(EModifytype::kAdd, "uint32_attr", &uint32_attr); +// modify_job.SetAttributeValue(EModifytype::kDelete, "str_attr", &str_value); +//============================================================================== +class CcbModifyJob : public JobBase { + public: + explicit CcbModifyJob(const std::string& obj_name) + : obj_name_{obj_name} + , ccb_handle_{0} + , ccb_modify_obj_{0, obj_name} {} + ~CcbModifyJob() {} + + void UpdateHandle(const SaImmCcbHandleT& ccb_handle) { + ccb_handle_ = ccb_handle; + ccb_modify_obj_.UpdateHandle(ccb_handle); + } + + template <typename T> + CcbModifyJob& SetAttributeValue(EModifyType modify_type, + const std::string& name, + T* ptr_to_value); + template <typename T> + CcbModifyJob& SetAttributeValue(EModifyType modify_type, + const std::string& name, + const std::vector<T*>& ptr_to_values); + + template <typename T> + CcbModifyJob& SetAttributeValue(EModifyType modify_type, + const std::string& name, + T value); + template <typename T> + CcbModifyJob& SetAttributeValue(EModifyType modify_type, + const std::string& name, + const std::vector<T>& values); + const std::string& object() const { return obj_name_; } + EJobType job_type() const { return EJobType::kCcbModify; } + + private: + ErrInfo DoJob(); + + std::string obj_name_; + SaImmCcbHandleT ccb_handle_; + immom::ImmOmCcbObjectModify ccb_modify_obj_; +}; + +//============================================================================== +// CcbDeleteJob class represents IMM object deletion job. +// +// Example of seting up the job: +// CcbDeleteJob delete_job{"obj=dn"}; +//============================================================================== +class CcbDeleteJob : public JobBase { + public: + explicit CcbDeleteJob(const std::string& obj_name) + : obj_name_{obj_name} + , ccb_handle_{0} + , ccb_delete_obj_{0} {} + ~CcbDeleteJob() {} + + void UpdateHandle(const SaImmCcbHandleT& ccb_handle) { + ccb_handle_ = ccb_handle; + ccb_delete_obj_.UpdateHandle(ccb_handle); + } + + const std::string& object() const { return obj_name_; } + EJobType job_type() const { return EJobType::kCcbDelete; } + + private: + ErrInfo DoJob(); + + std::string obj_name_; + SaImmCcbHandleT ccb_handle_; + immom::ImmOmCcbObjectDelete ccb_delete_obj_; +}; + +//============================================================================== +// JobExecutor is used to execute all added-in jobs. +// +// Usage: +// JobExecutor jobex{"AdminOwnerName", EJobMode::kNoOiRequired} +// jobex.AddJob(&create_job); +// jobex.AddJob(&delete_Job); +// jobex.AddJob(&modify_job); +// if (jobex.Execute() == true) { +// CCB is committed +// } else { +// CCB is aborted. +// } +// +// jobex.ClearJobs().AddJobs({&job1, &job2, job3}); +// jobex.Execute(); +//============================================================================== +class JobExecutor { + public: + // @name: admin owner name for all added-in jobs + // @mode: refer to @JobMode + explicit JobExecutor(const std::string& name, EJobMode mode) + : ccb_flags_{to_ccb_flag(mode)} + , handle_obj_{} + , ao_handle_obj_{0, name} + , ao_set_obj_{0} + , ccb_handle_obj_{0, ccb_flags_} + , job_list_{} {} + + ~JobExecutor() { FinalizeHandles(); } + + // Add job (create/modify/delete) one by one or list of jobs. + JobExecutor& AddJob(JobBase* job) { + job_list_.push_back(job); + return *this; + } + + JobExecutor& AddJobs(const std::vector<JobBase*>& job_list) { + job_list_ = job_list; + return *this; + } + + ErrInfo error_info() { return error_info_; } + + JobExecutor& ClearJobs() { + job_list_.clear(); + return *this; + } + + // Execute all added-in jobs. Return true if all jobs are committed, + // false otherwise. Call error_info() to get error information. + bool Execute(); + + private: + ErrInfo InitializeOmHandle(); + ErrInfo InitializeCcbHandle(); + ErrInfo InitializeAdminOwnerHandle(); + ErrInfo SetAdminOwner(); + ErrInfo DoJobs(); + ErrInfo ApplyCcb(); + ErrInfo FinalizeHandles(); + SaImmCcbFlagsT to_ccb_flag(EJobMode mode) { + if (mode == EJobMode::kOiRequired) { + return SA_IMM_CCB_REGISTERED_OI; + } else if (mode == EJobMode::kNoOiRequired) { + return 0; + } else { + return SA_IMM_CCB_REGISTERED_OI | SA_IMM_CCB_ALLOW_NULL_OI; + } + } + SaImmCcbFlagsT ccb_flags_; + immom::ImmOmHandle handle_obj_; + immom::ImmOmAdminOwnerHandle ao_handle_obj_; + immom::ImmOmAdminOwnerSet ao_set_obj_; + immom::ImmOmCcbHandle ccb_handle_obj_; + ErrInfo error_info_; + std::vector<JobBase*> job_list_; +}; + +template <typename T> +CcbCreateJob& CcbCreateJob::SetAttributeValue(const std::string& name, + T* ptr_to_value) { + ccb_create_obj_.SetAttributeValue(name, ptr_to_value); + return *this; +} + +template <typename T> +CcbCreateJob& CcbCreateJob::SetAttributeValue( + const std::string& name, + const std::vector<T*>& ptr_to_values) { + ccb_create_obj_.SetAttributeValue(name, ptr_to_values); + return *this; +} + +template <typename T> +CcbCreateJob& CcbCreateJob::SetAttributeValue(const std::string& name, + T value) { + T tmp = value; + ccb_create_obj_.SetAttributeValue(name, &tmp); + return *this; +} + +template <typename T> +CcbCreateJob& CcbCreateJob::SetAttributeValue(const std::string& name, + const std::vector<T>& values) { + T tmp[values.size()]; + std::vector<T*> ptr_to_values; + + int i = 0; + for (const auto& v : values) { + tmp[i] = v; + ptr_to_values.push_back(&tmp[i]); + i++; + } + + ccb_create_obj_.SetAttributeValue(name, ptr_to_values); + return *this; +} + +template <typename T> +CcbModifyJob& CcbModifyJob::SetAttributeValue( + EModifyType modify_type, + const std::string& name, + T* ptr_to_value) { + switch (modify_type) { + case EModifyType::kReplace: + ccb_modify_obj_.ReplaceAttributeValue(name, ptr_to_value); + break; + + case EModifyType::kDelete: + ccb_modify_obj_.DeleteAttributeValue(name, ptr_to_value); + break; + + case EModifyType::kAdd: + ccb_modify_obj_.AddAttributeValue(name, ptr_to_value); + break; + + default: + assert(0 && "Unknown Modify type"); + } + return *this; +} + +template <typename T> +CcbModifyJob& CcbModifyJob::SetAttributeValue( + EModifyType modify_type, + const std::string& name, + const std::vector<T*>& ptr_to_values) { + switch (modify_type) { + case EModifyType::kReplace: + ccb_modify_obj_.ReplaceAttributeValue(name, ptr_to_values); + break; + + case EModifyType::kDelete: + ccb_modify_obj_.DeleteAttributeValue(name, ptr_to_values); + break; + + case EModifyType::kAdd: + ccb_modify_obj_.AddAttributeValue(name, ptr_to_values); + break; + + default: + assert(0 && "Unknown Modify type"); + } + return *this; +} + +template <typename T> +CcbModifyJob& CcbModifyJob::SetAttributeValue( + EModifyType modify_type, + const std::string& name, + T value) { + T tmp = value; + switch (modify_type) { + case EModifyType::kReplace: + ccb_modify_obj_.ReplaceAttributeValue(name, &tmp); + break; + + case EModifyType::kDelete: + ccb_modify_obj_.DeleteAttributeValue(name, &tmp); + break; + + case EModifyType::kAdd: + ccb_modify_obj_.AddAttributeValue(name, &tmp); + break; + + default: + assert(0 && "Unknown Modify type"); + } + return *this; +} + +template <typename T> +CcbModifyJob& CcbModifyJob::SetAttributeValue( + EModifyType modify_type, + const std::string& name, + const std::vector<T>& values) { + T tmp[values.size()]; + std::vector<T*> ptr_to_values; + + int i = 0; + for (const auto& v : values) { + tmp[i] = v; + ptr_to_values.push_back(&tmp[i]); + i++; + } + + switch (modify_type) { + case EModifyType::kReplace: + ccb_modify_obj_.ReplaceAttributeValue(name, ptr_to_values); + break; + + case EModifyType::kDelete: + ccb_modify_obj_.DeleteAttributeValue(name, ptr_to_values); + break; + + case EModifyType::kAdd: + ccb_modify_obj_.AddAttributeValue(name, ptr_to_values); + break; + + default: + assert(0 && "Unknown Modify type"); + } + return *this; +} + +} // namespace modelmodify + +#endif diff --git a/src/smf/smfd/imm_modify_demo/test_ccbhdl.cc b/src/smf/smfd/imm_modify_demo/test_ccbhdl.cc index 727953edd..f13f34738 100644 --- a/src/smf/smfd/imm_modify_demo/test_ccbhdl.cc +++ b/src/smf/smfd/imm_modify_demo/test_ccbhdl.cc @@ -23,7 +23,7 @@ #include <memory> #include <utility> #include <iostream> - +#include <algorithm> #include "ais/include/saImm.h" #include "ais/include/saAis.h" #include "base/osaf_extended_name.h" @@ -32,7 +32,7 @@ #include "smf/smfd/imm_modify_demo/common.h" -#include "smf/smfd/imm_modify_config/immccb.h" +#include "smf/smfd/imm_modify_config/imm_ccb_handle.h" #include "smf/smfd/imm_om_ccapi/common/common.h" #include "smf/smfd/imm_om_ccapi/om_admin_owner_clear.h" @@ -56,101 +56,40 @@ using namespace std; void CreateOneObject(void) { // Create an object description // ============================ - modelmodify::AttributeDescriptor attribute; - modelmodify::CreateDescriptor imm_object; + modelmodify::CcbCreateJob imm_object {"ImmTestValuesConfig"}; std::string object_name = "Test1=1"; + SaNameT a_name, a_name2, a_name3; + + imm_object.SetParentName("safApp=safSmfService"); + imm_object.SetAttributeValue("immTestValuesCfg", &object_name); + imm_object.SetAttributeValue<SaUint32T>("SaUint32TValues", {1, 2}); + imm_object.SetAttributeValue<SaInt32T>("SaInt32TValues", {3, 4}); - // Define the object - // ----------------- - imm_object.class_name = "ImmTestValuesConfig"; - imm_object.parent_name = "safApp=safSmfService"; - // Set IMM Object name - attribute.attribute_name = "immTestValuesCfg"; - attribute.value_type = SA_IMM_ATTR_SASTRINGT; - attribute.AddValue(object_name); - imm_object.AddAttribute(attribute); - - // Set some attributes - // ------------------- - - // SA_UINT32_T multi-value attribute - attribute.attribute_name = "SaUint32TValues"; - attribute.value_type = SA_IMM_ATTR_SAUINT32T; - // We are reusing so remove "old" values and add new ones - attribute.values_as_strings.clear(); - attribute.AddValue(std::to_string(1)); - attribute.AddValue(std::to_string(2)); - // Add the attribute to the object - imm_object.AddAttribute(attribute); - - // SA_INT32_T multi-value attribute - attribute.attribute_name = "SaInt32TValues"; - attribute.value_type = SA_IMM_ATTR_SAINT32T; - attribute.values_as_strings.clear(); - attribute.AddValue(std::to_string(3)); - attribute.AddValue(std::to_string(4)); - // Add the attribute to the object - imm_object.AddAttribute(attribute); - - // SA_NAME_T multi-value attribute - SaNameT a_name; - attribute.attribute_name = "SaNameTValues"; - attribute.value_type = SA_IMM_ATTR_SANAMET; - attribute.values_as_strings.clear(); - // Add two short names osaf_extended_name_lend("a_name1", &a_name); - attribute.AddValue(modelmodify::SaNametToString(&a_name)); - osaf_extended_name_lend("a_name2", &a_name); - attribute.AddValue(modelmodify::SaNametToString(&a_name)); + osaf_extended_name_lend("a_name2", &a_name2); // Add a long name and a third short name char long_name[300]; - for (size_t i = 0; i < 299; i++) { - long_name[i] = 'a'; - } + memset(long_name, 'a', 299); long_name[299] = '\0'; - osaf_extended_name_lend(long_name, &a_name); - attribute.AddValue(modelmodify::SaNametToString(&a_name)); - osaf_extended_name_lend("a_name3", &a_name); - attribute.AddValue(modelmodify::SaNametToString(&a_name)); - imm_object.AddAttribute(attribute); + osaf_extended_name_lend(long_name, &a_name3); + std::vector<SaNameT*> names = {&a_name, &a_name2, &a_name3}; + //imm_object.SetAttributeValue("SaNameTValues", {&a_name, &a_name2, &a_name3}); + imm_object.SetAttributeValue("SaNameTValues", names); // SA_UINT32_T single-value attribute - attribute.attribute_name = "SaUint32TValue"; - attribute.value_type = SA_IMM_ATTR_SAUINT32T; - attribute.values_as_strings.clear(); - // Note: Single value attribute so only one value can be added - attribute.AddValue(std::to_string(10)); - imm_object.AddAttribute(attribute); - - // Create a CCB descriptor and add the description of the object to create - // ======================================================================= - modelmodify::CcbDescriptor CcbDescriptor; - - CcbDescriptor.AddCreate(imm_object); - - // Create a modification handler and use it to create the object as defined - // above - // ======================================================================== - - modelmodify::ModelModification ModelModifier; + imm_object.SetAttributeValue<SaUint32T>("SaUint32TValue", 10); - // Set CCB flag to inform IMM that there is no Object Implementer - ModelModifier.SetCcbFlags(0); + modelmodify::JobExecutor jobs{"Testing", EJobMode::kNoOiRequired}; + jobs.AddJob(&imm_object); // Create the IMM object - if (ModelModifier.DoModelModification(CcbDescriptor) == false) { + if (jobs.Execute() == false) { cout << "Creation of '" << object_name << "' FAIL" << endl; } else { cout << "Creation of '" << object_name << "' SUCCESS" << endl; } } -// Remove all modifications from a CCB descriptor so it can be reused -void CcbDescriptorCleaner(modelmodify::CcbDescriptor& ccb_descriptor) { - ccb_descriptor.create_descriptors.clear(); - ccb_descriptor.delete_descriptors.clear(); - ccb_descriptor.modify_descriptors.clear(); -} // Fill in a create descriptor. // The created object will be given the name in 'object_name' @@ -159,43 +98,17 @@ void CcbDescriptorCleaner(modelmodify::CcbDescriptor& ccb_descriptor) { // SaInt32TValues: 1, 2, 3 // SaUint64TValues: 100, 200 // SaTimeTValues: 10000 -void SetupObjectCreate1(const std::string object_name, - modelmodify::CreateDescriptor& create_desc) { - modelmodify::AttributeDescriptor attribute; - // Prepare the create descriptor - create_desc.class_name = "ImmTestValuesConfig"; - create_desc.parent_name = "safApp=safSmfService"; - create_desc.attributes.clear(); - - // Set object name - attribute.attribute_name = "immTestValuesCfg"; - attribute.value_type = SA_IMM_ATTR_SASTRINGT; - attribute.AddValue(object_name); - create_desc.AddAttribute(attribute); - - // Set SaInt32TValues - attribute.values_as_strings.clear(); - attribute.attribute_name = "SaInt32TValues"; - attribute.value_type = SA_IMM_ATTR_SAINT32T; - attribute.AddValue(std::to_string(1)); - attribute.AddValue(std::to_string(2)); - attribute.AddValue(std::to_string(3)); - create_desc.AddAttribute(attribute); - - // Set SaUint64TValues - attribute.values_as_strings.clear(); - attribute.attribute_name = "SaUint64TValues"; - attribute.value_type = SA_IMM_ATTR_SAUINT64T; - attribute.AddValue(std::to_string(100)); - attribute.AddValue(std::to_string(200)); - create_desc.AddAttribute(attribute); - - // Set SaTimeTValues - attribute.values_as_strings.clear(); - attribute.attribute_name = "SaTimeTValues"; - attribute.value_type = SA_IMM_ATTR_SATIMET; - attribute.AddValue(std::to_string(10000)); - create_desc.AddAttribute(attribute); + +void SetupObjectCreate1(const std::string& object_name, + modelmodify::CcbCreateJob& create_job) { + std::string obj_name = object_name; + create_job.SetParentName("safApp=safSmfService"); + create_job.SetAttributeValue("immTestValuesCfg", &obj_name); + create_job.SetAttributeValue<SaInt32T>("SaInt32TValues", {1, 2, 3}); + create_job.SetAttributeValue<SaUint64T>("SaUint64TValues", {100, 200}); + CppSaTimeT value = 10000; + std::vector<CppSaTimeT*> times{&value}; + create_job.SetAttributeValue<CppSaTimeT>("SaTimeTValues", times); } void WaitForUserAction(const std::string& message) { @@ -230,7 +143,7 @@ int main() { // Prepare/enable extended name // ---------------------------- setenv("SA_ENABLE_EXTENDED_NAMES", "1", 1); - + if (EnableImmLongDn() == false) return -1; // Note: Long DN must be configured in IMM configuration object before @@ -250,31 +163,15 @@ int main() { // Wait for the user to verify in another node and press Enter in this node WaitForUserAction("Verify creation of Test1=1,safApp=safSmfService"); - // Create a modifier to be used here in main() and set CCB flag to handle - // that there is no Object Implementer for objects handled here - // ---------------------------------------------------------------------- - modelmodify::ModelModification modifier; - modifier.SetCcbFlags(0); - // A CCB descriptor for the modifier - modelmodify::CcbDescriptor ccb_descriptor; - - // We also need some model modification descriptors - modelmodify::CreateDescriptor create_descriptor; - modelmodify::ModifyDescriptor modify_descriptor; - modelmodify::DeleteDescriptor delete_descriptor; - // an attribute modify descriptor - modelmodify::AttributeDescriptor attribute_descriptor; - // and an attribute modify descriptor - modelmodify::AttributeModifyDescriptor attribute_modify_descriptor; - - // Create and apply a CCB that creates two more objects - // ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ - - SetupObjectCreate1("Test1=2", create_descriptor); - ccb_descriptor.AddCreate(create_descriptor); - SetupObjectCreate1("Test1=3", create_descriptor); - ccb_descriptor.AddCreate(create_descriptor); - if (modifier.DoModelModification(ccb_descriptor) == false) { + modelmodify::CcbCreateJob create_job2("ImmTestValuesConfig"); + modelmodify::CcbCreateJob create_job3("ImmTestValuesConfig"); + SetupObjectCreate1("Test1=2", create_job2); + SetupObjectCreate1("Test1=3", create_job3); + + modelmodify::JobExecutor jobs("Testing2", EJobMode::kNoOiRequired); + jobs.AddJob(&create_job2).AddJob(&create_job3); + + if (jobs.Execute() == false) { cout << "Create two more objects in the same CCB, FAIL" << endl; } else { cout << "Create two more objects in the same CCB, SUCCESS" << endl; @@ -295,61 +192,31 @@ int main() { // Replace SaInt32TValues 3 and 4 with 5, 6, 7 // All is done in the same CCB - // We are reusing the CCB descriptor so: - // Clean the CCB descriptor from the previous object creation - CcbDescriptorCleaner(ccb_descriptor); - // Add a new object to the CBB. The new object is created within a function // that uses an attribute descriptor that is local to this function. This will // test that data is correctly handed over to the create descriptor - SetupObjectCreate1("Test1=4", create_descriptor); - ccb_descriptor.AddCreate(create_descriptor); + modelmodify::CcbCreateJob create_job4("ImmTestValuesConfig"); + SetupObjectCreate1("Test1=4", create_job4); // Add two objects deletions - delete_descriptor.object_name = "Test1=2,safApp=safSmfService"; - ccb_descriptor.AddDelete(delete_descriptor); - delete_descriptor.object_name = "Test1=3,safApp=safSmfService"; - ccb_descriptor.AddDelete(delete_descriptor); + modelmodify::CcbDeleteJob delete_job2("Test1=2,safApp=safSmfService"); + modelmodify::CcbDeleteJob delete_job3("Test1=3,safApp=safSmfService"); // Setup the modifications for the "test1=1" object: - modify_descriptor.object_name = "Test1=1,safApp=safSmfService"; - // Add a value to SaUint32TValues - // Clean attribute descriptor from any possible previous usage - attribute_descriptor.values_as_strings.clear(); - attribute_descriptor.attribute_name = "SaUint32TValues"; - attribute_descriptor.value_type = SA_IMM_ATTR_SAUINT32T; - attribute_descriptor.AddValue(std::to_string(4)); - attribute_modify_descriptor.modification_type = SA_IMM_ATTR_VALUES_ADD; - attribute_modify_descriptor.attribute_descriptor = attribute_descriptor; - modify_descriptor.AddAttributeModification(attribute_modify_descriptor); - // Delete a value from SaNameTValues - attribute_descriptor.values_as_strings.clear(); SaNameT a_name; // Use a real SaNameT osaf_extended_name_lend("a_name1", &a_name); - attribute_descriptor.attribute_name = "SaNameTValues"; - attribute_descriptor.value_type = SA_IMM_ATTR_SANAMET; - attribute_descriptor.AddValue(modelmodify::SaNametToString(&a_name)); - attribute_modify_descriptor.modification_type = SA_IMM_ATTR_VALUES_DELETE; - attribute_modify_descriptor.attribute_descriptor = attribute_descriptor; - modify_descriptor.AddAttributeModification(attribute_modify_descriptor); - // Replace the values in SaInt32TValues - attribute_descriptor.attribute_name = "SaInt32TValues"; - attribute_descriptor.value_type = SA_IMM_ATTR_SAINT32T; - attribute_descriptor.values_as_strings.clear(); - attribute_descriptor.AddValue(std::to_string(5)); - attribute_descriptor.AddValue(std::to_string(6)); - attribute_descriptor.AddValue(std::to_string(7)); - attribute_modify_descriptor.modification_type = SA_IMM_ATTR_VALUES_REPLACE; - attribute_modify_descriptor.attribute_descriptor = attribute_descriptor; - modify_descriptor.AddAttributeModification(attribute_modify_descriptor); - - // Add the modifications to the CCB - ccb_descriptor.AddModify(modify_descriptor); + modelmodify::CcbModifyJob modify_job1("Test1=1,safApp=safSmfService"); + + modify_job1.SetAttributeValue<SaUint32T>(EModifyType::kAdd, "SaUint32TValues", 4); + modify_job1.SetAttributeValue(EModifyType::kDelete, "SaNameTValues", &a_name); + modify_job1.SetAttributeValue<SaInt32T>(EModifyType::kReplace, "SaInt32TValues", {5, 6, 7}); + + jobs.ClearJobs().AddJobs({&create_job4, &delete_job2, &delete_job3, &modify_job1}); cout << "Modify the model using a mixed CCB START" << endl; // The modifier object is used here for the second time - if (modifier.DoModelModification(ccb_descriptor) == false) { + if (jobs.Execute() == false) { cout << "Modify the model using a mixed CCB, FAIL" << endl; } else { cout << "Modify the model using a mixed CCB, SUCCESS" << endl; @@ -371,14 +238,12 @@ int main() { cout << "Cleanup by deleting the remaining Test1=1 and Test1=4 objects" << endl; - CcbDescriptorCleaner(ccb_descriptor); - delete_descriptor.object_name = "Test1=1,safApp=safSmfService"; - ccb_descriptor.AddDelete(delete_descriptor); - delete_descriptor.object_name = "Test1=4,safApp=safSmfService"; - ccb_descriptor.AddDelete(delete_descriptor); + modelmodify::CcbDeleteJob delete_job1("Test1=1,safApp=safSmfService"); + modelmodify::CcbDeleteJob delete_job4("Test1=4,safApp=safSmfService"); + jobs.ClearJobs().AddJob(&delete_job1).AddJob(&delete_job4); // The modifier object is used here for the third time - if (modifier.DoModelModification(ccb_descriptor) == false) { + if (jobs.Execute() == false) { cout << "Delete Test1=1 and Test1=4, FAIL" << endl; } else { cout << "Delete Test1=1 and Test1=4, SUCCESS" << endl; @@ -391,114 +256,47 @@ int main() { // value_type. Use SA_IMM_ATTR_SAUINT32T where SA_IMM_ATTR_SASTRINGT is the // correct type. The modification shall fail but there should not cause any // crash e.g. segv - // Create an object description - // ============================ - // Reuse the create descriptor - create_descriptor.attributes.clear(); - std::string object_name = "Test12=1"; // Define the object // ----------------- - create_descriptor.class_name = "ImmTestValuesConfig"; - create_descriptor.parent_name = "safApp=safSmfService"; - // Set IMM Object name - attribute_descriptor.attribute_name = "immTestValuesCfg"; - attribute_descriptor.value_type = SA_IMM_ATTR_SASTRINGT; - // We are reusing so remove "old" values and add new ones - attribute_descriptor.values_as_strings.clear(); - attribute_descriptor.AddValue(object_name); - create_descriptor.AddAttribute(attribute_descriptor); - - // Set some attribute_descriptors - // ------------------- - - // SA_UINT32_T multi-value attribute_descriptor - attribute_descriptor.attribute_name = "SaUint32TValues"; - attribute_descriptor.value_type = SA_IMM_ATTR_SAUINT32T; - attribute_descriptor.values_as_strings.clear(); - attribute_descriptor.AddValue(std::to_string(1)); - attribute_descriptor.AddValue(std::to_string(2)); - // Add the attribute_descriptor to the object - create_descriptor.AddAttribute(attribute_descriptor); - - // SA_INT32_T multi-value attribute_descriptor - attribute_descriptor.attribute_name = "SaInt32TValues"; - attribute_descriptor.value_type = SA_IMM_ATTR_SAINT32T; - attribute_descriptor.values_as_strings.clear(); - attribute_descriptor.AddValue(std::to_string(3)); - attribute_descriptor.AddValue(std::to_string(4)); - // Add the attribute_descriptor to the object - create_descriptor.AddAttribute(attribute_descriptor); - - // SA_NAME_T multi-value attribute_descriptor - SaNameT a_name1; - attribute_descriptor.attribute_name = "SaNameTValues"; - attribute_descriptor.value_type = SA_IMM_ATTR_SANAMET; - attribute_descriptor.values_as_strings.clear(); - // Add two short names + std::string object_name{"Test12=1"}; + SaNameT a_name1, a_name2, a_name3; + std::string str1{"A_string_value=1"}; + std::string str2{"A_string_value=2"}; + std::string str3{"A_string_value=3"}; + std::string str4{"A_string_value=4"}; + std::vector<SaNameT*> list_namet{&a_name1, &a_name2, &a_name3}; + std::vector<std::string*> list_str{&str1, &str2, &str3, &str4}; osaf_extended_name_lend("a_name11", &a_name1); - attribute_descriptor.AddValue(modelmodify::SaNametToString(&a_name1)); - osaf_extended_name_lend("a_name12", &a_name1); - attribute_descriptor.AddValue(modelmodify::SaNametToString(&a_name1)); + osaf_extended_name_lend("a_name12", &a_name2); + // Add a long name and a third short name char long_name[300]; - for (size_t i = 0; i < 299; i++) { - long_name[i] = 'a'; - } + memset(long_name, 'a', 299); long_name[299] = '\0'; - osaf_extended_name_lend(long_name, &a_name1); - attribute_descriptor.AddValue(modelmodify::SaNametToString(&a_name1)); - osaf_extended_name_lend("a_name13", &a_name1); - attribute_descriptor.AddValue(modelmodify::SaNametToString(&a_name1)); - create_descriptor.AddAttribute(attribute_descriptor); - - // SA_UINT32_T single-value attribute_descriptor - attribute_descriptor.attribute_name = "SaUint32TValue"; - attribute_descriptor.value_type = SA_IMM_ATTR_SAUINT32T; - attribute_descriptor.values_as_strings.clear(); - // Note: Single value attribute_descriptor so only one value can be added - attribute_descriptor.AddValue(std::to_string(10)); - create_descriptor.AddAttribute(attribute_descriptor); - - - // SA_IMM_ATTR_SASTRINGT multi value attribute_descriptor - // SA_IMM_ATTR_SAUINT32T will be incorrectly used here - attribute_descriptor.attribute_name = "SaStringValues"; - attribute_descriptor.value_type = SA_IMM_ATTR_SAUINT32T; - attribute_descriptor.values_as_strings.clear(); - attribute_descriptor.AddValue("A_string_value=1"); - attribute_descriptor.AddValue("A_string_value=2"); - attribute_descriptor.AddValue("A_string_value=3"); - attribute_descriptor.AddValue("A_string_value=4"); - create_descriptor.AddAttribute(attribute_descriptor); - - // Reuse the ccb_descriptor and add the object creation - CcbDescriptorCleaner(ccb_descriptor); - ccb_descriptor.AddCreate(create_descriptor); - - // Do the modification - // Set CCB flag to inform IMM that there is no Object Implementer - modifier.SetCcbFlags(0); - + osaf_extended_name_lend(long_name, &a_name3); + + modelmodify::CcbCreateJob create_job12("ImmTestValuesConfig"); + create_job12.SetParentName("safApp=safSmfService"); + create_job12.SetAttributeValue("immTestValuesCfg", &object_name); + create_job12.SetAttributeValue<SaUint32T>("SaUint32TValues", {1, 2}); + create_job12.SetAttributeValue<SaInt32T>("SaInt32TValues", {3, 4}); + create_job12.SetAttributeValue("SaNameTValues", list_namet); + create_job12.SetAttributeValue("SaStringValues", list_str); + // Mistmatch b/w IMM model data type(SaUint32T) and value data type (SaInt32T) + create_job12.SetAttributeValue<SaInt32T>("SaUint32TValue", 10); + + jobs.ClearJobs().AddJob(&create_job12); cout << "In the request to create a Test12=1,safApp=safSmfService object " << endl << "a string attribute is incorrectly given SA_IMM_ATTR_SAUINT32T as " << endl << "IMM type. This shall fail in a controlled way" << endl; // Create the IMM object - if (modifier.DoModelModification(ccb_descriptor) == false) { + if (jobs.Execute() == false) { cout << "Creation of '" << object_name << "' FAIL" << endl; cout << "This fail is intentional so if we get here the test is SUCCESS" << endl << endl; - - cout << "Error information:" << endl; - modelmodify::ErrorInformation error_info; - modifier.GetErrorInformation(error_info); - cout << "Failing API: '" << error_info.api_name << "' " << endl; - cout << "AIS error code: " << saf_error(error_info.ais_error) << endl; - cout << "This is an internal error so there shall be no valid AIS error " - "code or AIS API-name" << endl; - cout << "If 'Failng API:' is empty then test is SUCCESS" << endl; } else { cout << "Creation of '" << object_name << "' SUCCESS" << endl; cout << "Test case FAIL" << endl; @@ -520,41 +318,25 @@ int main() { cout << "Then with ignore_ais_err_exist = true, shall succeed. However " "no new object is created" << endl << endl; - // Reuse the create descriptor - create_descriptor.attributes.clear(); - object_name = "Test12=2"; + object_name = "Test13=2"; // Define the object // Note: No values other than the object name is given // ----------------- - create_descriptor.class_name = "ImmTestValuesConfig"; - create_descriptor.parent_name = "safApp=safSmfService"; - // Set IMM Object name - attribute_descriptor.attribute_name = "immTestValuesCfg"; - attribute_descriptor.value_type = SA_IMM_ATTR_SASTRINGT; - // We are reusing so remove "old" values and add new ones - attribute_descriptor.values_as_strings.clear(); - attribute_descriptor.AddValue(object_name); - create_descriptor.AddAttribute(attribute_descriptor); - - // Reuse the ccb_descriptor and add the object creation - CcbDescriptorCleaner(ccb_descriptor); - ccb_descriptor.AddCreate(create_descriptor); - - // Do the modification - // Set CCB flag to inform IMM that there is no Object Implementer - modifier.SetCcbFlags(0); + modelmodify::CcbCreateJob create_job13("ImmTestValuesConfig"); + SetupObjectCreate1(object_name, create_job13); + + jobs.ClearJobs().AddJob(&create_job13); cout << "1. First Create. Shall succeed" << endl; - if (modifier.DoModelModification(ccb_descriptor) == false) { + if (jobs.Execute() == false) { cout << "Creation of '" << object_name << "' FAIL" << endl; cout << "Error information:" << endl; - modelmodify::ErrorInformation error_info; - modifier.GetErrorInformation(error_info); - cout << "Failing API: '" << error_info.api_name << "' " << endl; - cout << "AIS error code: " << saf_error(error_info.ais_error) << endl; + modelmodify::ErrInfo info = jobs.error_info(); + cout << "Failing at: '" << info.at << "' " << endl; + cout << "AIS error code: " << saf_error(info.ais) << endl; cout << endl; cout << "First object shall be created with no FAIL" << endl; @@ -566,14 +348,15 @@ int main() { cout << "2. Second create of same object shall fail. " "Object already exist" << endl; - if (modifier.DoModelModification(ccb_descriptor) == false) { + + jobs.ClearJobs().AddJob(&create_job13); + if (jobs.Execute() == false) { cout << "Creation of '" << object_name << "' FAIL" << endl; cout << "Error information:" << endl; - modelmodify::ErrorInformation error_info; - modifier.GetErrorInformation(error_info); - cout << "Failing API: '" << error_info.api_name << "' " << endl; - cout << "AIS error code: " << saf_error(error_info.ais_error) << endl; + modelmodify::ErrInfo info = jobs.error_info(); + cout << "Failing at: '" << info.at << "' " << endl; + cout << "AIS error code: " << saf_error(info.ais) << endl; cout << "Second creation of same object shall FAIL. Test SUCCESS" << endl; } else { @@ -582,22 +365,13 @@ int main() { cout << endl; cout << "3. Third create of same object shall succeed." << endl; - cout << " Set ignore_ais_err_exist = true and try again." << endl; + cout << " Set ignore_ais_err = SA_AIS_ERR_EXIST and try again." << endl; cout << " This time the modification shall not fail" << endl; - create_descriptor.ignore_ais_err_exist = true; - ccb_descriptor.create_descriptors.clear(); - ccb_descriptor.AddCreate(create_descriptor); - if (modifier.DoModelModification(ccb_descriptor) == false) { + create_job13.ignore_ais_code(SA_AIS_ERR_EXIST); + jobs.ClearJobs().AddJob(&create_job13); + if (jobs.Execute() == false) { cout << "Creation of '" << object_name << "' FAIL" << endl; - - cout << "Error information:" << endl; - modelmodify::ErrorInformation error_info; - modifier.GetErrorInformation(error_info); - cout << "Failing API: '" << error_info.api_name << "' " << endl; - cout << "AIS error code: " << saf_error(error_info.ais_error) << endl; - - cout << "Third creation of same object failed. Test FAIL" << endl; } else { cout << "Third creation of same object did not fail. Test SUCCESS" << endl; } @@ -606,43 +380,29 @@ int main() { // Try deleting an object that does not exist; // ignore_ais_err_not_exist = true // Shall SUCCEED but no object is deleted - std::string object_name_not_exist = "Test12=100"; + std::string object_name_not_exist = "Test12=100,safApp=safSmfService"; cout << "Deleting object that does not exist. Flag ignore_ais_err_not_exist " - "= true (default)" << endl; - delete_descriptor.object_name = object_name_not_exist + "," + - create_descriptor.parent_name; - CcbDescriptorCleaner(ccb_descriptor); - ccb_descriptor.AddDelete(delete_descriptor); - if (modifier.DoModelModification(ccb_descriptor) == false) { - cout << "Deleting object '" << delete_descriptor.object_name << "' FAIL" + "= true" << endl; + + modelmodify::CcbDeleteJob delete_job5{object_name_not_exist}; + delete_job5.ignore_ais_code(SA_AIS_ERR_NOT_EXIST); + jobs.ClearJobs().AddJob(&delete_job5); + if (jobs.Execute() == false) { + cout << "Deleting object '" << object_name_not_exist << "' FAIL" << endl; cout << "Test FAIL" << endl; } else { cout << "Test SUCCESS" << endl; } - // Cleanup by deleting the test object - delete_descriptor.object_name = object_name + "," + - create_descriptor.parent_name; - delete_descriptor.ignore_ais_err_not_exist = true; - CcbDescriptorCleaner(ccb_descriptor); - ccb_descriptor.AddDelete(delete_descriptor); - if (modifier.DoModelModification(ccb_descriptor) == false) { - cout << "Deleting object '" << delete_descriptor.object_name << "' FAIL" - << endl; - } - // Try deleting an object that does not exist; // ignore_ais_err_not_exist = false cout << "Deleting object that does not exist. Flag ignore_ais_err_not_exist " "= false" << endl; - delete_descriptor.object_name = object_name_not_exist + "," + - create_descriptor.parent_name; - delete_descriptor.ignore_ais_err_not_exist = false; - CcbDescriptorCleaner(ccb_descriptor); - ccb_descriptor.AddDelete(delete_descriptor); - if (modifier.DoModelModification(ccb_descriptor) == false) { - cout << "Deleting object '" << delete_descriptor.object_name << "' FAIL" + modelmodify::CcbDeleteJob delete_job6{object_name_not_exist}; + jobs.ClearJobs().AddJob(&delete_job6); + if (jobs.Execute() == false) { + cout << "Deleting object '" << object_name_not_exist << "' FAIL" << endl; cout << "Test SUCCESS" << endl; } else { diff --git a/src/smf/smfd/imm_om_ccapi/common/common.h b/src/smf/smfd/imm_om_ccapi/common/common.h index b9c87cb06..6c095189e 100644 --- a/src/smf/smfd/imm_om_ccapi/common/common.h +++ b/src/smf/smfd/imm_om_ccapi/common/common.h @@ -23,6 +23,7 @@ #include "ais/include/saAis.h" #include "base/time.h" #include "base/saf_error.h" +#include "smf/smfd/imm_om_ccapi/common/imm_cpp_type.h" // When getting SA_AIS_ERR_TRY_AGAIN, the retry loop will be run. // and in default, the interval between retries is kDefaultIntervalMs(40ms) @@ -51,7 +52,7 @@ const SaUint8T kDefaultImmMinorVersion = 11; struct CppSaTimeT { CppSaTimeT() { time = 0; } explicit CppSaTimeT(SaTimeT t) : time{t} {}; - // explicit CppSaTimeT(int t) : time{t} {}; + CppSaTimeT(int t) : time{t} {}; CppSaTimeT& operator=(SaTimeT t) { time = t; @@ -146,7 +147,8 @@ SaImmValueTypeT ImmBase::GetAttributeValueType() { return SA_IMM_ATTR_SAUINT32T; } else if (std::is_same<T, SaInt64T>::value) { return SA_IMM_ATTR_SAINT64T; - } else if (std::is_same<T, CppSaTimeT>::value) { + } else if ((std::is_same<T, CppSaTimeT>::value) || + (std::is_same<T, cpptime_t>::value)) { return SA_IMM_ATTR_SATIMET; } else if (std::is_same<T, SaUint64T>::value) { return SA_IMM_ATTR_SAUINT64T; @@ -183,6 +185,7 @@ SaImmValueTypeT ImmBase::GetAttributeValueType() { std::is_same<T, SaConstStringT>::value || \ std::is_same<T, std::string>::value || \ std::is_same<T, SaTimeT>::value || \ + std::is_same<T, cpptime_t>::value || \ std::is_same<T, SaAnyT>::value, \ "typename T is not supported"); diff --git a/src/smf/smfd/imm_om_ccapi/common/imm_attribute.cc b/src/smf/smfd/imm_om_ccapi/common/imm_attribute.cc index c53fadaee..b6c80c062 100644 --- a/src/smf/smfd/imm_om_ccapi/common/imm_attribute.cc +++ b/src/smf/smfd/imm_om_ccapi/common/imm_attribute.cc @@ -15,7 +15,7 @@ * */ -#include "imm_attribute.h" +#include "smf/smfd/imm_om_ccapi/common/imm_attribute.h" #include "base/logtrace.h" void AttributeProperty::FormAttrValuesT_2( @@ -25,7 +25,7 @@ void AttributeProperty::FormAttrValuesT_2( output->attrName = const_cast<char*>(attribute_name_.c_str()); output->attrValueType = attribute_type_; output->attrValuesNumber = num_of_values_; - output->attrValues = attribute_values_pointers_; + output->attrValues = attribute_values_; } void AttributeProperty::FormSearchOneAttrT_2( @@ -34,8 +34,7 @@ void AttributeProperty::FormSearchOneAttrT_2( assert(output != nullptr); output->attrName = const_cast<char*>(attribute_name_.c_str()); output->attrValueType = attribute_type_; - void* value = (attribute_values_pointers_ == nullptr) ? nullptr : - attribute_values_pointers_[0]; + void* value = (attribute_values_ == nullptr) ? nullptr : attribute_values_[0]; output->attrValue = value; } @@ -45,8 +44,7 @@ void AttributeProperty::FormAdminOperationParamsT_2( assert(output != nullptr); output->paramName = const_cast<char*>(attribute_name_.c_str()); output->paramType = attribute_type_; - void* value = (attribute_values_pointers_ == nullptr) ? nullptr : - attribute_values_pointers_[0]; + void* value = (attribute_values_ == nullptr) ? nullptr : attribute_values_[0]; output->paramBuffer = value; } @@ -57,8 +55,7 @@ void AttributeDefinition::FormAttrDefinitionT_2( output->attrName = const_cast<char*>(attribute_name_.c_str()); output->attrValueType = attribute_type_; output->attrFlags = attribute_flags_; - void* value = (attribute_values_pointers_ == nullptr) ? nullptr : - attribute_values_pointers_[0]; + void* value = (attribute_values_ == nullptr) ? nullptr : attribute_values_[0]; output->attrDefaultValue = value; } @@ -72,44 +69,44 @@ void AttributeModification::FormAttrModificationT_2( void AttributeProperty::FreeMemory() { TRACE_ENTER(); - if (attribute_values_pointers_ == nullptr) return; + if (attribute_values_ == nullptr) return; switch (attribute_type_) { case SA_IMM_ATTR_SAINT32T: - delete[] reinterpret_cast<SaInt32T**>(attribute_values_pointers_); + delete[] reinterpret_cast<SaInt32T**>(attribute_values_); break; case SA_IMM_ATTR_SAUINT32T: - delete[] reinterpret_cast<SaUint32T**>(attribute_values_pointers_); + delete[] reinterpret_cast<SaUint32T**>(attribute_values_); break; case SA_IMM_ATTR_SAINT64T: - delete[] reinterpret_cast<SaInt64T**>(attribute_values_pointers_); + delete[] reinterpret_cast<SaInt64T**>(attribute_values_); break; case SA_IMM_ATTR_SAUINT64T: - delete[] reinterpret_cast<SaUint64T**>(attribute_values_pointers_); + delete[] reinterpret_cast<SaUint64T**>(attribute_values_); break; case SA_IMM_ATTR_SANAMET: - delete[] reinterpret_cast<SaNameT**>(attribute_values_pointers_); + delete[] reinterpret_cast<SaNameT**>(attribute_values_); break; case SA_IMM_ATTR_SAFLOATT: - delete[] reinterpret_cast<SaFloatT**>(attribute_values_pointers_); + delete[] reinterpret_cast<SaFloatT**>(attribute_values_); break; case SA_IMM_ATTR_SADOUBLET: - delete[] reinterpret_cast<SaDoubleT**>(attribute_values_pointers_); + delete[] reinterpret_cast<SaDoubleT**>(attribute_values_); break; case SA_IMM_ATTR_SASTRINGT: - delete[] reinterpret_cast<SaStringT**>(attribute_values_pointers_); + delete[] reinterpret_cast<SaStringT**>(attribute_values_); break; default: - delete[] reinterpret_cast<SaAnyT**>(attribute_values_pointers_); + delete[] reinterpret_cast<SaAnyT**>(attribute_values_); break; } - attribute_values_pointers_ = nullptr; + attribute_values_ = nullptr; } diff --git a/src/smf/smfd/imm_om_ccapi/common/imm_attribute.h b/src/smf/smfd/imm_om_ccapi/common/imm_attribute.h index d4794eb84..e349289e5 100644 --- a/src/smf/smfd/imm_om_ccapi/common/imm_attribute.h +++ b/src/smf/smfd/imm_om_ccapi/common/imm_attribute.h @@ -1,6 +1,6 @@ /* -*- OpenSAF -*- * - * Copyright Ericsson AB 2018 - All Rights Reserved. + * Copyright Ericsson AB 2017 - All Rights Reserved. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY @@ -18,11 +18,12 @@ #ifndef SMF_SMFD_IMM_OM_CCAPI_COMMON_IMM_ATTRIBUTE_H_ #define SMF_SMFD_IMM_OM_CCAPI_COMMON_IMM_ATTRIBUTE_H_ -#include <string.h> +#include <cstring> #include <string> #include <vector> #include "ais/include/saImm.h" #include "smf/smfd/imm_om_ccapi/common/common.h" +#include "smf/smfd/imm_om_ccapi/common/imm_cpp_type.h" //> // These below 03 classes represent C IMM data structures @@ -58,70 +59,75 @@ // // Example: // AttributeProperty* attribute = new AttributeProperty(name); -// attribute->set_value<SaUint32T>(value); +// attribute->set_value<uint32_t>(value); // // SaImmAttrValuesT_2 immattr; // attribute->FormAttrValuesT_2(&immattr); //< + + class AttributeProperty { public: explicit AttributeProperty(const std::string& name) : attribute_name_{name}, - attribute_values_pointers_{nullptr}, - num_of_values_{0}, - list_ptr_to_cpp_strings_{nullptr} {} + attribute_values_{nullptr}, + num_of_values_{0} {} virtual ~AttributeProperty() { - for (auto& item : list_ptr_to_cpp_strings_) { - if (item != nullptr) delete[] item; + for (auto& item : values_) { + delete item; } FreeMemory(); } template <typename T> - AttributeProperty& set_value(T* ptr_to_value) { + AttributeProperty& set_value(T* value) { attribute_type_ = ImmBase::GetAttributeValueType<T>(); - if (ptr_to_value != nullptr) { - attribute_values_pointers_ = reinterpret_cast<void**>(new T*[1]()); - assert(attribute_values_pointers_ != nullptr); - attribute_values_pointers_[0] = ptr_to_value; + if (value != nullptr) { + attribute_values_ = reinterpret_cast<void**>(new T*[1]()); + assert(attribute_values_ != nullptr); + values_.push_back(GenerateCppType<T>(value)); + attribute_values_[0] = values_[0]->data(); num_of_values_ = 1; } return *this; } template <typename T> - AttributeProperty& set_value(const std::vector<T*>& list_of_ptr_to_values) { + AttributeProperty& set_value(const std::vector<T*>& values) { attribute_type_ = ImmBase::GetAttributeValueType<T>(); - if (list_of_ptr_to_values.empty() == false) { - size_t size = list_of_ptr_to_values.size(); - attribute_values_pointers_ = reinterpret_cast<void**>(new T*[size]()); - assert(attribute_values_pointers_ != nullptr); + if (values.empty() == false) { + size_t size = values.size(); + attribute_values_ = reinterpret_cast<void**>(new T*[size]()); + assert(attribute_values_ != nullptr); unsigned i = 0; - for (auto& ptr_to_value : list_of_ptr_to_values) { - attribute_values_pointers_[i++] = ptr_to_value; + for (auto& value : values) { + values_.push_back(GenerateCppType<T>(value)); + attribute_values_[i] = values_[i]->data(); + i++; } num_of_values_ = size; } return *this; } - // Convert this class object to given `output` C IMM data structure + const std::string& name() { return attribute_name_; } + + // // Convert this class object to given `output` C IMM data structure void FormAttrValuesT_2(SaImmAttrValuesT_2* output) const; void FormSearchOneAttrT_2(SaImmSearchOneAttrT_2* output) const; void FormAdminOperationParamsT_2(SaImmAdminOperationParamsT_2* output) const; private: void FreeMemory(); + template <typename T> base_t* GenerateCppType(T* value); protected: std::string attribute_name_; - void** attribute_values_pointers_; - SaUint32T num_of_values_; + void** attribute_values_; + uint32_t num_of_values_; SaImmValueTypeT attribute_type_; - // Introduce this attribute to deal with typename T = std::string. - // Each element holds C string which is returned by std::string.c_str(); - std::vector<char*> list_ptr_to_cpp_strings_; + std::vector<base_t*> values_; }; class AttributeDefinition : public AttributeProperty { @@ -154,76 +160,66 @@ class AttributeModification : public AttributeProperty { SaImmAttrModificationTypeT modification_type_; }; -template<> inline AttributeProperty& -AttributeProperty::set_value<std::string>(std::string* ptr_to_value) { - attribute_type_ = ImmBase::GetAttributeValueType<std::string>(); - if (ptr_to_value != nullptr) { - size_t size = ptr_to_value->length(); - attribute_values_pointers_ = reinterpret_cast<void**>(new char**[1]()); - assert(attribute_values_pointers_ != nullptr); - num_of_values_ = 1; - - // Trick to deal with typename std::string - list_ptr_to_cpp_strings_.resize(1); - list_ptr_to_cpp_strings_[0] = new char[size + 1](); - assert(list_ptr_to_cpp_strings_[0] != nullptr); - memcpy(list_ptr_to_cpp_strings_[0], ptr_to_value->c_str(), size); - attribute_values_pointers_[0] = &list_ptr_to_cpp_strings_[0]; - } - return *this; +template <> +inline base_t* AttributeProperty::GenerateCppType<SaInt32T>(SaInt32T* value) { + return new i32_t(*value); } -template<> inline AttributeProperty& -AttributeProperty::set_value<std::string>( - const std::vector<std::string*>& list_of_ptr_to_values) { - attribute_type_ = ImmBase::GetAttributeValueType<std::string>(); - if (list_of_ptr_to_values.empty() == false) { - size_t size = list_of_ptr_to_values.size(); - attribute_values_pointers_ = reinterpret_cast<void**>(new char**[size]()); - assert(attribute_values_pointers_ != nullptr); - num_of_values_ = size; - - list_ptr_to_cpp_strings_.resize(size); - unsigned i = 0; - for (auto& ptr_to_value : list_of_ptr_to_values) { - size_t ssize = ptr_to_value->length(); - list_ptr_to_cpp_strings_[i] = new char[ssize + 1](); - assert(list_ptr_to_cpp_strings_[i] != nullptr); - memcpy(list_ptr_to_cpp_strings_[i], ptr_to_value->c_str(), ssize); - attribute_values_pointers_[i] = &list_ptr_to_cpp_strings_[i]; - i++; - } - } - return *this; +template <> +inline base_t* AttributeProperty::GenerateCppType<uint32_t>(uint32_t* value) { + return new u32_t(*value); } -template <> inline AttributeProperty& -AttributeProperty::set_value<CppSaTimeT>(CppSaTimeT* ptr_to_value) { - attribute_type_ = ImmBase::GetAttributeValueType<CppSaTimeT>(); - if (ptr_to_value != nullptr) { - attribute_values_pointers_ = reinterpret_cast<void**>(new SaTimeT*[1]()); - assert(attribute_values_pointers_ != nullptr); - attribute_values_pointers_[0] = &(ptr_to_value->time); - num_of_values_ = 1; - } - return *this; +template <> +inline base_t* AttributeProperty::GenerateCppType<SaInt64T>(SaInt64T* value) { + return new i64_t(*value); } -template <> inline AttributeProperty& -AttributeProperty::set_value<CppSaTimeT>( - const std::vector<CppSaTimeT*>& list_of_ptr_to_values) { - attribute_type_ = ImmBase::GetAttributeValueType<CppSaTimeT>(); - if (list_of_ptr_to_values.empty() == false) { - size_t size = list_of_ptr_to_values.size(); - attribute_values_pointers_ = reinterpret_cast<void**>(new SaTimeT*[size]()); - assert(attribute_values_pointers_ != nullptr); - unsigned i = 0; - for (auto& ptr_to_value : list_of_ptr_to_values) { - attribute_values_pointers_[i++] = &(ptr_to_value->time); - } - num_of_values_ = size; - } - return *this; +template <> +inline base_t* AttributeProperty::GenerateCppType<SaUint64T>(SaUint64T* value) { + return new u64_t(*value); +} + +template <> +inline base_t* AttributeProperty::GenerateCppType<CppSaTimeT>(CppSaTimeT* value) { + return new t64_t(cpptime_t(value->time)); +} + +template <> +inline base_t* AttributeProperty::GenerateCppType<SaFloatT>(SaFloatT* value) { + return new f64_t(*value); +} + +template <> +inline base_t* AttributeProperty::GenerateCppType<SaDoubleT>(SaDoubleT* value) { + return new d64_t(*value); +} + +template <> +inline base_t* AttributeProperty::GenerateCppType<SaNameT>(SaNameT* value) { + return new name_t(*value); +} + +template <> +inline base_t* AttributeProperty::GenerateCppType<SaStringT>(SaStringT* value) { + return new string_t(*value); +} + +template <> +inline base_t* AttributeProperty::GenerateCppType<SaConstStringT>( + SaConstStringT* value) { + return new string_t(*value); +} + +template <> +inline base_t* AttributeProperty::GenerateCppType<std::string>( + std::string* value) { + return new string_t(*value); +} + +template <> +inline base_t* AttributeProperty::GenerateCppType<SaAnyT>(SaAnyT* value) { + return new any_t(*value); } // For internal use only diff --git a/src/smf/smfd/imm_om_ccapi/common/imm_cpp_type.h b/src/smf/smfd/imm_om_ccapi/common/imm_cpp_type.h new file mode 100644 index 000000000..664df018f --- /dev/null +++ b/src/smf/smfd/imm_om_ccapi/common/imm_cpp_type.h @@ -0,0 +1,380 @@ +#ifndef SMF_SMFD_IMM_OM_CCAPI_COMMON_IMM_CPP_TYPE_ +#define SMF_SMFD_IMM_OM_CCAPI_COMMON_IMM_CPP_TYPE_ + +#include <saAis.h> +#include <cstring> +#include <string> +#include <iostream> +#include <saImm.h> +#include "base/osaf_extended_name.h" + +//> +// These data wrappers are mainly used in common/imm_attribute.h, +// so that all IMM data types can be able to be stored in one container. +//< + +// enum class ECppType { +// kInt32T = 1, +// kUint32T, +// kInt64T, +// kUint64T, +// kTimeT, +// kNameT, +// kFloatT, +// kDoubleT, +// kStringT, +// kAnyT +// }; + +struct cpptime_t { + cpptime_t() { + data_ = 0; + } + + explicit cpptime_t(SaTimeT i) { + data_ = i; + } + + explicit cpptime_t(int i) { + data_ = static_cast<SaTimeT>(i); + } + + explicit cpptime_t(int64_t i) { + data_ = static_cast<SaTimeT>(i); + } + + cpptime_t& operator=(const SaTimeT& i) { + data_ = i; + return *this; + } + + cpptime_t& operator=(const cpptime_t& i) { + data_ = i.data_; + return *this; + } + + bool operator==(const cpptime_t& i) { + return data_ == i.data_; + } + + bool operator==(SaTimeT& i) { + return data_ == i; + } + + friend bool operator==(const SaTimeT& i, const cpptime_t& ii) { + return i == ii.data_; + } + + friend bool operator==(SaTimeT& i, cpptime_t& ii) { + return i == ii.data_; + } + + bool operator==(int i) { + return data_ == static_cast<SaTimeT>(i); + } + + SaTimeT operator()() { + return data_; + } + + SaTimeT* operator&() { return &data_; } + + private: + SaTimeT data_; +}; + +class base_t { + public: + virtual void* data() = 0; + virtual ~base_t() {} + virtual void display() = 0; + // virtual SaImmValueTypeT type() = 0; +}; + +template<typename T> +class numeric_t : public base_t { + public: + numeric_t() { + data_ = 0; + } + + explicit numeric_t(T i) { + data_ = i; + } + + explicit numeric_t(SaDoubleT i) { + data_ = static_cast<SaDoubleT>(i); + } + + explicit numeric_t(int i) { + data_ = static_cast<T>(i); + } + + explicit numeric_t(int64_t i) { + data_ = static_cast<T>(i); + } + + numeric_t(numeric_t<T>& i) { + data_ = i.data_; + } + + numeric_t(const numeric_t<T>& i) { + data_ = i.data_; + } + + bool operator==(const T& i) const { + return data_ == i; + } + + const T operator()() const { + return data_; + } + + void* data() { return &data_; } + + void display() { + std::cout << "\tdata: " << data_ << std::endl; + } + + private: + T data_; +}; + +template<> +class numeric_t<SaInt32T> : public base_t { + public: + numeric_t() { + data_ = 0; + } + + explicit numeric_t(SaInt32T i) { + data_ = i; + } + + numeric_t(numeric_t<SaInt32T>& i) { + data_ = i.data_; + } + + numeric_t(const numeric_t<SaInt32T>& i) { + data_ = i.data_; + } + + bool operator==(const SaInt32T& i) const { + return data_ == i; + } + + const SaInt32T operator()() const { + return data_; + } + + void* data() { return &data_; } + + void display() { + std::cout << "\tdata: " << data_ << std::endl; + } + + private: + SaInt32T data_; +}; + +template<> +class numeric_t<SaDoubleT> : public base_t { + public: + numeric_t() { + data_ = 0; + } + + explicit numeric_t(SaDoubleT i) { + data_ = i; + } + + numeric_t(numeric_t<SaDoubleT>& i) { + data_ = i.data_; + } + + numeric_t(const numeric_t<SaDoubleT>& i) { + data_ = i.data_; + } + + bool operator==(const SaDoubleT& i) const { + return data_ == i; + } + + const SaDoubleT operator()() const { + return data_; + } + + void* data() { return &data_; } + + void display() { + std::cout << "\tdata: " << data_ << std::endl; + } + + private: + SaDoubleT data_; +}; + +class string_t : public base_t { +public: + string_t() { + data_ = nullptr; + } + + explicit string_t(const char* i) { + data_ = new char[strlen(i) + 1](); + memcpy(data_, i, strlen(i) + 1); + } + + explicit string_t(const std::string& i) { + data_ = new char[i.length() + 1](); + memcpy(data_, i.c_str(), i.length()); + } + + string_t(const string_t& i) { + if (i.data_ == nullptr) return; + data_ = new char[strlen(i.data_) + 1](); + memcpy(data_, i(), strlen(i.data_) + 1); + } + + string_t(string_t& i) { + if (i.data_ == nullptr) return; + data_ = new char[strlen(i.data_) + 1](); + memcpy(data_, i(), strlen(i.data_) + 1); + } + + ~string_t() { + if (data_ != nullptr) { + delete[] data_; + data_ = nullptr; + } + } + + const char* operator()() const { + return data_; + } + + void* data() { return &data_; } + + void display() { + std::cout << "\tdata: " << data_ << std::endl; + } + +private: + char* data_; +}; + +template<> inline void numeric_t<cpptime_t>::display() { + std::cout << "\tdata: " << data_() << std::endl; +} + +class name_t : public base_t { + public: + name_t() { + buf_ = NULL; + } + + name_t(name_t& i) { + buf_ = new char[strlen(i.buf_) + 1](); + memcpy(buf_, i.buf_, strlen(i.buf_) + 1); + osaf_extended_name_lend(buf_, &data_); + } + + explicit name_t(SaNameT& i) { + SaConstStringT n = osaf_extended_name_borrow(&i); + buf_ = new char[strlen(n) + 1](); + memcpy(buf_, n, strlen(n) + 1); + osaf_extended_name_lend(buf_, &data_); + } + + name_t(const name_t& i) { + buf_ = new char[strlen(i.buf_) + 1](); + memcpy(buf_, i.buf_, strlen(i.buf_) + 1); + osaf_extended_name_lend(buf_, &data_); + } + + explicit name_t(std::string& i) { + buf_ = new char[i.length() + 1](); + memcpy(buf_, i.c_str(), i.length() + 1); + osaf_extended_name_lend(buf_, &data_); + } + + explicit name_t(const std::string& i) { + buf_ = new char[i.length() + 1](); + memcpy(buf_, i.c_str(), i.length() + 1); + osaf_extended_name_lend(buf_, &data_); + } + + ~name_t() { + if (buf_ != nullptr) { + delete[] buf_; + buf_ = nullptr; + } + } + + const char* operator()() { + return buf_; + } + + void* data() { return &data_; } + + void display() { + std::cout << "\tdata: " << buf_ << std::endl; + } + + private: + char* buf_; + SaNameT data_; +}; + +class any_t : public base_t { + public: + any_t() { + memset(&data_, 0, sizeof(SaAnyT)); + } + + ~any_t() { + if (data_.bufferAddr != nullptr) { + delete[] data_.bufferAddr; + data_.bufferAddr = nullptr; + } + } + + explicit any_t(const SaAnyT& i) { + data_.bufferSize = i.bufferSize; + data_.bufferAddr = new SaUint8T[i.bufferSize](); + memcpy(reinterpret_cast<char*>(data_.bufferAddr), + i.bufferAddr, i.bufferSize); + } + + explicit any_t(const char* i, size_t size) { + data_.bufferSize = size; + data_.bufferAddr = new SaUint8T[size](); + memcpy(reinterpret_cast<char*>(data_.bufferAddr), i, size); + } + + explicit any_t(const char* i) : any_t{i, strlen(i)} { } + explicit any_t(const std::string& i) : any_t{i.c_str()} { } + + const SaAnyT* operator()() { + return &data_; + } + + void* data() { return &data_; } + + void display() { + std::cout << "\tdata: " << data_.bufferAddr << std::endl; + } + + private: + SaAnyT data_; +}; + +using i32_t = numeric_t<SaInt32T>; +using u32_t = numeric_t<SaUint32T>; +using i64_t = numeric_t<SaInt64T>; +using u64_t = numeric_t<SaUint64T>; +using f64_t = numeric_t<SaFloatT>; +using d64_t = numeric_t<SaDoubleT>; +using t64_t = numeric_t<cpptime_t>; + +#endif // SMF_SMFD_IMM_OM_CCAPI_COMMON_IMM_CPP_TYPE_ -- 2.18.0 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel