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
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel