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
