"Fossies" - the Fresh Open Source Software Archive

Member "opensaf-5.21.09/src/imm/immnd/immnd_evt.c" (14 Sep 2021, 412423 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 "immnd_evt.c" 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  * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
    5  * Copyright Ericsson AB 2017, 2020 - 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): Ericsson AB
   17  *
   18  */
   19 
   20 /*****************************************************************************
   21   FILE NAME: immcn_evt.c
   22 
   23   DESCRIPTION: IMMND Event handling routines
   24 
   25   FUNCTIONS INCLUDED in this module:
   26   immnd_process_evt .........IMMND Event processing routine.
   27 ******************************************************************************/
   28 
   29 #include <sys/types.h>
   30 #include <pwd.h>
   31 #include "base/osaf_secutil.h"
   32 #include "immnd.h"
   33 #include "imm/immnd/immnd_utils.h"
   34 #include "imm/common/immsv_api.h"
   35 #include "base/ncssysf_mem.h"
   36 #include "mds/mds_papi.h"
   37 #include "base/osaf_extended_name.h"
   38 
   39 /* Adjust to 90% of MDS_DIRECT_BUF_MAXSIZE  */
   40 #define IMMND_SEARCH_BUNDLE_SIZE ((MDS_DIRECT_BUF_MAXSIZE / 100) * 90)
   41 #define IMMND_MAX_SEARCH_RESULT (IMMND_SEARCH_BUNDLE_SIZE / 300)
   42 
   43 static SaAisErrorT immnd_fevs_local_checks(IMMND_CB *cb, IMMSV_FEVS *fevsReq,
   44                        const IMMSV_SEND_INFO *sinfo);
   45 static uint32_t immnd_evt_proc_cb_dump(IMMND_CB *cb);
   46 static uint32_t immnd_evt_proc_imm_init(IMMND_CB *cb, IMMND_EVT *evt,
   47                     IMMSV_SEND_INFO *sinfo, bool isOm);
   48 static uint32_t immnd_evt_proc_imm_finalize(IMMND_CB *cb, IMMND_EVT *evt,
   49                         IMMSV_SEND_INFO *sinfo, bool isOm);
   50 static uint32_t immnd_evt_proc_imm_resurrect(IMMND_CB *cb, IMMND_EVT *evt,
   51                          IMMSV_SEND_INFO *sinfo, bool isOm);
   52 static uint32_t immnd_evt_proc_imm_client_high(IMMND_CB *cb, IMMND_EVT *evt,
   53                            IMMSV_SEND_INFO *sinfo,
   54                            bool isOm);
   55 static uint32_t immnd_evt_proc_recover_ccb_result(IMMND_CB *cb, IMMND_EVT *evt,
   56                           IMMSV_SEND_INFO *sinfo);
   57 static uint32_t immnd_evt_proc_cl_imma_timeout(IMMND_CB *cb, IMMND_EVT *evt);
   58 
   59 static uint32_t immnd_evt_proc_sync_finalize(IMMND_CB *cb, IMMND_EVT *evt,
   60                          IMMSV_SEND_INFO *sinfo);
   61 
   62 static uint32_t immnd_evt_proc_admowner_init(IMMND_CB *cb, IMMND_EVT *evt,
   63                          IMMSV_SEND_INFO *sinfo);
   64 static uint32_t immnd_evt_proc_impl_set(IMMND_CB *cb, IMMND_EVT *evt,
   65                     IMMSV_SEND_INFO *sinfo);
   66 static uint32_t immnd_evt_proc_ccb_init(IMMND_CB *cb, IMMND_EVT *evt,
   67                     IMMSV_SEND_INFO *sinfo);
   68 
   69 static uint32_t immnd_evt_proc_rt_update(IMMND_CB *cb, IMMND_EVT *evt,
   70                      IMMSV_SEND_INFO *sinfo);
   71 
   72 static void immnd_evt_proc_discard_impl(IMMND_CB *cb, IMMND_EVT *evt,
   73                     bool originatedAtThisNd,
   74                     SaImmHandleT clnt_hdl,
   75                     MDS_DEST reply_dest);
   76 
   77 static void immnd_evt_proc_discard_node(IMMND_CB *cb, IMMND_EVT *evt,
   78                     bool originatedAtThisNd,
   79                     SaImmHandleT clnt_hdl,
   80                     MDS_DEST reply_dest);
   81 
   82 static void immnd_evt_proc_adminit_rsp(IMMND_CB *cb, IMMND_EVT *evt,
   83                        bool originatedAtThisNd,
   84                        SaImmHandleT clnt_hdl,
   85                        MDS_DEST reply_dest);
   86 
   87 static void immnd_evt_proc_admo_finalize(IMMND_CB *cb, IMMND_EVT *evt,
   88                      bool originatedAtThisNd,
   89                      SaImmHandleT clnt_hdl,
   90                      MDS_DEST reply_dest);
   91 
   92 // static void immnd_evt_proc_admo_hard_finalize(IMMND_CB *cb,
   93 //                        IMMND_EVT *evt,
   94 //                        bool originatedAtThisNd, SaImmHandleT
   95 //clnt_hdl, MDS_DEST reply_dest);
   96 
   97 static void immnd_evt_proc_admo_set(IMMND_CB *cb, IMMND_EVT *evt,
   98                     bool originatedAtThisNd,
   99                     SaImmHandleT clnt_hdl, MDS_DEST reply_dest);
  100 
  101 static void immnd_evt_proc_admo_release(IMMND_CB *cb, IMMND_EVT *evt,
  102                     bool originatedAtThisNd,
  103                     SaImmHandleT clnt_hdl,
  104                     MDS_DEST reply_dest);
  105 
  106 static void immnd_evt_proc_admo_clear(IMMND_CB *cb, IMMND_EVT *evt,
  107                       bool originatedAtThisNd,
  108                       SaImmHandleT clnt_hdl,
  109                       MDS_DEST reply_dest);
  110 
  111 static void immnd_evt_proc_finalize_sync(IMMND_CB *cb, IMMND_EVT *evt,
  112                      bool originatedAtThisNd,
  113                      SaImmHandleT clnt_hdl,
  114                      MDS_DEST reply_dest);
  115 
  116 static void immnd_evt_proc_impl_set_rsp(IMMND_CB *cb, IMMND_EVT *evt,
  117                     bool originatedAtThisNd,
  118                     SaImmHandleT clnt_hdl,
  119                     MDS_DEST reply_dest);
  120 
  121 static void immnd_evt_proc_impl_clr(IMMND_CB *cb, IMMND_EVT *evt,
  122                     bool originatedAtThisNd,
  123                     SaImmHandleT clnt_hdl, MDS_DEST reply_dest);
  124 
  125 static void immnd_evt_proc_cl_impl_set(IMMND_CB *cb, IMMND_EVT *evt,
  126                        bool originatedAtThisNd,
  127                        SaImmHandleT clnt_hdl,
  128                        MDS_DEST reply_dest);
  129 
  130 static void immnd_evt_proc_cl_impl_rel(IMMND_CB *cb, IMMND_EVT *evt,
  131                        bool originatedAtThisNd,
  132                        SaImmHandleT clnt_hdl,
  133                        MDS_DEST reply_dest);
  134 
  135 static void immnd_evt_proc_obj_impl_set(IMMND_CB *cb, IMMND_EVT *evt,
  136                     bool originatedAtThisNd,
  137                     SaImmHandleT clnt_hdl,
  138                     MDS_DEST reply_dest);
  139 
  140 static void immnd_evt_proc_obj_impl_rel(IMMND_CB *cb, IMMND_EVT *evt,
  141                     bool originatedAtThisNd,
  142                     SaImmHandleT clnt_hdl,
  143                     MDS_DEST reply_dest);
  144 
  145 static void immnd_evt_proc_ccbinit_rsp(IMMND_CB *cb, IMMND_EVT *evt,
  146                        bool originatedAtThisNd,
  147                        SaImmHandleT clnt_hdl,
  148                        MDS_DEST reply_dest);
  149 
  150 static void immnd_evt_ccb_augment_init(IMMND_CB *cb, IMMND_EVT *evt,
  151                        bool originatedAtThisNd,
  152                        SaImmHandleT clnt_hdl,
  153                        MDS_DEST reply_dest);
  154 
  155 static void immnd_evt_ccb_augment_admo(IMMND_CB *cb, IMMND_EVT *evt,
  156                        bool originatedAtThisNd,
  157                        SaImmHandleT clnt_hdl,
  158                        MDS_DEST reply_dest);
  159 
  160 static void immnd_evt_proc_admop(IMMND_CB *cb, IMMND_EVT *evt,
  161                  bool originatedAtThisNd, SaImmHandleT clnt_hdl,
  162                  MDS_DEST reply_dest);
  163 
  164 static void immnd_evt_proc_class_create(IMMND_CB *cb, IMMND_EVT *evt,
  165                     bool originatedAtThisNd,
  166                     SaImmHandleT clnt_hdl,
  167                     MDS_DEST reply_dest);
  168 
  169 static void immnd_evt_proc_class_delete(IMMND_CB *cb, IMMND_EVT *evt,
  170                     bool originatedAtThisNd,
  171                     SaImmHandleT clnt_hdl,
  172                     MDS_DEST reply_dest);
  173 
  174 static void immnd_evt_proc_object_create(IMMND_CB *cb, IMMND_EVT *evt,
  175                      bool originatedAtThisNd,
  176                      SaImmHandleT clnt_hdl,
  177                      MDS_DEST reply_dest);
  178 
  179 static void immnd_evt_proc_rt_object_create(IMMND_CB *cb, IMMND_EVT *evt,
  180                         bool originatedAtThisNd,
  181                         SaImmHandleT clnt_hdl,
  182                         MDS_DEST reply_dest);
  183 
  184 static void immnd_evt_proc_object_modify(IMMND_CB *cb, IMMND_EVT *evt,
  185                      bool originatedAtThisNd,
  186                      SaImmHandleT clnt_hdl,
  187                      MDS_DEST reply_dest);
  188 
  189 static void immnd_evt_proc_rt_object_modify(IMMND_CB *cb, IMMND_EVT *evt,
  190                         bool originatedAtThisNd,
  191                         SaImmHandleT clnt_hdl,
  192                         MDS_DEST reply_dest,
  193                         SaUint64T msgNo);
  194 
  195 static void immnd_evt_proc_object_delete(IMMND_CB *cb, IMMND_EVT *evt,
  196                      bool originatedAtThisNd,
  197                      SaImmHandleT clnt_hdl,
  198                      MDS_DEST reply_dest);
  199 
  200 static void immnd_evt_proc_rt_object_delete(IMMND_CB *cb, IMMND_EVT *evt,
  201                         bool originatedAtThisNd,
  202                         SaImmHandleT clnt_hdl,
  203                         MDS_DEST reply_dest);
  204 
  205 static void immnd_evt_pbe_admop_rsp(IMMND_CB *cb, IMMND_EVT *evt,
  206                     bool originatedAtThisNd,
  207                     SaImmHandleT clnt_hdl, MDS_DEST reply_dest);
  208 
  209 static void immnd_evt_proc_object_sync(IMMND_CB *cb, IMMND_EVT *evt,
  210                        bool originatedAtThisNd,
  211                        SaImmHandleT clnt_hdl,
  212                        MDS_DEST reply_dest, SaUint64T msgNo);
  213 
  214 static void immnd_evt_proc_ccb_apply(IMMND_CB *cb, IMMND_EVT *evt,
  215                      bool originatedAtThisNd,
  216                      SaImmHandleT clnt_hdl, MDS_DEST reply_dest,
  217                      bool validateOnly);
  218 
  219 static void immnd_evt_proc_ccb_compl_rsp(IMMND_CB *cb, IMMND_EVT *evt,
  220                      bool originatedAtThisNd,
  221                      SaImmHandleT clnt_hdl,
  222                      MDS_DEST reply_dest);
  223 
  224 static uint32_t immnd_evt_proc_admop_rsp(IMMND_CB *cb, IMMND_EVT *evt,
  225                      IMMSV_SEND_INFO *sinfo, bool async,
  226                      bool local);
  227 
  228 static uint32_t immnd_evt_proc_fevs_forward(IMMND_CB *cb, IMMND_EVT *evt,
  229                         IMMSV_SEND_INFO *sinfo,
  230                         bool onStack, bool newMsg);
  231 static uint32_t immnd_evt_proc_fevs_rcv(IMMND_CB *cb, IMMND_EVT *evt,
  232                     IMMSV_SEND_INFO *sinfo);
  233 
  234 static uint32_t immnd_evt_proc_intro_rsp(IMMND_CB *cb, IMMND_EVT *evt,
  235                      IMMSV_SEND_INFO *sinfo);
  236 
  237 static uint32_t immnd_evt_proc_sync_req(IMMND_CB *cb, IMMND_EVT *evt,
  238                     IMMSV_SEND_INFO *sinfo);
  239 
  240 static uint32_t immnd_evt_proc_loading_ok(IMMND_CB *cb, IMMND_EVT *evt,
  241                       IMMSV_SEND_INFO *sinfo);
  242 
  243 static uint32_t immnd_evt_proc_dump_ok(IMMND_CB *cb, IMMND_EVT *evt,
  244                        IMMSV_SEND_INFO *sinfo);
  245 
  246 static uint32_t immnd_evt_proc_start_sync(IMMND_CB *cb, IMMND_EVT *evt,
  247                       IMMSV_SEND_INFO *sinfo);
  248 
  249 static uint32_t immnd_evt_proc_abort_sync(IMMND_CB *cb, IMMND_EVT *evt,
  250                       IMMSV_SEND_INFO *sinfo);
  251 static uint32_t immnd_evt_proc_pbe_prto_purge_mutations(IMMND_CB *cb,
  252                             IMMND_EVT *evt,
  253                             IMMSV_SEND_INFO *sinfo);
  254 
  255 static uint32_t immnd_evt_proc_class_desc_get(IMMND_CB *cb, IMMND_EVT *evt,
  256                           IMMSV_SEND_INFO *sinfo);
  257 static uint32_t immnd_evt_proc_search_init(IMMND_CB *cb, IMMND_EVT *evt,
  258                        IMMSV_SEND_INFO *sinfo);
  259 static uint32_t immnd_evt_proc_search_next(IMMND_CB *cb, IMMND_EVT *evt,
  260                        IMMSV_SEND_INFO *sinfo);
  261 
  262 static uint32_t immnd_evt_proc_rt_update_pull(IMMND_CB *cb, IMMND_EVT *evt,
  263                           IMMSV_SEND_INFO *sinfo);
  264 
  265 static uint32_t immnd_evt_proc_oi_att_pull_rpl(IMMND_CB *cb, IMMND_EVT *evt,
  266                            IMMSV_SEND_INFO *sinfo);
  267 
  268 static uint32_t immnd_evt_proc_remote_search_rsp(IMMND_CB *cb, IMMND_EVT *evt,
  269                          IMMSV_SEND_INFO *sinfo);
  270 
  271 static uint32_t immnd_evt_proc_search_finalize(IMMND_CB *cb, IMMND_EVT *evt,
  272                            IMMSV_SEND_INFO *sinfo);
  273 
  274 static uint32_t immnd_evt_proc_accessor_get(IMMND_CB *cb, IMMND_EVT *evt,
  275                         IMMSV_SEND_INFO *sinfo);
  276 
  277 static uint32_t immnd_evt_proc_safe_read(IMMND_CB *cb, IMMND_EVT *evt,
  278                      IMMSV_SEND_INFO *sinfo);
  279 
  280 static uint32_t immnd_evt_proc_mds_evt(IMMND_CB *cb, IMMND_EVT *evt);
  281 
  282 static void immnd_evt_ccb_abort(IMMND_CB *cb, SaUint32T ccbId,
  283                 SaUint32T **clientArr, SaUint32T *clArrSize,
  284                 SaUint32T *nodeId);
  285 
  286 static uint32_t immnd_evt_proc_reset(IMMND_CB *cb, IMMND_EVT *evt,
  287                      IMMSV_SEND_INFO *sinfo);
  288 
  289 static uint32_t immnd_evt_impl_delete(IMMND_CB *cb, IMMND_EVT *evt);
  290 
  291 static uint32_t immnd_syncr_timeout_update_all(SaTimeT syncrTimeout);
  292 
  293 #if 0 /* Only for debug */
  294 static void printImmValue(SaImmValueTypeT t, IMMSV_EDU_ATTR_VAL *v)
  295 {
  296     switch (t) {
  297     case SA_IMM_ATTR_SAINT32T:
  298         TRACE_2("INT32: %i", v->val.saint32);
  299         break;
  300     case SA_IMM_ATTR_SAUINT32T:
  301         TRACE_2("UINT32: %u", v->val.sauint32);
  302         break;
  303     case SA_IMM_ATTR_SAINT64T:
  304         TRACE_2("INT64: %lli", v->val.saint64);
  305         break;
  306     case SA_IMM_ATTR_SAUINT64T:
  307         TRACE_2("UINT64: %llu", v->val.sauint64);
  308         break;
  309     case SA_IMM_ATTR_SATIMET:
  310         TRACE_2("TIME: %llu", v->val.satime);
  311         break;
  312     case SA_IMM_ATTR_SANAMET:
  313         TRACE_2("NAME: %u/%s", v->val.x.size, v->val.x.buf);
  314         break;
  315     case SA_IMM_ATTR_SAFLOATT:
  316         TRACE_2("FLOAT: %f", v->val.safloat);
  317         break;
  318     case SA_IMM_ATTR_SADOUBLET:
  319         TRACE_2("DOUBLE: %f", v->val.sadouble);
  320         break;
  321     case SA_IMM_ATTR_SASTRINGT:
  322         TRACE_2("STRING: %u/%s", v->val.x.size, v->val.x.buf);
  323         break;
  324     case SA_IMM_ATTR_SAANYT:
  325         TRACE_2("ANYT: %u/%s", v->val.x.size, v->val.x.buf);
  326         break;
  327     default:
  328         TRACE_2("ERRONEOUS VALUE TAG: %i", t);
  329         break;
  330     }
  331 }
  332 #endif
  333 
  334 /****************************************************************************
  335  * Name          : immnd_evt_destroy
  336  *
  337  * Description   : Function to process the
  338  *                 from Applications.
  339  *
  340  * Arguments     : IMMSV_EVT *evt - Received Event structure
  341  *                 bool onheap - false => dont deallocate root
  342  *
  343  * Return Values : NCSCC_RC_SUCCESS/Error.
  344  *
  345  * Notes         : None.
  346  *****************************************************************************/
  347 
  348 uint32_t immnd_evt_destroy(IMMSV_EVT *evt, bool onheap, uint32_t line)
  349 {
  350     uint32_t rc = NCSCC_RC_SUCCESS;
  351 
  352     if (evt == NULL) {
  353         /* LOG */
  354         return NCSCC_RC_SUCCESS;
  355     }
  356 
  357     if (evt->info.immnd.dont_free_me)
  358         return NCSCC_RC_SUCCESS;
  359 
  360     if (evt->type != IMMSV_EVT_TYPE_IMMND)
  361         return NCSCC_RC_SUCCESS;
  362 
  363     if ((evt->info.immnd.type == IMMND_EVT_A2ND_IMM_ADMOP) ||
  364         (evt->info.immnd.type == IMMND_EVT_A2ND_IMM_ADMOP_ASYNC)) {
  365         /*TODO See TODO 12345 code repeated (almost) in imma_om_api.c
  366            free-1 */
  367         free(evt->info.immnd.info.admOpReq.objectName.buf);
  368         evt->info.immnd.info.admOpReq.objectName.buf = NULL;
  369         while (evt->info.immnd.info.admOpReq.params) {
  370             IMMSV_ADMIN_OPERATION_PARAM *p =
  371                 evt->info.immnd.info.admOpReq.params;
  372             evt->info.immnd.info.admOpReq.params = p->next;
  373 
  374             if (p->paramName.buf) { /*free-3 */
  375                 free(p->paramName.buf);
  376                 p->paramName.buf = NULL;
  377                 p->paramName.size = 0;
  378             }
  379             immsv_evt_free_att_val(&(p->paramBuffer),
  380                            p->paramType); /*free-4 */
  381             p->next = NULL;
  382             free(p); /*free-2 */
  383         }
  384     } else if ((evt->info.immnd.type == IMMND_EVT_A2ND_ADMOP_RSP_2) ||
  385            (evt->info.immnd.type == IMMND_EVT_A2ND_ASYNC_ADMOP_RSP_2) ||
  386            (evt->info.immnd.type == IMMND_EVT_ND2ND_ADMOP_RSP_2) ||
  387            (evt->info.immnd.type ==
  388             IMMND_EVT_ND2ND_ASYNC_ADMOP_RSP_2)) {
  389         while (evt->info.immnd.info.admOpRsp.parms) {
  390             IMMSV_ADMIN_OPERATION_PARAM *p =
  391                 evt->info.immnd.info.admOpRsp.parms;
  392             evt->info.immnd.info.admOpRsp.parms = p->next;
  393 
  394             if (p->paramName.buf) { /*free-b */
  395                 free(p->paramName.buf);
  396                 p->paramName.buf = NULL;
  397                 p->paramName.size = 0;
  398             }
  399             immsv_evt_free_att_val(&(p->paramBuffer),
  400                            p->paramType); /*free-c */
  401             p->next = NULL;
  402             free(p); /*free-a */
  403         }
  404     } else if ((evt->info.immnd.type == IMMND_EVT_D2ND_GLOB_FEVS_REQ) ||
  405            (evt->info.immnd.type == IMMND_EVT_A2ND_IMM_FEVS) ||
  406            (evt->info.immnd.type == IMMND_EVT_D2ND_GLOB_FEVS_REQ_2) ||
  407            (evt->info.immnd.type == IMMND_EVT_A2ND_IMM_FEVS_2)) {
  408         if (evt->info.immnd.info.fevsReq.msg.buf != NULL) {
  409             free(evt->info.immnd.info.fevsReq.msg.buf);
  410             evt->info.immnd.info.fevsReq.msg.buf = NULL;
  411             evt->info.immnd.info.fevsReq.msg.size = 0;
  412         }
  413     } else if (evt->info.immnd.type == IMMND_EVT_A2ND_RT_ATT_UPPD_RSP) {
  414         free(evt->info.immnd.info.rtAttUpdRpl.sr.objectName.buf);
  415         evt->info.immnd.info.rtAttUpdRpl.sr.objectName.buf = NULL;
  416         evt->info.immnd.info.rtAttUpdRpl.sr.objectName.size = 0;
  417         immsv_evt_free_attrNames(
  418             evt->info.immnd.info.rtAttUpdRpl.sr.attributeNames);
  419         evt->info.immnd.info.rtAttUpdRpl.sr.attributeNames = NULL;
  420     } else if (evt->info.immnd.type == IMMND_EVT_ND2ND_SEARCH_REMOTE) {
  421         free(evt->info.immnd.info.searchRemote.objectName.buf);
  422         evt->info.immnd.info.searchRemote.objectName.buf = NULL;
  423         evt->info.immnd.info.searchRemote.objectName.size = 0;
  424         immsv_evt_free_attrNames(
  425             evt->info.immnd.info.searchRemote.attributeNames);
  426         evt->info.immnd.info.searchRemote.attributeNames = NULL;
  427     } else if (evt->info.immnd.type == IMMND_EVT_ND2ND_SEARCH_REMOTE_RSP) {
  428         freeSearchNext(&evt->info.immnd.info.rspSrchRmte.runtimeAttrs,
  429                    false);
  430     } else if ((evt->info.immnd.type == IMMND_EVT_A2ND_SEARCHINIT) ||
  431            (evt->info.immnd.type == IMMND_EVT_A2ND_ACCESSOR_GET) ||
  432            (evt->info.immnd.type == IMMND_EVT_A2ND_OBJ_SAFE_READ)) {
  433         free(evt->info.immnd.info.searchInit.rootName.buf);
  434         evt->info.immnd.info.searchInit.rootName.buf = NULL;
  435         evt->info.immnd.info.searchInit.rootName.size = 0;
  436 
  437         if (evt->info.immnd.info.searchInit.searchParam.present ==
  438             ImmOmSearchParameter_PR_oneAttrParam ||
  439             evt->info.immnd.info.searchInit.searchParam.present ==
  440             ImmOmSearchParameter_PR_nonExtendedName_oneAttrParam) {
  441             free(evt->info.immnd.info.searchInit.searchParam.choice
  442                  .oneAttrParam.attrName.buf);
  443             evt->info.immnd.info.searchInit.searchParam.choice
  444                 .oneAttrParam.attrName.buf = NULL;
  445             evt->info.immnd.info.searchInit.searchParam.choice
  446                 .oneAttrParam.attrName.size = 0;
  447             immsv_evt_free_att_val(
  448                 &(evt->info.immnd.info.searchInit.searchParam.choice
  449                   .oneAttrParam.attrValue),
  450                 evt->info.immnd.info.searchInit.searchParam.choice
  451                 .oneAttrParam.attrValueType);
  452         }
  453 
  454         immsv_evt_free_attrNames(
  455             evt->info.immnd.info.searchInit.attributeNames);
  456         evt->info.immnd.info.searchInit.attributeNames = NULL;
  457     } else if ((evt->info.immnd.type == IMMND_EVT_ND2ND_SYNC_FINALIZE) ||
  458            (evt->info.immnd.type == IMMND_EVT_ND2ND_SYNC_FINALIZE_2)) {
  459         immsv_evt_free_admo(evt->info.immnd.info.finSync.adminOwners);
  460         evt->info.immnd.info.finSync.adminOwners = NULL;
  461         immsv_evt_free_impl(evt->info.immnd.info.finSync.implementers);
  462         evt->info.immnd.info.finSync.implementers = NULL;
  463         immsv_evt_free_classList(evt->info.immnd.info.finSync.classes);
  464         evt->info.immnd.info.finSync.classes = NULL;
  465         if (evt->info.immnd.type == IMMND_EVT_ND2ND_SYNC_FINALIZE_2) {
  466             immsv_evt_free_ccbOutcomeList(
  467                 evt->info.immnd.info.finSync.ccbResults);
  468             evt->info.immnd.info.finSync.ccbResults = NULL;
  469         }
  470     } else if ((evt->info.immnd.type == IMMND_EVT_A2ND_OBJ_CREATE) ||
  471            (evt->info.immnd.type == IMMND_EVT_A2ND_OI_OBJ_CREATE) ||
  472            (evt->info.immnd.type == IMMND_EVT_A2ND_OBJ_CREATE_2) ||
  473            (evt->info.immnd.type == IMMND_EVT_A2ND_OI_OBJ_CREATE_2)) {
  474         free(evt->info.immnd.info.objCreate.className.buf);
  475         evt->info.immnd.info.objCreate.className.buf = NULL;
  476         evt->info.immnd.info.objCreate.className.size = 0;
  477 
  478         free(evt->info.immnd.info.objCreate.parentOrObjectDn.buf);
  479         evt->info.immnd.info.objCreate.parentOrObjectDn.buf = NULL;
  480         evt->info.immnd.info.objCreate.parentOrObjectDn.size = 0;
  481 
  482         immsv_free_attrvalues_list(
  483             evt->info.immnd.info.objCreate.attrValues);
  484         evt->info.immnd.info.objCreate.attrValues = NULL;
  485     } else if ((evt->info.immnd.type == IMMND_EVT_A2ND_OBJ_MODIFY) ||
  486            (evt->info.immnd.type == IMMND_EVT_A2ND_OI_OBJ_MODIFY)) {
  487         free(evt->info.immnd.info.objModify.objectName.buf);
  488         evt->info.immnd.info.objModify.objectName.buf = NULL;
  489         evt->info.immnd.info.objModify.objectName.size = 0;
  490 
  491         immsv_free_attrmods(evt->info.immnd.info.objModify.attrMods);
  492         evt->info.immnd.info.objModify.attrMods = NULL;
  493     } else if ((evt->info.immnd.type == IMMND_EVT_A2ND_OBJ_DELETE) ||
  494            (evt->info.immnd.type == IMMND_EVT_A2ND_OI_OBJ_DELETE)) {
  495         free(evt->info.immnd.info.objDelete.objectName.buf);
  496         evt->info.immnd.info.objDelete.objectName.buf = NULL;
  497         evt->info.immnd.info.objDelete.objectName.size = 0;
  498     } else if ((evt->info.immnd.type == IMMND_EVT_A2ND_OBJ_SYNC) ||
  499            (evt->info.immnd.type == IMMND_EVT_A2ND_OBJ_SYNC_2)) {
  500         IMMSV_OM_OBJECT_SYNC *obj_sync =
  501             &(evt->info.immnd.info.obj_sync);
  502         IMMSV_OM_OBJECT_SYNC *tmp = NULL;
  503         bool top = true;
  504 
  505         while (obj_sync) {
  506             free(obj_sync->className.buf);
  507             obj_sync->className.buf = NULL;
  508             obj_sync->className.size = 0;
  509 
  510             free(obj_sync->objectName.buf);
  511             obj_sync->objectName.buf = NULL;
  512             obj_sync->objectName.size = 0;
  513 
  514             immsv_free_attrvalues_list(obj_sync->attrValues);
  515             obj_sync->attrValues = NULL;
  516 
  517             if (evt->info.immnd.type == IMMND_EVT_A2ND_OBJ_SYNC) {
  518                 obj_sync = NULL;
  519             } else {
  520                 tmp = obj_sync;
  521                 obj_sync = obj_sync->next;
  522                 tmp->next = NULL;
  523                 if (top) { /* Top object resides in evt on
  524                           stack. */
  525                     top = false;
  526                 } else {
  527                     free(tmp);
  528                 }
  529             }
  530         }
  531 
  532     } else if ((evt->info.immnd.type == IMMND_EVT_A2ND_CLASS_CREATE) ||
  533            (evt->info.immnd.type == IMMND_EVT_A2ND_CLASS_DESCR_GET) ||
  534            (evt->info.immnd.type == IMMND_EVT_A2ND_CLASS_DELETE)) {
  535         free(evt->info.immnd.info.classDescr.className.buf);
  536         evt->info.immnd.info.classDescr.className.buf = NULL;
  537         evt->info.immnd.info.classDescr.className.size = 0;
  538 
  539         immsv_free_attrdefs_list(
  540             evt->info.immnd.info.classDescr.attrDefinitions);
  541         evt->info.immnd.info.classDescr.attrDefinitions = NULL;
  542 
  543     } else if ((evt->info.immnd.type == IMMND_EVT_A2ND_OI_IMPL_SET) ||
  544            (evt->info.immnd.type == IMMND_EVT_A2ND_OI_IMPL_SET_2) ||
  545            (evt->info.immnd.type == IMMND_EVT_D2ND_IMPLSET_RSP) ||
  546            (evt->info.immnd.type == IMMND_EVT_D2ND_IMPLSET_RSP_2) ||
  547            (evt->info.immnd.type == IMMND_EVT_A2ND_OI_CL_IMPL_SET) ||
  548            (evt->info.immnd.type == IMMND_EVT_A2ND_OI_CL_IMPL_REL) ||
  549            (evt->info.immnd.type == IMMND_EVT_A2ND_OI_OBJ_IMPL_SET) ||
  550            (evt->info.immnd.type == IMMND_EVT_A2ND_OI_OBJ_IMPL_REL)) {
  551         free(evt->info.immnd.info.implSet.impl_name.buf);
  552         evt->info.immnd.info.implSet.impl_name.buf = NULL;
  553         evt->info.immnd.info.implSet.impl_name.size = 0;
  554     } else if ((evt->info.immnd.type == IMMND_EVT_A2ND_ADMO_SET) ||
  555            (evt->info.immnd.type == IMMND_EVT_A2ND_ADMO_RELEASE) ||
  556            (evt->info.immnd.type == IMMND_EVT_A2ND_ADMO_CLEAR)) {
  557         immsv_evt_free_name_list(
  558             evt->info.immnd.info.admReq.objectNames);
  559         evt->info.immnd.info.admReq.objectNames = NULL;
  560     } else if ((evt->info.immnd.type ==
  561             IMMND_EVT_A2ND_CCB_OBJ_CREATE_RSP_2) ||
  562            (evt->info.immnd.type ==
  563             IMMND_EVT_A2ND_CCB_OBJ_DELETE_RSP_2) ||
  564            (evt->info.immnd.type ==
  565             IMMND_EVT_A2ND_CCB_OBJ_MODIFY_RSP_2) ||
  566            (evt->info.immnd.type ==
  567             IMMND_EVT_A2ND_CCB_COMPLETED_RSP_2)) {
  568         free(evt->info.immnd.info.ccbUpcallRsp.errorString.buf);
  569         evt->info.immnd.info.ccbUpcallRsp.errorString.buf = NULL;
  570         evt->info.immnd.info.ccbUpcallRsp.errorString.size = 0;
  571         if (evt->info.immnd.type ==
  572             IMMND_EVT_A2ND_CCB_OBJ_DELETE_RSP_2)
  573             osaf_extended_name_free(
  574                 &evt->info.immnd.info.ccbUpcallRsp.name);
  575     } else if ((evt->info.immnd.type ==
  576             IMMND_EVT_A2ND_CCB_OBJ_DELETE_RSP) ||
  577             (evt->info.immnd.type ==
  578             IMMND_EVT_A2ND_OI_CCB_AUG_INIT)) {
  579         osaf_extended_name_free(
  580             &evt->info.immnd.info.ccbUpcallRsp.name);
  581     } else if (evt->info.immnd.type == IMMND_EVT_A2ND_IMM_ADMINIT) {
  582         osaf_extended_name_free(
  583             &evt->info.immnd.info.adminitReq.i.adminOwnerName);
  584     } else if (evt->info.immnd.type == IMMND_EVT_D2ND_ADMINIT) {
  585         osaf_extended_name_free(
  586             &evt->info.immnd.info.adminitGlobal.i.adminOwnerName);
  587     } else if (evt->info.immnd.type == IMMND_EVT_D2ND_IMPLDELETE) {
  588         for(uint32_t i=0; i<evt->info.immnd.info.impl_delete.size; ++i) {
  589             free(evt->info.immnd.info.impl_delete.implNameList[i].buf);
  590         }
  591         free(evt->info.immnd.info.impl_delete.implNameList);
  592     }
  593 
  594     if (onheap) {
  595         free(evt);
  596     }
  597     return rc;
  598 }
  599 
  600 void immnd_process_evt(void)
  601 {
  602     IMMND_CB *cb = immnd_cb;
  603     uint32_t rc = NCSCC_RC_SUCCESS;
  604 
  605     IMMSV_EVT *evt;
  606 
  607     evt = (IMMSV_EVT *)ncs_ipc_non_blk_recv(&immnd_cb->immnd_mbx);
  608 
  609     if (evt == NULL) {
  610         LOG_ER("No mbx message although indicated in fd!");
  611         TRACE_LEAVE();
  612         return;
  613     }
  614 
  615     if (evt->type != IMMSV_EVT_TYPE_IMMND) {
  616         LOG_ER("IMMND - Unknown Event");
  617         immnd_evt_destroy(evt, true, __LINE__);
  618         return;
  619     }
  620 
  621     if ((evt->sinfo.to_svc == NCSMDS_SVC_ID_IMMD) &&
  622         (evt->sinfo.node_id != cb->immd_node_id) &&
  623         (evt->sinfo.node_id != cb->other_immd_id)) {
  624         LOG_WA("DISCARD message from IMMD %x as ACT:%x SBY:%x",
  625             evt->sinfo.node_id, cb->immd_node_id, cb->other_immd_id);
  626         immnd_evt_destroy(evt, true, __LINE__);
  627         return;
  628     }
  629 
  630     if ((cb->mIntroduced == 2) &&
  631         ((evt->info.immnd.type == IMMND_EVT_D2ND_SYNC_START) ||
  632          (evt->info.immnd.type == IMMND_EVT_D2ND_SYNC_ABORT) ||
  633          (evt->info.immnd.type == IMMND_EVT_D2ND_PBE_PRTO_PURGE_MUTATIONS) ||
  634          (evt->info.immnd.type == IMMND_EVT_D2ND_DUMP_OK) ||
  635          (evt->info.immnd.type == IMMND_EVT_D2ND_LOADING_OK) ||
  636          (evt->info.immnd.type == IMMND_EVT_D2ND_GLOB_FEVS_REQ) ||
  637          (evt->info.immnd.type == IMMND_EVT_D2ND_GLOB_FEVS_REQ_2))) {
  638         LOG_WA("DISCARD message %s from IMMD %x as re-intro on-going",
  639             immsv_get_immnd_evt_name(evt->info.immnd.type),
  640             evt->sinfo.node_id);
  641         immnd_evt_destroy(evt, true, __LINE__);
  642         return;
  643     }
  644 
  645     if ((evt->info.immnd.type != IMMND_EVT_D2ND_GLOB_FEVS_REQ) &&
  646         (evt->info.immnd.type != IMMND_EVT_D2ND_GLOB_FEVS_REQ_2))
  647         immsv_msg_trace_rec(evt->sinfo.dest, evt);
  648 
  649     switch (evt->info.immnd.type) {
  650     case IMMND_EVT_MDS_INFO:
  651         rc = immnd_evt_proc_mds_evt(cb, &evt->info.immnd);
  652         break;
  653 
  654     case IMMND_EVT_CB_DUMP:
  655         rc = immnd_evt_proc_cb_dump(cb);
  656         break;
  657 
  658     /* Agent to ND */
  659     case IMMND_EVT_A2ND_IMM_INIT:
  660         rc = immnd_evt_proc_imm_init(cb, &evt->info.immnd, &evt->sinfo,
  661                          true);
  662         break;
  663 
  664     case IMMND_EVT_A2ND_IMM_OI_INIT:
  665         rc = immnd_evt_proc_imm_init(cb, &evt->info.immnd, &evt->sinfo,
  666                          false);
  667         break;
  668 
  669     case IMMND_EVT_A2ND_IMM_FINALIZE:
  670         rc = immnd_evt_proc_imm_finalize(cb, &evt->info.immnd,
  671                          &evt->sinfo, true);
  672         break;
  673 
  674     case IMMND_EVT_A2ND_IMM_OI_FINALIZE:
  675         rc = immnd_evt_proc_imm_finalize(cb, &evt->info.immnd,
  676                          &evt->sinfo, false);
  677         break;
  678 
  679     case IMMND_EVT_A2ND_CL_TIMEOUT:
  680         rc = immnd_evt_proc_cl_imma_timeout(cb, &evt->info.immnd);
  681         break;
  682 
  683     case IMMND_EVT_A2ND_IMM_OM_RESURRECT:
  684         rc = immnd_evt_proc_imm_resurrect(cb, &evt->info.immnd,
  685                           &evt->sinfo, true);
  686         break;
  687 
  688     case IMMND_EVT_A2ND_IMM_OI_RESURRECT:
  689         rc = immnd_evt_proc_imm_resurrect(cb, &evt->info.immnd,
  690                           &evt->sinfo, false);
  691         break;
  692 
  693     case IMMND_EVT_A2ND_IMM_CLIENTHIGH:
  694         LOG_WA(
  695             "Deprecated message type IMMND_EVT_A2ND_IMM_CLIENTHIGH - ignoring");
  696         break;
  697 
  698     case IMMND_EVT_A2ND_IMM_OM_CLIENTHIGH:
  699         rc = immnd_evt_proc_imm_client_high(cb, &evt->info.immnd,
  700                             &evt->sinfo, true);
  701         break;
  702 
  703     case IMMND_EVT_A2ND_IMM_OI_CLIENTHIGH:
  704         rc = immnd_evt_proc_imm_client_high(cb, &evt->info.immnd,
  705                             &evt->sinfo, false);
  706         break;
  707 
  708     case IMMND_EVT_A2ND_RECOVER_CCB_OUTCOME:
  709         rc = immnd_evt_proc_recover_ccb_result(cb, &evt->info.immnd,
  710                                &evt->sinfo);
  711         break;
  712 
  713     case IMMND_EVT_A2ND_SYNC_FINALIZE:
  714         rc = immnd_evt_proc_sync_finalize(cb, &evt->info.immnd,
  715                           &evt->sinfo);
  716         break;
  717 
  718     case IMMND_EVT_A2ND_IMM_ADMINIT:
  719         rc = immnd_evt_proc_admowner_init(cb, &evt->info.immnd,
  720                           &evt->sinfo);
  721         break;
  722 
  723     case IMMND_EVT_A2ND_OI_IMPL_SET:
  724     case IMMND_EVT_A2ND_OI_IMPL_SET_2:
  725         rc = immnd_evt_proc_impl_set(cb, &evt->info.immnd, &evt->sinfo);
  726         break;
  727 
  728     case IMMND_EVT_A2ND_CCBINIT:
  729         rc = immnd_evt_proc_ccb_init(cb, &evt->info.immnd, &evt->sinfo);
  730         break;
  731 
  732     case IMMND_EVT_A2ND_OI_OBJ_MODIFY:
  733         rc =
  734             immnd_evt_proc_rt_update(cb, &evt->info.immnd, &evt->sinfo);
  735         break;
  736 
  737     case IMMND_EVT_A2ND_IMM_FEVS:
  738     case IMMND_EVT_A2ND_IMM_FEVS_2:
  739         rc = immnd_evt_proc_fevs_forward(cb, &evt->info.immnd,
  740                          &evt->sinfo, false, true);
  741         break;
  742 
  743     case IMMND_EVT_A2ND_CLASS_DESCR_GET:
  744         rc = immnd_evt_proc_class_desc_get(cb, &evt->info.immnd,
  745                            &evt->sinfo);
  746         break;
  747 
  748     case IMMND_EVT_A2ND_SEARCHINIT:
  749         rc = immnd_evt_proc_search_init(cb, &evt->info.immnd,
  750                         &evt->sinfo);
  751         break;
  752 
  753     case IMMND_EVT_A2ND_SEARCHNEXT:
  754         rc = immnd_evt_proc_search_next(cb, &evt->info.immnd,
  755                         &evt->sinfo);
  756         break;
  757 
  758     case IMMND_EVT_A2ND_OBJ_SAFE_READ:
  759         rc =
  760             immnd_evt_proc_safe_read(cb, &evt->info.immnd, &evt->sinfo);
  761         break;
  762 
  763     case IMMND_EVT_A2ND_ACCESSOR_GET:
  764         rc = immnd_evt_proc_accessor_get(cb, &evt->info.immnd,
  765                          &evt->sinfo);
  766         break;
  767 
  768     case IMMND_EVT_A2ND_RT_ATT_UPPD_RSP:
  769         rc = immnd_evt_proc_oi_att_pull_rpl(cb, &evt->info.immnd,
  770                             &evt->sinfo);
  771         break;
  772 
  773     case IMMND_EVT_A2ND_SEARCHFINALIZE:
  774         rc = immnd_evt_proc_search_finalize(cb, &evt->info.immnd,
  775                             &evt->sinfo);
  776         break;
  777 
  778     case IMMND_EVT_A2ND_ADMOP_RSP:
  779     case IMMND_EVT_A2ND_ADMOP_RSP_2:
  780         rc = immnd_evt_proc_admop_rsp(cb, &evt->info.immnd, &evt->sinfo,
  781                           false, true);
  782         break;
  783 
  784     case IMMND_EVT_A2ND_ASYNC_ADMOP_RSP:
  785     case IMMND_EVT_A2ND_ASYNC_ADMOP_RSP_2:
  786         rc = immnd_evt_proc_admop_rsp(cb, &evt->info.immnd, &evt->sinfo,
  787                           true, true);
  788         break;
  789 
  790     case IMMND_EVT_ND2ND_ADMOP_RSP:
  791     case IMMND_EVT_ND2ND_ADMOP_RSP_2:
  792         rc = immnd_evt_proc_admop_rsp(cb, &evt->info.immnd, &evt->sinfo,
  793                           false, false);
  794         break;
  795 
  796     case IMMND_EVT_ND2ND_ASYNC_ADMOP_RSP:
  797     case IMMND_EVT_ND2ND_ASYNC_ADMOP_RSP_2:
  798         rc = immnd_evt_proc_admop_rsp(cb, &evt->info.immnd, &evt->sinfo,
  799                           true, false);
  800         break;
  801 
  802     case IMMND_EVT_ND2ND_SEARCH_REMOTE:
  803         rc = immnd_evt_proc_rt_update_pull(cb, &evt->info.immnd,
  804                            &evt->sinfo);
  805         break;
  806 
  807     case IMMND_EVT_ND2ND_SEARCH_REMOTE_RSP:
  808         rc = immnd_evt_proc_remote_search_rsp(cb, &evt->info.immnd,
  809                               &evt->sinfo);
  810         break;
  811 
  812     /* D to ND */
  813 
  814     case IMMND_EVT_D2ND_INTRO_RSP:
  815         rc =
  816             immnd_evt_proc_intro_rsp(cb, &evt->info.immnd, &evt->sinfo);
  817         break;
  818 
  819     case IMMND_EVT_D2ND_SYNC_REQ:
  820         rc = immnd_evt_proc_sync_req(cb, &evt->info.immnd, &evt->sinfo);
  821         break;
  822 
  823     case IMMND_EVT_D2ND_LOADING_OK:
  824         rc = immnd_evt_proc_loading_ok(cb, &evt->info.immnd,
  825                            &evt->sinfo);
  826         break;
  827 
  828     case IMMND_EVT_D2ND_DUMP_OK:
  829         rc = immnd_evt_proc_dump_ok(cb, &evt->info.immnd, &evt->sinfo);
  830         break;
  831 
  832     case IMMND_EVT_D2ND_SYNC_START:
  833         rc = immnd_evt_proc_start_sync(cb, &evt->info.immnd,
  834                            &evt->sinfo);
  835         break;
  836 
  837     case IMMND_EVT_D2ND_SYNC_ABORT:
  838         rc = immnd_evt_proc_abort_sync(cb, &evt->info.immnd,
  839                            &evt->sinfo);
  840         break;
  841 
  842     case IMMND_EVT_D2ND_PBE_PRTO_PURGE_MUTATIONS:
  843         rc = immnd_evt_proc_pbe_prto_purge_mutations(
  844             cb, &evt->info.immnd, &evt->sinfo);
  845         break;
  846 
  847     case IMMND_EVT_D2ND_GLOB_FEVS_REQ:
  848     case IMMND_EVT_D2ND_GLOB_FEVS_REQ_2:
  849         rc = immnd_evt_proc_fevs_rcv(cb, &evt->info.immnd, &evt->sinfo);
  850         break;
  851 
  852     case IMMND_EVT_D2ND_RESET:
  853         rc = immnd_evt_proc_reset(cb, &evt->info.immnd, &evt->sinfo);
  854         break;
  855 
  856     default:
  857         LOG_ER("UNPACK FAILURE, unrecognized message type: %u",
  858                evt->info.immnd.type);
  859         rc = NCSCC_RC_FAILURE;
  860         break;
  861     }
  862 
  863     if (rc != NCSCC_RC_SUCCESS) {
  864         LOG_WA("Error code %u returned for message type %u - ignoring",
  865                rc, evt->info.immnd.type);
  866     }
  867 
  868     /* Free the Event */
  869     immnd_evt_destroy(evt, true, __LINE__);
  870 
  871     return;
  872 }
  873 
  874 /****************************************************************************
  875  * Name          : immnd_evt_proc_imm_init
  876  *
  877  * Description   : Function to process the SaImmOmInitialize and
  878  *                 SaImmOiInitialize calls from IMM Agents.
  879  *
  880  * Arguments     : IMMND_CB *cb - IMMND CB pointer
  881  *                 IMMND_EVT *evt - Received Event structure
  882  *                 IMMSV_SEND_INFO *sinfo - sender info
  883  *                 bool isOm - true => OM, false => OI
  884  *
  885  * Return Values : NCSCC_RC_SUCCESS/Error.
  886  *
  887  * Notes         : None.
  888  *****************************************************************************/
  889 static uint32_t immnd_evt_proc_imm_init(IMMND_CB *cb, IMMND_EVT *evt,
  890                     IMMSV_SEND_INFO *sinfo, bool isOm)
  891 {
  892     IMMSV_EVT send_evt;
  893     SaAisErrorT error;
  894     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
  895     SaUint64T clientId = 0LL;
  896     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
  897 
  898     int load_pid = immModel_getLoader(cb);
  899     int sync_pid = (!load_pid && (cb->syncPid > 0)) ? (cb->syncPid) : 0;
  900     int pbe_pid = (!load_pid && (cb->pbePid > 0)) ? (cb->pbePid) : 0;
  901 
  902     if (sinfo->pid == 0) {
  903         LOG_WA("%s: PID 0 (%d) for %" PRIx64 ", MDS problem?",
  904                __FUNCTION__, evt->info.initReq.client_pid, sinfo->dest);
  905         error = SA_AIS_ERR_LIBRARY;
  906         goto agent_rsp;
  907     }
  908 
  909     if (load_pid > 0) {
  910         if (sinfo->pid == load_pid) {
  911             TRACE_2("Loader attached, pid: %u", load_pid);
  912         } else {
  913             TRACE_2(
  914                 "Rejecting OM client attach during loading, pid %u != %u",
  915                 sinfo->pid, load_pid);
  916             error = SA_AIS_ERR_TRY_AGAIN;
  917             goto agent_rsp;
  918         }
  919     } else if (sinfo->pid == cb->preLoadPid) {
  920         LOG_IN("2PBE Pre-loader attached");
  921     } else if (load_pid < 0) {
  922         TRACE_2(
  923             "Rejecting OM client attach. Waiting for loading or sync to complete");
  924         error = SA_AIS_ERR_TRY_AGAIN;
  925         goto agent_rsp;
  926     }
  927 
  928     OsafImmAccessControlModeT mode = immModel_accessControlMode(immnd_cb);
  929     if (mode != ACCESS_CONTROL_DISABLED) {
  930         /* allow access using white list approach */
  931         if (sinfo->uid == 0) {
  932             TRACE("superuser");
  933         } else if (getgid() == sinfo->gid) {
  934             TRACE("same group");
  935         } else {
  936             const char *authorized_group =
  937                 immModel_authorizedGroup(immnd_cb);
  938             if ((authorized_group != NULL) &&
  939                 (osaf_user_is_member_of_group(sinfo->uid, authorized_group) ||
  940                  osaf_pid_has_supplementary_group(sinfo->pid,
  941                         authorized_group))) {
  942                 TRACE("configured group");
  943             } else {
  944                 if (mode == ACCESS_CONTROL_PERMISSIVE) {
  945                     struct passwd *pwd =
  946                         getpwuid(sinfo->uid);
  947                     if (pwd != NULL)
  948                         syslog(
  949                             LOG_ALERT | LOG_AUTH,
  950                             "access violation by %s(uid=%d)",
  951                             pwd->pw_name, sinfo->uid);
  952                     TRACE_2(
  953                         "access violation, uid:%d, pid:%d, group_name:%s",
  954                         sinfo->uid, sinfo->pid,
  955                         authorized_group);
  956                 } else {
  957                     // mode ENFORCING
  958                     struct passwd *pwd =
  959                         getpwuid(sinfo->uid);
  960                     if (pwd != NULL)
  961                         syslog(
  962                             LOG_ALERT | LOG_AUTH,
  963                             "access denied for %s(uid=%d)",
  964                             pwd->pw_name, sinfo->uid);
  965                     TRACE_2(
  966                         "access denied, uid:%d, pid:%d, group_name:%s",
  967                         sinfo->uid, sinfo->pid,
  968                         authorized_group);
  969                     error = SA_AIS_ERR_ACCESS_DENIED;
  970                     goto agent_rsp;
  971                 }
  972             }
  973         }
  974     }
  975 
  976     if (evt->info.initReq.version.minorVersion >= 0x12 &&
  977         evt->info.initReq.version.majorVersion == 0x2 &&
  978         evt->info.initReq.version.releaseCode == 'A') {
  979         if (!cb->isClmNodeJoined && cb->mIntroduced != 2) {
  980             error = SA_AIS_ERR_UNAVAILABLE;
  981             LOG_ER("CLM node went down nodeJoined=%x",
  982                    cb->isClmNodeJoined);
  983             goto clm_left;
  984         }
  985     }
  986 
  987     cl_node = calloc(1, sizeof(IMMND_IMM_CLIENT_NODE));
  988     if (cl_node == NULL) {
  989         LOG_ER("IMMND - Client Alloc Failed");
  990         error = SA_AIS_ERR_NO_MEMORY;
  991         goto agent_rsp;
  992     }
  993 
  994     clientId = cb->cli_id_gen++;
  995     if (cb->cli_id_gen == 0xffffffff) {
  996         cb->cli_id_gen = 1;
  997         /* Counter wrap arround causes risk (low) for collisions.
  998            Symtom would be that this client node_add would fail below.
  999            This is why we change the error code to try-again.
 1000          */
 1001     }
 1002 
 1003     /*The id generated by the ND is only valid as long as this ND process
 1004        survives => restart of ND means loss of all client connections.
 1005        Return ND pid in reply to use in handshake ??
 1006      */
 1007 
 1008     cl_node->imm_app_hdl = m_IMMSV_PACK_HANDLE(clientId, cb->node_id);
 1009 
 1010     cl_node->agent_mds_dest = sinfo->dest;
 1011     cl_node->version = evt->info.initReq.version;
 1012     cl_node->sv_id = (isOm) ? NCSMDS_SVC_ID_IMMA_OM : NCSMDS_SVC_ID_IMMA_OI;
 1013 
 1014     if (immnd_client_node_add(cb, cl_node) != NCSCC_RC_SUCCESS) {
 1015         LOG_WA(
 1016             "IMMND - Client Tree Add Failed client id wrap-arround?");
 1017         free(cl_node);
 1018         error = SA_AIS_ERR_TRY_AGAIN; /* cl-id wraparround collision? */
 1019         goto agent_rsp;
 1020     }
 1021 
 1022     TRACE_2("Added client with id: %llx <node:%x, count:%u>",
 1023         cl_node->imm_app_hdl, cb->node_id, (SaUint32T)clientId);
 1024 
 1025     if (sync_pid && (sinfo->pid == sync_pid)) {
 1026         TRACE_2("Sync agent attached, pid: %u", sync_pid);
 1027         cl_node->mIsSync = 1;
 1028     } else if (pbe_pid && (sinfo->pid == pbe_pid) && !isOm &&
 1029            !(cl_node->mIsPbe)) {
 1030         LOG_NO("Persistent Back End OI attached, pid: %u", pbe_pid);
 1031         cl_node->mIsPbe = 1;
 1032     }
 1033 
 1034     send_evt.info.imma.info.initRsp.immHandle = cl_node->imm_app_hdl;
 1035     send_evt.info.imma.info.initRsp.syncrTimeout =
 1036         immModel_getSyncrTimeout(cb);
 1037     error = SA_AIS_OK;
 1038 
 1039 clm_left:
 1040 agent_rsp:
 1041     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 1042     send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_INIT_RSP;
 1043     send_evt.info.imma.info.initRsp.error = error;
 1044 
 1045     return immnd_mds_send_rsp(cb, sinfo, &send_evt);
 1046 }
 1047 
 1048 /****************************************************************************
 1049  * Name          : immnd_evt_proc_search_init
 1050  *
 1051  * Description   : Function to process the SaImmOmSearchInitialize call.
 1052  *                 Note that this is a read, local to the ND (does not go
 1053  *                 over FEVS).
 1054  *
 1055  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 1056  *                 IMMND_EVT *evt - Received Event structure
 1057  *                 IMMSV_SEND_INFO *sinfo - sender info
 1058  *
 1059  * Return Values : NCSCC_RC_SUCCESS/Error.
 1060  *
 1061  * Notes         : None.
 1062  *****************************************************************************/
 1063 static uint32_t immnd_evt_proc_search_init(IMMND_CB *cb, IMMND_EVT *evt,
 1064                        IMMSV_SEND_INFO *sinfo)
 1065 {
 1066     IMMSV_EVT send_evt;
 1067     uint32_t rc = NCSCC_RC_SUCCESS;
 1068     SaAisErrorT error = SA_AIS_OK;
 1069     void *searchOp = NULL;
 1070     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 1071     IMMND_OM_SEARCH_NODE *sn = NULL;
 1072     uint16_t searchOpCount = 0;
 1073 
 1074     /* Official DUMP/BACKUP assumed when search is global for only
 1075      * persistent attrs and done at SC. */
 1076     bool officialDump =
 1077         cb->mCanBeCoord &&
 1078         (((SaImmSearchOptionsT)evt->info.searchInit.searchOptions) &
 1079          SA_IMM_SEARCH_PERSISTENT_ATTRS) &&
 1080         (evt->info.searchInit.searchParam.present ==
 1081          ImmOmSearchParameter_PR_NOTHING) &&
 1082         (evt->info.searchInit.rootName.size == 0);
 1083 
 1084     bool isSync =
 1085         cb->mIsCoord && (cb->syncPid > 0) &&
 1086         (((SaImmSearchOptionsT)evt->info.searchInit.searchOptions) &
 1087          SA_IMM_SEARCH_SYNC_CACHED_ATTRS);
 1088 
 1089     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 1090     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 1091     send_evt.info.imma.type = IMMA_EVT_ND2A_SEARCHINIT_RSP;
 1092     TRACE_2("SEARCH INIT for root:%s", evt->info.searchInit.rootName.buf);
 1093 
 1094     /*Look up client-node */
 1095     immnd_client_node_get(cb, evt->info.searchInit.client_hdl, &cl_node);
 1096     if (cl_node == NULL || cl_node->mIsStale) {
 1097         LOG_WA("IMMND - Client Node Get Failed for client handle: %llu",
 1098                evt->info.searchInit.client_hdl);
 1099 
 1100         send_evt.info.imma.info.searchInitRsp.error =
 1101             SA_AIS_ERR_BAD_HANDLE;
 1102         goto agent_rsp;
 1103     }
 1104 
 1105     if (officialDump) {
 1106         if (immModel_immNotWritable(cb) ||
 1107             (cb->mState != IMM_SERVER_READY)) {
 1108             LOG_WA(
 1109                 "Cannot allow official dump/backup when imm-sync is in progress");
 1110             error = SA_AIS_ERR_TRY_AGAIN;
 1111             goto agent_rsp;
 1112         }
 1113 
 1114         if (cb->m2Pbe) {
 1115             if (cb->mIsOtherScUp &&
 1116                 immModel_oneSafe2PBEAllowed(cb)) {
 1117                 LOG_ER(
 1118                     "ERR_NO_RESOURCES: Cannot allow official dump/backup "
 1119                     "when 1-safe2PBE is allowed!!");
 1120                 /* This is simply a guard. Only reason it is not
 1121                    an assert is that this does not signify
 1122                    imm-ram inconsistency, but a grave risk of
 1123                    causing an inconsistent joining PBE in 2PBE.
 1124                    We should never end up here. */
 1125                 error = SA_AIS_ERR_NO_RESOURCES;
 1126                 goto agent_rsp;
 1127             }
 1128 
 1129             if ((!cb->mIsCoord) && immModel_pbeNotWritable(cb) &&
 1130                 !immModel_ccbsTerminated(cb, true)) {
 1131                 LOG_WA(
 1132                     "ERR_NO_RESOURCES: Active Ccbs still exist in the system");
 1133                 /*Not sure this is a problem though. These ccbs
 1134                   are dommed. They will not be allowed to apply
 1135                   untill we are 2-safe. And any ccbs that
 1136                   created ops before 2-safe will fail in the
 1137                   apply because object count does not match at
 1138                   slave. May need a way to get out of this
 1139                   state, such as starting a sync despite that we
 1140                   dont really need a sync.
 1141                 */
 1142                 error = SA_AIS_ERR_NO_RESOURCES;
 1143                 goto agent_rsp;
 1144             }
 1145         }
 1146     }
 1147 
 1148     if (isSync) {
 1149         /* Special check only for sync iterator. */
 1150         if (!immnd_is_immd_up(cb)) {
 1151             LOG_WA(
 1152                 "ERR_TRY_AGAIN: IMMD is down can not progress with sync");
 1153             error = SA_AIS_ERR_TRY_AGAIN;
 1154             goto agent_rsp;
 1155         }
 1156     }
 1157 
 1158     sn = cl_node->searchOpList;
 1159     while (sn) {
 1160         ++searchOpCount;
 1161         sn = sn->next;
 1162     }
 1163     if (searchOpCount >= 5000) {
 1164         LOG_WA(
 1165             "ERR_NO_RESOURCES: Too many search operations (%u) on OM handle -"
 1166             " probable resource leak.",
 1167             searchOpCount);
 1168         error = SA_AIS_ERR_NO_RESOURCES;
 1169         goto agent_rsp;
 1170     }
 1171 
 1172     error = immModel_searchInitialize(cb, &(evt->info.searchInit),
 1173                       &searchOp, isSync, false);
 1174 
 1175     if ((error == SA_AIS_OK) && isSync) {
 1176         /* Special processing only for sync iterator. */
 1177         IMMSV_EVT send_evt2;
 1178         memset(&send_evt2, '\0', sizeof(IMMSV_EVT));
 1179         send_evt2.type = IMMSV_EVT_TYPE_IMMD;
 1180         send_evt2.info.immd.type = IMMD_EVT_ND2D_SYNC_FEVS_BASE;
 1181         send_evt2.info.immd.info.syncFevsBase.fevsBase =
 1182             cb->highestProcessed;
 1183         send_evt2.info.immd.info.syncFevsBase.client_hdl =
 1184             evt->info.searchInit.client_hdl;
 1185 
 1186         cb->fevs_replies_pending++; /*flow control */
 1187         if (cb->fevs_replies_pending > 1) {
 1188             TRACE("Messages pending:%u", cb->fevs_replies_pending);
 1189         }
 1190 
 1191         rc = immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMD,
 1192                     cb->immd_mdest_id, &send_evt2);
 1193 
 1194         if (rc != NCSCC_RC_SUCCESS) {
 1195             LOG_ER("IMMND - Send of SYNC_FEVS_BASE message failed");
 1196             error = SA_AIS_ERR_TRY_AGAIN;
 1197             cb->fevs_replies_pending--;
 1198         }
 1199     }
 1200 
 1201     /*Generate search-id */
 1202     if (error == SA_AIS_OK) {
 1203         sn = calloc(1, sizeof(IMMND_OM_SEARCH_NODE));
 1204         if (sn == NULL) {
 1205             send_evt.info.imma.info.searchInitRsp.error =
 1206                 SA_AIS_ERR_NO_MEMORY;
 1207             goto agent_rsp;
 1208         }
 1209 
 1210         sn->searchId = cb->cli_id_gen++;
 1211         if (cb->cli_id_gen == 0xffffffff) { /* handle wrap arround */
 1212             cb->cli_id_gen = 1;
 1213         }
 1214         sn->searchOp = searchOp;
 1215         sn->next = cl_node->searchOpList;
 1216         cl_node->searchOpList = sn;
 1217         send_evt.info.imma.info.searchInitRsp.searchId = sn->searchId;
 1218 
 1219         if (officialDump) { /*=>DUMP/BACKUP*/
 1220             osafassert(!immModel_immNotWritable(cb));
 1221             TRACE_2("SEARCH INIT tentatively adj epoch to "
 1222                 ":%u & adnnounce dump",
 1223                 cb->mMyEpoch + 1);
 1224             immnd_announceDump(cb);
 1225         }
 1226     }
 1227 
 1228 agent_rsp:
 1229     if (error != SA_AIS_OK) {
 1230         immModel_deleteSearchOp(searchOp);
 1231         searchOp = NULL;
 1232     }
 1233     send_evt.info.imma.info.searchInitRsp.error = error;
 1234     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 1235     return rc;
 1236 }
 1237 
 1238 void search_req_continue(IMMND_CB *cb, IMMSV_OM_RSP_SEARCH_REMOTE *reply,
 1239              SaUint32T reqConn)
 1240 {
 1241     IMMSV_EVT send_evt;
 1242     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 1243     IMMSV_OM_RSP_SEARCH_NEXT *rsp = NULL;
 1244     IMMSV_ATTR_VALUES_LIST *oldRsp, *fetchedRsp;
 1245     IMMND_OM_SEARCH_NODE *sn = NULL;
 1246     SaAisErrorT err = reply->result;
 1247     bool isAccessor = false;
 1248     bool nonExtendedName = false;
 1249     TRACE_ENTER();
 1250     osafassert(reply->requestNodeId == cb->node_id);
 1251     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 1252     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 1253     SaImmHandleT tmp_hdl = m_IMMSV_PACK_HANDLE(reqConn, cb->node_id);
 1254 
 1255     /*Look up client-node */
 1256     immnd_client_node_get(cb, tmp_hdl, &cl_node);
 1257     if (cl_node == NULL || cl_node->mIsStale) {
 1258         LOG_WA("IMMND - Client Node Get Failed for cli_hdl:%llx",
 1259                tmp_hdl);
 1260         /*Cant do anything */
 1261         goto leave;
 1262     }
 1263 
 1264     TRACE_2("SEARCH NEXT, Look for id:%u", reply->searchId);
 1265 
 1266     sn = cl_node->searchOpList;
 1267     while (sn) {
 1268         if (sn->searchId == reply->searchId) {
 1269             break;
 1270         }
 1271         sn = sn->next;
 1272     }
 1273 
 1274     if (sn) {
 1275         /* Don't move to the next iteration in searchOp
 1276          * if OI resturns ERR_NO_MEMORY or ERR_NO_RESOURCES */
 1277         if (err != SA_AIS_ERR_NO_MEMORY &&
 1278             err != SA_AIS_ERR_NO_RESOURCES) {
 1279             immModel_popLastResult(sn->searchOp);
 1280         }
 1281         immModel_fetchLastResult(sn->searchOp, &rsp);
 1282         immModel_clearLastResult(sn->searchOp);
 1283         isAccessor = immModel_isSearchOpAccessor(sn->searchOp);
 1284         nonExtendedName =
 1285             immModel_isSearchOpNonExtendedNameSet(sn->searchOp);
 1286     } else {
 1287         LOG_ER("Could not find search node for search-ID:%u",
 1288                reply->searchId);
 1289         if (err == SA_AIS_OK) {
 1290             err = SA_AIS_ERR_LIBRARY;
 1291         }
 1292     }
 1293 
 1294     if (err != SA_AIS_OK) {
 1295         goto agent_rsp;
 1296     }
 1297 
 1298     if (!rsp) {
 1299         LOG_ER("Part of continuation lost!");
 1300         err = SA_AIS_ERR_LIBRARY; /*not the proper error code.. */
 1301         goto agent_rsp;
 1302     }
 1303 
 1304     TRACE_2("Last result found, add current runtime values");
 1305     osafassert(strncmp((const char *)rsp->objectName.buf,
 1306                (const char *)reply->runtimeAttrs.objectName.buf,
 1307                rsp->objectName.size) == 0);
 1308     /* Iterate through reply->runtimeAttrs.attrValuesList */
 1309     /* Update value in rsp->attrValuesList */
 1310 
 1311     if (nonExtendedName) {
 1312         IMMSV_ATTR_VALUES *att;
 1313         IMMSV_EDU_ATTR_VAL_LIST *attrList;
 1314 
 1315         if (reply->runtimeAttrs.objectName.size >=
 1316             SA_MAX_UNEXTENDED_NAME_LENGTH) {
 1317             err = SA_AIS_ERR_NAME_TOO_LONG;
 1318             goto agent_rsp;
 1319         }
 1320 
 1321         fetchedRsp = reply->runtimeAttrs.attrValuesList;
 1322         while (fetchedRsp) {
 1323             att = &(fetchedRsp->n);
 1324             if (att->attrValueType == SA_IMM_ATTR_SANAMET &&
 1325                 att->attrValuesNumber > 0) {
 1326                 if (att->attrValue.val.x.size >=
 1327                     SA_MAX_UNEXTENDED_NAME_LENGTH) {
 1328                     err = SA_AIS_ERR_NAME_TOO_LONG;
 1329                     goto agent_rsp;
 1330                 }
 1331                 if (att->attrValuesNumber > 1) {
 1332                     attrList = att->attrMoreValues;
 1333                     while (attrList) {
 1334                         if (attrList->n.val.x.size >=
 1335                             SA_MAX_UNEXTENDED_NAME_LENGTH) {
 1336                             err =
 1337                                 SA_AIS_ERR_NAME_TOO_LONG;
 1338                             goto agent_rsp;
 1339                         }
 1340                         attrList = attrList->next;
 1341                     }
 1342                 }
 1343             }
 1344             fetchedRsp = fetchedRsp->next;
 1345         }
 1346     }
 1347 
 1348     fetchedRsp = reply->runtimeAttrs.attrValuesList;
 1349     while (fetchedRsp) { // For each fetched rt-attr-value
 1350         IMMSV_ATTR_VALUES *att = &(fetchedRsp->n);
 1351         TRACE_2("Looking for attribute:%s", att->attrName.buf);
 1352 
 1353         oldRsp = rsp->attrValuesList;
 1354         while (oldRsp) { // Find the old value
 1355             IMMSV_ATTR_VALUES *att2 = &(oldRsp->n);
 1356             /*TRACE_2("Mattching against:%s", att2->attrName.buf);*/
 1357             if (att->attrName.size == att2->attrName.size &&
 1358                 (strncmp((const char *)att->attrName.buf,
 1359                      (const char *)att2->attrName.buf,
 1360                      att->attrName.size) == 0)) {
 1361                 TRACE_2("MATCH FOUND nrof old values:%lu",
 1362                     att2->attrValuesNumber);
 1363                 osafassert(att->attrValueType ==
 1364                        att2->attrValueType);
 1365                 /* delete the current old value & set
 1366                  * attrValuesNumber to zero. */
 1367                 /* if reply value has attrValuesNumber > 0 then
 1368                  * assign this fetched value. */
 1369                 /* Note: dont forget AttrMoreValues ! */
 1370                 if (att2->attrValuesNumber) {
 1371                     immsv_evt_free_att_val(
 1372                         &att2->attrValue,
 1373                         att2->attrValueType);
 1374 
 1375                     if (att2->attrValuesNumber > 1) {
 1376                         IMMSV_EDU_ATTR_VAL_LIST
 1377                             *att2multi =
 1378                             att2->attrMoreValues;
 1379                         do {
 1380                             IMMSV_EDU_ATTR_VAL_LIST
 1381                                 *tmp;
 1382                             osafassert(
 1383                                 att2multi); // must
 1384                                     // be at
 1385                                     // least
 1386                                     // one
 1387                                     // extra
 1388                                     // value
 1389                             immsv_evt_free_att_val(
 1390                                 &att2multi->n,
 1391                                 att2->attrValueType);
 1392                             tmp = att2multi;
 1393                             att2multi =
 1394                                 att2multi->next;
 1395                             tmp->next = NULL;
 1396                             free(tmp);
 1397                         } while (att2multi);
 1398                         att2->attrValuesNumber = 0;
 1399                         att2->attrMoreValues = NULL;
 1400                     } // multis deleted
 1401 
 1402                 } // old value in rsp deleted.
 1403 
 1404                 TRACE_2(
 1405                     "OLD VALUES DELETED nrof new values:%lu",
 1406                     att->attrValuesNumber);
 1407 
 1408                 if (att->attrValuesNumber) { // there is a new
 1409                                  // value, copy it.
 1410                     att2->attrValue =
 1411                         att->attrValue; // steals any
 1412                                 // buffer.
 1413                     att2->attrValuesNumber =
 1414                         att->attrValuesNumber;
 1415                     att->attrValue.val.x.buf =
 1416                         NULL; // ensure stolen buffer is not
 1417                           // freed twice.
 1418                     att->attrValue.val.x.size = 0;
 1419                 }
 1420 
 1421                 if (att->attrValuesNumber >
 1422                     1) { // multivalued attribute
 1423                     att2->attrMoreValues =
 1424                         att->attrMoreValues; // steal the
 1425                                  // whole list
 1426                     att->attrMoreValues = NULL;
 1427                 }
 1428                 att->attrValuesNumber = 0;
 1429 
 1430                 break; // out of inner loop, since we already
 1431                        // matched this fetched value
 1432             }
 1433             oldRsp = oldRsp->next;
 1434         }
 1435         fetchedRsp = fetchedRsp->next;
 1436     }
 1437 
 1438 agent_rsp:
 1439     if (err == SA_AIS_OK) {
 1440         send_evt.info.imma.type = isAccessor
 1441                           ? IMMA_EVT_ND2A_ACCESSOR_GET_RSP
 1442                           : IMMA_EVT_ND2A_SEARCHNEXT_RSP;
 1443         send_evt.info.imma.info.searchNextRsp = rsp;
 1444     } else { /*err != SA_AIS_OK */
 1445         send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 1446         send_evt.info.imma.info.errRsp.error = err;
 1447     }
 1448 
 1449     if (immnd_mds_send_rsp(cb, &(cl_node->tmpSinfo), &send_evt) !=
 1450         NCSCC_RC_SUCCESS) {
 1451         LOG_WA(
 1452             "Could not send reply to agent for search-next continuaton");
 1453     }
 1454 
 1455     if (isAccessor || /* Accessor case */
 1456         (err != SA_AIS_OK && err != SA_AIS_ERR_NO_MEMORY &&
 1457          err != SA_AIS_ERR_NO_RESOURCES)) { /* Search case */
 1458         if (!isAccessor) {
 1459             /* Finalize search node when it's not ERR_NO_MEMORY or
 1460              * ERR_NO_RESOURCES */
 1461             TRACE("Finalizing search node, err = %u", err);
 1462         }
 1463         if (sn && cl_node) {
 1464             IMMND_OM_SEARCH_NODE **prev = &(cl_node->searchOpList);
 1465             IMMND_OM_SEARCH_NODE *n = cl_node->searchOpList;
 1466             while (n) {
 1467                 if (n == sn) {
 1468                     *prev = n->next;
 1469                     break;
 1470                 }
 1471                 prev = &(n->next);
 1472                 n = n->next;
 1473             }
 1474         }
 1475         if (sn) {
 1476             if (sn->searchOp)
 1477                 immModel_deleteSearchOp(sn->searchOp);
 1478             free(sn);
 1479         }
 1480     }
 1481 
 1482     if (rsp) {
 1483         freeSearchNext(rsp, true);
 1484     }
 1485 
 1486 leave:
 1487     TRACE_LEAVE();
 1488 }
 1489 
 1490 /****************************************************************************
 1491  * Name          : immnd_evt_proc_oi_att_pull_rpl
 1492  *
 1493  * Description   : Function to process the reply from the invocation
 1494  *                 of the SaImmOiRtAttrUpdateCallbackT.
 1495  *                 Note that this is a call local to the ND (does not arrive
 1496  *                 over FEVS).
 1497  *
 1498  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 1499  *                 IMMND_EVT *evt - Received Event structure
 1500  *                 IMMSV_SEND_INFO *sinfo - sender info
 1501  *
 1502  * Return Values : NCSCC_RC_SUCCESS/Error.
 1503  *
 1504  * Notes         : None.
 1505  *****************************************************************************/
 1506 static uint32_t immnd_evt_proc_oi_att_pull_rpl(IMMND_CB *cb, IMMND_EVT *evt,
 1507                            IMMSV_SEND_INFO *sinfo)
 1508 {
 1509     IMMSV_EVT send_evt;
 1510     SaAisErrorT err;
 1511     uint32_t rc = NCSCC_RC_SUCCESS;
 1512     bool isLocal;
 1513     void *searchOp = NULL;
 1514     TRACE_ENTER();
 1515     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 1516     IMMSV_OM_RSP_SEARCH_REMOTE *rspo =
 1517         &send_evt.info.immnd.info.rspSrchRmte;
 1518     rspo->remoteNodeId = evt->info.rtAttUpdRpl.sr.remoteNodeId;
 1519     rspo->searchId = evt->info.rtAttUpdRpl.sr.searchId;
 1520     rspo->requestNodeId = evt->info.rtAttUpdRpl.sr.requestNodeId;
 1521     rspo->runtimeAttrs.objectName =
 1522         evt->info.rtAttUpdRpl.sr.objectName; /* borrowing buf */
 1523     err = evt->info.rtAttUpdRpl.result;
 1524 
 1525     osafassert(evt->info.rtAttUpdRpl.sr.remoteNodeId == cb->node_id);
 1526     isLocal = evt->info.rtAttUpdRpl.sr.requestNodeId == cb->node_id;
 1527     /* Note stack allocated search-initialize struct with members */
 1528     /* shallow copied to refer into the search-remote struct. */
 1529     /* No heap allocations! Dont explicitly delete anything of this struct
 1530      */
 1531     /* ImmsvOmSearchInit reqo; */
 1532     if (err == SA_AIS_OK) {
 1533         /* Fetch latest runtime values from the object. Use
 1534          * search/accessor. */
 1535         IMMSV_OM_SEARCH_INIT reqo;
 1536         memset(&reqo, '\0', sizeof(IMMSV_OM_SEARCH_INIT));
 1537         reqo.rootName.buf =
 1538             evt->info.rtAttUpdRpl.sr.objectName.buf; /*borrowing */
 1539         reqo.rootName.size = evt->info.rtAttUpdRpl.sr.objectName.size;
 1540         reqo.scope = SA_IMM_ONE;
 1541         reqo.searchOptions =
 1542             SA_IMM_SEARCH_ONE_ATTR | SA_IMM_SEARCH_GET_SOME_ATTR;
 1543         reqo.searchParam.present = ImmOmSearchParameter_PR_NOTHING;
 1544         reqo.attributeNames =
 1545             evt->info.rtAttUpdRpl.sr.attributeNames; /*borrowing. */
 1546         TRACE_2(
 1547             "Fetching the folowing rt attributes after implementer has updated");
 1548         while (reqo.attributeNames) {
 1549             TRACE_2("attrname: %s", reqo.attributeNames->name.buf);
 1550             reqo.attributeNames = reqo.attributeNames->next;
 1551         }
 1552         reqo.attributeNames =
 1553             evt->info.rtAttUpdRpl.sr.attributeNames; /*borrowing. */
 1554 
 1555         TRACE_2("oi_att_pull_rpl Before searchInit");
 1556         err = immModel_searchInitialize(cb, &reqo, &searchOp, false,
 1557                         true);
 1558         if (err == SA_AIS_OK) {
 1559             TRACE_2(
 1560                 "oi_att_pull_rpl searchInit returned OK, calling searchNext");
 1561             IMMSV_OM_RSP_SEARCH_NEXT *rsp = 0;
 1562             err =
 1563                 immModel_nextResult(cb, searchOp, &rsp, NULL, NULL,
 1564                         NULL, NULL, false, NULL);
 1565             if (err == SA_AIS_OK) {
 1566                 rspo->runtimeAttrs.attrValuesList =
 1567                     rsp->attrValuesList;
 1568                 /*STEALING*/ rsp->attrValuesList = NULL;
 1569 
 1570                 immModel_clearLastResult(searchOp);
 1571                 freeSearchNext(rsp, true);
 1572             } else {
 1573                 LOG_WA(
 1574                     "Internal IMM server problem - failure from internal nextResult: %u",
 1575                     err);
 1576                 err = SA_AIS_ERR_NO_RESOURCES;
 1577             }
 1578         } else {
 1579             LOG_ER(
 1580                 "Internal IMM server problem - failure from internal searchInit: %u",
 1581                 err);
 1582             err = SA_AIS_ERR_NO_RESOURCES;
 1583         }
 1584     }
 1585     if (err == SA_AIS_ERR_FAILED_OPERATION) {
 1586         /* We can get FAILED_OPERATION here as response from
 1587            implementer, which is not an allowed return code towards
 1588            client/agent in the searchNext.. So what to convert it to ?
 1589            We will go for NO RESOURCES in the lack of anything better.
 1590          */
 1591         err = SA_AIS_ERR_NO_RESOURCES;
 1592     }
 1593 
 1594     rspo->result = err;
 1595 
 1596     TRACE_2("oi_att_pull_rpl searchNext OK");
 1597     /* We have the updated values fetched in "rsp", or an error indication.
 1598      */
 1599 
 1600     if (isLocal) {
 1601         TRACE_2("Originating client is local");
 1602         /* Case (B) Fetch request continuation locally. */
 1603         SaUint32T reqConn;
 1604         SaInvocationT invoc =
 1605             m_IMMSV_PACK_HANDLE(evt->info.rtAttUpdRpl.sr.remoteNodeId,
 1606                     evt->info.rtAttUpdRpl.sr.searchId);
 1607 
 1608         immModel_fetchSearchReqContinuation(cb, invoc, &reqConn);
 1609         TRACE_2("FETCHED SEARCH REQ CONTINUATION FOR %u|%u->%u",
 1610             (SaUint32T)m_IMMSV_UNPACK_HANDLE_LOW(invoc),
 1611             (SaUint32T)m_IMMSV_UNPACK_HANDLE_HIGH(invoc), reqConn);
 1612 
 1613         if (!reqConn) {
 1614             LOG_WA(
 1615                 "Failed to retrieve search continuation, client died ?");
 1616             /* Cant do anything but just drop it. */
 1617             goto deleteSearchOp;
 1618         }
 1619         TRACE_2("Build local reply to agent");
 1620         search_req_continue(cb, rspo, reqConn);
 1621     } else {
 1622         TRACE_2("Originating client is remote");
 1623         /* Case (C) Fetch implementer continuation to get reply_dest. */
 1624         MDS_DEST reply_dest;
 1625         immModel_fetchSearchImplContinuation(
 1626             cb, rspo->searchId, rspo->requestNodeId, &reply_dest);
 1627         if (!reply_dest) {
 1628             LOG_WA(
 1629                 "Continuation for remote rt attribute fetch was lost, can not complete fetch");
 1630             /* Just drop it. The search should have been, or will
 1631              * be, aborted by a time-out. */
 1632             goto deleteSearchOp;
 1633         } else {
 1634             TRACE_2("Send the fetched result back to request node");
 1635             send_evt.type = IMMSV_EVT_TYPE_IMMND;
 1636             send_evt.info.immnd.type =
 1637                 IMMND_EVT_ND2ND_SEARCH_REMOTE_RSP;
 1638 
 1639             rc = immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMND,
 1640                         reply_dest, &send_evt);
 1641             if (rc != NCSCC_RC_SUCCESS) {
 1642                 LOG_ER(
 1643                     "Problem in replying to peer IMMND over MDS. "
 1644                     "Abandoning searchNext fetch remote rt attrs.");
 1645                 goto deleteSearchOp;
 1646             }
 1647         }
 1648     }
 1649 
 1650 deleteSearchOp:
 1651     if (searchOp) {
 1652         /* immModel_nextResult(cb, searchOp, &rsp, NULL, NULL, NULL,
 1653          * NULL, false); */
 1654         immModel_deleteSearchOp(searchOp);
 1655     }
 1656 
 1657     if (rspo->runtimeAttrs.attrValuesList) {
 1658         rspo->runtimeAttrs.objectName.buf = NULL; /* was borrowed. */
 1659         rspo->runtimeAttrs.objectName.size = 0;
 1660         freeSearchNext(&rspo->runtimeAttrs, false);
 1661     }
 1662     TRACE_2("oi_att_pull_rpl finalize of internal search OK");
 1663     TRACE_LEAVE();
 1664     return rc;
 1665 }
 1666 
 1667 void freeSearchNext(IMMSV_OM_RSP_SEARCH_NEXT *rsp, bool freeTop)
 1668 {
 1669     TRACE_ENTER();
 1670 
 1671     TRACE_2("objectName:%s", rsp->objectName.buf);
 1672     free(rsp->objectName.buf);
 1673     rsp->objectName.buf = NULL;
 1674 
 1675     IMMSV_ATTR_VALUES_LIST *al = rsp->attrValuesList;
 1676     while (al) {
 1677         free(al->n.attrName.buf);
 1678         al->n.attrName.buf = NULL;
 1679         al->n.attrName.size = 0;
 1680         if (al->n.attrValuesNumber) {
 1681             immsv_evt_free_att_val(&al->n.attrValue,
 1682                            al->n.attrValueType);
 1683             if (al->n.attrValuesNumber > 1) {
 1684                 IMMSV_EDU_ATTR_VAL_LIST *att2multi =
 1685                     al->n.attrMoreValues;
 1686                 do {
 1687                     IMMSV_EDU_ATTR_VAL_LIST *tmp;
 1688                     osafassert(att2multi); /* must be at
 1689                                   least one
 1690                                   extra value */
 1691                     immsv_evt_free_att_val(
 1692                         &att2multi->n, al->n.attrValueType);
 1693                     tmp = att2multi;
 1694                     att2multi = att2multi->next;
 1695                     tmp->next = NULL;
 1696                     free(tmp);
 1697                 } while (att2multi);
 1698                 al->n.attrValuesNumber = 0;
 1699                 al->n.attrMoreValues = NULL;
 1700             } // multis deleted
 1701         }
 1702         IMMSV_ATTR_VALUES_LIST *tmp2 = al;
 1703         al = al->next;
 1704         tmp2->next = NULL;
 1705         free(tmp2);
 1706     }
 1707     rsp->attrValuesList = NULL;
 1708     if (freeTop) { /*Top object was also heap allocated. */
 1709         free(rsp);
 1710     }
 1711     TRACE_LEAVE();
 1712 }
 1713 
 1714 static uint32_t search_result_size(IMMSV_OM_RSP_SEARCH_NEXT *rsp)
 1715 {
 1716     uint32_t size = strnlen(rsp->objectName.buf, rsp->objectName.size);
 1717     IMMSV_ATTR_VALUES_LIST *attrList = rsp->attrValuesList;
 1718 
 1719     while (attrList) {
 1720         size += strnlen(attrList->n.attrName.buf,
 1721                 attrList->n.attrName.size);
 1722         size += 4; /* type */
 1723         switch (attrList->n.attrValueType) {
 1724         case SA_IMM_ATTR_SAINT32T:
 1725         case SA_IMM_ATTR_SAUINT32T:
 1726             size += 4 * attrList->n.attrValuesNumber;
 1727             break;
 1728         case SA_IMM_ATTR_SAINT64T:
 1729         case SA_IMM_ATTR_SAUINT64T:
 1730         case SA_IMM_ATTR_SATIMET:
 1731             size += 8 * attrList->n.attrValuesNumber;
 1732             break;
 1733         case SA_IMM_ATTR_SAFLOATT:
 1734             size += sizeof(SaFloatT) * attrList->n.attrValuesNumber;
 1735             break;
 1736         case SA_IMM_ATTR_SADOUBLET:
 1737             size +=
 1738                 sizeof(SaDoubleT) * attrList->n.attrValuesNumber;
 1739             break;
 1740 
 1741         case SA_IMM_ATTR_SANAMET:
 1742         case SA_IMM_ATTR_SASTRINGT:
 1743         case SA_IMM_ATTR_SAANYT:
 1744             size += attrList->n.attrValue.val.x.size *
 1745                 attrList->n.attrValuesNumber;
 1746             break;
 1747 
 1748         default:
 1749             TRACE_1("Incorrect value for SaImmValueTypeT: %ld. ",
 1750                 attrList->n.attrValueType);
 1751             osafassert(0);
 1752             break;
 1753         }
 1754 
 1755         attrList = attrList->next;
 1756     }
 1757 
 1758     return size;
 1759 }
 1760 
 1761 /****************************************************************************
 1762  * Name          : immnd_evt_proc_search_next
 1763  *
 1764  * Description   : Function to process the SaImmOmSearchNext call.
 1765  *                 Note that this is a read, local to the ND (does not go
 1766  *                 over FEVS).
 1767  *
 1768  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 1769  *                 IMMND_EVT *evt - Received Event structure
 1770  *                 IMMSV_SEND_INFO *sinfo - sender info
 1771  *
 1772  * Return Values : NCSCC_RC_SUCCESS/Error.
 1773  *
 1774  * Notes         : None.
 1775  *****************************************************************************/
 1776 static uint32_t immnd_evt_proc_search_next(IMMND_CB *cb, IMMND_EVT *evt,
 1777                        IMMSV_SEND_INFO *sinfo)
 1778 {
 1779     IMMSV_EVT send_evt;
 1780     uint32_t rc = NCSCC_RC_SUCCESS;
 1781     SaAisErrorT error;
 1782     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 1783     IMMND_IMM_CLIENT_NODE *oi_cl_node = NULL;
 1784     IMMND_OM_SEARCH_NODE *sn = NULL;
 1785     SaImmOiHandleT implHandle = 0LL;
 1786     IMMSV_ATTR_NAME_LIST *rtAttrsToFetch = NULL;
 1787     SaUint32T implConn = 0;
 1788     SaUint32T implNodeId = 0;
 1789     IMMSV_OM_RSP_SEARCH_NEXT *rsp = NULL;
 1790     IMMSV_OM_RSP_SEARCH_NEXT *rsp1 = NULL;
 1791     IMMSV_OM_RSP_SEARCH_NEXT **rspList = NULL;
 1792     MDS_DEST implDest = 0LL;
 1793     bool retardSync =
 1794         ((cb->fevs_replies_pending >= cb->mFevsMaxPending) &&
 1795          cb->mIsCoord && (cb->syncPid > 0));
 1796     SaUint32T resultSize = 0;
 1797     IMMSV_OM_RSP_SEARCH_BUNDLE_NEXT bundleSearch = {0, NULL};
 1798     int ix;
 1799     bool isAccessor = false;
 1800     SaUint32T oiTimeout = 0;
 1801 
 1802     TRACE_ENTER();
 1803 
 1804     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 1805 
 1806     /*Look up client-node */
 1807     immnd_client_node_get(cb, evt->info.searchOp.client_hdl, &cl_node);
 1808     if (cl_node == NULL || cl_node->mIsStale) {
 1809         LOG_WA("IMMND - Client Node Get Failed for cli_hdl:%llu",
 1810                evt->info.searchOp.client_hdl);
 1811         error = SA_AIS_ERR_BAD_HANDLE;
 1812         goto agent_rsp;
 1813     }
 1814     TRACE_2("SEARCH NEXT, Look for id:%u", evt->info.searchOp.searchId);
 1815 
 1816     sn = cl_node->searchOpList;
 1817     while (sn) {
 1818         if (sn->searchId == evt->info.searchOp.searchId) {
 1819             break;
 1820         }
 1821         sn = sn->next;
 1822     }
 1823 
 1824     if (!sn) {
 1825         LOG_ER("Could not find search node for search-ID:%u",
 1826                evt->info.searchOp.searchId);
 1827         error = SA_AIS_ERR_BAD_HANDLE;
 1828         goto agent_rsp;
 1829     }
 1830 
 1831     error = immnd_mds_client_not_busy(&(cl_node->tmpSinfo));
 1832     if (error != SA_AIS_OK) {
 1833         if (error == SA_AIS_ERR_BAD_HANDLE) {
 1834             /* The connection appears to be hung indefinitely
 1835                waiting for a reply on a previous syncronous call.
 1836                Discard the connection and return BAD_HANDLE to allow
 1837                client to recover and make progress.
 1838              */
 1839             immnd_proc_imma_discard_connection(cb, cl_node, false);
 1840             rc = immnd_client_node_del(cb, cl_node);
 1841             osafassert(rc == NCSCC_RC_SUCCESS);
 1842             free(cl_node);
 1843         }
 1844         goto agent_rsp;
 1845     }
 1846 
 1847     error = immModel_nextResult(cb, sn->searchOp, &rsp, &implConn,
 1848                     &implNodeId, &rtAttrsToFetch, &implDest,
 1849                     retardSync, &oiTimeout);
 1850     if (error != SA_AIS_OK) {
 1851         goto agent_rsp;
 1852     }
 1853 
 1854     /*Three cases:
 1855        A) No runtime attributes to fetch.
 1856        Reply directly with this call.
 1857        B) Runtime attributes to fetch and the implementer is local.
 1858        => (store continuation?) and call on implementer.
 1859        C) Runtime attributes to fetch, but the implementer is remote
 1860        => store continuation and use request remote invoc over
 1861        either FEVS or direct adressing to peer ND.
 1862      */
 1863 
 1864     if (implNodeId) { /* Case B or C */
 1865         TRACE_2("There is an implementer and there are pure rt's !");
 1866         osafassert(rtAttrsToFetch);
 1867         /*rsp kept in ImmSearchOp to be used in continuation.
 1868            rtAttrsToFetch is expected to be deleted by this layer after
 1869            used.
 1870 
 1871            rsp needs to be appended by the replies.
 1872            ((attrsToFetch needs to be checked/matched when replies
 1873            received.)) If the (non cached runtime) attribute is ALSO
 1874            persistent, then the value should be stored (exactly as
 1875            cached). The only difference with respect to officially
 1876            cached is how the attribute is fetched.
 1877          */
 1878 
 1879         if (implConn) {
 1880             TRACE_2("The implementer is local- case B");
 1881             /*Case B Invoke rtUpdateCallback directly. */
 1882             osafassert(implNodeId == cb->node_id);
 1883             send_evt.type = IMMSV_EVT_TYPE_IMMA;
 1884             send_evt.info.imma.type = IMMA_EVT_ND2A_SEARCH_REMOTE;
 1885             IMMSV_OM_SEARCH_REMOTE *rreq =
 1886                 &send_evt.info.imma.info.searchRemote;
 1887             rreq->remoteNodeId = implNodeId;
 1888             rreq->searchId = sn->searchId;
 1889             rreq->requestNodeId =
 1890                 cb->node_id; /* NOTE: obsolete ? */
 1891             rreq->objectName =
 1892                 rsp->objectName; /* borrow objectName.buf */
 1893             rreq->attributeNames =
 1894                 rtAttrsToFetch; /* borrow this structure */
 1895 
 1896             implHandle = m_IMMSV_PACK_HANDLE(implConn, implNodeId);
 1897             /*Fetch client node for OI ! */
 1898             immnd_client_node_get(cb, implHandle, &oi_cl_node);
 1899             if (oi_cl_node == NULL || oi_cl_node->mIsStale) {
 1900                 immModel_clearLastResult(sn->searchOp);
 1901                 LOG_WA(
 1902                     "ERR_NO_RESOURCES: SearchNext: Implementer died during fetch of pure RTA");
 1903                 error = SA_AIS_ERR_NO_RESOURCES;
 1904                 goto agent_rsp;
 1905             } else {
 1906                 rreq->client_hdl = implHandle;
 1907                 TRACE_2(
 1908                     "MAKING OI-IMPLEMENTER rtUpdate upcall towards agent");
 1909                 if (immnd_mds_msg_send(
 1910                     cb, NCSMDS_SVC_ID_IMMA_OI,
 1911                     oi_cl_node->agent_mds_dest,
 1912                     &send_evt) != NCSCC_RC_SUCCESS) {
 1913                     immModel_clearLastResult(sn->searchOp);
 1914                     LOG_WA(
 1915                         "ERR_NO_RESOURCES: SearchNext - Agent upcall over MDS for rtUpdate failed");
 1916                     error = SA_AIS_ERR_NO_RESOURCES;
 1917                     goto agent_rsp;
 1918                 }
 1919             }
 1920         } else {
 1921             TRACE_2("The implementer is remote - case C");
 1922             /*Case C Send the message directly to nd where
 1923              * implementer resides. */
 1924             send_evt.type = IMMSV_EVT_TYPE_IMMND;
 1925             send_evt.info.immnd.type =
 1926                 IMMND_EVT_ND2ND_SEARCH_REMOTE;
 1927             IMMSV_OM_SEARCH_REMOTE *rreq =
 1928                 &send_evt.info.immnd.info.searchRemote;
 1929             rreq->remoteNodeId = implNodeId;
 1930             rreq->searchId = sn->searchId;
 1931             rreq->requestNodeId =
 1932                 cb->node_id; /* NOTE: obsolete ? */
 1933             rreq->objectName = rsp->objectName; /* borrowed buf; */
 1934             rreq->attributeNames =
 1935                 rtAttrsToFetch; /* borrowed attrList */
 1936 
 1937             TRACE_2("FORWARDING TO OTHER ND!");
 1938 
 1939             rc = immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMND,
 1940                         implDest, &send_evt);
 1941             if (rc != NCSCC_RC_SUCCESS) {
 1942                 immModel_clearLastResult(sn->searchOp);
 1943                 LOG_ER(
 1944                     "ERR_NO_RESOURCES: SearchNext - Problem in sending to peer IMMND over MDS. Aborting searchNext.");
 1945                 error = SA_AIS_ERR_NO_RESOURCES;
 1946                 goto agent_rsp;
 1947             }
 1948         }
 1949 
 1950         /*Register request continuation ! */
 1951         SaInvocationT invoc =
 1952             m_IMMSV_PACK_HANDLE(implNodeId, sn->searchId);
 1953         SaUint32T clientId =
 1954             m_IMMSV_UNPACK_HANDLE_HIGH(evt->info.searchOp.client_hdl);
 1955 
 1956         TRACE_2("SETTING SEARCH REQ CONTINUATION FOR %u|%x->%u",
 1957             sn->searchId, implNodeId, clientId);
 1958 
 1959         immModel_setSearchReqContinuation(cb, invoc, clientId,
 1960                           oiTimeout);
 1961 
 1962         cl_node->tmpSinfo =
 1963             *sinfo; // TODO should be part of continuation?
 1964 
 1965         osafassert(error == SA_AIS_OK);
 1966         if (rtAttrsToFetch) {
 1967             immsv_evt_free_attrNames(rtAttrsToFetch);
 1968         }
 1969         TRACE_LEAVE();
 1970         return NCSCC_RC_SUCCESS;
 1971     } else if (!rtAttrsToFetch) { /*Case A */
 1972         IMMSV_ATTR_NAME_LIST *rtAttrs;
 1973         SaAisErrorT err;
 1974         bool bRtAttrs;
 1975         uint32_t size = search_result_size(rsp);
 1976         resultSize = 1;
 1977         isAccessor = immModel_isSearchOpAccessor(sn->searchOp);
 1978 
 1979         /* Repeat to the maximum search result,
 1980          * or the size os search results becomes bigger then
 1981          * IMMND_SEARCH_BUNDLE_SIZE, or till the object with at least
 1982          * one pure runtime attribute */
 1983         while (resultSize < IMMND_MAX_SEARCH_RESULT &&
 1984                size < IMMND_SEARCH_BUNDLE_SIZE) {
 1985             err = immModel_testTopResult(sn->searchOp, &implNodeId,
 1986                              &bRtAttrs);
 1987             if ((err != SA_AIS_OK) || bRtAttrs)
 1988                 break;
 1989 
 1990             err = immModel_nextResult(
 1991                 cb, sn->searchOp, &rsp1, &implConn, &implNodeId,
 1992                 &rtAttrs, &implDest, retardSync, NULL);
 1993             if (err != SA_AIS_OK) {
 1994                 osafassert(err == SA_AIS_ERR_NOT_EXIST);
 1995                 break;
 1996             }
 1997 
 1998             if (resultSize == 1) {
 1999                 rspList = (IMMSV_OM_RSP_SEARCH_NEXT **)calloc(
 2000                     IMMND_MAX_SEARCH_RESULT,
 2001                     sizeof(IMMSV_OM_RSP_SEARCH_NEXT *));
 2002                 rspList[0] = rsp;
 2003                 rsp = NULL;
 2004             }
 2005 
 2006             rspList[resultSize++] = rsp1;
 2007 
 2008             size += search_result_size(rsp1);
 2009         }
 2010 
 2011         immModel_clearLastResult(sn->searchOp);
 2012     }
 2013 
 2014 agent_rsp:
 2015 
 2016     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 2017 
 2018     if (error == SA_AIS_OK) {
 2019         if (resultSize == 1) {
 2020             send_evt.info.imma.type =
 2021                 isAccessor ? IMMA_EVT_ND2A_ACCESSOR_GET_RSP
 2022                        : IMMA_EVT_ND2A_SEARCHNEXT_RSP;
 2023             send_evt.info.imma.info.searchNextRsp = rsp;
 2024         } else {
 2025             osafassert(rspList);
 2026             bundleSearch.resultSize = resultSize;
 2027             bundleSearch.searchResult =
 2028                 (IMMSV_OM_RSP_SEARCH_NEXT **)malloc(
 2029                 sizeof(IMMSV_OM_RSP_SEARCH_NEXT *) *
 2030                 resultSize);
 2031             for (ix = 0; ix < resultSize; ix++)
 2032                 bundleSearch.searchResult[ix] = rspList[ix];
 2033 
 2034             send_evt.info.imma.type =
 2035                 IMMA_EVT_ND2A_SEARCHBUNDLENEXT_RSP;
 2036             send_evt.info.imma.info.searchBundleNextRsp =
 2037                 &bundleSearch;
 2038         }
 2039     } else {
 2040         send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 2041         send_evt.info.imma.info.errRsp.error = error;
 2042         send_evt.info.imma.info.errRsp.errStrings = NULL;
 2043     }
 2044 
 2045     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 2046 
 2047     if (rsp) {
 2048         freeSearchNext(rsp, true);
 2049     }
 2050 
 2051     if (rspList) {
 2052         for (ix = 0; ix < IMMND_MAX_SEARCH_RESULT; ix++) {
 2053             if (rspList[ix]) {
 2054                 freeSearchNext(rspList[ix], true);
 2055             }
 2056         }
 2057         free(rspList);
 2058 
 2059         immModel_clearLastResult(sn->searchOp);
 2060     }
 2061 
 2062     if (bundleSearch.searchResult) {
 2063         free(bundleSearch.searchResult);
 2064     }
 2065 
 2066     if (rtAttrsToFetch) {
 2067         immsv_evt_free_attrNames(rtAttrsToFetch);
 2068     }
 2069 
 2070     if (error == SA_AIS_ERR_NOT_EXIST || isAccessor) {
 2071         if (immnd_evt_proc_search_finalize(cb, evt, NULL) !=
 2072             NCSCC_RC_SUCCESS) {
 2073             LOG_WA(
 2074                 "Failed in finalizing consumed iterator/accessor");
 2075         }
 2076     }
 2077 
 2078     TRACE_LEAVE();
 2079     return rc;
 2080 }
 2081 
 2082 /****************************************************************************
 2083  * Name          : immnd_evt_proc_search_finalize
 2084  *
 2085  * Description   : Function to process the SaImmOmSearchFinalize call.
 2086  *                 Note that this is a read, local to the ND (does not go
 2087  *                 over FEVS).
 2088  *
 2089  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 2090  *                 IMMND_EVT *evt - Received Event structure
 2091  *                 IMMSV_SEND_INFO *sinfo - sender info
 2092  *
 2093  * Return Values : NCSCC_RC_SUCCESS/Error.
 2094  *
 2095  * Notes         : None.
 2096  *****************************************************************************/
 2097 static uint32_t immnd_evt_proc_search_finalize(IMMND_CB *cb, IMMND_EVT *evt,
 2098                            IMMSV_SEND_INFO *sinfo)
 2099 {
 2100     IMMSV_EVT send_evt;
 2101     uint32_t rc = NCSCC_RC_SUCCESS;
 2102     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 2103     IMMND_OM_SEARCH_NODE *sn = NULL;
 2104     IMMND_OM_SEARCH_NODE **prev = NULL;
 2105     IMMSV_OM_RSP_SEARCH_NEXT *rsp = NULL;
 2106     TRACE_ENTER();
 2107 
 2108     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 2109     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 2110     send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 2111 
 2112     /*Look up client-node */
 2113     immnd_client_node_get(cb, evt->info.searchOp.client_hdl, &cl_node);
 2114     if (cl_node == NULL || cl_node->mIsStale) {
 2115         LOG_WA("IMMND - %llu Client Died",
 2116                evt->info.searchOp.client_hdl);
 2117         send_evt.info.imma.info.errRsp.error = SA_AIS_ERR_BAD_HANDLE;
 2118         goto agent_rsp;
 2119     }
 2120     TRACE_2("SEARCH FINALIZE, Look for id:%u", evt->info.searchOp.searchId);
 2121 
 2122     sn = cl_node->searchOpList;
 2123     prev = &(cl_node->searchOpList);
 2124     while (sn) {
 2125         if (sn->searchId == evt->info.searchOp.searchId) {
 2126             *prev = sn->next;
 2127             break;
 2128         }
 2129         prev = &(sn->next);
 2130         sn = sn->next;
 2131     }
 2132 
 2133     if (!sn) {
 2134         TRACE("Search node for search-ID:%u already finalized",
 2135               evt->info.searchOp.searchId);
 2136         send_evt.info.imma.info.errRsp.error = SA_AIS_OK;
 2137         goto agent_rsp;
 2138     }
 2139 
 2140     immModel_fetchLastResult(sn->searchOp, &rsp);
 2141     immModel_clearLastResult(sn->searchOp);
 2142     if (rsp) {
 2143         freeSearchNext(rsp, true);
 2144     }
 2145 
 2146     immModel_deleteSearchOp(sn->searchOp);
 2147     sn->searchOp = NULL;
 2148     sn->next = NULL;
 2149     free(sn);
 2150     send_evt.info.imma.info.errRsp.error = SA_AIS_OK;
 2151 agent_rsp:
 2152 
 2153     if (sinfo) {
 2154         rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 2155     }
 2156     TRACE_LEAVE();
 2157     return rc;
 2158 }
 2159 
 2160 /****************************************************************************
 2161  * Name          : immnd_evt_proc_safe_read
 2162  *
 2163  * Description   : Function to process the saImmOmCcbObjectRead call.
 2164  *                 This call can in some cases be resolved with success locally.
 2165  *                 This will be the case if the object to be accessed is already
 2166  *                 locked previously by this CCB.
 2167  *
 2168  *
 2169  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 2170  *                 IMMND_EVT *evt - Received Event structure
 2171  *                 IMMSV_SEND_INFO *sinfo - sender info
 2172  *****************************************************************************/
 2173 static uint32_t immnd_evt_proc_safe_read(IMMND_CB *cb, IMMND_EVT *evt,
 2174                      IMMSV_SEND_INFO *sinfo)
 2175 {
 2176     IMMSV_EVT send_evt;
 2177     uint32_t rc = NCSCC_RC_SUCCESS;
 2178     SaAisErrorT err = SA_AIS_OK;
 2179     TRACE_ENTER();
 2180     memset(&send_evt, 0, sizeof(IMMSV_EVT));
 2181 
 2182     if (evt->info.searchInit.ccbId == 0) {
 2183         err = SA_AIS_ERR_LIBRARY;
 2184         LOG_WA("ERR_LIBRARY: Received zero ccb-id for safe-read");
 2185         goto error;
 2186     }
 2187 
 2188     /* Dive into ImmModel to do locking checks.
 2189        If already locked in this ccb continue with accessor.
 2190        If locked by other ccb then reject with ERR_BUSY
 2191        If not locked, then generate fevs message for locking AND read.
 2192      */
 2193 
 2194     err = immModel_objectIsLockedByCcb(cb, &(evt->info.searchInit));
 2195 
 2196     switch (err) {
 2197     case SA_AIS_OK:
 2198         TRACE(
 2199             "Safe read: Object is locked by this CCB(%u). Go ahead and safe-read",
 2200             evt->info.searchInit.ccbId);
 2201         /* Invoke accessor_get which will send the reply. */
 2202         break;
 2203 
 2204     case SA_AIS_ERR_BUSY:
 2205         TRACE(
 2206             "Object is locked by some other CCB than this CCB(%u). Reply with BUSY",
 2207             evt->info.searchInit.ccbId);
 2208         goto error;
 2209 
 2210     case SA_AIS_ERR_INTERRUPT:
 2211         TRACE(
 2212             "Object not locked. Ccb (%u) needs to lock it over fevs. Reply with INTERRUPT",
 2213             evt->info.searchInit.ccbId);
 2214         /* Should result in fevs message to read-lock object. */
 2215         goto error;
 2216 
 2217     default:
 2218         TRACE("Unusual error from immModel_objectIsLockedByCcb: %u",
 2219               err);
 2220         goto error;
 2221     }
 2222 
 2223     rc = immnd_evt_proc_accessor_get(cb, evt, sinfo);
 2224     goto done;
 2225 
 2226 error:
 2227     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 2228     send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 2229     send_evt.info.imma.info.errRsp.error = err;
 2230     send_evt.info.imma.info.errRsp.errStrings = NULL;
 2231 
 2232     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 2233 
 2234 done:
 2235     TRACE_LEAVE();
 2236     return rc;
 2237 }
 2238 
 2239 /****************************************************************************
 2240  * Name          : immnd_evt_proc_accessor_get
 2241  *
 2242  * Description   : Function to process the saImmOmAccessorGet call.
 2243  *                 Note that this is a read, local to the ND (does not go
 2244  *                 over FEVS).
 2245  *
 2246  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 2247  *                 IMMND_EVT *evt - Received Event structure
 2248  *                 IMMSV_SEND_INFO *sinfo - sender info
 2249  *
 2250  * Return Values : NCSCC_RC_SUCCESS/Error.
 2251  *
 2252  * Notes         : None.
 2253  *****************************************************************************/
 2254 static uint32_t immnd_evt_proc_accessor_get(IMMND_CB *cb, IMMND_EVT *evt,
 2255                         IMMSV_SEND_INFO *sinfo)
 2256 {
 2257     IMMSV_EVT send_evt;
 2258     uint32_t rc = NCSCC_RC_SUCCESS;
 2259     SaAisErrorT error = SA_AIS_OK;
 2260     void *searchOp = NULL;
 2261     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 2262     IMMND_OM_SEARCH_NODE *sn = NULL;
 2263     TRACE_ENTER();
 2264 
 2265     /* Search Init */
 2266 
 2267     memset(&send_evt, 0, sizeof(IMMSV_EVT));
 2268 
 2269     if (evt->info.searchInit.ccbId != 0) {
 2270         TRACE_2("SAFE READ :%s CcbId: %u",
 2271             evt->info.searchInit.rootName.buf,
 2272             evt->info.searchInit.ccbId);
 2273     } else {
 2274         TRACE_2("ACCESSOR GET:%s", evt->info.searchInit.rootName.buf);
 2275     }
 2276 
 2277     /*Look up client-node */
 2278     immnd_client_node_get(cb, evt->info.searchInit.client_hdl, &cl_node);
 2279     if (cl_node == NULL || cl_node->mIsStale) {
 2280         LOG_WA("IMMND - Client Node Get Failed for cli_hdl");
 2281         TRACE_2("Client Node get failed for handle:%llu",
 2282             evt->info.searchInit.client_hdl);
 2283         error = SA_AIS_ERR_BAD_HANDLE;
 2284         goto search_init_err;
 2285     }
 2286 
 2287     error = immModel_searchInitialize(cb, &(evt->info.searchInit),
 2288                       &searchOp, false, true);
 2289 
 2290     if (error != SA_AIS_OK) {
 2291         goto search_init_err;
 2292     }
 2293 
 2294     /*Generate search-id */
 2295     sn = calloc(1, sizeof(IMMND_OM_SEARCH_NODE));
 2296     if (sn == NULL) {
 2297         error = SA_AIS_ERR_NO_MEMORY;
 2298         goto search_init_err;
 2299     }
 2300 
 2301     sn->searchId = cb->cli_id_gen++;
 2302     if (cb->cli_id_gen == 0xffffffff) { /* handle wrap arround */
 2303         cb->cli_id_gen = 1;
 2304     }
 2305     sn->searchOp = searchOp;
 2306     sn->next = cl_node->searchOpList;
 2307     cl_node->searchOpList = sn;
 2308 
 2309     send_evt.info.immnd.type = IMMND_EVT_A2ND_SEARCHNEXT;
 2310     send_evt.info.immnd.info.searchOp.searchId = sn->searchId;
 2311     send_evt.info.immnd.info.searchOp.client_hdl =
 2312         evt->info.searchInit.client_hdl;
 2313 
 2314     /*  Search Next handles the rest, sends reply, error or not. */
 2315     rc = immnd_evt_proc_search_next(cb, &(send_evt.info.immnd), sinfo);
 2316     goto done;
 2317 
 2318 search_init_err:
 2319     osafassert(error != SA_AIS_OK);
 2320 
 2321     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 2322     send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 2323     send_evt.info.imma.info.errRsp.error = error;
 2324     send_evt.info.imma.info.errRsp.errStrings = NULL;
 2325 
 2326     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 2327 
 2328     if (searchOp) {
 2329         immModel_deleteSearchOp(searchOp);
 2330     }
 2331 
 2332 done:
 2333     TRACE_LEAVE();
 2334     return rc;
 2335 }
 2336 
 2337 /****************************************************************************
 2338  * Name          : immnd_evt_proc_class_desc_get
 2339  *
 2340  * Description   : Function to process the SaImmOmClassDescriptionGet call.
 2341  *                 Note that this is a read, local to the ND (does not go
 2342  *                 over FEVS).
 2343  *
 2344  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 2345  *                 IMMND_EVT *evt - Received Event structure
 2346  *                 IMMSV_SEND_INFO *sinfo - sender info
 2347  *
 2348  * Return Values : NCSCC_RC_SUCCESS/Error.
 2349  *
 2350  * Notes         : None.
 2351  *****************************************************************************/
 2352 static uint32_t immnd_evt_proc_class_desc_get(IMMND_CB *cb, IMMND_EVT *evt,
 2353                           IMMSV_SEND_INFO *sinfo)
 2354 {
 2355     IMMSV_EVT send_evt;
 2356     uint32_t rc = NCSCC_RC_SUCCESS;
 2357     SaAisErrorT error;
 2358 
 2359     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 2360 
 2361     TRACE_2("className:%s", evt->info.classDescr.className.buf);
 2362     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 2363 
 2364     error =
 2365         immModel_classDescriptionGet(cb, &(evt->info.classDescr.className),
 2366                      &(send_evt.info.imma.info.classDescr));
 2367     if (error == SA_AIS_OK) {
 2368         send_evt.info.imma.type = IMMA_EVT_ND2A_CLASS_DESCR_GET_RSP;
 2369     } else {
 2370         send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 2371         send_evt.info.imma.info.errRsp.error = error;
 2372     }
 2373 
 2374     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 2375     /*Deallocate the extras on the send_message */
 2376     IMMSV_ATTR_DEF_LIST *p =
 2377         send_evt.info.imma.info.classDescr.attrDefinitions;
 2378     while (p) {
 2379         IMMSV_ATTR_DEF_LIST *prev = p;
 2380         if (p->d.attrName.size) {
 2381             free(p->d.attrName.buf); /*Free-Y */
 2382             p->d.attrName.buf = NULL;
 2383         }
 2384         if (p->d.attrDefaultValue) {
 2385             if ((p->d.attrValueType == SA_IMM_ATTR_SASTRINGT) ||
 2386                 (p->d.attrValueType == SA_IMM_ATTR_SAANYT) ||
 2387                 (p->d.attrValueType == SA_IMM_ATTR_SANAMET)) {
 2388                 if (p->d.attrDefaultValue->val.x
 2389                     .size) { /*Free-ZZ */
 2390                     free(p->d.attrDefaultValue->val.x.buf);
 2391                     p->d.attrDefaultValue->val.x.buf = NULL;
 2392                     p->d.attrDefaultValue->val.x.size = 0;
 2393                 }
 2394             }
 2395             free(p->d.attrDefaultValue); /*Free-Z */
 2396             p->d.attrDefaultValue = NULL;
 2397         }
 2398         p = p->next;
 2399         free(prev); /*Free-X */
 2400     }
 2401     send_evt.info.imma.info.classDescr.attrDefinitions = NULL;
 2402     return rc;
 2403 }
 2404 
 2405 /****************************************************************************
 2406  * Name          : immnd_evt_proc_imm_finalize
 2407  *
 2408  * Description   : Function to process the SaImmOmFinalize and SaImmOiFinalize
 2409  *                 from IMM Agents.
 2410  *
 2411  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 2412  *                 IMMSV_EVT *evt - Received Event structure
 2413  *                 bool isOm - true=> OM finalize, false => OI finalize.
 2414  *
 2415  * Return Values : NCSCC_RC_SUCCESS/Error.
 2416  *
 2417  * Notes         : None.
 2418  *****************************************************************************/
 2419 static uint32_t immnd_evt_proc_imm_finalize(IMMND_CB *cb, IMMND_EVT *evt,
 2420                         IMMSV_SEND_INFO *sinfo, bool isOm)
 2421 {
 2422     /* Note: parameter isOm is ignored, should be noted in cl_node */
 2423     IMMSV_EVT send_evt;
 2424     uint32_t rc = NCSCC_RC_SUCCESS;
 2425     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 2426 
 2427     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 2428 
 2429     TRACE_2("finalize for handle: %llx", evt->info.finReq.client_hdl);
 2430     immnd_client_node_get(cb, evt->info.finReq.client_hdl, &cl_node);
 2431     /* Skipping check for stale client for this case (finalize client call)
 2432      */
 2433     if (cl_node == NULL) {
 2434         LOG_WA("IMMND - Client Node Get Failed for cli_hdl %llu",
 2435                evt->info.finReq.client_hdl);
 2436         send_evt.info.imma.info.errRsp.error = SA_AIS_ERR_BAD_HANDLE;
 2437         goto agent_rsp;
 2438     }
 2439 
 2440     immnd_proc_imma_discard_connection(cb, cl_node, false);
 2441 
 2442     rc = immnd_client_node_del(cb, cl_node);
 2443     if (rc == NCSCC_RC_FAILURE) {
 2444         LOG_ER("IMMND - Client Tree Del Failed , cli_hdl");
 2445         send_evt.info.imma.info.errRsp.error = SA_AIS_ERR_LIBRARY;
 2446     }
 2447 
 2448     free(cl_node);
 2449 
 2450     send_evt.info.imma.info.errRsp.error = SA_AIS_OK;
 2451 
 2452 agent_rsp:
 2453     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 2454     send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_FINALIZE_RSP;
 2455     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 2456     return rc;
 2457 }
 2458 
 2459 /****************************************************************************
 2460  * Name          : immnd_evt_proc_cl_imma_timeout
 2461  *
 2462  * Description   : Function that receives message from an imma client that
 2463  *                 the client handle/node has timed out in the library on
 2464  *                 a syncronous downcall. This means that unless the reply
 2465  *                 (such as from an OI) does arrive to clear the call, then
 2466  *                 the handle/node is doomed in the current implementation.
 2467  *                 This is handled by reducing the number of TRY_AGAINs
 2468  *                 (rejected new syncronous calls) allowed on the blocked
 2469  *                 cl_node.
 2470  *
 2471  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 2472  *                 IMMSV_EVT *evt - Received Event structure
 2473  *                 bool isOm - true=> OM finalize, false => OI finalize.
 2474  *
 2475  * Return Values : NCSCC_RC_SUCCESS/Error.
 2476  *
 2477  * Notes         : None.
 2478  *****************************************************************************/
 2479 static uint32_t immnd_evt_proc_cl_imma_timeout(IMMND_CB *cb, IMMND_EVT *evt)
 2480 {
 2481     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 2482     TRACE_ENTER();
 2483 
 2484     TRACE_2("timeout in imma library for handle: %llx",
 2485         evt->info.finReq.client_hdl);
 2486     immnd_client_node_get(cb, evt->info.finReq.client_hdl, &cl_node);
 2487     if (!cl_node) {
 2488         goto done;
 2489     }
 2490 
 2491     SaUint32T clientId =
 2492         m_IMMSV_UNPACK_HANDLE_HIGH(evt->info.finReq.client_hdl);
 2493     if (immModel_purgeSyncRequest(cb, clientId)) {
 2494         /* One and only one request has been purged => no reply message
 2495            send will be attempted for *that* request. We can safely
 2496            clear the MDS reply info. This will also clear the handle for
 2497            new use in sending syncronous requests.
 2498         */
 2499         immnd_proc_imma_discard_connection(cb, cl_node, false);
 2500         osafassert(immnd_client_node_del(cb, cl_node) ==
 2501                NCSCC_RC_SUCCESS);
 2502         free(cl_node);
 2503     } else {
 2504         /* The request could not be purged (depends on request type),
 2505            or the reply has already been arrived but came too late
 2506            to reach a client that has timedout.
 2507         */
 2508         if (immnd_mds_client_not_busy(&(cl_node->tmpSinfo)) ==
 2509             SA_AIS_ERR_TRY_AGAIN) {
 2510             /* Reply has not arrived, i.e. the request type was not
 2511                possible to purge. Force any subsequent syncronous
 2512                calls to invalidate the handle.
 2513             */
 2514             cl_node->tmpSinfo.mSynReqCount = 255;
 2515         }
 2516     }
 2517 
 2518 done:
 2519     TRACE_LEAVE();
 2520     return NCSCC_RC_SUCCESS;
 2521 }
 2522 
 2523 /****************************************************************************
 2524  * Name          : immnd_evt_proc_imm_resurrect
 2525  *
 2526  * Description   : Function to attempt to resurrect an IMMA client_id after an
 2527  *                 IMMND restart. This to try to make the restart transparent
 2528  *                 towards the clients.
 2529  *
 2530  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 2531  *                 IMMSV_EVT *evt - Received Event structure
 2532  *                 bool isOm - true=> OM resurrect, false => OI resurrect.
 2533  *
 2534  * Return Values : NCSCC_RC_SUCCESS/Error.
 2535  *
 2536  * Notes         : None.
 2537  *****************************************************************************/
 2538 static uint32_t immnd_evt_proc_imm_resurrect(IMMND_CB *cb, IMMND_EVT *evt,
 2539                          IMMSV_SEND_INFO *sinfo, bool isOm)
 2540 {
 2541     /* Note: parameter isOm is ignored, should be noted in cl_node*/
 2542     IMMSV_EVT send_evt;
 2543     uint32_t rc = NCSCC_RC_SUCCESS;
 2544     SaAisErrorT error = SA_AIS_OK;
 2545     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 2546     SaUint32T clientId =
 2547         m_IMMSV_UNPACK_HANDLE_HIGH(evt->info.finReq.client_hdl);
 2548     SaUint32T nodeId =
 2549         m_IMMSV_UNPACK_HANDLE_LOW(evt->info.finReq.client_hdl);
 2550 
 2551     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 2552 
 2553     TRACE_2("resurect for handle: %llx", evt->info.finReq.client_hdl);
 2554 
 2555     /* First check that no one else grabbed the old handle value before us.
 2556      */
 2557     immnd_client_node_get(cb, evt->info.finReq.client_hdl, &cl_node);
 2558     if (cl_node != NULL) {
 2559         if (cl_node->mIsResurrect) {
 2560             /* The temporary client node is still present
 2561                => this immnd is still being synced. */
 2562             TRACE_2(
 2563                 "Rejecting OM client resurrect, sync not complete");
 2564             error = SA_AIS_ERR_TRY_AGAIN;
 2565         } else {
 2566             LOG_ER(
 2567                 "IMMND - Client Node already occupied for handle %llu",
 2568                 evt->info.finReq.client_hdl);
 2569             error = SA_AIS_ERR_EXIST;
 2570         }
 2571         goto agent_rsp;
 2572     }
 2573 
 2574     int load_pid = immModel_getLoader(cb);
 2575 
 2576     if (load_pid != 0) {
 2577         TRACE_2("Rejecting OM client resurrect if sync not complete");
 2578         error = SA_AIS_ERR_TRY_AGAIN;
 2579         goto agent_rsp;
 2580     }
 2581 
 2582     /* Go ahead and create the client object using the old handle value. */
 2583 
 2584     cl_node = calloc(1, sizeof(IMMND_IMM_CLIENT_NODE));
 2585     if (cl_node == NULL) {
 2586         LOG_ER("IMMND - Client Alloc Failed");
 2587         error = SA_AIS_ERR_NO_MEMORY;
 2588         goto agent_rsp;
 2589     }
 2590 
 2591     if ((cb->cli_id_gen <= clientId) && (clientId < 0x000f0000)) {
 2592         cb->cli_id_gen = clientId + 1;
 2593     }
 2594 
 2595     if (cb->node_id != nodeId) {
 2596         LOG_ER("Rejecting OM client resurrect from wrong node! %x",
 2597                nodeId);
 2598         free(cl_node);
 2599         error = SA_AIS_ERR_FAILED_OPERATION;
 2600         goto agent_rsp;
 2601     }
 2602 
 2603     cl_node->imm_app_hdl = m_IMMSV_PACK_HANDLE(clientId, cb->node_id);
 2604     cl_node->agent_mds_dest = sinfo->dest;
 2605     /*cl_node->version= .. TODO correct version (not used today)*/
 2606     cl_node->sv_id = (isOm) ? NCSMDS_SVC_ID_IMMA_OM : NCSMDS_SVC_ID_IMMA_OI;
 2607 
 2608     if (immnd_client_node_add(cb, cl_node) != NCSCC_RC_SUCCESS) {
 2609         LOG_ER("IMMND - Client Tree Add Failed , cli_hdl");
 2610         free(cl_node);
 2611         error = SA_AIS_ERR_FAILED_OPERATION;
 2612         goto agent_rsp;
 2613     }
 2614 
 2615     TRACE_2("Added client with id: %llx <node:%x, count:%u>",
 2616         cl_node->imm_app_hdl, cb->node_id, (SaUint32T)clientId);
 2617 
 2618     error = SA_AIS_OK;
 2619 
 2620 agent_rsp:
 2621     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 2622     send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_RESURRECT_RSP;
 2623     send_evt.info.imma.info.errRsp.error = error;
 2624     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 2625     return rc;
 2626 }
 2627 
 2628 /****************************************************************************
 2629  * Name          : immnd_evt_proc_imm_client_high
 2630  *
 2631  * Description   : Function to bump up the clientId counter after
 2632  *                 IMMND restart. The clientId would be bumped up by
 2633  *                 client_high messages from all pre-existing IMMAgents.
 2634  *                 This is an attempt to increase the chances of successfull
 2635  *                 client resurrections, when client_high is a low number.
 2636  *
 2637  *                 The counter does wrap arround, but a restarted IMMND will
 2638  *                 restart the counter from zero, causing high risk for
 2639  *                 collision and failed resurrects.
 2640  *                 We skip bumping up the counter if the clientHigh is too
 2641  *                 high.
 2642  *
 2643  *****************************************************************************/
 2644 static uint32_t immnd_evt_proc_imm_client_high(IMMND_CB *cb, IMMND_EVT *evt,
 2645                            IMMSV_SEND_INFO *sinfo,
 2646                            bool isOm)
 2647 {
 2648     SaUint32T clientHigh = evt->info.initReq.client_pid;
 2649     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 2650 
 2651     TRACE_2("Client high received: %x", clientHigh);
 2652 
 2653     if ((cb->cli_id_gen <= clientHigh) && (clientHigh < 0x000f0000)) {
 2654         cb->cli_id_gen = evt->info.initReq.client_pid + 1;
 2655         TRACE_2("Client high bumped up to: %x, IMMND just restarted?",
 2656             cb->cli_id_gen);
 2657     }
 2658 
 2659     /* Create a temporary client place holder for resurrect.*/
 2660     cl_node = calloc(1, sizeof(IMMND_IMM_CLIENT_NODE));
 2661     memset(cl_node, '\0', sizeof(IMMND_IMM_CLIENT_NODE));
 2662     osafassert(cl_node);
 2663     cl_node->imm_app_hdl = m_IMMSV_PACK_HANDLE(clientHigh, cb->node_id);
 2664     cl_node->agent_mds_dest = sinfo->dest;
 2665     cl_node->sv_id = (isOm) ? NCSMDS_SVC_ID_IMMA_OM : NCSMDS_SVC_ID_IMMA_OI;
 2666     cl_node->mIsResurrect = 0x1;
 2667 
 2668     if (immnd_client_node_add(cb, cl_node) != NCSCC_RC_SUCCESS) {
 2669 #if 0 // CLOUD-PROTO  clients should be discarded !!!!
 2670         LOG_ER("IMMND - Adding temporary imma client Failed.");
 2671         /*free(cl_node);*/
 2672         abort();
 2673 #endif
 2674     }
 2675 
 2676     TRACE_2("Added client with id: %llx <node:%x, count:%u>",
 2677         cl_node->imm_app_hdl, cb->node_id, clientHigh);
 2678 
 2679     return NCSCC_RC_SUCCESS;
 2680 }
 2681 
 2682 /****************************************************************************
 2683  * Name          : immnd_evt_proc_recover_ccb_result
 2684  *
 2685  * Description   : Function attempts to obtain the result of a terminated CCB.
 2686  *                 This is used in IMMA resurrect (both OM and OI side) to hide
 2687  *                 the effects of losing contact with IMMND during a CCB in
 2688  *progress. Of particular importance is resolving the outcome of a ccb-apply.
 2689  *
 2690  *                 The possible replies to IMMA are:
 2691  *                 SA_AIS_ERR_TRY_AGAIN - If this IMMND is not in sync (not sent
 2692  *from here). SA_AIS_OK - The CCB id was commited. SA_AIS_ERR_FAILED_OPERATION -
 2693  *The CCB id was aborted. SA_AIS_ERR_NO_RESOURCES - The CCB id
 2694  *is unknown (too old) or in progress (should not be possible).
 2695  *
 2696  *****************************************************************************/
 2697 static uint32_t immnd_evt_proc_recover_ccb_result(IMMND_CB *cb, IMMND_EVT *evt,
 2698                           IMMSV_SEND_INFO *sinfo)
 2699 {
 2700     IMMSV_EVT send_evt;
 2701     uint32_t rc = NCSCC_RC_SUCCESS;
 2702     TRACE_ENTER();
 2703 
 2704     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 2705     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 2706     send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 2707 
 2708     int load_pid = immModel_getLoader(cb);
 2709 
 2710     if (load_pid != 0) {
 2711         TRACE_2("Rejecting OM client resurrect if sync not complete");
 2712         send_evt.info.imma.info.errRsp.error = SA_AIS_ERR_TRY_AGAIN;
 2713     } else {
 2714         send_evt.info.imma.info.errRsp.error =
 2715             immModel_ccbResult(cb, evt->info.ccbId);
 2716     }
 2717 
 2718     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 2719 
 2720     if (rc != NCSCC_RC_SUCCESS) {
 2721         LOG_WA("Failed to send response to IMMA over MDS rc:%u", rc);
 2722     }
 2723 
 2724     TRACE_LEAVE();
 2725     return NCSCC_RC_SUCCESS;
 2726 }
 2727 
 2728 /****************************************************************************
 2729  * Name          : immnd_evt_proc_admowner_init
 2730  *
 2731  * Description   : Function to process the SaImmOmAdminOwnerInitialize
 2732  *                 from Applications
 2733  *
 2734  *
 2735  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 2736  *                 IMMSV_EVT *evt - Received Event structure
 2737  *
 2738  * Return Values : NCSCC_RC_SUCCESS/Error.
 2739  *
 2740  * Notes         : None.
 2741  *****************************************************************************/
 2742 static uint32_t immnd_evt_proc_admowner_init(IMMND_CB *cb, IMMND_EVT *evt,
 2743                          IMMSV_SEND_INFO *sinfo)
 2744 {
 2745     IMMSV_EVT send_evt;
 2746     uint32_t rc = NCSCC_RC_SUCCESS;
 2747     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 2748     SaImmHandleT client_hdl;
 2749 
 2750     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 2751 
 2752     client_hdl = evt->info.adminitReq.client_hdl;
 2753     immnd_client_node_get(cb, client_hdl, &cl_node);
 2754     if (cl_node == NULL || cl_node->mIsStale) {
 2755         LOG_WA("ERR_BAD_HANDLE: Client %llu not found in server",
 2756                client_hdl);
 2757         send_evt.info.imma.info.admInitRsp.error =
 2758             SA_AIS_ERR_BAD_HANDLE;
 2759         goto agent_rsp;
 2760     }
 2761 
 2762     if (!immnd_is_immd_up(cb)) {
 2763         send_evt.info.imma.info.admInitRsp.error = SA_AIS_ERR_TRY_AGAIN;
 2764         goto agent_rsp;
 2765     }
 2766 
 2767     if (immModel_immNotWritable(cb) ||
 2768         (cb->mSyncFinalizing && cb->fevs_out_count)) {
 2769         /*Avoid broadcasting doomed requests. */
 2770         send_evt.info.imma.info.admInitRsp.error = SA_AIS_ERR_TRY_AGAIN;
 2771         goto agent_rsp;
 2772     }
 2773 
 2774     if (cb->fevs_replies_pending >= cb->mFevsMaxPending) {
 2775         TRACE_2(
 2776             "ERR_TRY_AGAIN: Too many pending incoming fevs messages (> %u) rejecting admo_init request",
 2777             cb->mFevsMaxPending);
 2778         send_evt.info.imma.info.admInitRsp.error = SA_AIS_ERR_TRY_AGAIN;
 2779         goto agent_rsp;
 2780     }
 2781 
 2782     send_evt.info.imma.info.admInitRsp.error =
 2783         immnd_mds_client_not_busy(&(cl_node->tmpSinfo));
 2784 
 2785     if (send_evt.info.imma.info.admInitRsp.error != SA_AIS_OK) {
 2786         if (send_evt.info.imma.info.admInitRsp.error ==
 2787             SA_AIS_ERR_BAD_HANDLE) {
 2788             /* The connection appears to be hung indefinitely
 2789                waiting for a reply on a previous syncronous call.
 2790                Discard the connection and return BAD_HANDLE to allow
 2791                client to recover and make progress.
 2792              */
 2793             immnd_proc_imma_discard_connection(cb, cl_node, false);
 2794             rc = immnd_client_node_del(cb, cl_node);
 2795             osafassert(rc == NCSCC_RC_SUCCESS);
 2796             free(cl_node);
 2797         }
 2798         goto agent_rsp;
 2799     }
 2800 
 2801     /*aquire a ND sender count and send the fevs to ND (without waiting) */
 2802     cb->fevs_replies_pending++; /*flow control */
 2803     if (cb->fevs_replies_pending > 1) {
 2804         TRACE("Messages pending:%u", cb->fevs_replies_pending);
 2805     }
 2806 
 2807     send_evt.type = IMMSV_EVT_TYPE_IMMD;
 2808     send_evt.info.immd.type = IMMD_EVT_ND2D_ADMINIT_REQ;
 2809     send_evt.info.immd.info.admown_init.client_hdl =
 2810         evt->info.adminitReq.client_hdl;
 2811 
 2812     send_evt.info.immd.info.admown_init.i = evt->info.adminitReq.i;
 2813 
 2814     /* send the request to the IMMD, reply comes back over fevs. */
 2815 
 2816     rc = immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMD, cb->immd_mdest_id,
 2817                 &send_evt);
 2818 
 2819     if (rc != NCSCC_RC_SUCCESS) {
 2820         LOG_WA("IMMND - AdminOwner Initialize Failed");
 2821         send_evt.info.imma.info.admInitRsp.error = SA_AIS_ERR_TRY_AGAIN;
 2822         cb->fevs_replies_pending--;
 2823         goto agent_rsp;
 2824     }
 2825 
 2826     /*Save sinfo in continuation.
 2827        Note: should set up a wait time for the continuation roughly in line
 2828        with IMMSV_WAIT_TIME. */
 2829     cl_node->tmpSinfo = *sinfo; // TODO should be part of continuation ?
 2830 
 2831     return rc;
 2832 
 2833 agent_rsp:
 2834     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 2835     send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ADMINIT_RSP;
 2836 
 2837     TRACE_2("immnd_evt:imm_adminOwner_init: SENDRSP FAIL %u ",
 2838         send_evt.info.imma.info.admInitRsp.error);
 2839     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 2840 
 2841     return rc;
 2842 }
 2843 
 2844 /****************************************************************************
 2845  * Name          : immnd_evt_proc_impl_set
 2846  *
 2847  * Description   : Function to process the SaImmOiImplementerSet
 2848  *                 from Applications
 2849  *
 2850  *
 2851  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 2852  *                 IMMSV_EVT *evt - Received Event structure
 2853  *
 2854  * Return Values : NCSCC_RC_SUCCESS/Error.
 2855  *
 2856  * Notes         : None.
 2857  *****************************************************************************/
 2858 static uint32_t immnd_evt_proc_impl_set(IMMND_CB *cb, IMMND_EVT *evt,
 2859                     IMMSV_SEND_INFO *sinfo)
 2860 {
 2861     IMMSV_EVT send_evt;
 2862     uint32_t rc = NCSCC_RC_SUCCESS;
 2863     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 2864     SaImmHandleT client_hdl;
 2865 
 2866     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 2867 
 2868     client_hdl = evt->info.implSet.client_hdl;
 2869     immnd_client_node_get(cb, client_hdl, &cl_node);
 2870     if (cl_node == NULL || cl_node->mIsStale) {
 2871         LOG_WA("ERR_BAD_HANDLE: Client %llu not found in server",
 2872                client_hdl);
 2873         send_evt.info.imma.info.implSetRsp.error =
 2874             SA_AIS_ERR_BAD_HANDLE;
 2875         goto agent_rsp;
 2876     }
 2877 
 2878     if (!immnd_is_immd_up(cb)) {
 2879         send_evt.info.imma.info.implSetRsp.error = SA_AIS_ERR_TRY_AGAIN;
 2880         goto agent_rsp;
 2881     }
 2882 
 2883     if (!immModel_protocol43Allowed(cb) &&
 2884         (immModel_immNotWritable(cb) ||
 2885          (cb->mSyncFinalizing && cb->fevs_out_count))) {
 2886         /*Avoid broadcasting doomed requests. */
 2887         send_evt.info.imma.info.implSetRsp.error = SA_AIS_ERR_TRY_AGAIN;
 2888         goto agent_rsp;
 2889     }
 2890 
 2891     if (evt->type == IMMND_EVT_A2ND_OI_IMPL_SET_2 &&
 2892         !immModel_protocol45Allowed(cb)) {
 2893         LOG_WA(
 2894             "Failed to set OI implementer (%u) with OI callback timeout "
 2895             "(OpenSAF 4.5 features are disabled)",
 2896             evt->info.implSet.impl_id);
 2897         send_evt.info.imma.info.implSetRsp.error =
 2898             SA_AIS_ERR_NO_RESOURCES;
 2899         goto agent_rsp;
 2900     }
 2901 
 2902     if (cb->fevs_replies_pending >= cb->mFevsMaxPending) {
 2903         TRACE_2(
 2904             "ERR_TRY_AGAIN: Too many pending incoming fevs messages (> %u) rejecting impl_set request",
 2905             cb->mFevsMaxPending);
 2906         send_evt.info.imma.info.implSetRsp.error = SA_AIS_ERR_TRY_AGAIN;
 2907         goto agent_rsp;
 2908     }
 2909 
 2910     if (strncmp(evt->info.implSet.impl_name.buf, OPENSAF_IMM_PBE_IMPL_NAME,
 2911             evt->info.implSet.impl_name.size) == 0) {
 2912         if (cl_node->mIsPbe) {
 2913             TRACE("Persistent Back End OI %s is attaching",
 2914                   OPENSAF_IMM_PBE_IMPL_NAME);
 2915         } else {
 2916             LOG_WA(
 2917                 "Will not allow Pbe implementer %s to attach, client was not forked by this IMMND",
 2918                 OPENSAF_IMM_PBE_IMPL_NAME);
 2919             send_evt.info.imma.info.implSetRsp.error =
 2920                 SA_AIS_ERR_BAD_HANDLE;
 2921             goto agent_rsp;
 2922         }
 2923     }
 2924 
 2925     send_evt.info.imma.info.implSetRsp.error =
 2926         immnd_mds_client_not_busy(&(cl_node->tmpSinfo));
 2927 
 2928     if (send_evt.info.imma.info.implSetRsp.error != SA_AIS_OK) {
 2929         if (send_evt.info.imma.info.implSetRsp.error ==
 2930             SA_AIS_ERR_BAD_HANDLE) {
 2931             /* The connection appears to be hung indefinitely
 2932                waiting for a reply on a previous syncronous call.
 2933                Discard the connection and return BAD_HANDLE to allow
 2934                client to recover and make progress.
 2935              */
 2936             immnd_proc_imma_discard_connection(cb, cl_node, false);
 2937             rc = immnd_client_node_del(cb, cl_node);
 2938             osafassert(rc == NCSCC_RC_SUCCESS);
 2939             free(cl_node);
 2940         }
 2941         goto agent_rsp;
 2942     }
 2943 
 2944     /* Avoid sending the implSet request if the implementer is currently
 2945        occupied locally. This greatly reduces the risk of a an incorrect
 2946        create of implementer at sync clients, where the create is rejected
 2947        at veteran nodes. It can still happen if the implementer is free here
 2948        and now, but gets occupied soon after in a subsequent implementerSet
 2949        over fevs arriving before this implementerSet arrives back over fevs.
 2950        See finalizeSync #1871.
 2951     */
 2952     SaUint32T impl_id;
 2953     send_evt.info.imma.info.implSetRsp.error =
 2954         immModel_implIsFree(cb, &evt->info.implSet, &impl_id);
 2955 
 2956     if (send_evt.info.imma.info.implSetRsp.error != SA_AIS_OK) {
 2957         if (impl_id && send_evt.info.imma.info.implSetRsp.error ==
 2958                    SA_AIS_ERR_EXIST) {
 2959             /* Immediately respond OK to agent */
 2960             send_evt.info.imma.info.implSetRsp.error = SA_AIS_OK;
 2961             send_evt.info.imma.info.implSetRsp.implId = impl_id;
 2962         }
 2963         goto agent_rsp;
 2964     }
 2965 
 2966     cb->fevs_replies_pending++; /*flow control */
 2967     if (cb->fevs_replies_pending > 1) {
 2968         TRACE("Messages pending:%u", cb->fevs_replies_pending);
 2969     }
 2970 
 2971     send_evt.type = IMMSV_EVT_TYPE_IMMD;
 2972     send_evt.info.immd.info.impl_set.r.client_hdl = client_hdl;
 2973     send_evt.info.immd.info.impl_set.r.impl_name.size =
 2974         evt->info.implSet.impl_name.size;
 2975     send_evt.info.immd.info.impl_set.r.impl_name.buf =
 2976         evt->info.implSet.impl_name
 2977         .buf; /*Warning re-using buffer, no copy. */
 2978     send_evt.info.immd.info.impl_set.reply_dest = cb->immnd_mdest_id;
 2979 
 2980     if (evt->type == IMMND_EVT_A2ND_OI_IMPL_SET_2) {
 2981         send_evt.info.immd.info.impl_set.r.oi_timeout =
 2982             evt->info.implSet.oi_timeout;
 2983         send_evt.info.immd.type = IMMD_EVT_ND2D_IMPLSET_REQ_2;
 2984     } else {
 2985         send_evt.info.immd.type = IMMD_EVT_ND2D_IMPLSET_REQ;
 2986     }
 2987 
 2988     /* send the request to the IMMD, reply comes back over fevs. */
 2989 
 2990     rc = immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMD, cb->immd_mdest_id,
 2991                 &send_evt);
 2992 
 2993     send_evt.info.immd.info.impl_set.r.impl_name.size = 0;
 2994     send_evt.info.immd.info.impl_set.r.impl_name.buf =
 2995         NULL; /*precaution. */
 2996 
 2997     if (rc != NCSCC_RC_SUCCESS) {
 2998         LOG_WA("Problem in sending to IMMD over MDS");
 2999         send_evt.info.imma.info.implSetRsp.error = SA_AIS_ERR_TRY_AGAIN;
 3000         cb->fevs_replies_pending--;
 3001         goto agent_rsp;
 3002     }
 3003 
 3004     /*Save sinfo in continuation.
 3005        Note should set up a wait time for the continuation roughly in line
 3006        with IMMSV_WAIT_TIME.
 3007      */
 3008     cl_node->tmpSinfo = *sinfo; // TODO: should be part of continuation?
 3009 
 3010     return rc;
 3011 
 3012 agent_rsp:
 3013     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 3014     send_evt.info.imma.type = IMMA_EVT_ND2A_IMPLSET_RSP;
 3015 
 3016     TRACE_2("SENDRSP FAIL %u ", send_evt.info.imma.info.implSetRsp.error);
 3017     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 3018 
 3019     return rc;
 3020 }
 3021 
 3022 /****************************************************************************
 3023  * Name          : immnd_evt_proc_ccb_init
 3024  *
 3025  * Description   : Function to process the SaImmOmCcbInitialize
 3026  *                 from Applications
 3027  *
 3028  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 3029  *                 IMMSV_EVT *evt - Received Event structure
 3030  *
 3031  * Return Values : NCSCC_RC_SUCCESS/Error.
 3032  *
 3033  * Notes         : None.
 3034  *****************************************************************************/
 3035 static uint32_t immnd_evt_proc_ccb_init(IMMND_CB *cb, IMMND_EVT *evt,
 3036                     IMMSV_SEND_INFO *sinfo)
 3037 {
 3038     IMMSV_EVT send_evt;
 3039     uint32_t rc = NCSCC_RC_SUCCESS;
 3040     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 3041     SaImmHandleT client_hdl;
 3042     TRACE_ENTER();
 3043 
 3044     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 3045 
 3046     client_hdl = evt->info.ccbinitReq.client_hdl;
 3047     immnd_client_node_get(cb, client_hdl, &cl_node);
 3048     if (cl_node == NULL || cl_node->mIsStale) {
 3049         LOG_WA("ERR_BAD_HANDLE: Client %llu not found in server",
 3050                client_hdl);
 3051         send_evt.info.imma.info.ccbInitRsp.error =
 3052             SA_AIS_ERR_BAD_HANDLE;
 3053         goto agent_rsp;
 3054     }
 3055 
 3056     if (!immnd_is_immd_up(cb)) {
 3057         send_evt.info.imma.info.ccbInitRsp.error = SA_AIS_ERR_TRY_AGAIN;
 3058         goto agent_rsp;
 3059     }
 3060 
 3061     if (immModel_immNotWritable(cb) ||
 3062         (cb->mSyncFinalizing && cb->fevs_out_count)) {
 3063         /*Avoid broadcasting doomed requests. */
 3064         send_evt.info.imma.info.ccbInitRsp.error = SA_AIS_ERR_TRY_AGAIN;
 3065         goto agent_rsp;
 3066     }
 3067 
 3068     if (cb->fevs_replies_pending >= cb->mFevsMaxPending) {
 3069         TRACE_2(
 3070             "ERR_TRY_AGAIN: Too many pending incoming fevs messages (> %u) rejecting ccb_init request",
 3071             cb->mFevsMaxPending);
 3072         send_evt.info.imma.info.ccbInitRsp.error = SA_AIS_ERR_TRY_AGAIN;
 3073         goto agent_rsp;
 3074     }
 3075 
 3076     send_evt.info.imma.info.ccbInitRsp.error =
 3077         immnd_mds_client_not_busy(&(cl_node->tmpSinfo));
 3078 
 3079     if (send_evt.info.imma.info.ccbInitRsp.error != SA_AIS_OK) {
 3080         if (send_evt.info.imma.info.ccbInitRsp.error ==
 3081             SA_AIS_ERR_BAD_HANDLE) {
 3082             /* The connection appears to be hung indefinitely
 3083                waiting for a reply on a previous syncronous call.
 3084                Discard the connection and return BAD_HANDLE to allow
 3085                client to recover and make progress.
 3086              */
 3087             immnd_proc_imma_discard_connection(cb, cl_node, false);
 3088             rc = immnd_client_node_del(cb, cl_node);
 3089             osafassert(rc == NCSCC_RC_SUCCESS);
 3090             free(cl_node);
 3091         }
 3092         goto agent_rsp;
 3093     }
 3094 
 3095     cb->fevs_replies_pending++; /*flow control */
 3096     if (cb->fevs_replies_pending > 1) {
 3097         TRACE("Messages pending:%u", cb->fevs_replies_pending);
 3098     }
 3099 
 3100     send_evt.type = IMMSV_EVT_TYPE_IMMD;
 3101     send_evt.info.immd.type = IMMD_EVT_ND2D_CCBINIT_REQ;
 3102     send_evt.info.immd.info.ccb_init = evt->info.ccbinitReq;
 3103 
 3104     /* send the request to the IMMD, reply comes back over fevs. */
 3105 
 3106     TRACE_2("Sending CCB init msg to IMMD AO:%u FL:%llx client:%llu",
 3107         send_evt.info.immd.info.ccb_init.adminOwnerId,
 3108         send_evt.info.immd.info.ccb_init.ccbFlags,
 3109         send_evt.info.immd.info.ccb_init.client_hdl);
 3110     rc = immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMD, cb->immd_mdest_id,
 3111                 &send_evt);
 3112 
 3113     if (rc != NCSCC_RC_SUCCESS) {
 3114         LOG_WA("Problem in sending ro IMMD over MDS");
 3115         send_evt.info.imma.info.ccbInitRsp.error = SA_AIS_ERR_TRY_AGAIN;
 3116         cb->fevs_replies_pending--;
 3117         goto agent_rsp;
 3118     }
 3119 
 3120     /*Save sinfo in continuation.
 3121        Note should set up a wait time for the continuation roughly in line
 3122        with IMMSV_WAIT_TIME. */
 3123     cl_node->tmpSinfo = *sinfo; // TODO should be part of continuation?
 3124     TRACE_LEAVE();
 3125     return rc;
 3126 
 3127 agent_rsp:
 3128     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 3129     send_evt.info.imma.type = IMMA_EVT_ND2A_CCBINIT_RSP;
 3130 
 3131     TRACE_2("SENDRSP FAIL %u ", send_evt.info.imma.info.ccbInitRsp.error);
 3132     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 3133 
 3134     TRACE_LEAVE();
 3135     return rc;
 3136 }
 3137 
 3138 /****************************************************************************
 3139  * Name          : immnd_evt_proc_rt_update
 3140  *
 3141  * Description   : Function to process the saImmOiRtObjectUpdate/_2
 3142  *                 from local agent. Only pure local rtattrs are
 3143  *                 updated here. Cached and Persistent rtattrs are first
 3144  *                 forwarded over fevs.
 3145  *
 3146  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 3147  *                 IMMSV_EVT *evt - Received Event structure
 3148  *
 3149  * Return Values : NCSCC_RC_SUCCESS/Error.
 3150  *
 3151  * Notes         : None.
 3152  *****************************************************************************/
 3153 
 3154 static uint32_t immnd_evt_proc_rt_update(IMMND_CB *cb, IMMND_EVT *evt,
 3155                      IMMSV_SEND_INFO *sinfo)
 3156 {
 3157     IMMSV_EVT send_evt;
 3158     uint32_t rc = NCSCC_RC_SUCCESS;
 3159     SaAisErrorT err = SA_AIS_OK;
 3160     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 3161     SaImmHandleT client_hdl;
 3162     SaUint32T clientId;
 3163     SaUint32T clientNode;
 3164     SaUint32T dummyPbeConn = 0;
 3165     SaUint32T dummyPbe2BConn = 0;
 3166     NCS_NODE_ID *dummyPbeNodeIdPtr = NULL;
 3167     SaUint32T dummyContinuationId = 0;
 3168     SaUint32T spApplConn = 0; /* Special applier locally connected. */
 3169     TRACE_ENTER();
 3170     unsigned int isPureLocal = 1;
 3171 
 3172     client_hdl = evt->info.objModify.immHandle;
 3173     immnd_client_node_get(cb, client_hdl, &cl_node);
 3174     if (cl_node == NULL || cl_node->mIsStale) {
 3175         LOG_WA("ERR_BAD_HANDLE: Client %llu not found in server",
 3176                client_hdl);
 3177         err = SA_AIS_ERR_BAD_HANDLE;
 3178         goto agent_rsp;
 3179     }
 3180 
 3181     /* Do broadcast checks BEFORE updating model because we dont want
 3182        to do the update and then fail to propagate it if it should be
 3183        propagated. Dowsnide: Even pure local rtattrs can not be updated if
 3184        we can not communicate with the IMMD. */
 3185 
 3186     if (!immnd_is_immd_up(cb)) {
 3187         err = SA_AIS_ERR_TRY_AGAIN;
 3188         goto agent_rsp;
 3189     }
 3190 
 3191     err = immnd_mds_client_not_busy(&(cl_node->tmpSinfo));
 3192     if (err != SA_AIS_OK) {
 3193         if (err == SA_AIS_ERR_BAD_HANDLE) {
 3194             /* The connection appears to be hung indefinitely
 3195                waiting for a reply on a previous syncronous call.
 3196                Discard the connection and return BAD_HANDLE to allow
 3197                client to recover and make progress.
 3198              */
 3199             immnd_proc_imma_discard_connection(cb, cl_node, false);
 3200             rc = immnd_client_node_del(cb, cl_node);
 3201             osafassert(rc == NCSCC_RC_SUCCESS);
 3202             free(cl_node);
 3203         }
 3204         goto agent_rsp;
 3205     }
 3206 
 3207     clientId = m_IMMSV_UNPACK_HANDLE_HIGH(client_hdl);
 3208     clientNode = m_IMMSV_UNPACK_HANDLE_LOW(client_hdl);
 3209 
 3210     err = immModel_rtObjectUpdate(
 3211         cb, &(evt->info.objModify), clientId, clientNode, &isPureLocal,
 3212         &dummyContinuationId, &dummyPbeConn, dummyPbeNodeIdPtr, &spApplConn,
 3213         &dummyPbe2BConn);
 3214 
 3215     osafassert(!dummyContinuationId && !dummyPbeConn && !spApplConn &&
 3216            !dummyPbe2BConn); /* Only relevant for cached (fevs first) */
 3217 
 3218     if (!isPureLocal && (err == SA_AIS_OK)) {
 3219         TRACE_2(
 3220             "immnd_evt_proc_rt_update was not pure local, i.e. cached RT attrs");
 3221         /*This message is allowed even when imm not writable. But
 3222            isPureLocal should never be false if we are not writable,
 3223            thus we should never get to this code branch if imm is not
 3224            writbale.
 3225          */
 3226 
 3227         if (cb->fevs_replies_pending >= cb->mFevsMaxPending) {
 3228             TRACE_2(
 3229                 "ERR_TRY_AGAIN: Too many pending incoming fevs messages (> %u) rejecting rt_update request",
 3230                 cb->mFevsMaxPending);
 3231             err = SA_AIS_ERR_TRY_AGAIN;
 3232             goto agent_rsp;
 3233         }
 3234 
 3235         cb->fevs_replies_pending++; /*flow control */
 3236         if (cb->fevs_replies_pending > 1) {
 3237             TRACE("Messages pending:%u", cb->fevs_replies_pending);
 3238         }
 3239 
 3240         memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 3241         send_evt.type = IMMSV_EVT_TYPE_IMMD;
 3242         send_evt.info.immd.type = IMMD_EVT_ND2D_OI_OBJ_MODIFY;
 3243         send_evt.info.immd.info.objModify = evt->info.objModify;
 3244         /* Borrow pointer structures. */
 3245         /* send the request to the IMMD, reply comes back over fevs. */
 3246 
 3247         if (!immnd_is_immd_up(cb)) {
 3248             err = SA_AIS_ERR_TRY_AGAIN;
 3249             cb->fevs_replies_pending--;
 3250             goto agent_rsp;
 3251         }
 3252 
 3253         rc = immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMD,
 3254                     cb->immd_mdest_id, &send_evt);
 3255 
 3256         if (rc != NCSCC_RC_SUCCESS) {
 3257             LOG_WA("Problem in sending to IMMD over MDS");
 3258             err = SA_AIS_ERR_TRY_AGAIN;
 3259             cb->fevs_replies_pending--;
 3260             goto agent_rsp;
 3261         }
 3262 
 3263         /*Save sinfo in continuation.
 3264            Note should set up a wait time for the continuation roughly
 3265            in line with IMMSV_WAIT_TIME. */
 3266         cl_node->tmpSinfo =
 3267             *sinfo; // TODO should be part of continuation?
 3268         goto done;
 3269     }
 3270 
 3271     TRACE_2("immnd_evt_proc_rt_update was pure local, i.e. pure RT attrs");
 3272 /* Here is where we should end up if the saImmOiRtObjectUpdate_2 call was
 3273    made because of an SaImmOiRtAttrUpdateCallbackT upcall. In that case
 3274    we are pulling values for pure (i.e. local) runtime attributes.
 3275    If the saImmOiRtObjectUpdate_2 call is a push call from the implementer
 3276    then the attributes are expected to be cached, i.e. non-local. */
 3277 
 3278 agent_rsp:
 3279 
 3280     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 3281     TRACE_2("send immediate reply to client/agent");
 3282     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 3283     send_evt.info.imma.info.errRsp.error = err;
 3284     send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 3285     TRACE_2("SENDRSP RESULT %u ", err);
 3286     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 3287 
 3288 done:
 3289     free(evt->info.objModify.objectName.buf);
 3290     evt->info.objModify.objectName.buf = NULL;
 3291     evt->info.objModify.objectName.size = 0;
 3292     immsv_free_attrmods(evt->info.objModify.attrMods);
 3293     evt->info.objModify.attrMods = NULL;
 3294     TRACE_LEAVE();
 3295     return rc;
 3296 }
 3297 
 3298 #if 0 /*Only for debug */
 3299 static void dump_usrbuf(USRBUF *ub)
 3300 {
 3301     if (ub) {
 3302         TRACE_2("IMMND dump_usrbuf: ");
 3303         TRACE_2("next:%p ", ub->next);
 3304         TRACE_2("link:%p ", ub->link);
 3305         TRACE_2("count:%u ", ub->count);
 3306         TRACE_2("start:%u ", ub->start);
 3307         TRACE_2("pool_ops:%p ", ub->pool_ops);
 3308         TRACE_2("specific.opaque:%u ", ub->specific.opaque);
 3309         TRACE_2("payload:%p", ub->payload);
 3310     } else {
 3311         TRACE_2("EMPTY", ub->start);
 3312     }
 3313 }
 3314 #endif
 3315 
 3316 /****************************************************************************
 3317  * Name          : immnd_evt_proc_fevs_forward
 3318  *
 3319  * Description   : Function to handle (forward) fevs messages.
 3320  *
 3321  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 3322  *                 IMMSV_EVT *evt - Received Event structure
 3323  *                 sinfo    - Reply address for syncronous call.
 3324  *                 onStack - true => Message resides on stack.
 3325  *                           false => message resides on heap.
 3326  *                 newMsg  - true => If the fevs out-queue is not empty,
 3327  *                                      New messages can be forced to go via
 3328  *                                      the out-queue even when there is no
 3329  *                                      fevs overflow. This to maintain sender
 3330  *                                      order and not only IMMD fevs order.
 3331  *                                      Sender order is currently used during
 3332  *                                      finalizeSync when the finalizeSync has
 3333  *                                      been sent from coord, until it has been
 3334  *                                      received (cb->mSyncFinalizing is true).
 3335  *                           false =>Message has already passed queue.
 3336  *                                      Fevs order through IMMD is enough.
 3337  *
 3338  * Return Values : NCSCC_RC_SUCCESS/Error.
 3339  *****************************************************************************/
 3340 static uint32_t immnd_evt_proc_fevs_forward(IMMND_CB *cb, IMMND_EVT *evt,
 3341                         IMMSV_SEND_INFO *sinfo,
 3342                         bool onStack, bool newMsg)
 3343 {
 3344     IMMSV_EVT send_evt;
 3345     uint32_t rc = NCSCC_RC_SUCCESS;
 3346     SaAisErrorT error;
 3347     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 3348     SaImmHandleT client_hdl;
 3349     bool asyncReq = (!sinfo || sinfo->stype != MDS_SENDTYPE_SNDRSP);
 3350 
 3351     TRACE_2("sender_count: %llu size: %u ", evt->info.fevsReq.sender_count,
 3352         evt->info.fevsReq.msg.size);
 3353 
 3354     client_hdl = evt->info.fevsReq.client_hdl;
 3355     immnd_client_node_get(cb, client_hdl, &cl_node);
 3356     if (cl_node == NULL || cl_node->mIsStale) {
 3357         if (asyncReq) {
 3358             TRACE(
 3359                 "IMMND - Client %llu went down on asyncronous request, still sending it",
 3360                 client_hdl);
 3361         } else {
 3362             LOG_WA(
 3363                 "IMMND - Client %llu went down on syncronous request, discarding request",
 3364                 client_hdl);
 3365             error = SA_AIS_ERR_BAD_HANDLE;
 3366             goto agent_rsp;
 3367         }
 3368     }
 3369 
 3370     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 3371 
 3372     if (!immnd_is_immd_up(cb)) {
 3373         if (asyncReq) {
 3374             /* We could enqueue async messages (typically replies)
 3375                but there is a risk that a failover would be followed
 3376                by a "burst" of old replies, which could provoke more
 3377                problems than it solves.
 3378             */
 3379             if (cb->mState == IMM_SERVER_SYNC_SERVER) {
 3380                 LOG_IN(
 3381                     "Asyncronous FEVS request received when IMMD is down during sync, will buffer");
 3382             } else {
 3383                 LOG_WA(
 3384                     "IMMND - Director Service Is Down. Dropping asyncronous FEVS request.");
 3385                 return NCSCC_RC_FAILURE;
 3386             }
 3387         } else {
 3388             LOG_WA(
 3389                 "IMMND - Director Service Is Down. Rejecting FEVS request.");
 3390             error = SA_AIS_ERR_TRY_AGAIN;
 3391             goto agent_rsp;
 3392         }
 3393     }
 3394 
 3395     if (!asyncReq) {
 3396         error = immnd_mds_client_not_busy(&(cl_node->tmpSinfo));
 3397         if (error != SA_AIS_OK) {
 3398             if (error == SA_AIS_ERR_BAD_HANDLE) {
 3399                 /* The connection appears to be hung
 3400                    indefinitely waiting for a reply on a
 3401                    previous syncronous call. Discard the
 3402                    connection and return BAD_HANDLE to allow
 3403                    client to recover and make progress.
 3404                 */
 3405                 immnd_proc_imma_discard_connection(cb, cl_node,
 3406                                    false);
 3407                 rc = immnd_client_node_del(cb, cl_node);
 3408                 osafassert(rc == NCSCC_RC_SUCCESS);
 3409                 free(cl_node);
 3410             }
 3411             goto agent_rsp;
 3412         }
 3413     }
 3414 
 3415     if (newMsg) {
 3416         error =
 3417             immnd_fevs_local_checks(cb, &(evt->info.fevsReq), sinfo);
 3418         if (error != SA_AIS_OK) {
 3419             /*Fevs request will NOT be forwarded to IMMD.
 3420               Return directly with error or OK for idempotent
 3421               requests.
 3422              */
 3423             if (error == SA_AIS_ERR_NO_BINDINGS) {
 3424                 /* Bogus error code indicating that SA_AIS_OK
 3425                    should be returned immediately on grounds of
 3426                    idempotency. That is the state desired by the
 3427                    request is already in place. This short
 3428                    circuit of fevs due to idempotency detected
 3429                    *locally* can only be done during on-going
 3430                    sync, where *no* other interfering mutating
 3431                    requests are allowed, i.e. such mutations
 3432                    could not already be in the buffered fevs
 3433                    backlog.
 3434                  */
 3435                 osafassert(immModel_immNotWritable(cb));
 3436                 error = SA_AIS_OK;
 3437             }
 3438 
 3439             if (asyncReq) {
 3440                 LOG_WA(
 3441                     "Asyncronous FEVS message failed verification - dropping message!");
 3442                 return NCSCC_RC_FAILURE;
 3443             }
 3444             goto agent_rsp; // Fevs request is not forwarded to IMMD
 3445         }
 3446     }
 3447 
 3448     /* Special handling before forwarding. */
 3449     if ((evt->info.fevsReq.sender_count == 0x1) &&
 3450         !(cl_node && cl_node->mIsSync) &&
 3451         (immModel_immNotWritable(cb) ||
 3452          (cb->mSyncFinalizing && cb->fevs_out_count))) {
 3453         /* sender_count set to 1 if we are to check locally for
 3454           writability before sending to IMMD. This to avoid broadcasting
 3455           requests that are doomed anyway. The clause '!(cl_node &&
 3456           cl_node->mIsSync)' is there to allow the immsync process to
 3457           use saImmOmClassCreate. The local check is skipped for immsync
 3458           resulting in the class-creaet message to be broadcast over
 3459           fevs. The class create will be rejected at all normal nodes
 3460           with TRY_AGAIN, but accepted at sync clients. See #2754.
 3461 
 3462           Immnd coord opens for writability when finalizeSync message is
 3463           generated. But finalizeSync is asyncronous since 4.1 and may
 3464           get enqueued into the out queue, instead of being sent
 3465           immediately. While finalizeSync is in the out queue,
 3466                       syncronous fevs messages that require
 3467           writability, could bypass finalizeSync. This is BAD because
 3468           such messages can arrive back here at coord and be accepted,
 3469           but will be rejected at other nodes until they receive
 3470           finalizeSync and open for writes.
 3471 
 3472           Such bypass is prevented here by also screening on
 3473           mSyncFinalizing, which is true starting when coord generates
 3474           finalize sync and ends when coord receives its own finalize
 3475           sync. This is actually more restrivtive than necessary. An
 3476           optimization is to detect when finalizeSync is actually sent
 3477           from coord, instead of waiting until it is received. As soon
 3478           as it is has been sent from the coord, any subsequent sends
 3479           from coord can not bypass the finalizeSync. We dont quite
 3480           capture the send of finalizeSync, but if the out-queue is
 3481           empty, then we know finalizeSync must have been sent.
 3482 
 3483           Note that fevs messages that do not require IMMND writability,
 3484           such as runtime-attribute-updates, will not be affected by
 3485           this.
 3486         */
 3487 
 3488         if (asyncReq) {
 3489             LOG_IN(
 3490                 "Rare case (?) of enqueueing async & write message due to on-going sync.");
 3491             immnd_enqueue_outgoing_fevs_msg(
 3492                 cb, client_hdl, &(evt->info.fevsReq.msg));
 3493             return NCSCC_RC_SUCCESS;
 3494         } else {
 3495             error = SA_AIS_ERR_TRY_AGAIN;
 3496             goto agent_rsp;
 3497         }
 3498     }
 3499 
 3500     /* If overflow .....OR IMMD is down.....OR sync is on-going AND
 3501        out-queue is not empty => go via out-queue. The sync should be
 3502        throttled by immnd_evt_proc_search_next. */
 3503     if ((cb->fevs_replies_pending >= cb->mFevsMaxPending) ||
 3504         !immnd_is_immd_up(cb) ||
 3505         ((cb->mState == IMM_SERVER_SYNC_SERVER) && cb->fevs_out_count &&
 3506          asyncReq && newMsg)) {
 3507         if (asyncReq) {
 3508 
 3509             if (onStack) {
 3510                 /* Delaying the send => message must be copied
 3511                  * to heap. */
 3512                 char *buf = malloc(evt->info.fevsReq.msg.size);
 3513                 memcpy(buf, evt->info.fevsReq.msg.buf,
 3514                        evt->info.fevsReq.msg.size);
 3515                 evt->info.fevsReq.msg.buf = buf;
 3516             }
 3517             unsigned int backlog = immnd_enqueue_outgoing_fevs_msg(
 3518                 cb, client_hdl, &(evt->info.fevsReq.msg));
 3519 
 3520             if (backlog % 50) {
 3521                 TRACE_2(
 3522                     "Too many pending incoming FEVS messages (> %u) "
 3523                     "enqueueing async message. Backlog:%u",
 3524                     cb->mFevsMaxPending, backlog);
 3525             } else {
 3526                 LOG_IN(
 3527                     "Too many pending incoming FEVS messages (> %u) "
 3528                     "enqueueing async message. Backlog:%u",
 3529                     cb->mFevsMaxPending, backlog);
 3530             }
 3531 
 3532             return NCSCC_RC_SUCCESS;
 3533         } else {
 3534             /* Syncronous message, never goes to out-queue, instead
 3535                push back to user. Should only be for the overflow
 3536                case. */
 3537             TRACE_2(
 3538                 "ERR_TRY_AGAIN: Too many pending FEVS message replies (> %u) rejecting request",
 3539                 cb->mFevsMaxPending);
 3540             error = SA_AIS_ERR_TRY_AGAIN;
 3541             goto agent_rsp;
 3542         }
 3543     }
 3544 
 3545     cb->fevs_replies_pending++; /*flow control */
 3546     if (cb->fevs_replies_pending > 1) {
 3547         TRACE("Replies pending:%u", cb->fevs_replies_pending);
 3548     }
 3549 
 3550     send_evt.type = IMMSV_EVT_TYPE_IMMD;
 3551     if ((evt->type == IMMND_EVT_A2ND_IMM_FEVS_2) &&
 3552         immModel_protocol41Allowed(cb)) {
 3553         send_evt.info.immd.type = IMMD_EVT_ND2D_FEVS_REQ_2;
 3554     } else {
 3555         send_evt.info.immd.type = IMMD_EVT_ND2D_FEVS_REQ;
 3556     }
 3557     send_evt.info.immd.info.fevsReq.reply_dest = cb->immnd_mdest_id;
 3558     send_evt.info.immd.info.fevsReq.client_hdl = client_hdl;
 3559     send_evt.info.immd.info.fevsReq.msg.size = evt->info.fevsReq.msg.size;
 3560     /*Borrow the octet buffer from the input message instead of copying */
 3561     send_evt.info.immd.info.fevsReq.msg.buf = evt->info.fevsReq.msg.buf;
 3562     send_evt.info.immd.info.fevsReq.isObjSync =
 3563         (evt->type == IMMND_EVT_A2ND_IMM_FEVS_2)
 3564         ? (uint8_t)evt->info.fevsReq.isObjSync
 3565         : 0x0;
 3566 
 3567     /* send the request to the IMMD */
 3568 
 3569     TRACE_2("SENDING FEVS TO IMMD");
 3570     rc = immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMD, cb->immd_mdest_id,
 3571                 &send_evt);
 3572 
 3573     if (rc != NCSCC_RC_SUCCESS) {
 3574         cb->fevs_replies_pending--;
 3575         if (asyncReq) {
 3576             LOG_ER(
 3577                 "Problem in sending asyncronous FEVS message over MDS - dropping message!");
 3578             return NCSCC_RC_FAILURE;
 3579         } else {
 3580             LOG_WA("Problem in sending FEVS message over MDS");
 3581             error = SA_AIS_ERR_TRY_AGAIN;
 3582             goto agent_rsp;
 3583         }
 3584     }
 3585 
 3586     /*Save sinfo in continuation.
 3587        Note should set up a wait time for the continuation roughly in line
 3588        with IMMSV_WAIT_TIME. */
 3589     osafassert(rc == NCSCC_RC_SUCCESS);
 3590 
 3591     if (evt->info.fevsReq.sender_count > 0x1) {
 3592         /* sender_count greater than 1 if this is an admop message.
 3593          This is to generate a request continuation at the client
 3594          node BEFORE sending the request over fevs. Otherwise there
 3595          is a risk that the reply may arrive back at the request node,
 3596          before the request arrives over fevs. This can happen because
 3597          the reply is not sent over the fevs "bottleneck".
 3598          */
 3599         SaUint32T conn = m_IMMSV_UNPACK_HANDLE_HIGH(client_hdl);
 3600         SaInvocationT saInv =
 3601             (SaInvocationT)evt->info.fevsReq.sender_count;
 3602 
 3603         immModel_setAdmReqContinuation(cb, saInv, conn);
 3604     }
 3605 
 3606     if (cl_node && sinfo && !asyncReq) {
 3607         cl_node->tmpSinfo =
 3608             *sinfo; // TODO: should be part of continuation?
 3609     }
 3610 
 3611     /* Only a single continuation per client
 3612        possible, but not when op is async!
 3613        This is where the ND sender count is needed.
 3614        But we should be able to use the agents
 3615        count/continuation-id .. ? */
 3616 
 3617     if (cl_node && cl_node->mIsSync) {
 3618         osafassert(!cl_node->mSyncBlocked);
 3619         if (!asyncReq) {
 3620             cl_node->mSyncBlocked = true;
 3621         }
 3622     }
 3623 
 3624     return rc; /*Normal return here => asyncronous reply in fevs_rcv. */
 3625 
 3626 agent_rsp:
 3627 
 3628     send_evt.type = IMMSV_EVT_TYPE_IMMA;
 3629     send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 3630     send_evt.info.imma.info.errRsp.error = error;
 3631 
 3632     osafassert(!asyncReq);
 3633 
 3634     TRACE_2("SENDRSP FAIL %u ", send_evt.info.imma.info.admInitRsp.error);
 3635     rc = immnd_mds_send_rsp(cb, sinfo, &send_evt);
 3636 
 3637     return rc;
 3638 }
 3639 
 3640 static bool is_class_name_reserved(const IMMND_CB* cb, const char* name)
 3641 {
 3642     int i = 0;
 3643     const char* r_name;
 3644     char** list = cb->reserved_class_names;
 3645     while ((r_name = list[i++])) {
 3646         if (!strcmp(name, r_name)) return true;
 3647     }
 3648     return false;
 3649 }
 3650 
 3651 /*
 3652   Function for performing immnd local checks on fevs packed messages.
 3653   Normally they pass the checks and are forwarded to the IMMD.
 3654   The intention is to prevent a bogus message from a bad client to
 3655   propagate to all IMMNDs. The intention is also to capture any IMMND
 3656   local handling that can or should be done before forwarding.
 3657 
 3658   For example, saImmOiClassImplementerSet and saImmOiObjectImplementerSet
 3659   are not allowed during imm-sync. But the idempotent case of trying to
 3660   set class/object implementer in a way that is already set should be
 3661   allowed. Such an idempotency case must be resolved locally at veteran
 3662   nodes and not propagated over fevs, because sync clients may not yet
 3663   have synced the implementer setting and thus reject the idempotent case.
 3664 
 3665   sinfo - only valid for synchronous calls, can be NULL
 3666 
 3667 */
 3668 static SaAisErrorT immnd_fevs_local_checks(IMMND_CB *cb, IMMSV_FEVS *fevsReq,
 3669                        const IMMSV_SEND_INFO *sinfo)
 3670 {
 3671     SaAisErrorT error = SA_AIS_OK;
 3672     osafassert(fevsReq);
 3673     IMMSV_OCTET_STRING *msg = &fevsReq->msg;
 3674     SaImmHandleT clnt_hdl = fevsReq->client_hdl;
 3675     NCS_NODE_ID nodeId = m_IMMSV_UNPACK_HANDLE_LOW(clnt_hdl);
 3676     SaUint32T conn = m_IMMSV_UNPACK_HANDLE_HIGH(clnt_hdl);
 3677     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 3678     bool isLoading =
 3679         (cb->mState == IMM_SERVER_LOADING_SERVER) && immModel_getLoader(cb);
 3680     NCS_UBAID uba;
 3681     TRACE_ENTER();
 3682     uba.start = NULL;
 3683     IMMSV_EVT frwrd_evt;
 3684     memset(&frwrd_evt, '\0', sizeof(IMMSV_EVT));
 3685 
 3686     immnd_client_node_get(cb, clnt_hdl, &cl_node);
 3687     if (cl_node == NULL || cl_node->mIsStale) {
 3688         error = SA_AIS_ERR_BAD_HANDLE;
 3689         goto client_down;
 3690     }
 3691 
 3692     /*Unpack the embedded message */
 3693     if (ncs_enc_init_space_pp(&uba, 0, 0) != NCSCC_RC_SUCCESS) {
 3694         LOG_ER("Failed init ubaid");
 3695         error = SA_AIS_ERR_NO_RESOURCES;
 3696         goto unpack_failure;
 3697     }
 3698 
 3699     if (ncs_encode_n_octets_in_uba(&uba, (uint8_t *)msg->buf, msg->size) !=
 3700         NCSCC_RC_SUCCESS) {
 3701         LOG_ER("Failed buffer copy");
 3702         error = SA_AIS_ERR_NO_RESOURCES;
 3703         goto unpack_failure;
 3704     }
 3705 
 3706     ncs_dec_init_space(&uba, uba.start);
 3707     uba.bufp = NULL;
 3708 
 3709     /* Decode non flat. */
 3710     if (immsv_evt_dec(&uba, &frwrd_evt) != NCSCC_RC_SUCCESS) {
 3711         LOG_ER("Edu decode Failed");
 3712         error = SA_AIS_ERR_LIBRARY;
 3713         goto unpack_failure;
 3714     }
 3715 
 3716     if (frwrd_evt.type != IMMSV_EVT_TYPE_IMMND) {
 3717         LOG_ER("IMMND - Wrong Event Type: %u", frwrd_evt.type);
 3718         error = SA_AIS_ERR_LIBRARY;
 3719         goto unpack_failure;
 3720     }
 3721 
 3722     switch (frwrd_evt.info.immnd.type) {
 3723 
 3724     case IMMND_EVT_A2ND_OBJ_MODIFY:
 3725         if ((sinfo != NULL) &&
 3726             ((strcmp(frwrd_evt.info.immnd.info.objModify.objectName.buf,
 3727                  OPENSAF_IMM_OBJECT_DN) == 0) ||
 3728              (strcmp(frwrd_evt.info.immnd.info.objModify.objectName.buf,
 3729                  "safRdn=immManagement,safApp=safImmService") ==
 3730               0))) {
 3731             /* Modifications to IMM service objects are only allowed
 3732              * for root users and same group as me. Except for
 3733              * access control settings which are only allowed by
 3734              * root.
 3735              */
 3736             if ((sinfo->uid > 0) && (sinfo->gid != getgid())) {
 3737                 struct passwd *pwd = getpwuid(sinfo->uid);
 3738                 if (pwd != NULL) {
 3739                     syslog(
 3740                         LOG_ALERT | LOG_AUTH,
 3741                         "Modifications to imm service objects denied for %s(uid=%d)",
 3742                         pwd->pw_name, sinfo->uid);
 3743                 }
 3744                 error = SA_AIS_ERR_ACCESS_DENIED;
 3745                 break; /* out of switch */
 3746             } else if (sinfo->uid > 0) {
 3747                 // non root and same group as me, disallow
 3748                 // access control changes
 3749                 bool ac_failed = false;
 3750                 const IMMSV_ATTR_MODS_LIST *attrMod =
 3751                     frwrd_evt.info.immnd.info.objModify
 3752                     .attrMods;
 3753                 while (attrMod != NULL) {
 3754                     if ((strcmp(
 3755                          attrMod->attrValue.attrName
 3756                              .buf,
 3757                          OPENSAF_IMM_ACCESS_CONTROL_MODE) ==
 3758                          0) ||
 3759                         (strcmp(
 3760                          attrMod->attrValue.attrName
 3761                              .buf,
 3762                          OPENSAF_IMM_AUTHORIZED_GROUP) ==
 3763                          0)) {
 3764                         struct passwd *pwd =
 3765                             getpwuid(sinfo->uid);
 3766                         if (pwd != NULL)
 3767                             syslog(
 3768                                 LOG_ALERT | LOG_AUTH,
 3769                                 "change of %s denied for %s(uid=%d)",
 3770                                 attrMod->attrValue
 3771                                 .attrName.buf,
 3772                                 pwd->pw_name,
 3773                                 sinfo->uid);
 3774                         error =
 3775                             SA_AIS_ERR_ACCESS_DENIED;
 3776                         ac_failed = true;
 3777                         break; /* out of while */
 3778                     }
 3779                     attrMod = attrMod->next;
 3780                 }
 3781                 if (ac_failed) {
 3782                     break;
 3783                 } /* out of switch */
 3784             } else
 3785                 ; // modifications by root are OK
 3786         }
 3787     /* intentional fall through. */
 3788     case IMMND_EVT_A2ND_OBJ_CREATE:
 3789     case IMMND_EVT_A2ND_OBJ_DELETE:
 3790     case IMMND_EVT_A2ND_CCB_FINALIZE:
 3791     case IMMND_EVT_A2ND_OI_CCB_AUG_INIT:
 3792     case IMMND_EVT_A2ND_AUG_ADMO:
 3793         if (immModel_pbeNotWritable(cb)) {
 3794             error = SA_AIS_ERR_TRY_AGAIN;
 3795         }
 3796         break;
 3797 
 3798     case IMMND_EVT_A2ND_OBJ_SAFE_READ:
 3799         TRACE(
 3800             "IMMND_EVT_A2ND_OBJ_SAFE_READ noted in fevs_local_checks");
 3801         if (!immModel_protocol50Allowed(cb) ||
 3802             immModel_pbeNotWritable(cb)) {
 3803             error = SA_AIS_ERR_TRY_AGAIN;
 3804         }
 3805         break;
 3806 
 3807     case IMMND_EVT_A2ND_OBJ_CREATE_2:
 3808         if (!immModel_protocol46Allowed(cb) ||
 3809             immModel_pbeNotWritable(cb)) {
 3810             error = SA_AIS_ERR_TRY_AGAIN;
 3811         }
 3812         break;
 3813 
 3814     case IMMND_EVT_A2ND_CCB_VALIDATE:
 3815         if (!immModel_protocol45Allowed(cb)) {
 3816             LOG_NO(
 3817                 "saImmOmCcbValidate rejected during upgrade to 4.5 (OPENSAF_IMM_FLAG_PRT45_ALLOW is false)");
 3818             error = SA_AIS_ERR_NO_RESOURCES;
 3819             break;
 3820         }
 3821     /* intentional fallthrough. */
 3822     case IMMND_EVT_A2ND_CCB_APPLY:
 3823         if (cb->mPbeDisableCritical) {
 3824             LOG_WA(
 3825                 "ERR_TRY_AGAIN: Disable of PBE has been initiated, waiting for the reply from the PBE");
 3826             error = SA_AIS_ERR_TRY_AGAIN;
 3827             break;
 3828         }
 3829         if (immModel_pbeNotWritable(cb) ||
 3830             (cb->fevs_replies_pending >= cb->mFevsMaxPending) ||
 3831             !immnd_is_immd_up(cb)) {
 3832             /* NO_RESOURCES is here imm internal proxy for
 3833                TRY_AGAIN. The library code for saImmOmCcbApply will
 3834                translate NO_RESOURCES to TRY_AGAIN towards the user.
 3835                That library code (for ccbApply) treats TRY_AGAIN
 3836                from IMMND as an indication of handle resurrect. So
 3837                we need to take this detour to really communicate
 3838                TRY_AGAIN towards that particular library code.
 3839              */
 3840             error = SA_AIS_ERR_NO_RESOURCES;
 3841             if (cb->fevs_replies_pending >= cb->mFevsMaxPending) {
 3842                 TRACE_2(
 3843                     "ERR_TRY_AGAIN: Too many pending FEVS message replies (> %u) rejecting request"
 3844                     "for CcbApply",
 3845                     cb->mFevsMaxPending);
 3846             }
 3847         }
 3848         break;
 3849 
 3850     case IMMND_EVT_A2ND_OBJ_SYNC:
 3851     case IMMND_EVT_A2ND_OBJ_SYNC_2:
 3852         if (fevsReq->sender_count != 0x0) {
 3853             LOG_WA(
 3854                 "ERR_LIBRARY: IMMND_EVT_A2ND_OBJ_SYNC fevsReq->sender_count != 0x0");
 3855             error = SA_AIS_ERR_LIBRARY;
 3856         }
 3857 
 3858         if (!(cl_node->mIsSync)) {
 3859             LOG_WA(
 3860                 "ERR_LIBRARY: IMMND_EVT_A2ND_OBJ_SYNC can only arrive from sync client");
 3861             error = SA_AIS_ERR_LIBRARY;
 3862         }
 3863         break;
 3864 
 3865     case IMMND_EVT_A2ND_IMM_ADMOP:
 3866     case IMMND_EVT_A2ND_IMM_ADMOP_ASYNC:
 3867     {
 3868         IMMSV_OM_ADMIN_OP_INVOKE *adm = &frwrd_evt.info.immnd.info.admOpReq;
 3869         bool fs_op = (adm->operationId == SA_IMM_ADMIN_FS_AVAILABLE ||
 3870                   adm->operationId == SA_IMM_ADMIN_FS_UNAVAILABLE);
 3871         if (!immModel_protocol51906Allowed(cb) && fs_op &&
 3872             strcmp(adm->objectName.buf,
 3873             "safRdn=immManagement,safApp=safImmService") == 0) {
 3874             error = SA_AIS_ERR_TRY_AGAIN;
 3875         }
 3876         break;
 3877     }
 3878 
 3879     case IMMND_EVT_A2ND_CLASS_CREATE:
 3880         if (fevsReq->sender_count != 0x1) {
 3881             LOG_WA(
 3882                 "ERR_LIBRARY: IMMND_EVT_A2ND_CLASS_CREATE fevsReq->sender_count != 0x1");
 3883             error = SA_AIS_ERR_LIBRARY;
 3884         } else if (!(cl_node->mIsSync) &&
 3885                (immModel_immNotWritable(cb) ||
 3886                 cb->mSyncFinalizing)) {
 3887             /* Regular class create attempted during sync. */
 3888             error = SA_AIS_ERR_TRY_AGAIN;
 3889         }
 3890         if (!immModel_protocol47Allowed(cb) &&
 3891             !immModel_readyForLoading(cb)) {
 3892             /* IMM supports creating classes with unknown flags.
 3893              * When the upgrade process is not completed, a
 3894              * class-create request (with DEFAULT_REMOVED flag) may
 3895              * be accepted on nodes with old version and rejected on
 3896              * nodes with new version. This check will prevent the
 3897              * inconsistency between nodes. */
 3898             IMMSV_ATTR_DEF_LIST *list =
 3899                 frwrd_evt.info.immnd.info.classDescr
 3900                 .attrDefinitions;
 3901             while (list) {
 3902                 if (list->d.attrFlags &
 3903                     SA_IMM_ATTR_DEFAULT_REMOVED) {
 3904                     LOG_WA(
 3905                         "ERR_TRY_AGAIN: Can not create class with SA_IMM_ATTR_DEFAULT_REMOVED "
 3906                         "when proto47 is not enabled");
 3907                     error = SA_AIS_ERR_TRY_AGAIN;
 3908                     break; /* while */
 3909                 }
 3910                 list = list->next;
 3911             }
 3912         }
 3913         if (!immModel_protocol50Allowed(cb)) {
 3914             IMMSV_ATTR_DEF_LIST *list =
 3915                 frwrd_evt.info.immnd.info.classDescr
 3916                 .attrDefinitions;
 3917             while (list) {
 3918                 if (list->d.attrFlags &
 3919                     SA_IMM_ATTR_STRONG_DEFAULT) {
 3920                     LOG_WA(
 3921                         "ERR_TRY_AGAIN: Can not create class with SA_IMM_ATTR_STRONG_DEFAULT "
 3922                         "when proto50 is not enabled");
 3923                     error = SA_AIS_ERR_TRY_AGAIN;
 3924                     break; /* while */
 3925                 }
 3926                 list = list->next;
 3927             }
 3928         }
 3929 
 3930         char *class_name =
 3931             frwrd_evt.info.immnd.info.classDescr.className.buf;
 3932         if (is_class_name_reserved(cb, class_name)) {
 3933             error = SA_AIS_ERR_INVALID_PARAM;
 3934         }
 3935 
 3936         break;
 3937 
 3938     case IMMND_EVT_A2ND_CLASS_DELETE:
 3939         if (fevsReq->sender_count != 0x1) {
 3940             LOG_WA(
 3941                 "ERR_LIBRARY: IMMND_EVT_A2ND_CLASS_DELETE fevsReq->sender_count != 0x1");
 3942             error = SA_AIS_ERR_LIBRARY;
 3943         } else if (immModel_immNotWritable(cb) || cb->mSyncFinalizing) {
 3944             error = SA_AIS_ERR_TRY_AGAIN;
 3945         }
 3946 
 3947         break;
 3948 
 3949     case IMMND_EVT_D2ND_DISCARD_IMPL:
 3950         LOG_WA(
 3951             "ERR_LIBRARY: IMMND_EVT_D2ND_DISCARD_IMPL can not arrive from client lib");
 3952         error = SA_AIS_ERR_LIBRARY;
 3953         break;
 3954 
 3955     case IMMND_EVT_D2ND_DISCARD_NODE:
 3956         LOG_WA(
 3957             "ERR_LIBRARY: IMMND_EVT_D2ND_DISCARD_NODE can not arrive from client lib");
 3958         error = SA_AIS_ERR_LIBRARY;
 3959         break;
 3960 
 3961     case IMMND_EVT_D2ND_ADMINIT:
 3962         LOG_WA(
 3963             "ERR_LIBRARY: IMMND_EVT_D2ND_ADMINIT can not arrive from client lib");
 3964         error = SA_AIS_ERR_LIBRARY;
 3965         break;
 3966 
 3967     case IMMND_EVT_D2ND_IMPLSET_RSP:
 3968         LOG_WA(
 3969             "ERR_LIBRARY: IMMND_EVT_D2ND_IMPLSET_RSP can not arrive from client lib");
 3970         error = SA_AIS_ERR_LIBRARY;
 3971         break;
 3972 
 3973     case IMMND_EVT_D2ND_IMPLSET_RSP_2:
 3974         LOG_WA(
 3975             "ERR_LIBRARY: IMMND_EVT_D2ND_IMPLSET_RSP_2 can not arrive from client lib");
 3976         error = SA_AIS_ERR_LIBRARY;
 3977         break;
 3978 
 3979     case IMMND_EVT_D2ND_CCBINIT:
 3980         LOG_WA(
 3981             "ERR_LIBRARY: IMMND_EVT_D2ND_CCBINIT can not arrive from client lib");
 3982         error = SA_AIS_ERR_LIBRARY;
 3983         break;
 3984 
 3985     case IMMND_EVT_D2ND_ABORT_CCB:
 3986         LOG_WA(
 3987             "ERR_LIBRARY: IMMND_EVT_D2ND_ABORT_CCB can not arrive from client lib");
 3988         error = SA_AIS_ERR_LIBRARY;
 3989         break;
 3990 
 3991     case IMMND_EVT_A2ND_OI_CL_IMPL_SET:
 3992 
 3993         if (fevsReq->sender_count != 0x1) {
 3994             LOG_WA(
 3995                 "ERR_LIBRARY: IMMND_EVT_A2ND_OI_CL_IMPL_SET fevsReq->sender_count != 0x1");
 3996             error = SA_AIS_ERR_LIBRARY;
 3997         } else if (immModel_immNotWritable(cb)) { // sync is on-going
 3998             SaUint32T ccbId = 0;
 3999             error = immModel_classImplementerSet(
 4000                 cb, &(frwrd_evt.info.immnd.info.implSet), conn,
 4001                 nodeId, &ccbId);
 4002             osafassert(error != SA_AIS_OK); /* OK is impossible
 4003                                since we are not
 4004                                writable */
 4005             if (error == SA_AIS_ERR_NO_BINDINGS) {
 4006                 TRACE(
 4007                     "idempotent classImplementerSet locally detected, impl_id:%u",
 4008                     frwrd_evt.info.immnd.info.implSet.impl_id);
 4009                 osafassert(!ccbId);
 4010             } else if (error == SA_AIS_ERR_TRY_AGAIN && ccbId) {
 4011                 /* Yes there can be an active non critical ccb
 4012                    even though imsmv is not writable. A sync
 4013                    could be just starting and still waiting for
 4014                    ccbs to terminate (period of grace). Here we
 4015                    turn ungracefull on this ccb to give
 4016                    class-implementer-set priority over the ccb
 4017                    doing un-protected (un-validated) changes to
 4018                    instances of the class.
 4019                 */
 4020                 immnd_proc_global_abort_ccb(cb, ccbId);
 4021             }
 4022         } else if (cb->mSyncFinalizing) {
 4023             // Writable, but sync is finalizing at coord.
 4024             error = SA_AIS_ERR_TRY_AGAIN;
 4025         }
 4026         /* Else when imm is writable, idempotency can not be trusted
 4027            locally. OK will be returned, which will trigger forwarding
 4028            over fevs. */
 4029 
 4030         break;
 4031 
 4032     case IMMND_EVT_A2ND_OI_OBJ_IMPL_SET:
 4033 
 4034         if (fevsReq->sender_count != 0x1) {
 4035             LOG_WA(
 4036                 "ERR_LIBRARY: IMMND_EVT_A2ND_OI_OBJ_IMPL_SET fevsReq->sender_count != 0x1");
 4037             error = SA_AIS_ERR_LIBRARY;
 4038         } else if (immModel_immNotWritable(cb)) { // sync is on-going
 4039             SaUint32T ccbId = 0;
 4040             error = immModel_objectImplementerSet(
 4041                 cb, &(frwrd_evt.info.immnd.info.implSet), conn,
 4042                 nodeId, &ccbId);
 4043             osafassert(error != SA_AIS_OK); /* OK is impossible
 4044                                since we are not
 4045                                writable */
 4046             if (error == SA_AIS_ERR_NO_BINDINGS) {
 4047                 TRACE(
 4048                     "idempotent objectImplementerSet locally detected, impl_id:%u",
 4049                     frwrd_evt.info.immnd.info.implSet.impl_id);
 4050                 osafassert(!ccbId);
 4051             } else if (error == SA_AIS_ERR_TRY_AGAIN && ccbId) {
 4052                 /* Yes there can be an active non critical ccb
 4053                    even though imsmv is not writable. A sync
 4054                    could be just starting and still waiting for
 4055                    ccbs to terminate (period of grace). Here we
 4056                    turn ungracefull on this ccb to give
 4057                    object-implementer-set priority over the ccb
 4058                    doing un-protected (un-validated) changes to
 4059                    this object.
 4060                 */
 4061                 immnd_proc_global_abort_ccb(cb, ccbId);
 4062             }
 4063         } else if (cb->mSyncFinalizing) {
 4064             // Writable, but sync is finalizing at coord.
 4065             error = SA_AIS_ERR_TRY_AGAIN;
 4066         }
 4067         /* Else when imm is writable, idempotency can not be trusted
 4068            locally. OK will be returned, which will trigger forwarding
 4069            over fevs. */
 4070         break;
 4071 
 4072     case IMMND_EVT_A2ND_OI_IMPL_CLR:
 4073         if (fevsReq->sender_count != 0x0) {
 4074             LOG_WA(
 4075                 "ERR_LIBRARY: IMMND_EVT_A2ND_OI_IMPL_CLR fevsReq->sender_count != 0x0");
 4076             error = SA_AIS_ERR_LIBRARY;
 4077         }
 4078         break;
 4079 
 4080     case IMMND_EVT_A2ND_OI_CL_IMPL_REL:
 4081         if (fevsReq->sender_count != 0x1) {
 4082             LOG_WA(
 4083                 "ERR_LIBRARY: IMMND_EVT_A2ND_OI_CL_IMPL_REL fevsReq->sender_count != 0x1");
 4084             error = SA_AIS_ERR_LIBRARY;
 4085         }
 4086         break;
 4087 
 4088     case IMMND_EVT_A2ND_OI_OBJ_IMPL_REL:
 4089         if (fevsReq->sender_count != 0x1) {
 4090             LOG_WA(
 4091                 "ERR_LIBRARY: IMMND_EVT_A2ND_OI_OBJ_IMPL_REL fevsReq->sender_count != 0x1");
 4092             error = SA_AIS_ERR_LIBRARY;
 4093         }
 4094         break;
 4095 
 4096     case IMMND_EVT_A2ND_OI_OBJ_CREATE:
 4097         if (fevsReq->sender_count != 0x1) {
 4098             LOG_WA(
 4099                 "ERR_LIBRARY: IMMND_EVT_A2ND_OI_OBJ_CREATE fevsReq->sender_count != 0x1");
 4100             error = SA_AIS_ERR_LIBRARY;
 4101         }
 4102         break;
 4103 
 4104     case IMMND_EVT_A2ND_OI_OBJ_CREATE_2:
 4105         if (!immModel_protocol46Allowed(cb)) {
 4106             error = SA_AIS_ERR_TRY_AGAIN;
 4107         } else if (fevsReq->sender_count != 0x1) {
 4108             LOG_WA(
 4109                 "ERR_LIBRARY: IMMND_EVT_A2ND_OI_OBJ_CREATE_2 fevsReq->sender_count != 0x1");
 4110             error = SA_AIS_ERR_LIBRARY;
 4111         }
 4112         break;
 4113 
 4114     case IMMND_EVT_A2ND_OI_OBJ_MODIFY:
 4115         /* rtObjectUpdate is not encoded by imma client as fevs. */
 4116         LOG_WA(
 4117             "ERR_LIBRARY: IMMND_EVT_A2ND_OI_OBJ_MODIFY can not arrive from client as fevs");
 4118         error = SA_AIS_ERR_LIBRARY;
 4119         break;
 4120 
 4121     case IMMND_EVT_A2ND_OI_OBJ_DELETE:
 4122         if (fevsReq->sender_count != 0x1) {
 4123             LOG_WA(
 4124                 "ERR_LIBRARY: IMMND_EVT_A2ND_OI_OBJ_DELETE fevsReq->sender_count != 0x1");
 4125             error = SA_AIS_ERR_LIBRARY;
 4126         }
 4127         break;
 4128 
 4129     case IMMND_EVT_D2ND_ADMO_HARD_FINALIZE:
 4130         LOG_WA(
 4131             "ERR_LIBRARY: IMMND_EVT_D2ND_ADMO_HARD_FIMNALIZE can not arrive from client lib");
 4132         error = SA_AIS_ERR_LIBRARY;
 4133         break;
 4134 
 4135     case IMMND_EVT_A2ND_ADMO_CLEAR:
 4136         if ((immModel_accessControlMode(cb) ==
 4137              ACCESS_CONTROL_ENFORCING)) {
 4138             /*
 4139               The om API downcall 'saImmOmAdminOwnerClear(...)' is
 4140               special in that it forces the removal of
 4141               adminownership set up by some other user/handle. It is
 4142               only needed to 'clean up' after an application has
 4143               terminated without releaseing admin-owner and with
 4144               releaseOnFinalize set to false. Because of the very
 4145               special and powerful nature of this operation, only
 4146               root users should be allowed to use it, when acces
 4147               control is enabled.
 4148             */
 4149             if ((sinfo != NULL) && (sinfo->uid > 0)) {
 4150                 struct passwd *pwd = getpwuid(sinfo->uid);
 4151                 if (pwd != NULL) {
 4152                     syslog(
 4153                         LOG_ALERT | LOG_AUTH,
 4154                         "saImmOmAdminOwnerClear denied for %s(uid=%d)",
 4155                         pwd->pw_name, sinfo->uid);
 4156                 }
 4157                 error = SA_AIS_ERR_ACCESS_DENIED;
 4158                 break;
 4159             }
 4160         }
 4161     /* intentional fall through. */
 4162     case IMMND_EVT_A2ND_ADMO_SET:
 4163     case IMMND_EVT_A2ND_ADMO_RELEASE:
 4164         if (fevsReq->sender_count != 0x1) {
 4165             LOG_WA(
 4166                 "ERR_LIBRARY: IMMND_EVT_A2ND_ADMO_XXX(%u) fevsReq->sender_count != 0x1",
 4167                 frwrd_evt.info.immnd.type);
 4168             error = SA_AIS_ERR_LIBRARY;
 4169             break;
 4170         }
 4171     /* Intentional fall through. */
 4172 
 4173     case IMMND_EVT_A2ND_ADMO_FINALIZE:
 4174         if (immModel_immNotWritable(cb) || cb->mSyncFinalizing) {
 4175             TRACE("PRECHECK ADMO_FINALIZE->TRY_AGAIN");
 4176             error = SA_AIS_ERR_TRY_AGAIN;
 4177         }
 4178 
 4179         if (isLoading && (error == SA_AIS_OK)) {
 4180             IMMSV_EVT send_evt;
 4181             memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 4182 
 4183             send_evt.type = IMMSV_EVT_TYPE_IMMD;
 4184             send_evt.info.immd.type =
 4185                 IMMD_EVT_ND2D_LOADING_COMPLETED;
 4186             send_evt.info.immd.info.ctrl_msg.ndExecPid = cb->mMyPid;
 4187             send_evt.info.immd.info.ctrl_msg.epoch = cb->mMyEpoch;
 4188             send_evt.info.immd.info.ctrl_msg
 4189                 .pbeEnabled = /*see immsv_d2nd_control in
 4190                          immsv_ev.h*/
 4191                 (cb->mPbeFile)
 4192                 ? ((cb->mRim == SA_IMM_KEEP_REPOSITORY) ? 4 : 3)
 4193                 : 2;
 4194 
 4195             error =
 4196                 immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMD,
 4197                            cb->immd_mdest_id, &send_evt);
 4198 
 4199             if (error != NCSCC_RC_SUCCESS) {
 4200                 LOG_ER(
 4201                     "Coord failed to send 'loading completed' message to IMMD");
 4202                 error = SA_AIS_ERR_LIBRARY;
 4203             }
 4204         }
 4205 
 4206         break;
 4207 
 4208     case IMMND_EVT_ND2ND_SYNC_FINALIZE:
 4209         if (!(cl_node->mIsSync)) {
 4210             LOG_WA(
 4211                 "ERR_LIBRARY: IMMND_EVT_ND2ND_SYNC_FINALIZE can only arrive from sync client");
 4212             error = SA_AIS_ERR_LIBRARY;
 4213         }
 4214         break;
 4215 
 4216     case IMMND_EVT_ND2ND_SYNC_FINALIZE_2:
 4217         if (!(cl_node->mIsSync)) {
 4218             LOG_WA(
 4219                 "ERR_LIBRARY: IMMND_EVT_ND2ND_SYNC_FINALIZE_2 can not arrive from client lib");
 4220             error = SA_AIS_ERR_LIBRARY;
 4221         }
 4222         break;
 4223 
 4224     case IMMND_EVT_A2ND_CCB_COMPLETED_RSP:
 4225     case IMMND_EVT_A2ND_CCB_COMPLETED_RSP_2:
 4226     case IMMND_EVT_A2ND_PBE_PRTO_DELETES_COMPLETED_RSP:
 4227     case IMMND_EVT_A2ND_CCB_OBJ_CREATE_RSP:
 4228     case IMMND_EVT_A2ND_CCB_OBJ_CREATE_RSP_2:
 4229     case IMMND_EVT_A2ND_PBE_PRT_OBJ_CREATE_RSP:
 4230     case IMMND_EVT_A2ND_CCB_OBJ_MODIFY_RSP:
 4231     case IMMND_EVT_A2ND_CCB_OBJ_MODIFY_RSP_2:
 4232     case IMMND_EVT_A2ND_PBE_PRT_ATTR_UPDATE_RSP:
 4233     case IMMND_EVT_A2ND_CCB_OBJ_DELETE_RSP:
 4234     case IMMND_EVT_A2ND_CCB_OBJ_DELETE_RSP_2:
 4235         if (fevsReq->sender_count != 0x0) {
 4236             LOG_WA(
 4237                 "ERR_LIBRARY:  fevsReq->sender_count != 0x0 for OI response type:%u",
 4238                 frwrd_evt.info.immnd.type);
 4239             error = SA_AIS_ERR_LIBRARY;
 4240         }
 4241         break;
 4242 
 4243     case IMMND_EVT_A2ND_PBE_ADMOP_RSP:
 4244         if (fevsReq->sender_count != 0x0) {
 4245             LOG_WA(
 4246                 "ERR_LIBRARY: IMMND_EVT_A2ND_PBE_ADMOP_RSP fevsReq->sender_count != 0x0");
 4247             error = SA_AIS_ERR_LIBRARY;
 4248         }
 4249         break;
 4250 
 4251     case IMMND_EVT_D2ND_SYNC_FEVS_BASE:
 4252         LOG_WA(
 4253             "ERR_LIBRARY: IMMND_EVT_D2ND_SYNC_FEVS_BASE can not arrive from client lib");
 4254         error = SA_AIS_ERR_LIBRARY;
 4255         break;
 4256 
 4257     default:
 4258         LOG_ER(
 4259             "UNPACK FAILURE, unrecognized message type: %u caught in fevs_local_checks",
 4260             frwrd_evt.info.immnd.type);
 4261         error = SA_AIS_ERR_LIBRARY;
 4262         break;
 4263     }
 4264 
 4265 unpack_failure:
 4266 
 4267     if (uba.start) {
 4268         m_MMGR_FREE_BUFR_LIST(uba.start);
 4269     }
 4270 
 4271     if ((error != SA_AIS_OK) && (error != SA_AIS_ERR_NO_BINDINGS) &&
 4272         (error != SA_AIS_ERR_TRY_AGAIN)) {
 4273         LOG_NO(
 4274             "Precheck of fevs message of type <%u> failed with ERROR:%u",
 4275             frwrd_evt.info.immnd.type, error);
 4276     }
 4277 
 4278     immnd_evt_destroy(&frwrd_evt, false, __LINE__);
 4279 
 4280 client_down:
 4281 
 4282     TRACE_LEAVE();
 4283     return error;
 4284 }
 4285 
 4286 /****************************************************************************
 4287  * Name          : immnd_evt_proc_ccb_obj_modify_rsp
 4288  *
 4289  * Description   : Function to process the reply from the
 4290  *                 SaImmOiCcbObjectModifyCallbackT upcall.
 4291  *                 Note this call arrived over fevs, to ALL IMMNDs.
 4292  *                 This is because ALL must receive ACK/NACK from EACH
 4293  *                 implementer.
 4294  *
 4295  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 4296  *                 IMMSV_EVT *evt - Received Event structure
 4297  *
 4298  * Return Values : None.
 4299  *
 4300  *****************************************************************************/
 4301 static void immnd_evt_proc_ccb_obj_modify_rsp(IMMND_CB *cb, IMMND_EVT *evt,
 4302                           bool originatedAtThisNd,
 4303                           SaImmHandleT clnt_hdl,
 4304                           MDS_DEST reply_dest)
 4305 {
 4306     uint32_t rc = NCSCC_RC_SUCCESS;
 4307     IMMSV_EVT send_evt;
 4308     SaUint32T reqConn = 0;
 4309     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 4310     TRACE_ENTER();
 4311 
 4312     immModel_ccbObjModifyContinuation(
 4313         cb, evt->info.ccbUpcallRsp.ccbId, evt->info.ccbUpcallRsp.inv,
 4314         evt->info.ccbUpcallRsp.result, &reqConn);
 4315 
 4316     if (reqConn) {
 4317         SaImmHandleT tmp_hdl =
 4318             m_IMMSV_PACK_HANDLE(reqConn, cb->node_id);
 4319 
 4320         immnd_client_node_get(cb, tmp_hdl, &cl_node);
 4321         if (cl_node == NULL || cl_node->mIsStale) {
 4322             LOG_WA("IMMND - Client went down so no response");
 4323             TRACE_LEAVE();
 4324             return; /*Note, this means that regardles of ccb
 4325                    outcome, we can not reply to the process that
 4326                    started the ccb. */
 4327         }
 4328 
 4329         TRACE_2("SENDRSP %u", evt->info.ccbUpcallRsp.result);
 4330 
 4331         memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 4332         send_evt.type = IMMSV_EVT_TYPE_IMMA;
 4333         send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 4334         IMMSV_ATTR_NAME_LIST strList;
 4335         IMMSV_ATTR_NAME_LIST *errStrList = immModel_ccbGrabErrStrings(
 4336             cb, evt->info.ccbUpcallRsp.ccbId);
 4337 
 4338         if (evt->info.ccbUpcallRsp.result != SA_AIS_OK) {
 4339             evt->info.ccbUpcallRsp.result =
 4340                 SA_AIS_ERR_FAILED_OPERATION;
 4341 
 4342             if (evt->info.ccbUpcallRsp.errorString.size) {
 4343                 osafassert(evt->type ==
 4344                        IMMND_EVT_A2ND_CCB_OBJ_MODIFY_RSP_2);
 4345 
 4346                 strList.next = errStrList;
 4347                 strList.name = evt->info.ccbUpcallRsp
 4348                            .errorString; /*borrow*/
 4349                 send_evt.info.imma.info.errRsp.errStrings =
 4350                     &(strList);
 4351                 send_evt.info.imma.type =
 4352                     IMMA_EVT_ND2A_IMM_ERROR_2;
 4353             } else if (errStrList) {
 4354                 osafassert(evt->type ==
 4355                        IMMND_EVT_A2ND_CCB_OBJ_MODIFY_RSP);
 4356                 send_evt.info.imma.info.errRsp.errStrings =
 4357                     errStrList;
 4358                 send_evt.info.imma.type =
 4359                     IMMA_EVT_ND2A_IMM_ERROR_2;
 4360             }
 4361         }
 4362 
 4363         /* Dont move this line up. Error return code may have been
 4364          * adjusted above.*/
 4365         send_evt.info.imma.info.errRsp.error =
 4366             evt->info.ccbUpcallRsp.result;
 4367 
 4368         rc = immnd_mds_send_rsp(cb, &(cl_node->tmpSinfo), &send_evt);
 4369         if (rc != NCSCC_RC_SUCCESS) {
 4370             LOG_WA(
 4371                 "Failed to send response to agent/client over MDS rc:%u",
 4372                 rc);
 4373         }
 4374 
 4375         immsv_evt_free_attrNames(errStrList);
 4376     }
 4377 
 4378     TRACE_LEAVE();
 4379 }
 4380 
 4381 /****************************************************************************
 4382  * Name          : immnd_evt_proc_ccb_obj_create_rsp
 4383  *
 4384  * Description   : Function to process the reply from the
 4385  *                 SaImmOiCcbObjectCreateCallbackT upcall.
 4386  *                 Note this call arrived over fevs, to ALL IMMNDs.
 4387  *                 This is because ALL must receive ACK/NACK from EACH
 4388  *                 implementer.
 4389  *
 4390  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 4391  *                 IMMSV_EVT *evt - Received Event structure
 4392  *
 4393  * Return Values : None.
 4394  *
 4395  *****************************************************************************/
 4396 static void immnd_evt_proc_ccb_obj_create_rsp(IMMND_CB *cb, IMMND_EVT *evt,
 4397                           bool originatedAtThisNd,
 4398                           SaImmHandleT clnt_hdl,
 4399                           MDS_DEST reply_dest)
 4400 {
 4401     uint32_t rc = NCSCC_RC_SUCCESS;
 4402     IMMSV_EVT send_evt;
 4403     SaUint32T reqConn = 0;
 4404     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 4405     TRACE_ENTER();
 4406 
 4407     immModel_ccbObjCreateContinuation(
 4408         cb, evt->info.ccbUpcallRsp.ccbId, evt->info.ccbUpcallRsp.inv,
 4409         evt->info.ccbUpcallRsp.result, &reqConn);
 4410 
 4411     if (reqConn) {
 4412         SaImmHandleT tmp_hdl =
 4413             m_IMMSV_PACK_HANDLE(reqConn, cb->node_id);
 4414 
 4415         immnd_client_node_get(cb, tmp_hdl, &cl_node);
 4416         if (cl_node == NULL || cl_node->mIsStale) {
 4417             LOG_WA("IMMND - Client went down so no response");
 4418             TRACE_LEAVE();
 4419             return; /*Note, this means that regardles of ccb
 4420                    outcome, we can not reply to the process that
 4421                    started the ccb. */
 4422         }
 4423 
 4424         TRACE_2("SENDRSP %u", evt->info.ccbUpcallRsp.result);
 4425 
 4426         memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 4427         send_evt.type = IMMSV_EVT_TYPE_IMMA;
 4428         send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 4429         IMMSV_ATTR_NAME_LIST strList;
 4430         IMMSV_ATTR_NAME_LIST *errStrList = immModel_ccbGrabErrStrings(
 4431             cb, evt->info.ccbUpcallRsp.ccbId);
 4432 
 4433         if (evt->info.ccbUpcallRsp.result != SA_AIS_OK) {
 4434             evt->info.ccbUpcallRsp.result =
 4435                 SA_AIS_ERR_FAILED_OPERATION;
 4436 
 4437             if (evt->info.ccbUpcallRsp.errorString.size) {
 4438                 osafassert(evt->type ==
 4439                        IMMND_EVT_A2ND_CCB_OBJ_CREATE_RSP_2);
 4440 
 4441                 strList.next = errStrList;
 4442                 strList.name = evt->info.ccbUpcallRsp
 4443                            .errorString; /*borrow*/
 4444                 send_evt.info.imma.info.errRsp.errStrings =
 4445                     &(strList);
 4446                 send_evt.info.imma.type =
 4447                     IMMA_EVT_ND2A_IMM_ERROR_2;
 4448             } else if (errStrList) {
 4449                 osafassert(evt->type ==
 4450                        IMMND_EVT_A2ND_CCB_OBJ_CREATE_RSP);
 4451                 send_evt.info.imma.info.errRsp.errStrings =
 4452                     errStrList;
 4453                 send_evt.info.imma.type =
 4454                     IMMA_EVT_ND2A_IMM_ERROR_2;
 4455             }
 4456         }
 4457 
 4458         /* Dont move this line up. Error return code may have been
 4459          * adjusted above.*/
 4460         send_evt.info.imma.info.errRsp.error =
 4461             evt->info.ccbUpcallRsp.result;
 4462 
 4463         rc = immnd_mds_send_rsp(cb, &(cl_node->tmpSinfo), &send_evt);
 4464         if (rc != NCSCC_RC_SUCCESS) {
 4465             LOG_WA(
 4466                 "Failed to send response to agent/client over MDS rc:%u",
 4467                 rc);
 4468         }
 4469 
 4470         immsv_evt_free_attrNames(errStrList);
 4471     }
 4472 
 4473     TRACE_LEAVE();
 4474 }
 4475 
 4476 /****************************************************************************
 4477  * Name          : immnd_evt_proc_ccb_obj_delete_rsp
 4478  *
 4479  * Description   : Function to process the reply from the
 4480  *                 SaImmOiCcbObjectDeleteCallbackT upcall.
 4481  *                 Note this call arrived over fevs, to ALL IMMNDs.
 4482  *                 This is because ALL must receive ACK/NACK from EACH
 4483  *                 implementer.
 4484  *
 4485  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 4486  *                 IMMSV_EVT *evt - Received Event structure
 4487  *
 4488  * Return Values : None.
 4489  *
 4490  *****************************************************************************/
 4491 static void immnd_evt_proc_ccb_obj_delete_rsp(IMMND_CB *cb, IMMND_EVT *evt,
 4492                           bool originatedAtThisNd,
 4493                           SaImmHandleT clnt_hdl,
 4494                           MDS_DEST reply_dest)
 4495 {
 4496     uint32_t rc = NCSCC_RC_SUCCESS;
 4497     IMMSV_EVT send_evt;
 4498     SaUint32T reqConn = 0;
 4499     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 4500     bool augDelete = false;
 4501     TRACE_ENTER();
 4502 
 4503     immModel_ccbObjDelContinuation(cb, &(evt->info.ccbUpcallRsp), &reqConn,
 4504                        &augDelete);
 4505 
 4506     SaAisErrorT err = SA_AIS_OK;
 4507 
 4508     if (!immModel_ccbWaitForDeleteImplAck(cb, evt->info.ccbUpcallRsp.ccbId,
 4509                           &err, augDelete) &&
 4510         reqConn) {
 4511         SaImmHandleT tmp_hdl =
 4512             m_IMMSV_PACK_HANDLE(reqConn, cb->node_id);
 4513 
 4514         immnd_client_node_get(cb, tmp_hdl, &cl_node);
 4515         if (cl_node == NULL || cl_node->mIsStale) {
 4516             LOG_WA("IMMND - Client went down so no response");
 4517             TRACE_LEAVE();
 4518             return; /*Note, this means that regardles of ccb
 4519                    outcome, we can not reply to the process that
 4520                    started the ccb. */
 4521         }
 4522 
 4523         TRACE_2("SENDRSP %u", evt->info.ccbUpcallRsp.result);
 4524 
 4525         memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 4526         send_evt.type = IMMSV_EVT_TYPE_IMMA;
 4527         send_evt.info.imma.info.errRsp.error = err;
 4528         send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 4529         if (err != SA_AIS_OK) {
 4530             send_evt.info.imma.info.errRsp.errStrings =
 4531                 immModel_ccbGrabErrStrings(
 4532                 cb, evt->info.ccbUpcallRsp.ccbId);
 4533 
 4534             if (send_evt.info.imma.info.errRsp.errStrings) {
 4535                 send_evt.info.imma.type =
 4536                     IMMA_EVT_ND2A_IMM_ERROR_2;
 4537             }
 4538         }
 4539 
 4540         rc = immnd_mds_send_rsp(cb, &(cl_node->tmpSinfo), &send_evt);
 4541         if (rc != NCSCC_RC_SUCCESS) {
 4542             LOG_WA(
 4543                 "Failed to send response to agent/client over MDS rc:%u",
 4544                 rc);
 4545         }
 4546         immsv_evt_free_attrNames(
 4547             send_evt.info.imma.info.errRsp.errStrings);
 4548     }
 4549 
 4550     TRACE_LEAVE();
 4551 }
 4552 
 4553 /****************************************************************************
 4554  * Name          : immnd_evt_proc_ccb_compl_rsp
 4555  *
 4556  * Description   : Function to process the reply from the
 4557  *                 SaImmOiCcbCompletedCallbackT upcall.
 4558  *                 Note this call arrived over fevs, to ALL IMMNDs.
 4559  *                 This is because ALL must receive ACK/NACK from EACH
 4560  *                 implementer.
 4561  *
 4562  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 4563  *                 IMMSV_EVT *evt - Received Event structure
 4564  *
 4565  * Return Values : None.
 4566  *
 4567  *****************************************************************************/
 4568 static void immnd_evt_proc_ccb_compl_rsp(IMMND_CB *cb, IMMND_EVT *evt,
 4569                      bool originatedAtThisNd,
 4570                      SaImmHandleT clnt_hdl,
 4571                      MDS_DEST reply_dest)
 4572 {
 4573     uint32_t rc = NCSCC_RC_SUCCESS;
 4574     IMMSV_EVT send_evt;
 4575     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 4576     IMMND_IMM_CLIENT_NODE *oi_cl_node = NULL;
 4577     SaAisErrorT err = SA_AIS_OK;
 4578     SaUint32T reqConn = 0;
 4579     SaUint32T pbeConn = 0;
 4580     NCS_NODE_ID pbeNodeId = 0;
 4581     NCS_NODE_ID *pbeNodeIdPtr = NULL; /* Defaults to NULL for no PBE. */
 4582     SaUint32T pbeId = 0;
 4583     SaUint32T pbeCtn = 0;
 4584     IMMSV_ATTR_NAME_LIST *errStrings = NULL;
 4585     TRACE_ENTER();
 4586 
 4587     immModel_ccbCompletedContinuation(cb, &(evt->info.ccbUpcallRsp),
 4588                       &reqConn);
 4589     if (cb->mPbeFile && (cb->mRim == SA_IMM_KEEP_REPOSITORY)) {
 4590         pbeNodeIdPtr = &pbeNodeId;
 4591 
 4592         /* If pbeNodeIdPtr is NULL then ccbWaitForCompletedAck skips the
 4593            lookup of the pbe implementer and does not make us wait for
 4594            it.
 4595          */
 4596     }
 4597     if (immModel_ccbWaitForCompletedAck(cb, evt->info.ccbUpcallRsp.ccbId,
 4598                         &err, &pbeConn, pbeNodeIdPtr,
 4599                         &pbeId, &pbeCtn)) {
 4600         /* We still need to wait for some implementer replies, possibly
 4601          * also the PBE.*/
 4602         if (pbeNodeId) {
 4603             /* There is be a PBE. */
 4604             osafassert(err ==
 4605                    SA_AIS_OK); /* If not OK then we should not
 4606                           have arrived here. */
 4607             TRACE_5("Wait for PBE commit decision for ccb %u",
 4608                 evt->info.ccbUpcallRsp.ccbId);
 4609             if (pbeConn) {
 4610                 TRACE_5(
 4611                     "PBE is LOCAL - send completed upcall for %u",
 4612                     evt->info.ccbUpcallRsp.ccbId);
 4613                 /* The PBE is connected at THIS node. Make the
 4614                    completed upcall. If the PBE decides to
 4615                    commit it does so immediately. It does not
 4616                    wait for the apply upcall.
 4617                  */
 4618                 SaImmOiHandleT implHandle =
 4619                     m_IMMSV_PACK_HANDLE(pbeConn, pbeNodeId);
 4620                 /*Fetch client node for OI ! */
 4621                 immnd_client_node_get(cb, implHandle,
 4622                               &oi_cl_node);
 4623                 osafassert(oi_cl_node);
 4624                 if (oi_cl_node->mIsStale) {
 4625                     LOG_WA("PBE went down");
 4626                     /* This is a bad case. The immnds have
 4627                        just delegated the decision to commit
 4628                        or abort this ccb to the PBE, yet it
 4629                        has just detached. We know here that
 4630                        we have not sent the completed call
 4631                        to the pbe, so in principle the abort
 4632                        should be simple. But the Ccb has
 4633                        just entered the critical state in
 4634                        ImmModel, so we would need to undo
 4635                        that critical state. Problem is it
 4636                        would have to be undone at all IMMNDs
 4637                        which is complicated. Instead of
 4638                        optimizing this error case with
 4639                        complex logic and messaging, we unify
 4640                        it with the case of having sent
 4641                        completed to the PBE, not getting any
 4642                        response and let ccb-recovery sort it
 4643                        out.
 4644                      */
 4645                     goto skip_send;
 4646                 }
 4647 
 4648                 memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 4649                 send_evt.type = IMMSV_EVT_TYPE_IMMA;
 4650                 send_evt.info.imma.type =
 4651                     IMMA_EVT_ND2A_OI_CCB_COMPLETED_UC;
 4652                 send_evt.info.imma.info.ccbCompl.ccbId =
 4653                     evt->info.ccbUpcallRsp.ccbId;
 4654                 send_evt.info.imma.info.ccbCompl.immHandle =
 4655                     implHandle;
 4656                 send_evt.info.imma.info.ccbCompl.implId = pbeId;
 4657                 send_evt.info.imma.info.ccbCompl.invocation =
 4658                     pbeCtn;
 4659 
 4660                 TRACE_2(
 4661                     "MAKING PBE-IMPLEMENTER CCB COMPLETED upcall");
 4662                 if (immnd_mds_msg_send(
 4663                     cb, NCSMDS_SVC_ID_IMMA_OI,
 4664                     oi_cl_node->agent_mds_dest,
 4665                     &send_evt) != NCSCC_RC_SUCCESS) {
 4666                     LOG_WA(
 4667                         "CCB COMPLETED UPCALL SEND TO PBE FAILED");
 4668                     /* If the send to PBE fails in Mds then
 4669                        we *dont* know for sure that the
 4670                        message did not reach the PBE.
 4671                        Therefore act as if send succceeded
 4672                        and let ccb-recovery sort it out.
 4673                     */
 4674                 } else {
 4675                     TRACE_5(
 4676                         "IMMND UPCALL TO PBE for ccb %u, SEND SUCCEEDED",
 4677                         evt->info.ccbUpcallRsp.ccbId);
 4678                 }
 4679             }
 4680             if (cb->mPbeDisableCcbId ==
 4681                 evt->info.ccbUpcallRsp.ccbId) {
 4682                 TRACE(
 4683                     " Disable of PBE is sent to PBE for ACK, in ccb:%u",
 4684                     evt->info.ccbId);
 4685                 cb->mPbeDisableCritical = true;
 4686             }
 4687         skip_send:
 4688             reqConn =
 4689                 0; /* Ensure we dont reply to OM client yet. */
 4690         }
 4691     } else {
 4692         bool validateOnly = false;
 4693         if (err == SA_AIS_OK) { /*Proceed with commit */
 4694             TRACE(
 4695                 "Finished waiting for completed Acks from implementers (and PBE)");
 4696             /*If we arrive here, the assumption is that all
 4697                implementors have agreed to commit and all immnds are
 4698                prepared to commit this ccb. Fevs must guarantee that
 4699                all have seen the same replies from implementers. If
 4700                there is a PBE then it has also decided to commit.
 4701                Appliers now receive completed upcall (any replies
 4702                from appliers are ignored). Then we do the internal
 4703                commit, then send the apply to implementers then the
 4704                apply to appliers.
 4705             */
 4706             SaUint32T applCtn = 0;
 4707             SaUint32T *applConnArr = NULL;
 4708             SaUint32T applArrSize = immModel_getLocalAppliersForCcb(
 4709                 cb, evt->info.ccbUpcallRsp.ccbId, &applConnArr,
 4710                 &applCtn);
 4711 
 4712             if (applArrSize) {
 4713                 memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 4714                 send_evt.type = IMMSV_EVT_TYPE_IMMA;
 4715                 send_evt.info.imma.type =
 4716                     IMMA_EVT_ND2A_OI_CCB_COMPLETED_UC;
 4717                 send_evt.info.imma.info.ccbCompl.ccbId =
 4718                     evt->info.ccbUpcallRsp.ccbId;
 4719                 send_evt.info.imma.info.ccbCompl.implId = 0;
 4720                 send_evt.info.imma.info.ccbCompl.invocation =
 4721                     applCtn;
 4722                 int ix = 0;
 4723                 for (; ix < applArrSize && err == SA_AIS_OK;
 4724                      ++ix) {
 4725                     SaImmOiHandleT implHandle =
 4726                         m_IMMSV_PACK_HANDLE(applConnArr[ix],
 4727                                 cb->node_id);
 4728                     send_evt.info.imma.info.ccbCompl
 4729                         .immHandle = implHandle;
 4730 
 4731                     /*Fetch client node for Applier OI ! */
 4732                     immnd_client_node_get(cb, implHandle,
 4733                                   &oi_cl_node);
 4734                     osafassert(oi_cl_node != NULL);
 4735                     if (oi_cl_node->mIsStale) {
 4736                         LOG_WA(
 4737                             "Applier client went down so completed upcall not sent");
 4738                         continue;
 4739                     } else if (immnd_mds_msg_send(
 4740                                cb,
 4741                                NCSMDS_SVC_ID_IMMA_OI,
 4742                                oi_cl_node
 4743                                ->agent_mds_dest,
 4744                                &send_evt) !=
 4745                            NCSCC_RC_SUCCESS) {
 4746                         LOG_WA(
 4747                             "Completed upcall for applier failed");
 4748                     }
 4749                 }
 4750             }
 4751 
 4752             TRACE_2("DELAYED COMMIT TAKING EFFECT");
 4753             SaUint32T *implConnArr = NULL;
 4754             SaUint32T arrSize = 0;
 4755 
 4756             if (immModel_ccbCommit(cb, evt->info.ccbUpcallRsp.ccbId,
 4757                            &arrSize, &implConnArr)) {
 4758                 osafassert(cb->mPbeDisableCcbId ==
 4759                        evt->info.ccbUpcallRsp.ccbId);
 4760                 cb->mPbeDisableCcbId = 0;
 4761                 cb->mPbeDisableCritical = false;
 4762                 SaImmRepositoryInitModeT oldRim = cb->mRim;
 4763                 cb->mRim = immModel_getRepositoryInitMode(cb);
 4764                 if (oldRim != cb->mRim) {
 4765                     /* Reset mPbeVeteran to force
 4766                        re-generation of db-file when mRim is
 4767                        changed again. We can not continue
 4768                        using any existing db-file because we
 4769                        would get a gap in the persistent
 4770                        history.
 4771                      */
 4772                     cb->mPbeVeteran = false;
 4773                     cb->mPbeVeteranB = false;
 4774 
 4775                     TRACE_2(
 4776                         "Repository init mode changed to: %s",
 4777                         (cb->mRim == SA_IMM_INIT_FROM_FILE)
 4778                         ? "INIT_FROM_FILE"
 4779                         : "KEEP_REPOSITORY");
 4780                     if (cb->mIsCoord && cb->mPbeFile &&
 4781                         (cb->mRim ==
 4782                          SA_IMM_INIT_FROM_FILE)) {
 4783                         cb->mBlockPbeEnable = 0x1;
 4784                         /* Prevent PBE re-enable until
 4785                          * current PBE has terminated.
 4786                          */
 4787                         immnd_announceDump(cb);
 4788                         /* Communicates RIM to IMMD.
 4789                            Needed to decide if reload
 4790                            must cause cluster restart.
 4791                         */
 4792                     }
 4793                 }
 4794             }
 4795 
 4796             if (cb->mSyncrTimeout) {
 4797                 cb->mSyncrTimeout = false;
 4798                 SaTimeT newSyncr = immModel_getSyncrTimeout(cb);
 4799                 uint32_t rc = immnd_syncr_timeout_update_all(newSyncr);
 4800                 if (rc == NCSCC_RC_SUCCESS) {
 4801                     LOG_NO("Update Syncr timeout(%lld) successful", newSyncr);
 4802                 }
 4803                 else {
 4804                     LOG_NO("Update Syncr timeout(%lld) failure. rc:%u",
 4805                            newSyncr, rc);
 4806                 }
 4807             }
 4808 
 4809             if (arrSize) {
 4810                 int ix;
 4811                 memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 4812                 send_evt.type = IMMSV_EVT_TYPE_IMMA;
 4813                 send_evt.info.imma.type =
 4814                     IMMA_EVT_ND2A_OI_CCB_APPLY_UC;
 4815 
 4816                 for (ix = 0; ix < arrSize && err == SA_AIS_OK;
 4817                      ++ix) {
 4818                     /* Send apply callbacks for all
 4819                        implementers at this node involved
 4820                        with the ccb. Re-use evt */
 4821                     /*Look up the client node for the
 4822                      * implementer, using implConn */
 4823                     SaImmHandleT tmp_hdl =
 4824                         m_IMMSV_PACK_HANDLE(implConnArr[ix],
 4825                                 cb->node_id);
 4826 
 4827                     /*Fetch client node for OI ! */
 4828                     immnd_client_node_get(cb, tmp_hdl,
 4829                                   &oi_cl_node);
 4830                     if (oi_cl_node == NULL ||
 4831                         oi_cl_node->mIsStale) {
 4832                         /*Implementer client died ? */
 4833                         LOG_WA(
 4834                             "IMMND - Client went down so can not send apply - ignoring!");
 4835                     } else {
 4836                         /*GENERATE apply message to
 4837                          * implementer. */
 4838                         send_evt.info.imma.info.ccbCompl
 4839                             .ccbId =
 4840                             evt->info.ccbUpcallRsp
 4841                             .ccbId;
 4842                         send_evt.info.imma.info.ccbCompl
 4843                             .implId =
 4844                             evt->info.ccbUpcallRsp
 4845                             .implId;
 4846                         send_evt.info.imma.info.ccbCompl
 4847                             .invocation =
 4848                             evt->info.ccbUpcallRsp.inv;
 4849                         send_evt.info.imma.info.ccbCompl
 4850                             .immHandle = tmp_hdl;
 4851                         TRACE_2(
 4852                             "MAKING IMPLEMENTER CCB APPLY upcall");
 4853                         if (immnd_mds_msg_send(
 4854                             cb,
 4855                             NCSMDS_SVC_ID_IMMA_OI,
 4856                             oi_cl_node
 4857                                 ->agent_mds_dest,
 4858                             &send_evt) !=
 4859                             NCSCC_RC_SUCCESS) {
 4860                             LOG_WA(
 4861                                 "IMMND CCB APPLY: CCB APPLY UPCALL FAILED - ignoring.");
 4862                         }
 4863                     }
 4864                 } // for
 4865                 free(implConnArr);
 4866             } // if(arrSize
 4867 
 4868             if (applArrSize) {
 4869                 memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 4870                 send_evt.type = IMMSV_EVT_TYPE_IMMA;
 4871                 send_evt.info.imma.type =
 4872                     IMMA_EVT_ND2A_OI_CCB_APPLY_UC;
 4873                 send_evt.info.imma.info.ccbCompl.ccbId =
 4874                     evt->info.ccbUpcallRsp.ccbId;
 4875                 send_evt.info.imma.info.ccbCompl.implId = 0;
 4876                 send_evt.info.imma.info.ccbCompl.invocation = 0;
 4877                 int ix = 0;
 4878                 for (; ix < applArrSize && err == SA_AIS_OK;
 4879                      ++ix) {
 4880                     SaImmOiHandleT implHandle =
 4881                         m_IMMSV_PACK_HANDLE(applConnArr[ix],
 4882                                 cb->node_id);
 4883                     send_evt.info.imma.info.ccbCompl
 4884                         .immHandle = implHandle;
 4885 
 4886                     /*Fetch client node for Applier OI ! */
 4887                     immnd_client_node_get(cb, implHandle,
 4888                                   &oi_cl_node);
 4889                     osafassert(oi_cl_node != NULL);
 4890                     if (oi_cl_node->mIsStale) {
 4891                         LOG_WA(
 4892                             "Applier client went down so completed upcall not sent");
 4893                         continue;
 4894                     } else if (immnd_mds_msg_send(
 4895                                cb,
 4896                                NCSMDS_SVC_ID_IMMA_OI,
 4897                                oi_cl_node
 4898                                ->agent_mds_dest,
 4899                                &send_evt) !=
 4900                            NCSCC_RC_SUCCESS) {
 4901                         LOG_WA(
 4902                             "Completed upcall for applier failed");
 4903                     }
 4904                 }
 4905 
 4906                 free(applConnArr);
 4907                 applConnArr = NULL;
 4908             }
 4909         } else if (err == SA_AIS_ERR_INTERRUPT) {
 4910             /* ERR_INTERRUPT => validateOnly. */
 4911             TRACE(
 4912                 "Explicit validation finished OK with completed Acks from OIs "
 4913                 "(not includingPBE)");
 4914 
 4915             err = SA_AIS_OK;
 4916             validateOnly = true;
 4917         } else {
 4918             TRACE(
 4919                 "Abort in immnd_evt_proc_ccb_compl_rsp reqConn: %u",
 4920                 reqConn);
 4921             /*err != SA_AIS_OK => generate SaImmOiCcbAbortCallbackT
 4922                upcall for all local implementers involved in the Ccb
 4923              */
 4924             immnd_evt_ccb_abort(cb, evt->info.ccbUpcallRsp.ccbId,
 4925                         NULL, NULL, NULL);
 4926             errStrings = immModel_ccbGrabErrStrings(
 4927                 cb, evt->info.ccbUpcallRsp.ccbId);
 4928         }
 4929         /* Either commit or abort has been decided. Ccb is now done.
 4930            If we are at originating request node, then we ALWAYS reply
 4931            here. No acks to wait for from apply callbacks and we know we
 4932            have no more completed callback replyes pending.
 4933          */
 4934 
 4935         if (reqConn) {
 4936 
 4937             SaImmHandleT tmp_hdl =
 4938                 m_IMMSV_PACK_HANDLE(reqConn, cb->node_id);
 4939             immnd_client_node_get(cb, tmp_hdl, &cl_node);
 4940             if (cl_node == NULL || cl_node->mIsStale) {
 4941                 LOG_WA(
 4942                     "IMMND - Client went down so no response");
 4943                 /* If the client went down, then object must be
 4944                    either commited or aborted. If the
 4945                    immModel_ccbFinalize is skipped over (below)
 4946                    then the CCB will be left suspended at this
 4947                    node indefinitely (opensaf Ticket #2010), */
 4948                 goto finalize_ccb;
 4949             }
 4950 
 4951             memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 4952             send_evt.type = IMMSV_EVT_TYPE_IMMA;
 4953             send_evt.info.imma.info.errRsp.error = err;
 4954             send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 4955             if (err != SA_AIS_OK) {
 4956                 send_evt.info.imma.info.errRsp.errStrings =
 4957                     errStrings;
 4958 
 4959                 if (send_evt.info.imma.info.errRsp.errStrings) {
 4960                     send_evt.info.imma.type =
 4961                         IMMA_EVT_ND2A_IMM_ERROR_2;
 4962                 }
 4963             }
 4964 
 4965             rc = immnd_mds_send_rsp(cb, &(cl_node->tmpSinfo),
 4966                         &send_evt);
 4967             if (rc != NCSCC_RC_SUCCESS) {
 4968                 LOG_WA(
 4969                     "Failed to send response to agent/client over MDS rc:%u",
 4970                     rc);
 4971             }
 4972         }
 4973     finalize_ccb:
 4974         if (validateOnly) {
 4975             goto done;
 4976         }
 4977 
 4978         immsv_evt_free_attrNames(errStrings);
 4979         TRACE_2("CCB COMPLETED: TERMINATING CCB:%u",
 4980             evt->info.ccbUpcallRsp.ccbId);
 4981         err = immModel_ccbFinalize(cb, evt->info.ccbUpcallRsp.ccbId);
 4982         if (err != SA_AIS_OK) {
 4983             LOG_WA("Failure in termination of CCB:%u - ignoring!",
 4984                    evt->info.ccbUpcallRsp.ccbId);
 4985             /* There is really not much we can do here. */
 4986         }
 4987     }
 4988 done:
 4989     TRACE_LEAVE();
 4990 }
 4991 
 4992 /****************************************************************************
 4993  * Name          : immnd_evt_pbe_rt_obj_create_rsp
 4994  *
 4995  * Description   : Function to process the reply from the
 4996  *                 SaImmOiCcbObjectCreateCallbackT upcall for the PRTO case.
 4997  *                 Note this call arrived over fevs, to ALL IMMNDs.
 4998  *                 This is because ALL must receive ACK/NACK from EACH
 4999  *                 implementer.
 5000  *
 5001  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 5002  *                 IMMSV_EVT *evt - Received Event structure
 5003  *
 5004  * Return Values : None.
 5005  *
 5006  *****************************************************************************/
 5007 static void immnd_evt_pbe_rt_obj_create_rsp(IMMND_CB *cb, IMMND_EVT *evt,
 5008                         bool originatedAtThisNd,
 5009                         SaImmHandleT clnt_hdl,
 5010                         MDS_DEST reply_dest)
 5011 {
 5012     uint32_t rc = NCSCC_RC_SUCCESS;
 5013     IMMSV_EVT send_evt;
 5014     SaUint32T reqConn = 0;
 5015     SaUint32T spApplConn = 0;
 5016     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 5017     TRACE_ENTER();
 5018     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 5019 
 5020     immModel_pbePrtObjCreateContinuation(
 5021         cb, evt->info.ccbUpcallRsp.inv, evt->info.ccbUpcallRsp.result,
 5022         cb->node_id, &reqConn, &spApplConn,
 5023         &(send_evt.info.imma.info.objCreate));
 5024     TRACE(
 5025         "Returned from pbePrtObjCreateContinuation err: %u reqConn:%x applConn:%x",
 5026         evt->info.ccbUpcallRsp.result, reqConn, spApplConn);
 5027 
 5028     if (evt->info.ccbUpcallRsp.result != SA_AIS_OK) {
 5029         /* If 2PBE-slave restarts in close proximity to PRT problems,
 5030            then it should regenerate the pbe-file.*/
 5031         cb->mPbeVeteranB = false;
 5032     }
 5033 
 5034     if (spApplConn) {
 5035         SaImmHandleT implHandle =
 5036             m_IMMSV_PACK_HANDLE(spApplConn, cb->node_id);
 5037         cl_node = 0LL;
 5038         immnd_client_node_get(cb, implHandle, &cl_node);
 5039         osafassert(cl_node != NULL);
 5040         send_evt.type = IMMSV_EVT_TYPE_IMMA;
 5041         /* Assuming special applier is long DN capable. */
 5042         send_evt.info.imma.type = IMMA_EVT_ND2A_OI_OBJ_CREATE_UC;
 5043         send_evt.info.imma.info.objCreate.adminOwnerId = 0;
 5044         send_evt.info.imma.info.objCreate.immHandle = implHandle;
 5045         send_evt.info.imma.info.objCreate.ccbId = 0;
 5046         osafassert(send_evt.info.imma.info.objCreate.attrValues);
 5047         TRACE("Sending special applier PRTO create");
 5048         if (cl_node->mIsStale) {
 5049             LOG_WA(
 5050                 "Special applier client went down so PRTO create upcall not sent");
 5051         } else if (immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMA_OI,
 5052                           cl_node->agent_mds_dest,
 5053                           &send_evt) != NCSCC_RC_SUCCESS) {
 5054             LOG_WA("PRTO Create upcall for special applier failed");
 5055             /* This is an unhandled message loss case!*/
 5056         }
 5057         immsv_free_attrvalues_list(
 5058             send_evt.info.imma.info.objCreate.attrValues);
 5059         send_evt.info.imma.info.objCreate.attrValues = NULL;
 5060 
 5061         free(send_evt.info.imma.info.objCreate.className.buf);
 5062         send_evt.info.imma.info.objCreate.className.buf = NULL;
 5063         send_evt.info.imma.info.objCreate.className.size = 0;
 5064 
 5065         if (send_evt.info.imma.info.objCreate.parentOrObjectDn.buf) {
 5066             free(send_evt.info.imma.info.objCreate.parentOrObjectDn
 5067                  .buf);
 5068             send_evt.info.imma.info.objCreate.parentOrObjectDn.buf =
 5069                 NULL;
 5070             send_evt.info.imma.info.objCreate.parentOrObjectDn
 5071                 .size = 0;
 5072         }
 5073     }
 5074 
 5075     if (reqConn) {
 5076         SaImmHandleT tmp_hdl =
 5077             m_IMMSV_PACK_HANDLE(reqConn, cb->node_id);
 5078 
 5079         immnd_client_node_get(cb, tmp_hdl, &cl_node);
 5080         if (cl_node == NULL || cl_node->mIsStale) {
 5081             LOG_WA("IMMND - Client went down so no response");
 5082             TRACE_LEAVE();
 5083             return; /*Note, this means that regardles of ccb
 5084                    outcome, we can not reply to the process that
 5085                    started the ccb. */
 5086         }
 5087 
 5088         TRACE_2("SENDRSP %u", evt->info.ccbUpcallRsp.result);
 5089 
 5090         memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 5091         send_evt.type = IMMSV_EVT_TYPE_IMMA;
 5092         send_evt.info.imma.info.errRsp.error =
 5093             evt->info.ccbUpcallRsp.result;
 5094         send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 5095 
 5096         rc = immnd_mds_send_rsp(cb, &(cl_node->tmpSinfo), &send_evt);
 5097         if (rc != NCSCC_RC_SUCCESS) {
 5098             LOG_WA(
 5099                 "Failed to send response to agent/client over MDS rc:%u",
 5100                 rc);
 5101         }
 5102     }
 5103 
 5104     TRACE_LEAVE();
 5105 }
 5106 
 5107 /****************************************************************************
 5108  * Name          : immnd_evt_pbe_rt_attr_update_rsp
 5109  *
 5110  * Description   : Function to process the reply from the
 5111  *                 SaImmOiCcbObjectModifyCallbackT upcall for the PRT attr case.
 5112  *                 Note this call arrived over fevs, to ALL IMMNDs.
 5113  *                 This is because ALL must receive ACK/NACK from EACH
 5114  *                 implementer.
 5115  *
 5116  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 5117  *                 IMMSV_EVT *evt - Received Event structure
 5118  *
 5119  * Return Values : None.
 5120  *
 5121  *****************************************************************************/
 5122 static void immnd_evt_pbe_rt_attr_update_rsp(IMMND_CB *cb, IMMND_EVT *evt,
 5123                          bool originatedAtThisNd,
 5124                          SaImmHandleT clnt_hdl,
 5125                          MDS_DEST reply_dest)
 5126 {
 5127     uint32_t rc = NCSCC_RC_SUCCESS;
 5128     IMMSV_EVT send_evt;
 5129     SaUint32T reqConn = 0;
 5130     SaUint32T spApplConn = 0;
 5131     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 5132     TRACE_ENTER();
 5133     memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 5134 
 5135     immModel_pbePrtAttrUpdateContinuation(
 5136         cb, evt->info.ccbUpcallRsp.inv, evt->info.ccbUpcallRsp.result,
 5137         cb->node_id, &reqConn, &spApplConn,
 5138         &(send_evt.info.imma.info.objModify));
 5139     TRACE(
 5140         "Returned from pbePrtAttrUpdateContinuation err: %u reqConn:%x applConn:%x",
 5141         evt->info.ccbUpcallRsp.result, reqConn, spApplConn);
 5142 
 5143     if (evt->info.ccbUpcallRsp.result != SA_AIS_OK) {
 5144         /* If 2PBE-slave restarts in close proximity to PRT problems,
 5145            then it should regenerate the pbe-file.*/
 5146         cb->mPbeVeteranB = false;
 5147     }
 5148 
 5149     if (spApplConn) {
 5150         SaImmHandleT implHandle =
 5151             m_IMMSV_PACK_HANDLE(spApplConn, cb->node_id);
 5152         cl_node = 0LL;
 5153         immnd_client_node_get(cb, implHandle, &cl_node);
 5154         osafassert(cl_node != NULL);
 5155         send_evt.type = IMMSV_EVT_TYPE_IMMA;
 5156         /* Assuming special applier is long DN capable. */
 5157         send_evt.info.imma.type = IMMA_EVT_ND2A_OI_OBJ_MODIFY_UC;
 5158         send_evt.info.imma.info.objModify.adminOwnerId = 0;
 5159         send_evt.info.imma.info.objModify.immHandle = implHandle;
 5160         send_evt.info.imma.info.objModify.ccbId = 0;
 5161         osafassert(send_evt.info.imma.info.objModify.attrMods);
 5162         TRACE("Sending special applier PRTA update");
 5163         if (cl_node->mIsStale) {
 5164             LOG_WA(
 5165                 "Special applier client went down so RTA update upcall not sent");
 5166         } else if (immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMA_OI,
 5167                           cl_node->agent_mds_dest,
 5168                           &send_evt) != NCSCC_RC_SUCCESS) {
 5169             LOG_WA("RTA update upcall for special applier failed");
 5170             /* This is an unhandled message loss case!*/
 5171         }
 5172         immsv_free_attrmods(send_evt.info.imma.info.objModify.attrMods);
 5173         send_evt.info.imma.info.objModify.attrMods = NULL;
 5174 
 5175         free(send_evt.info.imma.info.objModify.objectName.buf);
 5176         send_evt.info.imma.info.objModify.objectName.buf = NULL;
 5177         send_evt.info.imma.info.objModify.objectName.size = 0;
 5178     }
 5179 
 5180     if (reqConn) {
 5181         SaImmHandleT tmp_hdl =
 5182             m_IMMSV_PACK_HANDLE(reqConn, cb->node_id);
 5183 
 5184         immnd_client_node_get(cb, tmp_hdl, &cl_node);
 5185         if (cl_node == NULL || cl_node->mIsStale) {
 5186             LOG_WA("IMMND - Client went down so no response");
 5187             TRACE_LEAVE();
 5188             return; /*Note, this means that regardles of ccb
 5189                    outcome, we can not reply to the process that
 5190                    started the ccb. */
 5191         }
 5192 
 5193         TRACE_2("SENDRSP %u", evt->info.ccbUpcallRsp.result);
 5194 
 5195         memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 5196         send_evt.type = IMMSV_EVT_TYPE_IMMA;
 5197         send_evt.info.imma.info.errRsp.error =
 5198             evt->info.ccbUpcallRsp.result;
 5199         send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 5200 
 5201         rc = immnd_mds_send_rsp(cb, &(cl_node->tmpSinfo), &send_evt);
 5202         if (rc != NCSCC_RC_SUCCESS) {
 5203             LOG_WA(
 5204                 "Failed to send response to agent/client over MDS rc:%u",
 5205                 rc);
 5206         }
 5207     }
 5208 
 5209     TRACE_LEAVE();
 5210 }
 5211 
 5212 /****************************************************************************
 5213  * Name          : immnd_evt_sync_fevs_base
 5214  *
 5215  * Description   : Function to receive the sync_fevs_base.
 5216  *                 This is the fevs coutn at the coord at the time when
 5217  *                 the searchinitialize for the sync is generated.
 5218  *                 This count is used to discard any RTA updates that
 5219  *                 arrived at the sync client before the sync base was
 5220  *generated. Any RTA updates arriving after the sync-base iterator initialize,
 5221  *must be applied at the sync client as soon as the sync
 5222  *message for the object arrives.
 5223  *
 5224  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 5225  *                 IMMSV_EVT *evt - Received Event structure
 5226  *
 5227  * Return Values : None.
 5228  *
 5229  *****************************************************************************/
 5230 static void immnd_evt_sync_fevs_base(IMMND_CB *cb, IMMND_EVT *evt,
 5231                      bool originatedAtThisNd,
 5232                      SaImmHandleT clnt_hdl, MDS_DEST reply_dest)
 5233 {
 5234     TRACE_ENTER2("Received syncFevsBase: %llu", evt->info.syncFevsBase);
 5235     if (cb->mSync) {
 5236         cb->syncFevsBase = evt->info.syncFevsBase;
 5237     }
 5238 }
 5239 
 5240 static void immnd_evt_safe_read_lock(IMMND_CB *cb, IMMND_EVT *evt,
 5241                      bool originatedAtThisNd,
 5242                      SaImmHandleT clnt_hdl, MDS_DEST reply_dest)
 5243 {
 5244     IMMSV_EVT send_evt;
 5245     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 5246     TRACE_ENTER();
 5247 
 5248     SaAisErrorT err =
 5249         immModel_objectIsLockedByCcb(cb, &(evt->info.searchInit));
 5250 
 5251     switch (err) {
 5252     case SA_AIS_OK:
 5253         TRACE(
 5254             "safe_read_lock: Object is already locked by this CCB(%u)!!",
 5255             evt->info.searchInit.ccbId);
 5256         break;
 5257 
 5258     case SA_AIS_ERR_BUSY:
 5259         TRACE(
 5260             "Object is locked by some other CCB than this CCB(%u). Reply with BUSY",
 5261             evt->info.searchInit.ccbId);
 5262         break;
 5263 
 5264     case SA_AIS_ERR_INTERRUPT:
 5265         TRACE("Object not locked. Ccb (%u) will now lock it",
 5266               evt->info.searchInit.ccbId);
 5267         err = immModel_ccbReadLockObject(cb, &(evt->info.searchInit));
 5268         break;
 5269 
 5270     default:
 5271         TRACE("Unusual error from immModel_objectIsLockedByCcb: %u",
 5272               err);
 5273     }
 5274 
 5275     if (originatedAtThisNd) {
 5276         immnd_client_node_get(cb, clnt_hdl, &cl_node);
 5277         if (cl_node == NULL || cl_node->mIsStale) {
 5278             LOG_WA("IMMND - Client went down so no response");
 5279             return;
 5280         }
 5281         TRACE_2("Send immediate reply to client");
 5282 
 5283         memset(&send_evt, '\0', sizeof(IMMSV_EVT));
 5284         send_evt.type = IMMSV_EVT_TYPE_IMMA;
 5285         send_evt.info.imma.info.errRsp.error = err;
 5286         send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_ERROR;
 5287 
 5288         if (immnd_mds_send_rsp(cb, &(cl_node->tmpSinfo), &send_evt) !=
 5289             NCSCC_RC_SUCCESS) {
 5290             LOG_WA(
 5291                 "immnd_evt_class_delete: SENDRSP FAILED TO SEND");
 5292         }
 5293     }
 5294 
 5295     TRACE_LEAVE();
 5296 }
 5297 
 5298 /****************************************************************************
 5299  * Name          : immnd_evt_pbe_admop_rsp
 5300  *
 5301  * Description   : Function to process the reply from the special
 5302  *                 admop to persistify class create.
 5303  *                 Note this call arrived over fevs, to ALL IMMNDs.
 5304  *
 5305  * Arguments     : IMMND_CB *cb - IMMND CB pointer
 5306  *                 IMMSV_EVT *evt - Received Event structure
 5307  *
 5308  * Return Values : None.
 5309  *
 5310  *****************************************************************************/
 5311 static void immnd_evt_pbe_admop_rsp(IMMND_CB *cb, IMMND_EVT *evt,
 5312                     bool originatedAtThisNd,
 5313                     SaImmHandleT clnt_hdl, MDS_DEST reply_dest)
 5314 {
 5315     uint32_t rc = NCSCC_RC_SUCCESS;
 5316     IMMSV_EVT send_evt;
 5317     SaUint32T reqConn = 0;
 5318     IMMND_IMM_CLIENT_NODE *cl_node = NULL;
 5319     TRACE_ENTER();
 5320     SaUint32T admoId =
 5321         m_IMMSV_UNPACK_HANDLE_HIGH(evt->info.admOpRsp.invocation);
 5322     osafassert(admoId == 0);
 5323     SaUint32T invoc =
 5324         m_IMMSV_UNPACK_HANDLE_LOW(evt->info.admOpRsp.invocation);
 5325 
 5326     if (evt->info.admOpRsp.error != SA_AIS_OK) {
 5327         LOG_ER(
 5328             "Received error result %u from PBE CLASS CREATE - dropping "
 5329             "continuation. PBE should get restarted",
 5330             evt->info.admOpRsp.error);
 5331         return;
 5332     }
 5333 
 5334     if (evt->info.admOpRsp.result == SA_AIS_ERR_REPAIR_PENDING) {
 5335         /* OK result on OPENSAF_IMM_PBE_CLASS_CREATE */
 5336         immModel_pbeClassCreateContinuation(cb, invoc, cb->node_id,
 5337                             &reqConn);
 5338         TRACE("Returned from pbeClassCreateContinuation invoc:%x",
 5339               invoc);
 5340     } else if (evt->info.admOpRsp.result == SA_AIS_ERR_NO_SPACE) {
 5341         /* OK result on OPENSAF_IMM_PBE_CLASS_DELETE */
 5342         immModel_pbeClassDeleteContinuation(cb, invoc, cb->node_id,
 5343                             &reqConn);
 5344         TRACE("Returned from pbeClassDeleteContinuation invoc:%x",
 5345               invoc);
 5346     } else if (evt->info.admOpRsp.result ==
 5347            SA_AIS_ERR_QUEUE_NOT_AVAILABLE) {
 5348         /* OK result on OPENSAF_IMM_PBE_UPDATE_EPOCH
 5349            No reqConn since this is no client for this call. */
 5350         immModel_pbeUpdateEpochContinuation(cb, invoc, cb->node_id);
 5351         TRACE("Returned from pbeUpdateEpochContinuation invoc:%x",
 5352