ack, code review only. Minor comments below/Thanks HansN
On 01/05/2016 02:33 PM, Minh Hon Chau wrote:
> osaf/services/saf/amf/amfd/cluster.cc | 69 ++++-
> osaf/services/saf/amf/amfd/comp.cc | 8 +-
> osaf/services/saf/amf/amfd/csi.cc | 107 +++++++
> 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 | 16 +-
> 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/include/util.h | 2 +-
> 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 | 9 +-
> osaf/services/saf/amf/amfd/sg.cc | 57 ++++
> osaf/services/saf/amf/amfd/sg_2n_fsm.cc | 140 +++++++++
> osaf/services/saf/amf/amfd/sg_nored_fsm.cc | 6 +
> osaf/services/saf/amf/amfd/sg_npm_fsm.cc | 24 +
> osaf/services/saf/amf/amfd/sg_nway_fsm.cc | 24 +
> osaf/services/saf/amf/amfd/sg_nwayact_fsm.cc | 6 +
> osaf/services/saf/amf/amfd/sgproc.cc | 49 ++-
> osaf/services/saf/amf/amfd/si.cc | 45 ++-
> osaf/services/saf/amf/amfd/siass.cc | 123 ++++++++
> osaf/services/saf/amf/amfd/su.cc | 19 +-
> 34 files changed, 1209 insertions(+), 63 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
> . Failover may happens during headless, adjust_delayed_failover() to
> balance the assignment in term of active/standby availability
> . SI dependencies also can change due to assignment removal during headless
> adjust_delayed_sidep() to update the si dependencies
>
> 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);
> @@ -74,19 +76,84 @@ void avd_cluster_tmr_init_evh(AVD_CL_CB
> * system that are not NCS specific.
> */
>
> + /* The SI Dependency could be broken due to failover or instantiation/
> + * termination failure during headless.
> + * adjust_delayed_sidep() removes SI(s) assignment which has any
> + * unassigned sponsored SI.
> + *
> + */
> + if (cb->scs_absence_max_duration > 0) {
> + adjust_delayed_sidep();
> + }
> +
> for (std::map<std::string, AVD_SG*>::const_iterator it = sg_db->begin();
> it != sg_db->end(); it++) {
> AVD_SG *i_sg = it->second;
> if ((i_sg->list_of_su.empty() == true) || (i_sg->sg_ncs_spec ==
> true)) {
> continue;
> }
> - i_sg->realign(cb, i_sg);
> +
> + /* If hydra is enabled and su failover happened during headless,
> + * currently only the active assignment is removed but the
> standby
> + * assignment has not been switched to active.
> + * adjust_delayed_failover() finds the standby assignment being
> + * moved to active.
> + * Next, the realign() will find the remaining possible su-si
> + * to satisfy the number of assignment configuration.
> + */
> + if (cb->scs_absence_max_duration > 0) {
> + i_sg->adjust_delayed_failover(cb);
> + }
> + 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_pres_state_set(AVD_COMP *c
> node->name.value);
> LOG_NO("Node Failfast for '%s' as '%s' enters Term/Inst Failed
> state",
> node->name.value,comp->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
> @@ -1409,3 +1409,110 @@ 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
> + avd_comp_oper_state_set(comp,
> +
> 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
> + avd_comp_pres_state_set(comp,
> +
> 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();}
[HansN] db.size() returns size_type
> + unsigned int 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
> @@ -37,7 +37,7 @@
> #include <amf_d2nmsg.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
> @@ -288,6 +288,15 @@ public:
> virtual void node_fail(AVD_CL_CB *cb, AVD_SU *su) = 0;
>
> /**
> + * Run the delayed su failover that happened during headless
> + * Called when cluster init finishes and hydra option is enabled
> + *
> + * @param cb
> + * @return
> + */
> + virtual void adjust_delayed_failover(AVD_CL_CB *cb) = 0;
> +
> + /**
> * Handle SG realign
> * Assign SIs if needed. If any assigning is gets done it adds
> * the SUs to the operation list and sets the SG FSM state to SG
> realign.
> @@ -439,6 +448,7 @@ class SG_2N : public AVD_SG {
> public:
> ~SG_2N();
> void node_fail(AVD_CL_CB*, AVD_SU*);
> + void adjust_delayed_failover(AVD_CL_CB *cb);
> uint32_t realign(AVD_CL_CB *cb, AVD_SG *sg);
> uint32_t si_assign(AVD_CL_CB *cb, AVD_SI *si);
> uint32_t si_admin_down(AVD_CL_CB *cb, AVD_SI *si);
> @@ -472,6 +482,7 @@ class SG_NORED : public AVD_SG {
> public:
> ~SG_NORED();
> void node_fail(AVD_CL_CB*, AVD_SU*);
> + void adjust_delayed_failover(AVD_CL_CB *cb);
> uint32_t realign(AVD_CL_CB *cb, AVD_SG *sg);
> uint32_t si_assign(AVD_CL_CB *cb, AVD_SI *si);
> uint32_t si_admin_down(AVD_CL_CB *cb, AVD_SI *si);
> @@ -495,6 +506,7 @@ class SG_NPM : public AVD_SG {
> public:
> ~SG_NPM();
> void node_fail(AVD_CL_CB*, AVD_SU*);
> + void adjust_delayed_failover(AVD_CL_CB *cb);
> uint32_t realign(AVD_CL_CB *cb, AVD_SG *sg);
> uint32_t si_assign(AVD_CL_CB *cb, AVD_SI *si);
> uint32_t si_admin_down(AVD_CL_CB *cb, AVD_SI *si);
> @@ -526,6 +538,7 @@ class SG_NACV : public AVD_SG {
> public:
> ~SG_NACV();
> void node_fail(AVD_CL_CB*, AVD_SU*);
> + void adjust_delayed_failover(AVD_CL_CB *cb);
> uint32_t realign(AVD_CL_CB *cb, AVD_SG *sg);
> uint32_t si_assign(AVD_CL_CB *cb, AVD_SI *si);
> uint32_t si_admin_down(AVD_CL_CB *cb, AVD_SI *si);
> @@ -547,6 +560,7 @@ class SG_NWAY : public AVD_SG {
> public:
> ~SG_NWAY();
> void node_fail(AVD_CL_CB*, AVD_SU*);
> + void adjust_delayed_failover(AVD_CL_CB *cb);
> uint32_t realign(AVD_CL_CB *cb, AVD_SG *sg);
> uint32_t si_assign(AVD_CL_CB *cb, AVD_SI *si);
> uint32_t si_admin_down(AVD_CL_CB *cb, AVD_SI *si);
> @@ -592,6 +606,6 @@ extern void avd_sg_adjust_config(AVD_SG
> extern uint32_t sg_instantiated_su_count(const AVD_SG *sg);
> 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);
> -
> +extern void adjust_delayed_sidep(void);
>
> #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
> @@ -139,6 +139,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();
> private:
> 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/include/util.h
> b/osaf/services/saf/amf/amfd/include/util.h
> --- a/osaf/services/saf/amf/amfd/include/util.h
> +++ b/osaf/services/saf/amf/amfd/include/util.h
> @@ -44,7 +44,7 @@
> class AVD_SU;
>
> 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/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;
[HansN] use const std::queue<AVD_EVT_QUEUE*>::size_type queue_size =
cb->evt_queue.size(); or (preferably) const auto queue_size =
cb->evt_queue.size();
> + const uint64_t 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);
> }
> @@ -164,6 +165,8 @@ AVD_AVND *avd_node_new(const SaNameT *dn
> AVD_AVND *node;
>
> node = new AVD_AVND(dn);
[HansN] indentation, or put the initialization in the constructor
> + node->node_up_msg_count = 0;
> + node->reboot = false;
>
> return node;
> }
> @@ -409,8 +412,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/sg.cc
> b/osaf/services/saf/amf/amfd/sg.cc
> --- a/osaf/services/saf/amf/amfd/sg.cc
> +++ b/osaf/services/saf/amf/amfd/sg.cc
> @@ -1982,6 +1982,63 @@ done:
> return rc;
>
> }
> +/**
> + * @Brief Check if SI Dependency relations between SIs are still valid
> + * as cluster has just being came from headless. The dependent SIs
> + * which have any unassigned sponsor SI will remove the assignments.
> + *
> + * @param None
> + * @Return None
> +*/
> +void adjust_delayed_sidep(void)
> +{
> + AVD_SU_SI_REL *curr_susi;
> + bool rescan = true;
> + TRACE_ENTER();
> +
> + // Searching for the dependent SIs which's sponsored SI(s)
> + // had removed assignment in headless.
> + while (rescan) {
> + rescan = false;
> + for (std::map<std::string, AVD_SG*>::const_iterator it =
> sg_db->begin();
> + it != sg_db->end(); it++) {
> + AVD_SG *i_sg = it->second;
> + if (i_sg->list_of_su.empty() || (i_sg->sg_ncs_spec ==
> true)) {
> + continue;
> + }
> + for (const auto& si : i_sg->list_of_si) {
> + if (si->list_of_sisu &&
> + si->saAmfSIAssignmentState !=
> SA_AMF_ASSIGNMENT_UNASSIGNED) {
> + bool any_unassign_spsi = false;
> + AVD_SPONS_SI_NODE *spsi_node =
> si->spons_si_list;
> + for(; spsi_node != nullptr &&
> !any_unassign_spsi;
> + spsi_node =
> spsi_node->next) {
> + // if any of sponsored si has
> no assignment
> + // @si will remove its all
> assignments
> + if
> ((spsi_node->si->curr_standby_assignments() +
> +
> spsi_node->si->curr_active_assignments()) == 0) {
> + // remove all sisu of
> @si
> + for(curr_susi =
> si->list_of_sisu; curr_susi;
> +
> curr_susi = curr_susi->si_next) {
> + if
> (curr_susi->fsm == AVD_SU_SI_STATE_ASGND) {
> +
> LOG_NO("Remove '%s' from '%s' due to sponsor SI %s is unassigned",
> +
> curr_susi->si->name.value, curr_susi->su->name.value,
> +
> spsi_node->si->name.value);
> +
> avd_susi_del_send(curr_susi);
> +
> any_unassign_spsi = true;
> + // Need
> to rescan due to recursive dependencies
> + rescan
> = true;
> + }
> + }
> + }
> + }
> + }
> + }
> + }
> + }
> +
> + TRACE_LEAVE();
> +}
>
> AVD_SU* AVD_SG::first_su()
> {
> diff --git a/osaf/services/saf/amf/amfd/sg_2n_fsm.cc
> b/osaf/services/saf/amf/amfd/sg_2n_fsm.cc
> --- a/osaf/services/saf/amf/amfd/sg_2n_fsm.cc
> +++ b/osaf/services/saf/amf/amfd/sg_2n_fsm.cc
> @@ -3534,6 +3534,146 @@ done:
> TRACE_LEAVE();
> }
>
> +void SG_2N::adjust_delayed_failover(AVD_CL_CB *cb) {
> + AVD_SU_SI_REL *curr_susi;
> + TRACE_ENTER();
> +
> + // Check AdminState of node/sg/su whether is LOCKED or SHUTTING_DOWN
> + // which states will cause removal of assignment
> + for (const auto& su : list_of_su) {
> + SaAmfHAStateT su_ha_state;
> + TRACE("Check AdminState of SU/SG/Node, SU:'%s',
> saAmfSUAdminState:%u, "
> + "saAmfSGAdminState:%u, saAmfNodeAdminState:%u, "
> + "saAmfSUNumCurrActiveSIs:%u,
> saAmfSUNumCurrStandbySIs:%u",
> + su->name.value,
> + su->saAmfSUAdminState,
> + su->sg_of_su->saAmfSGAdminState,
> + su->su_on_node->saAmfNodeAdminState,
> + su->saAmfSUNumCurrActiveSIs,
> + su->saAmfSUNumCurrStandbySIs);
> +
> + if (su->saAmfSUAdminState == SA_AMF_ADMIN_LOCKED ||
> + su->sg_of_su->saAmfSGAdminState == SA_AMF_ADMIN_LOCKED
> ||
> + su->su_on_node->saAmfNodeAdminState ==
> SA_AMF_ADMIN_LOCKED ||
> + su->saAmfSUAdminState == SA_AMF_ADMIN_SHUTTING_DOWN ||
> + su->sg_of_su->saAmfSGAdminState ==
> SA_AMF_ADMIN_SHUTTING_DOWN ||
> + su->su_on_node->saAmfNodeAdminState ==
> SA_AMF_ADMIN_SHUTTING_DOWN) {
> +
> + if (su->list_of_susi) {
> + su_ha_state = avd_su_state_determine(su);
> + if (su_ha_state == SA_AMF_HA_QUIESCED ||
> + su_ha_state == SA_AMF_HA_STANDBY ||
> + su_ha_state == SA_AMF_HA_QUIESCING) {
> + // remove all susi belong to this su
> + avd_sg_su_si_del_snd(cb, su);
> + } else if (su_ha_state == SA_AMF_HA_ACTIVE) {
> + // quiesced this su
> + avd_sg_su_si_mod_snd(cb, su,
> SA_AMF_HA_QUIESCED);
> + }
> + avd_sg_su_oper_list_add(cb, su, false);
> + set_fsm_state(AVD_SG_FSM_SG_REALIGN);
> + }
> + // directly move from SHUTTING_DOWN to LOCKED
> + if (su->saAmfSUAdminState == SA_AMF_ADMIN_SHUTTING_DOWN)
> + su->set_admin_state(SA_AMF_ADMIN_LOCKED);
> + if (su->sg_of_su->saAmfSGAdminState ==
> SA_AMF_ADMIN_SHUTTING_DOWN)
> + avd_sg_admin_state_set(su->sg_of_su,
> SA_AMF_ADMIN_LOCKED);
> + if (su->su_on_node->saAmfNodeAdminState ==
> SA_AMF_ADMIN_SHUTTING_DOWN)
> + node_admin_state_set(su->su_on_node,
> SA_AMF_ADMIN_LOCKED);
> + }
> + }
> +
> + // Check AdminState of si whether is LOCKED or SHUTTING_DOWN
> + for (const auto& si : list_of_si) {
> +
> + AVD_SU_SI_REL *curr_active_susi = nullptr;
> + AVD_SU_SI_REL *curr_quiesce_susi = nullptr;
> + AVD_SU_SI_REL *curr_standby_susi = nullptr;
> +
> + TRACE("Check SI:'%s', saAmfSIAdminState:%u,
> saAmfSINumCurrActiveAssignments:%u, "
> + "saAmfSINumCurrStandbyAssignments:%u",
> + si->name.value,
> + si->saAmfSIAdminState,
> + si->saAmfSINumCurrActiveAssignments,
> + si->saAmfSINumCurrStandbyAssignments);
> +
> + for (curr_susi = si->list_of_sisu; curr_susi;
> + curr_susi = curr_susi->si_next) {
> +
> + TRACE("Check SUSI:'%s,%s', HaState:%u",
> curr_susi->su->name.value,
> + curr_susi->si->name.value,
> + curr_susi->state);
> +
> + if (si->saAmfSIAdminState == SA_AMF_ADMIN_SHUTTING_DOWN
> ||
> + si->saAmfSIAdminState == SA_AMF_ADMIN_LOCKED) {
> + // only process assigned susi, ignore the
> others due to
> + // being modified or unassigned, ...
> + if (curr_susi->fsm == AVD_SU_SI_STATE_ASGND) {
> + if (curr_susi->state ==
> SA_AMF_HA_STANDBY ||
> + curr_susi->state ==
> SA_AMF_HA_QUIESCED ||
> + curr_susi->state ==
> SA_AMF_HA_QUIESCING) {
> + // remove one susi
> + avd_susi_del_send(curr_susi);
> + } else if (curr_susi->state ==
> SA_AMF_HA_ACTIVE) {
> + // quiesced one susi
> + avd_susi_mod_send(curr_susi,
> SA_AMF_HA_QUIESCED);
> + }
> + set_fsm_state(AVD_SG_FSM_SG_REALIGN);
> + avd_sg_su_oper_list_add(cb,
> curr_susi->su, false);
> + }
> + // directly move from SHUTTING_DOWN to LOCKED
> + if (si->saAmfSIAdminState ==
> SA_AMF_ADMIN_SHUTTING_DOWN)
> +
> si->set_admin_state(SA_AMF_ADMIN_LOCKED);
> + }
> + if (curr_susi->fsm != AVD_SU_SI_STATE_ASGND)
> + continue;
> +
> + if (curr_susi->state == SA_AMF_HA_ACTIVE)
> + curr_active_susi = curr_susi;
> + else if (curr_susi->state == SA_AMF_HA_STANDBY)
> + curr_standby_susi = curr_susi;
> + else
> + curr_quiesce_susi = curr_susi;
> + }
> +
> + if (!curr_active_susi && !curr_quiesce_susi &&
> !curr_standby_susi)
> + continue;
> +
> + // at this point in time, there could be inappropriate susi in
> term of
> + // HA state due to uncompleted failover/si-swap around the time
> cluster
> + // was going into headless.
> + // Adjust the HA state if neccessary.
> + if (curr_active_susi) {
> + if (!curr_standby_susi && curr_quiesce_susi) {
> + avd_sg_su_si_mod_snd(cb, curr_quiesce_susi->su,
> SA_AMF_HA_STANDBY);
> + avd_sg_su_oper_list_add(cb,
> curr_quiesce_susi->su, false);
> + set_fsm_state(AVD_SG_FSM_SG_REALIGN);
> + }
> + } else {
> + if (curr_standby_susi && curr_quiesce_susi) {
> + avd_sg_su_si_mod_snd(cb, curr_quiesce_susi->su,
> SA_AMF_HA_STANDBY);
> + avd_sg_su_oper_list_add(cb,
> curr_quiesce_susi->su, false);
> +
> + avd_sg_su_si_mod_snd(cb, curr_standby_susi->su,
> SA_AMF_HA_ACTIVE);
> + avd_sg_su_oper_list_add(cb,
> curr_standby_susi->su, false);
> +
> + set_fsm_state(AVD_SG_FSM_SG_REALIGN);
> + } else if (!curr_standby_susi && curr_quiesce_susi) {
> + avd_sg_su_si_mod_snd(cb, curr_quiesce_susi->su,
> SA_AMF_HA_ACTIVE);
> + avd_sg_su_oper_list_add(cb,
> curr_quiesce_susi->su, false);
> +
> + set_fsm_state(AVD_SG_FSM_SG_REALIGN);
> + } else if (curr_standby_susi && !curr_quiesce_susi) {
> + avd_sg_su_si_mod_snd(cb, curr_standby_susi->su,
> SA_AMF_HA_ACTIVE);
> + avd_sg_su_oper_list_add(cb,
> curr_standby_susi->su, false);
> +
> + set_fsm_state(AVD_SG_FSM_SG_REALIGN);
> + }
> + }
> + }
> + TRACE_LEAVE();
> +}
> +
> uint32_t SG_2N::su_admin_down(AVD_CL_CB *cb, AVD_SU *su, AVD_AVND *avnd) {
> uint32_t rc = NCSCC_RC_FAILURE;
>
> diff --git a/osaf/services/saf/amf/amfd/sg_nored_fsm.cc
> b/osaf/services/saf/amf/amfd/sg_nored_fsm.cc
> --- a/osaf/services/saf/amf/amfd/sg_nored_fsm.cc
> +++ b/osaf/services/saf/amf/amfd/sg_nored_fsm.cc
> @@ -949,6 +949,12 @@ void SG_NORED::node_fail(AVD_CL_CB *cb,
> TRACE_LEAVE();
> }
>
> +void SG_NORED::adjust_delayed_failover(AVD_CL_CB *cb) {
> + TRACE_ENTER();
> + TRACE("Currently not applicable");
> + TRACE_LEAVE();
> +}
> +
> uint32_t SG_NORED::su_admin_down(AVD_CL_CB *cb, AVD_SU *su, AVD_AVND *avnd)
> {
> TRACE_ENTER2("%u", su->sg_of_su->sg_fsm_state);
>
> diff --git a/osaf/services/saf/amf/amfd/sg_npm_fsm.cc
> b/osaf/services/saf/amf/amfd/sg_npm_fsm.cc
> --- a/osaf/services/saf/amf/amfd/sg_npm_fsm.cc
> +++ b/osaf/services/saf/amf/amfd/sg_npm_fsm.cc
> @@ -4200,6 +4200,30 @@ void SG_NPM::node_fail(AVD_CL_CB *cb, AV
> return;
> }
>
> +void SG_NPM::adjust_delayed_failover(AVD_CL_CB *cb) {
> + uint32_t stb_si_count = 0;
> + uint32_t act_si_count = 0;
> + TRACE_ENTER();
> +
> + for (const auto& su : list_of_su) {
> + stb_si_count += su->saAmfSUNumCurrStandbySIs;
> + act_si_count += su->saAmfSUNumCurrActiveSIs;
> + }
> +
> + if (stb_si_count > 0 && act_si_count == 0) {
[HansN] use TODO(userid) comment , (see Google c++ style guide)
> + // TODO: smoothly transfer the assignment from STANDBY to ACTIVE
> + // as well as satisfying the configurations by:
> + // saAmfSGNumPrefAssignedSUs, saAmfSGMaxActiveSIsperSU,
> + // saAmfSGNumPrefActiveSUs, saAmfSIPrefActiveAssignments
> + for (const auto& si : list_of_si) {
> + si->delete_assignments(cb);
> + }
> + set_fsm_state(AVD_SG_FSM_SG_REALIGN);
> + }
> +
> + TRACE_LEAVE();
> +}
> +
> uint32_t SG_NPM::su_admin_down(AVD_CL_CB *cb, AVD_SU *su, AVD_AVND *avnd) {
> uint32_t rc;
>
> diff --git a/osaf/services/saf/amf/amfd/sg_nway_fsm.cc
> b/osaf/services/saf/amf/amfd/sg_nway_fsm.cc
> --- a/osaf/services/saf/amf/amfd/sg_nway_fsm.cc
> +++ b/osaf/services/saf/amf/amfd/sg_nway_fsm.cc
> @@ -521,6 +521,30 @@ done:
> TRACE_LEAVE();
> }
>
> +void SG_NWAY::adjust_delayed_failover(AVD_CL_CB *cb) {
> + uint32_t stb_si_count = 0;
> + uint32_t act_si_count = 0;
> + TRACE_ENTER();
> +
> + for (const auto& su : list_of_su) {
> + stb_si_count += su->saAmfSUNumCurrStandbySIs;
> + act_si_count += su->saAmfSUNumCurrActiveSIs;
> + }
> +
> + if (stb_si_count > 0 && act_si_count == 0) {
[HansN] use TODO(userid) comment , (see Google c++ style guide)
> + // TODO: smoothly transfer the assignment from STANDBY to ACTIVE
> + // as well as satisfying the configurations by:
> + // saAmfSGNumPrefAssignedSUs, saAmfSGMaxActiveSIsperSU,
> + // saAmfSGNumPrefActiveSUs, saAmfSIPrefActiveAssignments
> + for (const auto& si : list_of_si) {
> + si->delete_assignments(cb);
> + }
> + set_fsm_state(AVD_SG_FSM_SG_REALIGN);
> + }
> +
> + TRACE_LEAVE();
> +}
> +
> uint32_t SG_NWAY::su_admin_down(AVD_CL_CB *cb, AVD_SU *su, AVD_AVND *avnd) {
> AVD_SU_SI_REL *curr_susi = 0;
> SaAmfHAStateT state;
> diff --git a/osaf/services/saf/amf/amfd/sg_nwayact_fsm.cc
> b/osaf/services/saf/amf/amfd/sg_nwayact_fsm.cc
> --- a/osaf/services/saf/amf/amfd/sg_nwayact_fsm.cc
> +++ b/osaf/services/saf/amf/amfd/sg_nwayact_fsm.cc
> @@ -1507,6 +1507,12 @@ void SG_NACV::node_fail(AVD_CL_CB *cb, A
> return;
> }
>
> +void SG_NACV::adjust_delayed_failover(AVD_CL_CB *cb) {
> + TRACE_ENTER();
> + TRACE("Currently not applicable");
> + TRACE_LEAVE();
> +}
> +
> uint32_t SG_NACV::su_admin_down(AVD_CL_CB *cb, AVD_SU *su, AVD_AVND *avnd) {
> TRACE_ENTER2("%u", su->sg_of_su->sg_fsm_state);
>
> 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);
>
> @@ -287,12 +287,12 @@ static void su_try_repair(const AVD_SU *
> (su->saAmfSUPresenceState !=
> SA_AMF_PRESENCE_INSTANTIATION_FAILED) &&
> (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);
> + LOG_NO("Ordering Auto repair of '%s' as sufailover repair
> action",
> + 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);
> + LOG_NO("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
> @@ -634,6 +634,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:
> @@ -673,6 +677,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
> };
>
> @@ -1293,8 +1298,8 @@ void AVD_SI::update_ass_state()
> if (saAmfSINumCurrActiveAssignments == 0) {
> newState = SA_AMF_ASSIGNMENT_UNASSIGNED;
> } else {
> - osafassert(saAmfSINumCurrActiveAssignments == 1);
> - osafassert(saAmfSINumCurrStandbyAssignments == 0);
[HansN] remove these osafasserts instead of commenting
> + //osafassert(saAmfSINumCurrActiveAssignments == 1);
> + //osafassert(saAmfSINumCurrStandbyAssignments == 0);
> newState = SA_AMF_ASSIGNMENT_FULLY_ASSIGNED;
> }
> break;
> @@ -1314,21 +1319,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",
> @@ -1501,3 +1499,28 @@ void AVD_SI::update_sirank(uint32_t newS
> saAmfSIRank = (newSiRank == 0) ? ~0U : newSiRank;
> sg->add_si(this);
> }
> +
> +/*
> + * @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);
> + }
> + }
> +}
> 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,126 @@ 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
> + // . 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();
> + }
[HansN] use TODO(userid) comment , (see Google c++ style guide)
> + // TODO: check if su needs saAmfSUHostedByNode update
> + su->saAmfSUHostedByNode = node->name;
> + avd_saImmOiRtObjectUpdate(&su->name, "saAmfSUHostedByNode",
> + SA_IMM_ATTR_SANAMET, &su->saAmfSUHostedByNode);
> +
> + 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=267308311&iu=/4140
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel