See my comments below [Lennart] Note: Only the new files are relevant to check using cpplint and cppcheck old smf files will not pass. It is also possible that changes made in the old files may add new fails
Thanks Lennart > -----Original Message----- > From: Rafael Odzakow > Sent: den 9 december 2016 12:24 > 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] > > I am not finished with the review but I have two comments so far. > > 1) SmfLongDnInfo is a global googles style guide describes possible > problems with those. > > https://google.github.io/styleguide/cppguide.html#Static_and_Global_Varia > bles > > Because this is a class type it is not allowed to be used. > [Lennart] This is correct and it is not a good solution but the construction is intentional. A better way could be to construct the applier as a singleton but I have chosen this simpler way since it's no meaning to construct and create the applier more than once and it is done in smfd_main that still is C code even if the make file is changed so that it is compiled using the C++ compiler. In smfd_amf that is also C code compiled with the C++ compiler the Start and Stop method of the SmfLongDnApplier is used. These are the only places in the SMF code where the applier is administrated in any way. Both the applier handler and the applier can only be instantiated once (it is possible to remove them and do a new instantiation) it is not possible to have to appliers at the same time in the same process. One reason is that they use static C functions and these functions are not guaranteed to be thread safe. This is also intentional. I have not put any effort in trying to handle this since it is not needed for now to make it any better in this aspect. Note: I have written about limitations and special design decisions in the README file and in comments in the code > > 2) smfd.h has the wrong indentation and possibly other places as well. > [Lennart] This file is not part of the applier. The only reason for do any changes here is to make it possible to compile with the C++ compiler. The type of the return value was not correct. This means that it is not relevant to do cpp checks on this file. > > 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 > > + > > +/* 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
