Hi Rafael


> -----Original Message-----
> From: Rafael Odzakow
> Sent: den 12 december 2016 11:02
> To: Lennart Lund <[email protected]>;
> [email protected]
> Cc: [email protected]
> Subject: Re: [PATCH 1 of 1] smf: use IMM appler for the change in
> longDnsAllowed attributes [#2139]
> 
> Still not completed the review. Check comments inline
> 
> 
> On 12/08/2016 10:22 AM, Lennart Lund wrote:
> >   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);
> [rafael] too large indentation
[Lennart] Yes, will fix

> > +      if (is_cancel) {
> > +        is_cancel = false;
> > +        rc = false;
> > +        break;
> > +      } else {
> > +        continue;
> [rafael] unnecessary continue.
[Lennart] Yes, I will remove in all IMM API wrapper functions
> 
> [rafael] The try again code is repeated for each API call. Consider the
> decorator pattern where the try again logic is decorated onto the API calls.
[Lennart] For simplicity I will keep the try again loops as is. These wrapper 
functions are static C functions which
in itself is a "shortcut". If the corresponding API wrappers in immutil.c 
hadn't been using the global "immutilWrapperProfile "
they could have been used instead. 

> > +      }
> > +    } 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));
> [rafael] tabs and spaces
[Lennart] Will fix
> > +  }
> > +
> > +  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