ACK with comments.
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); > + if (is_cancel) { > + is_cancel = false; > + rc = false; > + break; > + } else { > + continue; > + } > + } else if (ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiInitialize_2() Fail '%s'", __FUNCTION__, > + saf_error(ais_rc)); > + rc = false; > + break; > + } else { > + // Done > + break; > + } > + } > + if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiInitialize_2() timeout Fail '%s'", __FUNCTION__, > + saf_error(ais_rc)); > + } > + > + return rc; > +} > + > +static bool FinalizeImmOi(SaImmOiHandleT i_immOiHandle) { > + base::Timer adminOpTimer(20000); > + SaAisErrorT ais_rc = SA_AIS_OK; > + bool rc = true; > + > + if (i_immOiHandle != 0) { > + // Only if there is anything to finalize > + while (adminOpTimer.is_timeout() == false) { > + ais_rc = saImmOiFinalize(i_immOiHandle); > + if (ais_rc == SA_AIS_ERR_TRY_AGAIN) { > + base::Sleep(base::kFiveHundredMilliseconds); > + continue; > + } else if (ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiFinalize() Fail '%s'", __FUNCTION__, > + saf_error(ais_rc)); > + rc = false; > + break; > + } else { > + // Done > + break; > + } > + } > + if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiFinalize() timeout Fail '%s'", __FUNCTION__, > + saf_error(ais_rc)); > + } > + } > + > + return rc; > +} > + > +static bool GetImmOiSelectionObject(SaImmOiHandleT i_immOiHandle, > + SaSelectionObjectT *selectionObject) { > + base::Timer adminOpTimer(20000); > + SaAisErrorT ais_rc = SA_AIS_OK; > + bool rc = true; > + TRACE_ENTER(); > + > + while (adminOpTimer.is_timeout() == false) { > + ais_rc = saImmOiSelectionObjectGet(i_immOiHandle, selectionObject); > + if (ais_rc == SA_AIS_ERR_TRY_AGAIN) { > + base::Sleep(base::kFiveHundredMilliseconds); > + continue; > + } else if (ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiSelectionObjectGet() Fail '%s'", __FUNCTION__, > + saf_error(ais_rc)); > + rc = false; > + break; > + } else { > + // Done > + break; > + } > + } > + if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiSelectionObjectGet() timeout Fail '%s'", > + __FUNCTION__, saf_error(ais_rc)); > + } > + > + TRACE_LEAVE(); > + return rc; > +} > + > +static bool ImmOiSet(SaImmOiHandleT i_immOiHandle, > + const std::string& i_implementerName) { > + base::Timer adminOpTimer(20000); > + SaAisErrorT ais_rc = SA_AIS_OK; > + bool rc = true; > + SaImmOiImplementerNameT implementerName = > + const_cast<SaImmOiImplementerNameT>(i_implementerName.c_str()); > + TRACE_ENTER(); > + > + while (adminOpTimer.is_timeout() == false) { > + ais_rc = saImmOiImplementerSet(i_immOiHandle, implementerName); > + if (ais_rc == SA_AIS_ERR_TRY_AGAIN) { > + base::Sleep(base::kFiveHundredMilliseconds); > + continue; > + } else if (ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiImplementerSet() Fail '%s'", __FUNCTION__, > + saf_error(ais_rc)); > + rc = false; > + break; > + } else { > + // Done > + break; > + } > + } > + if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiImplementerSet() timeout Fail '%s'", > + __FUNCTION__, saf_error(ais_rc)); > + } > + > + TRACE_LEAVE(); > + return rc; > +} > + > +static bool ImmOiClear(SaImmOiHandleT i_immOiHandle) { > + base::Timer adminOpTimer(20000); > + SaAisErrorT ais_rc = SA_AIS_OK; > + bool rc = true; > + > + while (adminOpTimer.is_timeout() == false) { > + ais_rc = saImmOiImplementerClear(i_immOiHandle); > + if (ais_rc == SA_AIS_ERR_TRY_AGAIN) { > + base::Sleep(base::kFiveHundredMilliseconds); > + continue; > + } else if (ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiImplementerClear() Fail '%s'", __FUNCTION__, > + saf_error(ais_rc)); > + rc = false; > + break; > + } else { > + // Done > + break; > + } > + } > + if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiImplementerClear() timeout Fail '%s'", __FUNCTION__, > + saf_error(ais_rc)); > + } > + > + return rc; > +} > + > +/** > + * Become applier for the given object. This starts the applier > + */ > +static bool SetImmOiForObject(SaImmOiHandleT i_immOiHandle, > + const std::string& i_objectName, > + SaImmScopeT i_scope) { > + base::Timer adminOpTimer(20000); > + SaAisErrorT ais_rc = SA_AIS_OK; > + bool rc = true; > + SaNameT object_name; > + osaf_extended_name_lend(i_objectName.c_str(), &object_name); > + > + while (adminOpTimer.is_timeout() == false) { > + ais_rc = saImmOiObjectImplementerSet(i_immOiHandle, &object_name, > i_scope); > + if (ais_rc == SA_AIS_ERR_TRY_AGAIN) { > + base::Sleep(base::kFiveHundredMilliseconds); > + continue; > + } else if (ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiObjectImplementerSet() Fail '%s'", __FUNCTION__, > + saf_error(ais_rc)); > + rc = false; > + break; > + } else { > + // Done > + break; > + } > + } > + if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiObjectImplementerSet() timeout Fail '%s'", > __FUNCTION__, > + saf_error(ais_rc)); > + } > + > + return rc; > +} > + > +/** > + * Release the applier for the given object. This stops the applier > + */ > +static bool ReleaseImmOiForObject(SaImmOiHandleT i_immOiHandle, > + const std::string& i_objectName, > + SaImmScopeT i_scope) { > + base::Timer adminOpTimer(20000); > + SaAisErrorT ais_rc = SA_AIS_OK; > + bool rc = true; > + SaNameT object_name; > + osaf_extended_name_lend(i_objectName.c_str(), &object_name); > + > + while (adminOpTimer.is_timeout() == false) { > + ais_rc = saImmOiObjectImplementerRelease(i_immOiHandle, &object_name, > + i_scope); > + if (ais_rc == SA_AIS_ERR_TRY_AGAIN) { > + base::Sleep(base::kFiveHundredMilliseconds); > + continue; > + } else if (ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiObjectImplementerRelease() Fail '%s'", __FUNCTION__, > + saf_error(ais_rc)); > + rc = false; > + break; > + } else { > + // Done > + break; > + } > + } > + if (adminOpTimer.is_timeout() == true && ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiObjectImplementerRelease() timeout Fail '%s'", > + __FUNCTION__, saf_error(ais_rc)); > + } > + > + return rc; > +} > + > +static SaAisErrorT DispatchOiCallback(SaImmOiHandleT i_immOiHandle, > + SaDispatchFlagsT i_dispatchFlags) { > + base::Timer dispatchTimer(20000); > + SaAisErrorT ais_rc = SA_AIS_OK; > + TRACE_ENTER(); > + > + while (dispatchTimer.is_timeout() == false) { > + ais_rc = saImmOiDispatch(i_immOiHandle, i_dispatchFlags); > + > + if (ais_rc == SA_AIS_ERR_TRY_AGAIN) { > + base::Sleep(base::kFiveHundredMilliseconds); > + continue; > + } else if (ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiDispatch() Fail '%s'", __FUNCTION__, > + saf_error(ais_rc)); > + break; > + } else { > + // Done > + break; > + } > + } > + if (dispatchTimer.is_timeout() == true && ais_rc != SA_AIS_OK) { > + LOG_WA("%s: saImmOiDispatch() timeout Fail '%s'", __FUNCTION__, > + saf_error(ais_rc)); > + } > + TRACE_LEAVE(); > + return ais_rc; > +} > + > +/** > + * The applier callback functions > + * These are C functions as specified by IMM AIS SaImmOiCallbacksT_2 > + * Note: CCB is "collected" using existing list handling in immutil.c > + **/ > + > +/** > + * Save ccb info if OpensafConfig object is modified > + * > + */ > +static SaAisErrorT CcbObjectModifyCallback(SaImmOiHandleT immOiHandle, > + SaImmOiCcbIdT ccbId, > + const SaNameT *objectName, > + const SaImmAttrModificationT_2 > **attrMods) { > + SaAisErrorT rc = SA_AIS_OK; > + struct CcbUtilCcbData *ccbUtilCcbData; > + > + TRACE_ENTER(); > + > + if ((ccbUtilCcbData = ccbutil_findCcbData(ccbId)) == nullptr) { > + if ((ccbUtilCcbData = ccbutil_getCcbData(ccbId)) == nullptr) { > + TRACE("%s: Failed to get CCB object for %llu", __FUNCTION__, ccbId); > + rc = SA_AIS_ERR_NO_MEMORY; > + goto done; > + } > + } > + > + ccbutil_ccbAddModifyOperation(ccbUtilCcbData, objectName, attrMods); > + > +done: > + TRACE_LEAVE(); > + return rc; > +} > + > +/** > + * Get the new value of the attribute > + * Note: This function is limited to handle one attribute in one object and > + * the type of the attribute must be SaUint32T > + */ > +static void CcbApplyCallback(SaImmOiHandleT immOiHandle, SaImmOiCcbIdT > ccbId) { > + struct CcbUtilCcbData *ccbUtilCcbData; > + struct CcbUtilOperationData *opdata; > + const SaImmAttrModificationT_2 *attrMod; > + SaConstStringT objName; > + SaImmAttrValuesT_2 attribute; > + > + // Note: Only one value of type SaUint32T can be handled > + SaUint32T *value = nullptr; > + > + TRACE_ENTER(); > + > + /* Verify the ccb */ > + if ((ccbUtilCcbData = ccbutil_findCcbData(ccbId)) == nullptr) { > + LOG_NO("%s: Failed to find CCB object for id %llu", __FUNCTION__, ccbId); > + goto done; > + } > + > + /* We don't need to loop since the only possible operation is MODIFY > + * and only one object is monitored > + */ > + opdata = ccbUtilCcbData->operationListHead; > + if (opdata->operationType != CCBUTIL_MODIFY) { > + TRACE("%s: Not a modify operation", __FUNCTION__); > + goto done; > + } > + > + objName = osaf_extended_name_borrow(&opdata->objectName); > + if (object_name_.compare(objName) != 0) { > + TRACE("%s: Object \"%s\" not an OpensafConfig object", > + __FUNCTION__, objName); > + goto done; > + } > + > + /* Read value in opensafNetworkName > + * Note: This is implemented as a loop in case more attributes are > + * added in the class in the future. For now the only > + * attribute of interest here is opensafNetworkName > + */ > + TRACE("%s: Read value in attributes", __FUNCTION__); > + attrMod = opdata->param.modify.attrMods[0]; > + attribute = attrMod->modAttr; > + > + for (int i = 1; attrMod != nullptr; i++) { > + /* Get the value */ > + if (attribute_name_.compare(attribute.attrName) != 0) { > + // Not found > + attrMod = opdata->param.modify.attrMods[i]; > + continue; > + } > + > + // Attribute found > + value = static_cast<SaUint32T*> (attribute.attrValues[0]); > + break; > + } > + > + if (value == nullptr) { > + TRACE("%s: Value is nullptr", __FUNCTION__); > + SetAttributeValue(""); > + attribute_value_is_valid_ = false; > + } else { > + SetAttributeValue(std::to_string(*value)); > + attribute_value_is_valid_ = true; > + } > + > +done: > + if (ccbUtilCcbData != nullptr) > + ccbutil_deleteCcbData(ccbUtilCcbData); > + > + TRACE_LEAVE(); > +} > + > +/** > + * Cleanup by deleting saved ccb info if aborted > + * > + */ > +static void CcbAbortCallback(SaImmOiHandleT immOiHandle, SaImmOiCcbIdT > ccbId) { > + struct CcbUtilCcbData *ccbUtilCcbData; > + > + TRACE_ENTER2("CCB ID %llu", ccbId); > + > + if ((ccbUtilCcbData = ccbutil_findCcbData(ccbId)) != nullptr) > + ccbutil_deleteCcbData(ccbUtilCcbData); > + else > + TRACE("%s: Failed to find CCB object for %llu", __FUNCTION__, ccbId); > + > + TRACE_LEAVE(); > +} > + > +/** > + * An object of OpensafConfig class is created. We don't have to do anything > + * Cannot be replaced by nullptr pointer in callback list > + */ > +static SaAisErrorT CcbCreateCallback(SaImmOiHandleT immOiHandle, > + SaImmOiCcbIdT ccbId, > + const SaImmClassNameT className, > + const SaNameT *parentName, > + const SaImmAttrValuesT_2 **attr) { > + TRACE_ENTER(); > + TRACE_LEAVE(); > + return SA_AIS_OK; > +} > + > +/** > + * An object of OpensafConfig class is deleted. We don't have to do anything > + * Cannot be replaced by nullptr pointer in callback list > + */ > +static SaAisErrorT CcbDeleteCallback(SaImmOiHandleT immOiHandle, > + SaImmOiCcbIdT ccbId, > + const SaNameT *objectName) { > + TRACE_ENTER(); > + TRACE_LEAVE(); > + return SA_AIS_OK; > +} > + > +/* Callback function list given to IMM when OI is initialized > + * We need: > + * Modify for saving modify ccb > + * Apply for knowing that the modification has been applied > + * Abort for removing saved ccb in case of an abortion of ccb > + */ > +static const SaImmOiCallbacksT_2 callbacks = { > + .saImmOiAdminOperationCallback = nullptr, > + .saImmOiCcbAbortCallback = CcbAbortCallback, > + .saImmOiCcbApplyCallback = CcbApplyCallback, > + .saImmOiCcbCompletedCallback = nullptr, > + .saImmOiCcbObjectCreateCallback = CcbCreateCallback, > + .saImmOiCcbObjectDeleteCallback = CcbDeleteCallback, > + .saImmOiCcbObjectModifyCallback = CcbObjectModifyCallback, > + .saImmOiRtAttrUpdateCallback = nullptr > +}; > + > +// ===================================== > +// SmfImmApplierHdl Class implementation > +// ===================================== > +// Make next_instance_number_ thread safe > +std::atomic<unsigned int> SmfImmApplierHdl::instance_number_{1}; > +SmfImmApplierHdl::SmfImmApplierHdl() : > + isCreated_ {false}, > + imm_appl_hdl_ {0}, > + imm_appl_selobj_ {0} { > + applier_name_ = "@safSmf_applier"+std::to_string(instance_number_++); > +} > + > +SmfImmApplierHdl::~SmfImmApplierHdl() { > + TRACE_ENTER(); > + Remove(); > + TRACE_LEAVE(); > +} > + > +void SmfImmApplierHdl::Remove() { > + // Release all resources, give up applier, remove applier name and > finalize OI > + if (Stop() == false) { > + LOG_NO("%s: ReleaseImmOiForObject Fail", __FUNCTION__); > + } > + if (ImmOiClear(imm_appl_hdl_) == false) { > + LOG_NO("%s: ImmOiClear() Fail", __FUNCTION__); > + } > + if (FinalizeImmOi(imm_appl_hdl_) == false) { > + LOG_NO("%s: FinalizeImmOi() Fail", __FUNCTION__); > + } > +} > + > +bool SmfImmApplierHdl::Create(const ApplierSetupInfo& setup_info) { > + bool do_continue = true; > + TRACE_ENTER(); > + > + is_cancel = false; > + if (imm_appl_hdl_ == 0) { > + // If initialize is needed > + TRACE("%s: Do create", __FUNCTION__); > + object_name_ = setup_info.object_name; > + attribute_name_ = setup_info.attribute_name; > + attribute_value_is_valid_ = false; > + > + // Initialize > + do_continue = InitializeImmOi(&imm_appl_hdl_, &callbacks, &kImmVersion); > + TRACE("%s: InitializeImmOi() = %s", __FUNCTION__, > + do_continue? "true": "false"); > + > + // Get selection object > + if (do_continue) { > + do_continue = GetImmOiSelectionObject(imm_appl_hdl_, > &imm_appl_selobj_); > + TRACE("%s: GetImmOiSelectionObject() = %s", __FUNCTION__, > + do_continue? "true": "false"); > + } > + } > + > + TRACE_LEAVE(); > + return do_continue; > +} > + > +bool SmfImmApplierHdl::Start() { > + std::string value; > + bool do_continue = true; > + > + TRACE_ENTER(); > + is_cancel = false; > + > + // OI Set > + // Note: If the applier name already exist it is because SMF on another > + // node has created an applier with the same name. This not ok for an > + // object implementer but is ok for an applier. > + // Create a new name and try again. Limit number of retries > + for (int i = 0; i < 3; i++) { > + do_continue = ImmOiSet(imm_appl_hdl_, applier_name_); > + > + if (do_continue) { > + break; > + } else { > + // Create a new name and try again > + applier_name_ = "@safSmf_applier"+std::to_string(instance_number_++); > + LOG_NO("%s: A new applier name is created '%s'", > + __FUNCTION__, applier_name_.c_str()); > + } > + } > + > + // Set which object to monitor > + if (do_continue) { > + do_continue = SetImmOiForObject(imm_appl_hdl_, object_name_, SA_IMM_ONE); > + TRACE("%s: SetImmOiForObject() = %s", __FUNCTION__, > + do_continue? "true": "false"); > + > + if (do_continue) { > + if (attribute_value_is_valid_ == false) { > + // Get the current value from IMM > + value = GetAttributeValueFromImm(object_name_, attribute_name_); > + TRACE("%s: GetAttributeValueFromImm() = '%s'", > + __FUNCTION__, value.c_str()); > + } > + if (value != "") { > + attribute_value_is_valid_ = true; > + } > + SetAttributeValue(value); > + TRACE("%s: SetAttributeValue(%s), " > + "attribute_value_is_valid_ = %s", __FUNCTION__, value.c_str(), > + attribute_value_is_valid_? "true": "false"); > + } > + } > + > + if (do_continue == false) { > + LOG_WA("%s: Applier could not be started", __FUNCTION__); > + } > + > + TRACE_LEAVE(); > + return do_continue; > +} > + > +bool SmfImmApplierHdl::Stop() { > + bool rc = true; > + > + TRACE_ENTER(); > + > + is_cancel = true; > + attribute_value_is_valid_ = false; > + SetAttributeValue(""); > + > + if (imm_appl_hdl_ != 0) { > + rc = ReleaseImmOiForObject(imm_appl_hdl_, object_name_, SA_IMM_ONE); > + if (rc == false) { > + LOG_NO("%s: ReleaseImmOiForObject() Fail", __FUNCTION__); > + } > + > + rc = ImmOiClear(imm_appl_hdl_); > + if (rc == false) { > + LOG_NO("%s: ImmOiClear Fail", __FUNCTION__); > + } > + } > + TRACE_LEAVE2("rc = %s", rc? "true": "false"); > + return rc; > +} > + > +void SmfImmApplierHdl::CancelCreate() { > + is_cancel = true; > +} > + > +std::string SmfImmApplierHdl::get_value() { > + attribute_value_lock.lock(); > + std::string value = attribute_value_; > + attribute_value_lock.unlock(); > + return value; > +} > + > +ExecuteImmCallbackReply SmfImmApplierHdl::ExecuteImmCallback() { > + ExecuteImmCallbackReply method_rc = ExecuteImmCallbackReply::kOk; > + > + TRACE_ENTER(); > + SaAisErrorT ais_rc = DispatchOiCallback(imm_appl_hdl_, SA_DISPATCH_ALL); > + > + if (ais_rc == SA_AIS_OK) { > + method_rc = ExecuteImmCallbackReply::kOk; > + } else if (ais_rc == SA_AIS_ERR_BAD_HANDLE) { > + struct ApplierSetupInfo setup; > + setup.object_name = object_name_; > + setup.attribute_name = attribute_name_; > + imm_appl_hdl_ = 0; > + bool is_ok = Create(setup); > + if (is_ok) { > + method_rc = ExecuteImmCallbackReply::kGetNewSelctionObject; > + } else { > + method_rc = ExecuteImmCallbackReply::kError; > + } > + } else { > + method_rc = ExecuteImmCallbackReply::kError; > + } > + > + TRACE_LEAVE(); > + return method_rc; > +} > diff --git a/osaf/services/saf/smfsv/smfd/SmfImmApplierHdl.hh > b/osaf/services/saf/smfsv/smfd/SmfImmApplierHdl.hh > new file mode 100644 > --- /dev/null > +++ b/osaf/services/saf/smfsv/smfd/SmfImmApplierHdl.hh > @@ -0,0 +1,113 @@ > +/* -*- OpenSAF -*- > + * > + * (C) Copyright 2016 The OpenSAF Foundation > + * > + * > + * This program is distributed in the hope that it will be useful, but > + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY > + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed > + * under the GNU Lesser General Public License Version 2.1, February 1999. > + * The complete license can be accessed from the following location: > + * http://opensource.org/licenses/lgpl-license.php > + * See the Copying file included with the OpenSAF distribution for full > + * licensing terms. > + * > + * Author(s): Ericsson AB > + * > + */ > + > +#include <string> > +#include <atomic> > + > +#include "base/macros.h" > +#include "saImmOi.h" > + > +#ifndef SMFIMMAPPLIERHDL_HH > +#define SMFIMMAPPLIERHDL_HH > + > +/** > + * This class creates and handle an IMM applier > + * The handler must be used in an "outer" thread that implements a poll loop > + * The thread shall get a selection object (poll fd) and call the > + * ExecuteImmCallback() method when released > + * > + * Note/Warning: > + * The IMM object applier handle may be set to invalid by IMM. This will be > + * detected and handled in the ExecuteImmCallback() method. This method will > + * not return until the applier is restored or timed out which may take up to > + * one minute. > + * Do not use this handler in a thread that cannot handle this! > + * > + * In this version the following limitations apply: > + * - Only one IMM object can be monitored > + * - Only modifications of one attribute can be handled > + * - All values are given as a std::string. The user has to convert to other > + * type if needed > + */ > + > +// In-parameter for SmfImmApplierHdl Create()) > +struct ApplierSetupInfo { > + std::string object_name; > + std::string attribute_name; > + //SaImmOiCcbApplyCallbackT ApplyCallbackFunction; > +}; > + > +enum class ExecuteImmCallbackReply { > + kOk = 0, > + kGetNewSelctionObject, > + kError > +}; > + > +class SmfImmApplierHdl { > + public: > + SmfImmApplierHdl(void); > + ~SmfImmApplierHdl(void); > + > + // Create an applier for monitoring changes of one attribute in one object > + // The applier is not started. To start use Start() method > + // Note: Create() must be called before Start() and Stop() can be used > + // Return false if Fail > + bool Create(const ApplierSetupInfo& setup_info); > + > + // Cancel an ongoing create operation that may take a long time. > + // The saImmOiInitialize_2() (see IMM documentation) must have a TRY AGAIN > + // loop that may take up to one minute. > + // This method can be used by an applier that uses a thread for IMM > handling > + // from outside the thread to cancel an ongoing create operation that may > + // hang the thread > + void CancelCreate(void); > + > + // Start the applier > + // Return false if Fail > + bool Start(void); > + > + // Finalize all resources used by the applier > + // Return false if Fail > + bool Stop(void); > + > + // Remove the applier by freeing all IMM resources > + void Remove(void); > + > + // Get the monitored value > + // If there is no valid value an empty string is returned > + std::string get_value(void); > + > + // Used with poll loop (fd) > + SaSelectionObjectT get_selection_object(void) { return imm_appl_selobj_; } > + > + // Uses saImmOiDispatch to call the appropriate callback function > + // Shall be called when the selection object releases the poll loop > + // If return code is kGetNewSelctionObject the applier has been restored > and > + // the selection object has to be updated > + ExecuteImmCallbackReply ExecuteImmCallback(void); > + > + private: > + const SaVersionT kImmVersion = { 'A', 2, 11 }; > + static std::atomic<unsigned int> instance_number_; > + bool isCreated_; > + std::string applier_name_; > + SaImmOiHandleT imm_appl_hdl_; > + SaSelectionObjectT imm_appl_selobj_; > +}; > + > +#endif /* SMFIMMAPPLIERHDL_HH */ > diff --git a/osaf/services/saf/smfsv/smfd/SmfImmOperation.cc > b/osaf/services/saf/smfsv/smfd/SmfImmOperation.cc > --- a/osaf/services/saf/smfsv/smfd/SmfImmOperation.cc > +++ b/osaf/services/saf/smfsv/smfd/SmfImmOperation.cc > @@ -34,6 +34,7 @@ > #include <saImm.h> > #include <saf_error.h> > #include "osaf_extended_name.h" > +#include "smfd_long_dn.hh" > > /* ======================================================================== > * DEFINITIONS > @@ -391,9 +392,9 @@ SmfImmCreateOperation::execute(SmfRollba > > const char *className = m_className.c_str(); > > - if (m_parentDn.length() > smfd_cb->maxDnLength) { > + if (m_parentDn.length() > GetSmfMaxDnLength()) { > LOG_NO("Object create op failed, parent name too long [%zu] > max=[%zu], parent=[%s]", > - m_parentDn.length(), > static_cast<size_t>(smfd_cb->maxDnLength), > + m_parentDn.length(), > static_cast<size_t>(GetSmfMaxDnLength()), > m_parentDn.c_str()); > TRACE_LEAVE(); > return SA_AIS_ERR_NAME_TOO_LONG; > @@ -629,7 +630,7 @@ SmfImmDeleteOperation::execute(SmfRollba > return SA_AIS_ERR_UNAVAILABLE; > } > > - if (m_dn.length() > smfd_cb->maxDnLength) { > + if (m_dn.length() > GetSmfMaxDnLength()) { > LOG_NO("SmfImmDeleteOperation::execute: failed Too long dn %zu", > m_dn.length()); > TRACE_LEAVE(); > @@ -1005,7 +1006,7 @@ SmfImmModifyOperation::execute(SmfRollba > return SA_AIS_ERR_UNAVAILABLE; > } > > - if (m_dn.length() > smfd_cb->maxDnLength) { > + if (m_dn.length() > GetSmfMaxDnLength()) { > LOG_NO("SmfImmModifOperation::execute: failed Too long dn %zu", > m_dn.length()); > TRACE_LEAVE(); > @@ -1290,7 +1291,7 @@ SmfImmRTCreateOperation::execute() > > const char *className = m_className.c_str(); > > - if (m_parentDn.length() > smfd_cb->maxDnLength) { > + if (m_parentDn.length() > GetSmfMaxDnLength()) { > LOG_NO("SmfImmRTCreateOperation::execute, createObject failed > Too long parent name %zu", > m_parentDn.length()); > TRACE_LEAVE(); > @@ -1483,9 +1484,9 @@ SmfImmRTUpdateOperation::execute() > goto exit; > } > > - if (m_dn.length() > smfd_cb->maxDnLength) { > + if (m_dn.length() > GetSmfMaxDnLength()) { > LOG_NO("SmfImmRTUpdateOperation::execute, too long DN [%zu], > max=[%zu], dn=[%s]", > - m_dn.length(), static_cast<size_t>(smfd_cb->maxDnLength), > m_dn.c_str()); > + m_dn.length(), static_cast<size_t>(GetSmfMaxDnLength()), > m_dn.c_str()); > result = SA_AIS_ERR_NAME_TOO_LONG; > goto exit; > } > diff --git a/osaf/services/saf/smfsv/smfd/SmfLongDnApplier.cc > b/osaf/services/saf/smfsv/smfd/SmfLongDnApplier.cc > new file mode 100644 > --- /dev/null > +++ b/osaf/services/saf/smfsv/smfd/SmfLongDnApplier.cc > @@ -0,0 +1,441 @@ > +/* -*- OpenSAF -*- > + * > + * (C) Copyright 2016 The OpenSAF Foundation > + * > + * This program is distributed in the hope that it will be useful, but > + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY > + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed > + * under the GNU Lesser General Public License Version 2.1, February 1999. > + * The complete license can be accessed from the following location: > + * http://opensource.org/licenses/lgpl-license.php > + * See the Copying file included with the OpenSAF distribution for full > + * licensing terms. > + * > + * Author(s): Ericsson AB > + * > + */ > + > +#include <thread> > +#include <atomic> > +#include <memory> > + > +#include "SmfLongDnApplier.hh" > +#include "SmfImmApplierHdl.hh" > +#include "smfd.h" > +#include "SmfUtils.hh" > + > +#include "saf_error.h" > +#include "logtrace.h" > +#include "osaf_utility.h" > +#include "osaf_time.h" > +#include "osaf_poll.h" > +#include "base/time.h" > + > +/** > + * Local definitions not needed outside of this file > + */ > + > +/* Inter thread communication (via socket pair) */ > +static const char* CMD_STOP = "s"; > +static const char* CMD_START = "a"; > +static const char* CMD_REMOVE = "r"; > +static const size_t CMD_SIZE = 2; > + > +static int socket_fd_thread = 0; // Socket for thread to read commands > +static int socket_fd_command = 0; // Socket for commands to thread [rafael] consider moving these to member variables > + > +/* 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, [rafael] should be lowercase: 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: [rafael] wrong indentation above > + 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) { [rafael] capital g, consider renaming this function to something more descriptive. For example: IsEnabled > + 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_; [rafael] lower case for 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; ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot _______________________________________________ Opensaf-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/opensaf-devel
