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

Reply via email to