osaf/services/saf/smfsv/README | 34 +-
osaf/services/saf/smfsv/smfd/Makefile.am | 13 +-
osaf/services/saf/smfsv/smfd/SmfCampaign.cc | 5 +-
osaf/services/saf/smfsv/smfd/SmfCampaignInit.cc | 6 -
osaf/services/saf/smfsv/smfd/SmfCampaignThread.cc | 13 +-
osaf/services/saf/smfsv/smfd/SmfImmApplierHdl.cc | 726 ++++++++++++++++++++++
osaf/services/saf/smfsv/smfd/SmfImmApplierHdl.hh | 113 +++
osaf/services/saf/smfsv/smfd/SmfImmOperation.cc | 15 +-
osaf/services/saf/smfsv/smfd/SmfLongDnApplier.cc | 441 +++++++++++++
osaf/services/saf/smfsv/smfd/SmfLongDnApplier.hh | 84 ++
osaf/services/saf/smfsv/smfd/SmfUtils.cc | 83 +--
osaf/services/saf/smfsv/smfd/SmfUtils.hh | 7 -
osaf/services/saf/smfsv/smfd/smfd.h | 2 +-
osaf/services/saf/smfsv/smfd/smfd_amf.c | 20 +-
osaf/services/saf/smfsv/smfd/smfd_campaign_oi.cc | 18 -
osaf/services/saf/smfsv/smfd/smfd_cb.h | 3 +-
osaf/services/saf/smfsv/smfd/smfd_evt.h | 7 +
osaf/services/saf/smfsv/smfd/smfd_long_dn.hh | 58 +
osaf/services/saf/smfsv/smfd/smfd_main.c | 13 +-
19 files changed, 1530 insertions(+), 131 deletions(-)
Keep track of long DN setting using an IMM applier instead of reading
the long DN setting in many places
diff --git a/osaf/services/saf/smfsv/README b/osaf/services/saf/smfsv/README
--- a/osaf/services/saf/smfsv/README
+++ b/osaf/services/saf/smfsv/README
@@ -251,6 +251,38 @@ directory "samples/smfsv"
CONTRIBUTORS/MAINTAINERS
========================
Bertil Engelholm <[email protected]>
-Ingvar Bergström <[email protected]>
+Ingvar Bergstr�m <[email protected]>
The SMF service was originally cloned from the immsv and log services.
+
+MAINTAINER NOTES
+================
+
+Applier for monitoring long Dn allowed setting
+----------------------------------------------
+SMF is dependent on knowing the longDnsAllowed setting in the IMM configuration
+object. This setting may change at any time and to monitor changes an IMM
+applier is used.
+
+SmfImmApplierHdl:
+Contains a wrapper for the IMM APIs and callback functions used with an
applier.
+A C++ class is used to create an interface for handling an applier e.g. create,
+start (initialize and set), stop (clear), get value etc.
+See SmfImmApplierHdl.hh for more information.
+
+SmfLongDnApplier:
+Runs an applier in a thread using the SmfImmApplierHdl.
+A C++ class is used to create an interface for running an applier.
+See SmfLongDnApplier.hh for more information.
+
+Installation in SMF:
+
+In smfd_main.cc the applier is constructed and created. A pointer to the
applier
+object is stored in a global variable. The applier is started and stopped in
the
+same place as the SMF object implementer when SMF gets a CSI set callback, see
+smfd_amf.cc. In previous versions of SMF a global variable in the smfd_cb
struct
+, maxDnLength, was used to store the maximum allowed length of a Dn depending
on
+the IMM config long Dn setting. This length information is used in many places
+in the SMF code. The global variable is replaced by a function call to
+GetSmfMaxDnLength() which returns the same length information. This function
+can be found in smfd_long_dn.hh
diff --git a/osaf/services/saf/smfsv/smfd/Makefile.am
b/osaf/services/saf/smfsv/smfd/Makefile.am
--- a/osaf/services/saf/smfsv/smfd/Makefile.am
+++ b/osaf/services/saf/smfsv/smfd/Makefile.am
@@ -51,7 +51,10 @@ noinst_HEADERS = \
SmfCallback.hh \
SmfCbkUtil.hh \
SmfExecControl.h \
- SmfExecControlHdl.h
+ SmfExecControlHdl.h \
+ SmfLongDnApplier.hh \
+ SmfImmApplierHdl.hh \
+ smfd_long_dn.hh
osafsmfd_CXXFLAGS = $(AM_CXXFLAGS) @XML2_CFLAGS@
@@ -63,9 +66,9 @@ osafsmfd_CPPFLAGS = \
-I$(top_srcdir)/osaf/tools/saflog/include
osafsmfd_SOURCES = \
- smfd_amf.c \
+ smfd_amf.cc \
smfd_evt.c \
- smfd_main.c \
+ smfd_main.cc \
smfd_smfnd.c \
smfd_mds.c \
SmfCampaignThread.cc \
@@ -91,7 +94,9 @@ osafsmfd_SOURCES = \
SmfCallback.cc \
SmfCbkUtil.cc \
SmfExecControl.cc \
- SmfExecControlHdl.cc
+ SmfExecControlHdl.cc \
+ SmfLongDnApplier.cc \
+ SmfImmApplierHdl.cc
osafsmfd_LDFLAGS = \
$(AM_LDFLAGS) \
diff --git a/osaf/services/saf/smfsv/smfd/SmfCampaign.cc
b/osaf/services/saf/smfsv/smfd/SmfCampaign.cc
--- a/osaf/services/saf/smfsv/smfd/SmfCampaign.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfCampaign.cc
@@ -34,6 +34,7 @@
#include "SmfUpgradeAction.hh"
#include "SmfUtils.hh"
#include "SmfExecControl.h"
+#include "smfd_long_dn.hh"
#include "saAis.h"
#include <saSmf.h>
@@ -713,10 +714,10 @@ SmfCampaign::startProcedureThreads()
while (iter != procedures.end()) {
//Set the DN of the procedure
std::string dn = (*iter)->getProcName() + "," +
SmfCampaignThread::instance()->campaign()->getDn();
- if (dn.length() >
static_cast<size_t>(smfd_cb->maxDnLength - OSAF_STEP_ACT_LENGTH)) {
+ if (dn.length() >
static_cast<size_t>(GetSmfMaxDnLength() - OSAF_STEP_ACT_LENGTH)) {
std::string error = "Procedure dn too long " +
dn;
LOG_ER("Procedure dn too long (max %zu) %s",
-
static_cast<size_t>(smfd_cb->maxDnLength - OSAF_STEP_ACT_LENGTH),
+ static_cast<size_t>(GetSmfMaxDnLength()
- OSAF_STEP_ACT_LENGTH),
dn.c_str());
SmfCampaignThread::instance()->campaign()->setError(error);
delete p_uc; // To terminate and remove any
previously started procedure threads
diff --git a/osaf/services/saf/smfsv/smfd/SmfCampaignInit.cc
b/osaf/services/saf/smfsv/smfd/SmfCampaignInit.cc
--- a/osaf/services/saf/smfsv/smfd/SmfCampaignInit.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfCampaignInit.cc
@@ -228,12 +228,6 @@ SmfCampaignInit::execute()
std::list < SmfUpgradeAction * >::iterator upActiter;
upActiter = m_campInitAction.begin();
while (upActiter != m_campInitAction.end()) {
- TRACE("3. %s:
read_IMM_long_DN_config_and_set_control_block()",__FUNCTION__);
- if
(!immUtil.read_IMM_long_DN_config_and_set_control_block(smfd_cb)) {
- LOG_ER("SmfCampaignInit: reading long DN config from
IMM FAILED");
- TRACE_LEAVE();
- return false;
- }
SaAisErrorT rc =
(*upActiter)->execute(SmfCampaignThread::instance()->getImmHandle(),
&initRollbackDn);
if (rc != SA_AIS_OK) {
diff --git a/osaf/services/saf/smfsv/smfd/SmfCampaignThread.cc
b/osaf/services/saf/smfsv/smfd/SmfCampaignThread.cc
--- a/osaf/services/saf/smfsv/smfd/SmfCampaignThread.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfCampaignThread.cc
@@ -37,6 +37,7 @@
#include "SmfUpgradeCampaign.hh"
#include "SmfUpgradeProcedure.hh"
#include "SmfUtils.hh"
+#include "smfd_long_dn.hh"
SmfCampaignThread *SmfCampaignThread::s_instance = NULL;
@@ -492,10 +493,10 @@ int SmfCampaignThread::sendStateNotifica
/* Notifying object */
size_t length = sizeof(SMF_NOTIFYING_OBJECT);
- if (length > static_cast<size_t>(smfd_cb->maxDnLength)) {
+ if (length > static_cast<size_t>(GetSmfMaxDnLength())) {
TRACE("notifyingObject length was %zu, truncated to %zu",
- length, static_cast<size_t>(smfd_cb->maxDnLength));
- length = smfd_cb->maxDnLength;
+ length, static_cast<size_t>(GetSmfMaxDnLength()));
+ length = GetSmfMaxDnLength();
}
char* value = (char*) malloc(length + 1);
if (value == NULL) {
@@ -509,10 +510,10 @@ int SmfCampaignThread::sendStateNotifica
/* Notification object */
length = dn.length();
- if (length > static_cast<size_t>(smfd_cb->maxDnLength)) {
+ if (length > static_cast<size_t>(GetSmfMaxDnLength())) {
TRACE("notificationHeader length was %zu, truncated to %zu",
- length, static_cast<size_t>(smfd_cb->maxDnLength));
- length = smfd_cb->maxDnLength;
+ length, static_cast<size_t>(GetSmfMaxDnLength()));
+ length = GetSmfMaxDnLength();
}
value = (char*) malloc(length + 1);
if (value == NULL) {
diff --git a/osaf/services/saf/smfsv/smfd/SmfImmApplierHdl.cc
b/osaf/services/saf/smfsv/smfd/SmfImmApplierHdl.cc
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/smfsv/smfd/SmfImmApplierHdl.cc
@@ -0,0 +1,726 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * 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 "SmfImmApplierHdl.hh"
+#include <string>
+#include <atomic>
+// TODO(Lennart): Replace with base::mutex when available
+#include <mutex>
+
+#include "smfd.h"
+#include "SmfUtils.hh"
+
+#include "saf_error.h"
+#include "logtrace.h"
+#include "osaf_utility.h"
+#include "saImmOi.h"
+#include "immutil.h"
+#include "base/time.h"
+#include "osaf_poll.h"
+#include "osaf_extended_name.h"
+
+/**
+ * Locals not needed outside of this file
+ */
+// Must be delclared here since it is used both in C callback functions and in
+// SmfImmApplierHdl class
+static std::string object_name_ = "";
+static std::string attribute_name_ = "";
+static std::string attribute_value_ = "";
+static bool attribute_value_is_valid_ = false;
+
+// Used to abort ongoing handler activity in case of Stop command
+// For example ongoing TRY_AGAIN handling in IMM APIs must be terminated
+static std::atomic<bool> is_cancel {false};
+
+// Mutex protecting attribute value
+// TODO: Replace std::mutex with base::mutex when base::mutex is available
+std::mutex attribute_value_lock;
+
+/**
+ * Local functions containing IMM operations needed here
+ **/
+
+/**
+ * Update the monitored value protected
+ * Note: Is not a method in SmfImmApplierHdl class since used by both
+ * C functions and in SmfImmApplierHdl class
+ */
+static void SetAttributeValue(const std::string& value) {
+ attribute_value_lock.lock();
+ attribute_value_ = value;
+ attribute_value_lock.unlock();
+}
+
+/**
+ * Read the value of the object and attribute
+ * Note1: This function uses an SMF specific IMM wrapper
+ * Note2: This may be replaced with a generic IMM wrapper when one has
+ * been implemented.
+ * Note3: This function can only read one attribute of type SaUint32T
+ *
+ */
+static std::string GetAttributeValueFromImm(const std::string& i_object_name,
+ const std::string& i_attribute_name) {
+ SaImmAttrValuesT_2 **attributes;
+ SmfImmUtils ImmCfg;
+
+ TRACE_ENTER();
+ if (i_object_name == "" || i_attribute_name == "") {
+ TRACE_LEAVE2("No object or attribute");
+ return "";
+ }
+
+ if (ImmCfg.getObject(i_object_name, &attributes) == false) {
+ LOG_WA("%s: Could not read IMM config object from IMM %s",
+ __FUNCTION__, IMM_CONFIG_OBJECT_DN);
+ }
+
+ const SaUint32T *attribute_value = immutil_getUint32Attr(
+ (const SaImmAttrValuesT_2 **) attributes,
+ i_attribute_name.c_str(), 0);
+
+ std::string long_dn_setting_as_string = "";
+ if (attribute_value != nullptr) {
+ long_dn_setting_as_string = std::to_string(*attribute_value);
+ } else {
+ LOG_NO("%s: Fail longDnsAllowed has no value", __FUNCTION__);
+ }
+
+ TRACE_LEAVE();
+ return long_dn_setting_as_string;
+}
+
+/**
+ * IMM API wrapper functions used instead of immutil.c
+ * All return false if Fail and log errors
+ * Note: To initialize IMM OI may take up to 60 seconds in a TRY AGAIN loop.
+ * In this loop the is_cancel flag is checked and if true the TRY AGAIN
+ * loop is canceled meaning that the applier is still not initialized
+ *
+ * TODO Replace with generic functions when implemented
+ */
+
+static bool InitializeImmOi(SaImmOiHandleT *o_immOiHandle,
+ const SaImmOiCallbacksT_2 *i_immOiCallbacks,
+ const SaVersionT *i_version) {
+ // It may take up to one minute to initialize if IMM is synchronizing
+ base::Timer adminOpTimer(60000);
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ bool rc = true;
+
+ SaVersionT version = *i_version;
+ while (adminOpTimer.is_timeout() == false) {
+ ais_rc = saImmOiInitialize_2(o_immOiHandle, i_immOiCallbacks, &version);
+ if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
+ base::Sleep(base::kFiveHundredMilliseconds);
+ if (is_cancel) {
+ is_cancel = false;
+ rc = false;
+ break;
+ } else {
+ continue;
+ }
+ } else if (ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiInitialize_2() Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ rc = false;
+ break;
+ } else {
+ // Done
+ break;
+ }
+ }
+ if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiInitialize_2() timeout Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ }
+
+ return rc;
+}
+
+static bool FinalizeImmOi(SaImmOiHandleT i_immOiHandle) {
+ base::Timer adminOpTimer(20000);
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ bool rc = true;
+
+ if (i_immOiHandle != 0) {
+ // Only if there is anything to finalize
+ while (adminOpTimer.is_timeout() == false) {
+ ais_rc = saImmOiFinalize(i_immOiHandle);
+ if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
+ base::Sleep(base::kFiveHundredMilliseconds);
+ continue;
+ } else if (ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiFinalize() Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ rc = false;
+ break;
+ } else {
+ // Done
+ break;
+ }
+ }
+ if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiFinalize() timeout Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ }
+ }
+
+ return rc;
+}
+
+static bool GetImmOiSelectionObject(SaImmOiHandleT i_immOiHandle,
+ SaSelectionObjectT *selectionObject) {
+ base::Timer adminOpTimer(20000);
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ bool rc = true;
+ TRACE_ENTER();
+
+ while (adminOpTimer.is_timeout() == false) {
+ ais_rc = saImmOiSelectionObjectGet(i_immOiHandle, selectionObject);
+ if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
+ base::Sleep(base::kFiveHundredMilliseconds);
+ continue;
+ } else if (ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiSelectionObjectGet() Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ rc = false;
+ break;
+ } else {
+ // Done
+ break;
+ }
+ }
+ if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiSelectionObjectGet() timeout Fail '%s'",
+ __FUNCTION__, saf_error(ais_rc));
+ }
+
+ TRACE_LEAVE();
+ return rc;
+}
+
+static bool ImmOiSet(SaImmOiHandleT i_immOiHandle,
+ const std::string& i_implementerName) {
+ base::Timer adminOpTimer(20000);
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ bool rc = true;
+ SaImmOiImplementerNameT implementerName =
+ const_cast<SaImmOiImplementerNameT>(i_implementerName.c_str());
+ TRACE_ENTER();
+
+ while (adminOpTimer.is_timeout() == false) {
+ ais_rc = saImmOiImplementerSet(i_immOiHandle, implementerName);
+ if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
+ base::Sleep(base::kFiveHundredMilliseconds);
+ continue;
+ } else if (ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiImplementerSet() Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ rc = false;
+ break;
+ } else {
+ // Done
+ break;
+ }
+ }
+ if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiImplementerSet() timeout Fail '%s'",
+ __FUNCTION__, saf_error(ais_rc));
+ }
+
+ TRACE_LEAVE();
+ return rc;
+}
+
+static bool ImmOiClear(SaImmOiHandleT i_immOiHandle) {
+ base::Timer adminOpTimer(20000);
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ bool rc = true;
+
+ while (adminOpTimer.is_timeout() == false) {
+ ais_rc = saImmOiImplementerClear(i_immOiHandle);
+ if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
+ base::Sleep(base::kFiveHundredMilliseconds);
+ continue;
+ } else if (ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiImplementerClear() Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ rc = false;
+ break;
+ } else {
+ // Done
+ break;
+ }
+ }
+ if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiImplementerClear() timeout Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ }
+
+ return rc;
+}
+
+/**
+ * Become applier for the given object. This starts the applier
+ */
+static bool SetImmOiForObject(SaImmOiHandleT i_immOiHandle,
+ const std::string& i_objectName,
+ SaImmScopeT i_scope) {
+ base::Timer adminOpTimer(20000);
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ bool rc = true;
+ SaNameT object_name;
+ osaf_extended_name_lend(i_objectName.c_str(), &object_name);
+
+ while (adminOpTimer.is_timeout() == false) {
+ ais_rc = saImmOiObjectImplementerSet(i_immOiHandle, &object_name, i_scope);
+ if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
+ base::Sleep(base::kFiveHundredMilliseconds);
+ continue;
+ } else if (ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiObjectImplementerSet() Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ rc = false;
+ break;
+ } else {
+ // Done
+ break;
+ }
+ }
+ if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiObjectImplementerSet() timeout Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ }
+
+ return rc;
+}
+
+/**
+ * Release the applier for the given object. This stops the applier
+ */
+static bool ReleaseImmOiForObject(SaImmOiHandleT i_immOiHandle,
+ const std::string& i_objectName,
+ SaImmScopeT i_scope) {
+ base::Timer adminOpTimer(20000);
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ bool rc = true;
+ SaNameT object_name;
+ osaf_extended_name_lend(i_objectName.c_str(), &object_name);
+
+ while (adminOpTimer.is_timeout() == false) {
+ ais_rc = saImmOiObjectImplementerRelease(i_immOiHandle, &object_name,
+ i_scope);
+ if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
+ base::Sleep(base::kFiveHundredMilliseconds);
+ continue;
+ } else if (ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiObjectImplementerRelease() Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ rc = false;
+ break;
+ } else {
+ // Done
+ break;
+ }
+ }
+ if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiObjectImplementerRelease() timeout Fail '%s'",
+ __FUNCTION__, saf_error(ais_rc));
+ }
+
+ return rc;
+}
+
+static SaAisErrorT DispatchOiCallback(SaImmOiHandleT i_immOiHandle,
+ SaDispatchFlagsT i_dispatchFlags) {
+ base::Timer dispatchTimer(20000);
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ TRACE_ENTER();
+
+ while (dispatchTimer.is_timeout() == false) {
+ ais_rc = saImmOiDispatch(i_immOiHandle, i_dispatchFlags);
+
+ if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
+ base::Sleep(base::kFiveHundredMilliseconds);
+ continue;
+ } else if (ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiDispatch() Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ break;
+ } else {
+ // Done
+ break;
+ }
+ }
+ if (dispatchTimer.is_timeout() == true && ais_rc != SA_AIS_OK) {
+ LOG_WA("%s: saImmOiDispatch() timeout Fail '%s'", __FUNCTION__,
+ saf_error(ais_rc));
+ }
+ TRACE_LEAVE();
+ return ais_rc;
+}
+
+/**
+ * The applier callback functions
+ * These are C functions as specified by IMM AIS SaImmOiCallbacksT_2
+ * Note: CCB is "collected" using existing list handling in immutil.c
+ **/
+
+/**
+ * Save ccb info if OpensafConfig object is modified
+ *
+ */
+static SaAisErrorT CcbObjectModifyCallback(SaImmOiHandleT immOiHandle,
+ SaImmOiCcbIdT ccbId,
+ const SaNameT *objectName,
+ const SaImmAttrModificationT_2 **attrMods)
{
+ SaAisErrorT rc = SA_AIS_OK;
+ struct CcbUtilCcbData *ccbUtilCcbData;
+
+ TRACE_ENTER();
+
+ if ((ccbUtilCcbData = ccbutil_findCcbData(ccbId)) == nullptr) {
+ if ((ccbUtilCcbData = ccbutil_getCcbData(ccbId)) == nullptr) {
+ TRACE("%s: Failed to get CCB object for %llu", __FUNCTION__, ccbId);
+ rc = SA_AIS_ERR_NO_MEMORY;
+ goto done;
+ }
+ }
+
+ ccbutil_ccbAddModifyOperation(ccbUtilCcbData, objectName, attrMods);
+
+done:
+ TRACE_LEAVE();
+ return rc;
+}
+
+/**
+ * Get the new value of the attribute
+ * Note: This function is limited to handle one attribute in one object and
+ * the type of the attribute must be SaUint32T
+ */
+static void CcbApplyCallback(SaImmOiHandleT immOiHandle, SaImmOiCcbIdT ccbId) {
+ struct CcbUtilCcbData *ccbUtilCcbData;
+ struct CcbUtilOperationData *opdata;
+ const SaImmAttrModificationT_2 *attrMod;
+ SaConstStringT objName;
+ SaImmAttrValuesT_2 attribute;
+
+ // Note: Only one value of type SaUint32T can be handled
+ SaUint32T *value = nullptr;
+
+ TRACE_ENTER();
+
+ /* Verify the ccb */
+ if ((ccbUtilCcbData = ccbutil_findCcbData(ccbId)) == nullptr) {
+ LOG_NO("%s: Failed to find CCB object for id %llu", __FUNCTION__, ccbId);
+ goto done;
+ }
+
+ /* We don't need to loop since the only possible operation is MODIFY
+ * and only one object is monitored
+ */
+ opdata = ccbUtilCcbData->operationListHead;
+ if (opdata->operationType != CCBUTIL_MODIFY) {
+ TRACE("%s: Not a modify operation", __FUNCTION__);
+ goto done;
+ }
+
+ objName = osaf_extended_name_borrow(&opdata->objectName);
+ if (object_name_.compare(objName) != 0) {
+ TRACE("%s: Object \"%s\" not an OpensafConfig object",
+ __FUNCTION__, objName);
+ goto done;
+ }
+
+ /* Read value in opensafNetworkName
+ * Note: This is implemented as a loop in case more attributes are
+ * added in the class in the future. For now the only
+ * attribute of interest here is opensafNetworkName
+ */
+ TRACE("%s: Read value in attributes", __FUNCTION__);
+ attrMod = opdata->param.modify.attrMods[0];
+ attribute = attrMod->modAttr;
+
+ for (int i = 1; attrMod != nullptr; i++) {
+ /* Get the value */
+ if (attribute_name_.compare(attribute.attrName) != 0) {
+ // Not found
+ attrMod = opdata->param.modify.attrMods[i];
+ continue;
+ }
+
+ // Attribute found
+ value = static_cast<SaUint32T*> (attribute.attrValues[0]);
+ break;
+ }
+
+ if (value == nullptr) {
+ TRACE("%s: Value is nullptr", __FUNCTION__);
+ SetAttributeValue("");
+ attribute_value_is_valid_ = false;
+ } else {
+ SetAttributeValue(std::to_string(*value));
+ attribute_value_is_valid_ = true;
+ }
+
+done:
+ if (ccbUtilCcbData != nullptr)
+ ccbutil_deleteCcbData(ccbUtilCcbData);
+
+ TRACE_LEAVE();
+}
+
+/**
+ * Cleanup by deleting saved ccb info if aborted
+ *
+ */
+static void CcbAbortCallback(SaImmOiHandleT immOiHandle, SaImmOiCcbIdT ccbId) {
+ struct CcbUtilCcbData *ccbUtilCcbData;
+
+ TRACE_ENTER2("CCB ID %llu", ccbId);
+
+ if ((ccbUtilCcbData = ccbutil_findCcbData(ccbId)) != nullptr)
+ ccbutil_deleteCcbData(ccbUtilCcbData);
+ else
+ TRACE("%s: Failed to find CCB object for %llu", __FUNCTION__, ccbId);
+
+ TRACE_LEAVE();
+}
+
+/**
+ * An object of OpensafConfig class is created. We don't have to do anything
+ * Cannot be replaced by nullptr pointer in callback list
+ */
+static SaAisErrorT CcbCreateCallback(SaImmOiHandleT immOiHandle,
+ SaImmOiCcbIdT ccbId,
+ const SaImmClassNameT className,
+ const SaNameT *parentName,
+ const SaImmAttrValuesT_2 **attr) {
+ TRACE_ENTER();
+ TRACE_LEAVE();
+ return SA_AIS_OK;
+}
+
+/**
+ * An object of OpensafConfig class is deleted. We don't have to do anything
+ * Cannot be replaced by nullptr pointer in callback list
+ */
+static SaAisErrorT CcbDeleteCallback(SaImmOiHandleT immOiHandle,
+ SaImmOiCcbIdT ccbId,
+ const SaNameT *objectName) {
+ TRACE_ENTER();
+ TRACE_LEAVE();
+ return SA_AIS_OK;
+}
+
+/* Callback function list given to IMM when OI is initialized
+ * We need:
+ * Modify for saving modify ccb
+ * Apply for knowing that the modification has been applied
+ * Abort for removing saved ccb in case of an abortion of ccb
+ */
+static const SaImmOiCallbacksT_2 callbacks = {
+ .saImmOiAdminOperationCallback = nullptr,
+ .saImmOiCcbAbortCallback = CcbAbortCallback,
+ .saImmOiCcbApplyCallback = CcbApplyCallback,
+ .saImmOiCcbCompletedCallback = nullptr,
+ .saImmOiCcbObjectCreateCallback = CcbCreateCallback,
+ .saImmOiCcbObjectDeleteCallback = CcbDeleteCallback,
+ .saImmOiCcbObjectModifyCallback = CcbObjectModifyCallback,
+ .saImmOiRtAttrUpdateCallback = nullptr
+};
+
+// =====================================
+// SmfImmApplierHdl Class implementation
+// =====================================
+// Make next_instance_number_ thread safe
+std::atomic<unsigned int> SmfImmApplierHdl::instance_number_{1};
+SmfImmApplierHdl::SmfImmApplierHdl() :
+ isCreated_ {false},
+ imm_appl_hdl_ {0},
+ imm_appl_selobj_ {0} {
+ applier_name_ = "@safSmf_applier"+std::to_string(instance_number_++);
+}
+
+SmfImmApplierHdl::~SmfImmApplierHdl() {
+ TRACE_ENTER();
+ Remove();
+ TRACE_LEAVE();
+}
+
+void SmfImmApplierHdl::Remove() {
+ // Release all resources, give up applier, remove applier name and finalize
OI
+ if (Stop() == false) {
+ LOG_NO("%s: ReleaseImmOiForObject Fail", __FUNCTION__);
+ }
+ if (ImmOiClear(imm_appl_hdl_) == false) {
+ LOG_NO("%s: ImmOiClear() Fail", __FUNCTION__);
+ }
+ if (FinalizeImmOi(imm_appl_hdl_) == false) {
+ LOG_NO("%s: FinalizeImmOi() Fail", __FUNCTION__);
+ }
+}
+
+bool SmfImmApplierHdl::Create(const ApplierSetupInfo& setup_info) {
+ bool do_continue = true;
+ TRACE_ENTER();
+
+ is_cancel = false;
+ if (imm_appl_hdl_ == 0) {
+ // If initialize is needed
+ TRACE("%s: Do create", __FUNCTION__);
+ object_name_ = setup_info.object_name;
+ attribute_name_ = setup_info.attribute_name;
+ attribute_value_is_valid_ = false;
+
+ // Initialize
+ do_continue = InitializeImmOi(&imm_appl_hdl_, &callbacks, &kImmVersion);
+ TRACE("%s: InitializeImmOi() = %s", __FUNCTION__,
+ do_continue? "true": "false");
+
+ // Get selection object
+ if (do_continue) {
+ do_continue = GetImmOiSelectionObject(imm_appl_hdl_, &imm_appl_selobj_);
+ TRACE("%s: GetImmOiSelectionObject() = %s", __FUNCTION__,
+ do_continue? "true": "false");
+ }
+ }
+
+ TRACE_LEAVE();
+ return do_continue;
+}
+
+bool SmfImmApplierHdl::Start() {
+ std::string value;
+ bool do_continue = true;
+
+ TRACE_ENTER();
+ is_cancel = false;
+
+ // OI Set
+ // Note: If the applier name already exist it is because SMF on another
+ // node has created an applier with the same name. This not ok for an
+ // object implementer but is ok for an applier.
+ // Create a new name and try again. Limit number of retries
+ for (int i = 0; i < 3; i++) {
+ do_continue = ImmOiSet(imm_appl_hdl_, applier_name_);
+
+ if (do_continue) {
+ break;
+ } else {
+ // Create a new name and try again
+ applier_name_ = "@safSmf_applier"+std::to_string(instance_number_++);
+ LOG_NO("%s: A new applier name is created '%s'",
+ __FUNCTION__, applier_name_.c_str());
+ }
+ }
+
+ // Set which object to monitor
+ if (do_continue) {
+ do_continue = SetImmOiForObject(imm_appl_hdl_, object_name_, SA_IMM_ONE);
+ TRACE("%s: SetImmOiForObject() = %s", __FUNCTION__,
+ do_continue? "true": "false");
+
+ if (do_continue) {
+ if (attribute_value_is_valid_ == false) {
+ // Get the current value from IMM
+ value = GetAttributeValueFromImm(object_name_, attribute_name_);
+ TRACE("%s: GetAttributeValueFromImm() = '%s'",
+ __FUNCTION__, value.c_str());
+ }
+ if (value != "") {
+ attribute_value_is_valid_ = true;
+ }
+ SetAttributeValue(value);
+ TRACE("%s: SetAttributeValue(%s), "
+ "attribute_value_is_valid_ = %s", __FUNCTION__, value.c_str(),
+ attribute_value_is_valid_? "true": "false");
+ }
+ }
+
+ if (do_continue == false) {
+ LOG_WA("%s: Applier could not be started", __FUNCTION__);
+ }
+
+ TRACE_LEAVE();
+ return do_continue;
+}
+
+bool SmfImmApplierHdl::Stop() {
+ bool rc = true;
+
+ TRACE_ENTER();
+
+ is_cancel = true;
+ attribute_value_is_valid_ = false;
+ SetAttributeValue("");
+
+ if (imm_appl_hdl_ != 0) {
+ rc = ReleaseImmOiForObject(imm_appl_hdl_, object_name_, SA_IMM_ONE);
+ if (rc == false) {
+ LOG_NO("%s: ReleaseImmOiForObject() Fail", __FUNCTION__);
+ }
+
+ rc = ImmOiClear(imm_appl_hdl_);
+ if (rc == false) {
+ LOG_NO("%s: ImmOiClear Fail", __FUNCTION__);
+ }
+ }
+ TRACE_LEAVE2("rc = %s", rc? "true": "false");
+ return rc;
+}
+
+void SmfImmApplierHdl::CancelCreate() {
+ is_cancel = true;
+}
+
+std::string SmfImmApplierHdl::get_value() {
+ attribute_value_lock.lock();
+ std::string value = attribute_value_;
+ attribute_value_lock.unlock();
+ return value;
+}
+
+ExecuteImmCallbackReply SmfImmApplierHdl::ExecuteImmCallback() {
+ ExecuteImmCallbackReply method_rc = ExecuteImmCallbackReply::kOk;
+
+ TRACE_ENTER();
+ SaAisErrorT ais_rc = DispatchOiCallback(imm_appl_hdl_, SA_DISPATCH_ALL);
+
+ if (ais_rc == SA_AIS_OK) {
+ method_rc = ExecuteImmCallbackReply::kOk;
+ } else if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
+ struct ApplierSetupInfo setup;
+ setup.object_name = object_name_;
+ setup.attribute_name = attribute_name_;
+ imm_appl_hdl_ = 0;
+ bool is_ok = Create(setup);
+ if (is_ok) {
+ method_rc = ExecuteImmCallbackReply::kGetNewSelctionObject;
+ } else {
+ method_rc = ExecuteImmCallbackReply::kError;
+ }
+ } else {
+ method_rc = ExecuteImmCallbackReply::kError;
+ }
+
+ TRACE_LEAVE();
+ return method_rc;
+}
diff --git a/osaf/services/saf/smfsv/smfd/SmfImmApplierHdl.hh
b/osaf/services/saf/smfsv/smfd/SmfImmApplierHdl.hh
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/smfsv/smfd/SmfImmApplierHdl.hh
@@ -0,0 +1,113 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ *
+ * 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 <string>
+#include <atomic>
+
+#include "base/macros.h"
+#include "saImmOi.h"
+
+#ifndef SMFIMMAPPLIERHDL_HH
+#define SMFIMMAPPLIERHDL_HH
+
+/**
+ * This class creates and handle an IMM applier
+ * The handler must be used in an "outer" thread that implements a poll loop
+ * The thread shall get a selection object (poll fd) and call the
+ * ExecuteImmCallback() method when released
+ *
+ * Note/Warning:
+ * The IMM object applier handle may be set to invalid by IMM. This will be
+ * detected and handled in the ExecuteImmCallback() method. This method will
+ * not return until the applier is restored or timed out which may take up to
+ * one minute.
+ * Do not use this handler in a thread that cannot handle this!
+ *
+ * In this version the following limitations apply:
+ * - Only one IMM object can be monitored
+ * - Only modifications of one attribute can be handled
+ * - All values are given as a std::string. The user has to convert to other
+ * type if needed
+ */
+
+// In-parameter for SmfImmApplierHdl Create())
+struct ApplierSetupInfo {
+ std::string object_name;
+ std::string attribute_name;
+ //SaImmOiCcbApplyCallbackT ApplyCallbackFunction;
+};
+
+enum class ExecuteImmCallbackReply {
+ kOk = 0,
+ kGetNewSelctionObject,
+ kError
+};
+
+class SmfImmApplierHdl {
+ public:
+ SmfImmApplierHdl(void);
+ ~SmfImmApplierHdl(void);
+
+ // Create an applier for monitoring changes of one attribute in one object
+ // The applier is not started. To start use Start() method
+ // Note: Create() must be called before Start() and Stop() can be used
+ // Return false if Fail
+ bool Create(const ApplierSetupInfo& setup_info);
+
+ // Cancel an ongoing create operation that may take a long time.
+ // The saImmOiInitialize_2() (see IMM documentation) must have a TRY AGAIN
+ // loop that may take up to one minute.
+ // This method can be used by an applier that uses a thread for IMM handling
+ // from outside the thread to cancel an ongoing create operation that may
+ // hang the thread
+ void CancelCreate(void);
+
+ // Start the applier
+ // Return false if Fail
+ bool Start(void);
+
+ // Finalize all resources used by the applier
+ // Return false if Fail
+ bool Stop(void);
+
+ // Remove the applier by freeing all IMM resources
+ void Remove(void);
+
+ // Get the monitored value
+ // If there is no valid value an empty string is returned
+ std::string get_value(void);
+
+ // Used with poll loop (fd)
+ SaSelectionObjectT get_selection_object(void) { return imm_appl_selobj_; }
+
+ // Uses saImmOiDispatch to call the appropriate callback function
+ // Shall be called when the selection object releases the poll loop
+ // If return code is kGetNewSelctionObject the applier has been restored and
+ // the selection object has to be updated
+ ExecuteImmCallbackReply ExecuteImmCallback(void);
+
+ private:
+ const SaVersionT kImmVersion = { 'A', 2, 11 };
+ static std::atomic<unsigned int> instance_number_;
+ bool isCreated_;
+ std::string applier_name_;
+ SaImmOiHandleT imm_appl_hdl_;
+ SaSelectionObjectT imm_appl_selobj_;
+};
+
+#endif /* SMFIMMAPPLIERHDL_HH */
diff --git a/osaf/services/saf/smfsv/smfd/SmfImmOperation.cc
b/osaf/services/saf/smfsv/smfd/SmfImmOperation.cc
--- a/osaf/services/saf/smfsv/smfd/SmfImmOperation.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfImmOperation.cc
@@ -34,6 +34,7 @@
#include <saImm.h>
#include <saf_error.h>
#include "osaf_extended_name.h"
+#include "smfd_long_dn.hh"
/* ========================================================================
* DEFINITIONS
@@ -391,9 +392,9 @@ SmfImmCreateOperation::execute(SmfRollba
const char *className = m_className.c_str();
- if (m_parentDn.length() > smfd_cb->maxDnLength) {
+ if (m_parentDn.length() > GetSmfMaxDnLength()) {
LOG_NO("Object create op failed, parent name too long [%zu]
max=[%zu], parent=[%s]",
- m_parentDn.length(),
static_cast<size_t>(smfd_cb->maxDnLength),
+ m_parentDn.length(),
static_cast<size_t>(GetSmfMaxDnLength()),
m_parentDn.c_str());
TRACE_LEAVE();
return SA_AIS_ERR_NAME_TOO_LONG;
@@ -629,7 +630,7 @@ SmfImmDeleteOperation::execute(SmfRollba
return SA_AIS_ERR_UNAVAILABLE;
}
- if (m_dn.length() > smfd_cb->maxDnLength) {
+ if (m_dn.length() > GetSmfMaxDnLength()) {
LOG_NO("SmfImmDeleteOperation::execute: failed Too long dn %zu",
m_dn.length());
TRACE_LEAVE();
@@ -1005,7 +1006,7 @@ SmfImmModifyOperation::execute(SmfRollba
return SA_AIS_ERR_UNAVAILABLE;
}
- if (m_dn.length() > smfd_cb->maxDnLength) {
+ if (m_dn.length() > GetSmfMaxDnLength()) {
LOG_NO("SmfImmModifOperation::execute: failed Too long dn %zu",
m_dn.length());
TRACE_LEAVE();
@@ -1290,7 +1291,7 @@ SmfImmRTCreateOperation::execute()
const char *className = m_className.c_str();
- if (m_parentDn.length() > smfd_cb->maxDnLength) {
+ if (m_parentDn.length() > GetSmfMaxDnLength()) {
LOG_NO("SmfImmRTCreateOperation::execute, createObject failed
Too long parent name %zu",
m_parentDn.length());
TRACE_LEAVE();
@@ -1483,9 +1484,9 @@ SmfImmRTUpdateOperation::execute()
goto exit;
}
- if (m_dn.length() > smfd_cb->maxDnLength) {
+ if (m_dn.length() > GetSmfMaxDnLength()) {
LOG_NO("SmfImmRTUpdateOperation::execute, too long DN [%zu],
max=[%zu], dn=[%s]",
- m_dn.length(), static_cast<size_t>(smfd_cb->maxDnLength),
m_dn.c_str());
+ m_dn.length(), static_cast<size_t>(GetSmfMaxDnLength()),
m_dn.c_str());
result = SA_AIS_ERR_NAME_TOO_LONG;
goto exit;
}
diff --git a/osaf/services/saf/smfsv/smfd/SmfLongDnApplier.cc
b/osaf/services/saf/smfsv/smfd/SmfLongDnApplier.cc
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/smfsv/smfd/SmfLongDnApplier.cc
@@ -0,0 +1,441 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * 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 <thread>
+#include <atomic>
+#include <memory>
+
+#include "SmfLongDnApplier.hh"
+#include "SmfImmApplierHdl.hh"
+#include "smfd.h"
+#include "SmfUtils.hh"
+
+#include "saf_error.h"
+#include "logtrace.h"
+#include "osaf_utility.h"
+#include "osaf_time.h"
+#include "osaf_poll.h"
+#include "base/time.h"
+
+/**
+ * Local definitions not needed outside of this file
+ */
+
+/* Inter thread communication (via socket pair) */
+static const char* CMD_STOP = "s";
+static const char* CMD_START = "a";
+static const char* CMD_REMOVE = "r";
+static const size_t CMD_SIZE = 2;
+
+static int socket_fd_thread = 0; // Socket for thread to read commands
+static int socket_fd_command = 0; // Socket for commands to thread
+
+/* States for the applier thread. Stopping and starting the applier is handled
+ * differently dependent on the thread state
+ */
+enum class th_state{
+ /* Thread not started */
+ TH_NOT_CREATED = 0,
+ /* Thread is started but has not yet entered the event handling poll loop */
+ TH_CREATING,
+ /* Thread is fully started and running as applier */
+ TH_IS_APPLIER,
+ /* Thread is fully started but is not running as applier. In this state
+ * it can service commands e.g. start applier command but has never
+ * become an applier or have given up the applier role
+ */
+ TH_IDLE,
+ /* Thread is terminating */
+ TH_TERMINATING
+};
+
+static std::atomic<th_state> th_state_info {th_state::TH_NOT_CREATED};
+
+/**
+ * These functions should be here so that also TRACEes can be made in the
future
+ * that prints the thread command and states as strings for better readability
+ */
+// cppcheck-suppress unusedFunction
+const char *th_statestr(th_state state) {
+ switch (state) {
+ case th_state::TH_CREATING: return "CREATING";
+ case th_state::TH_IDLE: return "IDLE";
+ case th_state::TH_IS_APPLIER: return "IS APPLIER";
+ case th_state::TH_NOT_CREATED: return "NOT_CREATED";
+ case th_state::TH_TERMINATING: return "TERMINATING";
+ default: return "UNKNOWN STATE";
+ }
+}
+
+// cppcheck-suppress unusedFunction
+const char *th_cmdstr(th_cmd cmd) {
+ switch (cmd) {
+ case th_cmd::AP_REMOVE: return "REMOVE";
+ case th_cmd::AP_START: return "START";
+ case th_cmd::AP_STOP: return "STOP";
+ default: return "UNKNOWN CMD";
+ }
+}
+
+// The thread function
+// This is the thread where the applier is running.
+// For communication with the thread a socket pair is used. Input
+// command_socket shall contain the fd to be used in the thread
+// Thread can be stopped if CMD_REMOVE command or if applier error.
+// If the thread is stopped the applier handler is removed and thread state is
+// set to TH_NOT_STARTED
+// Note:
+// This function is started as a thread using C++11 thread(). Parameters cannot
+// be passed as reference in the "normal" way. Also this function is used once
+//
+// cppcheck-suppress passedByValue
+static void ApplierThread(const std::string object_name,
+// cppcheck-suppress passedByValue
+ const std::string attribute_name,
+ SmfImmApplierHdl *ApplierHdl,
+ const int command_socket) {
+ /* Event handling
+ * Note:
+ * IMM selection object can only be part of polling when IMM OI is
+ * initialized. If IMM is finalized the selection object is not valid.
+ * This is handled by placing IMM selection fd as last element in fds
+ * vector and decrease and decrease nfds when IMM is finalized.
+ */
+ enum {
+ FDA_COM = 0, /* Communication events */
+ FDA_IMM, /* IMM events */
+ NUM_FDA
+ };
+
+ thread_local struct pollfd fds[NUM_FDA];
+ ExecuteImmCallbackReply execute_rc = ExecuteImmCallbackReply::kOk;
+
+ TRACE("%s: %s, %s, %d", __FUNCTION__, object_name.c_str(),
+ attribute_name.c_str(), command_socket);
+
+ th_state_info = th_state::TH_CREATING;
+
+ // Create the applier
+ ApplierSetupInfo setup_info {object_name, attribute_name};
+ bool create_rc = ApplierHdl->Create(setup_info);
+ if (create_rc == false) {
+ LOG_WA("%s: Creation of long DN applier Fail", __FUNCTION__);
+ th_state_info = th_state::TH_NOT_CREATED;
+ return; // Terminate the thread
+ }
+
+ // Setup event handling
+ fds[FDA_IMM].fd = ApplierHdl->get_selection_object();
+ fds[FDA_IMM].events = POLLIN;
+ fds[FDA_COM].fd = command_socket;
+ fds[FDA_COM].events = POLLIN;
+ thread_local nfds_t nfds = NUM_FDA;
+
+ th_state_info = th_state::TH_IDLE;
+
+ TRACE("%s: Applier is created, th_state_info = %s",
+ __FUNCTION__, th_statestr(th_state_info));
+
+ while(1) {
+ (void) osaf_poll(fds, nfds, -1);
+
+ // Handle IMM callback
+ if (fds[FDA_IMM].revents & POLLIN) {
+ TRACE("%s: IMM event", __FUNCTION__);
+
+ // Note: ExecuteImmCallback can "hang" for up to one minute if IMM
+ // has "invalidated" the OI handle and ExecuteImmCallback has to restore
+ // the applier. Such a restore can be canceled and that must be done
+ // before sending a stop command to this thread
+ execute_rc = ApplierHdl->ExecuteImmCallback();
+ if (execute_rc == ExecuteImmCallbackReply::kGetNewSelctionObject) {
+ fds[FDA_IMM].fd = ApplierHdl->get_selection_object();
+ } else if (execute_rc == ExecuteImmCallbackReply::kError) {
+ LOG_WA("%s: ExecuteImmCallback Error", __FUNCTION__);
+ th_state_info = th_state::TH_NOT_CREATED;
+ break; // Thread exit
+ }
+ }
+
+ // Handle commands
+ if (fds[FDA_COM].revents & POLLIN) {
+ TRACE("%s: COM event", __FUNCTION__);
+
+ char cmd_str[256] = {0};
+ int read_rc = 0;
+ while (1) {
+ read_rc = read(command_socket, cmd_str, 256);
+ if ((read_rc == -1) && (errno == EINTR)) {
+ /* Try again */
+ continue;
+ } else break;
+ }
+
+ if (read_rc == -1) {
+ LOG_WA("%s: Read socket Fail %s", __FUNCTION__, strerror(errno));
+ break; // Terminate thread
+ }
+
+ TRACE("%s: Command is: '%s'", __FUNCTION__, cmd_str);
+
+ if (strcmp(cmd_str, CMD_STOP) == 0) {
+ TRACE("%s: STOP received", __FUNCTION__);
+ if (ApplierHdl->Stop() == false) {
+ LOG_WA("%s: Applier.Stop() Fail", __FUNCTION__);
+ th_state_info = th_state::TH_NOT_CREATED;
+ ApplierHdl->Remove();
+ break; // Terminate thread
+ } else {
+ th_state_info = th_state::TH_IDLE;
+ }
+ } else if (strcmp(cmd_str, CMD_START) == 0) {
+ TRACE("%s: START received", __FUNCTION__);
+ if (ApplierHdl->Start() == false) {
+ LOG_NO("%s: Applier.Start() Fail", __FUNCTION__);
+ th_state_info = th_state::TH_TERMINATING;
+ ApplierHdl->Remove();
+ break; // Terminate thread
+ } else {
+ th_state_info = th_state::TH_IS_APPLIER;
+ }
+ } else if (strcmp(cmd_str, CMD_REMOVE) == 0) {
+ TRACE("%s: EXIT received", __FUNCTION__);
+ th_state_info = th_state::TH_TERMINATING;
+ ApplierHdl->Remove();
+ break; // Thread exit
+ }
+ }
+ } /* END Event handling loop */
+ LOG_NO("%s: Thread is terminated", __FUNCTION__);
+ th_state_info = th_state::TH_NOT_CREATED;
+}
+
+// ===================
+// SmLongDnApplier class
+// ===================
+SmfLongDnApplier::SmfLongDnApplier(const std::string& object_name,
+ const std::string& attribute_name) :
+ object_name_{object_name},
+ attribute_name_{attribute_name} {
+ TRACE_ENTER();
+ ApplierHdl_ = new SmfImmApplierHdl();
+ TRACE_LEAVE();
+}
+
+SmfLongDnApplier::~SmfLongDnApplier() {
+ // Stop/Finalize the applier including thread termination
+ TRACE_ENTER2();
+ Remove();
+ delete ApplierHdl_;
+ TRACE_LEAVE2();
+}
+
+void SmfLongDnApplier::Start() {
+ TRACE_ENTER();
+ if ((th_state_info == th_state::TH_IDLE) ||
+ (th_state_info == th_state::TH_CREATING)){
+ TRACE("%s: Sending START to thread", __FUNCTION__);
+ SendCommandToThread(th_cmd::AP_START);
+ } else {
+ LOG_WA("%s: Trying to start an applier that is not created",
+ __FUNCTION__);
+ // Try to recover by creating and start again. We may end up in this
+ // situation if creation or IMM bad handle recovery was canceled by a
+ // stop request
+ Create();
+ if ((th_state_info == th_state::TH_IDLE) ||
+ (th_state_info == th_state::TH_CREATING)){
+ TRACE("%s: Re-sending START to thread", __FUNCTION__);
+ SendCommandToThread(th_cmd::AP_START);
+ } else {
+ LOG_ER("%s: Cannot create and start "
+ "the long dn monitoring applier", __FUNCTION__);
+ }
+ }
+ TRACE_LEAVE();
+}
+
+void SmfLongDnApplier::Stop() {
+ TRACE_ENTER();
+ // Try to stop applier only if an applier is running
+ if (th_state_info == th_state::TH_IS_APPLIER) {
+ TRACE("%s: Sending STOP to thread", __FUNCTION__);
+ // If there is an ongoing IMM initialization TRY AGAIN loop it must be
+ // canceled so that the stop command can be executed immediately
+ ApplierHdl_->CancelCreate();
+ SendCommandToThread(th_cmd::AP_STOP);
+
+ // Wait until thread is in idle state before returning
+ // This guarantees that the applier is stopped and can be started
+ // on another node.
+ base::Timer applier_stop_timer (1000); // ms
+ while (applier_stop_timer.is_timeout() == false) {
+ if (th_state_info != th_state::TH_IS_APPLIER)
+ break; // Is stopped
+ base::Sleep(base::kTenMilliseconds);
+ }
+ if (th_state_info == th_state::TH_IS_APPLIER) {
+ // Timeout: This should never happen
+ LOG_ER("%s: Applier cold not be stopped within 1 sec",
+ __FUNCTION__);
+ }
+ TRACE("%s: STOP done. Thread state is %s", __FUNCTION__,
+ th_statestr(th_state_info));
+ } else {
+ LOG_WA("%s: Trying to stop an applier that is not running",
+ __FUNCTION__);
+ }
+ TRACE_LEAVE();
+}
+
+void SmfLongDnApplier::Create() {
+ TRACE_ENTER();
+ // Do not try to create if already created is creating or is terminating
+ if (th_state_info == th_state::TH_NOT_CREATED) {
+ // Create socket pair for communication with applier thread
+ // Note: Non block is used. This makes it possible to handle EAGAIN as an
+ // error. Commands shall not be queued so the buffer should never be full
+ int sock_fd[2] = {0};
+ int rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fd);
+ if (rc == -1) {
+ LOG_ER("%s: socketpair() Fail %s", __FUNCTION__, strerror(errno));
+ osaf_abort(0);
+ }
+
+ fcntl(sock_fd[0], F_SETFL, O_NONBLOCK);
+ fcntl(sock_fd[1], F_SETFL, O_NONBLOCK);
+ socket_fd_thread = sock_fd[0];
+ socket_fd_command = sock_fd[1];
+
+ // Start the thread
+ std::thread t1 {ApplierThread, object_name_, attribute_name_,
+ ApplierHdl_, socket_fd_thread};
+ t1.detach();
+ TRACE("%s: Thread is started", __FUNCTION__);
+
+ // For synchronization, Wait for thread to enter CREATING state
+ // Note: Thread shall enter CREATING state immediately after it has been
+ // started
+ int i = 0;
+ for (i = 0; i < 10; i++) {
+ if (th_state_info != th_state::TH_NOT_CREATED) break;
+ base::Sleep(base::kTenMilliseconds);
+ }
+ if (th_state_info == th_state::TH_NOT_CREATED) {
+ LOG_WA("%s: Applier thread has not started within 100 ms",
+ __FUNCTION__);
+ }
+ } else {
+ LOG_WA("%s: Trying to create an already created applier",
+ __FUNCTION__);
+ }
+ TRACE_LEAVE();
+}
+
+// --------------------
+// The private method's
+// --------------------
+
+// Terminates the applier by sending a remove command to the thread
+// The thread will remove the applier and terminate
+void SmfLongDnApplier::Remove() {
+ TRACE_ENTER();
+ // First check if there is any applier to terminate
+ if (th_state_info == th_state::TH_NOT_CREATED) {
+ LOG_NO("%s: Trying to remove an applier that is not created",
+ __FUNCTION__);
+ return;
+ }
+
+ // Finalize the applier and terminate the thread
+ ApplierHdl_->CancelCreate();
+ SendCommandToThread(th_cmd::AP_REMOVE);
+
+ TRACE("%s: REMOVE command sent. Waiting for termination of thread",
+ __FUNCTION__);
+ // Wait for thread to terminate. For synchronizing
+ base::Timer terminate_timeout(10000); // ms
+ while (terminate_timeout.is_timeout() == false) {
+ if (th_state_info == th_state::TH_NOT_CREATED)
+ break; // Thread has terminated
+ base::Sleep(base::kOneHundredMilliseconds);
+ }
+ if (th_state_info != th_state::TH_NOT_CREATED) {
+ // Should not be possible
+ LOG_ER("%s: Applier thread termination Failed. Thread state is '%s'",
+ __FUNCTION__, th_statestr(th_state_info));
+ osaf_abort(0);
+ }
+ TRACE("%s: Thread has terminated thread state is %s", __FUNCTION__,
+ th_statestr(th_state_info));
+
+ CloseSockets();
+ TRACE_LEAVE();
+}
+
+void SmfLongDnApplier::CloseSockets() {
+ TRACE_ENTER();
+ if (socket_fd_thread != 0) {
+ close(socket_fd_thread);
+ socket_fd_thread = 0;
+ }
+
+ if (socket_fd_command != 0) {
+ close(socket_fd_command);
+ socket_fd_command = 0;
+ }
+ TRACE_LEAVE();
+}
+
+void SmfLongDnApplier::SendCommandToThread(th_cmd command) {
+ const char *cmd_str = nullptr;
+ int rc = 0;
+
+ TRACE_ENTER2("Command %s", th_cmdstr(command));
+
+ switch (command) {
+ case th_cmd::AP_START:
+ cmd_str = CMD_START;
+ break;
+ case th_cmd::AP_STOP:
+ cmd_str = CMD_STOP;
+ break;
+ case th_cmd::AP_REMOVE:
+ cmd_str = CMD_REMOVE;
+ break;
+ default:
+ LOG_ER("%s: Unknown command %d", __FUNCTION__, command);
+ osaf_abort(0);
+ }
+
+ while (1) {
+ rc = write(socket_fd_command, cmd_str, CMD_SIZE);
+ if ((rc == -1) && (errno == EINTR))
+ /* Try again */
+ continue;
+ else
+ break;
+ }
+
+ if (rc == -1) {
+ LOG_ER("%s: Write Fail %s", __FUNCTION__, strerror(errno));
+ osaf_abort(0);
+ }
+
+ TRACE_LEAVE();
+}
+
diff --git a/osaf/services/saf/smfsv/smfd/SmfLongDnApplier.hh
b/osaf/services/saf/smfsv/smfd/SmfLongDnApplier.hh
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/smfsv/smfd/SmfLongDnApplier.hh
@@ -0,0 +1,84 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ *
+ * 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 <string>
+#include <memory>
+
+#include "base/macros.h"
+#include "SmfImmApplierHdl.hh"
+
+#ifndef SMFIMMAPPLIER_HH
+#define SMFIMMAPPLIER_HH
+
+// Commands that can be used with thread
+enum class th_cmd {
+ AP_START,
+ AP_STOP,
+ AP_REMOVE
+};
+
+/**
+ * This class implements an IMM applier for monitoring long Dn setting
+ * The applier is running in a separate thread.
+ * The thread implements a poll loop handling IMM callback and start/stop
+ * commands using the SmfImmApplierHdl class
+ * For communicating commands to the thread a socket pair is used
+ */
+class SmfLongDnApplier {
+ public:
+ SmfLongDnApplier(const std::string& object_name,
+ const std::string& attribute_name);
+
+ ~SmfLongDnApplier(void);
+
+ // Creates the applier thread
+ // The thread will create but not start the applier
+ void Create(void);
+
+ // Start an applier (in a separate thread).
+ void Start(void);
+
+ // Stop the applier.
+ // Wait until the applier is stopped
+ void Stop(void);
+
+ // Return true if long-dn is allowed based on setting in IMM configuration
+ // object
+ bool getValue(void) {
+ std::string value_str = ApplierHdl_->get_value();
+ if (value_str != "") {
+ return std::stoul(value_str, nullptr, 0) != 0? true: false;
+ } else {
+ return false;
+ }
+ }
+
+ private:
+ void Remove(void);
+ void CloseSockets(void);
+ void SendCommandToThread(th_cmd);
+
+ std::string object_name_;
+ std::string attribute_name_;
+ SmfImmApplierHdl *ApplierHdl_;
+
+ DELETE_COPY_AND_MOVE_OPERATORS(SmfLongDnApplier);
+};
+
+#endif /* SMFIMMAPPLIER_HH */
+
diff --git a/osaf/services/saf/smfsv/smfd/SmfUtils.cc
b/osaf/services/saf/smfsv/smfd/SmfUtils.cc
--- a/osaf/services/saf/smfsv/smfd/SmfUtils.cc
+++ b/osaf/services/saf/smfsv/smfd/SmfUtils.cc
@@ -35,6 +35,7 @@
#include <algorithm>
#include "osaf_extended_name.h"
+#include "smfd_long_dn.hh"
#include "osaf_time.h"
#include "logtrace.h"
#include "SmfUtils.hh"
@@ -337,9 +338,9 @@ SmfImmUtils::getObject(const std::string
SaAisErrorT rc = SA_AIS_OK;
SaNameT objectName;
- if (i_dn.length() > smfd_cb->maxDnLength) {
+ if (i_dn.length() > GetSmfMaxDnLength()) {
LOG_NO("getObject error, dn too long (%zu), max %zu",
- i_dn.length(),
static_cast<size_t>(smfd_cb->maxDnLength));
+ i_dn.length(),
static_cast<size_t>(GetSmfMaxDnLength()));
return false;
}
@@ -364,9 +365,9 @@ SmfImmUtils::getObjectAisRC(const std::s
SaAisErrorT rc = SA_AIS_OK;
SaNameT objectName;
- if (i_dn.length() > smfd_cb->maxDnLength) {
+ if (i_dn.length() > GetSmfMaxDnLength()) {
LOG_NO("getObjectAisRC error, dn too long (%zu), max %zu",
- i_dn.length(),
static_cast<size_t>(smfd_cb->maxDnLength));
+ i_dn.length(),
static_cast<size_t>(GetSmfMaxDnLength()));
return SA_AIS_ERR_NAME_TOO_LONG;
}
@@ -406,9 +407,9 @@ SmfImmUtils::getChildren(const std::stri
TRACE_ENTER();
if (i_dn.size() > 0) {
- if (i_dn.length() > smfd_cb->maxDnLength) {
+ if (i_dn.length() > GetSmfMaxDnLength()) {
LOG_NO("getChildren error, dn too long (%zu), max %zu",
- i_dn.length(),
static_cast<size_t>(smfd_cb->maxDnLength));
+ i_dn.length(),
static_cast<size_t>(GetSmfMaxDnLength()));
return false;
}
@@ -490,9 +491,9 @@ SmfImmUtils::getChildrenAndAttrBySearchH
TRACE_ENTER();
if (i_dn.size() > 0) {
- if (i_dn.length() > smfd_cb->maxDnLength) {
+ if (i_dn.length() > GetSmfMaxDnLength()) {
LOG_NO("getChildren error, dn too long (%zu), max %zu",
- i_dn.length(),
static_cast<size_t>(smfd_cb->maxDnLength));
+ i_dn.length(),
static_cast<size_t>(GetSmfMaxDnLength()));
rc = false;
goto done;
}
@@ -556,9 +557,9 @@ SmfImmUtils::callAdminOperation(const st
SaNameT objectName;
int retry = 100;
- if (i_dn.length() > smfd_cb->maxDnLength) {
+ if (i_dn.length() > GetSmfMaxDnLength()) {
LOG_NO("callAdminOperation error, dn too long (%zu), max %zu",
- i_dn.length(),
static_cast<size_t>(smfd_cb->maxDnLength));
+ i_dn.length(),
static_cast<size_t>(GetSmfMaxDnLength()));
return SA_AIS_ERR_NAME_TOO_LONG;
}
@@ -739,64 +740,6 @@ SmfImmUtils::nodeToClmNode(const std::st
return true;
}
-//------------------------------------------------------------------------------
-// Reads IMM configuration data for long DNs and sets cb data structure
-//------------------------------------------------------------------------------
-bool
-SmfImmUtils::read_IMM_long_DN_config_and_set_control_block(smfd_cb_t * cb)
-{
- TRACE_ENTER();
-
- //here is the only place where "kOsafMaxDnLength" constant is directly
used
- uint32_t maxDnLength = kOsafMaxDnLength;
-
- /* First check if long DNs already enabled.
- * If enabled then there is no need to check it again,
- * since once it is enabled, is never turned off again.
- */
- if(cb->maxDnLength == maxDnLength) {
- TRACE("read_IMM_long_DN_config_and_set_control_block(): "
- "Long DNs already enabled");
- TRACE_LEAVE();
- return true;
- }
-
- /* Set the default value first,
- * to make sure that a value is set,
- * even if this function fails to get the config from IMM.
- */
- //cb->maxDnLength = DEFAULT_MAX_DN_LENGTH;
- cb->maxDnLength = SA_MAX_UNEXTENDED_NAME_LENGTH - 1;
-
- SaImmAttrValuesT_2 **attributes;
-
- if(getObject(IMM_CONFIG_OBJECT_DN, &attributes) == false) {
- LOG_ER("Could not get IMM config object from IMM %s",
- IMM_CONFIG_OBJECT_DN);
- TRACE_LEAVE();
- return false;
- }
-
- const SaUint32T *longDnsAllowed = immutil_getUint32Attr(
- (const SaImmAttrValuesT_2 **)attributes,
- IMM_LONG_DN_CONFIG_ATTRIBUTE_NAME, 0);
- if(longDnsAllowed) {
- TRACE("%s=%u", IMM_LONG_DN_CONFIG_ATTRIBUTE_NAME,
*longDnsAllowed);
- if(*longDnsAllowed == 0) {
- cb->maxDnLength = SA_MAX_UNEXTENDED_NAME_LENGTH - 1;
- }
- else {
- cb->maxDnLength = maxDnLength;
- }
- } else {
- LOG_NO("Could not get long DN config [%s %s], "
- "use default DN length",
- IMM_LONG_DN_CONFIG_ATTRIBUTE_NAME,
IMM_CONFIG_OBJECT_DN);
- }
-
- TRACE_LEAVE();
- return true;
-}
//
------------------------------------------------------------------------------
// smf_stringToImmType()
@@ -952,9 +895,9 @@ smf_stringToValue(SaImmValueTypeT i_type
case SA_IMM_ATTR_SANAMET:
len = strlen(i_str);
- if (len > smfd_cb->maxDnLength) {
+ if (len > GetSmfMaxDnLength()) {
LOG_NO("smf_stringToValue error, SaNameT value too
long (%zu), max %zu",
- len,
static_cast<size_t>(smfd_cb->maxDnLength));
+ len, static_cast<size_t>(GetSmfMaxDnLength()));
return false;
}
diff --git a/osaf/services/saf/smfsv/smfd/SmfUtils.hh
b/osaf/services/saf/smfsv/smfd/SmfUtils.hh
--- a/osaf/services/saf/smfsv/smfd/SmfUtils.hh
+++ b/osaf/services/saf/smfsv/smfd/SmfUtils.hh
@@ -194,13 +194,6 @@ class SmfImmUtils {
/// @return True if successful, otherwise false
///
bool nodeToClmNode(const std::string& i_node, std::string& o_clmNode);
-
-///
-/// Purpose: Read long DN information from IMM
-/// @param cb is the SMF control block
-/// @return True if successful, otherwise false
-///
- bool read_IMM_long_DN_config_and_set_control_block(smfd_cb_t * cb);
private:
bool initialize(void);
diff --git a/osaf/services/saf/smfsv/smfd/smfd.h
b/osaf/services/saf/smfsv/smfd/smfd.h
--- a/osaf/services/saf/smfsv/smfd/smfd.h
+++ b/osaf/services/saf/smfsv/smfd/smfd.h
@@ -76,7 +76,7 @@ extern "C" {
extern const SaNameT *smfApplDN;
extern uint32_t initialize_for_assignment(smfd_cb_t *cb,
SaAmfHAStateT ha_state);
- extern uint32_t smfd_amf_init(smfd_cb_t *);
+ extern SaAisErrorT smfd_amf_init(smfd_cb_t *cb);
extern uint32_t smfd_mds_init(smfd_cb_t *);
extern uint32_t smfd_mds_finalize(smfd_cb_t *);
extern uint32_t smfd_mds_change_role(smfd_cb_t *);
diff --git a/osaf/services/saf/smfsv/smfd/smfd_amf.c
b/osaf/services/saf/smfsv/smfd/smfd_amf.cc
rename from osaf/services/saf/smfsv/smfd/smfd_amf.c
rename to osaf/services/saf/smfsv/smfd/smfd_amf.cc
--- a/osaf/services/saf/smfsv/smfd/smfd_amf.c
+++ b/osaf/services/saf/smfsv/smfd/smfd_amf.cc
@@ -20,6 +20,7 @@
*/
#include "smfd.h"
+#include "smfd_long_dn.hh"
/****************************************************************************
* Name : amf_active_state_handler
@@ -59,6 +60,10 @@ static SaAisErrorT amf_active_state_hand
rc = SA_AIS_ERR_FAILED_OPERATION;
}
+ // Start the long Dn monotoring applier
+ TRACE("%s: SmfLongDnInfo->Start()", __FUNCTION__);
+ SmfLongDnInfo->Start();
+
TRACE_LEAVE();
return rc;
}
@@ -130,22 +135,27 @@ static SaAisErrorT amf_quiesced_state_ha
{
TRACE_ENTER();
V_DEST_RL mds_role;
- SaAisErrorT rc = SA_AIS_OK;
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ uint32_t ncscc_rc = NCSCC_RC_SUCCESS;
/* Terminate threads and finalize the OI handle */
if (campaign_oi_deactivate(cb) != NCSCC_RC_SUCCESS) {
LOG_NO("amf_quiesced_state_handler oi deactivate FAILED,
continue");
}
+ // Stop the long Dn monitoring applier
+ TRACE("%s: SmfLongDnInfo->Stop()", __FUNCTION__);
+ SmfLongDnInfo->Stop();
+
/*
** Change the MDS VDSET role to Quiesced. Wait for MDS callback with
type
** MDS_CALLBACK_QUIESCED_ACK. Don't change cb->ha_state now.
*/
mds_role = cb->mds_role;
cb->mds_role = V_DEST_RL_QUIESCED;
- if ((rc = smfd_mds_change_role(cb)) != NCSCC_RC_SUCCESS) {
+ if ((ncscc_rc = smfd_mds_change_role(cb)) != NCSCC_RC_SUCCESS) {
LOG_ER("smfd_mds_change_role [V_DEST_RL_QUIESCED] FAILED");
- rc = SA_AIS_ERR_FAILED_OPERATION;
+ ais_rc = SA_AIS_ERR_FAILED_OPERATION;
cb->mds_role = mds_role;
goto done;
}
@@ -154,7 +164,7 @@ static SaAisErrorT amf_quiesced_state_ha
cb->is_quiesced_set = true;
done:
TRACE_LEAVE();
- return rc;
+ return ais_rc;
}
/****************************************************************************
@@ -405,7 +415,7 @@ static SaAisErrorT amf_healthcheck_start
SA_AIS_ERR_* - failure
**************************************************************************/
-SaAisErrorT smfd_amf_init(smfd_cb_t * cb)
+SaAisErrorT smfd_amf_init(smfd_cb_t *cb)
{
SaAmfCallbacksT amfCallbacks;
SaVersionT amf_version;
diff --git a/osaf/services/saf/smfsv/smfd/smfd_campaign_oi.cc
b/osaf/services/saf/smfsv/smfd/smfd_campaign_oi.cc
--- a/osaf/services/saf/smfsv/smfd/smfd_campaign_oi.cc
+++ b/osaf/services/saf/smfsv/smfd/smfd_campaign_oi.cc
@@ -84,16 +84,6 @@ static void saImmOiAdminOperationCallbac
goto done;
}
- //Read IMM configuration for long DNs and set cb data structure
- //There is chance that long DN is configured in IMM not in SMF config
object
- TRACE("2. %s:
read_IMM_long_DN_config_and_set_control_block()",__FUNCTION__);
- if (!immutil.read_IMM_long_DN_config_and_set_control_block(smfd_cb)) {
- LOG_ER("read_IMM_long_DN_config_and_set_control_block FAIL");
- (void)immutil_saImmOiAdminOperationResult(immOiHandle,
invocation, SA_AIS_ERR_INVALID_PARAM);
- goto done;
- }
-
-
/* Call admin operation and return result */
rc = campaign->adminOperation(opId, params);
@@ -907,14 +897,6 @@ uint32_t read_config_and_set_control_blo
SmfImmUtils immutil;
SaImmAttrValuesT_2 **attributes;
- //Read IMM configuration for long DNs and set cb data structure
- //The long DN info is configured in IMM not in SMF config object
- TRACE("1. %s:
read_IMM_long_DN_config_and_set_control_block()",__FUNCTION__);
- if (!immutil.read_IMM_long_DN_config_and_set_control_block(cb)) {
- LOG_ER("read_IMM_long_DN_config_and_set_control_block FAIL");
- return NCSCC_RC_FAILURE;
- }
-
if (immutil.getObject(SMF_CONFIG_OBJECT_DN, &attributes) == false) {
LOG_ER("Could not get SMF config object from IMM %s",
SMF_CONFIG_OBJECT_DN);
return NCSCC_RC_FAILURE;
diff --git a/osaf/services/saf/smfsv/smfd/smfd_cb.h
b/osaf/services/saf/smfsv/smfd/smfd_cb.h
--- a/osaf/services/saf/smfsv/smfd/smfd_cb.h
+++ b/osaf/services/saf/smfsv/smfd/smfd_cb.h
@@ -69,8 +69,7 @@ typedef struct smfd_cb {
uint32_t no_of_smfnd;
pthread_mutex_t lock; /* Used by smfd_cb_t
lock/unlock functions */
pthread_mutex_t imm_lock; /* Used when IMM OI handle is
shared between campaign thread and main thread*/
- uint32_t maxDnLength; /* Max DN length */
- bool long_dn_allowed;
+
} smfd_cb_t;
#ifdef __cplusplus
diff --git a/osaf/services/saf/smfsv/smfd/smfd_evt.h
b/osaf/services/saf/smfsv/smfd/smfd_evt.h
--- a/osaf/services/saf/smfsv/smfd/smfd_evt.h
+++ b/osaf/services/saf/smfsv/smfd/smfd_evt.h
@@ -18,6 +18,13 @@
#ifndef SMFD_EVT_H
#define SMFD_EVT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void smfd_process_mbx(SYSF_MBX * mbx);
+#ifdef __cplusplus
+}
+#endif
#endif /* SMFD_EVT_H */
diff --git a/osaf/services/saf/smfsv/smfd/smfd_long_dn.hh
b/osaf/services/saf/smfsv/smfd/smfd_long_dn.hh
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/smfsv/smfd/smfd_long_dn.hh
@@ -0,0 +1,58 @@
+/* OpenSAF
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * 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 "SmfLongDnApplier.hh"
+#include "osaf_extended_name.h"
+
+#ifndef SMFD_LONG_DN_HH
+#define SMFD_LONG_DN_HH
+
+ /* Store for SmfLongDnApplier. Must live as long as the process lives
+ * See smfd_main.cc
+ */
+ extern SmfLongDnApplier *SmfLongDnInfo;
+
+ /* This inline function replaces the maxDnLength variable in the
+ * smfd_cb structure that was updated in some places in the code by
+ * specifically reading the long dn setting in the IMM config object.
+ * This function will instead return a value corresponding to
+ * maxDnLength based on the same long dn setting but that is monitored
+ * using an IMM applier
+ * NOTE:
+ * I there is no applier or applier is not working, SmfMaxDnLength will
+ * return the length corresponding to that long dn is not allowed.
+ */
+ static inline uint32_t GetSmfMaxDnLength(void) {
+ // here is the only place where "kOsafMaxDnLength" constant is
+ // directly used
+ uint32_t maxDnLength_long = kOsafMaxDnLength;
+ uint32_t maxDnLength_short = SA_MAX_UNEXTENDED_NAME_LENGTH - 1;
+
+ if (SmfLongDnInfo == nullptr) {
+ return maxDnLength_short;
+ }
+
+ if (SmfLongDnInfo->getValue() == true) {
+ return maxDnLength_long;
+ } else {
+ return maxDnLength_short;
+ }
+ }
+
+
+#endif /* SMFD_LONG_DN_HH */
+
diff --git a/osaf/services/saf/smfsv/smfd/smfd_main.c
b/osaf/services/saf/smfsv/smfd/smfd_main.cc
rename from osaf/services/saf/smfsv/smfd/smfd_main.c
rename to osaf/services/saf/smfsv/smfd/smfd_main.cc
--- a/osaf/services/saf/smfsv/smfd/smfd_main.c
+++ b/osaf/services/saf/smfsv/smfd/smfd_main.cc
@@ -23,7 +23,7 @@
#include <configmake.h>
-#define _GNU_SOURCE
+//#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -43,6 +43,7 @@
#include "smfd.h"
#include "smfsv_defs.h"
#include "smfd_evt.h"
+#include "smfd_long_dn.hh"
/* ========================================================================
* DEFINITIONS
@@ -63,6 +64,9 @@ extern struct ImmutilWrapperProfile immu
static smfd_cb_t smfd_cb_instance;
smfd_cb_t *smfd_cb = &smfd_cb_instance;
+/* Store for Long Dn monitoring applier object */
+SmfLongDnApplier *SmfLongDnInfo;
+
static SaNameT smfApplDN_instance;
static void smfApplDN_instance_constructor(void) __attribute__ ((constructor));
@@ -284,6 +288,12 @@ static uint32_t initialize_smfd(void)
goto done;
}
+ /* Create a long dn monitoring applier */
+ SmfLongDnInfo = new SmfLongDnApplier(IMM_CONFIG_OBJECT_DN,
+
IMM_LONG_DN_CONFIG_ATTRIBUTE_NAME);
+ TRACE("%s: Create applier for long Dn setting", __FUNCTION__);
+ SmfLongDnInfo->Create();
+
done:
TRACE_LEAVE();
return (rc);
@@ -360,7 +370,6 @@ static void main_process(void)
fds[SMFD_COI_FD].events = POLLIN;
while (1) {
-
if (smfd_cb->campaignOiHandle != 0) {
fds[SMFD_COI_FD].fd = smfd_cb->campaignSelectionObject;
fds[SMFD_COI_FD].events = POLLIN;
------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today.http://sdm.link/xeonphi
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel