I have few concerns: 1. It has severe performance issues(when number of nodes increases with configurations) as we had discussed in #517 patch(Sent on 2 Sep 2013). 2. Due to syncing between directors and node directors(when complete configuration of sg is loaded at one go), there may be issues like #926, because directors will send su/comp information to amfnd and amfnd will also get it from immnd as applier. 3. It has lots of code duplicity and maintenance.
Thanks -Nagu > -----Original Message----- > From: Hans Nordeback [mailto:hans.nordeb...@ericsson.com] > Sent: 28 May 2014 14:27 > To: hans.fe...@ericsson.com; Nagendra Kumar; Praveen Malviya > Cc: opensaf-devel@lists.sourceforge.net > Subject: [PATCH 1 of 1] AMF: Use IMM applier in the AMF node director V3 > [#819] > > osaf/libs/common/amf/include/amf_defs.h | 6 + > osaf/services/saf/amf/amfnd/Makefile.am | 1 + > osaf/services/saf/amf/amfnd/evt.cc | 7 + > osaf/services/saf/amf/amfnd/hcdb.cc | 150 ++++ > osaf/services/saf/amf/amfnd/imm.cc | 758 > ++++++++++++++++++++++++ > osaf/services/saf/amf/amfnd/include/Makefile.am | 1 + > osaf/services/saf/amf/amfnd/include/avnd.h | 1 + > osaf/services/saf/amf/amfnd/include/avnd_evt.h | 8 + > osaf/services/saf/amf/amfnd/include/avnd_hc.h | 1 + > osaf/services/saf/amf/amfnd/include/avnd_imm.h | 148 ++++ > osaf/services/saf/amf/amfnd/main.cc | 10 +- > 11 files changed, 1090 insertions(+), 1 deletions(-) > > > This first patch adds support for changing attributes in class > SaAmfHealthcheckType > Updated with review comments. > > diff --git a/osaf/libs/common/amf/include/amf_defs.h > b/osaf/libs/common/amf/include/amf_defs.h > --- a/osaf/libs/common/amf/include/amf_defs.h > +++ b/osaf/libs/common/amf/include/amf_defs.h > @@ -254,6 +254,12 @@ typedef enum > saAmfHealthcheckMaxDuration_ID = 2, > } AVSV_AMF_HEALTHCHECK_ATTR_ID; > > +/* Attribute ID enum for the SaAmfHealthcheckType class */ > +typedef enum > +{ > + saAmfHctDefPeriod_ID = 1, > + saAmfHctDefMaxDuration_ID = 2, > +} AMF_HEALTHCHECK_TYPE_ATTR_ID; > > #define AVSV_COMMON_SUB_ID_DEFAULT_VAL 1 > #define SA_AMF_PRESENCE_ORPHANED > (SA_AMF_PRESENCE_TERMINATION_FAILED+1) > diff --git a/osaf/services/saf/amf/amfnd/Makefile.am > b/osaf/services/saf/amf/amfnd/Makefile.am > --- a/osaf/services/saf/amf/amfnd/Makefile.am > +++ b/osaf/services/saf/amf/amfnd/Makefile.am > @@ -51,6 +51,7 @@ osafamfnd_SOURCES = \ > err.cc \ > evt.cc \ > hcdb.cc \ > + imm.cc \ > main.cc \ > mbcsv.cc \ > mds.cc \ > diff --git a/osaf/services/saf/amf/amfnd/evt.cc > b/osaf/services/saf/amf/amfnd/evt.cc > --- a/osaf/services/saf/amf/amfnd/evt.cc > +++ b/osaf/services/saf/amf/amfnd/evt.cc > @@ -32,6 +32,7 @@ > */ > > #include "avnd.h" > +#include "avnd_imm.h" > > > /************************************************************ > **************** > Name : avnd_evt_create > @@ -200,6 +201,7 @@ AVND_EVT *avnd_evt_create(AVND_CB *cb, > void avnd_evt_destroy(AVND_EVT *evt) > { > uint32_t type = 0; > + AvndImmEvt *imm = 0; > > if (!evt) > return; > @@ -294,6 +296,11 @@ void avnd_evt_destroy(AVND_EVT *evt) > case AVND_EVT_PID_EXIT: > break; > > + case AVND_EVT_IMM: > + imm = static_cast<AvndImmEvt*>(evt->info.imm.imm_evt); > + delete imm; > + break; > + > default: > LOG_NO("%s: unknown event type %u", __FUNCTION__, > type); > break; > diff --git a/osaf/services/saf/amf/amfnd/hcdb.cc > b/osaf/services/saf/amf/amfnd/hcdb.cc > --- a/osaf/services/saf/amf/amfnd/hcdb.cc > +++ b/osaf/services/saf/amf/amfnd/hcdb.cc > @@ -36,6 +36,7 @@ > #include "avnd.h" > #include <saImmOm.h> > #include <immutil.h> > +#include <string> > > static NCS_PATRICIA_TREE hctypedb; /* healthcheck type db */ > > @@ -339,6 +340,93 @@ SaAisErrorT avnd_hctype_config_get(SaImm > return error; > } > > +// Search for a given key and return its value or empty string if not found. > +static std::string search_key(const std::string& str, const std::string& key) > +{ > + std::string value; > + > + std::string::size_type idx1; > + > + idx1 = str.find(key); > + > + // if key was found > + if (idx1 != std::string::npos) { > + // get value, idx2 points to value > + idx1 += key.length(); > + std::string part2 = str.substr(idx1); > + > + idx1 = part2.find(","); > + > + // get value > + value = part2.substr(0, idx1); > + } > + > + return value; > +} > + > +// > +static void comp_hctype_update_compdb(AVND_CB *cb, > AVSV_PARAM_INFO *param) > +{ > + AVND_COMP_HC_REC *comp_hc_rec; > + AVND_COMP * comp; > + char *comp_type_name; > + AVSV_HLT_KEY hlt_chk; > + AVND_COMP_HC_REC tmp_hc_rec; > + > + // 1. find component from componentType, > + // input example, param->name.value = > safHealthcheckKey=AmfDemo,safVersion=1,safCompType=AmfDemo1 > + comp_type_name = strstr((char *) param->name.value, "safVersion"); > + TRACE("comp_type_name: %s", comp_type_name); > + osafassert(comp_type_name); > + > + // 2. search each component for a matching compType > + comp = (AVND_COMP *) ncs_patricia_tree_getnext(&cb->compdb, > (uint8_t *) 0); > + while (comp != 0) { > + if (strncmp((const char*) comp->saAmfCompType.value, > comp_type_name, comp->saAmfCompType.length) == 0) { > + > + // 3. matching compType found, check that component > does not have a SaAmfHealthcheck rec (specialization) > + std::string hlt_chk_key = search_key((const char*) > param->name.value, "safHealthcheckKey="); > + if (hlt_chk_key.empty()) { > + LOG_ER("%s: failed to get healthcheckKey > from %s", __FUNCTION__, param->name.value); > + return; > + } > + > + memset(&hlt_chk, 0, sizeof(AVSV_HLT_KEY)); > + hlt_chk.comp_name.length = comp->name.length; > + memcpy(hlt_chk.comp_name.value, comp- > >name.value, hlt_chk.comp_name.length); > + hlt_chk.key_len = hlt_chk_key.size(); > + memcpy(hlt_chk.name.key, hlt_chk_key.c_str(), > hlt_chk_key.size()); > + hlt_chk.name.keyLen = hlt_chk.key_len; > + TRACE("comp_name %s key %s keyLen %u", > hlt_chk.comp_name.value, hlt_chk.name.key, hlt_chk.name.keyLen); > + if (avnd_hcdb_rec_get(cb, &hlt_chk) == 0) { > + TRACE("comp uses healthcheckType rec"); > + // 4. found a component that uses the > healthcheckType record, update the comp_hc_rec > + memset(&tmp_hc_rec, '\0', > sizeof(AVND_COMP_HC_REC)); > + tmp_hc_rec.key = hlt_chk.name; > + tmp_hc_rec.req_hdl = comp->reg_hdl; > + TRACE("tmp_hc_rec: key %s req_hdl %llu", > tmp_hc_rec.key.key, tmp_hc_rec.req_hdl); > + if ((comp_hc_rec = > m_AVND_COMPDB_REC_HC_GET(*comp, tmp_hc_rec)) != 0) { > + TRACE("comp_hc_rec: period %llu > max_dur %llu", comp_hc_rec->period, comp_hc_rec->max_dur); > + switch (param->attr_id) { > + case saAmfHctDefPeriod_ID: > + comp_hc_rec->period = > *((SaTimeT *) param->value); > + LOG_NO("%s: > saAmfHctDefPeriod updated, new value: %" PRIu64, __FUNCTION__, > (uint64_t) comp_hc_rec->period); > + break; > + case saAmfHctDefMaxDuration_ID: > + comp_hc_rec->max_dur = > *((SaTimeT *) param->value); > + LOG_NO("%s: > saAmfHctDefMaxDuration updated, new value: %" PRIu64, __FUNCTION__, > (uint64_t) comp_hc_rec->max_dur); > + break; > + default: > + osafassert(0); > + } > + } > + } > + } > + comp = (AVND_COMP *) ncs_patricia_tree_getnext(&cb- > >compdb, (uint8_t *) & comp->name); > + } > +} > + > +// > uint32_t avnd_hc_oper_req(AVND_CB *cb, AVSV_PARAM_INFO *param) > { > uint32_t rc = NCSCC_RC_FAILURE; > @@ -401,3 +489,65 @@ done: > return rc; > } > > +uint32_t avnd_hctype_oper_req(AVND_CB *cb, AVSV_PARAM_INFO > *param) > +{ > + uint32_t rc = NCSCC_RC_FAILURE; > + > + TRACE_ENTER2("'%s'", param->name.value); > + AVND_HCTYPE *hctype = (AVND_HCTYPE *) > ncs_patricia_tree_get(&hctypedb, (uint8_t *)¶m->name); > + > + switch (param->act) { > + case AVSV_OBJ_OPR_MOD: { > + if (!hctype) { > + LOG_ER("%s: failed to get %s", __FUNCTION__, > param->name.value); > + goto done; > + } > + > + switch (param->attr_id) { > + case saAmfHctDefPeriod_ID: > + osafassert(sizeof(SaTimeT) == param->value_len); > + hctype->saAmfHctDefPeriod = *((SaTimeT *)param- > >value); > + comp_hctype_update_compdb(cb, param); > + break; > + > + case saAmfHctDefMaxDuration_ID: > + osafassert(sizeof(SaTimeT) == param->value_len); > + hctype->saAmfHctDefMaxDuration = *((SaTimeT > *)param->value); > + comp_hctype_update_compdb(cb, param); > + break; > + > + default: > + LOG_NO("%s: Unsupported attribute %u", > __FUNCTION__, param->attr_id); > + goto done; > + } > + break; > + } > + > + case AVSV_OBJ_OPR_DEL: { > + if (hctype != NULL) { > + rc = ncs_patricia_tree_del(&hctypedb, &hctype- > >tree_node); > + osafassert(rc == NCSCC_RC_SUCCESS); > + LOG_IN("Deleted '%s'", param->name.value); > + } else { > + /* > + ** Normal case that happens if a parent of this HC was > + ** the real delete target for the CCB. > + */ > + TRACE("already deleted!"); > + } > + > + break; > + } > + default: > + LOG_NO("%s: Unsupported action %u", __FUNCTION__, > param->act); > + goto done; > + } > + > + rc = NCSCC_RC_SUCCESS; > + > +done: > + rc = NCSCC_RC_SUCCESS; > + > + TRACE_LEAVE(); > + return rc; > +} > diff --git a/osaf/services/saf/amf/amfnd/imm.cc > b/osaf/services/saf/amf/amfnd/imm.cc > new file mode 100644 > --- /dev/null > +++ b/osaf/services/saf/amf/amfnd/imm.cc > @@ -0,0 +1,758 @@ > +/* -*- OpenSAF -*- > + * > + * (C) Copyright 2014 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 > + * > + */ > + > +/*********************************************************** > ****************** > + > + DESCRIPTION: > + > + > ************************************************************* > ***************/ > +#include <string> > +#include <cstring> > +#include <algorithm> > +#include <poll.h> > +#include "avnd_imm.h" > +#include "immutil.h" > + > +extern struct ImmutilWrapperProfile immutilWrapperProfile; > + > +// > +SaVersionT AvndImm::immVersion_ = {'A', 2, 11}; > +SaImmOiHandleT AvndImm::immOiHandle_ = 0; > +SaImmOiHandleT AvndImm::immOmHandle_ = 0; > +SaSelectionObjectT AvndImm::imm_sel_obj_ = -1; > +AvndImm::UpdateFn > AvndImm::update_callback_[AVSV_SA_AMF_CLASS_MAX] = {0}; > + > +// This string array must match the AVND_AMF_CLASS_ID enum > +const char *AvndImm::avnd_class_names_[] = { > + "SaAmfHealthcheckType" > +}; > + > +/** > + * This method adds IMM modification attribute to attribute vector > + * > + * @param attr > + */ > +void AvndImmEvt::set_mod_attr(const SaImmAttrModificationT_2& attr) { > + SaImmAttrModificationT_2 *tmp = new SaImmAttrModificationT_2; > + tmp->modType = attr.modType; > + AvndImmUtil::copySaImmAttrValuesT(tmp->modAttr, attr.modAttr); > + attr_.push_back(tmp); > +} > + > + > +/** > + * Destructor > + */ > +AvndImmEvt::~AvndImmEvt() { > + std::for_each(attr_.begin(), attr_.end(), AvndImmUtil::remove_attr); > + attr_.clear(); > +} > + > +/** > + * This function returns a pointer to a new string which is a duplicate of > the > string s. > + * > + * @param s > + * > + * @return pointer to new string > + */ > +char *AvndImmUtil::str_dup(const char *s) { > + char *c = new char[strlen(s) + 1]; > + std::strcpy(c, s); > + return c; > +} > + > +/** > + * This function returns the size of given attribute value type. > + * > + * @param attrValueType > + * > + * @return attrValueType size > + */ > +size_t AvndImmUtil::value_size(SaImmValueTypeT attrValueType) { > + size_t value_size = 0; > + > + switch (attrValueType) { > + case SA_IMM_ATTR_SAINT32T: > + value_size = sizeof(SaInt32T); > + break; > + case SA_IMM_ATTR_SAUINT32T: > + value_size = sizeof(SaUint32T); > + break; > + case SA_IMM_ATTR_SAINT64T: > + value_size = sizeof(SaInt64T); > + break; > + case SA_IMM_ATTR_SAUINT64T: > + value_size = sizeof(SaUint64T); > + break; > + case SA_IMM_ATTR_SATIMET: > + value_size = sizeof(SaTimeT); > + break; > + case SA_IMM_ATTR_SANAMET: > + value_size = sizeof(SaNameT); > + break; > + case SA_IMM_ATTR_SAFLOATT: > + value_size = sizeof(SaFloatT); > + break; > + case SA_IMM_ATTR_SADOUBLET: > + value_size = sizeof(SaDoubleT); > + break; > + case SA_IMM_ATTR_SASTRINGT: > + value_size = sizeof(SaStringT); > + break; > + case SA_IMM_ATTR_SAANYT: > + osafassert(0); > + break; > + } > + > + return value_size; > +} > + > +/** > + * This function returns class enum corresponding to object name. > + * > + * @param obj_name > + * @param class_type > + * > + * @return AVSV_AMF_CLASS_ID > + */ > +AVSV_AMF_CLASS_ID AvndImmUtil::object_name_to_class_type(const > SaNameT *obj_name) { > + AVSV_AMF_CLASS_ID class_type = AVSV_SA_AMF_CLASS_INVALID; > + > + /* Cluster and Node Class Related */ > + if (strncmp((char *)&obj_name->value, "safAmfCluster=", 14) == 0) { > + class_type = AVSV_SA_AMF_CLUSTER; > + } else if (strncmp((char *)&obj_name->value, "safAmfNode=", 11) == 0) { > + class_type = AVSV_SA_AMF_NODE; > + } else if (strncmp((char *)&obj_name->value, "safAmfNodeGroup=", 16) == > 0) { > + class_type = AVSV_SA_AMF_NODE_GROUP; > + } else if (strncmp((char *)&obj_name->value, "safInstalledSwBundle=", 21) > == 0) { > + class_type = AVSV_SA_AMF_NODE_SW_BUNDLE; > + } > + > + /* Application Class Related */ > + else if (strncmp((char *)&obj_name->value, "safApp=", 7) == 0) { > + class_type = AVSV_SA_AMF_APP; > + } else if (strncmp((char *)&obj_name->value, "safAppType=", 11) == 0) { > + class_type = AVSV_SA_AMF_APP_BASE_TYPE; > + } > + > + /* Service Group Class Related */ > + else if (strncmp((char *)&obj_name->value, "safSg=", 6) == 0) { > + class_type = AVSV_SA_AMF_SG; > + } else if (strncmp((char *)&obj_name->value, "safSgType=", 10) == 0) { > + class_type = AVSV_SA_AMF_SG_BASE_TYPE; > + } > + > + /* Service Unit Class Related */ > + else if (strncmp((char *)&obj_name->value, "safSu=", 6) == 0) { > + class_type = AVSV_SA_AMF_SU; > + } else if (strncmp((char *)&obj_name->value, "safSuType=", 10) == 0) { > + class_type = AVSV_SA_AMF_SU_BASE_TYPE; > + } else if (strncmp((char *)&obj_name->value, "safMemberCompType=", 18) > == 0) { > + class_type = AVSV_SA_AMF_SUT_COMP_TYPE; > + } > + > + /* Service Instance Class Related */ > + else if (strncmp((char *)&obj_name->value, "safSi=", 6) == 0) { > + class_type = AVSV_SA_AMF_SI; > + } else if (strncmp((char *)&obj_name->value, "safSvcType=", 11) == 0) { > + class_type = AVSV_SA_AMF_SVC_BASE_TYPE; > + } else if (strncmp((char *)&obj_name->value, "safDepend=", 10) == 0) { > + class_type = AVSV_SA_AMF_SI_DEPENDENCY; > + } else if (strncmp((char *)&obj_name->value, "safRankedSu=", 12) == 0) { > + class_type = AVSV_SA_AMF_SI_RANKED_SU; > + } else if (strncmp((char *)&obj_name->value, "safSISU=", 8) == 0) { > + class_type = AVSV_SA_AMF_SI_ASSIGNMENT; > + } else if (strncmp((char *)&obj_name->value, "safMemberCSType=", 16) == > 0) { > + class_type = AVSV_SA_AMF_SVC_TYPE_CS_TYPES; > + } > + > + /* Component Service Instance Class Related */ > + else if (strncmp((char *)&obj_name->value, "safCsi=", 7) == 0) { > + class_type = AVSV_SA_AMF_CSI; > + } else if (strncmp((char *)&obj_name->value, "safCSType=", 10) == 0) { > + class_type = AVSV_SA_AMF_CS_BASE_TYPE; > + } else if (strncmp((char *)&obj_name->value, "safCsiAttr=", 11) == 0) { > + class_type = AVSV_SA_AMF_CSI_ATTRIBUTE; > + } else if (strncmp((char *)&obj_name->value, "safCSIComp=", 11) == 0) { > + class_type = AVSV_SA_AMF_CSI_ASSIGNMENT; > + } > + > + /* Component and component types Related */ > + else if (strncmp((char *)&obj_name->value, "safCompType=", 12) == 0) { > + class_type = AVSV_SA_AMF_COMP_BASE_TYPE; > + } else if (strncmp((char *)&obj_name->value, "safSupportedCsType=", 19) == > 0) { > + if (strstr((char *)&obj_name->value, "safCompType=") != 0) { > + class_type = AVSV_SA_AMF_CT_CS_TYPE; > + } else if (strstr((char *)&obj_name->value, "safComp=") != 0) { > + class_type = AVSV_SA_AMF_COMP_CS_TYPE; > + } > + } else if (strncmp((char *)&obj_name->value, "safComp=", 8) == 0) { > + class_type = AVSV_SA_AMF_COMP; > + } > + > + /* Global Component Attributes and Health Check Related */ > + else if (strncmp((char *)&obj_name->value, "safRdn=", 7) == 0) { > + class_type = AVSV_SA_AMF_COMP_GLOBAL_ATTR; > + } else if (strncmp((char *)&obj_name->value, "safHealthcheckKey=", 18) == > 0) { > + if (strstr((char *)&obj_name->value, "safVersion=") != 0) { > + class_type = AVSV_SA_AMF_HEALTH_CHECK_TYPE; > + } else if (strstr((char *)&obj_name->value, "safComp=") != 0) { > + class_type = AVSV_SA_AMF_HEALTH_CHECK; > + } > + } > + > + /* Common Version Related */ > + else if (strncmp((char *)&obj_name->value, "safVersion=", 11) == 0) { > + if (strstr((char *)&obj_name->value, "safAppType=") != 0) { > + class_type = AVSV_SA_AMF_APP_TYPE; > + } else if (strstr((char *)&obj_name->value, "safSgType=") != 0) { > + class_type = AVSV_SA_AMF_SG_TYPE; > + } else if (strstr((char *)&obj_name->value, "safSuType=") != 0) { > + class_type = AVSV_SA_AMF_SU_TYPE; > + } else if (strstr((char *)&obj_name->value, "safSvcType=") != 0) { > + class_type = AVSV_SA_AMF_SVC_TYPE; > + } else if (strstr((char *)&obj_name->value, "safCSType=") != 0) { > + class_type = AVSV_SA_AMF_CS_TYPE; > + } else if (strstr((char *)&obj_name->value, "safCompType=") != 0) { > + class_type = AVSV_SA_AMF_COMP_TYPE; > + } > + } > + > + return class_type; > +} > + > +/** > + * Delete attribute structures. > + * > + * @param attr > + */ > +void AvndImmUtil::remove_attr(SaImmAttrModificationT_2* attr) { > + AvndImmUtil::deleteSaImmAttrValuesT(attr->modAttr); > + delete attr; > +} > + > +/** > + * Delete attribute values. > + * > + * @param reference to attrValue > + */ > +void AvndImmUtil::deleteSaImmAttrValuesT(SaImmAttrValuesT_2& > attr_value) { > + unsigned int i; > + > + if (attr_value.attrValueType == SA_IMM_ATTR_SASTRINGT) { > + for (i = 0; i < attr_value.attrValuesNumber; i++) { > + char *p = *((char**) attr_value.attrValues[i]); > + delete [] p; > + } > + } > + > + delete [] attr_value.attrName; > + delete [] static_cast<char*> (attr_value.attrValues[0]); // free blob > shared by > all values > + delete [] attr_value.attrValues; > + > +} > + > +/** > + * Copy IMM attr values, > + * > + * @param to > + * @param from > + */ > +void AvndImmUtil::copySaImmAttrValuesT(SaImmAttrValuesT_2& to, const > SaImmAttrValuesT_2& from) { > + size_t val_size = 0; > + unsigned int i; > + unsigned int value_count = from.attrValuesNumber; > + char *databuffer; > + > + to.attrName = str_dup(from.attrName); > + > + to.attrValuesNumber = value_count; > + to.attrValueType = from.attrValueType; > + if (value_count == 0) > + return; /* (just in case...) */ > + > + to.attrValues = new SaImmAttrValueT[value_count]; > + > + val_size = value_size(from.attrValueType); > + > + // alloc blob shared by all values > + databuffer = new char[value_count * val_size]; > + > + for (i = 0; i < value_count; i++) { > + to.attrValues[i] = databuffer; > + if (from.attrValueType == SA_IMM_ATTR_SASTRINGT) { > + char *cporig = *((char **) from.attrValues[i]); > + char **cpp = (char **) databuffer; > + *cpp = str_dup(cporig); > + } else { > + memcpy(databuffer, from.attrValues[i], val_size); > + } > + databuffer += val_size; > + } > +} > + > +/** > + * Function called for not implemented callback types. > + * > + * @param object_name > + * @param imm_attr > + * > + * @return NCSCC_RC_FAILURE; > + */ > +uint32_t AvndImm::not_yet_implemented(const std::string& object_name, > const SaImmAttrModificationT_2* imm_attr) { > + LOG_WA("Not yet implemented"); > + return NCSCC_RC_FAILURE; > +} > + > +/** > + * Function called for updating health check type. > + * > + * @param object_name > + * @param imm_attr > + * > + * @return NCSCC_RC_SUCCESS or NCSCC_RC_FAILURE; > + */ > +uint32_t AvndImm::update_health_check_type(const std::string& > object_name, const SaImmAttrModificationT_2* imm_attr) { > + uint32_t rc = NCSCC_RC_FAILURE; > + AVND_CB *cb = avnd_cb; > + > + AVSV_PARAM_INFO param; > + memset(¶m, 0, sizeof(param)); > + param.class_id = AVSV_SA_AMF_HEALTH_CHECK_TYPE; > + > + std::string attr_name = imm_attr->modAttr.attrName; > + > + strncpy((char*) param.name.value, object_name.c_str(), > object_name.size()); > + param.name.length = object_name.size(); > + > + if (attr_name == "saAmfHctDefPeriod") { > + param.attr_id = saAmfHctDefPeriod_ID; > + } else if (attr_name == "saAmfHctDefMaxDuration") { > + param.attr_id = saAmfHctDefMaxDuration_ID; > + } else { > + LOG_WA("Unknown attribute name %s", attr_name.c_str()); > + rc = NCSCC_RC_FAILURE; > + goto done; > + } > + > + if (imm_attr->modType == SA_IMM_ATTR_VALUES_REPLACE) { > + param.act = AVSV_OBJ_OPR_MOD; > + } else if (imm_attr->modType == SA_IMM_ATTR_VALUES_DELETE) { > + param.act = AVSV_OBJ_OPR_DEL; > + } else { > + LOG_WA("Unknown modificaton type %d", imm_attr->modType); > + rc = NCSCC_RC_FAILURE; > + goto done; > + } > + > + param.value_len = AvndImmUtil::value_size(imm_attr- > >modAttr.attrValueType); > + memcpy(param.value, *imm_attr->modAttr.attrValues, param.value_len); > + > + rc = avnd_hctype_oper_req(cb, ¶m); > + > +done: > + return rc; > +} > + > +/** > + * IMM event handle, dispatch callback function for each changed attribute in > the current event. > + * > + * @param cb > + * @param evt > + * > + * @return NCSCC_RC_SUCCESS or NCSCC_RC_FAILURE > + */ > +uint32_t avnd_evt_imm_evh(AVND_CB *cb, AVND_EVT *evt) { > + AVSV_AMF_CLASS_ID type; > + uint32_t rc = NCSCC_RC_FAILURE; > + > + TRACE_ENTER(); > + > + AvndImmEvt *imm_evt = (AvndImmEvt*) evt->info.imm.imm_evt; > + > + // TODO(uabhano) change object_name_to_class_type argument to > std::string, then the SaNameT code below can be removed > + SaNameT obj_name; > + obj_name.length = imm_evt->get_object_name().size(); > + memcpy((char*)obj_name.value, imm_evt->get_object_name().c_str(), > obj_name.length); > + type = AvndImmUtil::object_name_to_class_type(&obj_name); > + > + for (std::vector<SaImmAttrModificationT_2*>::const_iterator it = imm_evt- > >begin(); it != imm_evt->end(); ++it) { > + const SaImmAttrModificationT_2 *imm_attr = *it; > + rc = AvndImm::update_callback_[type](imm_evt->get_object_name(), > imm_attr); > + } > + > + TRACE_LEAVE(); > + return rc; > +} > + > +/** > + * Handle imm apply, create and send an AvndImmEvt object to the avnd main > thread. > + * > + * @param immoi_handle > + * @param ccb_id > + */ > +void AvndImm::ccb_apply_cb(SaImmOiHandleT immoi_handle, > SaImmOiCcbIdT ccb_id) { > + AVND_EVT_TYPE type = AVND_EVT_IMM; > + > + AVND_EVT *evt = 0; > + const SaImmAttrModificationT_2 *mod; > + int i = 0; > + CcbUtilCcbData_t *ccb_util_ccb_data; > + CcbUtilOperationData_t *opdata = NULL; > + AvndImmEvt *imm_evt; > + uint32_t rc = NCSCC_RC_SUCCESS; > + AVND_CB *cb = avnd_cb; > + > + TRACE_ENTER2("CCB ID %llu", ccb_id); > + > + while ((opdata = ccbutil_getNextCcbOp(ccb_id, opdata)) != NULL) { > + imm_evt = new AvndImmEvt(opdata->objectName); > + while ((mod = opdata->param.modify.attrMods[i++]) != NULL) { > + imm_evt->set_mod_attr(*mod); > + } > + > + i = 0; > + > + /* create and send an event */ > + > + evt = new AVND_EVT(); > + > + evt->type = type; > + evt->priority = NCS_IPC_PRIORITY_NORMAL; > + evt->info.imm.imm_evt = imm_evt; > + > + rc = m_NCS_IPC_SEND(&cb->mbx, evt, evt->priority); > + if (rc != NCSCC_RC_SUCCESS) { > + LOG_CR("AvND send event to mailbox failed, type = %u", evt->type); > + } > + } > + > + /* Return CCB container memory */ > + ccb_util_ccb_data = ccbutil_findCcbData(ccb_id); > + osafassert(ccb_util_ccb_data); > + ccbutil_deleteCcbData(ccb_util_ccb_data); > + > + TRACE_LEAVE(); > +} > + > +/** > + * IMM modify callback, memorize the request. > + * > + * @param immoi_handle > + * @param ccb_id > + * @param object_name > + * @param attr_mods > + * > + * @return SA_AIS_OK or or SA_AIS_ERR_xx > + */ > +SaAisErrorT AvndImm::ccb_object_modify_cb(SaImmOiHandleT > immoi_handle, > + SaImmOiCcbIdT ccb_id, const SaNameT *object_name, > + const SaImmAttrModificationT_2 **attr_mods) { > + SaAisErrorT rc = SA_AIS_OK; > + struct CcbUtilCcbData *ccb_util_ccb_data; > + > + TRACE_ENTER2("CCB ID %llu, %s", ccb_id, object_name->value); > + > + if ((ccb_util_ccb_data = ccbutil_getCcbData(ccb_id)) != NULL) { > + /* "memorize the request" */ > + if (ccbutil_ccbAddModifyOperation(ccb_util_ccb_data, object_name, > attr_mods) != 0) { > + LOG_ER("Failed '%s'", object_name->value); > + rc = SA_AIS_ERR_BAD_OPERATION; > + } > + } else { > + LOG_ER("Failed to get CCB object for %llu", ccb_id); > + rc = SA_AIS_ERR_NO_MEMORY; > + } > + > + TRACE_LEAVE(); > + > + return rc; > +} > + > +/** > + * IMM ccb abort callback. > + * > + * @param immoi_handle > + * @param ccb_id > + */ > +void AvndImm::ccb_abort_cb(SaImmOiHandleT immoi_handle, > SaImmOiCcbIdT ccb_id) { > + TRACE_ENTER(); > + > + CcbUtilCcbData_t *ccb_util_ccb_data; > + > + /* Return CCB container memory */ > + ccb_util_ccb_data = ccbutil_findCcbData(ccb_id); > + osafassert(ccb_util_ccb_data); > + ccbutil_deleteCcbData(ccb_util_ccb_data); > + > + TRACE_LEAVE(); > +} > + > +/** > + * IMM ccb object delete callback. > + * > + * @param immoi_handle > + * @param ccb_id, > + * @param object_name > + * > + * @return SA_AIS_OK > + */ > +SaAisErrorT AvndImm::ccb_object_delete_cb(SaImmOiHandleT > immoi_handle, > + SaImmOiCcbIdT ccb_id, const SaNameT *object_name) { > + > + TRACE_ENTER(); > + TRACE_LEAVE(); > + > + return SA_AIS_OK; > +} > + > +/** > + * IMM ccb completed callback. > + * > + * @param immoi_handle > + * @param ccb_id, > + * > + * @return SA_AIS_OK > + */ > +SaAisErrorT AvndImm::ccb_completed_cb(SaImmOiHandleT immoi_handle, > + SaImmOiCcbIdT ccb_id) { > + > + TRACE_ENTER(); > + TRACE_LEAVE(); > + > + return SA_AIS_OK; > +} > + > +/** > + * IMM ccb object create callback. > + * > + * @param immoi_handle > + * @param ccb_id > + * @param class_name > + * @param parent_name > + * @param attr > + * > + * @return SA_AIS_OK > + */ > +SaAisErrorT AvndImm::ccb_object_create_cb(SaImmOiHandleT > immoi_handle, > + SaImmOiCcbIdT ccb_id, const SaImmClassNameT class_name, > + const SaNameT *parent_name, const SaImmAttrValuesT_2 **attr) { > + > + TRACE_ENTER(); > + TRACE_LEAVE(); > + > + return SA_AIS_OK; > +} > + > +const SaImmOiCallbacksT_2 AvndImm::avnd_callbacks_ = { > + .saImmOiAdminOperationCallback = NULL, > + .saImmOiCcbAbortCallback = ccb_abort_cb, > + .saImmOiCcbApplyCallback = ccb_apply_cb, > + .saImmOiCcbCompletedCallback = ccb_completed_cb, > + .saImmOiCcbObjectCreateCallback = ccb_object_create_cb, > + .saImmOiCcbObjectDeleteCallback = ccb_object_delete_cb, > + .saImmOiCcbObjectModifyCallback = ccb_object_modify_cb, > + .saImmOiRtAttrUpdateCallback = NULL > +}; > + > +/** > + * Set IMM applier. > + * > + * @return SA_AIS_OK or or SA_AIS_ERR_xx > + */ > +SaAisErrorT AvndImm::imm_applier_set() { > + SaAisErrorT rc = SA_AIS_OK; > + uint32_t i; > + std::string applier_name = "@safAmfNodeDirector_"; > + > + TRACE_ENTER(); > + > + char hostname[_POSIX_HOST_NAME_MAX]; > + if (gethostname(hostname, _POSIX_HOST_NAME_MAX) == -1) { > + LOG_ER("gethostname failed: %s\n", strerror(errno)); > + > + /* use the node id of the node on which the AVD is running instead. */ > + SaClmNodeIdT node_id_avnd = m_NCS_GET_NODE_ID; > + snprintf(hostname, _POSIX_HOST_NAME_MAX, "%x", node_id_avnd); > + } > + > + applier_name += hostname; > + > + LOG_NO("IMM applier name: %s", applier_name.c_str()); > + > + // > + if ((rc = immutil_saImmOiImplementerSet(immOiHandle_, (char*) > applier_name.c_str())) != SA_AIS_OK) { > + LOG_ER("saImmOiImplementerSet failed %u", rc); > + return rc; > + } > + > + // > + for (i = 0; i < AVND_SA_AMF_CLASS_MAX; i++) { > + if ((rc = immutil_saImmOiClassImplementerSet(immOiHandle_, > avnd_class_names_[i])) != SA_AIS_OK) { > + LOG_ER("Impl Set Failed for %s, returned %d", avnd_class_names_[i], > rc); > + break; > + } > + } > + > + TRACE_LEAVE(); > + > + return rc; > +} > + > +/** > + * Initialize IMM. > + * > + * @return SA_AIS_OK or or SA_AIS_ERR_xx > + */ > +SaAisErrorT AvndImm::imm_init() { > + SaAisErrorT rc = SA_AIS_OK ; > + > + TRACE_ENTER(); > + > + for (int i = 0; i < AVSV_SA_AMF_CLASS_MAX; ++i) { > + update_callback_[i] = not_yet_implemented; > + } > + > + update_callback_[AVSV_SA_AMF_HEALTH_CHECK_TYPE] = > update_health_check_type; > + > + /* Setup immutils profile once and for all */ > + immutilWrapperProfile.errorsAreFatal = false; > + immutilWrapperProfile.retryInterval = 1000; > + immutilWrapperProfile.nTries = 180; > + > + if ((rc = immutil_saImmOiInitialize_2(&immOiHandle_, &avnd_callbacks_, > &immVersion_)) != SA_AIS_OK) { > + LOG_ER("saImmOiInitialize failed %u", rc); > + goto done; > + } > + > + if ((rc = immutil_saImmOmInitialize(&immOmHandle_, NULL, > &immVersion_)) != SA_AIS_OK) { > + LOG_ER("saImmOmInitialize failed %u", rc); > + goto done; > + } > + > + if ((rc = immutil_saImmOiSelectionObjectGet(immOiHandle_, > &imm_sel_obj_)) != SA_AIS_OK) { > + LOG_ER("saImmOiSelectionObjectGet failed %u", rc); > + goto done; > + } > + > + TRACE("Successfully initialized IMM"); > + > +done: > + TRACE_LEAVE(); > + > + return rc; > +} > + > +/** > + * IMM thread main function, waits for IMM events and dispatch callback > functions. > + */ > +void AvndImm::imm_main() { > + SaAisErrorT rc = SA_AIS_OK; > + > + enum { > + FD_IMM = 0 > + }; > + > + static nfds_t nfds = FD_IMM + 1; > + int polltmo = -1; > + static struct pollfd fds[FD_IMM + 1]; > + > + TRACE_ENTER(); > + > + fds[FD_IMM].fd = imm_sel_obj_; > + fds[FD_IMM].events = POLLIN; > + nfds = FD_IMM + 1; > + > + while (true) { > + int pollretval = poll(fds, nfds, polltmo); > + > + if (pollretval == -1) { > + if (errno == EINTR) > + continue; > + > + LOG_ER("main: poll FAILED - %s", strerror(errno)); > + break; > + } > + > + if (immOiHandle_ && fds[FD_IMM].revents & POLLIN) { > + TRACE("IMM event rec"); > + rc = saImmOiDispatch(immOiHandle_, SA_DISPATCH_ALL); > + if (rc != SA_AIS_OK) { > + LOG_ER("saImmOiDispatch failed: %d", rc); > + > + } > + } > + } > + > + TRACE_LEAVE(); > +} > + > +/** > + * IMM thread start function. Init IMM and set as applier. > + * > + * @return 0 > + */ > +void *AvndImm::imm_start(void *) { > + SaAisErrorT rc = SA_AIS_OK; > + > + TRACE_ENTER(); > + > + if ((rc = imm_init()) != SA_AIS_OK) { > + LOG_ER("avnd_imm_init FAILED"); > + goto done; > + } > + > + if ((rc = imm_applier_set()) != SA_AIS_OK) { > + LOG_ER("avnd_imm_applier set FAILED"); > + goto done; > + } > + > + imm_main(); > + > +done: > + > + return 0; > +} > + > +/** > + * Create IMM thread for applier functionality. > + * > + * @return NCSCC_RC_SUCCESS or NCSCC_RC_FAILURE > + */ > +uint32_t avnd_create_imm_thread() { > + uint32_t rc = NCSCC_RC_SUCCESS; > + pthread_t thread; > + pthread_attr_t attr; > + > + TRACE_ENTER(); > + > + pthread_attr_init(&attr); > + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); > + > + if (pthread_create(&thread, &attr, AvndImm::imm_start, 0) != 0) { > + LOG_ER("pthread_create FAILED: %s", strerror(errno)); > + rc = NCSCC_RC_FAILURE; > + } > + > + pthread_attr_destroy(&attr); > + > + TRACE_LEAVE(); > + > + return rc; > +} > + > diff --git a/osaf/services/saf/amf/amfnd/include/Makefile.am > b/osaf/services/saf/amf/amfnd/include/Makefile.am > --- a/osaf/services/saf/amf/amfnd/include/Makefile.am > +++ b/osaf/services/saf/amf/amfnd/include/Makefile.am > @@ -29,6 +29,7 @@ noinst_HEADERS = \ > avnd_evt.h \ > avnd.h \ > avnd_hc.h \ > + avnd_imm.h \ > avnd_mds.h \ > avnd_mon.h \ > avnd_pg.h \ > diff --git a/osaf/services/saf/amf/amfnd/include/avnd.h > b/osaf/services/saf/amf/amfnd/include/avnd.h > --- a/osaf/services/saf/amf/amfnd/include/avnd.h > +++ b/osaf/services/saf/amf/amfnd/include/avnd.h > @@ -34,6 +34,7 @@ > #define AVND_H > > #include <saImmOm.h> > +#include <saImmOi.h> > > #include "amf.h" > #include "ncs_main_papi.h" > diff --git a/osaf/services/saf/amf/amfnd/include/avnd_evt.h > b/osaf/services/saf/amf/amfnd/include/avnd_evt.h > --- a/osaf/services/saf/amf/amfnd/include/avnd_evt.h > +++ b/osaf/services/saf/amf/amfnd/include/avnd_evt.h > @@ -110,6 +110,8 @@ typedef enum avnd_evt_type { > AVND_EVT_PID_EXIT, > AVND_EVT_TMR_QSCING_CMPL, > > + AVND_EVT_IMM, > + > AVND_EVT_MAX > } AVND_EVT_TYPE; > > @@ -155,6 +157,11 @@ typedef struct avnd_pm_mon_evt { > AVND_COMP_PM_REC *pm_rec; > } AVND_PM_MON_EVT; > > +/* imm event definition */ > +typedef struct avnd_imm_evt { > + void *imm_evt; /* AvndImmEvt ptr */ > +} AVND_IMM_EVT; > + > /* AVND top-level event structure */ > typedef struct avnd_evt_tag { > struct avnd_evt_tag *next; > @@ -173,6 +180,7 @@ typedef struct avnd_evt_tag { > AVND_CLC_EVT clc; > AVND_COMP_FSM_EVT comp_fsm; > AVND_PM_MON_EVT pm_evt; > + AVND_IMM_EVT imm; > } info; > > } AVND_EVT; > diff --git a/osaf/services/saf/amf/amfnd/include/avnd_hc.h > b/osaf/services/saf/amf/amfnd/include/avnd_hc.h > --- a/osaf/services/saf/amf/amfnd/include/avnd_hc.h > +++ b/osaf/services/saf/amf/amfnd/include/avnd_hc.h > @@ -59,5 +59,6 @@ extern SaAisErrorT avnd_hc_config_get(st > extern SaAisErrorT avnd_hctype_config_get(SaImmHandleT immOmHandle, > const SaNameT *comptype_dn); > extern AVND_HCTYPE *avnd_hctypedb_rec_get(const SaNameT > *comp_type_dn, const SaAmfHealthcheckKeyT *key); > extern uint32_t avnd_hc_oper_req(struct avnd_cb_tag *, AVSV_PARAM_INFO > *param); > +extern uint32_t avnd_hctype_oper_req(struct avnd_cb_tag *, > AVSV_PARAM_INFO *param); > > #endif /* !AVND_HC_H */ > diff --git a/osaf/services/saf/amf/amfnd/include/avnd_imm.h > b/osaf/services/saf/amf/amfnd/include/avnd_imm.h > new file mode 100644 > --- /dev/null > +++ b/osaf/services/saf/amf/amfnd/include/avnd_imm.h > @@ -0,0 +1,148 @@ > +/* -*- OpenSAF -*- > + * > + * (C) Copyright 2014 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 > + * > + */ > + > +/*********************************************************** > ****************** > + DESCRIPTION: > + > + Classes used for implementing AMF node director as an IMM applier. > + > + > ************************************************************* > ***************** > + */ > + > +#ifndef AVND_IMM_H > +#define AVND_IMM_H > + > +#ifdef __cplusplus > + > +#include <vector> > +#include <string> > +#include "avnd.h" > + > +// > +typedef enum { > + AVND_SA_AMF_HEALTH_CHECK_TYPE = 0, > + AVND_SA_AMF_CLASS_MAX > +} AVND_AMF_CLASS_ID; > + > +//-------------------------------------------------------------------------- > +// < \ingroup avndImm > +// > +// This class is used as a container for one IMM modify callback. > +// > > +//-------------------------------------------------------------------------- > +class AvndImmEvt { > +public: > + // > + explicit AvndImmEvt(const SaNameT& obj_name) : object_name_((const > char*) obj_name.value, obj_name.length) {} > + > + // > + ~AvndImmEvt(); > + > + // > + std::string get_object_name() {return object_name_;} > + > + // > + void set_mod_attr(const SaImmAttrModificationT_2& attr); > + > + // > + typedef typename std::vector<SaImmAttrModificationT_2*>::const_iterator > const_iterator; > + const_iterator begin() const {return attr_.begin();} > + const_iterator end() const {return attr_.end();} > + > +private: > + // > + AvndImmEvt(const AvndImmEvt&); > + void operator=(const AvndImmEvt&); > + > + std::string object_name_; > + > + std::vector<SaImmAttrModificationT_2*> attr_; > +}; > + > +//-------------------------------------------------------------------------- > +// < \ingroup avndImm > +// > +// This class contains utility functions for IMM. > +// > > +//-------------------------------------------------------------------------- > +class AvndImmUtil { > +public: > + // > + static void deleteSaImmAttrValuesT(SaImmAttrValuesT_2& attr_value); > + static void copySaImmAttrValuesT(SaImmAttrValuesT_2& to, const > SaImmAttrValuesT_2& from); > + static char *str_dup(const char *str); > + static size_t value_size(SaImmValueTypeT attrValueType); > + static AVSV_AMF_CLASS_ID object_name_to_class_type(const SaNameT* > obj_name); > + static void remove_attr(SaImmAttrModificationT_2* attr); > +private: > + AvndImmUtil(); > + AvndImmUtil(const AvndImmUtil&); > + void operator=(const AvndImmUtil&); > +}; > + > +//-------------------------------------------------------------------------- > +// < \ingroup avndImm > +// > +// This class contains IMM callback, init and set functions. > +// > > +//-------------------------------------------------------------------------- > +class AvndImm { > + public: > + // > + typedef uint32_t (*UpdateFn) (const std::string& dn, const > SaImmAttrModificationT_2* attr); > + > + // > + static void ccb_abort_cb(SaImmOiHandleT immoi_handle, SaImmOiCcbIdT > ccb_id); > + static SaAisErrorT ccb_object_delete_cb(SaImmOiHandleT immoi_handle, > SaImmOiCcbIdT ccb_id, const SaNameT *object_name); > + static void ccb_apply_cb(SaImmOiHandleT immoi_handle, SaImmOiCcbIdT > ccb_id); > + static SaAisErrorT ccb_completed_cb(SaImmOiHandleT immoi_handle, > SaImmOiCcbIdT ccb_id); > + static SaAisErrorT ccb_object_create_cb(SaImmOiHandleT immoi_handle, > SaImmOiCcbIdT ccb_id, const SaImmClassNameT class_name, > + const SaNameT *parent_name, const > SaImmAttrValuesT_2 **attr); > + static SaAisErrorT ccb_object_modify_cb(SaImmOiHandleT immoi_handle, > SaImmOiCcbIdT ccb_id, const SaNameT *object_name, const > SaImmAttrModificationT_2 **attr_mods); > + static void *imm_start(void *); > + > + // > + static uint32_t not_yet_implemented(const std::string& object_name, const > SaImmAttrModificationT_2* imm_attr); > + static uint32_t update_health_check_type(const std::string& object_name, > const SaImmAttrModificationT_2* imm_attr); > + > + // > + static SaVersionT immVersion_; > + static SaImmOiHandleT immOiHandle_; > + static SaImmOiHandleT immOmHandle_; > + static SaSelectionObjectT imm_sel_obj_; > + static UpdateFn update_callback_[AVSV_SA_AMF_CLASS_MAX]; > + static const char *avnd_class_names_[]; > + private: > + static SaAisErrorT imm_init(); > + static void imm_main(); > + static SaAisErrorT imm_applier_set(); > + static const SaImmOiCallbacksT_2 avnd_callbacks_; > + > + // > + AvndImm(); > + AvndImm(const AvndImmUtil&); > + void operator=(const AvndImm&); > +}; > + > +// > +extern uint32_t avnd_evt_imm_evh(AVND_CB *cb, AVND_EVT *evt); > +extern uint32_t avnd_create_imm_thread(); > + > +#endif /* __cplusclpus */ > + > +#endif /* AVND_IMM_H */ > + > diff --git a/osaf/services/saf/amf/amfnd/main.cc > b/osaf/services/saf/amf/amfnd/main.cc > --- a/osaf/services/saf/amf/amfnd/main.cc > +++ b/osaf/services/saf/amf/amfnd/main.cc > @@ -31,6 +31,7 @@ > #include "immutil.h" > #include "logtrace.h" > #include "nid_api.h" > +#include "avnd_imm.h" > > #define FD_MBX 0 > #define FD_TERM 1 > @@ -117,7 +118,8 @@ extern const AVND_EVT_HDLR g_avnd_func_l > avnd_evt_comp_pres_fsm_evh, /* AVND_EVT_COMP_PRES_FSM_EV > */ > avnd_evt_last_step_term_evh, /* AVND_EVT_LAST_STEP_TERM */ > avnd_evt_pid_exit_evh, /* AVND_EVT_PID_EXIT */ > - avnd_evt_tmr_qscing_cmpl_evh /* > AVND_EVT_TMR_QSCING_CMPL */ > + avnd_evt_tmr_qscing_cmpl_evh, /* > AVND_EVT_TMR_QSCING_CMPL */ > + avnd_evt_imm_evh /* AVND_EVT_IMML */ > }; > > /* global task handle */ > @@ -273,6 +275,12 @@ uint32_t avnd_create(void) > rc = NCSCC_RC_FAILURE; > goto done; > } > + > + rc = avnd_create_imm_thread(); > + if (NCSCC_RC_SUCCESS != rc) { > + rc = NCSCC_RC_FAILURE; > + goto done; > + } > > done: > TRACE_LEAVE(); ------------------------------------------------------------------------------ Time is money. Stop wasting it! Get your web API in 5 minutes. www.restlet.com/download http://p.sf.net/sfu/restlet _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel