Hi, (back from a 1 week vacation).
I reponded outside the list to Mahesh.

Ack'ed this ticket today.

/AndersBj

-----Original Message-----
From: Nagendra Kumar [mailto:nagendr...@oracle.com] 
Sent: den 29 maj 2014 08:24
To: Hans Nordebäck; Hans Feldt
Cc: opensaf-devel@lists.sourceforge.net
Subject: Re: [devel] [PATCH 1 of 1] AMF: Use IMM applier in the AMF node 
director V3 [#819]

Hi Anders Bj,   can we solicit your response on imm performance.

Response inline with [Nagu].            

Thanks
-Nagu
> -----Original Message-----
> From: Hans Nordebäck [mailto:hans.nordeb...@ericsson.com]
> Sent: 28 May 2014 15:59
> To: Hans Feldt
> Cc: Nagendra Kumar; Praveen Malviya; 
> opensaf-devel@lists.sourceforge.net
> Subject: Re: [PATCH 1 of 1] AMF: Use IMM applier in the AMF node 
> director V3 [#819]
> 
> Hi, see inline. /Regards HansN
> On 05/28/14 12:18, Hans Feldt wrote:
> > See inline and please comment.
> > /HansF
> >
> >> -----Original Message-----
> >> From: Nagendra Kumar [mailto:nagendr...@oracle.com]
> >> Sent: den 28 maj 2014 12:13
> >> To: Hans Nordebäck; Hans Feldt; Praveen Malviya
> >> Cc: opensaf-devel@lists.sourceforge.net
> >> Subject: RE: [PATCH 1 of 1] AMF: Use IMM applier in the AMF node 
> >> director V3 [#819]
> >>
> >> 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).
> > [Hans] I don't understand. This change actually reduces cluster 
> > impact during
> change. The AMF director validates and lets IMM distribute the change.
> >
> > 517 is something else. The relation to this patch is that handling 
> > of
> BADHANDLE needs to be added. I have looked at 517 an my conclusion is 
> that amfnd needs a helper thread to read from IMM. That thread can 
> block and reinitialize with IMM.
[Nagu]: Please check the imm and amf performance with this patch. For 70 node 
setups and with 200 CCBs apply, it will block immnd to longer sync time for 
further operations.
We need to have stats before we proceed this fix.
I would rather offer sending these attributes from amfd to amfnd a more 
traditional way.

> >
> >> 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.
> > [Hans] well I guess the idea as to only handle modifications of 
> > existing already
> used objects. How can something similar like 926 happen to amfnd you mean?
[Nagu]: For example, amfnd gets modify before Amfd sends su information to 
amfnd.
(Assuming create and modify can come in single ccb.)

> >
> >> 3. It has lots of code duplicity and maintenance.
> > [Hans] that could be true as I have already pointed out.
> [HansN] I agree, but shouldn't this be a separate ticket (refactoring) 
> to make common code reusable, e.g object_name_to_class_type etc and 
> place them in a separate directory?
> >> 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 *)&param->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(&param, 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, &param);
> >>> +
> >>> +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

------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and their 
applications. Written by three acclaimed leaders in the field, 
this first edition is now available. Download your free book today!
http://p.sf.net/sfu/NeoTech
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to