"Fossies" - the Fresh Open Source Software Archive

Member "opensaf-5.21.09/src/amf/amfnd/susm.cc" (14 Sep 2021, 172293 Bytes) of package /linux/misc/opensaf-5.21.09.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "susm.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.21.06_vs_5.21.09.

    1 /*      -*- OpenSAF  -*-
    2  *
    3  * (C) Copyright 2008 The OpenSAF Foundation
    4  * (C) Copyright 2017 Ericsson AB - All Rights Reserved
    5  * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
    6  *
    7  * This program is distributed in the hope that it will be useful, but
    8  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    9  * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
   10  * under the GNU Lesser General Public License Version 2.1, February 1999.
   11  * The complete license can be accessed from the following location:
   12  * http://opensource.org/licenses/lgpl-license.php
   13  * See the Copying file included with the OpenSAF distribution for full
   14  * licensing terms.
   15  *
   16  * Author(s): Emerson Network Power
   17  *
   18  */
   19 
   20 /*****************************************************************************
   21 ..............................................................................
   22 
   23 ..............................................................................
   24 
   25   DESCRIPTION:
   26 
   27   This file contains the routines to manage the SU-SI assignments (& removals)
   28   and SU presence state FSM.
   29 
   30 ..............................................................................
   31 
   32   FUNCTIONS INCLUDED in this module:
   33 
   34 
   35 ******************************************************************************
   36 */
   37 
   38 #include "amf/amfnd/avnd.h"
   39 #include "amf/amfnd/imm.h"
   40 
   41 /* static function declarations */
   42 static uint32_t avnd_su_pres_uninst_suinst_hdler(AVND_CB *, AVND_SU *,
   43                                                  AVND_COMP *);
   44 static uint32_t avnd_su_pres_insting_suterm_hdler(AVND_CB *, AVND_SU *,
   45                                                   AVND_COMP *);
   46 static uint32_t avnd_su_pres_insting_surestart_hdler(AVND_CB *, AVND_SU *,
   47                                                      AVND_COMP *);
   48 static uint32_t avnd_su_pres_insting_compinst_hdler(AVND_CB *, AVND_SU *,
   49                                                     AVND_COMP *);
   50 static uint32_t avnd_su_pres_insting_compinstfail_hdler(AVND_CB *, AVND_SU *,
   51                                                         AVND_COMP *);
   52 static uint32_t avnd_su_pres_inst_suterm_hdler(AVND_CB *, AVND_SU *,
   53                                                AVND_COMP *);
   54 static uint32_t avnd_su_pres_inst_surestart_hdler(AVND_CB *, AVND_SU *,
   55                                                   AVND_COMP *);
   56 static uint32_t avnd_su_pres_inst_comprestart_hdler(AVND_CB *, AVND_SU *,
   57                                                     AVND_COMP *);
   58 static uint32_t avnd_su_pres_inst_compterming_hdler(AVND_CB *, AVND_SU *,
   59                                                     AVND_COMP *);
   60 static uint32_t avnd_su_pres_inst_compinst_hdler(AVND_CB *cb, AVND_SU *su,
   61                                                  AVND_COMP *comp);
   62 static uint32_t avnd_su_pres_terming_compinst_hdler(AVND_CB *, AVND_SU *,
   63                                                     AVND_COMP *);
   64 static uint32_t avnd_su_pres_terming_comptermfail_hdler(AVND_CB *, AVND_SU *,
   65                                                         AVND_COMP *);
   66 static uint32_t avnd_su_pres_terming_compuninst_hdler(AVND_CB *, AVND_SU *,
   67                                                       AVND_COMP *);
   68 static uint32_t avnd_su_pres_terming_comprestart_hdler(AVND_CB *cb, AVND_SU *su,
   69                                                        AVND_COMP *comp);
   70 static uint32_t avnd_su_pres_terming_suinst_hdler(AVND_CB *cb, AVND_SU *su,
   71                                                   AVND_COMP *comp);
   72 static uint32_t avnd_su_pres_terming_surestart_hdler(AVND_CB *cb, AVND_SU *su,
   73                                                      AVND_COMP *comp);
   74 static uint32_t avnd_su_pres_restart_suterm_hdler(AVND_CB *, AVND_SU *,
   75                                                   AVND_COMP *);
   76 static uint32_t avnd_su_pres_restart_comprestart_hdler(AVND_CB *, AVND_SU *,
   77                                                        AVND_COMP *);
   78 static uint32_t avnd_su_pres_restart_compinst_hdler(AVND_CB *, AVND_SU *,
   79                                                     AVND_COMP *);
   80 static uint32_t avnd_su_pres_restart_compterming_hdler(AVND_CB *, AVND_SU *,
   81                                                        AVND_COMP *);
   82 static uint32_t avnd_su_pres_inst_compinstfail_hdler(AVND_CB *, AVND_SU *,
   83                                                      AVND_COMP *);
   84 static uint32_t avnd_su_pres_instfailed_compuninst(AVND_CB *, AVND_SU *,
   85                                                    AVND_COMP *);
   86 static uint32_t avnd_su_pres_termfailed_comptermfail_or_compuninst(AVND_CB *,
   87                                                                    AVND_SU *,
   88                                                                    AVND_COMP *);
   89 
   90 static uint32_t avnd_su_pres_st_chng_prc(AVND_CB *, AVND_SU *,
   91                                          SaAmfPresenceStateT,
   92                                          SaAmfPresenceStateT);
   93 
   94 /****************************************************************************
   95  * S E R V I C E  U N I T  P R E S  F S M  M A T R I X  D E F I N I T I O N *
   96  ****************************************************************************/
   97 
   98 /* evt handlers are named in this format: avnd_su_pres_<st>_<ev>_hdler() */
   99 static AVND_SU_PRES_FSM_FN avnd_su_pres_fsm[][AVND_SU_PRES_FSM_EV_MAX - 1] = {
  100     /* SA_AMF_PRESENCE_UNINSTANTIATED */
  101     {
  102         avnd_su_pres_uninst_suinst_hdler, /* SU INST */
  103         0,                                /* SU TERM */
  104         0,                                /* SU RESTART */
  105         0,                                /* COMP INSTANTIATED */
  106         0,                                /* COMP INST_FAIL */
  107         0,                                /* COMP RESTARTING */
  108         0,                                /* COMP TERM_FAIL */
  109         0,                                /* COMP UNINSTANTIATED */
  110         0,                                /* COMP TERMINATING */
  111     },
  112 
  113     /* SA_AMF_PRESENCE_INSTANTIATING */
  114     {
  115         0,                                       /* SU INST */
  116         avnd_su_pres_insting_suterm_hdler,       /* SU TERM */
  117         avnd_su_pres_insting_surestart_hdler,    /* SU RESTART */
  118         avnd_su_pres_insting_compinst_hdler,     /* COMP INSTANTIATED */
  119         avnd_su_pres_insting_compinstfail_hdler, /* COMP INST_FAIL */
  120         0,                                       /* COMP RESTARTING */
  121         avnd_su_pres_terming_comptermfail_hdler, /* COMP TERM_FAIL */
  122         0,                                       /* COMP UNINSTANTIATED */
  123         0,                                       /* COMP TERMINATING */
  124     },
  125 
  126     /* SA_AMF_PRESENCE_INSTANTIATED */
  127     {
  128         0,                                       /* SU INST */
  129         avnd_su_pres_inst_suterm_hdler,          /* SU TERM */
  130         avnd_su_pres_inst_surestart_hdler,       /* SU RESTART */
  131         avnd_su_pres_inst_compinst_hdler,        /* COMP INSTANTIATED */
  132         avnd_su_pres_inst_compinstfail_hdler,    /* COMP INST_FAIL */
  133         avnd_su_pres_inst_comprestart_hdler,     /* COMP RESTARTING */
  134         avnd_su_pres_terming_comptermfail_hdler, /* COMP TERM_FAIL */
  135         0,                                       /* COMP UNINSTANTIATED */
  136         avnd_su_pres_inst_compterming_hdler,     /* COMP TERMINATING */
  137     },
  138 
  139     /* SA_AMF_PRESENCE_TERMINATING */
  140     {
  141         avnd_su_pres_terming_suinst_hdler,       /* SU INST */
  142         avnd_su_pres_restart_suterm_hdler,       /* SU TERM */
  143         avnd_su_pres_terming_surestart_hdler,    /* SU RESTART */
  144         avnd_su_pres_terming_compinst_hdler,     /* COMP INSTANTIATED */
  145         avnd_su_pres_inst_compinstfail_hdler,    /* COMP INST_FAIL */
  146         avnd_su_pres_terming_comprestart_hdler,  /* COMP RESTARTING */
  147         avnd_su_pres_terming_comptermfail_hdler, /* COMP TERM_FAIL */
  148         avnd_su_pres_terming_compuninst_hdler,   /* COMP UNINSTANTIATED */
  149         0,                                       /* COMP TERMINATING */
  150     },
  151 
  152     /* SA_AMF_PRESENCE_RESTARTING */
  153     {
  154         0,                                       /* SU INST */
  155         avnd_su_pres_restart_suterm_hdler,       /* SU TERM */
  156         0,                                       /* SU RESTART */
  157         avnd_su_pres_restart_compinst_hdler,     /* COMP INSTANTIATED */
  158         avnd_su_pres_inst_compinstfail_hdler,    /* COMP INST_FAIL */
  159         avnd_su_pres_restart_comprestart_hdler,  /* COMP RESTARTING */
  160         avnd_su_pres_terming_comptermfail_hdler, /* COMP TERM_FAIL */
  161         0,                                       /* COMP UNINSTANTIATED */
  162         avnd_su_pres_restart_compterming_hdler,  /* COMP TERMINATING */
  163     },
  164 
  165     /* SA_AMF_PRESENCE_INSTANTIATION_FAILED */
  166     {
  167         0,                                  /* SU INST */
  168         0,                                  /* SU TERM */
  169         0,                                  /* SU RESTART */
  170         0,                                  /* COMP INSTANTIATED */
  171         avnd_su_pres_instfailed_compuninst, /* COMP INST_FAIL */
  172         0,                                  /* COMP RESTARTING */
  173         0,                                  /* COMP TERM_FAIL */
  174         avnd_su_pres_instfailed_compuninst, /* COMP UNINSTANTIATED */
  175         0,                                  /* COMP TERMINATING */
  176     },
  177 
  178     /* SA_AMF_PRESENCE_TERMINATION_FAILED */
  179     {
  180         0, /* SU INST */
  181         0, /* SU TERM */
  182         0, /* SU RESTART */
  183         0, /* COMP INSTANTIATED */
  184         0, /* COMP INST_FAIL */
  185         0, /* COMP RESTARTING */
  186         avnd_su_pres_termfailed_comptermfail_or_compuninst, /* COMP TERM_FAIL */
  187         avnd_su_pres_termfailed_comptermfail_or_compuninst, /* COMP
  188                                                                UNINSTANTIATED */
  189         0, /* COMP TERMINATING */
  190     }};
  191 
  192 /***************************************************************************
  193  * S U - S I  Q U E U E  M A N A G E M E N T   P O R T I O N   S T A R T S *
  194  ***************************************************************************/
  195 
  196 /****************************************************************************
  197   Name          : avnd_su_siq_rec_buf
  198 
  199   Description   : This routine determines if the SU-SI assign message from
  200                   AvD is to be buffered. If the message has to be buffered,
  201                   it is added to the SIQ (maintained on SU). Else the message
  202                   is ready for assignment.
  203 
  204   Arguments     : cb    - ptr to AvND control block
  205                   su    - ptr to the AvND SU
  206                   param - ptr to the SI parameters
  207 
  208   Return Values : ptr to the siq record, if the message is buffered
  209                   0, otherwise
  210 
  211   Notes         : None
  212 ******************************************************************************/
  213 AVND_SU_SIQ_REC *avnd_su_siq_rec_buf(AVND_CB *cb, AVND_SU *su,
  214                                      AVND_SU_SI_PARAM *param) {
  215   AVND_SU_SIQ_REC *siq = 0;
  216   AVND_SU_SI_REC *si_rec = 0;
  217   bool is_tob_buf = false;
  218   uint32_t rc = NCSCC_RC_SUCCESS;
  219   TRACE_ENTER2("'%s'", su->name.c_str());
  220 
  221   /* buffer the msg, if SU is inst-failed and all comps are not terminated
  222   or during SuRestart */
  223   if (((su->pres == SA_AMF_PRESENCE_INSTANTIATION_FAILED) &&
  224        (!m_AVND_SU_IS_ALL_TERM(su))) ||
  225       m_AVND_IS_SHUTTING_DOWN(cb) ||
  226       (m_AVND_SU_IS_RESTART(su) &&
  227       su_all_comps_restartable(*su))) {
  228     siq = avnd_su_siq_rec_add(cb, su, param, &rc);
  229     TRACE_LEAVE();
  230     return siq;
  231   }
  232 
  233   /* dont buffer quiesced assignments during failure */
  234   if (m_AVND_SU_IS_FAILED(su) && ((SA_AMF_HA_QUIESCED == param->ha_state) ||
  235                                   (AVSV_SUSI_ACT_DEL == param->msg_act))) {
  236     TRACE_LEAVE();
  237     return 0;
  238   }
  239 
  240   /*
  241    * Determine if msg is to be buffered.
  242    */
  243   if (!m_AVSV_SA_NAME_IS_NULL(param->si_name)) { /* => msg is for a single si */
  244     /* determine if an (non-quiescing) assign / remove operation is on */
  245     si_rec = avnd_su_si_rec_get(cb, su->name, Amf::to_string(&param->si_name));
  246     if (si_rec && ((m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_ASSIGNING(si_rec) &&
  247                     (SA_AMF_HA_QUIESCING != si_rec->curr_state)) ||
  248                    (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVING(si_rec))))
  249       is_tob_buf = true;
  250   } else { /* => msg is for all sis */
  251     /* determine if an (non-quiescing) assign / remove operation is on */
  252     for (si_rec = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
  253          si_rec && !((m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_ASSIGNING(si_rec) &&
  254                       (SA_AMF_HA_QUIESCING != si_rec->curr_state)) ||
  255                      (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVING(si_rec)));
  256          si_rec =
  257              (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(&si_rec->su_dll_node))
  258       ;
  259     if (si_rec) is_tob_buf = true;
  260   }
  261 
  262   /*
  263    * Buffer the msg (if reqd).
  264    */
  265   if (true == is_tob_buf) siq = avnd_su_siq_rec_add(cb, su, param, &rc);
  266 
  267   TRACE_LEAVE();
  268   return siq;
  269 }
  270 
  271 /****************************************************************************
  272   Name          : avnd_su_siq_prc
  273 
  274   Description   : This routine picks up the least-recent buffered message &
  275                   initiates the su-si assignment / removal.
  276 
  277   Arguments     : cb   - ptr to AvND control block
  278                   su   - ptr to the AvND SU
  279 
  280   Return Values : NCSCC_RC_SUCCESS / NCSCC_RC_FAILURE
  281 
  282   Notes         : None
  283 ******************************************************************************/
  284 uint32_t avnd_su_siq_prc(AVND_CB *cb, AVND_SU *su) {
  285   AVND_SU_SIQ_REC *siq = 0;
  286   AVND_SU_SI_REC *si = 0;
  287   uint32_t rc = NCSCC_RC_SUCCESS;
  288   TRACE_ENTER2("SU '%s'", su->name.c_str());
  289 
  290   /* get the least-recent buffered msg, if any */
  291   siq = (AVND_SU_SIQ_REC *)m_NCS_DBLIST_FIND_LAST(&su->siq);
  292   if (!siq) {
  293     TRACE_LEAVE();
  294     return rc;
  295   }
  296 
  297   /* determine if an (non-quiescing) assign / remove operation is on */
  298   for (si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
  299        si && !((m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_ASSIGNING(si) &&
  300                 (SA_AMF_HA_QUIESCING != si->curr_state)) ||
  301                (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVING(si)));
  302        si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(&si->su_dll_node))
  303     ;
  304   if (si) {
  305     TRACE_LEAVE();
  306     return rc;
  307   }
  308 
  309   /* unlink the buffered msg from the queue */
  310   ncs_db_link_list_delink(&su->siq, &siq->su_dll_node);
  311 
  312   /* initiate si asignment / removal */
  313   rc = avnd_su_si_msg_prc(cb, su, &siq->info);
  314 
  315   /* delete the buffered msg */
  316   avnd_su_siq_rec_del(cb, su, siq);
  317 
  318   TRACE_LEAVE2("%u", rc);
  319   return rc;
  320 }
  321 
  322 /***************************************************************************
  323  *****  S U - S I   M A N A G E M E N T   P O R T I O N   S T A R T S  *****
  324  ***************************************************************************/
  325 
  326 /****************************************************************************
  327   Name          : avnd_su_si_msg_prc
  328 
  329   Description   : This routine initiates the su-si assignment / removal. It
  330                   updates the database & then starts the assignment / removal.
  331 
  332   Arguments     : cb   - ptr to AvND control block
  333                   su   - ptr to the AvND SU
  334                   info - ptr to the si param
  335 
  336   Return Values : NCSCC_RC_SUCCESS / NCSCC_RC_FAILURE
  337 
  338   Notes         : None
  339 ******************************************************************************/
  340 uint32_t avnd_su_si_msg_prc(AVND_CB *cb, AVND_SU *su, AVND_SU_SI_PARAM *info) {
  341   AVND_SU_SI_REC *si = 0;
  342   uint32_t rc = NCSCC_RC_SUCCESS;
  343 
  344   TRACE_ENTER2("'%s', act=%u, ha_state=%u, single_csi=%u", su->name.c_str(),
  345                info->msg_act, info->ha_state, info->single_csi);
  346 
  347   /* we have started the su si msg processing */
  348   m_AVND_SU_ASSIGN_PEND_SET(su);
  349 
  350   /* If the request targets all SIs, set flag once early for all cases */
  351   if (avsv_sa_name_is_null(&info->si_name)) m_AVND_SU_ALL_SI_SET(su);
  352 
  353   switch (info->msg_act) {
  354     case AVSV_SUSI_ACT_ASGN: /* new assign */
  355     {
  356       if (false == info->single_csi) {
  357         /* add to the database */
  358         si = avnd_su_si_rec_add(cb, su, info, &rc);
  359       } else {
  360         AVND_COMP_CSI_PARAM *csi_param;
  361         AVND_COMP_CSI_REC *csi;
  362 
  363         /* verify if su-si relationship already exists */
  364         if (0 == (si = avnd_su_si_rec_get(cb, Amf::to_string(&info->su_name),
  365                                           Amf::to_string(&info->si_name)))) {
  366           LOG_ER("No SUSI Rec exists");
  367           goto done;
  368         }
  369 
  370         osafassert((info->num_assigns == 1));
  371         csi_param = info->list;
  372         osafassert(csi_param);
  373         osafassert(!(csi_param->next));
  374         csi = avnd_su_si_csi_rec_add(cb, su, si, csi_param, &rc);
  375         si->single_csi_add_rem_in_si = AVSV_SUSI_ACT_ASGN;
  376         csi->single_csi_add_rem_in_si = AVSV_SUSI_ACT_ASGN;
  377         LOG_NO("Adding CSI '%s'",
  378                osaf_extended_name_borrow(&csi_param->csi_name));
  379       }
  380 
  381       /* initiate si assignment */
  382       if (si) rc = avnd_su_si_assign(cb, su, si);
  383     } break;
  384 
  385     case AVSV_SUSI_ACT_DEL: /* remove */
  386     {
  387       /* get the si */
  388       si = avnd_su_si_rec_get(cb, su->name, Amf::to_string(&info->si_name));
  389       if (!si && !m_AVSV_SA_NAME_IS_NULL(info->si_name)) goto done;
  390 
  391       /*
  392        * si may point to si-rec to be deleted or be 0 (signifying all).
  393        * initiate si removal.
  394        */
  395       if (true == info->single_csi) {
  396         AVND_COMP_CSI_PARAM *csi_param;
  397         AVND_COMP_CSI_REC *csi_rec;
  398         osafassert(si != nullptr);
  399         si->single_csi_add_rem_in_si = AVSV_SUSI_ACT_DEL;
  400         osafassert((info->num_assigns == 1));
  401         csi_param = info->list;
  402         osafassert(csi_param);
  403         osafassert(!(csi_param->next));
  404         if (nullptr == (csi_rec = avnd_compdb_csi_rec_get(
  405                             cb, Amf::to_string(&csi_param->comp_name),
  406                             Amf::to_string(&csi_param->csi_name)))) {
  407           LOG_ER("No CSI Rec exists for comp='%s'and csi=%s",
  408                  osaf_extended_name_borrow(&csi_param->comp_name),
  409                  osaf_extended_name_borrow(&csi_param->csi_name));
  410           goto done;
  411         }
  412         csi_rec->single_csi_add_rem_in_si = AVSV_SUSI_ACT_DEL;
  413         LOG_NO("Removing CSI '%s'",
  414                osaf_extended_name_borrow(&csi_param->csi_name));
  415       }
  416 
  417       rc = avnd_su_si_remove(cb, su, si);
  418     } break;
  419 
  420     case AVSV_SUSI_ACT_MOD: /* modify */
  421     {
  422       /* modify in the database */
  423       if (!m_AVSV_SA_NAME_IS_NULL(info->si_name)) /* modify a specific si-rec */
  424         si = avnd_su_si_rec_modify(cb, su, info, &rc);
  425       else
  426         /* modify all the comp-csi records that belong to this su */
  427         rc = avnd_su_si_all_modify(cb, su, info);
  428 
  429       /* initiate si modification */
  430       if (NCSCC_RC_SUCCESS == rc) rc = avnd_su_si_assign(cb, su, si);
  431     } break;
  432 
  433     default:
  434       osafassert(0);
  435   } /* switch */
  436 
  437 done:
  438   TRACE_LEAVE2("%u", rc);
  439   return rc;
  440 }
  441 /**
  442  * @brief       Checks if all csi of same SI assigned to the component are in
  443  *assigning state
  444  *
  445  * @param [in]  cmp
  446  *              si
  447  *
  448  * @returns     true/false
  449  **/
  450 static bool csi_of_same_si_in_assigning_state(const AVND_COMP *cmp,
  451                                               const AVND_SU_SI_REC *si) {
  452   AVND_COMP_CSI_REC *curr_csi;
  453   bool all_csi_assigned = true;
  454   TRACE_ENTER();
  455   for (curr_csi = m_AVND_CSI_REC_FROM_COMP_DLL_NODE_GET(
  456            m_NCS_DBLIST_FIND_FIRST(&cmp->csi_list));
  457        curr_csi; curr_csi = m_AVND_CSI_REC_FROM_COMP_DLL_NODE_GET(
  458                      m_NCS_DBLIST_FIND_NEXT(&curr_csi->comp_dll_node))) {
  459     TRACE(
  460         "curr_csi:'%s', prv_assign_state:%u curr_assign_state:%u, suspending_assignment:%u",
  461         curr_csi->name.c_str(), curr_csi->prv_assign_state,
  462         curr_csi->curr_assign_state, curr_csi->suspending_assignment);
  463     if ((curr_csi->si == si) &&
  464         !m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_ASSIGNING(curr_csi)) {
  465       // ignore suspending_assignment
  466       if (!curr_csi->suspending_assignment) {
  467         all_csi_assigned = false;
  468         break;
  469       }
  470     }
  471   }
  472   TRACE_LEAVE();
  473   return all_csi_assigned;
  474 }
  475 /**
  476  * Assign a SI to an SU
  477  * @param si
  478  * @param su
  479  * @param single_csi if true just one CSI is assigned. if false all CSIs
  480  *                   are assigned in one shot.
  481  *
  482  * @return uns32
  483  */
  484 static uint32_t assign_si_to_su(const AVND_CB *cb, AVND_SU_SI_REC *si,
  485                                 AVND_SU *su, int single_csi) {
  486   uint32_t rc = NCSCC_RC_SUCCESS;
  487   AVND_COMP_CSI_REC *curr_csi;
  488 
  489   TRACE_ENTER2("'%s' si-state'%d' '%s' single_csi=%u", si->name.c_str(),
  490                si->curr_state, su->name.c_str(), single_csi);
  491 
  492   LOG_NO("Assigning '%s' %s to '%s'", si->name.c_str(),
  493          ha_state[si->curr_state], su->name.c_str());
  494 
  495   /* initiate the si assignment for pi su */
  496   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
  497     uint32_t rank;
  498 
  499     if (SA_AMF_HA_ACTIVE == si->curr_state ||
  500         SA_AMF_HA_STANDBY == si->curr_state) {
  501       if (single_csi) {
  502         for (curr_csi =
  503                  (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&si->csi_list),
  504             rank = curr_csi->rank;
  505              (curr_csi != nullptr) &&
  506              ((curr_csi->rank == rank) ||
  507               (curr_csi->si->single_csi_add_rem_in_si == AVSV_SUSI_ACT_ASGN));
  508              curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
  509                  &curr_csi->si_dll_node)) {
  510           curr_csi->comp->assigned_flag = false;
  511         }
  512       }
  513       for (curr_csi =
  514                (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&si->csi_list),
  515           rank = curr_csi->rank;
  516            (curr_csi != nullptr) &&
  517            ((curr_csi->rank == rank) ||
  518             (curr_csi->si->single_csi_add_rem_in_si == AVSV_SUSI_ACT_ASGN));
  519            curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
  520                &curr_csi->si_dll_node)) {
  521         if (AVND_COMP_CSI_ASSIGN_STATE_ASSIGNED !=
  522             curr_csi->curr_assign_state) {
  523           if (false == curr_csi->comp->assigned_flag) {
  524             /* Dont assign, if already assignd */
  525             if (AVND_SU_SI_ASSIGN_STATE_ASSIGNED !=
  526                 curr_csi->si->curr_assign_state) {
  527               rc = avnd_comp_csi_assign(avnd_cb, curr_csi->comp,
  528                                         (single_csi) ? curr_csi : nullptr);
  529               if (NCSCC_RC_SUCCESS != rc) goto done;
  530             }
  531             if ((false == curr_csi->comp->assigned_flag) &&
  532                 (m_AVND_COMP_CSI_PRV_ASSIGN_STATE_IS_ASSIGNED(curr_csi))) {
  533               if (csi_of_same_si_in_assigning_state(curr_csi->comp, si))
  534                 curr_csi->comp->assigned_flag = true;
  535             }
  536           } else {
  537             m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
  538                 curr_csi, AVND_COMP_CSI_ASSIGN_STATE_ASSIGNED);
  539           }
  540         }
  541       }
  542     } else {
  543       if (single_csi) {
  544         for (curr_csi =
  545                  (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_LAST(&si->csi_list),
  546             rank = curr_csi->rank;
  547              (curr_csi != nullptr) &&
  548              ((curr_csi->rank == rank) ||
  549               (curr_csi->si->single_csi_add_rem_in_si == AVSV_SUSI_ACT_ASGN));
  550              curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_PREV(
  551                  &curr_csi->si_dll_node)) {
  552           curr_csi->comp->assigned_flag = false;
  553         }
  554       }
  555       for (curr_csi =
  556                (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_LAST(&si->csi_list),
  557           rank = curr_csi->rank;
  558            (curr_csi != nullptr) &&
  559            ((curr_csi->rank == rank) ||
  560             (curr_csi->si->single_csi_add_rem_in_si == AVSV_SUSI_ACT_ASGN));
  561            curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_PREV(
  562                &curr_csi->si_dll_node)) {
  563         /* We need to send only one csi set for a comp having  more than one CSI
  564            assignment for csi mod/rem.*/
  565         if (AVND_COMP_CSI_ASSIGN_STATE_ASSIGNED !=
  566             curr_csi->curr_assign_state) {
  567           if (false == curr_csi->comp->assigned_flag) {
  568             /* Dont assign, if already assignd */
  569             if (AVND_SU_SI_ASSIGN_STATE_ASSIGNED !=
  570                 curr_csi->si->curr_assign_state) {
  571               rc = avnd_comp_csi_assign(avnd_cb, curr_csi->comp,
  572                                         (single_csi) ? curr_csi : nullptr);
  573               if (NCSCC_RC_SUCCESS != rc) goto done;
  574             }
  575             /*if ((!single_csi) && (false == curr_csi->comp->assigned_flag) &&
  576                                     (m_AVND_COMP_CSI_PRV_ASSIGN_STATE_IS_ASSIGNED(curr_csi)))*/
  577             if (false == curr_csi->comp->assigned_flag) {
  578               if (csi_of_same_si_in_assigning_state(curr_csi->comp, si)) {
  579                 curr_csi->comp->assigned_flag = true;
  580               }
  581             }
  582           } else {
  583             // Don't move csi to ASSIGNED state if its assignment's suspending
  584             if (!curr_csi->suspending_assignment) {
  585               m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
  586                   curr_csi, AVND_COMP_CSI_ASSIGN_STATE_ASSIGNED);
  587             }
  588           }
  589         }
  590       }
  591     }
  592   }
  593 
  594   /* initiate the si assignment for npi su */
  595   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
  596     TRACE("SU is NPI");
  597 
  598     if ((single_csi == 1) &&
  599         (si->single_csi_add_rem_in_si == AVSV_SUSI_ACT_ASGN)) {
  600       // we are adding a CSI to an unlocked SU
  601 
  602       // first find the newly added unassigned CSI
  603       for (curr_csi =
  604                (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&si->csi_list);
  605            curr_csi != nullptr;
  606            curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
  607                &curr_csi->si_dll_node)) {
  608         if (curr_csi->single_csi_add_rem_in_si == AVSV_SUSI_ACT_ASGN) break;
  609       }
  610 
  611       osafassert(curr_csi);
  612 
  613       if (si->curr_state == SA_AMF_HA_ACTIVE) {
  614         avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATING);
  615         rc = avnd_comp_csi_assign(avnd_cb, curr_csi->comp, curr_csi);
  616       } else {
  617         curr_csi->single_csi_add_rem_in_si = AVSV_SUSI_ACT_BASE;
  618         rc = avnd_su_si_oper_done(avnd_cb, su, si);
  619       }
  620 
  621       goto done;
  622     }
  623 
  624     bool npi_prv_inst = true, npi_curr_inst = true;
  625     AVND_SU_PRES_FSM_EV su_ev = AVND_SU_PRES_FSM_EV_MAX;
  626 
  627     /* determine the instantiation state of npi su */
  628     if (SA_AMF_HA_ACTIVE != si->prv_state)
  629       // If previous state was not active, it means SU was not instantiated.
  630       npi_prv_inst = false;
  631     if (SA_AMF_HA_ACTIVE != si->curr_state)
  632       /*If current state, that has come from AMFD, is not active, then also this
  633         NPI SU is not going to be instantiated.*/
  634       npi_curr_inst = false;
  635 
  636     /* Quiesced while Quiescing */
  637     if (m_AVND_SU_SI_PRV_ASSIGN_STATE_IS_ASSIGNING(si) &&
  638         (SA_AMF_HA_QUIESCING == si->prv_state))
  639       /*I guess this condition is for the situation when shutdown operation is
  640          going on and lock is issued over it.*/
  641       npi_prv_inst = true;
  642 
  643     /* determine the event for the su fsm */
  644     if (m_AVND_SU_IS_RESTART(su) && (true == npi_curr_inst))
  645       /* This seems to be a doubtful if block.
  646          Active state has come when su restart is going on.
  647          This can never happen as NPI su gets only one SI.
  648        */
  649       su_ev = AVND_SU_PRES_FSM_EV_RESTART;
  650     else if (!m_AVND_SU_IS_RESTART(su) && (npi_prv_inst != npi_curr_inst))
  651       /* When surestart is not going on and quiesced assignments or active
  652          state has come. */
  653       su_ev = (true == npi_curr_inst) ? AVND_SU_PRES_FSM_EV_INST
  654                                       : AVND_SU_PRES_FSM_EV_TERM;
  655     else if (m_AVND_SU_IS_RESTART(su) &&
  656              (su_all_comps_restartable(*su) == false) &&
  657              (npi_curr_inst == false)) {
  658       /*suRestart is going on and SU has atleast one component
  659        * non-restartable.*/
  660       TRACE(
  661           "suRestart is going on for a non-restartable SU,"
  662           "  terminate all the components for quiesced state.");
  663       su_ev = AVND_SU_PRES_FSM_EV_RESTART;
  664     }
  665 
  666     /* we cant do anything on inst-failed SU or term-failed SU, so just resp
  667      * success for quiesced */
  668     if (su->pres == SA_AMF_PRESENCE_INSTANTIATION_FAILED ||
  669         su->pres == SA_AMF_PRESENCE_TERMINATION_FAILED)
  670       su_ev = AVND_SU_PRES_FSM_EV_MAX;
  671 
  672     /* trigger the su fsm */
  673     if (AVND_SU_PRES_FSM_EV_MAX != su_ev) {
  674       rc = avnd_su_pres_fsm_run(avnd_cb, su, 0, su_ev);
  675     } else
  676       rc = avnd_su_si_oper_done(avnd_cb, su, ((single_csi) ? si : nullptr));
  677     if (NCSCC_RC_SUCCESS != rc) goto done;
  678   }
  679 
  680 done:
  681   TRACE_LEAVE2("%u", rc);
  682   return rc;
  683 }
  684 
  685 /****************************************************************************
  686   Name          : avnd_su_si_assign
  687 
  688   Description   : This routine triggers the su-si assignment.
  689                   For PI SU, it picks up the lowest/highest ranked csi from
  690                   the csi-list (maintained on si). It then invokes csi-set
  691                   callback for CSI belonging to PI components and triggers
  692                   comp FSM with InstEv/TermEv trigger for CSI belonging to
  693                   NPI comps.
  694                   For NPI SU, the SU FSM is triggered with SUInstEv/SUTerm
  695                   event.
  696                   The decision to pick the lowest/highest rank or generate
  697                   instantiate/terminate trigger depends on the current and
  698                   previous HA state.
  699                   If the SU is in restart state (i.e. su-restart recovery is
  700                   in progress), comp & SU FSM are triggered with Restart
  701                   events instead (in the above flow).
  702 
  703   Arguments     : cb - ptr to AvND control block
  704                   su - ptr to the AvND SU
  705                   si - ptr to the si record (if 0, all the CSIs corresponding
  706                        to a comp are assigned in one shot)
  707 
  708   Return Values : NCSCC_RC_SUCCESS / NCSCC_RC_FAILURE
  709 
  710   Notes         : None
  711 ******************************************************************************/
  712 uint32_t avnd_su_si_assign(AVND_CB *cb, AVND_SU *su, AVND_SU_SI_REC *si) {
  713   uint32_t rc = NCSCC_RC_SUCCESS, rank;
  714   AVND_SU_SI_REC *curr_si;
  715   AVND_COMP_CSI_REC *curr_csi;
  716 
  717   TRACE_ENTER2("'%s' '%s'", su->name.c_str(), si ? si->name.c_str() : nullptr);
  718 
  719   /* mark the si(s) assigning and assign to su */
  720   if (si) {
  721     m_AVND_SU_SI_CURR_ASSIGN_STATE_SET(si, AVND_SU_SI_ASSIGN_STATE_ASSIGNING);
  722     rc = assign_si_to_su(cb, si, su, true);
  723   } else {
  724     for (curr_si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
  725          curr_si != nullptr; curr_si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(
  726                                  &curr_si->su_dll_node)) {
  727       if (SA_AMF_HA_ACTIVE == curr_si->curr_state ||
  728           SA_AMF_HA_STANDBY == curr_si->curr_state) {
  729         for (curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(
  730                  &curr_si->csi_list),
  731             rank = curr_csi->rank;
  732              (curr_csi != nullptr) && (curr_csi->rank == rank);
  733              curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
  734                  &curr_csi->si_dll_node)) {
  735           curr_csi->comp->assigned_flag = false;
  736         }
  737       } else {
  738         for (curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_LAST(
  739                  &curr_si->csi_list),
  740             rank = curr_csi->rank;
  741              (curr_csi != nullptr) && (curr_csi->rank == rank);
  742              curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_PREV(
  743                  &curr_csi->si_dll_node)) {
  744           curr_csi->comp->assigned_flag = false;
  745         }
  746       }
  747       m_AVND_SU_SI_CURR_ASSIGN_STATE_SET(curr_si,
  748                                          AVND_SU_SI_ASSIGN_STATE_ASSIGNING);
  749     }
  750     /* if no si is specified, the action is aimed at all the sis... loop */
  751     for (curr_si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
  752          curr_si != nullptr; curr_si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(
  753                                  &curr_si->su_dll_node)) {
  754       rc = assign_si_to_su(cb, curr_si, su, false);
  755       if (NCSCC_RC_SUCCESS != rc) goto done;
  756     }
  757   }
  758 
  759 done:
  760   TRACE_LEAVE2("%u", rc);
  761   return rc;
  762 }
  763 
  764 /****************************************************************************
  765   Name          : avnd_su_si_remove
  766 
  767   Description   : This routine triggers su-si assignment removal. For PI SU,
  768                   it picks up the highest ranked CSIs from the csi-list. It
  769                   then invokes csi-remove callback for CSIs belonging to PI
  770                   components and triggers comp FSM with TermEv for CSIs
  771                   belonging to NPI comp. For NPI SU, the SU FSM is triggered
  772                   with SUTermEv.
  773 
  774   Arguments     : cb - ptr to AvND control block
  775                   su - ptr to the AvND SU
  776                   si - ptr to the si record (if 0, all the CSIs corresponding
  777                        to a comp are removed in one shot)
  778 
  779   Return Values : NCSCC_RC_SUCCESS / NCSCC_RC_FAILURE
  780 
  781   Notes         : None
  782 ******************************************************************************/
  783 uint32_t avnd_su_si_remove(AVND_CB *cb, AVND_SU *su, AVND_SU_SI_REC *si) {
  784   AVND_COMP_CSI_REC *curr_csi = 0;
  785   AVND_SU_SI_REC *curr_si = 0;
  786   uint32_t rc = NCSCC_RC_SUCCESS;
  787 
  788   TRACE_ENTER2("'%s' '%s'", su->name.c_str(), si ? si->name.c_str() : nullptr);
  789 
  790   /* mark the si(s) removing */
  791   if (si) {
  792     m_AVND_SU_SI_CURR_ASSIGN_STATE_SET(si, AVND_SU_SI_ASSIGN_STATE_REMOVING);
  793   } else {
  794     for (curr_si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
  795          curr_si; curr_si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(
  796                       &curr_si->su_dll_node)) {
  797       m_AVND_SU_SI_CURR_ASSIGN_STATE_SET(curr_si,
  798                                          AVND_SU_SI_ASSIGN_STATE_REMOVING);
  799     }
  800   }
  801 
  802   if ((su->si_list.n_nodes > 1) && (si == nullptr))
  803     LOG_NO("Removing 'all (%u) SIs' from '%s'", su->si_list.n_nodes,
  804            su->name.c_str());
  805 
  806   /* if no si is specified, the action is aimed at all the sis... pick up any si
  807    */
  808   curr_si = (si) ? si : (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
  809   if (!curr_si) {
  810     // after headless, we may have a buffered susi remove msg
  811     // if the susi can't be found (already removed), reset flag
  812     LOG_NO("no SI found in '%s'", su->name.c_str());
  813     m_AVND_SU_ALL_SI_RESET(su);
  814     goto done;
  815   }
  816 
  817   /* initiate the si removal for pi su */
  818   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
  819     if (si) {
  820       if (AVSV_SUSI_ACT_DEL == si->single_csi_add_rem_in_si) {
  821         AVND_COMP_CSI_REC *next_csi;
  822 
  823         /* We have to remove single csi. */
  824         for (curr_csi =
  825                  (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&si->csi_list);
  826              curr_csi;) {
  827           next_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
  828               &curr_csi->si_dll_node);
  829           if (AVSV_SUSI_ACT_DEL == curr_csi->single_csi_add_rem_in_si) {
  830             rc = avnd_comp_csi_remove(cb, curr_csi->comp, curr_csi);
  831             if (NCSCC_RC_SUCCESS != rc) goto done;
  832           }
  833           curr_csi = next_csi;
  834         }
  835       } else {
  836         /* pick up the last csi */
  837         curr_csi =
  838             (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_LAST(&curr_si->csi_list);
  839 
  840         /* remove the csi */
  841         if (curr_csi) {
  842           rc = avnd_comp_csi_remove(cb, curr_csi->comp, (si) ? curr_csi : 0);
  843           if (NCSCC_RC_SUCCESS != rc) goto done;
  844         }
  845       }
  846     } else {
  847       AVND_SU_SI_REC *next_si;
  848 
  849       /* removal for all SIs, do all in paralell */
  850       for (curr_si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
  851            curr_si;) {
  852         /* Save next ptr here since it might get deleted deep down in
  853          * avnd_comp_csi_remove */
  854         next_si =
  855             (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(&curr_si->su_dll_node);
  856 
  857         /* pick up the last csi */
  858         curr_csi =
  859             (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_LAST(&curr_si->csi_list);
  860 
  861         LOG_NO("Removing '%s' from '%s'", curr_si->name.c_str(),
  862                su->name.c_str());
  863 
  864         /* remove all the CSIs from this comp */
  865         if (curr_csi) {
  866           rc = avnd_comp_csi_remove(cb, curr_csi->comp, nullptr);
  867           if (NCSCC_RC_SUCCESS != rc || !su->si_list.n_nodes) goto done;
  868         }
  869         curr_si = next_si;
  870       }
  871     }
  872   }
  873 
  874   /* initiate the si removal for npi su */
  875   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
  876     if ((si != nullptr) &&
  877         (si->single_csi_add_rem_in_si == AVSV_SUSI_ACT_DEL) &&
  878         (si->curr_state == SA_AMF_HA_ACTIVE)) {
  879       /* we are removing a single CSI, first find it */
  880       for (curr_csi =
  881                (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&si->csi_list);
  882            curr_csi != nullptr;
  883            curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
  884                &curr_csi->si_dll_node)) {
  885         if (AVSV_SUSI_ACT_DEL == curr_csi->single_csi_add_rem_in_si) break;
  886       }
  887 
  888       osafassert(curr_csi != nullptr);
  889       rc = avnd_comp_csi_remove(cb, curr_csi->comp, curr_csi);
  890       if (rc == NCSCC_RC_SUCCESS)
  891         avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_TERMINATING);
  892     } else {
  893       /* nothing to be done, termination already done in
  894          quiescing/quiesced state */
  895       if ((su->pres == SA_AMF_PRESENCE_INSTANTIATED) ||
  896           (su->pres == SA_AMF_PRESENCE_RESTARTING)) {
  897         rc = avnd_su_pres_fsm_run(cb, su, 0, AVND_SU_PRES_FSM_EV_TERM);
  898         if (NCSCC_RC_SUCCESS != rc) goto done;
  899       } else {
  900         rc = avnd_su_si_oper_done(cb, su, si);
  901         if (NCSCC_RC_SUCCESS != rc) goto done;
  902       }
  903     }
  904   }
  905 
  906 done:
  907   TRACE_LEAVE2("%u", rc);
  908   return rc;
  909 }
  910 /**
  911  * @brief       Checks if any susi operation(assigning or removing) is in
  912  *progress
  913  *
  914  * @param[in]   su
  915  *              si
  916  *
  917  * @return      true/false
  918  **/
  919 static bool susi_operation_in_progress(AVND_SU *su, AVND_SU_SI_REC *si) {
  920   AVND_SU_SI_REC *curr_si, *t_si;
  921   AVND_COMP_CSI_REC *curr_csi, *t_csi;
  922   bool opr_done = true;
  923 
  924   TRACE_ENTER2("'%s' '%s'", su->name.c_str(), si ? si->name.c_str() : nullptr);
  925 
  926   for (curr_si = (si) ? si
  927                       : (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
  928        curr_si && opr_done;
  929        curr_si = (si) ? 0
  930                       : (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(
  931                             &curr_si->su_dll_node)) {
  932     for (curr_csi =
  933              (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&curr_si->csi_list);
  934          curr_csi; curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
  935                        &curr_csi->si_dll_node)) {
  936       if (m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_ASSIGNING(curr_csi) ||
  937           m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_REMOVING(curr_csi)) {
  938         opr_done = false;
  939         break;
  940       } else if (m_AVND_COMP_IS_FAILED(curr_csi->comp)) {
  941         for (t_si =
  942                  (si) ? si
  943                       : (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
  944              t_si; t_si = (si) ? 0
  945                                : (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(
  946                                      &t_si->su_dll_node)) {
  947           for (t_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(
  948                    &t_si->csi_list);
  949                t_csi; t_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
  950                           &t_csi->si_dll_node)) {
  951             if (m_AVND_COMP_IS_FAILED(t_csi->comp) ||
  952                 (su->pres == SA_AMF_PRESENCE_INSTANTIATION_FAILED) ||
  953                 (su->pres == SA_AMF_PRESENCE_TERMINATION_FAILED) ||
  954                 !m_AVND_COMP_IS_REG(t_csi->comp))
  955               continue;
  956             else if (m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_ASSIGNING(t_csi) ||
  957                      m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_REMOVING(t_csi) ||
  958                      m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_UNASSIGNED(t_csi)) {
  959               if (!t_csi->suspending_assignment) {
  960                 opr_done = false;
  961                 break;
  962               }
  963             }
  964           }
  965         }
  966       }
  967     }
  968   }
  969 
  970   // reset suspending_assignment flag if opr_done
  971   if (opr_done) {
  972     for (curr_si =
  973              (si) ? si
  974                   : (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
  975          curr_si; curr_si = (si) ? 0
  976                                  : (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(
  977                                        &curr_si->su_dll_node)) {
  978       for (curr_csi =
  979                (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&curr_si->csi_list);
  980            curr_csi; curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
  981                          &curr_csi->si_dll_node)) {
  982         if (curr_csi->suspending_assignment)
  983           curr_csi->suspending_assignment = false;
  984       }
  985     }
  986   }
  987 
  988   TRACE_LEAVE2("%u", opr_done);
  989   return opr_done;
  990 }
  991 
  992 /**
  993  * Get a higher ranked SI (if any)
  994  * @param si
  995  *
  996  * @return AVND_SU_SI_REC*
  997  */
  998 static AVND_SU_SI_REC *get_higher_ranked_si(const AVND_SU_SI_REC *si) {
  999   AVND_SU_SI_REC *tmp = avnd_silist_getprev(si);
 1000 
 1001   if (tmp) {
 1002     for (; tmp && (tmp->rank == si->rank); tmp = avnd_silist_getprev(tmp))
 1003       ;
 1004   }
 1005 
 1006   return tmp;
 1007 }
 1008 
 1009 /**
 1010  * Are all SIs of the same rank as the passed SI removed/unassigned?
 1011  *
 1012  * @param si
 1013  *
 1014  * @return bool
 1015  */
 1016 static bool all_sis_atrank_removed(const AVND_SU_SI_REC *si) {
 1017   const AVND_SU_SI_REC *tmp;
 1018   osafassert(si != nullptr);
 1019 
 1020   /* search forwards */
 1021   for (tmp = si; tmp && (tmp->rank == si->rank);
 1022        tmp = avnd_silist_getnext(tmp)) {
 1023     if (!m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVED(tmp)) {
 1024       TRACE("%s not removed", tmp->name.c_str());
 1025       return false;
 1026     }
 1027   }
 1028 
 1029   /* search backwards */
 1030   for (tmp = si; tmp && (tmp->rank == si->rank);
 1031        tmp = avnd_silist_getprev(tmp)) {
 1032     if (!m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVED(tmp)) {
 1033       TRACE("%s not removed", tmp->name.c_str());
 1034       return false;
 1035     }
 1036   }
 1037 
 1038   TRACE("all SIs at rank %u removed", si->rank);
 1039   return true;
 1040 }
 1041 
 1042 /**
 1043  * @brief  This function resets surestart escalation or restart admin op params
 1044  *         for a restartable su. For a non restartable SU, it will resume
 1045  * surestart escalation or recovery when assignments are gracefully removed.
 1046  * @param  ptr to su.
 1047  */
 1048 static void su_finish_suRestart_escalation_or_admin_op(AVND_SU *su) {
 1049   TRACE_ENTER2("'%s'", su->name.c_str());
 1050   if ((su_all_comps_restartable(*su) == true) ||
 1051       ((is_any_non_restartable_comp_assigned(*su) == false) &&
 1052        (!m_AVND_SU_IS_FAILED(su)))) {
 1053     bool are_si_assigned;
 1054     TRACE(
 1055         "All the components restartable or non restartable comps are not assigned.");
 1056     m_AVND_SU_ARE_ALL_SI_ASSIGNED(su, are_si_assigned);
 1057     if (true == are_si_assigned) {
 1058       TRACE(
 1059           "All SIs are reassigned after suRestart escalation or admin op,"
 1060           " so resetting the suRestart flag.");
 1061       reset_suRestart_flag(su);
 1062     }
 1063   } else {
 1064     TRACE(
 1065         "SU has atleast one non-restartable (DisbaleRestart = 1) assigned component");
 1066     if (su->si_list.n_nodes > 0) {
 1067       TRACE(
 1068           "Can't resume termination/clean up of components as some of them"
 1069           " still have assignments.");
 1070     } else {
 1071       TRACE(
 1072           "Graceful removal of assignments from components of this"
 1073           " SU completed.");
 1074       if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 1075         TRACE("PI SU");
 1076         if (su->pres == SA_AMF_PRESENCE_TERMINATING) {
 1077           TRACE(
 1078               "PI SU: Resume termination/clean up of component honoring"
 1079               " their instantiation level in reverse order.");
 1080           avnd_su_pres_fsm_run(avnd_cb, su, 0, AVND_SU_PRES_FSM_EV_RESTART);
 1081         }
 1082         if (su->pres == SA_AMF_PRESENCE_UNINSTANTIATED) {
 1083           TRACE("PI SU: Instantiate SU honoring instantiation level");
 1084           m_AVND_SU_FAILED_RESET(su);
 1085           reset_suRestart_flag(su);
 1086           avnd_su_pres_fsm_run(avnd_cb, su, 0, AVND_SU_PRES_FSM_EV_INST);
 1087         }
 1088       } else {
 1089         TRACE("NPI SU");
 1090         m_AVND_SU_FAILED_RESET(su);
 1091         reset_suRestart_flag(su);
 1092         if (su->pres == SA_AMF_PRESENCE_UNINSTANTIATED)
 1093           avnd_di_oper_send(avnd_cb, su, 0);
 1094       }
 1095     }
 1096   }
 1097   TRACE_LEAVE();
 1098 }
 1099 
 1100 static bool container_contained_shutdown(const AVND_SU *su) {
 1101   bool res(false);
 1102 
 1103   if (su->contained()) {
 1104     // see if the associated container is being locked
 1105 
 1106   }
 1107 
 1108   return res;
 1109 }
 1110 
 1111 /****************************************************************************
 1112   Name          : avnd_su_si_oper_done
 1113 
 1114   Description   : This routine is invoked to indicate that the SI state
 1115                   assignment / removal that was pending on a SI is completed.
 1116                   It is generated when all the CSIs are assigned / removed OR
 1117                   when SU FSM transitions to INSTANTIATED / UNINSTANTIATED.
 1118                   AvD is informed that this SU-SI was successfully assigned /
 1119                   removed.
 1120 
 1121   Arguments     : cb - ptr to AvND control block
 1122                   su - ptr to the AvND SU
 1123                   si - ptr to the si record (if 0, it indicates that the
 1124                        assign/remove operation was done for all the SIs
 1125                        belonging to the SU)
 1126 
 1127   Return Values : NCSCC_RC_SUCCESS / NCSCC_RC_FAILURE
 1128 
 1129   Notes         : None
 1130 ******************************************************************************/
 1131 uint32_t avnd_su_si_oper_done(AVND_CB *cb, AVND_SU *su, AVND_SU_SI_REC *si) {
 1132   AVND_SU_SI_REC *curr_si = 0;
 1133   AVND_COMP_CSI_REC *curr_csi = 0, *t_csi = 0;
 1134   uint32_t rc = NCSCC_RC_SUCCESS;
 1135   bool opr_done;
 1136 
 1137   TRACE_ENTER2("'%s' '%s'", su->name.c_str(), si ? si->name.c_str() : nullptr);
 1138 
 1139   /* mark the individual sis after operation is completed for all the SI's */
 1140   opr_done = susi_operation_in_progress(su, si);
 1141 
 1142   for (curr_si = (si) ? si
 1143                       : (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 1144        curr_si; curr_si = (si) ? 0
 1145                                : (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(
 1146                                      &curr_si->su_dll_node)) {
 1147     /* mark the si assigned / removed */
 1148     TRACE("SI '%s'", curr_si->name.c_str());
 1149 
 1150     if (opr_done) {
 1151       if (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_ASSIGNING(curr_si)) {
 1152         m_AVND_SU_SI_CURR_ASSIGN_STATE_SET(curr_si,
 1153                                            AVND_SU_SI_ASSIGN_STATE_ASSIGNED);
 1154         LOG_NO("Assigned '%s' %s to '%s'", curr_si->name.c_str(),
 1155                ha_state[curr_si->curr_state], su->name.c_str());
 1156         if (su->is_ncs) cb->is_ncs_su_assigned = true;
 1157       } else if (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVING(curr_si)) {
 1158         m_AVND_SU_SI_CURR_ASSIGN_STATE_SET(curr_si,
 1159                                            AVND_SU_SI_ASSIGN_STATE_REMOVED);
 1160         LOG_NO("Removed '%s' from '%s'", curr_si->name.c_str(),
 1161                su->name.c_str());
 1162       } else if (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_UNASSIGNED(curr_si) &&
 1163             (cb->term_state == AVND_TERM_STATE_OPENSAF_SHUTDOWN_INITIATED)) {
 1164         m_AVND_SU_SI_CURR_ASSIGN_STATE_SET(curr_si,
 1165                                    AVND_SU_SI_ASSIGN_STATE_REMOVED);
 1166         LOG_NO("Removed '%s' from '%s'", curr_si->name.c_str(),
 1167                su->name.c_str());
 1168       } else {
 1169         LOG_CR("current si name ='%s'", curr_si->name.c_str());
 1170         LOG_CR(
 1171             "SI: curr_assign_state = %u, prv_assign_state = %u, curr_state = %u, prv_state = %u",
 1172             curr_si->curr_assign_state, curr_si->prv_assign_state,
 1173             curr_si->curr_state, curr_si->prv_state);
 1174         osafassert(0);
 1175       }
 1176     }
 1177     /*
 1178      * It is possible that the su fsm for npi su is never triggered (this
 1179      * happens when the si-state change does not lead to su instantition or
 1180      * termination). Mark the corresponding csis assigned/removed.
 1181      */
 1182     if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 1183       TRACE("SU is NPI");
 1184       for (curr_csi =
 1185                (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&curr_si->csi_list);
 1186            curr_csi; curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
 1187                          &curr_csi->si_dll_node)) {
 1188         TRACE("CSI '%s'", curr_csi->name.c_str());
 1189         if (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_ASSIGNED(curr_si)) {
 1190           TRACE("Setting CSI '%s' assigned", curr_csi->name.c_str());
 1191           m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 1192               curr_csi, AVND_COMP_CSI_ASSIGN_STATE_ASSIGNED);
 1193         } else if (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVED(curr_si))
 1194           m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 1195               curr_csi, AVND_COMP_CSI_ASSIGN_STATE_REMOVED);
 1196       }
 1197     }
 1198   } /* for */
 1199 
 1200   /* Inform AMFD when assign are over. During surestart only for non restartable
 1201      SU we need to inform AMFD.*/
 1202   if (opr_done &&
 1203       !container_contained_shutdown(su) &&
 1204       ((!(m_AVND_SU_IS_RESTART(su))) ||
 1205        (m_AVND_SU_IS_RESTART(su) && (su_all_comps_restartable(*su) == false) &&
 1206         (is_any_non_restartable_comp_assigned(*su) == true))) &&
 1207       (is_no_assignment_due_to_escalations(su) == false)) {
 1208     rc = avnd_di_susi_resp_send(cb, su, m_AVND_SU_IS_ALL_SI(su) ? nullptr : si);
 1209     if (NCSCC_RC_SUCCESS != rc) goto done;
 1210   }
 1211 
 1212   if (si && (cb->term_state == AVND_TERM_STATE_OPENSAF_SHUTDOWN_INITIATED)) {
 1213     (void)avnd_evt_last_step_term_evh(cb, nullptr);
 1214   } else if (si &&
 1215              (cb->term_state == AVND_TERM_STATE_OPENSAF_SHUTDOWN_STARTED) &&
 1216              m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVED(si)) {
 1217     if (all_sis_atrank_removed(si)) {
 1218       AVND_SU_SI_REC *tmp = get_higher_ranked_si(si);
 1219 
 1220       if (tmp != nullptr) {
 1221         uint32_t sirank = tmp->rank;
 1222 
 1223         for (; tmp && (tmp->rank == sirank);) {
 1224           AVND_SU_SI_REC *tmp1 = avnd_silist_getprev(tmp);
 1225           uint32_t rc = avnd_su_si_remove(cb, tmp->su, tmp);
 1226           osafassert(rc == NCSCC_RC_SUCCESS);
 1227           tmp = tmp1;
 1228         }
 1229       } else {
 1230         LOG_NO("Removed assignments from AMF components");
 1231         if (m_NCS_NODE_ID_FROM_MDS_DEST(cb->active_avd_adest) != ncs_get_node_id()) {
 1232           avnd_last_step_clean(cb);
 1233         } else {
 1234           avnd_di_node_down_msg_send(cb);
 1235         }
 1236       }
 1237     }
 1238   }
 1239 
 1240   /* Now correct si state if single csi was being removed. For the rest of csi
 1241      assigned, si should be in Assigned state*/
 1242   if ((si) && (AVSV_SUSI_ACT_DEL == si->single_csi_add_rem_in_si) &&
 1243       (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVED(si))) {
 1244     m_AVND_SU_SI_CURR_ASSIGN_STATE_SET(si, AVND_SU_SI_ASSIGN_STATE_ASSIGNED);
 1245     /* Also, we need to remove links of si, csi and comp. */
 1246     /* We have to remove single csi. */
 1247     for (t_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&si->csi_list);
 1248          t_csi; t_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
 1249                     &t_csi->si_dll_node)) {
 1250       if (AVSV_SUSI_ACT_DEL == t_csi->single_csi_add_rem_in_si) {
 1251         break;
 1252       }
 1253     }
 1254     osafassert(t_csi);
 1255     // free the csi attributes
 1256     // AVSV_ATTR_NAME_VAL variables
 1257     // are malloc'ed, use free()
 1258     free(t_csi->attrs.list);
 1259 
 1260     m_AVND_SU_SI_CSI_REC_REM(*si, *t_csi);
 1261     m_AVND_COMPDB_REC_CSI_REM(*(t_csi->comp), *t_csi);
 1262     delete t_csi;
 1263   }
 1264   /* Reset the single add/del */
 1265   if (si) si->single_csi_add_rem_in_si = AVSV_SUSI_ACT_BASE;
 1266 
 1267   /* finally delete the si(s) if they are removed */
 1268   curr_si = (si) ? si : (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 1269   if ((curr_si != nullptr) &&
 1270       m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVED(curr_si)) {
 1271     rc = (si) ? avnd_su_si_rec_del(cb, su->name, si->name)
 1272               : avnd_su_si_del(cb, su->name);
 1273     if (NCSCC_RC_SUCCESS != rc) goto done;
 1274 
 1275     /*
 1276      * Removal signifies an end to the recovery phase. Initiate repair
 1277      * unless a NODE level or su-failover recovery action is in progress.
 1278      * Also repair must be done after informing to AMFD about comp-failover and
 1279      * after removal of assignment.
 1280      */
 1281     if (m_AVND_SU_IS_FAILED(su) && !su->si_list.n_nodes &&
 1282         (!m_AVND_SU_IS_FAILOVER(su)) && (su->sufailover == false) &&
 1283         (cb->oper_state == SA_AMF_OPERATIONAL_ENABLED) &&
 1284         (!m_AVND_SU_IS_RESTART(su)))
 1285       rc = avnd_err_su_repair(cb, su);
 1286   }
 1287 
 1288   if ((nullptr == si) &&
 1289       (cb->term_state == AVND_TERM_STATE_OPENSAF_SHUTDOWN_INITIATED)) {
 1290     (void)avnd_evt_last_step_term_evh(cb, nullptr);
 1291   } else if ((nullptr == si) &&
 1292              (cb->term_state == AVND_TERM_STATE_OPENSAF_SHUTDOWN_STARTED)) {
 1293     AVND_SU_SI_REC *tmp = avnd_silist_getlast();
 1294 
 1295     if (tmp != nullptr) {
 1296       uint32_t sirank = tmp->rank;
 1297 
 1298       for (; tmp && (tmp->rank == sirank);) {
 1299         AVND_SU_SI_REC *tmp1 = avnd_silist_getprev(tmp);
 1300         uint32_t rc = avnd_su_si_remove(cb, tmp->su, tmp);
 1301         osafassert(rc == NCSCC_RC_SUCCESS);
 1302         tmp = tmp1;
 1303       }
 1304     } else {
 1305       LOG_NO("Removed assignments from AMF components");
 1306       if (m_NCS_NODE_ID_FROM_MDS_DEST(cb->active_avd_adest) != ncs_get_node_id()) {
 1307         avnd_last_step_clean(cb);
 1308       } else {
 1309         avnd_di_node_down_msg_send(cb);
 1310       }
 1311     }
 1312   }
 1313 
 1314   /*
 1315    * reset the su-restart flag if all the sis are in assigned
 1316    * state (signifying the end of su-restart phase)
 1317    */
 1318   if (m_AVND_SU_IS_RESTART(su)) {
 1319     TRACE("SU restart due to escalation or admin op going on.");
 1320     su_finish_suRestart_escalation_or_admin_op(su);
 1321   }
 1322   /* finally initiate buffered assignments, if any */
 1323   rc = avnd_su_siq_prc(cb, su);
 1324 
 1325 done:
 1326   TRACE_LEAVE2("%u", rc);
 1327   return rc;
 1328 }
 1329 
 1330 /****************************************************************************
 1331   Name          : avnd_su_si_unmark
 1332 
 1333   Description   : This routine stops the SU-SI assignment & brings the all
 1334                   the SIs (including the corresponding CSIs) to the initial
 1335                   unassigned state.
 1336 
 1337   Arguments     : cb - ptr to the AvND control block
 1338                   su - ptr to the comp
 1339 
 1340   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 1341 
 1342   Notes         : None.
 1343 ******************************************************************************/
 1344 uint32_t avnd_su_si_unmark(AVND_CB *cb, AVND_SU *su) {
 1345   AVND_SU_SI_REC *si = 0;
 1346   uint32_t rc = NCSCC_RC_SUCCESS;
 1347   TRACE_ENTER2("'%s'", su->name.c_str());
 1348 
 1349   /* scan the su-si list & unmark the sis */
 1350   for (si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list); si;
 1351        si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(&si->su_dll_node)) {
 1352     rc = avnd_su_si_rec_unmark(cb, su, si);
 1353     if (NCSCC_RC_SUCCESS != rc) break;
 1354   } /* for */
 1355 
 1356   TRACE_LEAVE();
 1357   return rc;
 1358 }
 1359 
 1360 /****************************************************************************
 1361   Name          : avnd_su_si_rec_unmark
 1362 
 1363   Description   : This routine unmarks a particular SU-SI assignment.
 1364 
 1365   Arguments     : cb - ptr to the AvND control block
 1366                   su - ptr to the comp
 1367                   si - ptr to the si rec
 1368 
 1369   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 1370 
 1371   Notes         : None.
 1372 ******************************************************************************/
 1373 uint32_t avnd_su_si_rec_unmark(AVND_CB *cb, AVND_SU *su, AVND_SU_SI_REC *si) {
 1374   AVND_COMP_CSI_REC *csi = 0;
 1375   uint32_t rc = NCSCC_RC_SUCCESS;
 1376   TRACE_ENTER2("'%s' : '%s'", su->name.c_str(), si->name.c_str());
 1377 
 1378   /* reset the prv state & update the new assign-state */
 1379   si->prv_state = static_cast<SaAmfHAStateT>(0);
 1380   si->prv_assign_state = static_cast<AVND_SU_SI_ASSIGN_STATE>(0);
 1381   m_AVND_SU_SI_CURR_ASSIGN_STATE_SET(si, AVND_SU_SI_ASSIGN_STATE_UNASSIGNED);
 1382   TRACE("Unmarking SU-SI assignment,SU ='%s' : SI=%s", si->su_name.c_str(),
 1383         si->name.c_str());
 1384 
 1385   /* scan the si-csi list & unmark the csis */
 1386   for (csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&si->csi_list); csi;
 1387        csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(&csi->si_dll_node)) {
 1388     csi->prv_assign_state = static_cast<AVND_COMP_CSI_ASSIGN_STATE>(0);
 1389     m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 1390         csi, AVND_COMP_CSI_ASSIGN_STATE_UNASSIGNED);
 1391     TRACE("Unmarking CSI'%s' corresponding to the si'%s'", csi->name.c_str(),
 1392           si->name.c_str());
 1393 
 1394     /* remove any pending callbacks for pi comps */
 1395     if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(csi->comp)) {
 1396       TRACE("Deleting callbacks for the PI component:'%s'",
 1397             csi->comp->name.c_str());
 1398       avnd_comp_cbq_csi_rec_del(cb, csi->comp, csi->name);
 1399     }
 1400   } /* End for */
 1401 
 1402   TRACE_LEAVE();
 1403   return rc;
 1404 }
 1405 
 1406 /***************************************************************************
 1407  ******  S U   P R E S E N C E   F S M   P O R T I O N   S T A R T S  ******
 1408  ***************************************************************************/
 1409 
 1410 /****************************************************************************
 1411   Name          : avnd_evt_avd_su_pres_msg
 1412 
 1413   Description   : This routine processes SU instantiate or terminate trigger
 1414                   as per the wishes of AvD.
 1415 
 1416   Arguments     : cb  - ptr to the AvND control block
 1417                   evt - ptr to the AvND event
 1418 
 1419   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 1420 
 1421   Notes         : None.
 1422 ******************************************************************************/
 1423 uint32_t avnd_evt_avd_su_pres_evh(AVND_CB *cb, AVND_EVT *evt) {
 1424   AVSV_D2N_PRESENCE_SU_MSG_INFO *info = 0;
 1425   AVND_SU *su = 0;
 1426   uint32_t rc = NCSCC_RC_SUCCESS;
 1427 
 1428   TRACE_ENTER();
 1429 
 1430   /* dont process unless AvD is up */
 1431   if (!m_AVND_CB_IS_AVD_UP(cb)) {
 1432     TRACE("AVD is not yet up");
 1433     goto done;
 1434   }
 1435 
 1436   /* since AMFND is going down no need to process SU instantiate/terminate msg
 1437    * because SU instantiate will cause component information to be read from
 1438    * IMMND and IMMND might have been already terminated and in that case AMFND
 1439    * will osafassert */
 1440   if (m_AVND_IS_SHUTTING_DOWN(cb)) {
 1441     TRACE("AMFND is in SHUTDOWN state");
 1442     goto done;
 1443   }
 1444 
 1445   info = &evt->info.avd->msg_info.d2n_prsc_su;
 1446 
 1447   avnd_msgid_assert(info->msg_id);
 1448   cb->rcv_msg_id = info->msg_id;
 1449 
 1450   /* get the su */
 1451   su = avnd_sudb_rec_get(cb->sudb, Amf::to_string(&info->su_name));
 1452   if (!su) {
 1453     TRACE("SU'%s', not found in DB", osaf_extended_name_borrow(&info->su_name));
 1454     goto done;
 1455   }
 1456 
 1457   if (info->term_state) { /* => terminate the su */
 1458     /* Stop saAmfSGSuRestartProb timer if started */
 1459     if (su->su_err_esc_level == AVND_ERR_ESC_LEVEL_1) {
 1460       tmr_su_err_esc_stop(cb, su);
 1461     }
 1462     /* Stop saAmfSGCompRestartProb timer if started */
 1463     else if (su->su_err_esc_level == AVND_ERR_ESC_LEVEL_0) {
 1464       tmr_comp_err_esc_stop(cb, su);
 1465     } else
 1466       TRACE("su_err_esc_tmr is started in wrong su_err_esc_level(%d)",
 1467             su->su_err_esc_level);
 1468 
 1469     TRACE("SU term state is set to true");
 1470     /* no si must be assigned to the su */
 1471     osafassert(!m_NCS_DBLIST_FIND_FIRST(&su->si_list));
 1472 
 1473     /* Mark SU as terminated by admn operation */
 1474     TRACE("Marking SU as terminated by admin operation");
 1475     m_AVND_SU_ADMN_TERM_SET(su);
 1476 
 1477     /* delete all the curr info on su & comp */
 1478     rc = avnd_su_curr_info_del(cb, su);
 1479 
 1480     /* now terminate the su */
 1481     if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 1482       /* trigger su termination for pi su */
 1483       TRACE("SU termination for PI SU, running the SU presence state FSM");
 1484       rc = avnd_su_pres_fsm_run(cb, su, 0, AVND_SU_PRES_FSM_EV_TERM);
 1485       if (NCSCC_RC_SUCCESS != rc) goto done;
 1486     }
 1487   } else { /* => instantiate the su */
 1488     // No need to wait for headless sync if there is no application SUs
 1489     // initiated. This is known because we are receiving su_pres message
 1490     // for NCS SUs
 1491     if (su->is_ncs == true) cb->amfd_sync_required = false;
 1492 
 1493     AVND_EVT *evt_ir = 0;
 1494     TRACE("Sending to Imm thread.");
 1495     evt_ir = avnd_evt_create(cb, AVND_EVT_IR, 0, nullptr, &info->su_name, 0, 0);
 1496     rc = m_NCS_IPC_SEND(&ir_cb.mbx, evt_ir, evt_ir->priority);
 1497     if (NCSCC_RC_SUCCESS != rc)
 1498       LOG_CR("AvND send event to IR mailbox failed, type = %u", evt_ir->type);
 1499     /* if failure, free the event */
 1500     if (NCSCC_RC_SUCCESS != rc && evt_ir) avnd_evt_destroy(evt_ir);
 1501   }
 1502 
 1503 done:
 1504   TRACE_LEAVE2("%u", rc);
 1505   return rc;
 1506 }
 1507 
 1508 /**
 1509  * Check if all components have been terminated in the su.
 1510  * @param su
 1511  * @return bool
 1512  */
 1513 bool all_comps_terminated_in_su(const AVND_SU *su, bool all_final_pres_states) {
 1514   AVND_COMP *comp;
 1515 
 1516   for (comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 1517            m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 1518        comp; comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 1519                  m_NCS_DBLIST_FIND_NEXT(&comp->su_dll_node))) {
 1520     if ((all_final_pres_states == false) &&
 1521         (comp->pres != SA_AMF_PRESENCE_UNINSTANTIATED)) {
 1522       TRACE("'%s' not terminated, pres.st=%u", comp->name.c_str(), comp->pres);
 1523       return false;
 1524     }
 1525     if ((all_final_pres_states == true) &&
 1526         (comp->pres != SA_AMF_PRESENCE_UNINSTANTIATED) &&
 1527         (comp->pres != SA_AMF_PRESENCE_INSTANTIATION_FAILED) &&
 1528         (comp->pres != SA_AMF_PRESENCE_TERMINATION_FAILED)) {
 1529       TRACE("'%s' not terminated, pres.st=%u", comp->name.c_str(), comp->pres);
 1530       return false;
 1531     }
 1532   }
 1533 
 1534   return true;
 1535 }
 1536 
 1537 static void perform_pending_nodeswitchover() {
 1538   bool nodeswitchover = true;
 1539 
 1540   /* Reverify if nodeswitchover is really pending */
 1541   if ((avnd_cb->term_state != AVND_TERM_STATE_NODE_SWITCHOVER_STARTED) ||
 1542       (avnd_cb->oper_state != SA_AMF_OPERATIONAL_DISABLED))
 1543     return;
 1544 
 1545   AVND_COMP *comp;
 1546   AVND_SU *su = avnd_cb->failed_su;
 1547   for (comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 1548            m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 1549        comp; comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 1550                  m_NCS_DBLIST_FIND_NEXT(&comp->su_dll_node))) {
 1551     if ((comp->pres == SA_AMF_PRESENCE_INSTANTIATING) ||
 1552         (comp->pres == SA_AMF_PRESENCE_TERMINATING) ||
 1553         (comp->pres == SA_AMF_PRESENCE_RESTARTING) ||
 1554         (comp->pres == SA_AMF_PRESENCE_TERMINATION_FAILED)) {
 1555       nodeswitchover = false;
 1556       break;
 1557     }
 1558   }
 1559 
 1560   if (nodeswitchover == true) {
 1561     /* Now send nodeswitchover request to AMFD as cleanup of failed component is
 1562        completed in faulted SU.
 1563      */
 1564 
 1565     LOG_NO("Informing director of Nodeswitchover");
 1566     if (su->sufailover == false) {
 1567       uint32_t rc = avnd_di_oper_send(avnd_cb, su, SA_AMF_NODE_SWITCHOVER);
 1568       osafassert(NCSCC_RC_SUCCESS == rc);
 1569       avnd_cb->failed_su = nullptr;
 1570     }
 1571   }
 1572 }
 1573 
 1574 /****************************************************************************
 1575   Name          : avnd_su_pres_fsm_run
 1576 
 1577   Description   : This routine runs the service presence state FSM. It also
 1578                   processes the change in su presence state.
 1579 
 1580   Arguments     : cb   - ptr to the AvND control block
 1581                   su   - ptr to the su
 1582                   comp - ptr to the comp that generated the ev (may be null)
 1583                   ev   - fsm event
 1584 
 1585   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 1586 
 1587   Notes         : None.
 1588 ******************************************************************************/
 1589 uint32_t avnd_su_pres_fsm_run(AVND_CB *cb, AVND_SU *su, AVND_COMP *comp,
 1590                               AVND_SU_PRES_FSM_EV ev) {
 1591   SaAmfPresenceStateT prv_st, final_st;
 1592   uint32_t rc = NCSCC_RC_SUCCESS;
 1593   TRACE_ENTER2("'%s'", su->name.c_str());
 1594 
 1595   /* get the prv presence state */
 1596   prv_st = su->pres;
 1597 
 1598   TRACE_1(
 1599       "Entering SU presence state FSM: current state: %u, event: %u, su name:%s",
 1600       prv_st, ev, su->name.c_str());
 1601 
 1602   /* run the fsm */
 1603   if (0 != avnd_su_pres_fsm[prv_st - 1][ev - 1]) {
 1604     rc = avnd_su_pres_fsm[prv_st - 1][ev - 1](cb, su, comp);
 1605     if (NCSCC_RC_SUCCESS != rc) goto done;
 1606   }
 1607 
 1608   /* get the final presence state */
 1609   final_st = su->pres;
 1610 
 1611   TRACE_1("Exited SU presence state FSM: New State = %u", final_st);
 1612 
 1613   /* TODO: This code related to sufailover handling will be moved to
 1614      avnd_su_pres_st_chng_prc() once NPI SU support is more proper. */
 1615   if (((sufailover_in_progress(su)) ||
 1616        (sufailover_during_nodeswitchover(su))) &&
 1617       (all_comps_terminated_in_su(su))) {
 1618     /* Since all components got successfully terminated, finish sufailover at
 1619        amfnd by deleting SUSIs at amfnd and informing amfd about sufailover.*/
 1620     LOG_NO("Terminated all components in '%s'", su->name.c_str());
 1621     if (cb->term_state == AVND_TERM_STATE_NODE_SWITCHOVER_STARTED) {
 1622       LOG_NO("Informing director of Nodeswitchover");
 1623       rc = avnd_di_oper_send(avnd_cb, su, SA_AMF_NODE_SWITCHOVER);
 1624     } else if (cb->term_state == AVND_TERM_STATE_OPENSAF_SHUTDOWN_INITIATED) {
 1625       AVND_SU_SI_REC *si = 0;
 1626       rc = avnd_su_si_unmark(cb, su);
 1627       if (rc != NCSCC_RC_SUCCESS) goto done;
 1628       rc = avnd_su_si_oper_done(cb, su, m_AVND_SU_IS_ALL_SI(su) ? 0 : si);
 1629     } else {
 1630       LOG_NO("Informing director of sufailover");
 1631       rc = avnd_di_oper_send(avnd_cb, su, AVSV_ERR_RCVR_SU_FAILOVER);
 1632     }
 1633     osafassert(NCSCC_RC_SUCCESS == rc);
 1634     avnd_su_si_del(avnd_cb, su->name);
 1635     if (!m_AVND_SU_IS_PREINSTANTIABLE(su))
 1636       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_UNINSTANTIATED);
 1637     goto done;
 1638   } else if ((cb->term_state == AVND_TERM_STATE_NODE_SWITCHOVER_STARTED) &&
 1639              (cb->oper_state == SA_AMF_OPERATIONAL_DISABLED) &&
 1640              (su->sufailover == false) && (cb->failed_su != nullptr)) {
 1641     perform_pending_nodeswitchover();
 1642   }
 1643 
 1644   /* process state change */
 1645   if (prv_st != final_st)
 1646     rc = avnd_su_pres_st_chng_prc(cb, su, prv_st, final_st);
 1647 
 1648 done:
 1649   TRACE_LEAVE2("%u", rc);
 1650   return rc;
 1651 }
 1652 
 1653 /**
 1654  * @brief  Reset flags when a NPI SU moves from INSTANTIATING/RESTARTING
 1655  *               to INSTANTIATED state.
 1656  * @param  su
 1657  * @return NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 1658  */
 1659 
 1660 static uint32_t npi_su_instantiating_to_instantiated(AVND_SU *su) {
 1661   uint32_t rc = NCSCC_RC_SUCCESS;
 1662   TRACE_ENTER();
 1663 
 1664   if (m_AVND_SU_IS_RESTART(su)) {
 1665     m_AVND_SU_FAILED_RESET(su);
 1666     reset_suRestart_flag(su);
 1667     su->admin_op_Id = static_cast<SaAmfAdminOperationIdT>(0);
 1668   } else {
 1669     AVND_SU_SI_REC *si = 0;
 1670     si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 1671     osafassert(si);
 1672     rc = avnd_su_si_oper_done(avnd_cb, su, m_AVND_SU_IS_ALL_SI(su) ? 0 : si);
 1673     m_AVND_SU_ALL_SI_RESET(su);
 1674     TRACE("SI Assignment succeeded, generating si-oper done indication");
 1675   }
 1676   TRACE_LEAVE2("rc:%d", rc);
 1677   return rc;
 1678 }
 1679 
 1680 /**
 1681  * @brief  Reset flags when a PI SU moves from INSTANTIATING/RESTARTING
 1682  *              to INSTANTIATED state.
 1683  * @param  su
 1684  * @return NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 1685  */
 1686 static uint32_t pi_su_instantiating_to_instantiated(AVND_SU *su) {
 1687   uint32_t rc = NCSCC_RC_SUCCESS;
 1688   TRACE_ENTER();
 1689 
 1690   /* A SU can be restarted because all components faulted with component
 1691      restart recovery policy or because of surestart escalation. */
 1692 
 1693   /* reset the su failed flag */
 1694   if (m_AVND_SU_IS_FAILED(su)) {
 1695     m_AVND_SU_FAILED_RESET(su);
 1696   }
 1697   if (m_AVND_SU_IS_RESTART(su)) {
 1698     /* reset the su failed flag & set the oper state to enabled */
 1699     m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_ENABLED);
 1700     TRACE("Setting the Oper state to Enabled");
 1701     /*
 1702      * reassign all the sis...
 1703      * it's possible that the si was never assigned. send su-oper
 1704      * enable msg instead.
 1705      */
 1706     if (su->si_list.n_nodes)
 1707       rc = avnd_su_si_reassign(avnd_cb, su);
 1708     else {
 1709       rc = avnd_di_oper_send(avnd_cb, su, 0);
 1710       reset_suRestart_flag(su);
 1711     }
 1712     su->admin_op_Id = static_cast<SaAmfAdminOperationIdT>(0);
 1713   } else {
 1714     bool is_en;
 1715     /* determine the su oper state. if enabled, inform avd. */
 1716     m_AVND_SU_IS_ENABLED(su, is_en);
 1717     if (true == is_en) {
 1718       TRACE("SU oper state is enabled");
 1719       m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_ENABLED);
 1720       rc = avnd_di_oper_send(avnd_cb, su, 0);
 1721     } else
 1722       TRACE("SU oper state is disabled");
 1723   }
 1724   TRACE_LEAVE();
 1725   return rc;
 1726 }
 1727 /****************************************************************************
 1728   Name          : avnd_su_pres_st_chng_prc
 1729 
 1730   Description   : This routine processes the change in  the presence state
 1731                   resulting due to running the SU presence state FSM.
 1732 
 1733   Arguments     : cb       - ptr to the AvND control block
 1734                   su       - ptr to the su
 1735                   prv_st   - previous presence state
 1736                   final_st - final presence state
 1737 
 1738   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 1739 
 1740   Notes         : None.
 1741 ******************************************************************************/
 1742 uint32_t avnd_su_pres_st_chng_prc(AVND_CB *cb, AVND_SU *su,
 1743                                   SaAmfPresenceStateT prv_st,
 1744                                   SaAmfPresenceStateT final_st) {
 1745   AVND_SU_SI_REC *si = 0;
 1746   bool is_en;
 1747   uint32_t rc = NCSCC_RC_SUCCESS;
 1748 
 1749   TRACE_ENTER2("'%s' %s => %s", su->name.c_str(), presence_state[prv_st],
 1750                presence_state[final_st]);
 1751 
 1752   /* pi su */
 1753   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 1754     TRACE("PI SU :'%s'", su->name.c_str());
 1755     /* instantiating/restarting -> instantiated */
 1756     if (((SA_AMF_PRESENCE_INSTANTIATING == prv_st) ||
 1757          (SA_AMF_PRESENCE_RESTARTING == prv_st)) &&
 1758         (SA_AMF_PRESENCE_INSTANTIATED == final_st) &&
 1759         (su_all_pi_comps_instantiated(su) == true)) {
 1760       rc = pi_su_instantiating_to_instantiated(su);
 1761       if (NCSCC_RC_SUCCESS != rc) goto done;
 1762     }
 1763     /* terminating -> instantiated */
 1764     if ((SA_AMF_PRESENCE_TERMINATING == prv_st) &&
 1765         (SA_AMF_PRESENCE_INSTANTIATED == final_st)) {
 1766       TRACE("SU Terminating -> Instantiated");
 1767       /* reset the su failed flag */
 1768       if (m_AVND_SU_IS_FAILED(su)) {
 1769         m_AVND_SU_FAILED_RESET(su);
 1770       }
 1771 
 1772       /* determine su oper state. if enabled, inform avd. */
 1773       m_AVND_SU_IS_ENABLED(su, is_en);
 1774       if (true == is_en) {
 1775         TRACE("SU oper state is enabled");
 1776         m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_ENABLED);
 1777         rc = avnd_di_oper_send(cb, su, 0);
 1778         if (NCSCC_RC_SUCCESS != rc) goto done;
 1779       } else
 1780         TRACE("SU oper state is disabled");
 1781     }
 1782 
 1783     /* terminating -> uninstantiated */
 1784     if ((SA_AMF_PRESENCE_TERMINATING == prv_st) &&
 1785         (SA_AMF_PRESENCE_UNINSTANTIATED == final_st)) {
 1786       TRACE("SU Terminating -> Uninstantiated");
 1787       if (sufailover_in_progress(su)) {
 1788         /*Do not reset any flag, this will be done as a part of repair.*/
 1789       } else {
 1790         if (!m_AVND_SU_IS_RESTART(su) && m_AVND_SU_IS_FAILED(su) &&
 1791             (su->si_list.n_nodes == 0)) {
 1792           m_AVND_SU_FAILED_RESET(su);
 1793         }
 1794         if (m_AVND_SU_IS_RESTART(su) &&
 1795             ((su_all_comps_restartable(*su) == true) ||
 1796              ((su_all_comps_restartable(*su) == false) &&
 1797               (is_any_non_restartable_comp_assigned(*su) == false)) ||
 1798              ((m_AVND_SU_IS_FAILOVER(su)) && (su->si_list.n_nodes == 0)))) {
 1799           /*
 1800              It means all comps are terminated in surestart recovery or
 1801              admin op. For non restartable SU with no non restartable comp
 1802              assigned, instantiation of SU will started from here.
 1803              Now instantiate SU honoring instantiation level.
 1804            */
 1805           rc = avnd_su_pres_fsm_run(cb, su, 0, AVND_SU_PRES_FSM_EV_INST);
 1806           if (NCSCC_RC_SUCCESS != rc) goto done;
 1807         }
 1808       }
 1809       goto done;
 1810     }
 1811     /* instantiating -> inst-failed */
 1812     if ((SA_AMF_PRESENCE_INSTANTIATING == prv_st) &&
 1813         (SA_AMF_PRESENCE_INSTANTIATION_FAILED == final_st)) {
 1814       TRACE("SU Instantiating -> Instantiation Failed");
 1815       /* send the su-oper state msg (to indicate that instantiation failed) */
 1816       m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_DISABLED);
 1817       rc = avnd_di_oper_send(cb, su, SA_AMF_COMPONENT_FAILOVER);
 1818       if (NCSCC_RC_SUCCESS != rc) goto done;
 1819     }
 1820 
 1821     /* instantiating -> term-failed */
 1822     if ((SA_AMF_PRESENCE_INSTANTIATING == prv_st) &&
 1823         (SA_AMF_PRESENCE_TERMINATION_FAILED == final_st)) {
 1824       TRACE("SU Instantiating -> Termination Failed");
 1825       m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_DISABLED);
 1826       /* Don't send su-oper state msg, just update su oper state
 1827        * AMF has lost control over this component and the operator needs
 1828        * to repair this node. Failover is not possible in this state. */
 1829       avnd_di_uns32_upd_send(AVSV_SA_AMF_SU, saAmfSUOperState_ID, su->name,
 1830                              su->oper);
 1831     }
 1832 
 1833     /* instantiated/restarting -> inst-failed */
 1834     if (((SA_AMF_PRESENCE_INSTANTIATED == prv_st) ||
 1835          (SA_AMF_PRESENCE_RESTARTING == prv_st)) &&
 1836         (SA_AMF_PRESENCE_INSTANTIATION_FAILED == final_st)) {
 1837       TRACE("SU Instantiated/Restarting -> Instantiation Failed");
 1838 
 1839       /* send the su-oper state msg (to indicate that instantiation failed) */
 1840       if (m_AVND_SU_OPER_STATE_IS_ENABLED(su)) {
 1841         TRACE("SU oper state is enabled");
 1842         m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_DISABLED);
 1843         /*No re-assignments and further escalation happens in INST_FAILED state,
 1844           so reset suRestart flag.*/
 1845         if (isRestartSet(su)) reset_suRestart_flag(su);
 1846         // Ask AMFD to remove assignments.
 1847         rc = avnd_di_oper_send(cb, su, SA_AMF_COMPONENT_FAILOVER);
 1848         if (NCSCC_RC_SUCCESS != rc) goto done;
 1849       } else
 1850         TRACE("SU oper state is disabled");
 1851     }
 1852 
 1853     /* terminating/restarting -> term-failed */
 1854     if (((prv_st == SA_AMF_PRESENCE_RESTARTING) ||
 1855          (SA_AMF_PRESENCE_TERMINATING == prv_st)) &&
 1856         (SA_AMF_PRESENCE_TERMINATION_FAILED == final_st)) {
 1857       TRACE("Terminating/Restarting -> Termination Failed");
 1858       if (sufailover_in_progress(su)) {
 1859         /*Do not reset any flag, this will be done as a part of repair.*/
 1860         rc = avnd_di_oper_send(cb, su, AVSV_ERR_RCVR_SU_FAILOVER);
 1861         osafassert(NCSCC_RC_SUCCESS == rc);
 1862         avnd_su_si_del(avnd_cb, su->name);
 1863         goto done;
 1864       }
 1865       m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_DISABLED);
 1866       /* inform AvD about oper state change, in case prev state was TERMINATING.
 1867          In RESTARTING case, comp FSM triggers comp-failover.*/
 1868       if (prv_st == SA_AMF_PRESENCE_TERMINATING)
 1869         rc = avnd_di_oper_send(cb, su, SA_AMF_COMPONENT_FAILOVER);
 1870       if (NCSCC_RC_SUCCESS != rc) goto done;
 1871     }
 1872     /*instantiated-> term-failed*/
 1873     if ((prv_st == SA_AMF_PRESENCE_INSTANTIATED) &&
 1874         (final_st == SA_AMF_PRESENCE_TERMINATION_FAILED)) {
 1875       TRACE("Instantiated -> Termination Failed");
 1876       /*
 1877          This state transition of SU can happen when:
 1878          -its one NPI comp moves to TERM_FAILED state. There can
 1879           be two subcases here: a)assigned NPI comp faults or b)it
 1880           faults during fresh assignments during instantiation phase.
 1881          -its restartable PI comp moves to TERM_FAILED state. There
 1882           can be two subcases here:a)assigned PI comp fault or b)
 1883           it faults during fresh assignments in CSI SET callback.
 1884          In these cases SU moves directly from INSTANTIATED to TERM_FAILED
 1885          state.
 1886 
 1887          AMFND should respond to AMFD for su-failover only when SU moves
 1888          to TERM_FAILED state during fresh assignments.
 1889        */
 1890       if ((su->si_list.n_nodes != 0) && (m_AVND_SU_IS_ASSIGN_PEND(su)) &&
 1891           (su->avnd_su_check_sis_previous_assign_state(
 1892                AVND_SU_SI_ASSIGN_STATE_UNASSIGNED) == true)) {
 1893         m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_DISABLED);
 1894         if (all_comps_terminated_in_su(su, true) == true) {
 1895           TRACE_2("Informing AMFD of su-failover");
 1896           rc = avnd_di_oper_send(cb, su, AVSV_ERR_RCVR_SU_FAILOVER);
 1897           avnd_su_si_del(avnd_cb, su->name);
 1898         } else {
 1899           // Some PI comps are still terminating. Try to terminate NPIs.
 1900           for (AVND_COMP *comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 1901                    m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 1902                comp; comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 1903                          m_NCS_DBLIST_FIND_NEXT(&comp->su_dll_node))) {
 1904             if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(comp)) continue;
 1905             rc = avnd_comp_clc_fsm_trigger(cb, comp,
 1906                                            AVND_COMP_CLC_PRES_FSM_EV_TERM);
 1907             if (NCSCC_RC_SUCCESS != rc) {
 1908               LOG_ER("'%s' termination failed", comp->name.c_str());
 1909               goto done;
 1910             }
 1911           }
 1912         }
 1913       }
 1914     }
 1915   }
 1916 
 1917   /* npi su */
 1918   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 1919     TRACE("NPI SU :'%s'", su->name.c_str());
 1920     /* get the only si */
 1921     si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 1922     osafassert(si);
 1923 
 1924     /* instantiating/restarting -> instantiated */
 1925     if (((SA_AMF_PRESENCE_INSTANTIATING == prv_st) ||
 1926          (SA_AMF_PRESENCE_RESTARTING == prv_st)) &&
 1927         (SA_AMF_PRESENCE_INSTANTIATED == final_st) &&
 1928         (all_csis_in_assigned_state(su) == true)) {
 1929       rc = npi_su_instantiating_to_instantiated(su);
 1930     }
 1931     /* instantiating/instantiated/restarting -> inst-failed */
 1932     if (((SA_AMF_PRESENCE_INSTANTIATING == prv_st) ||
 1933          (SA_AMF_PRESENCE_INSTANTIATED == prv_st)) &&
 1934         (SA_AMF_PRESENCE_INSTANTIATION_FAILED == final_st)) {
 1935       TRACE("SU Instantiating/Instantiated -> Instantiation Failed");
 1936       /*SU may fail with INST_FAILED state as a part of recovery
 1937         like comp-restart and su-restart. Inform AMFD if
 1938         assignments are pending from AMFD.*/
 1939       if (m_AVND_SU_IS_ASSIGN_PEND(su)) {
 1940         TRACE("SI-Assignment failed, Informing AVD");
 1941         rc = avnd_di_susi_resp_send(cb, su, si);
 1942         if (NCSCC_RC_SUCCESS != rc) goto done;
 1943       }
 1944 
 1945       /* mark su as failed */
 1946       m_AVND_SU_FAILED_SET(su);
 1947 
 1948       /* npi su is disabled in inst-fail state */
 1949       m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_DISABLED);
 1950 
 1951       /*No re-assignments and further escalation happens in INST_FAILED state,
 1952         so reset suRestart flag.*/
 1953       if (isRestartSet(su)) reset_suRestart_flag(su);
 1954       // Ask AMFD to remove assignments.
 1955       rc = avnd_di_oper_send(cb, su, SA_AMF_COMPONENT_FAILOVER);
 1956       if (cb->is_avd_down == true) {
 1957         LOG_WA("Director is down. Remove all SIs from '%s'", su->name.c_str());
 1958         avnd_su_si_del(avnd_cb, su->name);
 1959       }
 1960     }
 1961     if ((SA_AMF_PRESENCE_RESTARTING == prv_st) &&
 1962         (SA_AMF_PRESENCE_INSTANTIATION_FAILED == final_st)) {
 1963       TRACE("Restarting -> Instantiation Failed");
 1964       if (sufailover_in_progress(su)) {
 1965         /*Do not reset any flag, this will be done as a part of repair.*/
 1966         rc = avnd_di_oper_send(cb, su, AVSV_ERR_RCVR_SU_FAILOVER);
 1967         osafassert(NCSCC_RC_SUCCESS == rc);
 1968         avnd_su_si_del(avnd_cb, su->name);
 1969         goto done;
 1970       }
 1971     }
 1972 
 1973     /* terminating -> uninstantiated */
 1974     if ((SA_AMF_PRESENCE_TERMINATING == prv_st) &&
 1975         (SA_AMF_PRESENCE_UNINSTANTIATED == final_st)) {
 1976       TRACE("Terminating -> UnInstantiated");
 1977       if (sufailover_in_progress(su)) {
 1978         /*Do not reset any flag, this will be done as a part of repair.*/
 1979       } else {
 1980         if (m_AVND_SU_IS_RESTART(su) &&
 1981             (su_all_comps_restartable(*su) == true)) {
 1982           /* npi su is enabled in uninstantiated state */
 1983           m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_ENABLED);
 1984           /*
 1985              It means all comps are terminated in surestart recovery or admin
 1986              op. Now instantiate SU honoring instantiation level.
 1987            */
 1988           rc = avnd_su_pres_fsm_run(cb, su, 0, AVND_SU_PRES_FSM_EV_INST);
 1989           if (NCSCC_RC_SUCCESS != rc) goto done;
 1990         } else {
 1991           if (m_AVND_SU_IS_FAILED(su)) m_AVND_SU_FAILED_RESET(su);
 1992 
 1993           /* si assignment/removal success.. generate si-oper done indication */
 1994           rc = avnd_su_si_oper_done(cb, su, m_AVND_SU_IS_ALL_SI(su) ? 0 : si);
 1995           m_AVND_SU_ALL_SI_RESET(su);
 1996 
 1997           /* npi su is enabled in uninstantiated state */
 1998           m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_ENABLED);
 1999         }
 2000 
 2001         /* A NPI SU becomes uninstantiated, send SU oper state enabled event
 2002            to AMFD if removal of assignments is also done.*/
 2003         if (su->si_list.n_nodes == 0) {
 2004           rc = avnd_di_oper_send(cb, su, 0);
 2005         }
 2006       }
 2007     }
 2008 
 2009     /* terminating/instantiated/restarting -> term-failed */
 2010     if (((SA_AMF_PRESENCE_TERMINATING == prv_st) ||
 2011          (SA_AMF_PRESENCE_INSTANTIATED == prv_st) ||
 2012          (SA_AMF_PRESENCE_RESTARTING == prv_st)) &&
 2013         (SA_AMF_PRESENCE_TERMINATION_FAILED == final_st)) {
 2014       TRACE("Terminating/Instantiated/Restarting -> Termination Failed");
 2015       if (sufailover_in_progress(su)) {
 2016         /*Do not reset any flag, this will be done as a part of repair.*/
 2017         rc = avnd_di_oper_send(cb, su, AVSV_ERR_RCVR_SU_FAILOVER);
 2018         osafassert(NCSCC_RC_SUCCESS == rc);
 2019         avnd_su_si_del(avnd_cb, su->name);
 2020         goto done;
 2021       }
 2022       m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_DISABLED);
 2023       /* inform AvD about oper state change */
 2024       rc = avnd_di_oper_send(cb, su, SA_AMF_COMPONENT_FAILOVER);
 2025 
 2026       /* si assignment/removal failed.. inform AvD */
 2027       /* Send response to Amfd only when there is a pending assignment. */
 2028       if (m_AVND_SU_IS_ASSIGN_PEND(su))
 2029         rc = avnd_di_susi_resp_send(cb, su, m_AVND_SU_IS_ALL_SI(su) ? 0 : si);
 2030       /*
 2031          During shutdown phase, all comps of NPI SU are terminated as a part of
 2032          removal of assignments. If a SU enters in TERM_FAILED state then in
 2033          order to complete shutdown sequence generate a si-oper done indication.
 2034        */
 2035       if ((si != nullptr) && (m_AVND_IS_SHUTTING_DOWN(cb)) &&
 2036           (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVING(si)) &&
 2037           (all_comps_terminated_in_su(su, true) == true)) {
 2038         rc = avnd_su_si_oper_done(cb, su, si);
 2039       }
 2040     }
 2041 
 2042     /* instantiating -> term-failed */
 2043     if ((prv_st == SA_AMF_PRESENCE_INSTANTIATING) &&
 2044         (final_st == SA_AMF_PRESENCE_TERMINATION_FAILED)) {
 2045       m_AVND_SU_OPER_STATE_SET(su, SA_AMF_OPERATIONAL_DISABLED);
 2046 
 2047       /* Don't send su-oper state msg, just update su oper state
 2048        * AMF has lost control over this component and the operator needs
 2049        * to repair this node. Failover is not possible in this state.
 2050        *
 2051        * There exists one case which is not related to fail-over situation
 2052        * and related to fresh assignments in SU. When AMFD sends fresh
 2053        * assignments for a SU to AMFND, a SU can go into term-failed state
 2054        * during instantiation. In TERM-FAILED state, AMFND cleans up all the
 2055        * comps of SU. So AMFND can send su-oper state message so that AMFD can
 2056        * mark SG stable and make way for admin repair.
 2057        */
 2058       if ((si != nullptr) &&
 2059           (si->prv_assign_state == AVND_SU_SI_ASSIGN_STATE_UNASSIGNED)) {
 2060         rc = avnd_di_oper_send(cb, su, AVSV_ERR_RCVR_SU_FAILOVER);
 2061         avnd_su_si_del(avnd_cb, su->name);
 2062       } else {
 2063         avnd_di_uns32_upd_send(AVSV_SA_AMF_SU, saAmfSUOperState_ID, su->name,
 2064                                su->oper);
 2065       }
 2066     }
 2067 
 2068     if ((prv_st == SA_AMF_PRESENCE_INSTANTIATED) &&
 2069         (final_st == SA_AMF_PRESENCE_UNINSTANTIATED) &&
 2070         (cb->term_state == AVND_TERM_STATE_OPENSAF_SHUTDOWN_STARTED)) {
 2071       /*
 2072          During shutdown phase, all comps of SU may fault. In that case,
 2073          SU FSM marks SU in TERMINAIING state and finally moves it to
 2074          UNINSTANTIATED state. So generated the assignment done indication
 2075          so that removal of lower rank SI can proceed.
 2076        */
 2077       rc = avnd_su_si_oper_done(cb, su, si);
 2078       m_AVND_SU_ALL_SI_RESET(su);
 2079     }
 2080   }
 2081 
 2082 done:
 2083   TRACE_LEAVE2("%u", rc);
 2084   return rc;
 2085 }
 2086 
 2087 /****************************************************************************
 2088   Name          : avnd_su_pres_uninst_suinst_hdler
 2089 
 2090   Description   : This routine processes the `SU Instantiate` event in
 2091                   `Uninstantiated` state. For PI SU, this event is generated
 2092                   when SU is to be instantiated. For NPI SU, this event is
 2093                   generated when an active SI has to be assigned.
 2094 
 2095   Arguments     : cb   - ptr to the AvND control block
 2096                   su   - ptr to the su
 2097                   comp - ptr to the comp (can be nullptr)
 2098 
 2099   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 2100 
 2101   Notes         : None.
 2102 ******************************************************************************/
 2103 uint32_t avnd_su_pres_uninst_suinst_hdler(AVND_CB *cb, AVND_SU *su,
 2104                                           AVND_COMP *comp) {
 2105   AVND_COMP *curr_comp = 0;
 2106   AVND_SU_SI_REC *si = 0;
 2107   AVND_COMP_CSI_REC *csi = 0;
 2108   uint32_t rc = NCSCC_RC_SUCCESS;
 2109   TRACE_ENTER2("SU Instantiate event in the Uninstantiated state: '%s'",
 2110                su->name.c_str());
 2111 
 2112   /*
 2113    * If pi su, pick the first pi comp & trigger it's FSM with InstEv.
 2114    */
 2115   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2116     TRACE("PI SU:'%s'", su->name.c_str());
 2117     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2118              m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 2119          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2120                         m_NCS_DBLIST_FIND_NEXT(&curr_comp->su_dll_node))) {
 2121       /* instantiate the pi comp */
 2122       TRACE("%s", curr_comp->name.c_str());
 2123       if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp) &&
 2124           (curr_comp->pres == SA_AMF_PRESENCE_UNINSTANTIATED)) {
 2125         if (curr_comp->contained()) {
 2126           AVND_COMP *container(
 2127             avnd_get_comp_from_csi(cb, curr_comp->saAmfCompContainerCsi));
 2128 
 2129           if (container) {
 2130             // call the contained instantiate callback
 2131             rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 2132                                        AVND_COMP_CLC_PRES_FSM_EV_INST);
 2133             if (rc != NCSCC_RC_SUCCESS) {
 2134               LOG_ER("failed to start contained fsm: %s",
 2135                      curr_comp->name.c_str());
 2136               goto done;
 2137             }
 2138             break;
 2139           } else {
 2140             TRACE("no active container available; not instantiating contained");
 2141             goto done;
 2142           }
 2143         } else {
 2144           TRACE("Running the component CLC FSM ");
 2145           rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 2146                                      AVND_COMP_CLC_PRES_FSM_EV_INST);
 2147           if (NCSCC_RC_SUCCESS != rc) goto done;
 2148           break;
 2149         }
 2150       }
 2151     } /* for */
 2152   }
 2153 
 2154   /*
 2155    * If npi su, it'll have only one si-rec in the si-list. Pick the
 2156    * lowest ranked csi belonging to this si & trigger it's comp fsm.
 2157    */
 2158   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2159     TRACE("NPI SU:'%s'", su->name.c_str());
 2160     /* get the only si rec */
 2161     si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 2162     osafassert(si);
 2163 
 2164     csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&si->csi_list);
 2165     if (csi) {
 2166       /* mark the csi state assigning */
 2167       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 2168           csi, AVND_COMP_CSI_ASSIGN_STATE_ASSIGNING);
 2169 
 2170       TRACE("Running the component CLC FSM ");
 2171       /* instantiate the comp */
 2172       rc = avnd_comp_clc_fsm_run(cb, csi->comp, AVND_COMP_CLC_PRES_FSM_EV_INST);
 2173       if (NCSCC_RC_SUCCESS != rc) goto done;
 2174     }
 2175   }
 2176 
 2177   /* transition to instantiating state */
 2178   avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATING);
 2179 
 2180 done:
 2181   if (rc == NCSCC_RC_FAILURE)
 2182     avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATION_FAILED);
 2183   TRACE_LEAVE2("%u", rc);
 2184   return rc;
 2185 }
 2186 
 2187 /****************************************************************************
 2188   Name          : avnd_su_pres_insting_suterm_hdler
 2189 
 2190   Description   : This routine processes the `SU Terminate` event in
 2191                   `Instantiating` state.
 2192 
 2193   Arguments     : cb   - ptr to the AvND control block
 2194                   su   - ptr to the su
 2195                   comp - ptr to the comp (can be nullptr)
 2196 
 2197   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 2198 
 2199   Notes         : Note that this event is only generated for PI SUs. SUTermEv
 2200                   is generated for NPI SUs only during stable states i.e.
 2201                   uninstantiated & instantiated states. This is done by
 2202                   avoiding overlapping SI assignments.
 2203 ******************************************************************************/
 2204 uint32_t avnd_su_pres_insting_suterm_hdler(AVND_CB *cb, AVND_SU *su,
 2205                                            AVND_COMP *comp) {
 2206   AVND_COMP *curr_comp = 0;
 2207   uint32_t rc = NCSCC_RC_SUCCESS;
 2208   TRACE_ENTER2("SU Terminate event in Instantiating state:'%s'",
 2209                su->name.c_str());
 2210 
 2211   /*
 2212    * If pi su, pick all the instantiated/instantiating pi comps &
 2213    * trigger their FSM with TermEv.
 2214    */
 2215   for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2216            m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 2217        curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2218                       m_NCS_DBLIST_FIND_NEXT(&curr_comp->su_dll_node))) {
 2219     /*
 2220      * skip the npi comps.. as the su is yet to be instantiated,
 2221      * there are no SIs assigned.
 2222      */
 2223     if (!m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) continue;
 2224 
 2225     /* terminate the non-uninstantiated pi comp */
 2226     if (!m_AVND_COMP_PRES_STATE_IS_UNINSTANTIATED(curr_comp)) {
 2227       TRACE("Running the component clc FSM");
 2228       rc = avnd_comp_clc_fsm_run(cb, curr_comp, AVND_COMP_CLC_PRES_FSM_EV_TERM);
 2229       if (NCSCC_RC_SUCCESS != rc) goto done;
 2230     }
 2231   } /* for */
 2232 
 2233   /* transition to terminating state */
 2234   avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_TERMINATING);
 2235 
 2236 done:
 2237   TRACE_LEAVE2("%u", rc);
 2238   return rc;
 2239 }
 2240 
 2241 /****************************************************************************
 2242   Name          : avnd_su_pres_insting_surestart_hdler
 2243 
 2244   Description   : This routine processes the `SU Restart` event in
 2245                   `Instantiating` state.
 2246 
 2247   Arguments     : cb   - ptr to the AvND control block
 2248                   su   - ptr to the su
 2249                   comp - ptr to the comp (can be nullptr)
 2250 
 2251   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 2252 
 2253   Notes         : None.
 2254 ******************************************************************************/
 2255 uint32_t avnd_su_pres_insting_surestart_hdler(AVND_CB *cb, AVND_SU *su,
 2256                                               AVND_COMP *comp) { /* TBD */
 2257   uint32_t rc = NCSCC_RC_SUCCESS;
 2258   TRACE("SU Restart event in the Instantiating State, returning success:'%s'",
 2259         su->name.c_str());
 2260   return rc;
 2261 }
 2262 
 2263 /****************************************************************************
 2264   Name          : avnd_su_pres_insting_compinst_hdler
 2265 
 2266   Description   : This routine processes the `CompInstantiated` event in
 2267                   `Instantiating` state.
 2268 
 2269   Arguments     : cb   - ptr to the AvND control block
 2270                   su   - ptr to the su
 2271                   comp - ptr to the comp (can be nullptr)
 2272 
 2273   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 2274 
 2275   Notes         : None.
 2276 ******************************************************************************/
 2277 uint32_t avnd_su_pres_insting_compinst_hdler(AVND_CB *cb, AVND_SU *su,
 2278                                              AVND_COMP *comp) {
 2279   AVND_COMP *curr_comp = 0;
 2280   AVND_COMP_CSI_REC *curr_csi = 0;
 2281   bool is;
 2282   uint32_t rc = NCSCC_RC_SUCCESS;
 2283   const std::string compname = comp ? comp->name : "none";
 2284   TRACE_ENTER2(
 2285       "Component Instantiated event in the Instantiating state:'%s' : '%s'",
 2286       su->name.c_str(), compname.c_str());
 2287 
 2288   osafassert(comp != nullptr);
 2289 
 2290   /*
 2291    * If pi su, pick the next pi comp & trigger it's FSM with InstEv.
 2292    * If the component is marked failed (=> component has reinstantiated
 2293    * after some failure), unmark it & determine the su presence state.
 2294    */
 2295   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2296     TRACE("PI SU");
 2297     if (m_AVND_COMP_IS_FAILED(comp)) {
 2298       m_AVND_COMP_FAILED_RESET(comp);
 2299     } else {
 2300       for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2301                m_NCS_DBLIST_FIND_NEXT(&comp->su_dll_node));
 2302            curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2303                           m_NCS_DBLIST_FIND_NEXT(&curr_comp->su_dll_node))) {
 2304         /* instantiate the pi comp */
 2305         if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp) &&
 2306            (!m_AVND_COMP_IS_FAILED(curr_comp) ||
 2307             curr_comp->pres != SA_AMF_PRESENCE_RESTARTING)) {
 2308           TRACE("Running the component clc FSM");
 2309           rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 2310                                      AVND_COMP_CLC_PRES_FSM_EV_INST);
 2311           if (NCSCC_RC_SUCCESS != rc) goto done;
 2312           break;
 2313         }
 2314       } /* for */
 2315     }
 2316 
 2317     /* determine su presence state */
 2318     m_AVND_SU_IS_INSTANTIATED(su, is);
 2319     if (true == is) {
 2320       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATED);
 2321     }
 2322   }
 2323 
 2324   /*
 2325    * If npi su, pick the next csi & trigger it's comp fsm with InstEv.
 2326    */
 2327   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2328     TRACE("NPI SU");
 2329     /* get the only csi rec */
 2330     curr_csi = m_AVND_CSI_REC_FROM_COMP_DLL_NODE_GET(
 2331         m_NCS_DBLIST_FIND_FIRST(&comp->csi_list));
 2332     osafassert(curr_csi);
 2333 
 2334     /* mark the csi state assigned */
 2335     m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(curr_csi,
 2336                                           AVND_COMP_CSI_ASSIGN_STATE_ASSIGNED);
 2337 
 2338     if (curr_csi->single_csi_add_rem_in_si == AVSV_SUSI_ACT_ASGN) {
 2339       // we are adding a single CSI, the comp is instantiated so now we're done
 2340       curr_csi->single_csi_add_rem_in_si = AVSV_SUSI_ACT_BASE;
 2341       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATED);
 2342       goto done;
 2343     }
 2344 
 2345     /* get the next csi */
 2346     curr_csi =
 2347         (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(&curr_csi->si_dll_node);
 2348     if (curr_csi) {
 2349       /* we have another csi. trigger the comp fsm with InstEv */
 2350       TRACE(
 2351           "There's another CSI:'%s', Running the component clc FSM for comp:'%s'",
 2352           curr_csi->name.c_str(), curr_csi->comp->name.c_str());
 2353       rc = avnd_comp_clc_fsm_trigger(cb, curr_csi->comp,
 2354                                      AVND_COMP_CLC_PRES_FSM_EV_INST);
 2355       if (NCSCC_RC_SUCCESS != rc) goto done;
 2356     } else {
 2357       /* => si assignment done */
 2358       TRACE("SI Assignment done");
 2359       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATED);
 2360     }
 2361   }
 2362 
 2363 done:
 2364   TRACE_LEAVE2("%u", rc);
 2365   return rc;
 2366 }
 2367 
 2368 /****************************************************************************
 2369   Name          : avnd_su_pres_insting_compinstfail_hdler
 2370 
 2371   Description   : This routine processes the `CompInstantiateFailed` event in
 2372                   `Instantiating` state.
 2373                   For PI SU, a failure in the instantiation of any component
 2374                   means that SU instantiation has failed. Terminate all the
 2375                   already instantiated (or instantiating) components &
 2376                   transition to inst-failed state.
 2377                   For NPI SU, a failure in the instantiation of any component
 2378                   indicates that active SI assignment to this SU has failed.
 2379                   Terminate all the components to whom the active CSI has
 2380                   already been assigned (or assigning).
 2381 
 2382   Arguments     : cb   - ptr to the AvND control block
 2383                   su   - ptr to the su
 2384                   comp - ptr to the comp (can be nullptr)
 2385 
 2386   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 2387 
 2388   Notes         : None.
 2389 ******************************************************************************/
 2390 uint32_t avnd_su_pres_insting_compinstfail_hdler(AVND_CB *cb, AVND_SU *su,
 2391                                                  AVND_COMP *comp) {
 2392   AVND_COMP *curr_comp = 0;
 2393   AVND_SU_SI_REC *si = 0;
 2394   AVND_COMP_CSI_REC *curr_csi = 0;
 2395   uint32_t rc = NCSCC_RC_SUCCESS, comp_count = 0;
 2396   const std::string compname = comp ? comp->name : "none";
 2397   TRACE_ENTER2(
 2398       "CompInstantiateFailed event in the Instantiate State: '%s' : '%s'",
 2399       su->name.c_str(), compname.c_str());
 2400 
 2401   /* transition to inst-failed state */
 2402   avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATION_FAILED);
 2403   m_AVND_SU_ALL_TERM_RESET(su);
 2404 
 2405   /*
 2406    * If pi su, pick all the instantiated/instantiating pi comps &
 2407    * trigger their FSM with TermEv.
 2408    */
 2409   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2410     TRACE("PI SU:'%s'", su->name.c_str());
 2411     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2412              m_NCS_DBLIST_FIND_LAST(&su->comp_list));
 2413          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2414                         m_NCS_DBLIST_FIND_PREV(&curr_comp->su_dll_node))) {
 2415       /* skip the npi comps */
 2416       if (!m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) continue;
 2417 
 2418       /* terminate the non-uninstantiated pi comp */
 2419       if (!m_AVND_COMP_PRES_STATE_IS_UNINSTANTIATED(curr_comp)) {
 2420         TRACE("Running the component clc FSM");
 2421         rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 2422                                    AVND_COMP_CLC_PRES_FSM_EV_TERM);
 2423         if (NCSCC_RC_SUCCESS != rc) goto done;
 2424         comp_count++;
 2425       }
 2426     } /* for */
 2427     if (comp_count == 1) {
 2428       /* If all comps are terminated then set term state and
 2429          process the SUSI assignment.*/
 2430       m_AVND_SU_ALL_TERM_SET(su);
 2431       avnd_su_siq_prc(cb, su);
 2432     }
 2433   }
 2434 
 2435   /*
 2436    * If npi su, pick all the assigned/assigning comps &
 2437    * trigger their comp fsm with TermEv
 2438    */
 2439   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2440     TRACE("NPI SU:'%s'", su->name.c_str());
 2441     /* get the only si rec */
 2442     si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 2443     osafassert(si);
 2444 
 2445     for (curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_LAST(&si->csi_list);
 2446          curr_csi; curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_PREV(
 2447                        &curr_csi->si_dll_node)) {
 2448       /* terminate the component containing non-unassigned csi */
 2449       if (!m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_UNASSIGNED(curr_csi) &&
 2450           (curr_csi->comp->pres != SA_AMF_PRESENCE_INSTANTIATION_FAILED)) {
 2451         TRACE("Running the component clc FSM");
 2452         rc = avnd_comp_clc_fsm_run(cb, curr_csi->comp,
 2453                                    AVND_COMP_CLC_PRES_FSM_EV_TERM);
 2454         if (NCSCC_RC_SUCCESS != rc) goto done;
 2455       }
 2456     } /* for */
 2457     m_AVND_SU_ALL_TERM_SET(su);
 2458   }
 2459 
 2460 done:
 2461   TRACE_LEAVE2("%u", rc);
 2462   return rc;
 2463 }
 2464 
 2465 /**
 2466  * @brief  Returns first assigned csi traversing from end.
 2467  * @return Ptr to csi_rec.
 2468  */
 2469 static AVND_COMP_CSI_REC *get_next_assigned_csi_from_end(
 2470     const AVND_SU_SI_REC *si) {
 2471   for (AVND_COMP_CSI_REC *csi =
 2472            (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_LAST(&si->csi_list);
 2473        (csi != nullptr);
 2474        csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_PREV(&csi->si_dll_node)) {
 2475     if (m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_ASSIGNED(csi) &&
 2476         ((csi->comp != nullptr) &&
 2477          (csi->comp->pres == SA_AMF_PRESENCE_INSTANTIATED)))
 2478       return csi;
 2479   }
 2480   return nullptr;
 2481 }
 2482 /****************************************************************************
 2483   Name          : avnd_su_pres_inst_suterm_hdler
 2484 
 2485   Description   : This routine processes the `SU Terminate` event in
 2486                   `Instantiated` state.
 2487 
 2488   Arguments     : cb   - ptr to the AvND control block
 2489                   su   - ptr to the su
 2490                   comp - ptr to the comp (can be nullptr)
 2491 
 2492   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 2493 
 2494   Notes         : None.
 2495 ******************************************************************************/
 2496 uint32_t avnd_su_pres_inst_suterm_hdler(AVND_CB *cb, AVND_SU *su,
 2497                                         AVND_COMP *comp) {
 2498   AVND_COMP *curr_comp = 0;
 2499   AVND_SU_SI_REC *si = 0;
 2500   AVND_COMP_CSI_REC *csi = 0;
 2501   uint32_t rc = NCSCC_RC_SUCCESS;
 2502   TRACE_ENTER2("SUTerminate event in the Instantiated state: '%s'",
 2503                su->name.c_str());
 2504 
 2505   /*
 2506    * If pi su, pick the last pi comp & trigger it's FSM with TermEv.
 2507    */
 2508   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2509     TRACE("PI SU:'%s'", su->name.c_str());
 2510     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2511              m_NCS_DBLIST_FIND_LAST(&su->comp_list));
 2512          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2513                         m_NCS_DBLIST_FIND_PREV(&curr_comp->su_dll_node))) {
 2514       if (curr_comp->pres == SA_AMF_PRESENCE_UNINSTANTIATED) continue;
 2515 
 2516       /* terminate the pi comp */
 2517       if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) {
 2518         TRACE("Running the component clc FSM, terminate the component");
 2519         rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 2520                                    AVND_COMP_CLC_PRES_FSM_EV_TERM);
 2521         if (NCSCC_RC_SUCCESS != rc) goto done;
 2522         break;
 2523       }
 2524     } /* for */
 2525   }
 2526 
 2527   /*
 2528    * If npi su, it'll have only one si-rec in the si-list. Pick the
 2529    * highest ranked csi belonging to this si & trigger it's comp fsm.
 2530    */
 2531   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2532     TRACE("NPI SU:'%s'", su->name.c_str());
 2533     /* get the only si rec */
 2534     si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 2535     osafassert(si);
 2536     csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_LAST(&si->csi_list);
 2537     osafassert(csi);
 2538 
 2539     /* mark the csi state assigning/removing */
 2540     if (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVING(si))
 2541       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 2542           csi, AVND_COMP_CSI_ASSIGN_STATE_REMOVING);
 2543     else
 2544       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 2545           csi, AVND_COMP_CSI_ASSIGN_STATE_ASSIGNING);
 2546 
 2547     TRACE("Running the component clc FSM, terminate the component");
 2548     /* terminate the comp */
 2549     rc = avnd_comp_clc_fsm_run(cb, csi->comp,
 2550                                (m_AVND_COMP_IS_FAILED(csi->comp))
 2551                                    ? AVND_COMP_CLC_PRES_FSM_EV_CLEANUP
 2552                                    : AVND_COMP_CLC_PRES_FSM_EV_TERM);
 2553     if (NCSCC_RC_SUCCESS != rc) goto done;
 2554 
 2555     /*
 2556        During shutdown phase if a component faults, it will be cleaned up by
 2557        AMFND irrespective of recovery policy. This component will move to
 2558        UNINSTANTIATED after successful clean up. When amfnd starts removing SI
 2559        from SU of this comp, it will have to skip the CSI of cleaned up
 2560        component.
 2561     */
 2562     if ((csi->comp->pres == SA_AMF_PRESENCE_UNINSTANTIATED) &&
 2563         (cb->term_state == AVND_TERM_STATE_OPENSAF_SHUTDOWN_STARTED)) {
 2564       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(csi,
 2565                                             AVND_COMP_CSI_ASSIGN_STATE_REMOVED);
 2566       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_TERMINATING);
 2567       AVND_COMP_CSI_REC *assigned_csi = get_next_assigned_csi_from_end(si);
 2568       if (assigned_csi == nullptr) {
 2569         // Components of all the CSIs in SI are cleaned up.
 2570         avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_UNINSTANTIATED);
 2571         goto done;
 2572       } else {
 2573         // One CSI is still assigned.
 2574         m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 2575             assigned_csi, AVND_COMP_CSI_ASSIGN_STATE_REMOVING);
 2576         rc = avnd_comp_clc_fsm_trigger(
 2577             cb, assigned_csi->comp,
 2578             (m_AVND_COMP_IS_FAILED(assigned_csi->comp))
 2579                 ? AVND_COMP_CLC_PRES_FSM_EV_CLEANUP
 2580                 : AVND_COMP_CLC_PRES_FSM_EV_TERM);
 2581       }
 2582     }
 2583   }
 2584 
 2585   /* transition to terminating state */
 2586   if (su->pres != SA_AMF_PRESENCE_TERMINATING)
 2587     avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_TERMINATING);
 2588 
 2589 done:
 2590   TRACE_LEAVE2("%u", rc);
 2591   return rc;
 2592 }
 2593 
 2594 /**
 2595  * @brief  Return true if all pi comps of SU are in restarting state.
 2596  *         It will be used during restart admin operation on su.
 2597  * @param  ptr to su.
 2598  * @return  true/false.
 2599  */
 2600 bool su_evaluate_restarting_state(AVND_SU *su) {
 2601   for (AVND_COMP *comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2602            m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 2603        comp; comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2604                  m_NCS_DBLIST_FIND_NEXT(&comp->su_dll_node))) {
 2605     if (!m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(comp)) continue;
 2606     if (comp->pres != SA_AMF_PRESENCE_RESTARTING) {
 2607       return false;
 2608     }
 2609   }
 2610 
 2611   return true;
 2612 }
 2613 /**
 2614  * @brief       Checks if all csis of all the sis in this su are in restarting
 2615  state. Also performs same check by excluding the CSI passed in the default arg.
 2616  * @param [in]  cmp
 2617  * @param [in]  exclude_csi (default value nullptr)
 2618  * @returns     true/false
 2619  **/
 2620 bool all_csis_in_restarting_state(const AVND_SU *su,
 2621                                   AVND_COMP_CSI_REC *exclude_csi) {
 2622   AVND_COMP_CSI_REC *curr_csi;
 2623   AVND_SU_SI_REC *curr_si;
 2624 
 2625   for (curr_si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 2626        curr_si; curr_si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(
 2627                     &curr_si->su_dll_node)) {
 2628     for (curr_csi =
 2629              (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&curr_si->csi_list);
 2630          curr_csi; curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
 2631                        &curr_csi->si_dll_node)) {
 2632       if (curr_csi == exclude_csi) continue;
 2633       if (!m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_RESTARTING(curr_csi)) {
 2634         return false;
 2635       }
 2636     }
 2637   }
 2638   return true;
 2639 }
 2640 /****************************************************************************
 2641   Name          : avnd_su_pres_inst_surestart_hdler
 2642 
 2643   Description   : This routine processes the `SU Restart` event in
 2644                   `Instantiated` state.
 2645 
 2646   Arguments     : cb   - ptr to the AvND control block
 2647                   su   - ptr to the su
 2648                   comp - ptr to the comp (can be nullptr)
 2649 
 2650   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 2651 
 2652   Notes         : None.
 2653 ******************************************************************************/
 2654 uint32_t avnd_su_pres_inst_surestart_hdler(AVND_CB *cb, AVND_SU *su,
 2655                                            AVND_COMP *comp) {
 2656   AVND_COMP *curr_comp = 0;
 2657   AVND_SU_SI_REC *si = 0;
 2658   AVND_COMP_CSI_REC *csi = 0;
 2659   uint32_t rc = NCSCC_RC_SUCCESS;
 2660   TRACE_ENTER2("SURestart event in the Instantiated state: '%s'",
 2661                su->name.c_str());
 2662 
 2663   /*
 2664    * If pi su, pick the first pi comp & trigger it's FSM with RestartEv.
 2665    */
 2666   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2667     TRACE("PI SU:'%s'", su->name.c_str());
 2668     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2669              m_NCS_DBLIST_FIND_LAST(&su->comp_list));
 2670          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2671                         m_NCS_DBLIST_FIND_PREV(&curr_comp->su_dll_node))) {
 2672       if ((curr_comp->pres == SA_AMF_PRESENCE_RESTARTING) ||
 2673           (curr_comp->pres == SA_AMF_PRESENCE_UNINSTANTIATED))
 2674         continue;
 2675       if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) {
 2676         TRACE("Running the component clc FSM, restart the component");
 2677         if (m_AVND_SU_IS_RESTART(su) && m_AVND_SU_IS_FAILED(su))
 2678           rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 2679                                      AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 2680         else
 2681           rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 2682                                      AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 2683         if (NCSCC_RC_SUCCESS != rc) goto done;
 2684         break;
 2685       } else {
 2686         /*
 2687            For a NPI comp in PI SU, component FSM is always triggered at the
 2688            time of assignments. If this component is non-restartable then start
 2689            reassginment from the whole SU now, it will take care if its
 2690            termination/clean up.
 2691          */
 2692         if (m_AVND_COMP_IS_RESTART_DIS(curr_comp) &&
 2693             (curr_comp->csi_list.n_nodes > 0)) {
 2694           TRACE(
 2695               "Start reassignment to different SU as '%s' is"
 2696               " not restartable",
 2697               curr_comp->name.c_str());
 2698           su_send_suRestart_recovery_msg(su);
 2699           goto done;
 2700         } else {
 2701           if (m_AVND_SU_IS_RESTART(su) && m_AVND_SU_IS_FAILED(su))
 2702             rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 2703                                        AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 2704           else
 2705             rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 2706                                        AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 2707           if (curr_comp->pres == SA_AMF_PRESENCE_TERMINATING)
 2708             avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_TERMINATING);
 2709           break;
 2710         }
 2711       }
 2712     } /* for */
 2713     if ((su_evaluate_restarting_state(su) == true) &&
 2714         (!m_AVND_SU_IS_FAILED(su))) {
 2715       TRACE("Mark su restarting");
 2716       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_RESTARTING);
 2717     }
 2718   }
 2719 
 2720   /*
 2721    * If npi su, it'll have only one si-rec in the si-list. Pick the
 2722    * lowest ranked csi belonging to this si & trigger it's comp fsm.
 2723    */
 2724   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2725     TRACE("NPI SU:'%s'", su->name.c_str());
 2726     /* get the only si rec */
 2727     si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 2728     osafassert(si);
 2729 
 2730     csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_LAST(&si->csi_list);
 2731     if (csi) {
 2732       TRACE("Running the component clc FSM for csi:'%s', comp:%s",
 2733             csi->name.c_str(), csi->comp->name.c_str());
 2734       if (m_AVND_SU_IS_RESTART(su) && m_AVND_SU_IS_FAILED(su)) {
 2735         if (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVING(si))
 2736           m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 2737               csi, AVND_COMP_CSI_ASSIGN_STATE_REMOVING);
 2738         else
 2739           m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 2740               csi, AVND_COMP_CSI_ASSIGN_STATE_ASSIGNING);
 2741         rc = avnd_comp_clc_fsm_run(cb, csi->comp,
 2742                                    AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 2743       } else {
 2744         m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 2745             csi, AVND_COMP_CSI_ASSIGN_STATE_RESTARTING);
 2746         rc = avnd_comp_clc_fsm_run(cb, csi->comp,
 2747                                    AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 2748       }
 2749 
 2750       if (NCSCC_RC_SUCCESS != rc) goto done;
 2751     }
 2752     if ((all_csis_in_restarting_state(su) == true) &&
 2753         (!m_AVND_SU_IS_FAILED(su))) {
 2754       TRACE("All CSIs are in restarting state, so marking SU restarting");
 2755       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_RESTARTING);
 2756     }
 2757   }
 2758 
 2759 done:
 2760   TRACE_LEAVE2("%u", rc);
 2761   return rc;
 2762 }
 2763 
 2764 /****************************************************************************
 2765   Name          : avnd_su_pres_inst_comprestart_hdler
 2766 
 2767   Description   : This routine processes the `Comp Restart` event in
 2768                   `Instantiated` state.
 2769 
 2770   Arguments     : cb   - ptr to the AvND control block
 2771                   su   - ptr to the su
 2772                   comp - ptr to the comp (can be nullptr)
 2773 
 2774   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 2775 
 2776   Notes         : None.
 2777 ******************************************************************************/
 2778 uint32_t avnd_su_pres_inst_comprestart_hdler(AVND_CB *cb, AVND_SU *su,
 2779                                              AVND_COMP *comp) { /* TBD */
 2780   uint32_t rc = NCSCC_RC_SUCCESS;
 2781   AVND_COMP_CSI_REC *curr_csi = 0;
 2782   const std::string compname = comp ? comp->name : "none";
 2783   TRACE_ENTER2("Component restart event in the Instantiated state, '%s' : '%s'",
 2784                su->name.c_str(), compname.c_str());
 2785   osafassert(comp != nullptr);
 2786   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2787     TRACE("PI SU");
 2788     for (AVND_COMP *curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2789              m_NCS_DBLIST_FIND_PREV(&comp->su_dll_node));
 2790          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2791                         m_NCS_DBLIST_FIND_PREV(&curr_comp->su_dll_node))) {
 2792       if (curr_comp->pres == SA_AMF_PRESENCE_RESTARTING) continue;
 2793       if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) {
 2794         TRACE("Running the component clc FSM");
 2795         rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 2796                                    AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 2797         if (NCSCC_RC_SUCCESS != rc) goto done;
 2798         break;
 2799       } else {
 2800         /*
 2801            For a NPI comp in SU, component FSM is always triggered
 2802            at the time of assignments. If this component is
 2803            non-restartable then start reassginment from the
 2804            whole SU now.
 2805          */
 2806         if (m_AVND_COMP_IS_RESTART_DIS(curr_comp) &&
 2807             (curr_comp->csi_list.n_nodes > 0)) {
 2808           TRACE(
 2809               "Start reassignment to different SU as '%s' is"
 2810               " not restartable",
 2811               curr_comp->name.c_str());
 2812           su_send_suRestart_recovery_msg(su);
 2813           goto done;
 2814         } else {
 2815           if (m_AVND_SU_IS_RESTART(su) && m_AVND_SU_IS_FAILED(su))
 2816             rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 2817                                        AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 2818           else
 2819             rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 2820                                        AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 2821           if (curr_comp->pres == SA_AMF_PRESENCE_TERMINATING)
 2822             avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_TERMINATING);
 2823           break;
 2824         }
 2825       }
 2826     }
 2827     if (su_evaluate_restarting_state(su) == true)
 2828       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_RESTARTING);
 2829   }
 2830 
 2831   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2832     TRACE_1("NPI SU");
 2833     /* get the only csi rec */
 2834     curr_csi = m_AVND_CSI_REC_FROM_COMP_DLL_NODE_GET(
 2835         m_NCS_DBLIST_FIND_FIRST(&comp->csi_list));
 2836     osafassert(curr_csi);
 2837     /* Typically we mark the CSI state here. But initially we had marked
 2838        CSI state Restarting. It will be marked
 2839        AVND_COMP_CSI_ASSIGN_STATE_ASSIGNED when component will be instantiated.
 2840      */
 2841     curr_csi =
 2842         (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_PREV(&curr_csi->si_dll_node);
 2843     if (curr_csi) {
 2844       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 2845           curr_csi, AVND_COMP_CSI_ASSIGN_STATE_RESTARTING);
 2846       TRACE_2("Running the component clc FSM for csi:'%s', comp:%s",
 2847               curr_csi->name.c_str(), curr_csi->comp->name.c_str());
 2848       rc = avnd_comp_clc_fsm_run(cb, curr_csi->comp,
 2849                                  AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 2850       if (NCSCC_RC_SUCCESS != rc) goto done;
 2851     }
 2852     if (all_csis_in_restarting_state(su) == true) {
 2853       TRACE_2("All CSIs are in restarting state, so marking SU restarting");
 2854       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_RESTARTING);
 2855     }
 2856   }
 2857 done:
 2858   TRACE_LEAVE();
 2859   return rc;
 2860 }
 2861 
 2862 /****************************************************************************
 2863   Name          : avnd_su_pres_inst_compterming_hdler
 2864 
 2865   Description   : This routine processes the `Comp Terminating` event in
 2866                   `Instantiated` state.
 2867 
 2868   Arguments     : cb   - ptr to the AvND control block
 2869                   su   - ptr to the su
 2870                   comp - ptr to the comp (can be nullptr)
 2871 
 2872   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 2873 
 2874   Notes         : None.
 2875 ******************************************************************************/
 2876 uint32_t avnd_su_pres_inst_compterming_hdler(AVND_CB *cb, AVND_SU *su,
 2877                                              AVND_COMP *comp) {
 2878   uint32_t rc = NCSCC_RC_SUCCESS;
 2879   const std::string compname = comp ? comp->name : "none";
 2880   TRACE_ENTER2("CompTerminating event in the Instantiated state:'%s' : '%s'",
 2881                su->name.c_str(), compname.c_str());
 2882   // A SU enters in TERMINATING state when any component is terminating.
 2883   if (((comp != nullptr) && (comp->admin_oper == true)) ||
 2884       m_AVND_SU_IS_FAILED(su) || (su->admin_op_Id == SA_AMF_ADMIN_RESTART)) {
 2885     avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_TERMINATING);
 2886   }
 2887 
 2888   TRACE_LEAVE2("%u", rc);
 2889   return rc;
 2890 }
 2891 
 2892 /****************************************************************************
 2893   Name          : avnd_su_pres_terming_compinst_hdler
 2894 
 2895   Description   : This routine processes the `Comp Instantiate` event in
 2896                   `Terminating` state.
 2897 
 2898   Arguments     : cb   - ptr to the AvND control block
 2899                   su   - ptr to the su
 2900                   comp - ptr to the comp (can be nullptr)
 2901 
 2902   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 2903 
 2904   Notes         : None.
 2905 ******************************************************************************/
 2906 uint32_t avnd_su_pres_terming_compinst_hdler(AVND_CB *cb, AVND_SU *su,
 2907                                              AVND_COMP *comp) {
 2908   uint32_t rc = NCSCC_RC_SUCCESS;
 2909   const std::string compname = comp ? comp->name : "none";
 2910   TRACE_ENTER2(
 2911       "ComponentInstantiate event in the terminating state:'%s' : '%s'",
 2912       su->name.c_str(), compname.c_str());
 2913 
 2914   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2915     bool is;
 2916     osafassert(comp != nullptr);
 2917     if (m_AVND_COMP_IS_FAILED(comp)) {
 2918       m_AVND_COMP_FAILED_RESET(comp);
 2919     }
 2920 
 2921     /* determine if su can be transitioned to instantiated state */
 2922     m_AVND_SU_IS_INSTANTIATED(su, is);
 2923     if (true == is) {
 2924       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATED);
 2925     }
 2926     if (m_AVND_SU_IS_RESTART(su)) {
 2927       if (su->admin_op_Id == SA_AMF_ADMIN_RESTART)
 2928         /*This can happen when SU has both restartable and non restartable
 2929            comps.Go for further instantiation.*/
 2930         rc = avnd_su_pres_fsm_run(cb, su, 0, AVND_SU_PRES_FSM_EV_INST);
 2931       else if (m_AVND_SU_IS_FAILED(su)) {
 2932         /*Before going for surestart recovery from comp restart recovery, a
 2933           comp was in instantiating state, cleanup it now.*/
 2934         rc = avnd_comp_clc_fsm_run(cb, comp, AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 2935       }
 2936     }
 2937   }
 2938   TRACE_LEAVE2("%u", rc);
 2939   return rc;
 2940 }
 2941 
 2942 /****************************************************************************
 2943   Name          : avnd_su_pres_terming_comptermfail_hdler
 2944 
 2945   Description   : This routine processes the `Comp Termination Failed` event in
 2946                   `Terminating` state.
 2947                   For PI SU, a failure in the termination of any component
 2948                   means that SU termination has failed. Terminate all the
 2949                   already instantiated (or instantiating) components &
 2950                   transition to term-failed state.
 2951                   For NPI SU, a failure in the termination of any component
 2952                   indicates that active SI assignment to this SU has failed.
 2953                   Terminate all the components to whom the active CSI has
 2954                   already been assigned (or assigning).
 2955 
 2956   Arguments     : cb   - ptr to the AvND control block
 2957                   su   - ptr to the su
 2958                   comp - ptr to the comp (can be nullptr)
 2959 
 2960   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 2961 
 2962   Notes         : This function is reused for all state changes into termfail
 2963 ******************************************************************************/
 2964 uint32_t avnd_su_pres_terming_comptermfail_hdler(AVND_CB *cb, AVND_SU *su,
 2965                                                  AVND_COMP *comp) {
 2966   AVND_COMP *curr_comp = 0;
 2967   AVND_SU_SI_REC *si = 0;
 2968   AVND_COMP_CSI_REC *curr_csi = 0;
 2969   uint32_t rc = NCSCC_RC_SUCCESS;
 2970   const std::string compname = comp ? comp->name : "none";
 2971   TRACE_ENTER2(
 2972       "Component Termination failed event in the Terminating state,'%s': '%s'",
 2973       su->name.c_str(), compname.c_str());
 2974 
 2975   /*
 2976    * If pi su, pick all the instantiated/instantiating pi comps &
 2977    * trigger their FSM with TermEv.
 2978    */
 2979   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 2980     TRACE("PI SU");
 2981     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2982              m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 2983          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 2984                         m_NCS_DBLIST_FIND_NEXT(&curr_comp->su_dll_node))) {
 2985       /* skip the npi comps */
 2986       if (!m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) continue;
 2987 
 2988       /* terminate the non-uninstantiated pi comp */
 2989       if (!m_AVND_COMP_PRES_STATE_IS_UNINSTANTIATED(curr_comp)) {
 2990         TRACE(
 2991             "Running the component clc FSM, terminate the non-uninstantiated pi comp");
 2992         if (m_AVND_COMP_PRES_STATE_IS_INSTANTIATED(curr_comp) &&
 2993             (!m_AVND_COMP_IS_FAILED(curr_comp)))
 2994           rc = avnd_comp_clc_fsm_trigger(cb, curr_comp,
 2995                                          AVND_COMP_CLC_PRES_FSM_EV_TERM);
 2996         /* During shutdown phase AMFND cleans up all the components */
 2997         else if (cb->term_state != AVND_TERM_STATE_OPENSAF_SHUTDOWN_STARTED)
 2998           rc = avnd_comp_clc_fsm_trigger(cb, curr_comp,
 2999                                          AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 3000 
 3001         if (NCSCC_RC_SUCCESS != rc) goto done;
 3002       }
 3003     } /* for */
 3004   }
 3005 
 3006   /*
 3007    * If npi su, pick all the assigned/assigning comps &
 3008    * trigger their comp fsm with TermEv
 3009    */
 3010   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3011     TRACE("NPI SU");
 3012     /* get the only si rec */
 3013     si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 3014     osafassert(si);
 3015 
 3016     for (curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&si->csi_list);
 3017          curr_csi; curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
 3018                        &curr_csi->si_dll_node)) {
 3019       TRACE(
 3020           "Running the component clc FSM, terminate the component containing non-unassigned csi");
 3021       /* terminate the component containing non-unassigned csi */
 3022       if (!m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_UNASSIGNED(curr_csi)) {
 3023         rc = avnd_comp_clc_fsm_trigger(cb, curr_csi->comp,
 3024                                        AVND_COMP_CLC_PRES_FSM_EV_TERM);
 3025         if (NCSCC_RC_SUCCESS != rc) goto done;
 3026       }
 3027     } /* for */
 3028   }
 3029 
 3030   /* transition to term-failed state */
 3031   avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_TERMINATION_FAILED);
 3032 
 3033   if (true == su->is_ncs) {
 3034     std::string reason = "SU '" + su->name + "' Termination-failed";
 3035     if (su->suMaintenanceCampaign.empty()) {
 3036       opensaf_reboot(
 3037           avnd_cb->node_info.nodeId,
 3038           osaf_extended_name_borrow(&avnd_cb->node_info.executionEnvironment),
 3039           reason.c_str());
 3040     } else {
 3041       LOG_ER("%s", reason.c_str());
 3042       LOG_NO("not rebooting because su maintenance campaign is set: %s",
 3043              su->suMaintenanceCampaign.c_str());
 3044     }
 3045   }
 3046 
 3047 done:
 3048   TRACE_LEAVE2("%u", rc);
 3049   return rc;
 3050 }
 3051 
 3052 /**
 3053  * @brief       Checks if all csis of all the sis in this su are in removed
 3054  *state
 3055  *
 3056  * @param [in]  cmp
 3057  *
 3058  * @returns     true/false
 3059  **/
 3060 bool all_csis_in_assigned_state(const AVND_SU *su) {
 3061   TRACE_ENTER2("'%s'", su->name.c_str());
 3062   AVND_COMP_CSI_REC *curr_csi;
 3063   AVND_SU_SI_REC *curr_si;
 3064   bool all_csi_assigned = true;
 3065 
 3066   for (curr_si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 3067        curr_si && all_csi_assigned;
 3068        curr_si =
 3069            (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_NEXT(&curr_si->su_dll_node)) {
 3070     for (curr_csi =
 3071              (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&curr_si->csi_list);
 3072          curr_csi; curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
 3073                        &curr_csi->si_dll_node)) {
 3074       if (!m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_ASSIGNED(curr_csi)) {
 3075         all_csi_assigned = false;
 3076         break;
 3077       }
 3078     }
 3079   }
 3080   TRACE_LEAVE2("all_csi_assigned:%u", all_csi_assigned);
 3081   return all_csi_assigned;
 3082 }
 3083 
 3084 /****************************************************************************
 3085   Name          : avnd_su_pres_terming_compuninst_hdler
 3086 
 3087   Description   : This routine processes the `Comp Uninstantiated` event in
 3088                   `Terminating` state.
 3089 
 3090   Arguments     : cb   - ptr to the AvND control block
 3091                   su   - ptr to the su
 3092                   comp - ptr to the comp (can be nullptr)
 3093 
 3094   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 3095 
 3096   Notes         : None.
 3097 ******************************************************************************/
 3098 uint32_t avnd_su_pres_terming_compuninst_hdler(AVND_CB *cb, AVND_SU *su,
 3099                                                AVND_COMP *comp) {
 3100   AVND_COMP *curr_comp = 0;
 3101   AVND_COMP_CSI_REC *curr_csi = 0;
 3102   uint32_t rc = NCSCC_RC_SUCCESS;
 3103   const std::string compname = comp ? comp->name : "none";
 3104   TRACE_ENTER2(
 3105       "Component Uninstantiated event in the Terminating state:'%s' : '%s'",
 3106       su->name.c_str(), compname.c_str());
 3107   // TODO: write whole if block into a separate function for PI SUand call it
 3108   // here.
 3109   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3110     TRACE("PI SU");
 3111     if (m_AVND_SU_IS_FAILED(su)) {
 3112       TRACE("SU is in Failed state");
 3113       if (pi_su_all_comps_uninstantiated(*su) == true)
 3114         avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_UNINSTANTIATED);
 3115 
 3116       if (m_AVND_SU_IS_RESTART(su)) {
 3117         for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3118                  m_NCS_DBLIST_FIND_LAST(&su->comp_list));
 3119              curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3120                             m_NCS_DBLIST_FIND_PREV(&curr_comp->su_dll_node))) {
 3121           if (curr_comp->pres == SA_AMF_PRESENCE_UNINSTANTIATED) continue;
 3122           // Will pick up when terminating comp will move to uninstantiated
 3123           // state.
 3124           if ((curr_comp->pres == SA_AMF_PRESENCE_TERMINATING) ||
 3125               (curr_comp->pres == SA_AMF_PRESENCE_RESTARTING))
 3126             break;
 3127           if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) {
 3128             rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3129                                        AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 3130             if (NCSCC_RC_SUCCESS != rc) goto done;
 3131             break;
 3132           } else {
 3133             /*
 3134                For a NPI comp in SU, component FSM is always triggered
 3135                at the time of assignments. If this component is
 3136                non-restartable then start reassginment from the
 3137                whole SU now.
 3138              */
 3139             if (m_AVND_COMP_IS_RESTART_DIS(curr_comp) &&
 3140                 (curr_comp->csi_list.n_nodes > 0)) {
 3141               TRACE(
 3142                   "Start reassignment to different SU as '%s' is"
 3143                   " not restartable",
 3144                   curr_comp->name.c_str());
 3145               su_send_suRestart_recovery_msg(su);
 3146               goto done;
 3147             } else {
 3148               if (m_AVND_SU_IS_RESTART(su) && m_AVND_SU_IS_FAILED(su))
 3149                 rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3150                                            AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 3151               else
 3152                 rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3153                                            AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 3154               if (curr_comp->pres == SA_AMF_PRESENCE_TERMINATING)
 3155                 avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_TERMINATING);
 3156               break;
 3157             }
 3158           }
 3159         }
 3160       }
 3161     } else if ((comp != nullptr) && (comp->admin_oper == true) &&
 3162                (cb->term_state != AVND_TERM_STATE_OPENSAF_SHUTDOWN_STARTED) &&
 3163                (m_AVND_COMP_IS_RESTART_DIS(comp))) {
 3164       TRACE("Admin operation on component");
 3165       if (pi_su_all_comps_uninstantiated(*su) == true)
 3166         avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_UNINSTANTIATED);
 3167       avnd_comp_clc_fsm_run(cb, comp, AVND_COMP_CLC_PRES_FSM_EV_INST);
 3168       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATING);
 3169     } else {
 3170       osafassert(comp != nullptr);
 3171       TRACE("Admin operation on SU");
 3172       for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3173                m_NCS_DBLIST_FIND_PREV(&comp->su_dll_node));
 3174            curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3175                           m_NCS_DBLIST_FIND_PREV(&curr_comp->su_dll_node))) {
 3176         TRACE_1("comp:'%s', Pres state:%u", curr_comp->name.c_str(),
 3177                 curr_comp->pres);
 3178         if ((curr_comp->pres == SA_AMF_PRESENCE_RESTARTING) ||
 3179             (curr_comp->pres == SA_AMF_PRESENCE_UNINSTANTIATED))
 3180           continue;
 3181 
 3182         if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) {
 3183           TRACE("Running the component clc FSM");
 3184           if (su->admin_op_Id == SA_AMF_ADMIN_RESTART)
 3185             rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3186                                        AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 3187           else
 3188             rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3189                                        AVND_COMP_CLC_PRES_FSM_EV_TERM);
 3190           if (NCSCC_RC_SUCCESS != rc) goto done;
 3191           break;
 3192         } else {
 3193           /*
 3194              For a NPI comp in PI SU, component FSM is always triggered
 3195              at the time of assignments. If this component is non-restartable
 3196              then start reassginment from the whole SU now, it will take care
 3197              if its termination/clean up.
 3198            */
 3199           if ((nonrestartable(curr_comp) == true) &&
 3200               (csi_count(curr_comp) > 0)) {
 3201             TRACE(
 3202                 "Start reassignment to different SU as '%s' is"
 3203                 " not restartable",
 3204                 curr_comp->name.c_str());
 3205             su_send_suRestart_recovery_msg(su);
 3206             goto done;
 3207           } else if (isAdminRestarted(su) == true) {
 3208             rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3209                                        AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 3210             if (curr_comp->pres == SA_AMF_PRESENCE_RESTARTING) goto done;
 3211           }
 3212         }
 3213       }
 3214       if (pi_su_all_comps_uninstantiated(*su) == true)
 3215         avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_UNINSTANTIATED);
 3216       else if ((curr_comp == nullptr) &&
 3217                (su->admin_op_Id == SA_AMF_ADMIN_RESTART)) {
 3218         /*
 3219            It means it is a SU comprising of assigned non restartable comps and
 3220            restartable comps and it is restart admin op on su.
 3221            Now instantiate SU honoring instantiation level.
 3222          */
 3223         rc = avnd_su_pres_fsm_run(cb, su, 0, AVND_SU_PRES_FSM_EV_INST);
 3224         if (NCSCC_RC_SUCCESS != rc) goto done;
 3225       }
 3226     }
 3227   }
 3228 
 3229   /*
 3230    * If npi su, pick the prv csi & trigger it's comp fsm with TermEv.
 3231    */
 3232   if (!m_AVND_SU_IS_PREINSTANTIABLE(su) &&
 3233       (!m_AVND_SU_IS_FAILED(su) || m_AVND_SU_IS_RESTART(su))) {
 3234     TRACE("NPI SU");
 3235     /* get the only csi rec */
 3236     osafassert(comp != nullptr);
 3237     curr_csi = m_AVND_CSI_REC_FROM_COMP_DLL_NODE_GET(
 3238         m_NCS_DBLIST_FIND_FIRST(&comp->csi_list));
 3239     if ((cb->term_state == AVND_TERM_STATE_OPENSAF_SHUTDOWN_STARTED) &&
 3240       (!curr_csi)) {
 3241       LOG_NO("CSI has already removed in shutting down");
 3242       goto done;
 3243     }
 3244     osafassert(curr_csi);
 3245 
 3246     /* mark the csi state assigned/removed */
 3247     if (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVING(curr_csi->si))
 3248       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(curr_csi,
 3249                                             AVND_COMP_CSI_ASSIGN_STATE_REMOVED);
 3250     else
 3251       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 3252           curr_csi, AVND_COMP_CSI_ASSIGN_STATE_ASSIGNED);
 3253 
 3254     if (curr_csi->single_csi_add_rem_in_si == AVSV_SUSI_ACT_DEL) {
 3255       /* get here when a CSI is removed from a component in an NPI SU */
 3256       assert(curr_csi->si->single_csi_add_rem_in_si == AVSV_SUSI_ACT_DEL);
 3257       rc = avnd_su_si_oper_done(cb, su, curr_csi->si);
 3258       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATED);
 3259       goto done;
 3260     }
 3261 
 3262     /* get the prv csi */
 3263     curr_csi =
 3264         (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_PREV(&curr_csi->si_dll_node);
 3265     if (curr_csi) {
 3266       /* we have another csi. trigger the comp fsm with TermEv */
 3267       TRACE("There's another CSI, Running the component clc FSM");
 3268       if (m_AVND_SU_IS_RESTART(su) && m_AVND_SU_IS_FAILED(su))
 3269         rc = avnd_comp_clc_fsm_trigger(cb, curr_csi->comp,
 3270                                        AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 3271       else
 3272         rc = avnd_comp_clc_fsm_trigger(cb, curr_csi->comp,
 3273                                        (m_AVND_COMP_IS_FAILED(curr_csi->comp))
 3274                                            ? AVND_COMP_CLC_PRES_FSM_EV_CLEANUP
 3275                                            : AVND_COMP_CLC_PRES_FSM_EV_TERM);
 3276       if (NCSCC_RC_SUCCESS != rc) goto done;
 3277     }
 3278 
 3279     if (all_csis_in_assigned_state(su) || all_csis_removable_from_su(su)) {
 3280       TRACE("SI Assignment done");
 3281       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_UNINSTANTIATED);
 3282       goto done;
 3283     }
 3284 
 3285     /*
 3286        During shutdown phase if a component faults, it will be cleaned up by
 3287        AMFND irrespective of recovery policy. This component will move to
 3288        UNINSTANTIATED after successful clean up. When amfnd starts removing SI
 3289        from SU of this comp, it will have to skip the CSI of cleaned up
 3290        component.
 3291     */
 3292     if ((curr_csi != nullptr) &&
 3293         (curr_csi->comp->pres == SA_AMF_PRESENCE_UNINSTANTIATED) &&
 3294         (cb->term_state == AVND_TERM_STATE_OPENSAF_SHUTDOWN_STARTED)) {
 3295       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(curr_csi,
 3296                                             AVND_COMP_CSI_ASSIGN_STATE_REMOVED);
 3297       AVND_COMP_CSI_REC *assigned_csi =
 3298           get_next_assigned_csi_from_end(curr_csi->si);
 3299       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 3300           assigned_csi, AVND_COMP_CSI_ASSIGN_STATE_REMOVING);
 3301       rc = avnd_comp_clc_fsm_trigger(cb, assigned_csi->comp,
 3302                                      (m_AVND_COMP_IS_FAILED(assigned_csi->comp))
 3303                                          ? AVND_COMP_CLC_PRES_FSM_EV_CLEANUP
 3304                                          : AVND_COMP_CLC_PRES_FSM_EV_TERM);
 3305     }
 3306   }
 3307 
 3308 done:
 3309   TRACE_LEAVE2("%u", rc);
 3310   return rc;
 3311 }
 3312 
 3313 /****************************************************************************
 3314   Name          : avnd_su_pres_restart_suterm_hdler
 3315 
 3316   Description   : This routine processes the `SU Terminate` event in
 3317                   `Restarting` state.
 3318 
 3319   Arguments     : cb   - ptr to the AvND control block
 3320                   su   - ptr to the su
 3321                   comp - ptr to the comp (can be nullptr)
 3322 
 3323   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 3324 
 3325   Notes         : None.
 3326 ******************************************************************************/
 3327 uint32_t avnd_su_pres_restart_suterm_hdler(AVND_CB *cb, AVND_SU *su,
 3328                                            AVND_COMP *comp) {
 3329   AVND_COMP *curr_comp = 0;
 3330   uint32_t rc = NCSCC_RC_SUCCESS;
 3331   AVND_SU_SI_REC *si = nullptr;
 3332   AVND_COMP_CSI_REC *csi = nullptr;
 3333   const std::string compname = comp ? comp->name : "none";
 3334   TRACE_ENTER2("SU Terminate event in the Restarting state:'%s' : '%s'",
 3335                su->name.c_str(), compname.c_str());
 3336 
 3337   /*
 3338    * If pi su, pick all the instantiated/instantiating pi comps &
 3339    * trigger their FSM with CleanupEv.
 3340    */
 3341   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3342     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3343            m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 3344        curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3345                       m_NCS_DBLIST_FIND_NEXT(&curr_comp->su_dll_node))) {
 3346       /* terminate the non-uninstantiated pi comp */
 3347       if ((!m_AVND_COMP_PRES_STATE_IS_UNINSTANTIATED(curr_comp)) &&
 3348         (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp))) {
 3349        /* mark the comp failed */
 3350        m_AVND_COMP_FAILED_SET(curr_comp);
 3351 
 3352        /* update comp oper state */
 3353        m_AVND_COMP_OPER_STATE_SET(curr_comp, SA_AMF_OPERATIONAL_DISABLED);
 3354        rc = avnd_comp_oper_state_avd_sync(cb, curr_comp);
 3355        if (NCSCC_RC_SUCCESS != rc) goto done;
 3356 
 3357        rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3358                                  AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 3359        if (NCSCC_RC_SUCCESS != rc) goto done;
 3360       }
 3361     } /* for */
 3362   }
 3363 
 3364   /*NPI su, it'll have only one si-rec in the si-list. Pick the
 3365     highest ranked csi belonging to this si & trigger it's comp fsm.
 3366   */
 3367   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3368     TRACE("NPI SU:'%s'", su->name.c_str());
 3369 
 3370     si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 3371     osafassert(si);
 3372     csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_LAST(&si->csi_list);
 3373     osafassert(csi);
 3374 
 3375     if (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVING(si))
 3376       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 3377           csi, AVND_COMP_CSI_ASSIGN_STATE_REMOVING);
 3378     else
 3379       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 3380           csi, AVND_COMP_CSI_ASSIGN_STATE_ASSIGNING);
 3381 
 3382     TRACE("Running the component clc FSM, terminate the component");
 3383     rc = avnd_comp_clc_fsm_run(cb, csi->comp,
 3384                                (m_AVND_COMP_IS_FAILED(csi->comp))
 3385                                    ? AVND_COMP_CLC_PRES_FSM_EV_CLEANUP
 3386                                    : AVND_COMP_CLC_PRES_FSM_EV_TERM);
 3387   }
 3388 
 3389   /* transition to terminating state */
 3390   avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_TERMINATING);
 3391 
 3392 done:
 3393   TRACE_LEAVE2("%u", rc);
 3394   return rc;
 3395 }
 3396 
 3397 /**
 3398  * @brief  handler for a component restart event when SU is in restarting state.
 3399  *         This will be invoked when  either a comp is instantiated or
 3400  * terminated restarting state. It will be used during restart admin operation
 3401  * on su.
 3402  * @param  ptr to avnd_cb.
 3403  * @param  ptr to su.
 3404  * @param  ptr to comp.
 3405  * @return  NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE.
 3406  */
 3407 uint32_t avnd_su_pres_restart_comprestart_hdler(AVND_CB *cb, AVND_SU *su,
 3408                                                 AVND_COMP *comp) {
 3409   AVND_COMP *curr_comp = 0;
 3410   AVND_SU_SI_REC *si = 0;
 3411   AVND_COMP_CSI_REC *csi = 0;
 3412   uint32_t rc = NCSCC_RC_SUCCESS;
 3413   TRACE_ENTER2("Comp restart event while su is restarting: '%s'",
 3414                su->name.c_str());
 3415 
 3416   /* This event comes when a component in restarting state  is successfully
 3417      terminated or instantiated.
 3418    */
 3419   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3420     TRACE("PI SU:'%s'", su->name.c_str());
 3421     /*All restartable PI comps are terminated when SU remains in instantiated
 3422       state. After restarting all the PI comps in restarting state, su will be
 3423       marked restarting. Some NPI comps may remain instantiated, terminate them
 3424       now.
 3425      */
 3426     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3427              m_NCS_DBLIST_FIND_LAST(&su->comp_list));
 3428          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3429                         m_NCS_DBLIST_FIND_PREV(&curr_comp->su_dll_node))) {
 3430       TRACE("%s", curr_comp->name.c_str());
 3431       if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) continue;
 3432       if ((!m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) &&
 3433           (curr_comp->pres == SA_AMF_PRESENCE_INSTANTIATED)) {
 3434         rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3435                                    AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 3436         goto done;
 3437       }
 3438     }
 3439     /* It means last pi component got terminated,now instantiate the first
 3440      * comp.*/
 3441     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3442              m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 3443          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3444                         m_NCS_DBLIST_FIND_NEXT(&curr_comp->su_dll_node))) {
 3445       TRACE("%s", curr_comp->name.c_str());
 3446       if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp) &&
 3447           (curr_comp->pres == SA_AMF_PRESENCE_RESTARTING)) {
 3448         rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3449                                    AVND_COMP_CLC_PRES_FSM_EV_INST);
 3450         if (NCSCC_RC_SUCCESS != rc) goto done;
 3451         break;
 3452       }
 3453     }
 3454   }
 3455 
 3456   /*
 3457    * If npi su, it'll have only one si-rec in the si-list. Pick the
 3458    * lowest ranked csi belonging to this si & trigger it's comp fsm.
 3459    */
 3460   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3461     TRACE("NPI SU:'%s'", su->name.c_str());
 3462     /* get the only si rec */
 3463     si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 3464     osafassert(si);
 3465     csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&si->csi_list);
 3466     if (csi) {
 3467       /* This CSI must be in restarting state. We will mark it
 3468          AVND_COMP_CSI_ASSIGN_STATE_ASSIGNED after the instantiation
 3469          of associated component.
 3470        */
 3471       TRACE("Running the component CLC FSM for csi:%s, comp:%s",
 3472             csi->name.c_str(), comp->name.c_str());
 3473       rc = avnd_comp_clc_fsm_run(cb, csi->comp, AVND_COMP_CLC_PRES_FSM_EV_INST);
 3474       if (NCSCC_RC_SUCCESS != rc) goto done;
 3475     }
 3476   }
 3477 done:
 3478   TRACE_LEAVE();
 3479   return rc;
 3480 }
 3481 /****************************************************************************
 3482   Name          : avnd_su_pres_restart_compinst_hdler
 3483 
 3484   Description   : This routine processes the `CompInstantiated` event in
 3485                   `Restarting` state.
 3486 
 3487   Arguments     : cb   - ptr to the AvND control block
 3488                   su   - ptr to the su
 3489                   comp - ptr to the comp (can be nullptr)
 3490 
 3491   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 3492 
 3493   Notes         : None.
 3494 ******************************************************************************/
 3495 uint32_t avnd_su_pres_restart_compinst_hdler(AVND_CB *cb, AVND_SU *su,
 3496                                              AVND_COMP *comp) {
 3497   AVND_COMP *curr_comp = 0;
 3498   AVND_COMP_CSI_REC *curr_csi = 0;
 3499   uint32_t rc = NCSCC_RC_SUCCESS;
 3500   const std::string compname = comp ? comp->name : "none";
 3501   TRACE_ENTER2(
 3502       "ComponentInstantiated event in the Restarting state:'%s' : '%s'",
 3503       su->name.c_str(), compname.c_str());
 3504   SaAmfPresenceStateT pres_init = su->pres;
 3505   osafassert(comp != nullptr);
 3506   /*
 3507    * If pi su, pick the next pi comp & trigger it's FSM with Inst Event.
 3508    */
 3509   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3510     TRACE("PI SU:'%s'", su->name.c_str());
 3511     /* Mark SU instantiated if atleast one PI comp is in instantiated state.*/
 3512     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3513              m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 3514          curr_comp && (su->pres != SA_AMF_PRESENCE_INSTANTIATED);
 3515          curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3516              m_NCS_DBLIST_FIND_NEXT(&curr_comp->su_dll_node))) {
 3517       if ((curr_comp->pres == SA_AMF_PRESENCE_INSTANTIATED) &&
 3518           (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)))
 3519         avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATED);
 3520     }
 3521     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3522              m_NCS_DBLIST_FIND_NEXT(&comp->su_dll_node));
 3523          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3524                         m_NCS_DBLIST_FIND_NEXT(&curr_comp->su_dll_node))) {
 3525       if (curr_comp->pres == SA_AMF_PRESENCE_INSTANTIATED) continue;
 3526       if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp) &&
 3527           (curr_comp->pres == SA_AMF_PRESENCE_RESTARTING) &&
 3528           (m_AVND_SU_IS_RESTART(su))) {
 3529         rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3530                                    AVND_COMP_CLC_PRES_FSM_EV_INST);
 3531         if (NCSCC_RC_SUCCESS != rc) goto done;
 3532         break;
 3533       }
 3534     } /* for */
 3535 
 3536     /*If all comps are instantiated then reassign the SU execpt in a single comp
 3537      * case.*/
 3538     if ((pres_init == SA_AMF_PRESENCE_INSTANTIATED) &&
 3539         (su_all_pi_comps_instantiated(su) == true))
 3540       rc = pi_su_instantiating_to_instantiated(su);
 3541   }
 3542 
 3543   /*
 3544    * If npi su, pick the next csi & trigger it's comp fsm with RestartEv.
 3545    */
 3546   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3547     TRACE("NPI SU:'%s'", su->name.c_str());
 3548     /* get the only csi rec */
 3549     osafassert(comp != nullptr);
 3550     curr_csi = m_AVND_CSI_REC_FROM_COMP_DLL_NODE_GET(
 3551         m_NCS_DBLIST_FIND_FIRST(&comp->csi_list));
 3552     osafassert(curr_csi);
 3553 
 3554     /* mark the csi state assigned */
 3555     m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(curr_csi,
 3556                                           AVND_COMP_CSI_ASSIGN_STATE_ASSIGNED);
 3557     if (su->pres != SA_AMF_PRESENCE_INSTANTIATED)
 3558       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATED);
 3559 
 3560     /* get the next csi */
 3561     curr_csi =
 3562         (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(&curr_csi->si_dll_node);
 3563 
 3564     /* Restart next component associated with unassigned CSI and if the
 3565        component is not already in RESTARTING state.
 3566      */
 3567     if ((curr_csi != nullptr) &&
 3568         (m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_RESTARTING(curr_csi) == true) &&
 3569         (m_AVND_SU_IS_RESTART(su))) {
 3570       /* we have another csi. trigger the comp fsm with Inst event*/
 3571       rc = avnd_comp_clc_fsm_trigger(cb, curr_csi->comp,
 3572                                      AVND_COMP_CLC_PRES_FSM_EV_INST);
 3573       if (NCSCC_RC_SUCCESS != rc) goto done;
 3574     }
 3575     /*If all comps are instantiated then reset SU params.*/
 3576     if ((pres_init == SA_AMF_PRESENCE_INSTANTIATED) &&
 3577         (all_csis_in_assigned_state(su) == true))
 3578       rc = npi_su_instantiating_to_instantiated(su);
 3579   }
 3580 
 3581 done:
 3582   TRACE_LEAVE2("%u", rc);
 3583   return rc;
 3584 }
 3585 
 3586 /****************************************************************************
 3587   Name          : avnd_su_pres_restart_compterming_hdler
 3588 
 3589   Description   : This routine processes the `SU Terminate` event in
 3590                   `Instantiating` state.
 3591 
 3592   Arguments     : cb   - ptr to the AvND control block
 3593                   su   - ptr to the su
 3594                   comp - ptr to the comp (can be nullptr)
 3595 
 3596   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 3597 
 3598   Notes         : Note that this event is only generated for PI SUs. SUTermEv
 3599                   is generated for NPI SUs only during stable states i.e.
 3600                   uninstantiated & instantiated states. This is done by
 3601                   avoiding overlapping SI assignments.
 3602 ******************************************************************************/
 3603 uint32_t avnd_su_pres_restart_compterming_hdler(AVND_CB *cb, AVND_SU *su,
 3604                                                 AVND_COMP *comp) {
 3605   AVND_COMP *curr_comp = 0;
 3606   uint32_t rc = NCSCC_RC_SUCCESS;
 3607   const std::string compname = comp ? comp->name : "none";
 3608   TRACE_ENTER2("SUTerminate event in the Instantiating state:'%s' : '%s'",
 3609                su->name.c_str(), compname.c_str());
 3610 
 3611   if (m_AVND_SU_IS_ADMN_TERM(su)) {
 3612     /* This case will be hit, when an SU is already restarting and admin
 3613      * is trying to terminate it. As a part of admn term in SU restart
 3614      * we would clean up all the comp in SU. while this cleanup is happening
 3615      * for each componet, they will trigger SU FSM and this particular case
 3616      * will be hit.
 3617      * we need not do anything here.
 3618      */
 3619     goto done;
 3620   }
 3621 
 3622   /*
 3623    * If pi su, pick all the instantiated/instantiating pi comps &
 3624    * trigger their FSM with TermEv.
 3625    */
 3626   for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3627            m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 3628        curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3629                       m_NCS_DBLIST_FIND_NEXT(&curr_comp->su_dll_node))) {
 3630     /* skip the npi comps */
 3631     if (!m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) continue;
 3632 
 3633     /* terminate the non-uninstantiated pi comp */
 3634     if (!m_AVND_COMP_PRES_STATE_IS_UNINSTANTIATED(curr_comp) &&
 3635         (!m_AVND_COMP_PRES_STATE_IS_TERMINATING(curr_comp))) {
 3636       /* mark the comp failed */
 3637       m_AVND_COMP_FAILED_SET(curr_comp);
 3638 
 3639       /* update comp oper state */
 3640       m_AVND_COMP_OPER_STATE_SET(curr_comp, SA_AMF_OPERATIONAL_DISABLED);
 3641       rc = avnd_comp_oper_state_avd_sync(cb, curr_comp);
 3642       if (NCSCC_RC_SUCCESS != rc) goto done;
 3643 
 3644       rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3645                                  AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 3646       if (NCSCC_RC_SUCCESS != rc) goto done;
 3647     }
 3648   } /* for */
 3649 
 3650   /* transition to terminating state */
 3651   avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_TERMINATING);
 3652 
 3653 done:
 3654   TRACE_LEAVE2("%u", rc);
 3655   return rc;
 3656 }
 3657 
 3658 /****************************************************************************
 3659   Name          : avnd_su_pres_inst_compinstfail_hdler
 3660 
 3661   Description   : This routine processes the `CompInstantiateFailed` event in
 3662                   `Instantiated` state.
 3663 
 3664   Arguments     : cb   - ptr to the AvND control block
 3665                   su   - ptr to the su
 3666                   comp - ptr to the comp (can be nullptr)
 3667 
 3668   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 3669 
 3670   Notes         : This function is reused for the following su presence
 3671                   state transitions also
 3672                   INSTANTIATED -> INSTANTIATIONFAIL
 3673                   TERMINATING  -> INSTANTIATIONFAIL
 3674                   RESTARTING   -> INSTANTIATIONFAIL
 3675 ******************************************************************************/
 3676 uint32_t avnd_su_pres_inst_compinstfail_hdler(AVND_CB *cb, AVND_SU *su,
 3677                                               AVND_COMP *comp) {
 3678   AVND_COMP *curr_comp = 0;
 3679   AVND_SU_SI_REC *si = 0;
 3680   AVND_COMP_CSI_REC *curr_csi = 0;
 3681   uint32_t rc = NCSCC_RC_SUCCESS;
 3682   uint32_t comp_count = 0;
 3683   const std::string compname = comp ? comp->name : "none";
 3684   TRACE_ENTER2(
 3685       "Component Instantiation failed event in the Instantiated state: '%s' : '%s'",
 3686       su->name.c_str(), compname.c_str());
 3687 
 3688   /* transition to inst-failed state */
 3689   avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATION_FAILED);
 3690   m_AVND_SU_ALL_TERM_RESET(su);
 3691 
 3692   /*
 3693    * If pi su, pick all the instantiated/instantiating pi comps &
 3694    * trigger their FSM with TermEv.
 3695    */
 3696   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3697     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3698              m_NCS_DBLIST_FIND_LAST(&su->comp_list));
 3699          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3700                         m_NCS_DBLIST_FIND_PREV(&curr_comp->su_dll_node))) {
 3701       /* skip the npi comps */
 3702       if (!m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) continue;
 3703 
 3704       comp_count++;
 3705       /* terminate the non-uninstantiated pi healthy comp && clean the faulty
 3706        * comps */
 3707       if ((!m_AVND_COMP_PRES_STATE_IS_UNINSTANTIATED(curr_comp)) &&
 3708           (!m_AVND_COMP_IS_FAILED(curr_comp))) {
 3709         /* if this comp was getting assigned, mark it done */
 3710         avnd_comp_cmplete_all_assignment(cb, curr_comp);
 3711         avnd_comp_cmplete_all_csi_rec(cb, curr_comp);
 3712         rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3713                                    AVND_COMP_CLC_PRES_FSM_EV_TERM);
 3714         if (NCSCC_RC_SUCCESS != rc) goto done;
 3715       } else if ((!m_AVND_COMP_PRES_STATE_IS_UNINSTANTIATED(curr_comp)) &&
 3716                  (m_AVND_COMP_IS_FAILED(curr_comp))) {
 3717         /* if this comp was getting assigned, mark it done */
 3718         avnd_comp_cmplete_all_assignment(cb, curr_comp);
 3719         avnd_comp_cmplete_all_csi_rec(cb, curr_comp);
 3720         rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3721                                    AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 3722         if (NCSCC_RC_SUCCESS != rc) goto done;
 3723       }
 3724     } /* for */
 3725     if (1 == comp_count) {
 3726       /* If the componenet was alone then we need to set SU to term state and
 3727          process the SUSI assignment.*/
 3728       m_AVND_SU_ALL_TERM_SET(su);
 3729       avnd_su_siq_prc(cb, su);
 3730     }
 3731   }
 3732 
 3733   /*
 3734    * If npi su, pick all the assigned/assigning comps &
 3735    * trigger their comp fsm with TermEv
 3736    */
 3737   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3738     /* get the only si rec */
 3739     si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 3740     osafassert(si);
 3741 
 3742     for (curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&si->csi_list);
 3743          curr_csi; curr_csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(
 3744                        &curr_csi->si_dll_node)) {
 3745       /* terminate the component containing non-unassigned csi */
 3746       if (!m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_UNASSIGNED(curr_csi)) {
 3747         rc = avnd_comp_clc_fsm_run(cb, curr_csi->comp,
 3748                                    AVND_COMP_CLC_PRES_FSM_EV_TERM);
 3749         if (NCSCC_RC_SUCCESS != rc) goto done;
 3750       }
 3751     } /* for */
 3752     m_AVND_SU_ALL_TERM_SET(su);
 3753   }
 3754 
 3755 done:
 3756   TRACE_LEAVE2("%u", rc);
 3757   return rc;
 3758 }
 3759 
 3760 /****************************************************************************
 3761   Name          : avnd_su_pres_instfailed_compuninst
 3762 
 3763   Description   : This routine processes the `CompInstantiateFailed` event &
 3764                   `CompUnInstantiated` event in `Instantiationfailed` state.
 3765 
 3766   Arguments     : cb   - ptr to the AvND control block
 3767                   su   - ptr to the su
 3768                   comp - ptr to the comp (can be nullptr)
 3769 
 3770   Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 3771 
 3772   Notes         : None.
 3773 ******************************************************************************/
 3774 uint32_t avnd_su_pres_instfailed_compuninst(AVND_CB *cb, AVND_SU *su,
 3775                                             AVND_COMP *comp) {
 3776   AVND_COMP *curr_comp = 0;
 3777   AVND_SU_SIQ_REC *siq = 0;
 3778   uint32_t rc = NCSCC_RC_SUCCESS;
 3779   const std::string compname = comp ? comp->name : "none";
 3780   TRACE_ENTER2(
 3781       "CompInstantiateFailed/CompUnInstantiated event in the InstantiationFailed state:'%s', '%s'",
 3782       su->name.c_str(), compname.c_str());
 3783 
 3784   /* check whether all pi comps are terminated  */
 3785   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3786     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3787              m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 3788          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3789                         m_NCS_DBLIST_FIND_NEXT(&curr_comp->su_dll_node))) {
 3790       /* skip the npi comps */
 3791       if (!m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) continue;
 3792 
 3793       if (!m_AVND_COMP_PRES_STATE_IS_UNINSTANTIATED(curr_comp) &&
 3794           !m_AVND_COMP_PRES_STATE_IS_INSTANTIATIONFAILED(curr_comp)) {
 3795         m_AVND_SU_ALL_TERM_RESET(su);
 3796 
 3797         if (m_AVND_COMP_PRES_STATE_IS_TERMINATIONFAILED(curr_comp)) {
 3798           /* why waste memory -free entire queue */
 3799           siq = (AVND_SU_SIQ_REC *)m_NCS_DBLIST_FIND_LAST(&su->siq);
 3800           while (siq) {
 3801             /* unlink the buffered msg from the queue */
 3802             ncs_db_link_list_delink(&su->siq, &siq->su_dll_node);
 3803 
 3804             /* delete the buffered msg */
 3805             avnd_su_siq_rec_del(cb, su, siq);
 3806 
 3807             siq = (AVND_SU_SIQ_REC *)m_NCS_DBLIST_FIND_LAST(&su->siq);
 3808           }
 3809         }
 3810         return rc;
 3811       }
 3812 
 3813     } /* for */
 3814 
 3815     m_AVND_SU_ALL_TERM_SET(su);
 3816     avnd_su_siq_prc(cb, su);
 3817   }
 3818 
 3819   TRACE_LEAVE2("%u", rc);
 3820   return rc;
 3821 }
 3822 
 3823 /**
 3824  * This function checks if the sufailover is going on.
 3825  * @param su: ptr to the SU .
 3826  *
 3827  * @return true/false.
 3828  */
 3829 bool sufailover_in_progress(const AVND_SU *su) {
 3830   if (m_AVND_SU_IS_FAILED(su) && (su->sufailover) &&
 3831       (!m_AVND_SU_IS_RESTART(su)) &&
 3832       (avnd_cb->oper_state != SA_AMF_OPERATIONAL_DISABLED) && (!su->is_ncs) &&
 3833       m_AVND_SU_IS_FAILOVER(su))
 3834     return true;
 3835   return false;
 3836 }
 3837 
 3838 /**
 3839  * This function checks if the sufailover and node switchover are going on.
 3840  * @param su: ptr to the SU .
 3841  *
 3842  * @return true/false.
 3843  */
 3844 bool sufailover_during_nodeswitchover(const AVND_SU *su) {
 3845   if ((m_AVND_SU_IS_FAILED(su) && (su->sufailover) &&
 3846        (!m_AVND_SU_IS_RESTART(su)) &&
 3847        (avnd_cb->term_state == AVND_TERM_STATE_NODE_SWITCHOVER_STARTED) &&
 3848        (!su->is_ncs) && (m_AVND_SU_IS_FAILOVER(su))))
 3849     return true;
 3850 
 3851   return false;
 3852 }
 3853 
 3854 /**
 3855  * @brief  handler for restart recovery or admin op on su
 3856  *         when a SU is in terminating state.
 3857  * @param  ptr to avnd_cb.
 3858  * @param  ptr to su.
 3859  * @param  ptr to comp.
 3860  * @return  NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE.
 3861  */
 3862 uint32_t avnd_su_pres_terming_surestart_hdler(AVND_CB *cb, AVND_SU *su,
 3863                                               AVND_COMP *comp) {
 3864   AVND_COMP *curr_comp = 0;
 3865   AVND_SU_SI_REC *si = 0;
 3866   AVND_COMP_CSI_REC *csi = 0;
 3867   uint32_t rc = NCSCC_RC_SUCCESS;
 3868   TRACE_ENTER2("SURestart event in SU terminating state: '%s'",
 3869                su->name.c_str());
 3870 
 3871   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3872     TRACE("PI SU:'%s'", su->name.c_str());
 3873     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3874              m_NCS_DBLIST_FIND_LAST(&su->comp_list));
 3875          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3876                         m_NCS_DBLIST_FIND_PREV(&curr_comp->su_dll_node))) {
 3877       if ((curr_comp->pres == SA_AMF_PRESENCE_RESTARTING) ||
 3878           (curr_comp->pres == SA_AMF_PRESENCE_UNINSTANTIATED))
 3879         continue;
 3880       if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) {
 3881         if (m_AVND_SU_IS_RESTART(su) && m_AVND_SU_IS_FAILED(su))
 3882           rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3883                                      AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 3884         else
 3885           rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3886                                      AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 3887         if (NCSCC_RC_SUCCESS != rc) goto done;
 3888         break;
 3889       } else {
 3890         /*
 3891            For a NPI comp in SU, component FSM is always triggered at the time
 3892            of assignments. If this component is non-restartable then start
 3893            reassginment from the whole SU now.
 3894          */
 3895         if (m_AVND_COMP_IS_RESTART_DIS(curr_comp) &&
 3896             (curr_comp->csi_list.n_nodes > 0)) {
 3897           TRACE(
 3898               "Start reassignment to different SU as '%s' is"
 3899               " not restartable",
 3900               curr_comp->name.c_str());
 3901           su_send_suRestart_recovery_msg(su);
 3902           goto done;
 3903         } else {
 3904           // NPI comp in PI SU, clean it up now.
 3905           rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3906                                      AVND_COMP_CLC_PRES_FSM_EV_CLEANUP);
 3907           break;
 3908         }
 3909       }
 3910 
 3911     } /* for */
 3912   }
 3913 
 3914   /*TODO_SURESTART:Will relook for NPI SU as there seems a rare possbility for
 3915     surestart for NPI SU in terminating state .*/
 3916   /*
 3917    * If npi su, it'll have only one si-rec in the si-list. Pick the
 3918    * lowest ranked csi belonging to this si & trigger it's comp fsm.
 3919    */
 3920   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3921     TRACE("NPI SU:'%s'", su->name.c_str());
 3922     /* get the only si rec */
 3923     si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 3924     osafassert(si);
 3925 
 3926     csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_LAST(&si->csi_list);
 3927     if (csi) {
 3928       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 3929           csi, AVND_COMP_CSI_ASSIGN_STATE_RESTARTING);
 3930 
 3931       TRACE("Running the component clc FSM for csi:'%s', comp:%s",
 3932             csi->name.c_str(), csi->comp->name.c_str());
 3933       /* restart the comp */
 3934       rc = avnd_comp_clc_fsm_run(cb, csi->comp,
 3935                                  AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 3936       if (NCSCC_RC_SUCCESS != rc) goto done;
 3937     }
 3938     if (all_csis_in_restarting_state(su) == true) {
 3939       TRACE("All CSIs are in restarting state, so marking SU restarting");
 3940       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_RESTARTING);
 3941     }
 3942   }
 3943 done:
 3944   TRACE_LEAVE2("%u", rc);
 3945   return rc;
 3946 }
 3947 
 3948 /**
 3949  * @brief  handler for restart admin op on su
 3950  *         when a SU is in terminating state. Comp FSM will
 3951  *         invoke this event when a restartable component is terminated
 3952  *         during restart admin op on su.
 3953  * @param  ptr to avnd_cb.
 3954  * @param  ptr to su.
 3955  * @param  ptr to comp.
 3956  * @return  NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE.
 3957  */
 3958 uint32_t avnd_su_pres_terming_comprestart_hdler(AVND_CB *cb, AVND_SU *su,
 3959                                                 AVND_COMP *comp) {
 3960   uint32_t rc = NCSCC_RC_SUCCESS;
 3961   const std::string compname = comp ? comp->name : "none";
 3962   TRACE_ENTER2("Component restart event in the Instantiated state, '%s' : '%s'",
 3963                su->name.c_str(), compname.c_str());
 3964   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 3965     TRACE("PI SU");
 3966     AVND_COMP *curr_comp = nullptr;
 3967     osafassert(comp != nullptr);
 3968     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3969              m_NCS_DBLIST_FIND_PREV(&comp->su_dll_node));
 3970          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 3971                         m_NCS_DBLIST_FIND_PREV(&curr_comp->su_dll_node))) {
 3972       if ((curr_comp->pres == SA_AMF_PRESENCE_RESTARTING) ||
 3973           (curr_comp->pres == SA_AMF_PRESENCE_UNINSTANTIATED))
 3974         continue;
 3975       if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp)) {
 3976         TRACE("Running the component clc FSM");
 3977         rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 3978                                    AVND_COMP_CLC_PRES_FSM_EV_RESTART);
 3979         if (NCSCC_RC_SUCCESS != rc) goto done;
 3980         break;
 3981       }
 3982     }
 3983     if (!curr_comp) {
 3984       /*
 3985          It means all comps are terminated in surestart admin op.
 3986          Now instantiate SU honoring instantiation level.
 3987       */
 3988       rc = avnd_su_pres_fsm_run(cb, su, 0, AVND_SU_PRES_FSM_EV_INST);
 3989       if (NCSCC_RC_SUCCESS != rc) goto done;
 3990     }
 3991   }
 3992 done:
 3993   TRACE_LEAVE();
 3994   return rc;
 3995 }
 3996 
 3997 /**
 3998  * @brief  handler for instantiating a SU when it is in terminating state.
 3999  *         SU FSM will invoke this handler when all components are terminated.
 4000  *         It will start instantiating comps in SU.
 4001  * @param  ptr to avnd_cb.
 4002  * @param  ptr to su.
 4003  * @param  ptr to comp.
 4004  * @return  NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE.
 4005  */
 4006 uint32_t avnd_su_pres_terming_suinst_hdler(AVND_CB *cb, AVND_SU *su,
 4007                                            AVND_COMP *comp) {
 4008   AVND_COMP *curr_comp = 0;
 4009   AVND_SU_SI_REC *si = 0;
 4010   AVND_COMP_CSI_REC *csi = 0;
 4011   uint32_t rc = NCSCC_RC_SUCCESS;
 4012   TRACE_ENTER2("SU Instantiate event in Terminating state: '%s'",
 4013                su->name.c_str());
 4014 
 4015   /*
 4016    * If pi su, pick the first pi comp & trigger it's FSM with InstEv.
 4017    */
 4018   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 4019     TRACE("PI SU:'%s'", su->name.c_str());
 4020     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 4021              m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 4022          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 4023                         m_NCS_DBLIST_FIND_NEXT(&curr_comp->su_dll_node))) {
 4024       /* instantiate the pi comp */
 4025       TRACE("%s", curr_comp->name.c_str());
 4026       if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp) &&
 4027           ((curr_comp->pres == SA_AMF_PRESENCE_RESTARTING) ||
 4028            (curr_comp->pres == SA_AMF_PRESENCE_UNINSTANTIATED))) {
 4029         TRACE("Running the component CLC FSM ");
 4030         rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 4031                                    AVND_COMP_CLC_PRES_FSM_EV_INST);
 4032         if (NCSCC_RC_SUCCESS != rc) goto done;
 4033         break;
 4034       }
 4035     } /* for */
 4036     if ((curr_comp) && (curr_comp->pres == SA_AMF_PRESENCE_INSTANTIATING) &&
 4037         (su->pres == SA_AMF_PRESENCE_TERMINATING))
 4038       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATING);
 4039   }
 4040 
 4041   /*TODO_SURESTART:Will relook for NPI SU as there seems a rare possbility for
 4042     su instantiate event for NPI SU in terminating state .*/
 4043   /*
 4044    * If npi su, it'll have only one si-rec in the si-list. Pick the
 4045    * lowest ranked csi belonging to this si & trigger it's comp fsm.
 4046    */
 4047   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 4048     TRACE("NPI SU:'%s'", su->name.c_str());
 4049     si = (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 4050     osafassert(si);
 4051 
 4052     csi = (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_FIRST(&si->csi_list);
 4053     if ((csi) && (csi->comp)) {
 4054       /* mark the csi state assigning */
 4055       m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(
 4056           csi, AVND_COMP_CSI_ASSIGN_STATE_ASSIGNING);
 4057 
 4058       TRACE("Running the component CLC FSM ");
 4059       /* instantiate the comp */
 4060       rc = avnd_comp_clc_fsm_run(cb, csi->comp, AVND_COMP_CLC_PRES_FSM_EV_INST);
 4061       if (NCSCC_RC_SUCCESS != rc) goto done;
 4062       if ((csi->comp->pres == SA_AMF_PRESENCE_INSTANTIATING) &&
 4063           (su->pres == SA_AMF_PRESENCE_TERMINATING))
 4064         avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATING);
 4065     }
 4066   }
 4067 
 4068 done:
 4069   if (rc == NCSCC_RC_FAILURE)
 4070     avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATION_FAILED);
 4071   TRACE_LEAVE2("%u", rc);
 4072   return rc;
 4073 }
 4074 
 4075 /**
 4076  * @brief  During restart admin op on SU, a SU enters into INSTANTIATED state
 4077  *         as soon as the first component is succesfully instantiated. For all
 4078  * other components in SU, this handler will take care of their instantiation
 4079  * honoring instantiation-level.
 4080  * @param  ptr to avnd_cb.
 4081  * @param  ptr to su.
 4082  * @param  ptr to comp.
 4083  * @return  NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE.
 4084  */
 4085 uint32_t avnd_su_pres_inst_compinst_hdler(AVND_CB *cb, AVND_SU *su,
 4086                                           AVND_COMP *comp) {
 4087   AVND_COMP *curr_comp = 0;
 4088   AVND_COMP_CSI_REC *curr_csi = 0;
 4089   uint32_t rc = NCSCC_RC_SUCCESS;
 4090   const std::string compname = comp ? comp->name : "none";
 4091   TRACE_ENTER2(
 4092       "Component Instantiated event in the Instantiated state:'%s' : '%s'",
 4093       su->name.c_str(), compname.c_str());
 4094   osafassert(comp != nullptr);
 4095 
 4096   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 4097     TRACE("PI SU");
 4098     for (curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 4099              m_NCS_DBLIST_FIND_NEXT(&comp->su_dll_node));
 4100          curr_comp; curr_comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 4101                         m_NCS_DBLIST_FIND_NEXT(&curr_comp->su_dll_node))) {
 4102       if (curr_comp->pres == SA_AMF_PRESENCE_INSTANTIATED) continue;
 4103       if (m_AVND_COMP_TYPE_IS_PREINSTANTIABLE(curr_comp) &&
 4104           (curr_comp->pres == SA_AMF_PRESENCE_RESTARTING) &&
 4105           (m_AVND_SU_IS_RESTART(su))) {
 4106         TRACE("Running the component clc FSM for '%s'",
 4107               curr_comp->name.c_str());
 4108         rc = avnd_comp_clc_fsm_run(cb, curr_comp,
 4109                                    AVND_COMP_CLC_PRES_FSM_EV_INST);
 4110         if (NCSCC_RC_SUCCESS != rc) goto done;
 4111         break;
 4112       }
 4113     }
 4114     if (su_all_pi_comps_instantiated(su) == true)
 4115       rc = pi_su_instantiating_to_instantiated(su);
 4116   }
 4117 
 4118   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 4119     TRACE("NPI SU");
 4120     /* get the only csi rec */
 4121     curr_csi = m_AVND_CSI_REC_FROM_COMP_DLL_NODE_GET(
 4122         m_NCS_DBLIST_FIND_FIRST(&comp->csi_list));
 4123     osafassert(curr_csi);
 4124 
 4125     m_AVND_COMP_CSI_CURR_ASSIGN_STATE_SET(curr_csi,
 4126                                           AVND_COMP_CSI_ASSIGN_STATE_ASSIGNED);
 4127 
 4128     if (su->pres != SA_AMF_PRESENCE_INSTANTIATED)
 4129       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATED);
 4130 
 4131     /* get the next csi */
 4132     curr_csi =
 4133         (AVND_COMP_CSI_REC *)m_NCS_DBLIST_FIND_NEXT(&curr_csi->si_dll_node);
 4134     if ((curr_csi != nullptr) &&
 4135         (m_AVND_COMP_CSI_CURR_ASSIGN_STATE_IS_RESTARTING(curr_csi) == true) &&
 4136         (m_AVND_SU_IS_RESTART(su))) {
 4137       /* we have another csi. trigger the comp fsm with InstEv */
 4138       TRACE(
 4139           "There's another CSI:'%s', Running the component clc FSM for comp:'%s'",
 4140           curr_csi->name.c_str(), curr_csi->comp->name.c_str());
 4141       rc = avnd_comp_clc_fsm_trigger(cb, curr_csi->comp,
 4142                                      AVND_COMP_CLC_PRES_FSM_EV_INST);
 4143       if (NCSCC_RC_SUCCESS != rc) goto done;
 4144     }
 4145     /*If all comps are instantiated then reset SU params.*/
 4146     if (all_csis_in_assigned_state(su) == true) {
 4147       rc = npi_su_instantiating_to_instantiated(su);
 4148     }
 4149   }
 4150 done:
 4151   TRACE_LEAVE2("%u", rc);
 4152   return rc;
 4153 }
 4154 
 4155 /**
 4156  * @brief       This function processes events from IR thread.
 4157  *
 4158  * @param       ptr to the AvND control block
 4159  * @param       ptr to the AvND event
 4160  *
 4161  * @return      NCSCC_RC_FAILURE/NCSCC_RC_SUCCESS
 4162  */
 4163 uint32_t avnd_evt_ir_evh(struct avnd_cb_tag *cb, struct avnd_evt_tag *evt) {
 4164   uint32_t rc = NCSCC_RC_SUCCESS;
 4165   AVND_SU *su = 0;
 4166   TRACE_ENTER2("su name '%s'",
 4167                osaf_extended_name_borrow(&evt->info.ir_evt.su_name));
 4168 
 4169   /* get the su */
 4170   su = avnd_sudb_rec_get(cb->sudb, Amf::to_string(&evt->info.ir_evt.su_name));
 4171   if (!su) {
 4172     TRACE("SU'%s', not found in DB",
 4173           osaf_extended_name_borrow(&evt->info.ir_evt.su_name));
 4174     goto done;
 4175   }
 4176 
 4177   TRACE("SU term state is set to false");
 4178   /* Reset admn term operation flag */
 4179   m_AVND_SU_ADMN_TERM_RESET(su);
 4180   /* Add components belonging to this SU if components were not added before.
 4181      This can happen in runtime when SU is first added and then comp. When SU is
 4182      added amfd will send SU info to amfnd, at this point of time no component
 4183      exists in IMM DB, so SU list of comp is empty. When comp are added later,
 4184      it is not sent to amfnd as amfnd reads comp info from IMM DB. Now when
 4185      unlock-inst is done then avnd_evt_avd_su_pres_msg is called. At this point
 4186      of time, we are not having Comp info in SU list, so need to add it.
 4187 
 4188      If component exists as it would be in case controller is coming up with all
 4189      entities configured, then avnd_comp_config_get_su() will not read anything,
 4190      it will return success.
 4191 
 4192      Trying to read config info of openSAF SUs may result in a deadlock
 4193      condition when IMMND calls AMF register sync call(after AMF invokes
 4194      instantiate script in NoRed SU instantiation sequence) and amfnd reads
 4195      immsv database using search_initializie sync api(AMF reads database for
 4196      middleware 2N SUs during 2N Red SU instantiation). This is purely dependent
 4197      on timing when immnd is registering with AMF and AMF is reading config from
 4198      immnd during controller coming up. Fix for the above problem is that
 4199      Middleware Components wont be dynamically added in the case of openSAF SUs,
 4200      so don't refresh config info if it is openSAF SU. */
 4201 
 4202   if ((false == su->is_ncs) && (evt->info.ir_evt.status == false)) {
 4203     if (cb->scs_absence_max_duration == 0) {
 4204       m_AVND_SU_REG_FAILED_SET(su);
 4205       /* Will transition to instantiation-failed when instantiated */
 4206       LOG_ER("'%s':FAILED", __FUNCTION__);
 4207       rc = NCSCC_RC_FAILURE;
 4208       goto done;
 4209     } else {
 4210       // @TODO(garylee) this is a temporary workaround: IMM is not accepting OM
 4211       // connections and a component needs to be restarted.
 4212       LOG_CR(
 4213           "'%s': failed to refresh components in SU. Attempt to reuse old config",
 4214           __FUNCTION__);
 4215     }
 4216   }
 4217   /* trigger su instantiation for pi su */
 4218   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 4219     /* Update the comp oper state. */
 4220     for (AVND_COMP *comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 4221              m_NCS_DBLIST_FIND_FIRST(&su->comp_list));
 4222          comp; comp = m_AVND_COMP_FROM_SU_DLL_NODE_GET(
 4223                    m_NCS_DBLIST_FIND_NEXT(&comp->su_dll_node))) {
 4224       rc = avnd_comp_oper_state_avd_sync(avnd_cb, comp);
 4225     }
 4226     TRACE("SU instantiation for PI SUs, running the SU presence state FSM:'%s'",
 4227           su->name.c_str());
 4228     // If SU has been already instantiated, inform amfd
 4229     if ((cb->led_state == AVND_LED_STATE_RED) &&
 4230         (su->pres == SA_AMF_PRESENCE_INSTANTIATED) &&
 4231         (su_all_pi_comps_instantiated(su) == true) &&
 4232         (m_AVND_SU_OPER_STATE_IS_ENABLED(su))) {
 4233         TRACE("SU oper state is enabled and pres state is instantiated.");
 4234         rc = avnd_di_oper_send(cb, su, 0);
 4235     } else {
 4236         rc = avnd_su_pres_fsm_run(cb, su, 0, AVND_SU_PRES_FSM_EV_INST);
 4237     }
 4238   } else {
 4239     if (m_AVND_SU_IS_REG_FAILED(su)) {
 4240       /* The SU configuration is bad, we cannot do much other transition to
 4241        * failed state */
 4242       TRACE_2("SU Configuration is bad");
 4243       avnd_su_pres_state_set(cb, su, SA_AMF_PRESENCE_INSTANTIATION_FAILED);
 4244       m_AVND_SU_ALL_TERM_RESET(su);
 4245     } else
 4246       osafassert(0);
 4247   }
 4248 
 4249 done:
 4250   TRACE_LEAVE();
 4251   return rc;
 4252 }
 4253 
 4254 static uint32_t avnd_su_pres_termfailed_comptermfail_or_compuninst(
 4255     AVND_CB *cb, AVND_SU *su, AVND_COMP *comp) {
 4256   uint32_t rc = NCSCC_RC_SUCCESS;
 4257   const std::string compname = comp ? comp->name : "none";
 4258   TRACE_ENTER2(
 4259       "CompTermFailed/CompUnInstantiated event in the TermFailed state:'%s', '%s'",
 4260       su->name.c_str(), compname.c_str());
 4261 
 4262   // PI SU case.
 4263   if (m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 4264     TRACE_1("PI SU");
 4265     if ((all_comps_terminated_in_su(su, true) == true) &&
 4266         (su->si_list.n_nodes != 0) && (m_AVND_SU_IS_ASSIGN_PEND(su)) &&
 4267         (su->avnd_su_check_sis_previous_assign_state(
 4268              AVND_SU_SI_ASSIGN_STATE_UNASSIGNED) == true)) {
 4269       TRACE_2("Informing AMFD of su-failover");
 4270       rc = avnd_di_oper_send(cb, su, AVSV_ERR_RCVR_SU_FAILOVER);
 4271       avnd_su_si_del(cb, su->name);
 4272     }
 4273   }
 4274 
 4275   // NPI SU case.
 4276   if (!m_AVND_SU_IS_PREINSTANTIABLE(su)) {
 4277     TRACE_1("NPI SU");
 4278     AVND_SU_SI_REC *si =
 4279         (AVND_SU_SI_REC *)m_NCS_DBLIST_FIND_FIRST(&su->si_list);
 4280 
 4281     /*
 4282        During shutdown phase, all comps of NPI SU are terminated as a part of
 4283        removal of assignments. If a SU enters in TERM_FAILED state then in order
 4284        to complete shutdown sequence generate a si-oper done indication.
 4285      */
 4286     if ((si != nullptr) && (m_AVND_IS_SHUTTING_DOWN(cb)) &&
 4287         (m_AVND_SU_SI_CURR_ASSIGN_STATE_IS_REMOVING(si)) &&
 4288         (all_comps_terminated_in_su(su, true) == true)) {
 4289       rc = avnd_su_si_oper_done(cb, su, si);
 4290     }
 4291   }
 4292 
 4293   TRACE_LEAVE();
 4294   return rc;
 4295 }
 4296 
 4297 uint32_t avnd_evt_avd_contained_su_evh(AVND_CB *cb, AVND_EVT *evt) {
 4298   AVSV_D2N_CONTAINED_SU_MSG_INFO *info = 0;
 4299   AVND_SU *contained_su = 0, *container_su = 0;
 4300   uint32_t rc = NCSCC_RC_SUCCESS;
 4301   AVND_EVT *evt_ir = 0;
 4302 
 4303   TRACE_ENTER();
 4304 
 4305   if (!m_AVND_CB_IS_AVD_UP(cb)) {
 4306     TRACE("AVD is not yet up");
 4307     goto done;
 4308   }
 4309 
 4310   if (m_AVND_IS_SHUTTING_DOWN(cb)) {
 4311     TRACE("AMFND is in SHUTDOWN state");
 4312     goto done;
 4313   }
 4314 
 4315   info = &evt->info.avd->msg_info.d2n_contained_su_msg_info;
 4316 
 4317   avnd_msgid_assert(info->msg_id);
 4318   cb->rcv_msg_id = info->msg_id;
 4319 
 4320   container_su = avnd_sudb_rec_get(cb->sudb, Amf::to_string(&info->container_su_name));
 4321   if (!container_su) {
 4322     TRACE("SU'%s', not found in DB", osaf_extended_name_borrow(&info->container_su_name));
 4323     goto done;
 4324   }
 4325 
 4326   contained_su = avnd_sudb_rec_get(cb->sudb, Amf::to_string(&info->contained_su_name));
 4327   if (!contained_su) {
 4328     TRACE("SU'%s', not found in DB", osaf_extended_name_borrow(&info->contained_su_name));
 4329     goto done;
 4330   }
 4331   contained_su->container_su_name = container_su->name;
 4332   TRACE("Sending to Imm thread.");
 4333   evt_ir = avnd_evt_create(cb, AVND_EVT_IR, 0, nullptr, &info->contained_su_name, 0, 0);
 4334   rc = m_NCS_IPC_SEND(&ir_cb.mbx, evt_ir, evt_ir->priority);
 4335   if (NCSCC_RC_SUCCESS != rc)
 4336          LOG_CR("AvND send event to IR mailbox failed, type = %u", evt_ir->type);
 4337   /* if failure, free the event */
 4338   if (NCSCC_RC_SUCCESS != rc && evt_ir) avnd_evt_destroy(evt_ir);
 4339 done:
 4340   TRACE_LEAVE2("%u", rc);
 4341   return rc;
 4342 }