Hi, I made a mistake in rebase the patch, that I reverted fix of #1595 (the last diff) I'll remove that last diff in next version.
Thanks, Minh On 25/02/16 19:44, Minh Hon Chau wrote: > osaf/services/saf/amf/amfd/cluster.cc | 48 +++- > osaf/services/saf/amf/amfd/comp.cc | 8 +- > osaf/services/saf/amf/amfd/csi.cc | 105 +++++++ > osaf/services/saf/amf/amfd/imm.cc | 58 ++++ > osaf/services/saf/amf/amfd/include/cb.h | 5 + > osaf/services/saf/amf/amfd/include/cluster.h | 1 + > osaf/services/saf/amf/amfd/include/csi.h | 2 + > osaf/services/saf/amf/amfd/include/db_template.h | 1 + > osaf/services/saf/amf/amfd/include/evt.h | 3 + > osaf/services/saf/amf/amfd/include/mds.h | 7 +- > osaf/services/saf/amf/amfd/include/msg.h | 2 +- > osaf/services/saf/amf/amfd/include/node.h | 3 + > osaf/services/saf/amf/amfd/include/proc.h | 7 + > osaf/services/saf/amf/amfd/include/sg.h | 1 - > osaf/services/saf/amf/amfd/include/si.h | 1 + > osaf/services/saf/amf/amfd/include/susi.h | 3 + > osaf/services/saf/amf/amfd/include/timer.h | 1 + > osaf/services/saf/amf/amfd/main.cc | 24 + > osaf/services/saf/amf/amfd/mds.cc | 4 +- > osaf/services/saf/amf/amfd/ndfsm.cc | 325 > ++++++++++++++++++++++- > osaf/services/saf/amf/amfd/ndmsg.cc | 18 +- > osaf/services/saf/amf/amfd/ndproc.cc | 103 +++++++- > osaf/services/saf/amf/amfd/node.cc | 17 +- > osaf/services/saf/amf/amfd/sgproc.cc | 47 ++- > osaf/services/saf/amf/amfd/si.cc | 43 ++- > osaf/services/saf/amf/amfd/siass.cc | 121 ++++++++ > osaf/services/saf/amf/amfd/su.cc | 19 +- > 27 files changed, 911 insertions(+), 66 deletions(-) > > > Outlined changes: > . node_up_msg event handling has changed so that amfd can collect > the sync information sent from amfnd > . Node Sync timer is introduced as a window of amfnd sync from headless > > diff --git a/osaf/services/saf/amf/amfd/cluster.cc > b/osaf/services/saf/amf/amfd/cluster.cc > --- a/osaf/services/saf/amf/amfd/cluster.cc > +++ b/osaf/services/saf/amf/amfd/cluster.cc > @@ -25,6 +25,7 @@ > #include <imm.h> > #include <evt.h> > #include <proc.h> > +#include <si_dep.h> > > /* Singleton cluster object */ > static AVD_CLUSTER _avd_cluster; > @@ -52,6 +53,7 @@ AVD_CLUSTER *avd_cluster = &_avd_cluster > void avd_cluster_tmr_init_evh(AVD_CL_CB *cb, AVD_EVT *evt) > { > TRACE_ENTER(); > + AVD_SU *su = nullptr; > saflog(LOG_NOTICE, amfSvcUsrName, "Cluster startup timeout, assigning > SIs to SUs"); > > osafassert(evt->info.tmr.type == AVD_TMR_CL_INIT); > @@ -80,13 +82,57 @@ void avd_cluster_tmr_init_evh(AVD_CL_CB > if ((i_sg->list_of_su.empty() == true) || (i_sg->sg_ncs_spec == > true)) { > continue; > } > - i_sg->realign(cb, i_sg); > + > + if (i_sg->sg_fsm_state == AVD_SG_FSM_STABLE) > + i_sg->realign(cb, i_sg); > + } > + > + if (cb->scs_absence_max_duration > 0) { > + TRACE("check if any SU is auto repair enabled"); > + > + for (std::map<std::string, AVD_SU*>::const_iterator it = > su_db->begin(); > + it != su_db->end(); it++) { > + > + su = it->second; > + > + if (su->list_of_susi == nullptr && > + su->su_on_node != nullptr && > + su->su_on_node->saAmfNodeOperState == > SA_AMF_OPERATIONAL_ENABLED) { > + su_try_repair(su); > + } > + } > } > > done: > TRACE_LEAVE(); > } > > +/**************************************************************************** > + * Name : avd_node_sync_tmr_evh > + * > + * Description : This is node sync timer expiry routine handler > + * > + * Arguments : cb - AvD cb > + * evt - ptr to the received event > + * > + * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE > + * > + * Notes : None. > + ***************************************************************************/ > +void avd_node_sync_tmr_evh(AVD_CL_CB *cb, AVD_EVT *evt) > +{ > + TRACE_ENTER(); > + > + osafassert(evt->info.tmr.type == AVD_TMR_NODE_SYNC); > + LOG_NO("NodeSync timeout"); > + > + // Setting true here to indicate the node sync window has closed > + // Further node up message will be treated specially > + cb->node_sync_window_closed = true; > + > + TRACE_LEAVE(); > +} > + > static void ccb_apply_modify_hdlr(struct CcbUtilOperationData *opdata) > { > const SaImmAttrModificationT_2 *attr_mod; > diff --git a/osaf/services/saf/amf/amfd/comp.cc > b/osaf/services/saf/amf/amfd/comp.cc > --- a/osaf/services/saf/amf/amfd/comp.cc > +++ b/osaf/services/saf/amf/amfd/comp.cc > @@ -161,7 +161,13 @@ void AVD_COMP::avd_comp_pres_state_set(S > node->name.value); > LOG_NO("Node Failfast for '%s' as '%s' enters Term/Inst Failed > state", > node->name.value,comp_info.name.value); > - avd_d2n_reboot_snd(node); > + > + if (node->node_state < AVD_AVND_STATE_PRESENT) { > + // reboot when node_up is processed > + node->reboot = true; > + } else { > + avd_d2n_reboot_snd(node); > + } > } > TRACE_LEAVE(); > } > diff --git a/osaf/services/saf/amf/amfd/csi.cc > b/osaf/services/saf/amf/amfd/csi.cc > --- a/osaf/services/saf/amf/amfd/csi.cc > +++ b/osaf/services/saf/amf/amfd/csi.cc > @@ -1410,3 +1410,108 @@ bool are_sponsor_csis_assigned_in_su(AVD > return true; > } > > +/** > + * Clean up COMPCSI objects by searching for SaAmfCSIAssignment instances in > IMM > + * @return SA_AIS_OK when OK > + */ > +SaAisErrorT avd_compcsi_cleanup(void) > +{ > + SaAisErrorT rc; > + SaImmSearchHandleT searchHandle; > + SaImmSearchParametersT_2 searchParam; > + const char *className = "SaAmfCSIAssignment"; > + > + TRACE_ENTER(); > + > + searchParam.searchOneAttr.attrName = > const_cast<SaImmAttrNameT>("SaImmAttrClassName"); > + searchParam.searchOneAttr.attrValueType = SA_IMM_ATTR_SASTRINGT; > + searchParam.searchOneAttr.attrValue = &className; > + > + if ((rc = immutil_saImmOmSearchInitialize_2(avd_cb->immOmHandle, > nullptr, SA_IMM_SUBTREE, > + SA_IMM_SEARCH_ONE_ATTR | SA_IMM_SEARCH_GET_NO_ATTR, &searchParam, > + nullptr, &searchHandle)) != SA_AIS_OK) { > + LOG_ER("%s: saImmOmSearchInitialize_2 failed: %u", > __FUNCTION__, rc); > + goto done; > + } > + > + SaNameT csiass_name; > + const SaImmAttrValuesT_2 **attributes; > + while ((rc = immutil_saImmOmSearchNext_2(searchHandle, &csiass_name, > + (SaImmAttrValuesT_2 ***)&attributes)) == > SA_AIS_OK) { > + avd_saImmOiRtObjectDelete(&csiass_name); > + } > + > + (void)immutil_saImmOmSearchFinalize(searchHandle); > + > +done: > + TRACE_LEAVE(); > + return SA_AIS_OK; > +} > + > +/** > + * Re-create csi assignment and update comp related states, which are > + * collected after headless > + * Update relevant runtime attributes > + * @return SA_AIS_OK when OK > + */ > +SaAisErrorT avd_compcsi_recreate(AVSV_N2D_ND_CSICOMP_STATE_MSG_INFO *info) > +{ > + AVD_SU_SI_REL *susi; > + const AVD_SI *si; > + AVD_CSI *csi; > + AVD_COMP *comp; > + const AVSV_CSICOMP_STATE_MSG *csicomp; > + const AVSV_COMP_STATE_MSG *comp_state; > + > + TRACE_ENTER(); > + > + for (csicomp = info->csicomp_list; csicomp != nullptr; > csicomp=csicomp->next) { > + csi = csi_db->find(Amf::to_string(&csicomp->safCSI)); > + osafassert(csi); > + > + comp = comp_db->find(Amf::to_string(&csicomp->safComp)); > + osafassert(comp); > + > + TRACE("Received CSICOMP state msg: csi %s, comp %s", > + (char*)&csicomp->safCSI.value, > (char*)&csicomp->safComp.value); > + > + si = csi->si; > + osafassert(si); > + > + susi = avd_susi_find(avd_cb, &comp->su->name, &si->name); > + if (susi == 0) { > + LOG_ER("SU_SI_REL record for SU '%s' and SI '%s' was > not found", > + comp->su->name.value, si->name.value); > + return SA_AIS_ERR_NOT_EXIST; > + } > + > + AVD_COMP_CSI_REL *compcsi = avd_compcsi_create(susi, csi, comp, > true); > + osafassert(compcsi); > + } > + > + for (comp_state = info->comp_list; comp_state != nullptr; comp_state = > comp_state->next) { > + comp = comp_db->find(Amf::to_string(&comp_state->safComp)); > + osafassert(comp); > + > + // operation state > + > comp->avd_comp_oper_state_set(static_cast<SaAmfOperationalStateT>(comp_state->comp_oper_state)); > + > + // . update saAmfCompReadinessState after > SU:saAmfSuReadinessState > + // . saAmfCompCurrProxyName and saAmfCompCurrProxiedNames > wouldn't change during headless > + // so they need not to update > + > + // presense state > + > comp->avd_comp_pres_state_set(static_cast<SaAmfPresenceStateT>(comp_state->comp_pres_state)); > + > + // restart count > + comp->saAmfCompRestartCount = comp_state->comp_restart_cnt; > + m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, comp, > AVSV_CKPT_COMP_RESTART_COUNT); > + avd_saImmOiRtObjectUpdate(&comp->comp_info.name, > + const_cast<SaImmAttrNameT>("saAmfCompRestartCount"), > SA_IMM_ATTR_SAUINT32T, > + &comp->saAmfCompRestartCount); > + } > + > + TRACE_LEAVE(); > + return SA_AIS_OK; > +} > + > diff --git a/osaf/services/saf/amf/amfd/imm.cc > b/osaf/services/saf/amf/amfd/imm.cc > --- a/osaf/services/saf/amf/amfd/imm.cc > +++ b/osaf/services/saf/amf/amfd/imm.cc > @@ -1245,6 +1245,60 @@ static const SaImmOiCallbacksT_2 avd_cal > }; > > > /***************************************************************************** > + * Function: hydra_config_get > + * > + * Purpose: This function checks if Hydra configuration is enabled in IMM > + * then set the corresponding value to scs_absence_max_duration > variable in > + * avd_cb. > + * > + * Input: None. > + * > + * Returns: SaAisErrorT > + * > + * NOTES: If IMM attribute fetching fails that means Hydra > + * configuration is disabled. > + * > + **************************************************************************/ > +static SaAisErrorT hydra_config_get(void) > +{ > + SaAisErrorT rc = SA_AIS_OK; > + const SaImmAttrValuesT_2 **attributes; > + SaImmAccessorHandleT accessorHandle; > + SaNameT dn = {0, "opensafImm=opensafImm,safApp=safImmService"}; > + SaImmAttrNameT attrName = > const_cast<SaImmAttrNameT>("scAbsenceAllowed"); > + SaImmAttrNameT attributeNames[] = {attrName, nullptr}; > + const SaUint32T *value = nullptr; > + > + TRACE_ENTER(); > + > + dn.length = strlen((char *)dn.value); > + > + immutil_saImmOmAccessorInitialize(avd_cb->immOmHandle, &accessorHandle); > + rc = immutil_saImmOmAccessorGet_2(accessorHandle, &dn, attributeNames, > + (SaImmAttrValuesT_2 ***)&attributes); > + > + if (rc != SA_AIS_OK) { > + LOG_WA("saImmOmAccessorGet_2 FAILED %u for %s", rc, dn.value); > + goto done; > + } > + > + value = immutil_getUint32Attr(attributes, attrName, 0); > + if (value == nullptr) { > + LOG_WA("immutil_getUint32Attr FAILED for %s", dn.value); > + goto done; > + } > + > + avd_cb->scs_absence_max_duration = *value; > + > +done: > + immutil_saImmOmAccessorFinalize(accessorHandle); > + LOG_IN("scs_absence_max_duration: %d", > avd_cb->scs_absence_max_duration); > + > + TRACE_LEAVE(); > + return SA_AIS_OK; > +} > + > +/***************************************************************************** > * Function: avd_imm_init > * > * Purpose: This function Initialize the OI interface and get a selection > @@ -1501,6 +1555,10 @@ unsigned int avd_imm_config_get(void) > if (avd_sidep_config_get() != SA_AIS_OK) > goto done; > > + /* retrieve hydra configuration from IMM */ > + if (hydra_config_get() != SA_AIS_OK) > + goto done; > + > // SGs needs to adjust configuration once all instances have been added > { > for (std::map<std::string, AVD_SG*>::const_iterator it = > sg_db->begin(); > diff --git a/osaf/services/saf/amf/amfd/include/cb.h > b/osaf/services/saf/amf/amfd/include/cb.h > --- a/osaf/services/saf/amf/amfd/include/cb.h > +++ b/osaf/services/saf/amf/amfd/include/cb.h > @@ -182,6 +182,7 @@ typedef struct cl_cb_tag { > SaClmNodeIdT node_avd_failed; /* node id where AVD is down */ > > AVD_TMR amf_init_tmr; /* The timer for amf initialisation. */ > + AVD_TMR node_sync_tmr; /* The timer for reception of all node_up from > all PLs. */ > AVD_TMR heartbeat_tmr; /* The timer for sending heart beats to nd. */ > SaTimeT heartbeat_tmr_period; > > @@ -215,6 +216,8 @@ typedef struct cl_cb_tag { > * Used to skip usage of dependent services in the no-active state > */ > bool active_services_exist; > + bool all_nodes_synced; > + bool node_sync_window_closed; > > /* > A list of those SIs for which SI dep tolerance timer is running. > @@ -228,6 +231,8 @@ typedef struct cl_cb_tag { > */ > std::list<AVD_SI*> sis_in_Tolerance_Timer_state; > > + /* The duration that amfd should tolerate the absence of SCs */ > + uint32_t scs_absence_max_duration; > } AVD_CL_CB; > > extern AVD_CL_CB *avd_cb; > diff --git a/osaf/services/saf/amf/amfd/include/cluster.h > b/osaf/services/saf/amf/amfd/include/cluster.h > --- a/osaf/services/saf/amf/amfd/include/cluster.h > +++ b/osaf/services/saf/amf/amfd/include/cluster.h > @@ -38,6 +38,7 @@ extern AVD_CLUSTER *avd_cluster; > > extern SaAisErrorT avd_cluster_config_get(void); > extern void avd_cluster_tmr_init_evh(AVD_CL_CB *cb, struct avd_evt_tag > *evt); > +extern void avd_node_sync_tmr_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt); > extern void avd_cluster_constructor(void); > > #endif > diff --git a/osaf/services/saf/amf/amfd/include/csi.h > b/osaf/services/saf/amf/amfd/include/csi.h > --- a/osaf/services/saf/amf/amfd/include/csi.h > +++ b/osaf/services/saf/amf/amfd/include/csi.h > @@ -184,5 +184,7 @@ extern AVD_CSI *csi_create(const SaNameT > extern bool csi_assignment_validate(AVD_SG *sg); > extern SaAisErrorT csi_assign_hdlr(AVD_CSI *csi); > extern bool are_sponsor_csis_assigned_in_su(AVD_CSI *dep_csi, AVD_SU *su); > +SaAisErrorT avd_compcsi_cleanup(void); > +SaAisErrorT avd_compcsi_recreate(AVSV_N2D_ND_CSICOMP_STATE_MSG_INFO *info); > > #endif > diff --git a/osaf/services/saf/amf/amfd/include/db_template.h > b/osaf/services/saf/amf/amfd/include/db_template.h > --- a/osaf/services/saf/amf/amfd/include/db_template.h > +++ b/osaf/services/saf/amf/amfd/include/db_template.h > @@ -44,6 +44,7 @@ class AmfDb { > > const_iterator begin() const {return db.begin();} > const_iterator end() const {return db.end();} > + typename AmfDbMap::size_type size() const {return db.size();} > const_reverse_iterator rbegin() const {return db.rbegin();} > const_reverse_iterator rend() const {return db.rend();} > > diff --git a/osaf/services/saf/amf/amfd/include/evt.h > b/osaf/services/saf/amf/amfd/include/evt.h > --- a/osaf/services/saf/amf/amfd/include/evt.h > +++ b/osaf/services/saf/amf/amfd/include/evt.h > @@ -51,10 +51,13 @@ typedef enum avd_evt_type { > AVD_EVT_SHUTDOWN_APP_SU_MSG, > AVD_EVT_VERIFY_ACK_NACK_MSG, > AVD_EVT_COMP_VALIDATION_MSG, > + AVD_EVT_ND_SISU_STATE_INFO_MSG, > + AVD_EVT_ND_CSICOMP_STATE_INFO_MSG, > AVD_EVT_MSG_MAX, > AVD_EVT_TMR_SND_HB = AVD_EVT_MSG_MAX, > AVD_EVT_TMR_CL_INIT, > AVD_EVT_TMR_SI_DEP_TOL, > + AVD_EVT_TMR_NODE_SYNC, > AVD_EVT_TMR_MAX, > AVD_EVT_MDS_AVD_UP = AVD_EVT_TMR_MAX, > AVD_EVT_MDS_AVD_DOWN, > diff --git a/osaf/services/saf/amf/amfd/include/mds.h > b/osaf/services/saf/amf/amfd/include/mds.h > --- a/osaf/services/saf/amf/amfd/include/mds.h > +++ b/osaf/services/saf/amf/amfd/include/mds.h > @@ -33,13 +33,13 @@ > > /* In Service upgrade support */ > #define AVD_MDS_SUB_PART_VERSION_4 4 > -#define AVD_MDS_SUB_PART_VERSION 5 > +#define AVD_MDS_SUB_PART_VERSION 6 > > #define AVD_AVND_SUBPART_VER_MIN 1 > -#define AVD_AVND_SUBPART_VER_MAX 5 > +#define AVD_AVND_SUBPART_VER_MAX 6 > > #define AVD_AVD_SUBPART_VER_MIN 1 > -#define AVD_AVD_SUBPART_VER_MAX 5 > +#define AVD_AVD_SUBPART_VER_MAX 6 > > /* Message format versions */ > #define AVD_AVD_MSG_FMT_VER_1 1 > @@ -47,6 +47,7 @@ > #define AVD_AVD_MSG_FMT_VER_3 3 > #define AVD_AVD_MSG_FMT_VER_4 4 > #define AVD_AVD_MSG_FMT_VER_5 5 > +#define AVD_AVD_MSG_FMT_VER_6 6 > > uint32_t avd_mds_set_vdest_role(struct cl_cb_tag *cb, SaAmfHAStateT role); > uint32_t avd_mds_init(struct cl_cb_tag *cb); > diff --git a/osaf/services/saf/amf/amfd/include/msg.h > b/osaf/services/saf/amf/amfd/include/msg.h > --- a/osaf/services/saf/amf/amfd/include/msg.h > +++ b/osaf/services/saf/amf/amfd/include/msg.h > @@ -38,7 +38,7 @@ > #include "role.h" > > typedef enum { > - AVD_D2D_CHANGE_ROLE_REQ = AVSV_DND_MSG_MAX, > + AVD_D2D_CHANGE_ROLE_REQ = AVSV_D2D_CHANGE_ROLE_REQ, > AVD_D2D_CHANGE_ROLE_RSP, > AVD_D2D_MSG_MAX, > } AVD_D2D_MSG_TYPE; > diff --git a/osaf/services/saf/amf/amfd/include/node.h > b/osaf/services/saf/amf/amfd/include/node.h > --- a/osaf/services/saf/amf/amfd/include/node.h > +++ b/osaf/services/saf/amf/amfd/include/node.h > @@ -144,6 +144,8 @@ class AVD_AVND { > bool clm_change_start_preceded; /* to indicate there was CLM start cbk > before CLM completed cb. */ > bool recvr_fail_sw; /* to indicate there was node reboot because of node > failover/switchover.*/ > AVD_AMF_NG *admin_ng; /* points to the nodegroup on which admin operation > is going on.*/ > + uint16_t node_up_msg_count; /* to count of node_up msg that director had > received from this node */ > + bool reboot; > private: > void initialize(); > // disallow copy and assign > @@ -206,6 +208,7 @@ extern AVD_AVND *avd_node_getnext(const > extern uint32_t avd_node_add_nodeid(AVD_AVND *avnd); > extern void avd_node_delete_nodeid(AVD_AVND *node); > extern AVD_AVND *avd_node_find_nodeid(SaClmNodeIdT node_id); > +extern AVD_AVND *avd_node_get(const SaNameT *dn); > extern SaAisErrorT avd_node_config_get(void); > extern void avd_node_state_set(AVD_AVND *node, AVD_AVND_STATE node_state); > extern void avd_node_oper_state_set(AVD_AVND *node, SaAmfOperationalStateT > oper_state); > diff --git a/osaf/services/saf/amf/amfd/include/proc.h > b/osaf/services/saf/amf/amfd/include/proc.h > --- a/osaf/services/saf/amf/amfd/include/proc.h > +++ b/osaf/services/saf/amf/amfd/include/proc.h > @@ -43,6 +43,7 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb > void avd_su_si_assign_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt); > uint32_t avd_new_assgn_susi(AVD_CL_CB *cb, AVD_SU *su, AVD_SI *si, > SaAmfHAStateT role, bool ckpt, AVD_SU_SI_REL > **ret_ptr); > +void su_try_repair(const AVD_SU *su); > void avd_sg_app_node_su_inst_func(AVD_CL_CB *cb, AVD_AVND *avnd); > uint32_t avd_sg_app_su_inst_func(AVD_CL_CB *cb, AVD_SG *sg); > uint32_t avd_sg_su_oper_list_add(AVD_CL_CB *cb, AVD_SU *su, bool ckpt); > @@ -58,6 +59,10 @@ uint32_t avd_sg_nway_si_assign(AVD_CL_CB > /* The following are for N-way Active redundancy model */ > AVD_SU *avd_sg_nacvred_su_chose_asgn(AVD_CL_CB *cb, AVD_SG *sg); > > +uint32_t avd_count_node_up(AVD_CL_CB *cb); > +uint32_t avd_evt_queue_count(AVD_CL_CB *cb); > +uint32_t avd_count_sync_node_size(AVD_CL_CB *cb); > +void avd_process_state_info_queue(AVD_CL_CB *cb); > void avd_node_up_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt); > void avd_reg_su_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt); > void avd_oper_req_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt); > @@ -72,6 +77,8 @@ void avd_mds_qsd_role_evh(AVD_CL_CB *cb, > void avd_node_down_appl_susi_failover(AVD_CL_CB *cb, AVD_AVND *avnd); > void avd_node_down_mw_susi_failover(AVD_CL_CB *cb, AVD_AVND *avnd); > void avd_node_down_func(AVD_CL_CB *cb, AVD_AVND *avnd); > +void avd_nd_sisu_state_info_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt); > +void avd_nd_compcsi_state_info_evh(AVD_CL_CB *cb, struct avd_evt_tag *evt); > uint32_t avd_node_down(AVD_CL_CB *cb, SaClmNodeIdT node_id); > AVD_AVND *avd_msg_sanity_chk(AVD_EVT *evt, SaClmNodeIdT node_id, > AVSV_DND_MSG_TYPE msg_typ, uint32_t msg_id); > diff --git a/osaf/services/saf/amf/amfd/include/sg.h > b/osaf/services/saf/amf/amfd/include/sg.h > --- a/osaf/services/saf/amf/amfd/include/sg.h > +++ b/osaf/services/saf/amf/amfd/include/sg.h > @@ -593,5 +593,4 @@ extern uint32_t sg_instantiated_su_count > extern bool sg_stable_after_lock_in_or_unlock_in(AVD_SG *sg); > extern void process_su_si_response_for_ng(AVD_SU *su, SaAisErrorT res); > > - > #endif > diff --git a/osaf/services/saf/amf/amfd/include/si.h > b/osaf/services/saf/amf/amfd/include/si.h > --- a/osaf/services/saf/amf/amfd/include/si.h > +++ b/osaf/services/saf/amf/amfd/include/si.h > @@ -140,6 +140,7 @@ public: > void arrange_dep_csi(AVD_CSI* csi); > void add_csi_db(AVD_CSI* csi); > bool is_sirank_valid(uint32_t newSiRank) const; > + void update_alarm_state(bool alarm_state, bool sent_notification = > true); > void update_sirank(uint32_t newSiRank); > bool si_dep_states_check(); > const AVD_SIRANKEDSU *get_si_ranked_su(const std::string &su_name) > const; > diff --git a/osaf/services/saf/amf/amfd/include/susi.h > b/osaf/services/saf/amf/amfd/include/susi.h > --- a/osaf/services/saf/amf/amfd/include/susi.h > +++ b/osaf/services/saf/amf/amfd/include/susi.h > @@ -157,4 +157,7 @@ extern bool si_assignment_state_check(AV > extern SaAmfHAStateT avd_su_state_determine(AVD_SU *su); > extern AVD_SU_SI_REL *avd_siass_next_susi_to_quiesce(const AVD_SU_SI_REL > *susi); > extern bool avd_susi_quiesced_canbe_given(const AVD_SU_SI_REL *susi); > +SaAisErrorT avd_susi_cleanup(void); > +SaAisErrorT avd_susi_recreate(AVSV_N2D_ND_SISU_STATE_MSG_INFO*); > + > #endif > diff --git a/osaf/services/saf/amf/amfd/include/timer.h > b/osaf/services/saf/amf/amfd/include/timer.h > --- a/osaf/services/saf/amf/amfd/include/timer.h > +++ b/osaf/services/saf/amf/amfd/include/timer.h > @@ -44,6 +44,7 @@ typedef enum avd_tmr_type { > * SIs to application SU. */ > > AVD_TMR_SI_DEP_TOL, /* SI_SI dependency tolerance timer */ > + AVD_TMR_NODE_SYNC, /* node sync timer for all PLs from headless */ > AVD_TMR_MAX > } AVD_TMR_TYPE; > > diff --git a/osaf/services/saf/amf/amfd/main.cc > b/osaf/services/saf/amf/amfd/main.cc > --- a/osaf/services/saf/amf/amfd/main.cc > +++ b/osaf/services/saf/amf/amfd/main.cc > @@ -100,11 +100,14 @@ static const AVD_EVT_HDLR g_actv_list[AV > invalid_evh, /* AVD_EVT_SHUTDOWN_APP_SU_MSG */ > avd_ack_nack_evh, /* AVD_EVT_VERIFY_ACK_NACK_MSG */ > avd_comp_validation_evh, /* AVD_EVT_COMP_VALIDATION_MSG */ > + avd_nd_sisu_state_info_evh, /* AVD_EVT_ND_SISU_STATE_INFO_MSG */ > + avd_nd_compcsi_state_info_evh, /* AVD_EVT_ND_COMPCSI_STATE_INFO_MSG > */ > > /* active AvD timer events processing */ > avd_tmr_snd_hb_evh, /* AVD_EVT_TMR_SND_HB */ > avd_cluster_tmr_init_evh, /* AVD_EVT_TMR_CL_INIT */ > avd_sidep_tol_tmr_evh, /* AVD_EVT_TMR_SI_DEP_TOL */ > + avd_node_sync_tmr_evh, /* AVD_EVT_TMR_ALL_NODE_UP */ > > /* active AvD MDS events processing */ > avd_mds_avd_up_evh, /* AVD_EVT_MDS_AVD_UP */ > @@ -139,11 +142,15 @@ static const AVD_EVT_HDLR g_stndby_list[ > standby_invalid_evh, /* AVD_EVT_SHUTDOWN_APP_SU_MSG */ > standby_invalid_evh, /* AVD_EVT_VERIFY_ACK_NACK_MSG */ > standby_invalid_evh, /* AVD_EVT_COMP_VALIDATION_MSG */ > + standby_invalid_evh, /* AVD_EVT_ND_SUSI_STATE_INFO_MSG */ > + standby_invalid_evh, /* AVD_EVT_ND_COMPCSI_STATE_INFO_MSG */ > + > > /* standby AvD timer events processing */ > avd_tmr_snd_hb_evh, /* AVD_EVT_TMR_SND_HB */ > standby_invalid_evh, /* AVD_EVT_TMR_CL_INIT */ > avd_sidep_tol_tmr_evh, /* AVD_EVT_TMR_SI_DEP_TOL */ > + standby_invalid_evh, /* AVD_EVT_TMR_ALL_NODE_UP */ > > /* standby AvD MDS events processing */ > avd_mds_avd_up_evh, /* AVD_EVT_MDS_AVD_UP */ > @@ -177,11 +184,14 @@ static const AVD_EVT_HDLR g_quiesc_list[ > invalid_evh, /* AVD_EVT_SHUTDOWN_APP_SU_MSG */ > qsd_invalid_evh, /* AVD_EVT_VERIFY_ACK_NACK_MSG */ > avd_comp_validation_evh, /* AVD_EVT_COMP_VALIDATION_MSG */ > + qsd_invalid_evh, /* AVD_EVT_ND_SISU_STATE_INFO_MSG */ > + qsd_invalid_evh, /* AVD_EVT_ND_COMPCSI_STATE_INFO_MSG */ > > /* active AvD timer events processing */ > avd_tmr_snd_hb_evh, /* AVD_EVT_TMR_SND_HB */ > qsd_ignore_evh, /* AVD_EVT_TMR_CL_INIT */ > avd_sidep_tol_tmr_evh, /* AVD_EVT_TMR_SI_DEP_TOL */ > + qsd_ignore_evh, /* AVD_EVT_TMR_ALL_NODE_UP */ > > /* active AvD MDS events processing */ > avd_mds_avd_up_evh, /* AVD_EVT_MDS_AVD_UP */ > @@ -532,6 +542,9 @@ static uint32_t initialize(void) > cb->heartbeat_tmr.is_active = false; > cb->heartbeat_tmr.type = AVD_TMR_SND_HB; > cb->heartbeat_tmr_period = AVSV_DEF_HB_PERIOD; > + cb->all_nodes_synced = false; > + cb->node_sync_window_closed = false; > + cb->scs_absence_max_duration = 0; > > if ((val = getenv("AVSV_HB_PERIOD")) != nullptr) { > cb->heartbeat_tmr_period = strtoll(val, nullptr, 0); > @@ -598,6 +611,13 @@ static uint32_t initialize(void) > LOG_ER("avd_active_role_initialization FAILED"); > goto done; > } > + > + /* in a normal cluster start there will be no assignments > object found so > + * nothing happens. Used to cleanup cached RTAs after SCs > recover after > + * being headless. > + */ > + avd_susi_cleanup(); > + avd_compcsi_cleanup(); > } > else { > rc = avd_standby_role_initialization(cb); > @@ -780,6 +800,8 @@ static void main_loop(void) > **************************************************************************/ > static void process_event(AVD_CL_CB *cb_now, AVD_EVT *evt) > { > + TRACE_ENTER2("evt->rcv_evt %u", evt->rcv_evt); > + > /* check the HA state */ > if (cb_now->avail_state_avd == SA_AMF_HA_ACTIVE) { > /* if active call g_avd_actv_list functions */ > @@ -824,6 +846,8 @@ static void process_event(AVD_CL_CB *cb_ > cb_now->sync_required = true; > > delete evt; > + > + TRACE_LEAVE(); > } > > /** > diff --git a/osaf/services/saf/amf/amfd/mds.cc > b/osaf/services/saf/amf/amfd/mds.cc > --- a/osaf/services/saf/amf/amfd/mds.cc > +++ b/osaf/services/saf/amf/amfd/mds.cc > @@ -45,13 +45,13 @@ > const MDS_CLIENT_MSG_FORMAT_VER avd_avnd_msg_fmt_map_table[] = { > AVSV_AVD_AVND_MSG_FMT_VER_1, AVSV_AVD_AVND_MSG_FMT_VER_2, > AVSV_AVD_AVND_MSG_FMT_VER_3, AVSV_AVD_AVND_MSG_FMT_VER_4, > - AVSV_AVD_AVND_MSG_FMT_VER_5 > + AVSV_AVD_AVND_MSG_FMT_VER_5, AVSV_AVD_AVND_MSG_FMT_VER_6 > }; > > const MDS_CLIENT_MSG_FORMAT_VER avd_avd_msg_fmt_map_table[] = { > AVD_AVD_MSG_FMT_VER_1, AVD_AVD_MSG_FMT_VER_2, > AVD_AVD_MSG_FMT_VER_3, AVD_AVD_MSG_FMT_VER_4, > - AVD_AVD_MSG_FMT_VER_5}; > + AVD_AVD_MSG_FMT_VER_5, AVD_AVD_MSG_FMT_VER_6}; > > /* fwd decl */ > > diff --git a/osaf/services/saf/amf/amfd/ndfsm.cc > b/osaf/services/saf/amf/amfd/ndfsm.cc > --- a/osaf/services/saf/amf/amfd/ndfsm.cc > +++ b/osaf/services/saf/amf/amfd/ndfsm.cc > @@ -33,11 +33,221 @@ > AmfDb<uint32_t, AVD_FAIL_OVER_NODE> *node_list_db = 0; /* SaClmNodeIdT > index */ > > > /***************************************************************************** > - * Function: avd_node_up_func > + * Function: avd_process_state_info_queue > + * > + * Purpose: This function will pull out the queue event and looking for sync > + * info (sisu, compcsi) event to recover the SI/CSI assignment > + * > + * Input: cb - the AVD control block > + * > + * Returns: None. > + * > + * NOTES: > + * > + * > + **************************************************************************/ > +void avd_process_state_info_queue(AVD_CL_CB *cb) > +{ > + uint32_t i; > + const auto queue_size = cb->evt_queue.size(); > + AVD_EVT_QUEUE *queue_evt = nullptr; > + > + TRACE_ENTER(); > + > + TRACE("queue_size before processing: %lu", queue_size); > + > + // recover assignments from state info > + for(i=0 ; i<queue_size ; i++) { > + queue_evt = cb->evt_queue.front(); > + osafassert(queue_evt->evt); > + cb->evt_queue.pop(); > + > + TRACE("rcv_evt: %u", queue_evt->evt->rcv_evt); > + > + if (queue_evt->evt->rcv_evt == AVD_EVT_ND_SISU_STATE_INFO_MSG || > + queue_evt->evt->rcv_evt == > AVD_EVT_ND_CSICOMP_STATE_INFO_MSG) { > + > + AVD_DND_MSG* n2d_msg = queue_evt->evt->info.avnd_msg; > + > + TRACE("msg_type: %u", n2d_msg->msg_type); > + > + switch(n2d_msg->msg_type) { > + case AVSV_N2D_ND_SISU_STATE_INFO_MSG: > + > avd_susi_recreate(&n2d_msg->msg_info.n2d_nd_sisu_state_info); > + break; > + case AVSV_N2D_ND_CSICOMP_STATE_INFO_MSG: > + > avd_compcsi_recreate(&n2d_msg->msg_info.n2d_nd_csicomp_state_info); > + break; > + default: > + break; > + } > + > + avsv_dnd_msg_free(n2d_msg); > + > + delete queue_evt->evt; > + delete queue_evt; > + } else { > + cb->evt_queue.push(queue_evt); > + } > + } > + > + // Once active amfd looks up the state info from queue, that means node > sync > + // finishes. Therefore, if the queue is empty, this active amfd is > coming > + // from a cluster restart, the alarm state should be reset. > + // Otherwise, amfd is coming from SC recovery from headless, SI alarm > state > + // should be re-evalutated and raise the alarm in case it's still > unassigned. > + if (queue_size == 0) { > + for (std::map<std::string, AVD_SI*>::const_iterator it = > si_db->begin(); > + it != si_db->end(); it++) { > + AVD_SI *si = it->second; > + if (si->alarm_sent == true) { > + si->update_alarm_state(false, false); > + } > + } > + } > + else { > + for (std::map<std::string, AVD_SI*>::const_iterator it = > si_db->begin(); > + it != si_db->end(); it++) { > + AVD_SI *si = it->second; > + if (si->alarm_sent == false && > + si->saAmfSIAssignmentState == > SA_AMF_ASSIGNMENT_UNASSIGNED) { > + si->update_alarm_state(true); > + } > + } > + } > + TRACE("queue_size after processing: %lu", cb->evt_queue.size()); > + TRACE_LEAVE(); > +} > +/***************************************************************************** > + * Function: avd_count_sync_node_size > + * > + * Purpose: Helper function count the maximum number of node in cluster > + * to be synced from headless > + * > + * Input: cb - the AVD control block > + * > + * Returns: Number of nd > + * > + * NOTES: > + * > + **************************************************************************/ > +uint32_t avd_count_sync_node_size(AVD_CL_CB *cb) > +{ > + uint32_t twon_ncs_su_count = 0; > + uint32_t count = 0; > + TRACE_ENTER(); > + > + for (std::map<std::string, AVD_AVND *>::const_iterator it = > node_name_db->begin(); > + it != node_name_db->end(); it++) { > + AVD_AVND *avnd = it->second; > + osafassert(avnd); > + for (const auto& su :avnd->list_of_ncs_su) { > + if (su->sg_of_su->sg_redundancy_model == > SA_AMF_2N_REDUNDANCY_MODEL) { > + twon_ncs_su_count++; > + continue; > + } > + } > + } > + // cluster can have 1 SC or more SCs which hosting 2N Opensaf SU > + // so twon_ncs_su_count at least is 1 > + osafassert(twon_ncs_su_count > 0); > + > + if (twon_ncs_su_count == 1) { > + // 1 SC, the rest of nodes could be in sync from headless > + count = node_name_db->size() - 1; > + } else { > + // >=2 SCs, the rest of nodes could be in sync except > active/standby SC > + count = node_name_db->size() - 2; > + } > + > + TRACE("sync node size:%d", count); > + TRACE_LEAVE(); > + return count; > +} > +/***************************************************************************** > + * Function: avd_count_node_up > + * > + * Purpose: Helper function count number of nodes that sent node_up msg to > + * director > + * > + * Input: cb - the AVD control block > + * > + * Returns: Number of node > + * > + * NOTES: > + * > + * > + **************************************************************************/ > +uint32_t avd_count_node_up(AVD_CL_CB *cb) > +{ > + uint32_t received_count = 0; > + AVD_AVND *node = nullptr; > + > + TRACE_ENTER(); > + > + for (std::map<std::string, AVD_AVND *>::const_iterator it = > node_name_db->begin(); > + it != node_name_db->end(); it++) { > + node = it->second; > + if (node->node_up_msg_count > 0 > + && node->node_info.nodeId != cb->node_id_avd > + && node->node_info.nodeId != > cb->node_id_avd_other) > + ++received_count; > + } > + TRACE("Number of node director(s) that director received node_up > msg:%u", > + received_count); > + > + TRACE_LEAVE(); > + return received_count; > +} > + > +/***************************************************************************** > + * Function: record_node_up_msg_info > + * > + * Purpose: Update the rcv_msg_id and adest which are sent from amfnd > + * > + * Input: avnd - ptr to the appropriate amfnd > + * n2d_msg - node_up msg sent from amfnd > + * > + * Returns: None > + * > + * NOTES: > + * > + * > + **************************************************************************/ > +void record_node_up_msg_info(AVD_AVND *avnd, const AVD_DND_MSG *n2d_msg) > +{ > + osafassert(avnd != nullptr); > + > + avnd->adest = n2d_msg->msg_info.n2d_node_up.adest_address; > + > + if (n2d_msg->msg_info.n2d_node_up.msg_id >= avnd->rcv_msg_id) { > + LOG_NO("Received node_up from %x: msg_id %u", > + n2d_msg->msg_info.n2d_node_up.node_id, > + n2d_msg->msg_info.n2d_node_up.msg_id); > + > + avnd->rcv_msg_id = n2d_msg->msg_info.n2d_node_up.msg_id; > + } else { > + // This is expected after recovering from a headless state. > + // NODE_UPs will not be processed until all PLs are up. > + // In the mean time, we may get other messages from amfnd > + // that pushes up rcv_msg_id > + LOG_NO("NODE UP from %x: msg_id out of order. rcv_msg_id %u, > msg_id %u", > + n2d_msg->msg_info.n2d_node_up.node_id, > + avnd->rcv_msg_id, > + n2d_msg->msg_info.n2d_node_up.msg_id); > + } > +} > + > + > + > +/***************************************************************************** > + * Function: avd_node_up_evh > * > * Purpose: This function is the handler for node up event indicating > * the arrival of the node_up message. Based on the state machine either > - * It will ignore the message or send all the reg messages to the node. > + * It will ignore the message or send all the reg messages to the node > + * or order the node reboot if the node_up message arrives after the node > + * sync window has closed. > * > * Input: cb - the AVD control block > * evt - The event information. > @@ -54,8 +264,61 @@ void avd_node_up_evh(AVD_CL_CB *cb, AVD_ > AVD_AVND *avnd = nullptr; > AVD_DND_MSG *n2d_msg = evt->info.avnd_msg; > uint32_t rc = NCSCC_RC_SUCCESS; > + uint32_t sync_nd_size = avd_count_sync_node_size(cb); > + bool act_nd; > > - TRACE_ENTER2("from %x", n2d_msg->msg_info.n2d_node_up.node_id); > + TRACE_ENTER2("from %x, %s", n2d_msg->msg_info.n2d_node_up.node_id, > + n2d_msg->msg_info.n2d_node_up.node_name.value); > + > + act_nd = n2d_msg->msg_info.n2d_node_up.node_id == cb->node_id_avd; > + if (cb->scs_absence_max_duration > 0 && > + cb->all_nodes_synced == false && > + cb->node_sync_window_closed == false) { > + avnd = avd_node_get(&n2d_msg->msg_info.n2d_node_up.node_name); > + if (avnd == nullptr) { > + LOG_ER("Invalid node_name. Check node_id"); > + > + // perhaps this is a node_up from an old version of > amfnd without headless support > + // let's check if the node_id is valid > + if ((avnd = > avd_node_find_nodeid(n2d_msg->msg_info.n2d_node_up.node_id)) == nullptr) { > + LOG_ER("invalid node ID (%x)", > n2d_msg->msg_info.n2d_node_up.node_id); > + goto done; > + } > + } > + uint32_t rc_node_up; > + avnd->node_up_msg_count++; > + rc_node_up = avd_count_node_up(cb); > + if (rc_node_up == sync_nd_size) { > + if (cb->node_sync_tmr.is_active) { > + avd_stop_tmr(cb, &cb->node_sync_tmr); > + TRACE("stop NodeSync timer"); > + } > + cb->all_nodes_synced = true; > + LOG_NO("Received node_up_msg from all nodes"); > + } else { > + if (avnd->node_up_msg_count == 1 && > + (act_nd || > n2d_msg->msg_info.n2d_node_up.leds_set)) { > + > + // start (or restart) timer if this is the > first message > + // from amfnd-active-SC or amfnd-green-leds-PL > + cb->node_sync_tmr.type = AVD_TMR_NODE_SYNC; > + avd_start_tmr(cb, &(cb->node_sync_tmr), > AVSV_DEF_NODE_SYNC_PERIOD); > + > + TRACE("Received node_up_msg from node:%s. > Start/Restart " > + " NodeSync timer waiting for > remaining (%d) node(s)", > + > n2d_msg->msg_info.n2d_node_up.node_name.value, > + sync_nd_size - rc_node_up); > + goto done; > + } > + if (cb->node_sync_tmr.is_active == true) { > + if (n2d_msg->msg_info.n2d_node_up.leds_set == > false) { > + TRACE("NodeSync timer is active, ignore > this node_up msg (nodeid:%x)", > + > n2d_msg->msg_info.n2d_node_up.node_id); > + goto done; > + } > + } > + } > + } > > /* Cannot use avd_msg_sanity_chk here since this is a special case */ > if ((avnd = > avd_node_find_nodeid(n2d_msg->msg_info.n2d_node_up.node_id)) == nullptr) { > @@ -63,6 +326,9 @@ void avd_node_up_evh(AVD_CL_CB *cb, AVD_ > goto done; > } > > + /* Retrieve the information from the message */ > + record_node_up_msg_info(avnd, n2d_msg); > + > /* Check the AvD FSM state process node up only if AvD is in init done > or > * APP init state for all nodes except the primary system controller > * whose node up is accepted in config done state. > @@ -73,16 +339,11 @@ void avd_node_up_evh(AVD_CL_CB *cb, AVD_ > goto done; > } > > - if (avnd->node_state != AVD_AVND_STATE_ABSENT) { > - LOG_WA("invalid node state %u for node %x", > - avnd->node_state, > n2d_msg->msg_info.n2d_node_up.node_id); > - goto done; > + if ((n2d_msg->msg_info.n2d_node_up.node_id == cb->node_id_avd) && > (cb->init_state < AVD_INIT_DONE)) { > + // node up from local AVND > + avd_process_state_info_queue(cb); > } > > - /* Retrive the information from the message */ > - avnd->adest = n2d_msg->msg_info.n2d_node_up.adest_address; > - avnd->rcv_msg_id = n2d_msg->msg_info.n2d_node_up.msg_id; > - > if (avnd->node_info.member != SA_TRUE) { > LOG_WA("Not a Cluster Member dropping the msg"); > goto done; > @@ -108,7 +369,9 @@ void avd_node_up_evh(AVD_CL_CB *cb, AVD_ > } > > /* send the Ack message to the node. */ > - if (avd_snd_node_ack_msg(cb, avnd, avnd->rcv_msg_id) != > NCSCC_RC_SUCCESS) { > + // note: it's important to ack the msg_id received in n2d_msg, rather > than avnd->rcv_msg_id. > + // They will not always be same when headless option is enabled. > + if (avd_snd_node_ack_msg(cb, avnd, > n2d_msg->msg_info.n2d_node_up.msg_id) != NCSCC_RC_SUCCESS) { > /* log error that the director is not able to send the message > */ > LOG_ER("%s:%u: %u", __FILE__, __LINE__, avnd->node_info.nodeId); > > @@ -119,6 +382,39 @@ void avd_node_up_evh(AVD_CL_CB *cb, AVD_ > goto done; > } > > + if (n2d_msg->msg_info.n2d_node_up.leds_set == true) { > + TRACE("node %x is already up", avnd->node_info.nodeId); > + > + if (cb->node_sync_window_closed == true && > avnd->node_up_msg_count == 0) { > + LOG_WA("Received new node_up_msg from node:%s after > node sync window, " > + "sending node reboot order to target node", > + n2d_msg->msg_info.n2d_node_up.node_name.value); > + avd_d2n_reboot_snd(avnd); > + goto done; > + } else if (avnd->reboot) { > + // delayed node failfast > + avd_d2n_reboot_snd(avnd); > + avnd->reboot = false; > + goto done; > + } > + else { > + // this node is already up > + avd_node_state_set(avnd, AVD_AVND_STATE_PRESENT); > + avd_node_oper_state_set(avnd, > SA_AMF_OPERATIONAL_ENABLED); > + > + // Update readiness state of all SUs which are waiting > for node > + // oper state > + for (const auto& su :avnd->list_of_ncs_su) { > + > su->set_readiness_state(SA_AMF_READINESS_IN_SERVICE); > + } > + for (const auto& su :avnd->list_of_su) { > + if (su->is_in_service()) > + > su->set_readiness_state(SA_AMF_READINESS_IN_SERVICE); > + } > + goto node_joined; > + } > + } > + > /* Send role change to this controller AvND */ > if (avnd->node_info.nodeId == cb->node_id_avd) { > /* Here obviously the role will be ACT. */ > @@ -153,10 +449,11 @@ void avd_node_up_evh(AVD_CL_CB *cb, AVD_ > goto done; > } > > + avd_node_state_set(avnd, AVD_AVND_STATE_NO_CONFIG); > + > +node_joined: > LOG_NO("Node '%s' joined the cluster", avnd->node_name); > > - avd_node_state_set(avnd, AVD_AVND_STATE_NO_CONFIG); > - > /* checkpoint the node. */ > m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(cb, avnd, AVSV_CKPT_AVD_NODE_CONFIG); > > diff --git a/osaf/services/saf/amf/amfd/ndmsg.cc > b/osaf/services/saf/amf/amfd/ndmsg.cc > --- a/osaf/services/saf/amf/amfd/ndmsg.cc > +++ b/osaf/services/saf/amf/amfd/ndmsg.cc > @@ -357,7 +357,23 @@ uint32_t avd_n2d_msg_rcv(AVD_DND_MSG *rc > cb->peer_msg_fmt_ver = msg_fmt_ver; > } > > - evt->rcv_evt = static_cast<AVD_EVT_TYPE>((rcv_msg->msg_type - > AVSV_N2D_NODE_UP_MSG) + AVD_EVT_NODE_UP_MSG); > + switch (rcv_msg->msg_type) { > + case AVSV_N2D_ND_SISU_STATE_INFO_MSG: > + // 'offset lookup' can't be used for this > + evt->rcv_evt = AVD_EVT_ND_SISU_STATE_INFO_MSG; > + break; > + case AVSV_N2D_ND_CSICOMP_STATE_INFO_MSG: > + // 'offset lookup' can't be used for this > + evt->rcv_evt = AVD_EVT_ND_CSICOMP_STATE_INFO_MSG; > + break; > + default: > + evt->rcv_evt = > static_cast<AVD_EVT_TYPE>((rcv_msg->msg_type - AVSV_N2D_NODE_UP_MSG) + > AVD_EVT_NODE_UP_MSG); > + break; > + } > + > + osafassert((AVD_EVT_INVALID < evt->rcv_evt) > + && (evt->rcv_evt < AVD_EVT_MAX)); > + > evt->info.avnd_msg = rcv_msg; > > if (m_NCS_IPC_SEND(&cb->avd_mbx, evt, NCS_IPC_PRIORITY_HIGH) != > NCSCC_RC_SUCCESS) { > diff --git a/osaf/services/saf/amf/amfd/ndproc.cc > b/osaf/services/saf/amf/amfd/ndproc.cc > --- a/osaf/services/saf/amf/amfd/ndproc.cc > +++ b/osaf/services/saf/amf/amfd/ndproc.cc > @@ -68,8 +68,9 @@ AVD_AVND *avd_msg_sanity_chk(AVD_EVT* ev > } > > if ((node->rcv_msg_id + 1) != msg_id) { > - LOG_WA("%s: invalid msg id %u, from %x should be %u", > - __FUNCTION__, msg_id, node_id, node->rcv_msg_id + 1); > + LOG_WA("%s: invalid msg id %u, msg type %u, from %x should be > %u", > + __FUNCTION__, msg_id, evt->info.avnd_msg->msg_type, > + node_id, node->rcv_msg_id + 1); > return nullptr; > } > > @@ -278,6 +279,94 @@ void avd_oper_req_evh(AVD_CL_CB *cb, AVD > TRACE_LEAVE(); > } > > +/***************************************************************************** > + * Function: avd_nd_sisu_state_info_evh > + * > + * Purpose: This function is the handler for the sync sisu_state_info event. > + * No process on the event, push in queue or ignore it if the node sync > window > + * has closed. > + * > + * Input: cb - the AVD control block > + * evt - The event information. > + * > + * Returns: None. > + * > + * NOTES: > + * > + * > + **************************************************************************/ > + > +void avd_nd_sisu_state_info_evh(AVD_CL_CB *cb, AVD_EVT *evt) > +{ > + AVD_DND_MSG *n2d_msg = evt->info.avnd_msg; > + AVD_EVT_QUEUE* state_info_evt; > + > + TRACE_ENTER(); > + LOG_NO("Receive message with event type:%u, msg_type:%u, from node:%x, > msg_id:%u", > + evt->rcv_evt, > + evt->info.avnd_msg->msg_type, > + > evt->info.avnd_msg->msg_info.n2d_nd_sisu_state_info.node_id, > + > evt->info.avnd_msg->msg_info.n2d_nd_sisu_state_info.msg_id); > + > + if (cb->node_sync_window_closed == false) { > + state_info_evt = new AVD_EVT_QUEUE(); > + state_info_evt->evt = new AVD_EVT(); > + memcpy(state_info_evt->evt, evt, sizeof(AVD_EVT)); > + state_info_evt->evt->info.avnd_msg = n2d_msg; > + cb->evt_queue.push(state_info_evt); > + } > + else { > + LOG_WA("Ignore this sisu_state_info message since node sync > window has closed"); > + avsv_dnd_msg_free(n2d_msg); > + } > + > + TRACE_LEAVE(); > +} > + > +/***************************************************************************** > + * Function: avd_nd_compcsi_state_info_evh > + * > + * Purpose: This function is the handler for the sync compcsi_state_info > event. > + * No process on the event, push in queue or ignore it if the node sync > window > + * has closed. > + * > + * Input: cb - the AVD control block > + * evt - The event information. > + * > + * Returns: None. > + * > + * NOTES: > + * > + * > + **************************************************************************/ > + > +void avd_nd_compcsi_state_info_evh(AVD_CL_CB *cb, AVD_EVT *evt) > +{ > + AVD_DND_MSG *n2d_msg = evt->info.avnd_msg; > + AVD_EVT_QUEUE* state_info_evt; > + > + TRACE_ENTER(); > + LOG_NO("Receive message with event type:%u, msg_type:%u, from node:%x, > msg_id:%u", > + evt->rcv_evt, > + evt->info.avnd_msg->msg_type, > + > evt->info.avnd_msg->msg_info.n2d_nd_csicomp_state_info.node_id, > + > evt->info.avnd_msg->msg_info.n2d_nd_csicomp_state_info.msg_id); > + > + if (cb->node_sync_window_closed == false) { > + state_info_evt = new AVD_EVT_QUEUE(); > + state_info_evt->evt = new AVD_EVT(); > + memcpy(state_info_evt->evt, evt, sizeof(AVD_EVT)); > + state_info_evt->evt->info.avnd_msg = n2d_msg; > + cb->evt_queue.push(state_info_evt); > + } > + else { > + LOG_WA("Ignore this compcsi_state_info message since node sync > window has closed"); > + avsv_dnd_msg_free(n2d_msg); > + } > + > + TRACE_LEAVE(); > +} > + > /** > * handler to report error response to imm for any pending admin operation > on comp > * > @@ -721,7 +810,10 @@ void avd_data_update_req_evh(AVD_CL_CB * > } > > if ((node->node_state == AVD_AVND_STATE_ABSENT) || (node->node_state == > AVD_AVND_STATE_GO_DOWN)) { > - LOG_ER("%s: invalid node state %u", __FUNCTION__, > node->node_state); > + LOG_ER("%s: node %x, receive msg_id(%u) in invalid node state > %u", > + __FUNCTION__, node->node_info.nodeId, > + n2d_msg->msg_info.n2d_data_req.msg_id, > node->node_state); > + > goto done; > } > > @@ -883,6 +975,11 @@ void avd_data_update_req_evh(AVD_CL_CB * > l_val = ntohl(*((uint32_t > *)&n2d_msg->msg_info.n2d_data_req.param_info.value[0])); > su->set_oper_state(l_val); > } > + > + if (su->is_in_service() == true) { > + > su->set_readiness_state(SA_AMF_READINESS_IN_SERVICE); > + } > + > break; > case saAmfSUPresenceState_ID: > TRACE("su pres state"); > diff --git a/osaf/services/saf/amf/amfd/node.cc > b/osaf/services/saf/amf/amfd/node.cc > --- a/osaf/services/saf/amf/amfd/node.cc > +++ b/osaf/services/saf/amf/amfd/node.cc > @@ -57,6 +57,7 @@ uint32_t avd_node_add_nodeid(AVD_AVND *n > > if ((node_id_db->find(node->node_info.nodeId) == nullptr) && > (node->node_info.nodeId != 0)) { > + TRACE("added node %d", node->node_info.nodeId); > rc = node_id_db->insert(node->node_info.nodeId, node); > osafassert(rc == NCSCC_RC_SUCCESS); > } > @@ -161,11 +162,11 @@ AVD_AVND::~AVD_AVND() { > // > AVD_AVND *avd_node_new(const SaNameT *dn) > { > - AVD_AVND *node; > - > - node = new AVD_AVND(dn); > - > - return node; > + AVD_AVND *node; > + node = new AVD_AVND(dn); > + node->node_up_msg_count = 0; > + node->reboot = false; > + return node; > } > > void avd_node_delete(AVD_AVND *node) > @@ -409,8 +410,10 @@ void avd_node_state_set(AVD_AVND *node, > osafassert(node_state <= AVD_AVND_STATE_NCS_INIT); > TRACE_ENTER2("'%s' %s => %s", node->name.value, > node_state_name[node->node_state], > node_state_name[node_state]); > - node->node_state = node_state; > - m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, node, > AVSV_CKPT_AVND_NODE_STATE); > + if (node->node_state != node_state) { > + node->node_state = node_state; > + m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, node, > AVSV_CKPT_AVND_NODE_STATE); > + } > TRACE_LEAVE(); > } > > diff --git a/osaf/services/saf/amf/amfd/sgproc.cc > b/osaf/services/saf/amf/amfd/sgproc.cc > --- a/osaf/services/saf/amf/amfd/sgproc.cc > +++ b/osaf/services/saf/amf/amfd/sgproc.cc > @@ -278,7 +278,7 @@ done: > * @param[in] su > * > **/ > -static void su_try_repair(const AVD_SU *su) > +void su_try_repair(const AVD_SU *su) > { > TRACE_ENTER2("Repair for SU:'%s'", su->name.value); > > @@ -288,11 +288,11 @@ static void su_try_repair(const AVD_SU * > (su->saAmfSUPresenceState != > SA_AMF_PRESENCE_TERMINATION_FAILED)) { > > saflog(LOG_NOTICE, amfSvcUsrName, "Ordering Auto repair of '%s' > as sufailover repair action", > - su->sg_of_su->name.value); > + su->name.value); > avd_admin_op_msg_snd(&su->name, AVSV_SA_AMF_SU, > > static_cast<SaAmfAdminOperationIdT>(SA_AMF_ADMIN_REPAIRED), su->su_on_node); > } else { > - saflog(LOG_NOTICE, amfSvcUsrName, "Autorepair not done for > '%s'", su->sg_of_su->name.value); > + saflog(LOG_NOTICE, amfSvcUsrName, "Autorepair not done for > '%s'", su->name.value); > } > > TRACE_LEAVE(); > @@ -480,8 +480,11 @@ static uint32_t sg_su_failover_func(AVD_ > } > } > > + TRACE("init_state %u", avd_cb->init_state); > + > /*If the AvD is in AVD_APP_STATE then reassign all the SUSI assignments > for this SU */ > - if (avd_cb->init_state == AVD_APP_STATE) { > + if (avd_cb->init_state == AVD_APP_STATE || > + avd_cb->scs_absence_max_duration > 0) { > /* Unlike active, quiesced and standby HA states, assignment > counters > in quiescing HA state are updated when AMFD receives > assignment > response from AMFND. During sufailover amfd will not receive > @@ -489,6 +492,9 @@ static uint32_t sg_su_failover_func(AVD_ > So if any SU is under going modify operation then update > assignment > counters for those SUSIs which are in quiescing state in the > SU. > */ > + TRACE("Reassign SUSI assignments for %s, init_state %u", > + su->name.value, avd_cb->init_state); > + > for (AVD_SU_SI_REL *susi = su->list_of_susi; susi; susi = > susi->su_next) { > if ((susi->fsm == AVD_SU_SI_STATE_MODIFY) && > (susi->state == SA_AMF_HA_QUIESCING)) { > @@ -738,7 +744,9 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb > * disabled. > */ > > - if (cb->init_state == AVD_INIT_DONE) { > + TRACE("init_state %u", cb->init_state); > + > + if (cb->init_state == AVD_INIT_DONE && > cb->scs_absence_max_duration == 0) { > su->set_oper_state(SA_AMF_OPERATIONAL_DISABLED); > > su->set_readiness_state(SA_AMF_READINESS_OUT_OF_SERVICE); > if (n2d_msg->msg_info.n2d_opr_state.node_oper_state == > SA_AMF_OPERATIONAL_DISABLED) { > @@ -752,7 +760,11 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb > } > } /* if > (n2d_msg->msg_info.n2d_opr_state.node_oper_state == > SA_AMF_OPERATIONAL_DISABLED) */ > } /* if(cb->init_state == AVD_INIT_DONE) */ > - else if (cb->init_state == AVD_APP_STATE) { > + else if (cb->init_state == AVD_APP_STATE || > + (cb->init_state == AVD_INIT_DONE && > cb->scs_absence_max_duration > 0)) { > + > + TRACE("Setting SU to disabled in init_state %u", > cb->init_state); > + > su->set_oper_state(SA_AMF_OPERATIONAL_DISABLED); > > su->set_readiness_state(SA_AMF_READINESS_OUT_OF_SERVICE); > if (n2d_msg->msg_info.n2d_opr_state.node_oper_state == > SA_AMF_OPERATIONAL_DISABLED) { > @@ -873,6 +885,20 @@ void avd_su_oper_state_evh(AVD_CL_CB *cb > } > } > } else { /* if(su->sg_of_su->sg_ncs_spec == true) */ > + if (avd_cb->scs_absence_max_duration > 0 && > + su->saAmfSUPresenceState == > SA_AMF_PRESENCE_UNINSTANTIATED && > + su->saAmfSUPreInstantiable == false) { > + // this is to allow non NPI SUs to be repaired > if > + // headless mode is enabled. Otherwise, the code > + // following will assume the SU is already in > service > + // when it failed to instantiate while headless > + > + if (cb->init_state == AVD_APP_STATE) { > + LOG_NO("Setting NPI SU '%s' to OOS > after headless state", su->name.value); > + > su->set_readiness_state(SA_AMF_READINESS_OUT_OF_SERVICE); > + } > + } > + > /* If oper state of Uninstantiated SU got ENABLED so > try to instantiate it > after evaluating SG. */ > if (su->saAmfSUPresenceState == > SA_AMF_PRESENCE_UNINSTANTIATED) { > @@ -1726,6 +1752,14 @@ uint32_t avd_sg_app_su_inst_func(AVD_CL_ > TRACE_ENTER2("'%s'", sg->name.value); > > for (const auto& i_su : sg->list_of_su) { > + TRACE("Checking '%s'", i_su->name.value); > + > + TRACE("saAmfSuReadinessState: %u", i_su->saAmfSuReadinessState); > + TRACE("saAmfSUPreInstantiable: %u", > i_su->saAmfSUPreInstantiable); > + TRACE("saAmfSUPresenceState: %u", i_su->saAmfSUPresenceState); > + TRACE("saAmfSUOperState: %u", i_su->saAmfSUOperState); > + TRACE("term_state: %u", i_su->term_state); > + > su_node_ptr = i_su->get_node_ptr(); > num_su++; > /* Check if the SU is inservice */ > @@ -1746,6 +1780,7 @@ uint32_t avd_sg_app_su_inst_func(AVD_CL_ > (any_ng_in_locked_in_state(su_node_ptr) == false)) { > > if (i_su->is_in_service() == true) { > + TRACE("Calling su_insvc() for '%s'", > i_su->name.value); > > i_su->set_readiness_state(SA_AMF_READINESS_IN_SERVICE); > i_su->sg_of_su->su_insvc(cb, i_su); > > diff --git a/osaf/services/saf/amf/amfd/si.cc > b/osaf/services/saf/amf/amfd/si.cc > --- a/osaf/services/saf/amf/amfd/si.cc > +++ b/osaf/services/saf/amf/amfd/si.cc > @@ -614,6 +614,10 @@ static AVD_SI *si_create(SaNameT *si_nam > si->saAmfSIAdminState = SA_AMF_ADMIN_UNLOCKED; > } > > + if > (immutil_getAttr(const_cast<SaImmAttrNameT>("saAmfUnassignedAlarmStatus"), > attributes, 0, &si->alarm_sent) != SA_AIS_OK) { > + /* Empty, assign default value */ > + si->alarm_sent = false; > + } > rc = 0; > > done: > @@ -653,6 +657,7 @@ SaAisErrorT avd_si_config_get(AVD_APP *a > const_cast<SaImmAttrNameT>("saAmfSIPrefActiveAssignments"), > const_cast<SaImmAttrNameT>("saAmfSIPrefStandbyAssignments"), > const_cast<SaImmAttrNameT>("saAmfSIAdminState"), > + const_cast<SaImmAttrNameT>("saAmfUnassignedAlarmStatus"), > nullptr > }; > > @@ -1273,8 +1278,6 @@ void AVD_SI::update_ass_state() > if (saAmfSINumCurrActiveAssignments == 0) { > newState = SA_AMF_ASSIGNMENT_UNASSIGNED; > } else { > - osafassert(saAmfSINumCurrActiveAssignments == 1); > - osafassert(saAmfSINumCurrStandbyAssignments == 0); > newState = SA_AMF_ASSIGNMENT_FULLY_ASSIGNED; > } > break; > @@ -1294,21 +1297,14 @@ void AVD_SI::update_ass_state() > > /* alarm & notifications */ > if (saAmfSIAssignmentState == SA_AMF_ASSIGNMENT_UNASSIGNED) { > - avd_send_si_unassigned_alarm(&name); > - alarm_sent = true; > - m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, this, > AVSV_CKPT_SI_ALARM_SENT); > + update_alarm_state(true); > } > else { > avd_send_si_assigned_ntf(&name, oldState, > saAmfSIAssignmentState); > - > /* Clear of alarm */ > if ((oldState == SA_AMF_ASSIGNMENT_UNASSIGNED) && > alarm_sent) { > - avd_alarm_clear(&name, > SA_AMF_NTFID_SI_UNASSIGNED, SA_NTF_SOFTWARE_ERROR); > - m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, this, > AVSV_CKPT_SI_ALARM_SENT); > + update_alarm_state(false); > } > - > - /* always reset in case the SI has been recycled */ > - alarm_sent = false; > } > > avd_saImmOiRtObjectUpdate(&name, "saAmfSIAssignmentState", > @@ -1499,4 +1495,29 @@ const AVD_SIRANKEDSU *AVD_SI::get_si_ran > } > > return sirankedsu; > +} > + > +/* > + * @brief Update alarm_sent by new value of @alarm_state, > + * then update saAmfUnassignedAlarmStatus IMM attribute > + * and raise/clear SI unassigned alarm (if specified) accordingly > + * @param [in] @alarm_state: Indication of alarm raising/clearing > + * @param [in] @sent_notification: Indication of sending alarm > + * raising/clearing notification > + */ > +void AVD_SI::update_alarm_state(bool alarm_state, bool sent_notification) > +{ > + alarm_sent = alarm_state; > + avd_saImmOiRtObjectUpdate(&name, "saAmfUnassignedAlarmStatus", > + SA_IMM_ATTR_SAUINT32T, &alarm_sent); > + m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, this, AVSV_CKPT_SI_ALARM_SENT); > + > + if (sent_notification == true) { > + if (alarm_sent == true) { > + avd_send_si_unassigned_alarm(&name); > + } > + else { > + avd_alarm_clear(&name, SA_AMF_NTFID_SI_UNASSIGNED, > SA_NTF_SOFTWARE_ERROR); > + } > + } > } > \ No newline at end of file > diff --git a/osaf/services/saf/amf/amfd/siass.cc > b/osaf/services/saf/amf/amfd/siass.cc > --- a/osaf/services/saf/amf/amfd/siass.cc > +++ b/osaf/services/saf/amf/amfd/siass.cc > @@ -775,3 +775,124 @@ done: > TRACE_LEAVE2("quiesc_role:%u",quiesc_role); > return quiesc_role; > } > + > +/** > + * Clean up SUSI objects by searching for SaAmfSIAssignment instances in IMM > + * @return SA_AIS_OK when OK > + */ > +SaAisErrorT avd_susi_cleanup(void) > +{ > + SaAisErrorT rc; > + SaImmSearchHandleT searchHandle; > + SaImmSearchParametersT_2 searchParam; > + const char *className = "SaAmfSIAssignment"; > + > + TRACE_ENTER(); > + > + searchParam.searchOneAttr.attrName = > const_cast<SaImmAttrNameT>("SaImmAttrClassName"); > + searchParam.searchOneAttr.attrValueType = SA_IMM_ATTR_SASTRINGT; > + searchParam.searchOneAttr.attrValue = &className; > + > + if ((rc = immutil_saImmOmSearchInitialize_2(avd_cb->immOmHandle, > nullptr, SA_IMM_SUBTREE, > + SA_IMM_SEARCH_ONE_ATTR | SA_IMM_SEARCH_GET_NO_ATTR, &searchParam, > + nullptr, &searchHandle)) != SA_AIS_OK) { > + LOG_ER("%s: saImmOmSearchInitialize_2 failed: %u", > __FUNCTION__, rc); > + goto done; > + } > + > + SaNameT siass_name; > + const SaImmAttrValuesT_2 **attributes; > + while ((rc = immutil_saImmOmSearchNext_2(searchHandle, &siass_name, > + (SaImmAttrValuesT_2 ***)&attributes)) > == SA_AIS_OK) { > + avd_saImmOiRtObjectDelete(&siass_name); > + } > + > + (void)immutil_saImmOmSearchFinalize(searchHandle); > + > +done: > + TRACE_LEAVE(); > + return SA_AIS_OK; > +} > + > +/** > + * Recreates SUSI objects by with information retrieved from node directors. > + * Update relevant runtime attributes > + * @return SA_AIS_OK when OK > + */ > +SaAisErrorT avd_susi_recreate(AVSV_N2D_ND_SISU_STATE_MSG_INFO* info) > +{ > + TRACE_ENTER2("msg_id: %u node_id: %u num_sisu: %u", info->msg_id, > + info->node_id, info->num_sisu); > + AVD_SU_SI_REL *susi = nullptr; > + AVD_AVND *node = nullptr; > + > + const AVSV_SISU_STATE_MSG *susi_state = nullptr; > + const AVSV_SU_STATE_MSG *su_state = nullptr; > + > + node = avd_node_find_nodeid(info->node_id); > + if (node == 0) { > + LOG_ER("Node %" PRIx32 " has left the cluster", info->node_id); > + return SA_AIS_ERR_NOT_EXIST; > + } > + > + for (su_state = info->su_list; su_state != nullptr; > + su_state = su_state->next) { > + > + AVD_SU *su = su_db->find(Amf::to_string(&su_state->safSU)); > + osafassert(su); > + > + // present state > + > su->set_pres_state(static_cast<SaAmfPresenceStateT>(su_state->su_pres_state)); > + > + // oper state > + su->set_oper_state(su_state->su_oper_state); > + > + // . readiness state is updated when node_up of PL is accepted > + // . saAmfSUHostedByNode does not need to update since mapping > + // su to node should reserve the same order > + // . saAmfSUPreInstantiable wouldn't change during headless > + // so they need not to update > + // . saAmfSUNumCurrActiveSIs & saAmfSUNumCurrStandbySIs to be > updated > + // during avd_susi_create() > + > + // restart count > + su->saAmfSURestartCount = su_state->su_restart_cnt; > + avd_saImmOiRtObjectUpdate(&su->name, > + > const_cast<SaImmAttrNameT>("saAmfSURestartCount"), SA_IMM_ATTR_SAUINT32T, > + &su->saAmfSURestartCount); > + m_AVSV_SEND_CKPT_UPDT_ASYNC_UPDT(avd_cb, su, > AVSV_CKPT_SU_RESTART_COUNT); > + } > + > + for (susi_state = info->sisu_list; susi_state != nullptr; > + susi_state = susi_state->next) { > + > + assert(susi_state->safSI.length > 0); > + AVD_SI *si = si_db->find(Amf::to_string(&susi_state->safSI)); > + osafassert(si); > + > + AVD_SU *su = su_db->find(Amf::to_string(&susi_state->safSU)); > + osafassert(su); > + > + SaAmfHAStateT ha_state = susi_state->saAmfSISUHAState; > + > + susi = avd_su_susi_find(avd_cb, su, &susi_state->safSI); > + if (susi == nullptr) { > + susi = avd_susi_create(avd_cb, si, su, ha_state, false); > + osafassert(susi); > + } else { > + avd_susi_ha_state_set(susi, ha_state); > + } > + susi->fsm = AVD_SU_SI_STATE_ASGND; > + > + if (susi->state == SA_AMF_HA_QUIESCING) { > + susi->su->inc_curr_act_si(); > + susi->si->inc_curr_act_ass(); > + } > + > + m_AVSV_SEND_CKPT_UPDT_ASYNC_ADD(avd_cb, susi, > AVSV_CKPT_AVD_SI_ASS); > + } > + > + > + TRACE_LEAVE(); > + return SA_AIS_OK; > +} > diff --git a/osaf/services/saf/amf/amfd/su.cc > b/osaf/services/saf/amf/amfd/su.cc > --- a/osaf/services/saf/amf/amfd/su.cc > +++ b/osaf/services/saf/amf/amfd/su.cc > @@ -1368,21 +1368,14 @@ static SaAisErrorT su_ccb_completed_modi > SaAisErrorT rc = SA_AIS_OK; > const SaImmAttrModificationT_2 *attr_mod; > int i = 0; > - bool value_is_deleted = false; > > while ((attr_mod = opdata->param.modify.attrMods[i++]) != nullptr) { > > - if ((attr_mod->modType == SA_IMM_ATTR_VALUES_DELETE) || > - (attr_mod->modAttr.attrValues == nullptr)) { > - /* Attribute value is deleted, revert to default value > if applicable*/ > - value_is_deleted = true; > - } else { > - /* Attribute value is modified */ > - value_is_deleted = false; > - } > + /* Attribute value removed */ > + if ((attr_mod->modType == SA_IMM_ATTR_VALUES_DELETE) || > (attr_mod->modAttr.attrValues == nullptr)) > + continue; > + > if (!strcmp(attr_mod->modAttr.attrName, "saAmfSUFailover")) { > - if (value_is_deleted == true) > - continue; > AVD_SU *su = > su_db->find(Amf::to_string(&opdata->objectName)); > uint32_t su_failover = *((SaUint32T > *)attr_mod->modAttr.attrValues[0]); > > @@ -1403,8 +1396,6 @@ static SaAisErrorT su_ccb_completed_modi > goto done; > } > } else if (!strcmp(attr_mod->modAttr.attrName, > "saAmfSUMaintenanceCampaign")) { > - if (value_is_deleted == true) > - continue; > AVD_SU *su = > su_db->find(Amf::to_string(&opdata->objectName)); > > if (su->saAmfSUMaintenanceCampaign.length > 0) { > @@ -1414,8 +1405,6 @@ static SaAisErrorT su_ccb_completed_modi > goto done; > } > } else if (!strcmp(attr_mod->modAttr.attrName, "saAmfSUType")) { > - if (value_is_deleted == true) > - continue; > AVD_SU *su; > SaNameT sutype_name = *(SaNameT*) > attr_mod->modAttr.attrValues[0]; > su = su_db->find(Amf::to_string(&opdata->objectName)); > ------------------------------------------------------------------------------ Site24x7 APM Insight: Get Deep Visibility into Application Performance APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month Monitor end-to-end web transactions and take corrective actions now Troubleshoot faster and improve end-user experience. Signup Now! http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140 _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel