"Fossies" - the Fresh Open Source Software Archive

Member "opensaf-5.21.09/src/imm/agent/imma_oi_api.cc" (14 Sep 2021, 133596 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 "imma_oi_api.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.21.06_vs_5.21.09.

    1 /*      -*- OpenSAF  -*-
    2  *
    3  * (C) Copyright 2008 The OpenSAF Foundation
    4  * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
    5  *
    6  * This program is distributed in the hope that it will be useful, but
    7  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    8  * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
    9  * under the GNU Lesser General Public License Version 2.1, February 1999.
   10  * The complete license can be accessed from the following location:
   11  * http://opensource.org/licenses/lgpl-license.php
   12  * See the Copying file included with the OpenSAF distribution for full
   13  * licensing terms.
   14  *
   15  * Author(s): Ericsson AB
   16  *
   17  */
   18 
   19 /*****************************************************************************
   20   DESCRIPTION:
   21 
   22   This file contains the IMMSv SAF API definitions.
   23 
   24 TRACE GUIDE:
   25  Policy is to not use logging/syslog from library code.
   26  Only the trace part of logtrace is used from library.
   27 
   28  It is possible to turn on trace for the IMMA library used
   29  by an application process. This is done by the application
   30  defining the environment variable: IMMA_TRACE_PATHNAME.
   31  The trace will end up in the file defined by that variable.
   32 
   33  TRACE   debug traces                 - aproximates DEBUG
   34  TRACE_1 normal but important events  - aproximates INFO.
   35  TRACE_2 user errors with return code - aproximates NOTICE.
   36  TRACE_3 unusual or strange events    - aproximates WARNING
   37  TRACE_4 library errors ERR_LIBRARY   - aproximates ERROR
   38 *****************************************************************************/
   39 
   40 #include "imma.h"
   41 #include "imm/common/immsv_api.h"
   42 #include "base/osaf_extended_name.h"
   43 
   44 static const char *sysaClName = SA_IMM_ATTR_CLASS_NAME;
   45 static const char *sysaAdmName = SA_IMM_ATTR_ADMIN_OWNER_NAME;
   46 static const char *sysaImplName = SA_IMM_ATTR_IMPLEMENTER_NAME;
   47 
   48 static int imma_oi_resurrect(IMMA_CB *cb, IMMA_CLIENT_NODE *cl_node,
   49                              bool *locked, SaAisErrorT *err_cli_res);
   50 
   51 /****************************************************************************
   52   Name          :  SaImmOiInitialize_2/_o3
   53 
   54   Description   :  This function initializes the IMM OI Service for the
   55                    invoking process and registers the callback functions.
   56                    The handle 'immOiHandle' is returned as the reference to
   57                    this association between the process and the ImmOi Service.
   58 
   59 
   60   Arguments     :  immOiHandle -  A pointer to the handle designating this
   61                                 particular initialization of the IMM OI
   62                                 service that is to be returned by the
   63                                 ImmOi Service.
   64                    immOiCallbacks  - Pointer to a SaImmOiCallbacksT structure,
   65                                 containing the callback functions of the
   66                                 process that the ImmOi Service may invoke.
   67                    version    - Is a pointer to the version of the Imm
   68                                 Service that the invoking process is using.
   69 
   70   Return Values :  Refer to SAI-AIS specification for various return values.
   71 
   72   Notes         :
   73 ******************************************************************************/
   74 static SaAisErrorT initialize_common(SaImmOiHandleT *immOiHandle,
   75                                      SaVersionT *inout_version,
   76                                      IMMA_CLIENT_NODE **client_node);
   77 
   78 SaAisErrorT saImmOiInitialize_2(SaImmOiHandleT *immOiHandle,
   79                                 const SaImmOiCallbacksT_2 *immOiCallbacks,
   80                                 SaVersionT *inout_version) {
   81   IMMA_CLIENT_NODE *cl_node;
   82   SaAisErrorT rc;
   83 
   84   rc = initialize_common(immOiHandle, inout_version, &cl_node);
   85   if (rc == SA_AIS_OK && immOiCallbacks) {
   86     cl_node->o.iCallbk = *immOiCallbacks;
   87   }
   88 
   89   return rc;
   90 }
   91 
   92 SaAisErrorT saImmOiInitialize_o3(SaImmOiHandleT *immOiHandle,
   93                                  const SaImmOiCallbacksT_o3 *immOiCallbacks,
   94                                  SaVersionT *inout_version) {
   95   IMMA_CLIENT_NODE *cl_node;
   96   SaAisErrorT rc;
   97 
   98   if (inout_version && (inout_version->releaseCode == 'A') &&
   99       (inout_version->majorVersion == 0x02) &&
  100       (inout_version->minorVersion < 0x0f)) {
  101     TRACE_2(
  102         "ERR_VERSION: saImmOiInitialize_o3 is available from version A.2.15");
  103     return SA_AIS_ERR_VERSION;
  104   }
  105 
  106   rc = initialize_common(immOiHandle, inout_version, &cl_node);
  107   if (rc == SA_AIS_OK && immOiCallbacks) {
  108     cl_node->o.iCallbkA2f = *immOiCallbacks;
  109     cl_node->isImmA2fCbk = true;
  110   }
  111 
  112   return rc;
  113 }
  114 
  115 SaAisErrorT initialize_common(SaImmOiHandleT *immOiHandle,
  116                               SaVersionT *inout_version,
  117                               IMMA_CLIENT_NODE **client_node) {
  118   IMMA_CB *cb = &imma_cb;
  119   SaAisErrorT rc = SA_AIS_OK;
  120   IMMSV_EVT init_evt;
  121   IMMSV_EVT *out_evt = NULL;
  122   IMMA_CLIENT_NODE *cl_node = 0;
  123   bool locked = true;
  124   SaVersionT requested_version;
  125   char *timeout_env_value = NULL;
  126 
  127   TRACE_ENTER();
  128 
  129   *client_node = NULL;
  130 
  131   uint32_t proc_rc = imma_startup(NCSMDS_SVC_ID_IMMA_OI);
  132   if (NCSCC_RC_SUCCESS != proc_rc) {
  133     TRACE_4("ERR_LIBRARY: Agents_startup failed");
  134     TRACE_LEAVE();
  135     return SA_AIS_ERR_LIBRARY;
  136   }
  137 
  138   if ((!immOiHandle) || (!inout_version)) {
  139     TRACE_2("ERR_INVALID_PARAM: immOiHandle is NULL or version is NULL");
  140     rc = SA_AIS_ERR_INVALID_PARAM;
  141     goto end;
  142   }
  143 
  144   requested_version = (*inout_version);
  145 
  146   if (false == cb->is_immnd_up) {
  147     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
  148     rc = SA_AIS_ERR_TRY_AGAIN;
  149     goto end;
  150   }
  151 
  152   *immOiHandle = 0;
  153 
  154   /* Alloc the client info data structure & put it in the Pat tree */
  155   cl_node = new IMMA_CLIENT_NODE{};
  156   if (cl_node == NULL) {
  157     TRACE_2("ERR_NO_MEMORY: IMMA_CLIENT_NODE alloc failed");
  158     rc = SA_AIS_ERR_NO_MEMORY;
  159     goto cnode_alloc_fail;
  160   }
  161 
  162   cl_node->isOm = false;
  163 
  164   if ((requested_version.releaseCode == 'A') &&
  165       (requested_version.majorVersion == 0x02)) {
  166     TRACE_2("OI client version A.2.%u", requested_version.minorVersion);
  167     if (requested_version.minorVersion >= 0x0b) {
  168       cl_node->isImmA2b = 0x1;
  169       if (requested_version.minorVersion >= 0x0d) {
  170         cl_node->isImmA2d = true;
  171         if (requested_version.minorVersion >= 0x0e) {
  172           cl_node->isImmA2e = true;
  173           if (requested_version.minorVersion >= 0x0f) {
  174             cl_node->isImmA2f = true;
  175             if (requested_version.minorVersion >= 0x10) {
  176               cl_node->isImmA2x10 = true;
  177               if (requested_version.minorVersion >= 0x11) {
  178                 cl_node->isImmA2x11 = true;
  179                 if (requested_version.minorVersion >= 0x12) {
  180                   cl_node->isImmA2x12 = true;
  181                 }
  182               }
  183             }
  184           }
  185         }
  186       }
  187     }
  188   }
  189 
  190   cl_node->syncr_timeout = imma_getSyncrTimeout();
  191   TRACE_2("IMMA library syncronous timeout set to:%lld",
  192           cl_node->syncr_timeout);
  193 
  194   if (cl_node->isImmA2e &&
  195       (timeout_env_value = getenv("IMMA_OI_CALLBACK_TIMEOUT")) != NULL) {
  196     char *endp = NULL;
  197     cl_node->oiTimeout = strtol(timeout_env_value, &endp, 10);
  198     if (!endp || *endp) {
  199       TRACE_2(
  200           "Failed to parse IMMA_OI_CALLBACK_TIMEOUT. "
  201           "OI timeout will be set to the default value");
  202       cl_node->oiTimeout = 0;
  203     } else {
  204       TRACE_2("IMMA library OI timeout set to:%lld", cl_node->oiTimeout);
  205     }
  206   } else {
  207     cl_node->oiTimeout = 0;
  208   }
  209 
  210   /* Take the CB Lock */
  211   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
  212     TRACE_4("ERR_LIBRARY: LOCK failed");
  213     rc = SA_AIS_ERR_LIBRARY;
  214     goto lock_fail;
  215   }
  216   /* locked == true already */
  217 
  218   /* Draft Validations : Version this is the politically correct validatioin
  219      distinct from the pragmatic validation we do above. */
  220   rc = imma_version_validate(inout_version);
  221   if (rc != SA_AIS_OK) {
  222     TRACE_2("ERR_VERSION");
  223     goto version_fail;
  224   }
  225 
  226   proc_rc = imma_callback_ipc_init(cl_node);
  227 
  228   if (proc_rc != NCSCC_RC_SUCCESS) {
  229     rc = SA_AIS_ERR_LIBRARY;
  230     /* ALready log'ed by imma_callback_ipc_init */
  231     goto ipc_init_fail;
  232   }
  233 
  234   /* populate the EVT structure */
  235   memset(&init_evt, 0, sizeof(IMMSV_EVT));
  236   init_evt.type = IMMSV_EVT_TYPE_IMMND;
  237   init_evt.info.immnd.type = IMMND_EVT_A2ND_IMM_OI_INIT;
  238   init_evt.info.immnd.info.initReq.version = requested_version;
  239   init_evt.info.immnd.info.initReq.client_pid = getpid();
  240 
  241   /* Release the CB lock Before MDS Send */
  242   m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
  243   locked = false;
  244 
  245   /* cl_node has not been added to tree in cb yet so safe to access
  246      without cb-lock.
  247    */
  248 
  249   if (false == cb->is_immnd_up) {
  250     rc = SA_AIS_ERR_TRY_AGAIN;
  251     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
  252     goto mds_fail;
  253   }
  254   if (cl_node->isImmA2x12 && !cb->clmMemberNode) {
  255     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
  256     rc = SA_AIS_ERR_UNAVAILABLE;
  257     goto clm_left;
  258   }
  259 
  260   /* send the request to the IMMND */
  261   proc_rc = imma_mds_msg_sync_send(cb->imma_mds_hdl, &cb->immnd_mds_dest,
  262                                    &init_evt, &out_evt, cl_node->syncr_timeout);
  263 
  264   /* Error Handling */
  265   switch (proc_rc) {
  266     case NCSCC_RC_SUCCESS:
  267       break;
  268     case NCSCC_RC_REQ_TIMOUT:
  269       rc = SA_AIS_ERR_TIMEOUT;
  270       goto mds_fail;
  271     default:
  272       TRACE_4("ERR_LIBRARY: MDS returned unexpected error code %u", proc_rc);
  273       rc = SA_AIS_ERR_LIBRARY;
  274       goto mds_fail;
  275   }
  276 
  277   if (out_evt) {
  278     rc = out_evt->info.imma.info.initRsp.error;
  279     if (rc == SA_AIS_ERR_UNAVAILABLE && cl_node->isImmA2x12) {
  280       cb->clmMemberNode = false;
  281       TRACE(" Node left the CLM membership");
  282       goto rsp_not_ok;
  283     }
  284 
  285     if (rc != SA_AIS_OK) {
  286       goto rsp_not_ok;
  287     }
  288 
  289     /* Take the CB lock after MDS Send */
  290     if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
  291       TRACE_4("ERR_LIBRARY: LOCK failed");
  292       rc = SA_AIS_ERR_LIBRARY;
  293       goto lock_fail1;
  294     }
  295 
  296     locked = true;
  297 
  298     if (false == cb->is_immnd_up) {
  299       /*IMMND went down during THIS call! */
  300       rc = SA_AIS_ERR_TRY_AGAIN;
  301       TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
  302       goto rsp_not_ok;
  303     }
  304 
  305     cl_node->handle = out_evt->info.imma.info.initRsp.immHandle;
  306     SaTimeT timeout = out_evt->info.imma.info.initRsp.syncrTimeout;
  307     if (timeout >= NCS_SAF_MIN_ACCEPT_TIME) {
  308       cl_node->syncr_timeout = timeout;
  309       TRACE_2("IMMA library syncronous timeout set to:%lld",
  310               cl_node->syncr_timeout);
  311     }
  312 
  313     TRACE_1("Trying to add OI client id:%u node:%x handle:%llx",
  314             m_IMMSV_UNPACK_HANDLE_HIGH(cl_node->handle),
  315             m_IMMSV_UNPACK_HANDLE_LOW(cl_node->handle), cl_node->handle);
  316     proc_rc = imma_client_node_add(&cb->client_tree, cl_node);
  317     if (proc_rc != NCSCC_RC_SUCCESS) {
  318       IMMA_CLIENT_NODE *stale_node = NULL;
  319       imma_client_node_get(&cb->client_tree, &(cl_node->handle), &stale_node);
  320 
  321       if ((stale_node != NULL) && stale_node->stale) {
  322         TRACE_1("Removing stale client");
  323         imma_finalize_client(cb, stale_node);
  324         proc_rc = imma_shutdown(NCSMDS_SVC_ID_IMMA_OI);
  325         if (proc_rc != NCSCC_RC_SUCCESS) {
  326           TRACE_4("ERR_LIBRARY: Call to imma_shutdown FAILED");
  327           rc = SA_AIS_ERR_LIBRARY;
  328           goto node_add_fail;
  329         }
  330         TRACE_1("Retrying add of client node");
  331         proc_rc = imma_client_node_add(&cb->client_tree, cl_node);
  332       }
  333 
  334       if (proc_rc != NCSCC_RC_SUCCESS) {
  335         rc = SA_AIS_ERR_LIBRARY;
  336         TRACE_4("ERR_LIBRARY: client_node_add failed");
  337         goto node_add_fail;
  338       }
  339     }
  340   } else {
  341     TRACE_4("ERR_LIBRARY: Empty reply received");
  342     rc = SA_AIS_ERR_LIBRARY;
  343   }
  344 
  345 /*Error handling */
  346 node_add_fail:
  347 lock_fail1:
  348   if (rc != SA_AIS_OK) {
  349     IMMSV_EVT finalize_evt, *out_evt1;
  350 
  351     out_evt1 = NULL;
  352     memset(&finalize_evt, 0, sizeof(IMMSV_EVT));
  353     finalize_evt.type = IMMSV_EVT_TYPE_IMMND;
  354     finalize_evt.info.immnd.type = IMMND_EVT_A2ND_IMM_OI_FINALIZE;
  355     finalize_evt.info.immnd.info.finReq.client_hdl = cl_node->handle;
  356 
  357     if (locked) {
  358       m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
  359       locked = false;
  360     }
  361 
  362     /* send the request to the IMMND */
  363     imma_mds_msg_sync_send(cb->imma_mds_hdl, &(cb->immnd_mds_dest),
  364                            &finalize_evt, &out_evt1, cl_node->syncr_timeout);
  365     if (out_evt1) {
  366       free(out_evt1);
  367     }
  368   }
  369   TRACE_2("OI client version A.2.%u", requested_version.minorVersion);
  370 
  371 clm_left:
  372 rsp_not_ok:
  373 mds_fail:
  374 
  375   /* Free the IPC initialized for this client */
  376   if (rc != SA_AIS_OK) imma_callback_ipc_destroy(cl_node);
  377 
  378 ipc_init_fail:
  379 version_fail:
  380 
  381   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
  382   if (out_evt) {
  383     free(out_evt);
  384   }
  385 
  386 lock_fail:
  387   if (rc != SA_AIS_OK) delete cl_node;
  388 
  389 cnode_alloc_fail:
  390 
  391   if (rc == SA_AIS_OK) {
  392     /* Went well, return immHandle to the application */
  393     *immOiHandle = cl_node->handle;
  394   }
  395 
  396 end:
  397   if (rc != SA_AIS_OK) {
  398     if (NCSCC_RC_SUCCESS != imma_shutdown(NCSMDS_SVC_ID_IMMA_OI)) {
  399       /* Oh boy. Failure in imma_shutdown when we already have
  400          some other problem. */
  401       TRACE_4("ERR_LIBRARY: Call to imma_shutdown failed, prior error %u", rc);
  402       rc = SA_AIS_ERR_LIBRARY;
  403     }
  404   } else {
  405     *client_node = cl_node;
  406   }
  407   TRACE_LEAVE();
  408   return rc;
  409 }
  410 
  411 /****************************************************************************
  412   Name          :  saImmOiSelectionObjectGet
  413 
  414   Description   :  This function returns the operating system handle
  415                    associated with the immOiHandle.
  416 
  417   Arguments     :  immOiHandle - Imm OI service handle.
  418                    selectionObject - Pointer to the operating system handle.
  419 
  420   Return Values :  Refer to SAI-AIS specification for various return values.
  421 
  422   Notes         :
  423 ******************************************************************************/
  424 SaAisErrorT saImmOiSelectionObjectGet(SaImmOiHandleT immOiHandle,
  425                                       SaSelectionObjectT *selectionObject) {
  426   SaAisErrorT rc = SA_AIS_OK;
  427   IMMA_CB *cb = &imma_cb;
  428   IMMA_CLIENT_NODE *cl_node = 0;
  429   bool locked = true;
  430   TRACE_ENTER();
  431 
  432   if (!selectionObject) return SA_AIS_ERR_INVALID_PARAM;
  433 
  434   if (cb->sv_id == 0) {
  435     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
  436     return SA_AIS_ERR_BAD_HANDLE;
  437   }
  438 
  439   if (cb->is_immnd_up == false) {
  440     /* Normally this call will not go remote. But if IMMND is down,
  441        then it is highly likely that immOiHandle is stale marked.
  442        The reactive resurrect will fail as long as IMMND is down.
  443     */
  444     TRACE_2("ERR_TRY_AGAIN: IMMND_DOWN");
  445     return SA_AIS_ERR_TRY_AGAIN;
  446   }
  447 
  448   *selectionObject = (-1); /* Ensure non valid descriptor in case of failure. */
  449 
  450   /* Take the CB lock */
  451   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
  452     TRACE_4("ERR_LIBRARY: LOCK failed");
  453     rc = SA_AIS_ERR_LIBRARY;
  454     goto lock_fail;
  455   }
  456   /* locked == true already */
  457 
  458   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
  459 
  460   if (!cl_node || cl_node->isOm) {
  461     TRACE_2("ERR_BAD_HANDLE: Bad handle %llx", immOiHandle);
  462     rc = SA_AIS_ERR_BAD_HANDLE;
  463     goto node_not_found;
  464   }
  465   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
  466     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
  467     rc = SA_AIS_ERR_UNAVAILABLE;
  468     goto clm_left;
  469   }
  470 
  471   if (cl_node->stale) {
  472     TRACE_1("Handle %llx is stale", immOiHandle);
  473     bool resurrected = imma_oi_resurrect(cb, cl_node, &locked, &rc);
  474     if (rc == SA_AIS_ERR_TRY_AGAIN) {
  475       goto resurrect_failed;
  476     }
  477 
  478     if (!locked &&
  479         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
  480       TRACE_4("ERR_LIBRARY: LOCK failed");
  481       rc = SA_AIS_ERR_LIBRARY;
  482       goto lock_fail;
  483     }
  484     locked = true;
  485 
  486     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
  487 
  488     if (!resurrected || !cl_node || cl_node->isOm || cl_node->stale) {
  489       TRACE_2("ERR_BAD_HANDLE: Reactive ressurect of handle %llx failed",
  490               immOiHandle);
  491       if (cl_node && cl_node->stale) {
  492         cl_node->exposed = true;
  493       }
  494       rc = SA_AIS_ERR_BAD_HANDLE;
  495       goto resurrect_failed;
  496     }
  497 
  498     TRACE_1("Reactive resurrect of handle %llx succeeded", immOiHandle);
  499   }
  500 
  501   *selectionObject = (SaSelectionObjectT)m_GET_FD_FROM_SEL_OBJ(
  502       m_NCS_IPC_GET_SEL_OBJ(&cl_node->callbk_mbx));
  503 
  504   cl_node->selObjUsable = true;
  505 
  506 clm_left:
  507 node_not_found:
  508 resurrect_failed:
  509   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
  510 
  511 lock_fail:
  512   TRACE_LEAVE();
  513   return rc;
  514 }
  515 
  516 /****************************************************************************
  517   Name          :  saImmOiDispatch
  518 
  519   Description   :  This function invokes, in the context of the calling
  520                    thread, pending callbacks for the handle immOiHandle in a
  521                    way that is specified by the dispatchFlags parameter.
  522 
  523   Arguments     :  immOiHandle - IMM OI Service handle
  524                    dispatchFlags - Flags that specify the callback execution
  525                                    behaviour of this function.
  526 
  527   Return Values :  Refer to SAI-AIS specification for various return values.
  528 
  529   Notes         :
  530 ******************************************************************************/
  531 SaAisErrorT saImmOiDispatch(SaImmOiHandleT immOiHandle,
  532                             SaDispatchFlagsT dispatchFlags) {
  533   SaAisErrorT rc = SA_AIS_OK;
  534   IMMA_CB *cb = &imma_cb;
  535   IMMA_CLIENT_NODE *cl_node = 0;
  536   bool locked = false;
  537   uint32_t pend_fin = 0;
  538   uint32_t pend_dis = 0;
  539   TRACE_ENTER();
  540 
  541   if (cb->sv_id == 0) {
  542     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
  543     rc = SA_AIS_ERR_BAD_HANDLE;
  544     goto fail;
  545   }
  546 
  547   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
  548     TRACE_4("ERR_LIBRARY: LOCK failed");
  549     rc = SA_AIS_ERR_LIBRARY;
  550     goto fail;
  551   }
  552   locked = true;
  553 
  554   /* get the client_info */
  555   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
  556   if (!cl_node || cl_node->isOm) {
  557     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
  558     rc = SA_AIS_ERR_BAD_HANDLE;
  559     goto fail;
  560   }
  561 
  562   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
  563     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
  564     rc = SA_AIS_ERR_UNAVAILABLE;
  565     goto clm_left;
  566   }
  567 
  568   if (cl_node->stale) {
  569     TRACE_1("Handle %llx is stale, trying to resurrect it.", immOiHandle);
  570 
  571     if (cb->dispatch_clients_to_resurrect == 0) {
  572       rc = SA_AIS_ERR_BAD_HANDLE;
  573       cl_node->exposed = true;
  574       goto fail;
  575     }
  576 
  577     --(cb->dispatch_clients_to_resurrect);
  578     TRACE_1("Remaining clients to acively resurrect: %d",
  579             cb->dispatch_clients_to_resurrect);
  580 
  581     if (!imma_oi_resurrect(cb, cl_node, &locked, &rc)) {
  582       if (rc != SA_AIS_ERR_TRY_AGAIN) {
  583         TRACE_2(
  584             "ERR_BAD_HANDLE: Failed to resurrect stale OI handle <c:%u, n:%x>",
  585             m_IMMSV_UNPACK_HANDLE_HIGH(immOiHandle),
  586             m_IMMSV_UNPACK_HANDLE_LOW(immOiHandle));
  587         rc = SA_AIS_ERR_BAD_HANDLE;
  588       }
  589       goto fail;
  590     }
  591 
  592     TRACE_1("Successfully resurrected OI handle <c:%u, n:%x>",
  593             m_IMMSV_UNPACK_HANDLE_HIGH(immOiHandle),
  594             m_IMMSV_UNPACK_HANDLE_LOW(immOiHandle));
  595 
  596     if (!locked &&
  597         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
  598       TRACE_4("ERR_LIBRARY: Lock failure");
  599       rc = SA_AIS_ERR_LIBRARY;
  600       goto fail;
  601     }
  602     locked = true;
  603 
  604     /* get the client again. */
  605     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
  606     if (!cl_node || cl_node->isOm) {
  607       TRACE_2(
  608           "ERR_BAD_HANDLE: client_node_get failed AFTER successfull  resurrect!");
  609       rc = SA_AIS_ERR_BAD_HANDLE;
  610       goto fail;
  611     }
  612 
  613     if (cl_node->stale) {
  614       TRACE_2(
  615           "ERR_BAD_HANDLE: client became stale AGAIN after successfull resurrect!");
  616       cl_node->exposed = true;
  617       rc = SA_AIS_ERR_BAD_HANDLE;
  618       goto fail;
  619     }
  620 
  621     cl_node->selObjUsable = true; /* success */
  622   }
  623 
  624   /* Back to normal case of non stale (possibly resurrected) handle. */
  625   /* Unlock & do the dispatch to avoid deadlock in arrival callback. */
  626   if (locked) {
  627     m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
  628     locked = false;
  629   }
  630   cl_node = NULL; /*Prevent unsafe use.*/
  631   /* unlocked */
  632 
  633   /* Increment Dispatch usgae count */
  634   cb->pend_dis++;
  635 
  636   switch (dispatchFlags) {
  637     case SA_DISPATCH_ONE:
  638       rc = imma_hdl_callbk_dispatch_one(cb, immOiHandle);
  639       break;
  640 
  641     case SA_DISPATCH_ALL:
  642       rc = imma_hdl_callbk_dispatch_all(cb, immOiHandle);
  643       break;
  644 
  645     case SA_DISPATCH_BLOCKING:
  646       rc = imma_hdl_callbk_dispatch_block(cb, immOiHandle);
  647       break;
  648 
  649     default:
  650       rc = SA_AIS_ERR_INVALID_PARAM;
  651       break;
  652   } /* switch */
  653 
  654   /* Decrement Dispatch usage count */
  655   cb->pend_dis--;
  656 
  657   /* can't use cb after we do agent shutdown, so copy all counts */
  658   pend_dis = cb->pend_dis;
  659   pend_fin = cb->pend_fin;
  660 
  661 clm_left:
  662 fail:
  663   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
  664 
  665   /* see if we are still in any dispatch context */
  666   if (pend_dis == 0) {
  667     while (pend_fin != 0) {
  668       /* call agent shutdown,for each finalize done before */
  669       cb->pend_fin--;
  670       imma_shutdown(NCSMDS_SVC_ID_IMMA_OI);
  671       pend_fin--;
  672     }
  673   }
  674   TRACE_LEAVE();
  675   return rc;
  676 }
  677 
  678 /****************************************************************************
  679   Name          :  saImmOiFinalize
  680 
  681   Description   :  This function closes the association, represented by
  682                    immOiHandle, between the invoking process and the IMM OI
  683                    service.
  684 
  685   Arguments     :  immOiHandle - IMM OI Service handle.
  686 
  687   Return Values :  Refer to SAI-AIS specification for various return values.
  688 
  689   Notes         :
  690 ******************************************************************************/
  691 SaAisErrorT saImmOiFinalize(SaImmOiHandleT immOiHandle) {
  692   SaAisErrorT rc = SA_AIS_OK;
  693   IMMA_CB *cb = &imma_cb;
  694   IMMSV_EVT finalize_evt;
  695   IMMSV_EVT *out_evt = NULL;
  696   IMMA_CLIENT_NODE *cl_node = 0;
  697   uint32_t proc_rc = NCSCC_RC_SUCCESS;
  698   bool locked = true;
  699   bool agent_flag = false; /* flag = false, we should not call agent shutdown */
  700   SaTimeT timeout = 0;
  701   TRACE_ENTER();
  702 
  703   if (cb->sv_id == 0) {
  704     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
  705     return SA_AIS_ERR_BAD_HANDLE;
  706   }
  707 
  708   /* No check for immnd_up here because this is finalize, see below. */
  709 
  710   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
  711     TRACE_4("ERR_LIBRARY: LOCK failed");
  712     rc = SA_AIS_ERR_LIBRARY;
  713     goto lock_fail;
  714   }
  715   /* locked == true already */
  716 
  717   /* get the client_info */
  718   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
  719   if (!cl_node || cl_node->isOm) {
  720     rc = SA_AIS_ERR_BAD_HANDLE;
  721     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
  722     goto node_not_found;
  723   }
  724 
  725   /*Increment before stale check to get uniform stale handling
  726     before and after send (see stale_handle:)
  727   */
  728   if ((rc = imma_proc_increment_pending_reply(cl_node, true)) != SA_AIS_OK) {
  729     TRACE_4(
  730         "ERR_LIBRARY: Overlapping use of IMM OI handle by multiple threads");
  731     goto bad_sync;
  732   }
  733 
  734   if (cl_node->stale) {
  735     TRACE_1("Handle %llx is stale", immOiHandle);
  736     rc = SA_AIS_OK; /* Dont punish the client for closing stale handle */
  737     /* Dont try to resurrect since this is finalize. */
  738     cl_node->exposed = true;
  739     goto stale_handle;
  740   }
  741 
  742   timeout = cl_node->syncr_timeout;
  743 
  744   /* populate the structure */
  745   memset(&finalize_evt, 0, sizeof(IMMSV_EVT));
  746   finalize_evt.type = IMMSV_EVT_TYPE_IMMND;
  747   finalize_evt.info.immnd.type = IMMND_EVT_A2ND_IMM_OI_FINALIZE;
  748   finalize_evt.info.immnd.info.finReq.client_hdl = cl_node->handle;
  749 
  750   /* Unlock before MDS Send */
  751   m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
  752   locked = false;
  753   cl_node = NULL; /* avoid unsafe use */
  754 
  755   if (cb->is_immnd_up == false) {
  756     TRACE_3("IMMND is DOWN");
  757     /* IF IMMND IS DOWN then we know handle is stale.
  758        Since this is a handle finalize, we simply discard the handle.
  759        No error return!
  760      */
  761     goto stale_handle;
  762   }
  763 
  764   /* send the request to the IMMND */
  765   proc_rc = imma_mds_msg_sync_send(cb->imma_mds_hdl, &(cb->immnd_mds_dest),
  766                                    &finalize_evt, &out_evt, timeout);
  767 
  768   /* MDS error handling */
  769   switch (proc_rc) {
  770     case NCSCC_RC_SUCCESS:
  771       break;
  772     case NCSCC_RC_REQ_TIMOUT:
  773       TRACE_3("Got ERR_TIMEOUT in saImmOiFinalize - ignoring");
  774       /* Yes could be a stale handle, but this is handle finalize.
  775          Dont cause unnecessary problems by returning an error code.
  776          If this is a true timeout caused by an unusually sluggish but
  777          up IMMND, then this connection at the IMMND side may linger,
  778          but on this IMMA side we will drop it.
  779       */
  780       goto stale_handle;
  781 
  782     default:
  783       TRACE_4("ERR_LIBRARY: MDS returned unexpected error code %u", proc_rc);
  784       rc = SA_AIS_ERR_LIBRARY;
  785       /* We lose the pending reply count in this case but ERR_LIBRARY dominates.
  786        */
  787       goto mds_send_fail;
  788   }
  789 
  790   /* Read the received error (if any)  */
  791   if (out_evt) {
  792     rc = out_evt->info.imma.info.errRsp.error;
  793     free(out_evt);
  794     out_evt = NULL;
  795     if (rc == SA_AIS_ERR_BAD_HANDLE) {
  796       rc = SA_AIS_OK;
  797       /* Client was already gone in local immnd server, but client node
  798          still present in the imma library. This can happen as a result
  799          of timeout on syncronous downcall. Continue the finalize here
  800          in the library to deallocate the client-node in the library.
  801          No need to disturb the client doing this finalize, return OK.
  802       */
  803     }
  804 
  805   } else {
  806     /* rc = SA_AIS_ERR_LIBRARY
  807        This is a finalize, no point in disturbing the user with
  808        a communication error.
  809     */
  810     TRACE_3("Received empty reply from server");
  811   }
  812 
  813 stale_handle:
  814   /* Do the finalize processing at IMMA */
  815   if (rc == SA_AIS_OK) {
  816     /* Take the CB lock  */
  817     if (!locked &&
  818         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
  819       rc = SA_AIS_ERR_LIBRARY;
  820       /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
  821       TRACE_4("ERR_LIBRARY: LOCK failed");
  822       goto lock_fail1;
  823     }
  824 
  825     locked = true;
  826 
  827     /* get the client_info */
  828     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
  829     if (!cl_node || cl_node->isOm) {
  830       /*rc = SA_AIS_ERR_BAD_HANDLE; This is finalize*/
  831       TRACE_3("client_node_get failed");
  832       goto node_not_found;
  833     }
  834 
  835     if (cl_node->stale) {
  836       TRACE_1("Handle %llx is stale", immOiHandle);
  837       /*Dont punish the client for closing stale handle rc == SA_AIS_OK */
  838 
  839       cl_node->exposed = true; /* But dont resurrect it either. */
  840     }
  841 
  842     imma_proc_decrement_pending_reply(cl_node, true);
  843     imma_finalize_client(cb, cl_node);
  844 
  845     /* Finalize the environment */
  846     if (cb->pend_dis == 0) {
  847       agent_flag = true;
  848     } else if (cb->pend_dis > 0) {
  849       cb->pend_fin++;
  850     }
  851   }
  852 
  853 lock_fail1:
  854 mds_send_fail:
  855 node_not_found:
  856 bad_sync:
  857   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
  858 
  859 lock_fail:
  860   if (rc == SA_AIS_OK) {
  861     /* we are not in any dispatch context, we can do agent shutdown */
  862     if (agent_flag == true)
  863       if (NCSCC_RC_SUCCESS != imma_shutdown(NCSMDS_SVC_ID_IMMA_OI)) {
  864         TRACE_4("ERR_LIBRARY: Call to imma_shutdown failed");
  865         rc = SA_AIS_ERR_LIBRARY;
  866       }
  867   }
  868   TRACE_LEAVE();
  869   return rc;
  870 }
  871 
  872 /****************************************************************************
  873   Name          :  saImmOiAdminOperationResult/_o2
  874 
  875   Description   :  Send the result for an admin-op, supposedly invoked inside
  876                    the upcall for an admin op.
  877                    This is normally a NON blocking call (except when
  878 resurrecting client)
  879 
  880   Arguments     :  immOiHandle - Same as A.02.01 spec.
  881                    invocation  - Same as A.02.01 spec.
  882                    result      - Same as A.02.01 spec.
  883                    returnParams- Parameters to return with the reply (new for
  884 A.2.11)
  885 
  886   Return Values :  Refer to SAI-AIS specification for various possible return
  887 codes. No new return codes for A.2.11 version, except SA_AIS_ERR_VERSION for the
  888 case when saImmOiAdminOperationResult_o2 is used but not with A.2.11 set for the
  889 immOihandle.
  890 
  891 ******************************************************************************/
  892 static SaAisErrorT admin_op_result_common(
  893     SaImmOiHandleT immOiHandle, SaInvocationT invocation, SaAisErrorT result,
  894     const SaImmAdminOperationParamsT_2 **returnParams, bool isA2bCall);
  895 
  896 SaAisErrorT saImmOiAdminOperationResult(SaImmOiHandleT immOiHandle,
  897                                         SaInvocationT invocation,
  898                                         SaAisErrorT result) {
  899   return admin_op_result_common(immOiHandle, invocation, result, NULL, false);
  900 }
  901 
  902 SaAisErrorT saImmOiAdminOperationResult_o2(
  903     SaImmOiHandleT immOiHandle, SaInvocationT invocation, SaAisErrorT result,
  904     const SaImmAdminOperationParamsT_2 **returnParams) {
  905   return admin_op_result_common(immOiHandle, invocation, result, returnParams,
  906                                 true);
  907 }
  908 
  909 static SaAisErrorT admin_op_result_common(
  910     SaImmOiHandleT immOiHandle, SaInvocationT invocation, SaAisErrorT result,
  911     const SaImmAdminOperationParamsT_2 **returnParams, bool isA2bCall) {
  912   SaAisErrorT rc = SA_AIS_OK;
  913   IMMA_CB *cb = &imma_cb;
  914   IMMSV_EVT adminOpRslt_evt;
  915   IMMA_CLIENT_NODE *cl_node = 0;
  916   uint32_t proc_rc = NCSCC_RC_SUCCESS;
  917   bool locked = true;
  918   bool errStringPar = false;
  919   /* Note NOT unsigned since negative means async invoc. */
  920   SaInt32T inv = m_IMMSV_UNPACK_HANDLE_LOW(invocation);
  921   SaInt32T owner = m_IMMSV_UNPACK_HANDLE_HIGH(invocation);
  922   TRACE_ENTER();
  923 
  924   if (cb->sv_id == 0) {
  925     /* Error return on AdminOperationResult => No reply is sent from OI.
  926        The OI is typically a server. Log this error instead of trace,
  927        to simplify troubleshooting for the OI maintainer.
  928      */
  929     LOG_IN("ERR_BAD_HANDLE: No initialized handle exists!");
  930     TRACE_LEAVE();
  931     return SA_AIS_ERR_BAD_HANDLE;
  932   }
  933 
  934   if (cb->is_immnd_up == false) {
  935     TRACE_2("ERR_TRY_AGAIN: IMMND_DOWN");
  936     TRACE_LEAVE();
  937     return SA_AIS_ERR_TRY_AGAIN;
  938   }
  939 
  940   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
  941     /* Log this error instead of trace, to simplify troubleshooting
  942        for the OI maintainer. */
  943     LOG_IN("ERR_LIBRARY: LOCK failed");
  944     rc = SA_AIS_ERR_LIBRARY;
  945     goto lock_fail;
  946   }
  947   /* locked == true already */
  948 
  949   /* get the client_info */
  950   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
  951   if (!cl_node || cl_node->isOm) {
  952     rc = SA_AIS_ERR_BAD_HANDLE;
  953     /* Log this error instead of trace, to simplify troubleshooting
  954        for the OI maintainer. */
  955     LOG_IN("ERR_BAD_HANDLE: client_node_get failed");
  956     goto node_not_found;
  957   }
  958   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
  959     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
  960     rc = SA_AIS_ERR_UNAVAILABLE;
  961     goto clm_left;
  962   }
  963 
  964   if (cl_node->stale) {
  965     TRACE_1("Handle %llx is stale", immOiHandle);
  966     bool resurrected = imma_oi_resurrect(cb, cl_node, &locked, &rc);
  967     if (rc == SA_AIS_ERR_TRY_AGAIN) {
  968       osafassert(!resurrected);
  969       goto stale_handle;
  970     }
  971 
  972     if (!locked &&
  973         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
  974       /* Log this error instead of trace, to simplify troubleshooting
  975          for the OI maintainer. */
  976       LOG_IN("ERR_LIBRARY: LOCK failed");
  977       rc = SA_AIS_ERR_LIBRARY;
  978       goto lock_fail;
  979     }
  980     locked = true;
  981 
  982     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
  983 
  984     if (!resurrected || !cl_node || cl_node->isOm || cl_node->stale) {
  985       /* Log this error instead of trace, to simplify troubleshooting
  986          for the OI maintainer. */
  987       LOG_IN("ERR_BAD_HANDLE: Reactive ressurect of handle %llx failed",
  988              immOiHandle);
  989       if (cl_node && cl_node->stale) {
  990         cl_node->exposed = true;
  991       }
  992       rc = SA_AIS_ERR_BAD_HANDLE;
  993       goto stale_handle;
  994     }
  995 
  996     TRACE_1("Reactive ressurect of handle %llx succeeded", immOiHandle);
  997   }
  998 
  999   if (isA2bCall && !(cl_node->isImmA2b)) {
 1000     rc = SA_AIS_ERR_VERSION;
 1001     TRACE_2(
 1002         "ERR_VERSION: saImmOmAdminOperationInvoke_o2 only supported for "
 1003         "A.02.11 and above");
 1004     goto stale_handle;
 1005   }
 1006 
 1007   if (cl_node->callbackInvocationSet.find(invocation)
 1008       == cl_node->callbackInvocationSet.end()) {
 1009     LOG_WA(
 1010         "ERR_INVALID_PARAM: Illegal SaInvocationT value provided in saImmOiAdminOperationResult");
 1011     rc = SA_AIS_ERR_INVALID_PARAM;
 1012     goto stale_handle;
 1013   } else {
 1014     cl_node->callbackInvocationSet.erase(invocation);
 1015   }
 1016 
 1017   /* populate the structure */
 1018   memset(&adminOpRslt_evt, 0, sizeof(IMMSV_EVT));
 1019   adminOpRslt_evt.type = IMMSV_EVT_TYPE_IMMND;
 1020   /*Need to encode async/sync variant. */
 1021   if (inv < 0) {
 1022     adminOpRslt_evt.info.immnd.type = returnParams
 1023                                           ? IMMND_EVT_A2ND_ASYNC_ADMOP_RSP_2
 1024                                           : IMMND_EVT_A2ND_ASYNC_ADMOP_RSP;
 1025   } else {
 1026     if (owner) {
 1027       adminOpRslt_evt.info.immnd.type =
 1028           returnParams ? IMMND_EVT_A2ND_ADMOP_RSP_2 : IMMND_EVT_A2ND_ADMOP_RSP;
 1029     } else {
 1030       TRACE_1("PBE_ADMOP_RSP");
 1031       if (!(cl_node->isPbe)) {
 1032         /* Log this error instead of trace, to simplify troubleshooting
 1033            for the OI maintainer. */
 1034         LOG_IN(
 1035             "ERR_INVALID_PARAM: Illegal SaInvocationT value provided in saImmOiAdminOperationResult");
 1036         rc = SA_AIS_ERR_INVALID_PARAM;
 1037         goto mds_send_fail;
 1038       }
 1039       adminOpRslt_evt.info.immnd.type = IMMND_EVT_A2ND_PBE_ADMOP_RSP;
 1040     }
 1041   }
 1042   adminOpRslt_evt.info.immnd.info.admOpRsp.oi_client_hdl = immOiHandle;
 1043   adminOpRslt_evt.info.immnd.info.admOpRsp.invocation = invocation;
 1044   adminOpRslt_evt.info.immnd.info.admOpRsp.result = result;
 1045   adminOpRslt_evt.info.immnd.info.admOpRsp.error = SA_AIS_OK;
 1046 
 1047   if (returnParams) {
 1048     const SaImmAdminOperationParamsT_2 *param = NULL;
 1049     int i;
 1050 
 1051     if (!(cl_node->isImmA2b)) {
 1052       /* Log this error instead of trace, to simplify troubleshooting
 1053          for the OI maintainer. */
 1054       LOG_IN(
 1055           "ERR_VERSION: saImmOiAdminOperationResult_o2 with return params"
 1056           "only allowed when handle is registered as A.2.11");
 1057       rc = SA_AIS_ERR_VERSION;
 1058       goto mds_send_fail;
 1059     }
 1060 
 1061     if (!imma_proc_is_adminop_params_valid(returnParams)) {
 1062       /* Log this error instead of trace, to simplify troubleshooting
 1063          for the OI maintainer. */
 1064       LOG_IN("ERR_INVALID_PARAM: Not a valid parameter for reply");
 1065       rc = SA_AIS_ERR_INVALID_PARAM;
 1066       goto mds_send_fail;
 1067     }
 1068 
 1069     osafassert(adminOpRslt_evt.info.immnd.info.admOpRsp.parms == NULL);
 1070     for (i = 0; returnParams[i]; ++i) {
 1071       param = returnParams[i];
 1072       /*alloc-a */
 1073       IMMSV_ADMIN_OPERATION_PARAM *p = (IMMSV_ADMIN_OPERATION_PARAM *)malloc(
 1074           sizeof(IMMSV_ADMIN_OPERATION_PARAM));
 1075       memset(p, 0, sizeof(IMMSV_ADMIN_OPERATION_PARAM));
 1076       TRACE("PARAM:%s \n", param->paramName);
 1077 
 1078       errStringPar = (strcmp(param->paramName, SA_IMM_PARAM_ADMOP_ERROR) == 0);
 1079       if (errStringPar && (param->paramType != SA_IMM_ATTR_SASTRINGT)) {
 1080         /* Log this error instead of trace, to simplify troubleshooting
 1081            for the OI maintainer. */
 1082         LOG_IN("ERR_INVALID_PARAM: Param %s must be of type SaStringT",
 1083                SA_IMM_PARAM_ADMOP_ERROR);
 1084         rc = SA_AIS_ERR_INVALID_PARAM;
 1085         free(p);
 1086         p = NULL;
 1087         goto mds_send_fail;
 1088       }
 1089 
 1090       if (errStringPar && (result == SA_AIS_OK)) {
 1091         /* Log this error instead of trace, to simplify troubleshooting
 1092            for the OI maintainer. */
 1093         LOG_IN(
 1094             "ERR_INVALID_PARAM: Param %s only allowed when result != SA_AIS_OK",
 1095             SA_IMM_PARAM_ADMOP_ERROR);
 1096         rc = SA_AIS_ERR_INVALID_PARAM;
 1097         free(p);
 1098         p = NULL;
 1099         goto mds_send_fail;
 1100       }
 1101 
 1102       p->paramName.size = strlen(param->paramName) + 1;
 1103       if (p->paramName.size >= IMMSV_MAX_PARAM_NAME_LENGTH) {
 1104         /* Log this error instead of trace, to simplify troubleshooting
 1105            for the OI maintainer. */
 1106         LOG_IN("ERR_INVALID_PARAM: Param name too long");
 1107         rc = SA_AIS_ERR_INVALID_PARAM;
 1108         free(p);
 1109         p = NULL;
 1110         goto mds_send_fail;
 1111       }
 1112       /*alloc-b */
 1113       p->paramName.buf = (char *)malloc(p->paramName.size);
 1114       strncpy(p->paramName.buf, param->paramName, p->paramName.size);
 1115 
 1116       p->paramType = param->paramType;
 1117       /*alloc-c */
 1118       imma_copyAttrValue(&(p->paramBuffer), param->paramType,
 1119                          param->paramBuffer);
 1120 
 1121       p->next =
 1122           adminOpRslt_evt.info.immnd.info.admOpRsp.parms; /*NULL initially. */
 1123       adminOpRslt_evt.info.immnd.info.admOpRsp.parms = p;
 1124     }
 1125   }
 1126 
 1127   if (cb->is_immnd_up == false) {
 1128     rc = SA_AIS_ERR_TRY_AGAIN;
 1129     /* IMMND must have gone down after we locked above */
 1130     TRACE_2("ERR_TRY_AGAIN: IMMND_DOWN");
 1131     goto mds_send_fail;
 1132   }
 1133 
 1134   /* send the reply to the IMMND ASYNCronously */
 1135   if (adminOpRslt_evt.info.immnd.type == IMMND_EVT_A2ND_PBE_ADMOP_RSP) {
 1136     proc_rc = imma_evt_fake_evs(cb, &adminOpRslt_evt, NULL, 0, cl_node->handle,
 1137                                 &locked, false);
 1138   } else {
 1139     /* Unlock before MDS Send */
 1140     m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 1141     locked = false;
 1142     cl_node = NULL; /* avoid unsafe use */
 1143 
 1144     proc_rc = imma_mds_msg_send(cb->imma_mds_hdl, &cb->immnd_mds_dest,
 1145                                 &adminOpRslt_evt, NCSMDS_SVC_ID_IMMND);
 1146   }
 1147 
 1148   /* MDS error handling */
 1149   switch (proc_rc) {
 1150     case NCSCC_RC_SUCCESS:
 1151       break;
 1152     case NCSCC_RC_REQ_TIMOUT:
 1153       /*The timeout case should be impossible on asyncronous send.. */
 1154       rc = SA_AIS_ERR_TIMEOUT;
 1155       goto mds_send_fail;
 1156     default:
 1157       /* Log this error instead of trace, to simplify troubleshooting
 1158          for the OI maintainer. */
 1159       LOG_IN("ERR_LIBRARY: MDS returned unexpected error code %u", proc_rc);
 1160       rc = SA_AIS_ERR_LIBRARY;
 1161       goto mds_send_fail;
 1162   }
 1163 
 1164 mds_send_fail:
 1165   while (adminOpRslt_evt.info.immnd.info.admOpRsp.parms) {
 1166     IMMSV_ADMIN_OPERATION_PARAM *p =
 1167         adminOpRslt_evt.info.immnd.info.admOpRsp.parms;
 1168     adminOpRslt_evt.info.immnd.info.admOpRsp.parms = p->next;
 1169 
 1170     if (p->paramName.buf) { /*free-b */
 1171       free(p->paramName.buf);
 1172       p->paramName.buf = NULL;
 1173     }
 1174     immsv_evt_free_att_val(&(p->paramBuffer),
 1175                            (SaImmValueTypeT)p->paramType); /*free-c */
 1176     p->next = NULL;
 1177     free(p); /*free-a */
 1178   }
 1179 
 1180 clm_left:
 1181 stale_handle:
 1182 node_not_found:
 1183 
 1184   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 1185 
 1186 lock_fail:
 1187   TRACE_LEAVE();
 1188   return rc;
 1189 }
 1190 
 1191 /****************************************************************************
 1192   Name          :  saImmOiImplementerSet
 1193 
 1194   Description   :  Initialize an object implementer, associating this process
 1195                    with an implementer name.
 1196                    This is a blocking call.
 1197 
 1198 
 1199   Arguments     :  immOiHandle - IMM OI handle
 1200                    implementerName - The name of the implementer.
 1201 
 1202   Dont need any library local implementerInstance corresponding to
 1203   say the adminowner instance of the OM-API. Because there is
 1204   nothing corresponding to the adminOwnerHandle.
 1205   Instead the fact that implementer has been set can be associated with
 1206   the immOiHandle.
 1207 
 1208   A given oi-handle can be associated with at most one implementer name.
 1209   This then means that any new invocation of this method using the same
 1210   immOiHandle must either return with error, or perform an implicit clear
 1211   of the previous implementer name. We choose to return error.
 1212 
 1213   Return Values :  Refer to SAI-AIS specification for various return values.
 1214 ******************************************************************************/
 1215 SaAisErrorT saImmOiImplementerSet(
 1216     SaImmOiHandleT immOiHandle, const SaImmOiImplementerNameT implementerName) {
 1217   SaAisErrorT rc = SA_AIS_OK;
 1218   IMMA_CB *cb = &imma_cb;
 1219   IMMSV_EVT evt;
 1220   IMMSV_EVT *out_evt = NULL;
 1221   IMMA_CLIENT_NODE *cl_node = NULL;
 1222   SaUint32T proc_rc = NCSCC_RC_SUCCESS;
 1223   bool locked = true;
 1224   SaUint32T nameLen = 0;
 1225   SaTimeT timeout = 0;
 1226 
 1227   if (cb->sv_id == 0) {
 1228     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
 1229     return SA_AIS_ERR_BAD_HANDLE;
 1230   }
 1231 
 1232   if ((implementerName == NULL) || (nameLen = strlen(implementerName)) == 0) {
 1233     TRACE_2(
 1234         "ERR_INVALID_PARAM: Parameter 'implementerName' is NULL, or is a "
 1235         "string of 0 length");
 1236     return SA_AIS_ERR_INVALID_PARAM;
 1237   }
 1238   ++nameLen; /*Add 1 for the null. */
 1239 
 1240   if (nameLen >= IMMSV_MAX_IMPL_NAME_LENGTH) {
 1241     TRACE_4("ERR_LIBRARY: Implementer name too long, size: %u max:%u", nameLen,
 1242             IMMSV_MAX_IMPL_NAME_LENGTH - 1);
 1243     return SA_AIS_ERR_LIBRARY;
 1244   }
 1245 
 1246   if (cb->is_immnd_up == false) {
 1247     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
 1248     return SA_AIS_ERR_TRY_AGAIN;
 1249   }
 1250 
 1251   /* get the CB Lock */
 1252   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 1253     rc = SA_AIS_ERR_LIBRARY;
 1254     TRACE_4("ERR_LIBRARY: Lock failed");
 1255     goto lock_fail;
 1256   }
 1257 
 1258   /*locked == true already */
 1259 
 1260   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 1261   if (!cl_node || cl_node->isOm) {
 1262     rc = SA_AIS_ERR_BAD_HANDLE;
 1263     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
 1264     goto bad_handle;
 1265   }
 1266   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
 1267     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
 1268     rc = SA_AIS_ERR_UNAVAILABLE;
 1269     goto clm_left;
 1270   }
 1271 
 1272   if (cl_node->mImplementerId) {
 1273     rc = SA_AIS_ERR_INVALID_PARAM;
 1274     /* This is a tricky one #3086. This is not the ERR_EXIST case.
 1275        The ERR_EXIST case is where this client is trying to
 1276        set implementer-name for the oi-handle and that
 1277        implementer-name is occupied by some *other* handle/user.
 1278        The problem here is that *this* handle is already occupied
 1279        with an implementer name, possibly the same name possibly
 1280        not. This is an interface violation since the OI is not
 1281        making sense in this request on the handle. Ideally this
 1282        should result in ERR_INVALID_PARAM. That error code
 1283        happens not to be allowed on saImmOiImplementerSet according
 1284        to SAF. The legal alternatives available are BAD_HANDLE or
 1285        ERR_LIBRARY, both of which are missleading. We choose to
 1286        return ERR_INVALID_PARAM. This is a deviation from the spec,
 1287        but only happens to an OI that is incorrectly implemented.
 1288      */
 1289     LOG_NO(
 1290         "ERR_INVALID_PARAM: Implementer %s already set for this handle "
 1291         "when trying to set %s",
 1292         cl_node->mImplementerName, implementerName);
 1293     goto bad_handle;
 1294   }
 1295 
 1296   if (cl_node->stale) {
 1297     TRACE_1("Handle %llx is stale", immOiHandle);
 1298     bool resurrected = imma_oi_resurrect(cb, cl_node, &locked, &rc);
 1299     if (rc == SA_AIS_ERR_TRY_AGAIN) {
 1300       osafassert(!resurrected);
 1301       goto bad_handle; /* Handle is actually not bad yet. */
 1302     }
 1303 
 1304     if (!locked &&
 1305         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 1306       TRACE_4("ERR_LIBRARY: LOCK failed");
 1307       rc = SA_AIS_ERR_LIBRARY;
 1308       goto lock_fail;
 1309     }
 1310     locked = true;
 1311 
 1312     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 1313 
 1314     if (!resurrected || !cl_node || cl_node->isOm || cl_node->stale) {
 1315       TRACE_2("ERR_BAD_HANDLE: Reactive ressurect of handle %llx failed",
 1316               immOiHandle);
 1317       if (cl_node && cl_node->stale) {
 1318         cl_node->exposed = true;
 1319       }
 1320       rc = SA_AIS_ERR_BAD_HANDLE;
 1321       goto bad_handle;
 1322     }
 1323 
 1324     TRACE_1("Reactive resurrect of handle %llx succeeded", immOiHandle);
 1325   }
 1326 
 1327   timeout = cl_node->syncr_timeout;
 1328 
 1329   /* Check for API Version! Appliers only allow for A.02.11 and above. */
 1330   if (implementerName[0] == '@') {
 1331     if (!(cl_node->isImmA2b)) {
 1332       rc = SA_AIS_ERR_VERSION;
 1333       TRACE_2("ERR_VERSION: Applier OIs only supported for A.02.11 and above");
 1334       goto bad_handle;
 1335     }
 1336 
 1337     /* Don't need to do extra check for iCallbkA2f.
 1338      * It has the same structure as iCallbk,
 1339      * and checks for iCallbk applies for iCallbkA2f */
 1340     if (cl_node->o.iCallbk.saImmOiCcbApplyCallback == NULL) {
 1341       rc = SA_AIS_ERR_INIT;
 1342       TRACE_2(
 1343           "ERR_INIT: The SaImmOiCcbApplyCallbackT "
 1344           "function was not set in the initialization of the handle "
 1345           "=> Can not register as applier!");
 1346       goto bad_handle;
 1347     }
 1348 
 1349     if (cl_node->o.iCallbk.saImmOiCcbAbortCallback == NULL) {
 1350       rc = SA_AIS_ERR_INIT;
 1351       TRACE_2(
 1352           "ERR_INIT: The SaImmOiCcbAbortCallbackT "
 1353           "function was not set in the initialization of the handle "
 1354           "=> Can not register as applier!");
 1355       goto bad_handle;
 1356     }
 1357 
 1358     if (cl_node->o.iCallbk.saImmOiCcbObjectModifyCallback == NULL) {
 1359       rc = SA_AIS_ERR_INIT;
 1360       TRACE_2(
 1361           "ERR_INIT: The SaImmOiCcbObjectModifyCallbackT "
 1362           "function was not set in the initialization of the handle "
 1363           "=> Can not register as applier!");
 1364       goto bad_handle;
 1365     }
 1366 
 1367     if (cl_node->o.iCallbk.saImmOiCcbObjectDeleteCallback == NULL) {
 1368       rc = SA_AIS_ERR_INIT;
 1369       TRACE_2(
 1370           "ERR_INIT: The SaImmOiCcbObjectDeleteCallbackT "
 1371           "function was not set in the initialization of the handle "
 1372           "=> Can not register as applier!");
 1373       goto bad_handle;
 1374     }
 1375     /* Optimistically turn on cl_node->isApplier since callbacks may arrive to
 1376        the mds thread before reply on the implementerSet request arrives back
 1377        here. If error is returned by implementerSet then isApplier is reset to 0
 1378        below.
 1379      */
 1380     cl_node->isApplier = 0x1;
 1381   }
 1382 
 1383   if ((strncmp(implementerName, OPENSAF_IMM_PBE_IMPL_NAME, nameLen) == 0) ||
 1384       (strncmp(implementerName, OPENSAF_IMM_2PBE_APPL_NAME, nameLen) == 0)) {
 1385     /* Optimistically turn on cl-node->isPbe since callbacks may arrive to the
 1386        mds thread before reply on the implementerSet request arrives back here.
 1387        If error is returned by implementerSet then isPbe is reset to 0 below.
 1388      */
 1389     TRACE("Special PBE implementer %s detected and noted.", implementerName);
 1390     cl_node->isPbe = 0x1;
 1391   }
 1392 
 1393   if ((rc = imma_proc_increment_pending_reply(cl_node, true)) != SA_AIS_OK) {
 1394     TRACE_4(
 1395         "ERR_LIBRARY: Overlapping use of IMM OI handle by multiple threads");
 1396     goto bad_handle;
 1397   }
 1398 
 1399   /* Populate & Send the Open Event to IMMND */
 1400   memset(&evt, 0, sizeof(IMMSV_EVT));
 1401   evt.type = IMMSV_EVT_TYPE_IMMND;
 1402   evt.info.immnd.info.implSet.client_hdl = immOiHandle;
 1403   evt.info.immnd.info.implSet.impl_name.size = nameLen;
 1404   evt.info.immnd.info.implSet.impl_name.buf = implementerName;
 1405 
 1406   if (cl_node->isImmA2e && cl_node->oiTimeout) {
 1407     evt.info.immnd.info.implSet.oi_timeout = cl_node->oiTimeout;
 1408     evt.info.immnd.type = IMMND_EVT_A2ND_OI_IMPL_SET_2;
 1409   } else {
 1410     evt.info.immnd.type = IMMND_EVT_A2ND_OI_IMPL_SET;
 1411   }
 1412 
 1413   /* Unlock before MDS Send */
 1414   m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 1415   locked = false;
 1416   cl_node = NULL; /* avoid unsafe use */
 1417 
 1418   if (cb->is_immnd_up == false) {
 1419     rc = SA_AIS_ERR_TRY_AGAIN;
 1420     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
 1421     goto mds_send_fail;
 1422   }
 1423 
 1424   /* Send the evt to IMMND */
 1425   proc_rc = imma_mds_msg_sync_send(cb->imma_mds_hdl, &(cb->immnd_mds_dest),
 1426                                    &evt, &out_evt, timeout);
 1427 
 1428   evt.info.immnd.info.implSet.impl_name.buf = NULL;
 1429   evt.info.immnd.info.implSet.impl_name.size = 0;
 1430 
 1431   /* Generate rc from proc_rc */
 1432   switch (proc_rc) {
 1433     case NCSCC_RC_SUCCESS:
 1434       break;
 1435     case NCSCC_RC_REQ_TIMOUT:
 1436       rc = imma_proc_check_stale(cb, immOiHandle, SA_AIS_ERR_TIMEOUT);
 1437       break; /* i.e. goto mds_send_fail */
 1438     default:
 1439       rc = SA_AIS_ERR_LIBRARY;
 1440       TRACE_4("ERR_LIBRARY: MDS returned unexpected error code %u", proc_rc);
 1441       /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
 1442       goto bad_handle;
 1443       break;
 1444   }
 1445 
 1446 mds_send_fail:
 1447 
 1448   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 1449     rc = SA_AIS_ERR_LIBRARY;
 1450     /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
 1451     TRACE_4("ERR_LIBRARY: Lock failed");
 1452     goto lock_fail;
 1453   }
 1454   locked = true;
 1455 
 1456   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 1457   if (!cl_node || cl_node->isOm) {
 1458     rc = SA_AIS_ERR_BAD_HANDLE;
 1459     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
 1460     goto bad_handle;
 1461   }
 1462 
 1463   imma_proc_decrement_pending_reply(cl_node, true);
 1464 
 1465   if (cl_node->stale) {
 1466     TRACE_1("Handle %llx is stale after successfull call", immOiHandle);
 1467     /* This is implementer set => user expects this to be
 1468        upheld, handle is stale but implementorship SURVIVES
 1469        resurrection. But we can not reply ok on this call since
 1470        we should make the user aware that they are actually detached
 1471        from the implementership that this call could have established
 1472      */
 1473     rc = SA_AIS_ERR_BAD_HANDLE;
 1474     cl_node->exposed = true;
 1475     goto bad_handle;
 1476   }
 1477 
 1478   if (out_evt) {
 1479     /* Process the received Event */
 1480     osafassert(out_evt->type == IMMSV_EVT_TYPE_IMMA);
 1481     osafassert(out_evt->info.imma.type == IMMA_EVT_ND2A_IMPLSET_RSP);
 1482     if (rc == SA_AIS_OK) {
 1483       rc = out_evt->info.imma.info.implSetRsp.error;
 1484       if (rc == SA_AIS_OK) {
 1485         cl_node->mImplementerId = out_evt->info.imma.info.implSetRsp.implId;
 1486         cl_node->mImplementerName = (char *)calloc(1, nameLen);
 1487         strncpy(cl_node->mImplementerName, implementerName, nameLen);
 1488       }
 1489     }
 1490   }
 1491 
 1492   /* Revert any flags set optimistically.
 1493    *
 1494    * In case of SA_AIS_ERR_TIMEOUT, we don't revert the flag to prevent
 1495    * the library from crashing when receiving upcalls.
 1496    *
 1497    * cl_node->mImplementerId is not set in case of errors, so clients
 1498    * have to either finalize the handle or retry to set implementer.
 1499    */
 1500   if (rc != SA_AIS_OK && rc != SA_AIS_ERR_TIMEOUT && cl_node) {
 1501     cl_node->isApplier = 0x0;
 1502     cl_node->isPbe = 0x0;
 1503   }
 1504 
 1505 clm_left:
 1506 bad_handle:
 1507   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 1508 
 1509 lock_fail:
 1510   if (out_evt) free(out_evt);
 1511 
 1512   return rc;
 1513 }
 1514 
 1515 /****************************************************************************
 1516   Name          :  saImmOiImplementerClear
 1517 
 1518   Description   :  Clear implementer. Severs the association between
 1519                    this process/connection and the implementer name set
 1520                    by saImmOiImplementerSet.
 1521                    This is a blocking call.
 1522 
 1523 
 1524   Arguments     :  immOiHandle - IMM OI handle
 1525 
 1526   This call will fail if not a prior call to implementerSet has been made.
 1527 
 1528   Return Values :  Refer to SAI-AIS specification for various return values.
 1529 ******************************************************************************/
 1530 SaAisErrorT saImmOiImplementerClear(SaImmOiHandleT immOiHandle) {
 1531   SaAisErrorT rc = SA_AIS_OK;
 1532   IMMA_CB *cb = &imma_cb;
 1533   IMMSV_EVT evt;
 1534   IMMSV_EVT *out_evt = NULL;
 1535   IMMA_CLIENT_NODE *cl_node = NULL;
 1536   bool locked = true;
 1537 
 1538   if (cb->sv_id == 0) {
 1539     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
 1540     return SA_AIS_ERR_BAD_HANDLE;
 1541   }
 1542 
 1543   if (cb->is_immnd_up == false) {
 1544     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
 1545     return SA_AIS_ERR_TRY_AGAIN;
 1546   }
 1547 
 1548   /* get the CB Lock */
 1549   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 1550     rc = SA_AIS_ERR_LIBRARY;
 1551     TRACE_4("ERR_LIBRARY: Lock failed");
 1552     goto lock_fail;
 1553   }
 1554 
 1555   /*locked == true already */
 1556 
 1557   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 1558   if (!cl_node || cl_node->isOm) {
 1559     rc = SA_AIS_ERR_BAD_HANDLE;
 1560     goto bad_handle;
 1561   }
 1562   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
 1563     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
 1564     rc = SA_AIS_ERR_UNAVAILABLE;
 1565     goto clm_left;
 1566   }
 1567 
 1568   if (cl_node->mImplementerId == 0) {
 1569     rc = SA_AIS_ERR_BAD_HANDLE;
 1570     /* Yes BAD_HANDLE and not ERR_EXIST, see standard. */
 1571     TRACE_2("ERR_BAD_HANDLE: No implementer is set for this handle");
 1572     goto bad_handle;
 1573   }
 1574 
 1575   if (cl_node->stale) {
 1576     TRACE_1("Handle %llx is stale", immOiHandle);
 1577     /* Note that this is implementer clear. We dont want a resurrect to
 1578        set implementer, just so we can clear it right after!
 1579        Furthermore we know that the implementer-name is already cleared
 1580        (detached) from this handle by the stale marking event.
 1581        All that needs to be done is to clear the implementer id and
 1582        name from the client node. We dont try to resurrect here since
 1583        we dont need to. Instead the client is left as stale but not yet
 1584        exposed.
 1585      */
 1586     osafassert(rc == SA_AIS_OK);
 1587     goto skip_impl_clear;
 1588   }
 1589 
 1590   if ((rc = imma_proc_increment_pending_reply(cl_node, true)) != SA_AIS_OK) {
 1591     TRACE_4(
 1592         "ERR_LIBRARY: Overlapping use of IMM OI handle by multiple threads");
 1593     goto bad_handle;
 1594   }
 1595 
 1596   /* Populate & Send the Open Event to IMMND */
 1597   memset(&evt, 0, sizeof(IMMSV_EVT));
 1598   evt.type = IMMSV_EVT_TYPE_IMMND;
 1599   evt.info.immnd.type = IMMND_EVT_A2ND_OI_IMPL_CLR;
 1600   evt.info.immnd.info.implSet.client_hdl = immOiHandle;
 1601   evt.info.immnd.info.implSet.impl_id = cl_node->mImplementerId;
 1602 
 1603   rc = imma_evt_fake_evs(cb, &evt, &out_evt, cl_node->syncr_timeout,
 1604                          cl_node->handle, &locked, false);
 1605 
 1606   cl_node = NULL;
 1607   /* Take the CB lock  */
 1608   if (!locked && m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 1609     rc = SA_AIS_ERR_LIBRARY;
 1610     /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
 1611     TRACE_4("ERR_LIBRARY: LOCK failed");
 1612     goto lock_fail1;
 1613   }
 1614   locked = true;
 1615 
 1616   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 1617   if (!cl_node || cl_node->isOm) {
 1618     rc = SA_AIS_ERR_BAD_HANDLE;
 1619     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
 1620     goto bad_handle;
 1621   }
 1622 
 1623   imma_proc_decrement_pending_reply(cl_node, true);
 1624 
 1625   if (rc != SA_AIS_OK) {
 1626     /* fake_evs returned error */
 1627     goto skip_impl_clear;
 1628   }
 1629 
 1630   if (cl_node->stale) {
 1631     TRACE_1("Handle %llx is stale after successfull call - ignoring",
 1632             immOiHandle);
 1633     /*
 1634       This is implementer clear => a relaxation
 1635       => not necessary to expose when the call succeeded.
 1636       rc = SA_AIS_ERR_BAD_HANDLE;
 1637       cl_node->exposed = true;
 1638       goto bad_handle;
 1639     */
 1640   }
 1641 
 1642   osafassert(out_evt);
 1643   /* Process the received Event */
 1644   osafassert(out_evt->type == IMMSV_EVT_TYPE_IMMA);
 1645   osafassert(out_evt->info.imma.type == IMMA_EVT_ND2A_IMM_ERROR);
 1646 
 1647   rc = out_evt->info.imma.info.errRsp.error;
 1648 
 1649 skip_impl_clear:
 1650   if (rc == SA_AIS_OK) {
 1651     cl_node->mImplementerId = 0;
 1652     free(cl_node->mImplementerName);
 1653     cl_node->mImplementerName = NULL;
 1654     if (cl_node->isApplier) cl_node->isApplier = 0;
 1655   }
 1656 
 1657 clm_left:
 1658 bad_handle:
 1659   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 1660 
 1661 lock_fail1:
 1662   if (out_evt) free(out_evt);
 1663 
 1664 lock_fail:
 1665 
 1666   return rc;
 1667 }
 1668 
 1669 /****************************************************************************
 1670   Name          :  saImmOiClassImplementerSet
 1671 
 1672   Description   :  Set implementer for class and all instances.
 1673                    This is a blocking call.
 1674 
 1675 
 1676   Arguments     :  immOiHandle - IMM OI handle
 1677                    className - The name of the class.
 1678 
 1679   This call will fail if not a prior call to implementerSet has been made.
 1680 
 1681   Return Values :  Refer to SAI-AIS specification for various return values.
 1682 ******************************************************************************/
 1683 SaAisErrorT saImmOiClassImplementerSet(SaImmOiHandleT immOiHandle,
 1684                                        const SaImmClassNameT className) {
 1685   SaAisErrorT rc = SA_AIS_OK;
 1686   IMMA_CB *cb = &imma_cb;
 1687   IMMSV_EVT evt;
 1688   IMMSV_EVT *out_evt = NULL;
 1689   IMMA_CLIENT_NODE *cl_node = NULL;
 1690   bool locked = true;
 1691   SaUint32T nameLen = 0;
 1692 
 1693   if (cb->sv_id == 0) {
 1694     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
 1695     return SA_AIS_ERR_BAD_HANDLE;
 1696   }
 1697 
 1698   if ((className == NULL) || (nameLen = strlen(className)) == 0) {
 1699     TRACE_2("ERR_INVALID_PARAM: Parameter 'className' is NULL or has length 0");
 1700     return SA_AIS_ERR_INVALID_PARAM;
 1701   }
 1702   ++nameLen; /*Add 1 for the null. */
 1703 
 1704   if (nameLen >= IMMSV_MAX_CLASS_NAME_LENGTH) {
 1705     TRACE_4("ERR_LIBRARY: ClassName too long, size: %u max:%u", nameLen,
 1706             IMMSV_MAX_CLASS_NAME_LENGTH - 1);
 1707     return SA_AIS_ERR_LIBRARY;
 1708   }
 1709 
 1710   if (cb->is_immnd_up == false) {
 1711     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
 1712     return SA_AIS_ERR_TRY_AGAIN;
 1713   }
 1714 
 1715   /* get the CB Lock */
 1716   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 1717     rc = SA_AIS_ERR_LIBRARY;
 1718     TRACE_4("ERR_LIBRARY: Lock failed");
 1719     goto lock_fail;
 1720   }
 1721 
 1722   /*locked == true already */
 1723 
 1724   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 1725   if (!cl_node || cl_node->isOm) {
 1726     rc = SA_AIS_ERR_BAD_HANDLE;
 1727     goto bad_handle;
 1728   }
 1729   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
 1730     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
 1731     rc = SA_AIS_ERR_UNAVAILABLE;
 1732     goto clm_left;
 1733   }
 1734 
 1735   if (cl_node->stale) {
 1736     TRACE_1("Handle %llx is stale", immOiHandle);
 1737     bool resurrected = imma_oi_resurrect(cb, cl_node, &locked, &rc);
 1738     if (rc == SA_AIS_ERR_TRY_AGAIN) {
 1739       osafassert(!resurrected);
 1740       goto bad_handle; /* Handle is actually not bad yet. */
 1741     }
 1742 
 1743     if (!locked &&
 1744         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 1745       TRACE_4("ERR_LIBRARY: LOCK failed");
 1746       rc = SA_AIS_ERR_LIBRARY;
 1747       goto lock_fail;
 1748     }
 1749     locked = true;
 1750 
 1751     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 1752 
 1753     if (!resurrected || !cl_node || cl_node->isOm || cl_node->stale) {
 1754       TRACE_2("ERR_BAD_HANDLE: Reactive ressurect of handle %llx failed",
 1755               immOiHandle);
 1756       if (cl_node && cl_node->stale) {
 1757         cl_node->exposed = true;
 1758       }
 1759       rc = SA_AIS_ERR_BAD_HANDLE;
 1760       goto bad_handle;
 1761     }
 1762 
 1763     TRACE_1("Reactive resurrect of handle %llx succeeded", immOiHandle);
 1764   }
 1765 
 1766   if (cl_node->mImplementerId == 0) {
 1767     rc = SA_AIS_ERR_BAD_HANDLE;
 1768     TRACE_2("ERR_BAD_HANDLE: No implementer is set for this handle");
 1769     goto bad_handle;
 1770   }
 1771 
 1772   if (cl_node->isApplier) {
 1773     if (cl_node->o.iCallbk.saImmOiCcbObjectCreateCallback == NULL) {
 1774       rc = SA_AIS_ERR_INIT;
 1775       TRACE_2(
 1776           "ERR_INIT: The SaImmOiCcbObjectCreateCallbackT "
 1777           "function was not set in the initialization of the handle "
 1778           "=> Can not register as class applier!");
 1779       goto bad_handle;
 1780     }
 1781   }
 1782 
 1783   if ((rc = imma_proc_increment_pending_reply(cl_node, true)) != SA_AIS_OK) {
 1784     TRACE_4(
 1785         "ERR_LIBRARY: Overlapping use of IMM OI handle by multiple threads");
 1786     goto bad_handle;
 1787   }
 1788 
 1789   /* Populate & Send the Open Event to IMMND */
 1790   memset(&evt, 0, sizeof(IMMSV_EVT));
 1791   evt.type = IMMSV_EVT_TYPE_IMMND;
 1792   evt.info.immnd.type = IMMND_EVT_A2ND_OI_CL_IMPL_SET;
 1793   evt.info.immnd.info.implSet.client_hdl = cl_node->handle;
 1794   evt.info.immnd.info.implSet.impl_name.size = nameLen;
 1795   evt.info.immnd.info.implSet.impl_name.buf = className;
 1796   evt.info.immnd.info.implSet.impl_id = cl_node->mImplementerId;
 1797 
 1798   rc = imma_evt_fake_evs(cb, &evt, &out_evt, cl_node->syncr_timeout,
 1799                          cl_node->handle, &locked, true);
 1800 
 1801   cl_node = NULL;
 1802   evt.info.immnd.info.implSet.impl_name.buf = NULL;
 1803   evt.info.immnd.info.implSet.impl_name.size = 0;
 1804 
 1805   if (!locked && m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 1806     rc = SA_AIS_ERR_LIBRARY; /* Overwrites any error from fake_evs() */
 1807     /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
 1808     TRACE_4("ERR_LIBRARY: LOCK failed");
 1809     goto lock_fail;
 1810   }
 1811   locked = true;
 1812 
 1813   /* get the client_info */
 1814   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 1815   if (!cl_node || cl_node->isOm) {
 1816     rc = SA_AIS_ERR_BAD_HANDLE;
 1817     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
 1818     goto bad_handle;
 1819   }
 1820 
 1821   imma_proc_decrement_pending_reply(cl_node, true);
 1822 
 1823   if (rc != SA_AIS_OK) {
 1824     /* fake_evs returned error */
 1825     goto fevs_error;
 1826   }
 1827 
 1828   if (cl_node->stale) {
 1829     TRACE_3("Handle %llx is stale after successfull call", immOiHandle);
 1830 
 1831     /* This is class implementer set => user expects this to be
 1832        upheld, but handle is stale => exposed.
 1833      */
 1834     rc = SA_AIS_ERR_BAD_HANDLE;
 1835     cl_node->exposed = true;
 1836     goto bad_handle;
 1837   }
 1838 
 1839   osafassert(out_evt);
 1840   /* Process the received Event */
 1841   osafassert(out_evt->type == IMMSV_EVT_TYPE_IMMA);
 1842   osafassert(out_evt->info.imma.type == IMMA_EVT_ND2A_IMM_ERROR);
 1843   rc = out_evt->info.imma.info.errRsp.error;
 1844 
 1845 fevs_error:
 1846 bad_handle:
 1847 clm_left:
 1848   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 1849 
 1850 lock_fail:
 1851   if (out_evt) free(out_evt);
 1852 
 1853   return rc;
 1854 }
 1855 
 1856 /****************************************************************************
 1857   Name          :  saImmOiClassImplementerRelease
 1858 
 1859   Description   :  Release implementer for class and all instances.
 1860                    This is a blocking call.
 1861 
 1862 
 1863   Arguments     :  immOiHandle - IMM OI handle
 1864                    className - The name of the class.
 1865 
 1866   This call will fail if not a prior call to ClassImplementerSet has been made.
 1867 
 1868   Return Values :  Refer to SAI-AIS specification for various return values.
 1869 ******************************************************************************/
 1870 SaAisErrorT saImmOiClassImplementerRelease(SaImmOiHandleT immOiHandle,
 1871                                            const SaImmClassNameT className) {
 1872   SaAisErrorT rc = SA_AIS_OK;
 1873   IMMA_CB *cb = &imma_cb;
 1874   IMMSV_EVT evt;
 1875   IMMSV_EVT *out_evt = NULL;
 1876   IMMA_CLIENT_NODE *cl_node = NULL;
 1877   bool locked = true;
 1878   SaUint32T nameLen = 0;
 1879 
 1880   if (cb->sv_id == 0) {
 1881     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
 1882     return SA_AIS_ERR_BAD_HANDLE;
 1883   }
 1884 
 1885   if ((className == NULL) || (nameLen = strlen(className)) == 0) {
 1886     TRACE_2("ERR_INVALID_PARAM: Parameter 'className' is NULL or has length 0");
 1887     return SA_AIS_ERR_INVALID_PARAM;
 1888   }
 1889   ++nameLen; /*Add 1 for the null. */
 1890 
 1891   if (nameLen >= IMMSV_MAX_CLASS_NAME_LENGTH) {
 1892     TRACE_4("ERR_LIBRARY: ClassName too long, size: %u max:%u", nameLen,
 1893             IMMSV_MAX_CLASS_NAME_LENGTH - 1);
 1894     return SA_AIS_ERR_LIBRARY;
 1895   }
 1896 
 1897   if (cb->is_immnd_up == false) {
 1898     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
 1899     return SA_AIS_ERR_TRY_AGAIN;
 1900   }
 1901 
 1902   /* get the CB Lock */
 1903   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 1904     rc = SA_AIS_ERR_LIBRARY;
 1905     TRACE_4("ERR_LIBRARY: Lock failed");
 1906     goto lock_fail;
 1907   }
 1908 
 1909   /*locked == true already */
 1910 
 1911   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 1912   if (!cl_node || cl_node->isOm) {
 1913     rc = SA_AIS_ERR_BAD_HANDLE;
 1914     goto bad_handle;
 1915   }
 1916   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
 1917     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
 1918     rc = SA_AIS_ERR_UNAVAILABLE;
 1919     goto clm_left;
 1920   }
 1921 
 1922   if (cl_node->stale) {
 1923     TRACE_1("Handle %llx is stale", immOiHandle);
 1924     bool resurrected = imma_oi_resurrect(cb, cl_node, &locked, &rc);
 1925     if (rc == SA_AIS_ERR_TRY_AGAIN) {
 1926       osafassert(!resurrected);
 1927       goto bad_handle; /* Handle is actually not bad yet. */
 1928     }
 1929 
 1930     if (!locked &&
 1931         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 1932       TRACE_4("ERR_LIBRARY: LOCK failed");
 1933       rc = SA_AIS_ERR_LIBRARY;
 1934       goto lock_fail;
 1935     }
 1936     locked = true;
 1937 
 1938     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 1939 
 1940     if (!resurrected || !cl_node || cl_node->isOm || cl_node->stale) {
 1941       TRACE_2("ERR_BAD_HANDLE: Reactive ressurect of handle %llx failed",
 1942               immOiHandle);
 1943       if (cl_node && cl_node->stale) {
 1944         cl_node->exposed = true;
 1945       }
 1946       rc = SA_AIS_ERR_BAD_HANDLE;
 1947       goto bad_handle;
 1948     }
 1949 
 1950     TRACE_1("Reactive resurrect of handle %llx succeeded", immOiHandle);
 1951   }
 1952 
 1953   if (cl_node->mImplementerId == 0) {
 1954     rc = SA_AIS_ERR_BAD_HANDLE;
 1955     TRACE_2("ERR_BAD_HANDLE: No implementer is set for this handle");
 1956     goto bad_handle;
 1957   }
 1958 
 1959   if ((rc = imma_proc_increment_pending_reply(cl_node, true)) != SA_AIS_OK) {
 1960     TRACE_4(
 1961         "ERR_LIBRARY: Overlapping use of IMM OI handle by multiple threads");
 1962     goto bad_handle;
 1963   }
 1964 
 1965   /* Populate & Send the Open Event to IMMND */
 1966   memset(&evt, 0, sizeof(IMMSV_EVT));
 1967   evt.type = IMMSV_EVT_TYPE_IMMND;
 1968   evt.info.immnd.type = IMMND_EVT_A2ND_OI_CL_IMPL_REL;
 1969   evt.info.immnd.info.implSet.client_hdl = cl_node->handle;
 1970   evt.info.immnd.info.implSet.impl_name.size = nameLen;
 1971   evt.info.immnd.info.implSet.impl_name.buf = className;
 1972   evt.info.immnd.info.implSet.impl_id = cl_node->mImplementerId;
 1973 
 1974   rc = imma_evt_fake_evs(cb, &evt, &out_evt, cl_node->syncr_timeout,
 1975                          cl_node->handle, &locked, true);
 1976 
 1977   cl_node = NULL;
 1978   evt.info.immnd.info.implSet.impl_name.buf = NULL;
 1979   evt.info.immnd.info.implSet.impl_name.size = 0;
 1980 
 1981   if (!locked && m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 1982     rc = SA_AIS_ERR_LIBRARY; /* Overwrites any error from fake_evs() */
 1983     /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
 1984     TRACE_4("ERR_LIBRARY: LOCK failed");
 1985     goto lock_fail;
 1986   }
 1987   locked = true;
 1988 
 1989   /* get the client_info */
 1990   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 1991   if (!cl_node || cl_node->isOm) {
 1992     rc = SA_AIS_ERR_BAD_HANDLE;
 1993     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
 1994     goto bad_handle;
 1995   }
 1996 
 1997   imma_proc_decrement_pending_reply(cl_node, true);
 1998 
 1999   if (rc != SA_AIS_OK) {
 2000     /* fake_evs returned error */
 2001     goto fevs_error;
 2002   }
 2003 
 2004   if (cl_node->stale) {
 2005     TRACE_3("Handle %llx is stale after successfull call - ignoring",
 2006             immOiHandle);
 2007     /*
 2008       This is a class implementer release => a relaxation
 2009       => not necessary to expose when the call succeeded.
 2010       rc = SA_AIS_ERR_BAD_HANDLE;
 2011       cl_node->exposed = true;
 2012       goto bad_handle;
 2013     */
 2014   }
 2015 
 2016   osafassert(out_evt);
 2017   /* Process the received Event */
 2018   osafassert(out_evt->type == IMMSV_EVT_TYPE_IMMA);
 2019   osafassert(out_evt->info.imma.type == IMMA_EVT_ND2A_IMM_ERROR);
 2020   rc = out_evt->info.imma.info.errRsp.error;
 2021 
 2022 clm_left:
 2023 fevs_error:
 2024 bad_handle:
 2025   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 2026 
 2027 lock_fail:
 2028   if (out_evt) free(out_evt);
 2029   return rc;
 2030 }
 2031 
 2032 /****************************************************************************
 2033   Name          :  saImmOiObjectImplementerSet
 2034 
 2035   Description   :  Set implementer for the objects identified by scope
 2036                    and objectName. This is a blocking call.
 2037 
 2038 
 2039   Arguments     :  immOiHandle - IMM OI handle
 2040                    objectName - The name of the top object.
 2041 
 2042   This call will fail if not a prior call to implementerSet has been made.
 2043 
 2044   Return Values :  Refer to SAI-AIS specification for various return values.
 2045 ******************************************************************************/
 2046 static SaAisErrorT object_implementer_set_common(SaImmOiHandleT immOiHandle,
 2047                                                  SaConstStringT objectName,
 2048                                                  SaImmScopeT scope,
 2049                                                  bool isObjectDnUsed);
 2050 
 2051 SaAisErrorT saImmOiObjectImplementerSet(SaImmOiHandleT immOiHandle,
 2052                                         const SaNameT *objectName,
 2053                                         SaImmScopeT scope) {
 2054   SaStringT objectNameStr = NULL;
 2055   char objName[SA_MAX_UNEXTENDED_NAME_LENGTH];
 2056 
 2057   if (objectName) {
 2058     if (!osaf_is_extended_name_valid(objectName)) {
 2059       TRACE_2("ERR_INVALID_PARAM: Object name is invalid");
 2060       return SA_AIS_ERR_INVALID_PARAM;
 2061     }
 2062 
 2063     size_t len = osaf_extended_name_length(objectName);
 2064     if (len < SA_MAX_UNEXTENDED_NAME_LENGTH) {
 2065       objectNameStr = objName;
 2066       memcpy(objName, osaf_extended_name_borrow(objectName), len);
 2067       objName[len] = 0;
 2068     } else {
 2069       objectNameStr = (SaStringT)osaf_extended_name_borrow(objectName);
 2070     }
 2071   }
 2072 
 2073   return object_implementer_set_common(immOiHandle, objectNameStr, scope,
 2074                                        false);
 2075 }
 2076 
 2077 SaAisErrorT saImmOiObjectImplementerSet_o3(SaImmOiHandleT immOiHandle,
 2078                                            SaConstStringT objectName,
 2079                                            SaImmScopeT scope) {
 2080   return object_implementer_set_common(immOiHandle, objectName, scope, true);
 2081 }
 2082 
 2083 static SaAisErrorT object_implementer_set_common(SaImmOiHandleT immOiHandle,
 2084                                                  SaConstStringT objectName,
 2085                                                  SaImmScopeT scope,
 2086                                                  bool isObjectDnUsed) {
 2087   SaAisErrorT rc = SA_AIS_OK;
 2088   IMMA_CB *cb = &imma_cb;
 2089   IMMSV_EVT evt;
 2090   IMMSV_EVT *out_evt = NULL;
 2091   IMMA_CLIENT_NODE *cl_node = NULL;
 2092   bool locked = true;
 2093   SaUint32T nameLen = 0;
 2094 
 2095   if (cb->sv_id == 0) {
 2096     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
 2097     return SA_AIS_ERR_BAD_HANDLE;
 2098   }
 2099 
 2100   if ((objectName == NULL) ||
 2101       !(osaf_is_extended_names_enabled() ||
 2102         strlen(objectName) < SA_MAX_UNEXTENDED_NAME_LENGTH) ||
 2103       !objectName[0]) {
 2104     TRACE_2(
 2105         "ERR_INVALID_PARAM: Parameter 'objectName' is NULL, "
 2106         "invalid or zero length");
 2107     return SA_AIS_ERR_INVALID_PARAM;
 2108   }
 2109 
 2110   nameLen = strlen(objectName);
 2111   TRACE_1("value:'%s' len:%u", objectName, (unsigned)nameLen);
 2112   ++nameLen; /* Add 1 for the null */
 2113 
 2114   switch (scope) {
 2115     case SA_IMM_ONE:
 2116     case SA_IMM_SUBLEVEL:
 2117     case SA_IMM_SUBTREE:
 2118       break;
 2119     default:
 2120       TRACE_2("ERR_INVALID_PARAM: Parameter 'scope' has incorrect value %u",
 2121               scope);
 2122       return SA_AIS_ERR_INVALID_PARAM;
 2123   }
 2124 
 2125   if (cb->is_immnd_up == false) {
 2126     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
 2127     return SA_AIS_ERR_TRY_AGAIN;
 2128   }
 2129 
 2130   /* get the CB Lock */
 2131   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 2132     rc = SA_AIS_ERR_LIBRARY;
 2133     TRACE_4("ERR_LIBRARY: Lock failed");
 2134     goto lock_fail;
 2135   }
 2136 
 2137   /*locked == true already */
 2138 
 2139   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 2140   if (!cl_node || cl_node->isOm) {
 2141     rc = SA_AIS_ERR_BAD_HANDLE;
 2142     goto bad_handle;
 2143   }
 2144 
 2145   if (isObjectDnUsed && !cl_node->isImmA2f) {
 2146     /* TODO: ERR_VERSION is not according to SAF spec ??? */
 2147     rc = SA_AIS_ERR_VERSION;
 2148     TRACE_2(
 2149         "ERR_VERSION: saImmOiObjectImplementerSet_o3 is supported from A.2.15");
 2150     goto bad_handle;
 2151   }
 2152 
 2153   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
 2154     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
 2155     rc = SA_AIS_ERR_UNAVAILABLE;
 2156     goto clm_left;
 2157   }
 2158 
 2159   if (cl_node->stale) {
 2160     TRACE_1("Handle %llx is stale", immOiHandle);
 2161     bool resurrected = imma_oi_resurrect(cb, cl_node, &locked, &rc);
 2162     if (rc == SA_AIS_ERR_TRY_AGAIN) {
 2163       osafassert(!resurrected);
 2164       goto bad_handle; /* Handle is actually not bad yet. */
 2165     }
 2166 
 2167     if (!locked &&
 2168         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 2169       TRACE_4("ERR_LIBRARY: LOCK failed");
 2170       rc = SA_AIS_ERR_LIBRARY;
 2171       goto lock_fail;
 2172     }
 2173     locked = true;
 2174 
 2175     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 2176 
 2177     if (!resurrected || !cl_node || cl_node->isOm || cl_node->stale) {
 2178       TRACE_2("ERR_BAD_HANDLE: Reactive ressurect of handle %llx failed",
 2179               immOiHandle);
 2180       if (cl_node && cl_node->stale) {
 2181         cl_node->exposed = true;
 2182       }
 2183       rc = SA_AIS_ERR_BAD_HANDLE;
 2184       goto bad_handle;
 2185     }
 2186 
 2187     TRACE_1("Reactive resurrect of handle %llx succeeded", immOiHandle);
 2188   }
 2189 
 2190   if (cl_node->mImplementerId == 0) {
 2191     rc = SA_AIS_ERR_BAD_HANDLE;
 2192     TRACE_2("ERR_BAD_HANDLE: No implementer is set for this handle");
 2193     goto bad_handle;
 2194   }
 2195 
 2196   if ((rc = imma_proc_increment_pending_reply(cl_node, true)) != SA_AIS_OK) {
 2197     TRACE_4(
 2198         "ERR_LIBRARY: Overlapping use of IMM OI handle by multiple threads");
 2199     goto bad_handle;
 2200   }
 2201 
 2202   /* Populate & Send the Open Event to IMMND */
 2203   memset(&evt, 0, sizeof(IMMSV_EVT));
 2204   evt.type = IMMSV_EVT_TYPE_IMMND;
 2205   evt.info.immnd.type = IMMND_EVT_A2ND_OI_OBJ_IMPL_SET;
 2206   evt.info.immnd.info.implSet.client_hdl = cl_node->handle;
 2207   evt.info.immnd.info.implSet.impl_name.size = nameLen;
 2208   evt.info.immnd.info.implSet.impl_name.buf = (char *)objectName;
 2209   TRACE("Sending size:%u val:'%s'", nameLen - 1,
 2210         evt.info.immnd.info.implSet.impl_name.buf);
 2211   evt.info.immnd.info.implSet.impl_id = cl_node->mImplementerId;
 2212   evt.info.immnd.info.implSet.scope = scope;
 2213 
 2214   rc = imma_evt_fake_evs(cb, &evt, &out_evt, cl_node->syncr_timeout,
 2215                          cl_node->handle, &locked, true);
 2216 
 2217   cl_node = NULL;
 2218 
 2219   if (!locked && m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 2220     rc = SA_AIS_ERR_LIBRARY; /* Overwrites any error from fake_evs() */
 2221     /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
 2222     TRACE_4("ERR_LIBRARY: LOCK failed");
 2223     goto lock_fail;
 2224   }
 2225   locked = true;
 2226 
 2227   /* get the client_info */
 2228   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 2229   if (!cl_node || cl_node->isOm) {
 2230     rc = SA_AIS_ERR_BAD_HANDLE;
 2231     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
 2232     goto bad_handle;
 2233   }
 2234 
 2235   imma_proc_decrement_pending_reply(cl_node, true);
 2236 
 2237   if (rc != SA_AIS_OK) {
 2238     /* fake_evs returned error */
 2239     goto fevs_error;
 2240   }
 2241 
 2242   if (cl_node->stale) {
 2243     TRACE_3("Handle %llx is stale after successfull call", immOiHandle);
 2244 
 2245     /* This is an object implementer set => user expects this to be
 2246        upheld, but handle is stale => exposed.
 2247      */
 2248     rc = SA_AIS_ERR_BAD_HANDLE;
 2249     cl_node->exposed = true;
 2250     goto bad_handle;
 2251   }
 2252 
 2253   osafassert(out_evt);
 2254   osafassert(out_evt->type == IMMSV_EVT_TYPE_IMMA);
 2255   osafassert(out_evt->info.imma.type == IMMA_EVT_ND2A_IMM_ERROR);
 2256   rc = out_evt->info.imma.info.errRsp.error;
 2257 
 2258 clm_left:
 2259 fevs_error:
 2260 bad_handle:
 2261   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 2262 
 2263 lock_fail:
 2264   if (out_evt) free(out_evt);
 2265 
 2266   return rc;
 2267 }
 2268 
 2269 /****************************************************************************
 2270   Name          :  saImmOiObjectImplementerRelease
 2271 
 2272   Description   :  Release implementer for the objects identified by scope
 2273                    and objectName. This is a blocking call.
 2274 
 2275 
 2276   Arguments     :  immOiHandle - IMM OI handle
 2277                    objectName - The name of the top object.
 2278 
 2279   This call will fail if not a prior call to objectImplementerSet has been
 2280   made.
 2281 
 2282   Return Values :  Refer to SAI-AIS specification for various return values.
 2283 ******************************************************************************/
 2284 static SaAisErrorT object_implementer_release_common(SaImmOiHandleT immOiHandle,
 2285                                                      SaConstStringT objectName,
 2286                                                      SaImmScopeT scope,
 2287                                                      bool isObjectDnUsed);
 2288 
 2289 SaAisErrorT saImmOiObjectImplementerRelease(SaImmOiHandleT immOiHandle,
 2290                                             const SaNameT *objectName,
 2291                                             SaImmScopeT scope) {
 2292   SaStringT objectNameStr = NULL;
 2293   char objName[SA_MAX_UNEXTENDED_NAME_LENGTH];
 2294 
 2295   if (objectName) {
 2296     if (!osaf_is_extended_name_valid(objectName)) {
 2297       TRACE_2("ERR_INVALID_PARAM: Object name is invalid");
 2298       return SA_AIS_ERR_INVALID_PARAM;
 2299     }
 2300 
 2301     size_t len = osaf_extended_name_length(objectName);
 2302     if (len < SA_MAX_UNEXTENDED_NAME_LENGTH) {
 2303       objectNameStr = objName;
 2304       memcpy(objName, osaf_extended_name_borrow(objectName), len);
 2305       objName[len] = 0;
 2306     } else {
 2307       objectNameStr = (SaStringT)osaf_extended_name_borrow(objectName);
 2308     }
 2309   }
 2310 
 2311   return object_implementer_release_common(immOiHandle, objectNameStr, scope,
 2312                                            false);
 2313 }
 2314 
 2315 SaAisErrorT saImmOiObjectImplementerRelease_o3(SaImmOiHandleT immOiHandle,
 2316                                                SaConstStringT objectName,
 2317                                                SaImmScopeT scope) {
 2318   return object_implementer_release_common(immOiHandle, objectName, scope,
 2319                                            true);
 2320 }
 2321 
 2322 static SaAisErrorT object_implementer_release_common(SaImmOiHandleT immOiHandle,
 2323                                                      SaConstStringT objectName,
 2324                                                      SaImmScopeT scope,
 2325                                                      bool isObjectDnUsed) {
 2326   SaAisErrorT rc = SA_AIS_OK;
 2327   IMMA_CB *cb = &imma_cb;
 2328   IMMSV_EVT evt;
 2329   IMMSV_EVT *out_evt = NULL;
 2330   IMMA_CLIENT_NODE *cl_node = NULL;
 2331   bool locked = true;
 2332   SaUint32T nameLen = 0;
 2333 
 2334   if (cb->sv_id == 0) {
 2335     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
 2336     return SA_AIS_ERR_BAD_HANDLE;
 2337   }
 2338 
 2339   if ((objectName == NULL) || (!objectName[0]) ||
 2340       !(osaf_is_extended_names_enabled() ||
 2341         strlen(objectName) < SA_MAX_UNEXTENDED_NAME_LENGTH)) {
 2342     TRACE_2(
 2343         "ERR_INVALID_PARAM: Parameter 'objectName' is NULL "
 2344         "or zero length");
 2345     return SA_AIS_ERR_INVALID_PARAM;
 2346   }
 2347   nameLen = strlen(objectName);
 2348   ++nameLen; /*Add 1 for the null. */
 2349 
 2350   switch (scope) {
 2351     case SA_IMM_ONE:
 2352     case SA_IMM_SUBLEVEL:
 2353     case SA_IMM_SUBTREE:
 2354       break;
 2355     default:
 2356       TRACE_2("ERR_INVALID_PARAM: Parameter 'scope' has incorrect value %u",
 2357               scope);
 2358       return SA_AIS_ERR_INVALID_PARAM;
 2359   }
 2360 
 2361   if (cb->is_immnd_up == false) {
 2362     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
 2363     return SA_AIS_ERR_TRY_AGAIN;
 2364   }
 2365 
 2366   /* get the CB Lock */
 2367   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 2368     rc = SA_AIS_ERR_LIBRARY;
 2369     TRACE_4("ERR_LIBRARY: Lock failed");
 2370     goto lock_fail;
 2371   }
 2372 
 2373   /*locked == true already */
 2374 
 2375   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 2376   if (!cl_node || cl_node->isOm) {
 2377     TRACE_2("ERR_BAD_HANDLE: Not a valid SaImmOiHandleT");
 2378     rc = SA_AIS_ERR_BAD_HANDLE;
 2379     goto bad_handle;
 2380   }
 2381 
 2382   if (isObjectDnUsed && !cl_node->isImmA2f) {
 2383     rc = SA_AIS_ERR_VERSION;
 2384     TRACE_2(
 2385         "ERR_VERSION: saImmOiObjectImplementerRelease_o3 is supported from A.2.15");
 2386     goto bad_handle;
 2387   }
 2388 
 2389   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
 2390     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
 2391     rc = SA_AIS_ERR_UNAVAILABLE;
 2392     goto clm_left;
 2393   }
 2394 
 2395   if (cl_node->stale) {
 2396     TRACE_1("Handle %llx is stale", immOiHandle);
 2397     bool resurrected = imma_oi_resurrect(cb, cl_node, &locked, &rc);
 2398     if (rc == SA_AIS_ERR_TRY_AGAIN) {
 2399       osafassert(!resurrected);
 2400       goto bad_handle; /* Handle is actually not bad yet. */
 2401     }
 2402 
 2403     if (!locked &&
 2404         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 2405       TRACE_4("ERR_LIBRARY: LOCK failed");
 2406       rc = SA_AIS_ERR_LIBRARY;
 2407       goto lock_fail;
 2408     }
 2409     locked = true;
 2410 
 2411     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 2412 
 2413     if (!resurrected || !cl_node || cl_node->isOm || cl_node->stale) {
 2414       TRACE_2("ERR_BAD_HANDLE: Reactive ressurect of handle %llx failed",
 2415               immOiHandle);
 2416       if (cl_node && cl_node->stale) {
 2417         cl_node->exposed = true;
 2418       }
 2419       rc = SA_AIS_ERR_BAD_HANDLE;
 2420       goto bad_handle;
 2421     }
 2422 
 2423     TRACE_1("Reactive resurrect of handle %llx succeeded", immOiHandle);
 2424   }
 2425 
 2426   if (cl_node->mImplementerId == 0) {
 2427     rc = SA_AIS_ERR_BAD_HANDLE;
 2428     TRACE_2("ERR_BAD_HANDLE: No implementer is set for this handle");
 2429     goto bad_handle;
 2430   }
 2431 
 2432   if ((rc = imma_proc_increment_pending_reply(cl_node, true)) != SA_AIS_OK) {
 2433     TRACE_4(
 2434         "ERR_LIBRARY: Overlapping use of IMM OI handle by multiple threads");
 2435     goto bad_handle;
 2436   }
 2437 
 2438   /* Populate & Send the Open Event to IMMND */
 2439   memset(&evt, 0, sizeof(IMMSV_EVT));
 2440   evt.type = IMMSV_EVT_TYPE_IMMND;
 2441   evt.info.immnd.type = IMMND_EVT_A2ND_OI_OBJ_IMPL_REL;
 2442   evt.info.immnd.info.implSet.client_hdl = cl_node->handle;
 2443   evt.info.immnd.info.implSet.impl_name.size = nameLen;
 2444   evt.info.immnd.info.implSet.impl_name.buf = (char *)objectName;
 2445   evt.info.immnd.info.implSet.impl_id = cl_node->mImplementerId;
 2446   evt.info.immnd.info.implSet.scope = scope;
 2447 
 2448   rc = imma_evt_fake_evs(cb, &evt, &out_evt, cl_node->syncr_timeout,
 2449                          cl_node->handle, &locked, true);
 2450 
 2451   cl_node = NULL;
 2452 
 2453   if (!locked && m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 2454     rc = SA_AIS_ERR_LIBRARY; /* Overwrites any error from fake_evs() */
 2455     /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
 2456     TRACE_4("ERR_LIBRARY: LOCK failed");
 2457     goto lock_fail;
 2458   }
 2459   locked = true;
 2460 
 2461   /* get the client_info */
 2462   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 2463   if (!cl_node || cl_node->isOm) {
 2464     rc = SA_AIS_ERR_BAD_HANDLE;
 2465     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
 2466     goto bad_handle;
 2467   }
 2468 
 2469   imma_proc_decrement_pending_reply(cl_node, true);
 2470 
 2471   if (rc != SA_AIS_OK) {
 2472     /* fake_evs returned error */
 2473     goto fevs_error;
 2474   }
 2475 
 2476   if (cl_node->stale) {
 2477     TRACE_3("Handle %llx is stale after successfull call - ignoring",
 2478             immOiHandle);
 2479     /*
 2480       This is object implementer release => a relaxation
 2481       => not necessary to expose when the call succeeded.
 2482       rc = SA_AIS_ERR_BAD_HANDLE;
 2483       cl_node->exposed = true;
 2484       goto bad_handle;
 2485     */
 2486   }
 2487 
 2488   osafassert(out_evt);
 2489   osafassert(out_evt->type == IMMSV_EVT_TYPE_IMMA);
 2490   osafassert(out_evt->info.imma.type == IMMA_EVT_ND2A_IMM_ERROR);
 2491   rc = out_evt->info.imma.info.errRsp.error;
 2492 
 2493 clm_left:
 2494 fevs_error:
 2495 bad_handle:
 2496   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 2497 
 2498 lock_fail:
 2499   if (out_evt) free(out_evt);
 2500 
 2501   return rc;
 2502 }
 2503 
 2504 static SaAisErrorT rt_object_update_common(
 2505     SaImmOiHandleT immOiHandle, SaConstStringT objectName,
 2506     const SaImmAttrModificationT_2 **attrMods, bool isObjectDnUsed);
 2507 
 2508 SaAisErrorT saImmOiRtObjectUpdate_2(SaImmOiHandleT immOiHandle,
 2509                                     const SaNameT *objectName,
 2510                                     const SaImmAttrModificationT_2 **attrMods) {
 2511   SaStringT objectNameStr = NULL;
 2512   char objName[SA_MAX_UNEXTENDED_NAME_LENGTH];
 2513 
 2514   if (objectName) {
 2515     if (!osaf_is_extended_name_valid(objectName)) {
 2516       TRACE_2("ERR_INVALID_PARAM: Object name is invalid");
 2517       return SA_AIS_ERR_INVALID_PARAM;
 2518     }
 2519 
 2520     size_t len = osaf_extended_name_length(objectName);
 2521     if (len < SA_MAX_UNEXTENDED_NAME_LENGTH) {
 2522       objectNameStr = objName;
 2523       memcpy(objName, osaf_extended_name_borrow(objectName), len);
 2524       objName[len] = 0;
 2525     } else {
 2526       objectNameStr = (SaStringT)osaf_extended_name_borrow(objectName);
 2527     }
 2528   }
 2529 
 2530   return rt_object_update_common(immOiHandle, objectNameStr, attrMods, false);
 2531 }
 2532 
 2533 SaAisErrorT saImmOiRtObjectUpdate_o3(
 2534     SaImmOiHandleT immOiHandle, SaConstStringT objectName,
 2535     const SaImmAttrModificationT_2 **attrMods) {
 2536   return rt_object_update_common(immOiHandle, objectName, attrMods, true);
 2537 }
 2538 
 2539 static SaAisErrorT rt_object_update_common(
 2540     SaImmOiHandleT immOiHandle, SaConstStringT objectName,
 2541     const SaImmAttrModificationT_2 **attrMods, bool isObjectDnUsed) {
 2542   SaAisErrorT rc = SA_AIS_OK;
 2543   uint32_t proc_rc = NCSCC_RC_SUCCESS;
 2544   IMMA_CB *cb = &imma_cb;
 2545   IMMSV_EVT evt;
 2546   IMMSV_EVT *out_evt = NULL;
 2547   IMMA_CLIENT_NODE *cl_node = NULL;
 2548   bool locked = true;
 2549   SaTimeT timeout = 0;
 2550 
 2551   if (cb->sv_id == 0) {
 2552     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
 2553     return SA_AIS_ERR_BAD_HANDLE;
 2554   }
 2555 
 2556   TRACE_ENTER();
 2557 
 2558   if ((objectName == NULL) ||
 2559       !(osaf_is_extended_names_enabled() ||
 2560         strlen(objectName) < SA_MAX_UNEXTENDED_NAME_LENGTH) ||
 2561       !objectName[0]) {
 2562     TRACE_2(
 2563         "ERR_INVALID_PARAM: objectName is NULL, "
 2564         "invalid or length is 0");
 2565     TRACE_LEAVE();
 2566     return SA_AIS_ERR_INVALID_PARAM;
 2567   }
 2568 
 2569   if (attrMods == NULL) {
 2570     TRACE_2("ERR_INVALID_PARAM: attrMods is NULL");
 2571     TRACE_LEAVE();
 2572     return SA_AIS_ERR_INVALID_PARAM;
 2573   }
 2574 
 2575   if (false == cb->is_immnd_up) {
 2576     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
 2577     return SA_AIS_ERR_TRY_AGAIN;
 2578   }
 2579 
 2580   /* get the CB Lock */
 2581   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 2582     rc = SA_AIS_ERR_LIBRARY;
 2583     TRACE_4("ERR_LIBRARY: Lock failed");
 2584     goto lock_fail;
 2585   }
 2586   /*locked == true already */
 2587 
 2588   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 2589   if (!cl_node || cl_node->isOm) {
 2590     rc = SA_AIS_ERR_BAD_HANDLE;
 2591     TRACE_2("ERR_BAD_HANDLE: Non valid SaImmOiHandleT");
 2592     goto bad_handle;
 2593   }
 2594 
 2595   if (isObjectDnUsed && !cl_node->isImmA2f) {
 2596     rc = SA_AIS_ERR_VERSION;
 2597     TRACE_2("ERR_VERSION: saImmOiRtObjectUpdate_o3 is supported from A.2.15");
 2598     goto bad_handle;
 2599   }
 2600   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
 2601     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
 2602     rc = SA_AIS_ERR_UNAVAILABLE;
 2603     goto clm_left;
 2604   }
 2605 
 2606   if (cl_node->stale) {
 2607     TRACE_1("Handle %llx is stale", immOiHandle);
 2608     bool resurrected = imma_oi_resurrect(cb, cl_node, &locked, &rc);
 2609     if (rc == SA_AIS_ERR_TRY_AGAIN) {
 2610       osafassert(!resurrected);
 2611       goto bad_handle; /* Handle is actually not bad yet. */
 2612     }
 2613 
 2614     if (!locked &&
 2615         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 2616       TRACE_4("ERR_LIBRARY: LOCK failed");
 2617       rc = SA_AIS_ERR_LIBRARY;
 2618       goto lock_fail;
 2619     }
 2620     locked = true;
 2621 
 2622     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 2623 
 2624     if (!resurrected || !cl_node || cl_node->isOm || cl_node->stale) {
 2625       TRACE_2("ERR_BAD_HANDLE: Reactive ressurect of handle %llx failed",
 2626               immOiHandle);
 2627       if (cl_node && cl_node->stale) {
 2628         cl_node->exposed = true;
 2629       }
 2630       rc = SA_AIS_ERR_BAD_HANDLE;
 2631       goto bad_handle;
 2632     }
 2633 
 2634     TRACE_1("Reactive resurrect of handle %llx succeeded", immOiHandle);
 2635   }
 2636 
 2637   if (cl_node->mImplementerId == 0) {
 2638     rc = SA_AIS_ERR_BAD_OPERATION;
 2639     LOG_ER(
 2640         "ERR_BAD_OPERATION: The SaImmOiHandleT is not associated with any implementer name");
 2641     goto bad_handle;
 2642   }
 2643 
 2644   if (cl_node->isApplier) {
 2645     rc = SA_AIS_ERR_BAD_OPERATION;
 2646     LOG_ER(
 2647         "ERR_BAD_OPERATION: The SaImmOiHandleT is associated with an >>applier<< name");
 2648     goto bad_handle;
 2649   }
 2650 
 2651   timeout = cl_node->syncr_timeout;
 2652 
 2653   /* Populate the Object-Update event */
 2654   memset(&evt, 0, sizeof(IMMSV_EVT));
 2655   evt.type = IMMSV_EVT_TYPE_IMMND;
 2656   evt.info.immnd.type = IMMND_EVT_A2ND_OI_OBJ_MODIFY;
 2657 
 2658   evt.info.immnd.info.objModify.immHandle = immOiHandle;
 2659 
 2660   /*NOTE: should rename member adminOwnerId !!! */
 2661   evt.info.immnd.info.objModify.adminOwnerId = cl_node->mImplementerId;
 2662 
 2663   evt.info.immnd.info.objModify.objectName.size = strlen(objectName) + 1;
 2664   evt.info.immnd.info.objModify.objectName.buf = (char *)objectName;
 2665 
 2666   osafassert(evt.info.immnd.info.objModify.attrMods == NULL);
 2667 
 2668   const SaImmAttrModificationT_2 *attrMod;
 2669   int i;
 2670   for (i = 0; attrMods[i]; ++i) {
 2671     attrMod = attrMods[i];
 2672 
 2673     /* TODO Check that the user does not set values for System attributes. */
 2674 
 2675     /* Prevent duplicate attribute assignments */
 2676     IMMSV_ATTR_MODS_LIST *p = evt.info.immnd.info.objModify.attrMods;
 2677     while (p != NULL) {
 2678       if (strcmp(attrMod->modAttr.attrName, p->attrValue.attrName.buf) == 0) {
 2679         rc = SA_AIS_ERR_INVALID_PARAM;
 2680         TRACE_2(
 2681             "ERR_INVALID_PARAM: Attribute %s occurs multiple times "
 2682             "in attrMods parameter",
 2683             attrMod->modAttr.attrName);
 2684         goto skip_over_send;
 2685       }
 2686 
 2687       p = p->next;
 2688     }
 2689 
 2690     /*alloc-2 */
 2691     p = (IMMSV_ATTR_MODS_LIST *)calloc(1, sizeof(IMMSV_ATTR_MODS_LIST));
 2692     p->attrModType = attrMod->modType;
 2693     p->attrValue.attrName.size = strlen(attrMod->modAttr.attrName) + 1;
 2694 
 2695     /* alloc 3 */
 2696     p->attrValue.attrName.buf = (char *)malloc(p->attrValue.attrName.size);
 2697     strncpy(p->attrValue.attrName.buf, attrMod->modAttr.attrName,
 2698             p->attrValue.attrName.size);
 2699     p->attrValue.attrName.buf[p->attrValue.attrName.size-1] = 0;
 2700 
 2701     p->attrValue.attrValuesNumber = attrMod->modAttr.attrValuesNumber;
 2702     p->attrValue.attrValueType = attrMod->modAttr.attrValueType;
 2703 
 2704     if (attrMod->modAttr.attrValuesNumber) { /*At least one value */
 2705       const SaImmAttrValueT *avarr = attrMod->modAttr.attrValues;
 2706       /*alloc-4 */
 2707       imma_copyAttrValue(&(p->attrValue.attrValue),
 2708                          attrMod->modAttr.attrValueType, avarr[0]);
 2709 
 2710       if (attrMod->modAttr.attrValuesNumber > 1) { /*Multiple values */
 2711         unsigned int numAdded = attrMod->modAttr.attrValuesNumber - 1;
 2712         unsigned int i;
 2713         for (i = 1; i <= numAdded; ++i) {
 2714           /*alloc-5 */
 2715           IMMSV_EDU_ATTR_VAL_LIST *al = (IMMSV_EDU_ATTR_VAL_LIST *)calloc(
 2716               1, sizeof(IMMSV_EDU_ATTR_VAL_LIST));
 2717           /*alloc-6 */
 2718           imma_copyAttrValue(&(al->n), attrMod->modAttr.attrValueType,
 2719                              avarr[i]);
 2720           al->next = p->attrValue.attrMoreValues; /*NULL initially */
 2721           p->attrValue.attrMoreValues = al;
 2722         } /*for */
 2723       }   /*Multiple values */
 2724     }     /*At least one value */
 2725     else {
 2726       TRACE_3("Strange update of attribute %s, without any modifications",
 2727               attrMod->modAttr.attrName);
 2728     }
 2729     p->next = evt.info.immnd.info.objModify.attrMods; /*NULL initially. */
 2730     evt.info.immnd.info.objModify.attrMods = p;
 2731   }
 2732 
 2733   /* We do not send the rt update over fevs, because the update may
 2734      often be a PURELY LOCAL update, by an object implementor reacting to
 2735      the SaImmOiRtAttrUpdateCallbackT upcall. In that local case, the
 2736      return of the upcall is the signal that the new values are ready, not
 2737      the invocation of this update call. */
 2738 
 2739   if ((rc = imma_proc_increment_pending_reply(cl_node, true)) != SA_AIS_OK) {
 2740     TRACE_4(
 2741         "ERR_LIBRARY: Overlapping use of IMM OI handle by multiple threads");
 2742     goto bad_sync;
 2743   }
 2744 
 2745   /* Release the CB lock Before MDS Send */
 2746   m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 2747   locked = false;
 2748   cl_node = NULL;
 2749 
 2750   if (false == cb->is_immnd_up) {
 2751     rc = SA_AIS_ERR_TRY_AGAIN;
 2752     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
 2753     goto mds_send_fail;
 2754   }
 2755 
 2756   /* send the request to the IMMND */
 2757   proc_rc = imma_mds_msg_sync_send(cb->imma_mds_hdl, &cb->immnd_mds_dest, &evt,
 2758                                    &out_evt, timeout);
 2759 
 2760   /* Error Handling */
 2761   switch (proc_rc) {
 2762     case NCSCC_RC_SUCCESS:
 2763       break;
 2764     case NCSCC_RC_REQ_TIMOUT:
 2765       rc = imma_proc_check_stale(cb, immOiHandle, SA_AIS_ERR_TIMEOUT);
 2766       break; /* i.e. goto mds_send_fail */
 2767     default:
 2768       TRACE_4("ERR_LIBRARY: MDS returned unexpected error code %u", proc_rc);
 2769       rc = SA_AIS_ERR_LIBRARY;
 2770       /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
 2771       goto bad_handle;
 2772   }
 2773 
 2774 mds_send_fail:
 2775 
 2776   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 2777     rc = SA_AIS_ERR_LIBRARY;
 2778     /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
 2779     TRACE_4("ERR_LIBRARY: Lock failed");
 2780     goto free_obj; /* locked will be false */
 2781   }
 2782   locked = true;
 2783 
 2784   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 2785   if (!cl_node || cl_node->isOm) {
 2786     rc = SA_AIS_ERR_BAD_HANDLE;
 2787     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
 2788     goto bad_handle1;
 2789   }
 2790 
 2791   imma_proc_decrement_pending_reply(cl_node, true);
 2792 
 2793   if (cl_node->stale) {
 2794     TRACE_1("Handle %llx is stale", immOiHandle);
 2795     rc = SA_AIS_ERR_BAD_HANDLE;
 2796     cl_node->exposed = true;
 2797     goto bad_handle1;
 2798   }
 2799 
 2800   if (out_evt) {
 2801     /* Process the outcome, note this is after a blocking call. */
 2802     osafassert(out_evt->type == IMMSV_EVT_TYPE_IMMA);
 2803     osafassert(out_evt->info.imma.type == IMMA_EVT_ND2A_IMM_ERROR);
 2804     if (rc == SA_AIS_OK) {
 2805       rc = out_evt->info.imma.info.errRsp.error;
 2806     }
 2807   }
 2808 
 2809 clm_left:
 2810 skip_over_send:
 2811 bad_sync:
 2812 bad_handle1:
 2813 free_obj:
 2814 
 2815   while (evt.info.immnd.info.objModify.attrMods) {
 2816     IMMSV_ATTR_MODS_LIST *p = evt.info.immnd.info.objModify.attrMods;
 2817     evt.info.immnd.info.objModify.attrMods = p->next;
 2818     p->next = NULL;
 2819 
 2820     if (p->attrValue.attrName.buf) {
 2821       free(p->attrValue.attrName.buf); /*free-3 */
 2822       p->attrValue.attrName.buf = NULL;
 2823     }
 2824 
 2825     if (p->attrValue.attrValuesNumber) {
 2826       immsv_evt_free_att_val(&(p->attrValue.attrValue), /*free-4 */
 2827                              (SaImmValueTypeT)p->attrValue.attrValueType);
 2828 
 2829       while (p->attrValue.attrMoreValues) {
 2830         IMMSV_EDU_ATTR_VAL_LIST *al = p->attrValue.attrMoreValues;
 2831         p->attrValue.attrMoreValues = al->next;
 2832         al->next = NULL;
 2833         immsv_evt_free_att_val(
 2834             &(al->n), (SaImmValueTypeT)p->attrValue.attrValueType); /*free-6 */
 2835         free(al);                                                   /*free-5 */
 2836       }
 2837     }
 2838 
 2839     free(p); /*free-2 */
 2840   }
 2841 
 2842 bad_handle:
 2843   if (locked) {
 2844     m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 2845   }
 2846 
 2847 lock_fail:
 2848   if (out_evt) free(out_evt);
 2849 
 2850   TRACE_LEAVE();
 2851   return rc;
 2852 }
 2853 
 2854 static SaAisErrorT rt_object_create_common(
 2855     SaImmOiHandleT immOiHandle, const SaImmClassNameT className,
 2856     const SaNameT *parentName, SaConstStringT objectName,
 2857     const SaImmAttrValuesT_2 **attrValues);
 2858 
 2859 SaAisErrorT saImmOiRtObjectCreate_2(SaImmOiHandleT immOiHandle,
 2860                                     const SaImmClassNameT className,
 2861                                     const SaNameT *parentName,
 2862                                     const SaImmAttrValuesT_2 **attrValues) {
 2863   if (attrValues == NULL) {
 2864     TRACE_2("ERR_INVALID_PARAM: attrValues is NULL");
 2865     return SA_AIS_ERR_INVALID_PARAM;
 2866   }
 2867 
 2868   return rt_object_create_common(immOiHandle, className, parentName, NULL,
 2869                                  attrValues);
 2870 }
 2871 
 2872 SaAisErrorT saImmOiRtObjectCreate_o3(SaImmOiHandleT immOiHandle,
 2873                                      const SaImmClassNameT className,
 2874                                      SaConstStringT objectName,
 2875                                      const SaImmAttrValuesT_2 **attrValues) {
 2876   if (objectName == NULL) {
 2877     TRACE_2("ERR_INVALID_PARAM: objectName is NULL");
 2878     return SA_AIS_ERR_INVALID_PARAM;
 2879   }
 2880 
 2881   return rt_object_create_common(immOiHandle, className, NULL, objectName,
 2882                                  attrValues);
 2883 }
 2884 
 2885 static SaAisErrorT rt_object_create_common(
 2886     SaImmOiHandleT immOiHandle, const SaImmClassNameT className,
 2887     const SaNameT *parentName, SaConstStringT objectName,
 2888     const SaImmAttrValuesT_2 **attrValues) {
 2889   SaAisErrorT rc = SA_AIS_OK;
 2890   IMMA_CB *cb = &imma_cb;
 2891   IMMSV_EVT evt;
 2892   IMMSV_EVT *out_evt = NULL;
 2893   IMMA_CLIENT_NODE *cl_node = NULL;
 2894   bool locked = true;
 2895 
 2896   if (cb->sv_id == 0) {
 2897     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
 2898     return SA_AIS_ERR_BAD_HANDLE;
 2899   }
 2900 
 2901   if (className == NULL) {
 2902     TRACE_2("ERR_INVALID_PARAM: classname is NULL");
 2903     return SA_AIS_ERR_INVALID_PARAM;
 2904   }
 2905 
 2906   if (parentName && !osaf_is_extended_name_valid(parentName)) {
 2907     TRACE_2("ERR_INVALID_PARAM: parentName is invalid");
 2908     return SA_AIS_ERR_INVALID_PARAM;
 2909   }
 2910 
 2911   if (cb->is_immnd_up == false) {
 2912     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
 2913     return SA_AIS_ERR_TRY_AGAIN;
 2914   }
 2915 
 2916   TRACE_ENTER();
 2917   /* get the CB Lock */
 2918   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 2919     rc = SA_AIS_ERR_LIBRARY;
 2920     TRACE_4("ERR_LIBRARY: Lock failed");
 2921     goto lock_fail;
 2922   }
 2923   /* locked == true already*/
 2924 
 2925   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 2926   if (!cl_node || cl_node->isOm) {
 2927     rc = SA_AIS_ERR_BAD_HANDLE;
 2928     TRACE_2("ERR_BAD_HANDLE: Non valid SaImmOiHandleT");
 2929     goto bad_handle;
 2930   }
 2931 
 2932   if (objectName && !cl_node->isImmA2f) {
 2933     rc = SA_AIS_ERR_VERSION;
 2934     TRACE_2("ERR_VERSION: saImmOiRtObjectCreate_o3 is supported from A.2.15");
 2935     goto bad_handle;
 2936   }
 2937   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
 2938     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
 2939     rc = SA_AIS_ERR_UNAVAILABLE;
 2940     goto clm_left;
 2941   }
 2942 
 2943   if (cl_node->stale) {
 2944     TRACE_1("Handle %llx is stale", immOiHandle);
 2945     bool resurrected = imma_oi_resurrect(cb, cl_node, &locked, &rc);
 2946     if (rc == SA_AIS_ERR_TRY_AGAIN) {
 2947       osafassert(!resurrected);
 2948       goto bad_handle; /* Handle is actually not bad yet. */
 2949     }
 2950 
 2951     if (!locked &&
 2952         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 2953       TRACE_4("ERR_LIBRARY: LOCK failed");
 2954       rc = SA_AIS_ERR_LIBRARY;
 2955       goto lock_fail;
 2956     }
 2957     locked = true;
 2958 
 2959     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 2960 
 2961     if (!resurrected || !cl_node || cl_node->isOm || cl_node->stale) {
 2962       TRACE_2("ERR_BAD_HANDLE: Reactive ressurect of handle %llx failed",
 2963               immOiHandle);
 2964       if (cl_node && cl_node->stale) {
 2965         cl_node->exposed = true;
 2966       }
 2967       rc = SA_AIS_ERR_BAD_HANDLE;
 2968       goto bad_handle;
 2969     }
 2970 
 2971     TRACE_1("Reactive resurrect of handle %llx succeeded", immOiHandle);
 2972   }
 2973 
 2974   if (cl_node->mImplementerId == 0) {
 2975     rc = SA_AIS_ERR_BAD_OPERATION;
 2976     LOG_ER(
 2977         "ERR_BAD_OPERATION: The SaImmOiHandleT is not associated with any implementer name");
 2978     goto bad_handle;
 2979   }
 2980 
 2981   if (cl_node->isApplier) {
 2982     rc = SA_AIS_ERR_BAD_OPERATION;
 2983     LOG_ER(
 2984         "ERR_BAD_OPERATION: The SaImmOiHandleT is associated with an >>applier<< name");
 2985     goto bad_handle;
 2986   }
 2987 
 2988   /* Populate the Object-Create event */
 2989   memset(&evt, 0, sizeof(IMMSV_EVT));
 2990   evt.type = IMMSV_EVT_TYPE_IMMND;
 2991 
 2992   /* NOTE: should rename member adminOwnerId !!! */
 2993   evt.info.immnd.info.objCreate.adminOwnerId = cl_node->mImplementerId;
 2994   evt.info.immnd.info.objCreate.className.size = strlen(className) + 1;
 2995 
 2996   /*alloc-1 */
 2997   evt.info.immnd.info.objCreate.className.buf =
 2998       (char *)malloc(evt.info.immnd.info.objCreate.className.size);
 2999   strcpy(evt.info.immnd.info.objCreate.className.buf, className);
 3000 
 3001   if (objectName) {
 3002     SaUint32T objectNameLen = strlen(objectName);
 3003     evt.info.immnd.type = IMMND_EVT_A2ND_OI_OBJ_CREATE_2;
 3004     if (objectNameLen > 0) {
 3005       evt.info.immnd.info.objCreate.parentOrObjectDn.size = objectNameLen + 1;
 3006       evt.info.immnd.info.objCreate.parentOrObjectDn.buf = (char *)objectName;
 3007     }
 3008   } else {
 3009     size_t parentNameLen = 0;
 3010     if (parentName &&
 3011         (parentNameLen = osaf_extended_name_length(parentName)) > 0) {
 3012       evt.info.immnd.info.objCreate.parentOrObjectDn.size = parentNameLen + 1;
 3013       evt.info.immnd.info.objCreate.parentOrObjectDn.buf =
 3014           (char *)malloc((parentNameLen + 1) * sizeof(char));
 3015       if (!evt.info.immnd.info.objCreate.parentOrObjectDn.buf) {
 3016         rc = SA_AIS_ERR_NO_MEMORY;
 3017         goto mds_send_fail;
 3018       }
 3019       memcpy(evt.info.immnd.info.objCreate.parentOrObjectDn.buf,
 3020              osaf_extended_name_borrow(parentName), parentNameLen);
 3021       evt.info.immnd.info.objCreate.parentOrObjectDn.buf[parentNameLen] = '\0';
 3022     } else {
 3023       evt.info.immnd.info.objCreate.parentOrObjectDn.size = 0;
 3024       evt.info.immnd.info.objCreate.parentOrObjectDn.buf = NULL;
 3025     }
 3026     evt.info.immnd.type = IMMND_EVT_A2ND_OI_OBJ_CREATE;
 3027   }
 3028 
 3029   osafassert(evt.info.immnd.info.objCreate.attrValues == NULL);
 3030 
 3031   if (attrValues) {
 3032     const SaImmAttrValuesT_2 *attr;
 3033     int i;
 3034     for (i = 0; attrValues[i]; ++i) {
 3035       attr = attrValues[i];
 3036       TRACE("attr:%s \n", attr->attrName);
 3037 
 3038       /* Prevent duplicate attribute assignments */
 3039       IMMSV_ATTR_VALUES_LIST *p = evt.info.immnd.info.objCreate.attrValues;
 3040       while (p != NULL) {
 3041         if (strcmp(attr->attrName, p->n.attrName.buf) == 0) {
 3042           rc = SA_AIS_ERR_INVALID_PARAM;
 3043           TRACE_2(
 3044               "ERR_INVALID_PARAM: Attribute %s occurs multiple times "
 3045               "in attrValues parameter",
 3046               attr->attrName);
 3047           goto mds_send_fail;
 3048         }
 3049         p = p->next;
 3050       }
 3051 
 3052       /*Check that the user does not set value for System attributes. */
 3053 
 3054       if (strcmp(attr->attrName, sysaClName) == 0) {
 3055         rc = SA_AIS_ERR_INVALID_PARAM;
 3056         TRACE_2("ERR_INVALID_PARAM: Not allowed to set attribute %s ",
 3057                 sysaClName);
 3058         goto mds_send_fail;
 3059       } else if (strcmp(attr->attrName, sysaAdmName) == 0) {
 3060         rc = SA_AIS_ERR_INVALID_PARAM;
 3061         TRACE_2("ERR_INVALID_PARAM: Not allowed to set attribute %s",
 3062                 sysaAdmName);
 3063         goto mds_send_fail;
 3064       } else if (strcmp(attr->attrName, sysaImplName) == 0) {
 3065         rc = SA_AIS_ERR_INVALID_PARAM;
 3066         TRACE_2("ERR_INVALID_PARAM: Not allowed to set attribute %s",
 3067                 sysaImplName);
 3068         goto mds_send_fail;
 3069       } else if (attr->attrValuesNumber == 0) {
 3070         TRACE("RtObjectCreate ignoring attribute %s with no values",
 3071               attr->attrName);
 3072         continue;
 3073       } else if (attr->attrValueType == SA_IMM_ATTR_SANAMET) {
 3074         SaUint32T n;
 3075         for (n = 0; n < attr->attrValuesNumber; n++) {
 3076           if (!osaf_is_extended_name_valid((SaNameT *)attr->attrValues[n])) {
 3077             rc = SA_AIS_ERR_INVALID_PARAM;
 3078             TRACE_2("ERR_INVALID_PARAM: Attribute '%s' value is not valid",
 3079                     attr->attrName);
 3080             goto mds_send_fail;
 3081           }
 3082         }
 3083       }
 3084 
 3085       /*alloc-3 */
 3086       p = (IMMSV_ATTR_VALUES_LIST *)calloc(1, sizeof(IMMSV_ATTR_VALUES_LIST));
 3087 
 3088       p->n.attrName.size = strlen(attr->attrName) + 1;
 3089       if (p->n.attrName.size >= IMMSV_MAX_ATTR_NAME_LENGTH) {
 3090         TRACE_2("ERR_INVALID_PARAM: Attribute name too long");
 3091         rc = SA_AIS_ERR_INVALID_PARAM;
 3092         free(p);
 3093         goto mds_send_fail;
 3094       }
 3095 
 3096       /*alloc-4 */
 3097       p->n.attrName.buf = (char *)malloc(p->n.attrName.size);
 3098       strncpy(p->n.attrName.buf, attr->attrName, p->n.attrName.size);
 3099       p->n.attrName.buf[p->n.attrName.size-1] = 0;
 3100 
 3101       p->n.attrValuesNumber = attr->attrValuesNumber;
 3102       p->n.attrValueType = attr->attrValueType;
 3103 
 3104       const SaImmAttrValueT *avarr = attr->attrValues;
 3105       /*alloc-5 */
 3106       imma_copyAttrValue(&(p->n.attrValue), attr->attrValueType, avarr[0]);
 3107 
 3108       if (attr->attrValuesNumber > 1) {
 3109         unsigned int numAdded = attr->attrValuesNumber - 1;
 3110         unsigned int i;
 3111         for (i = 1; i <= numAdded; ++i) {
 3112           /*alloc-6 */
 3113           IMMSV_EDU_ATTR_VAL_LIST *al = (IMMSV_EDU_ATTR_VAL_LIST *)calloc(
 3114               1, sizeof(IMMSV_EDU_ATTR_VAL_LIST));
 3115 
 3116           /*alloc-7 */
 3117           imma_copyAttrValue(&(al->n), attr->attrValueType, avarr[i]);
 3118           al->next = p->n.attrMoreValues;
 3119           p->n.attrMoreValues = al;
 3120         }
 3121       }
 3122 
 3123       p->next = evt.info.immnd.info.objCreate.attrValues; /*NULL initially. */
 3124       evt.info.immnd.info.objCreate.attrValues = p;
 3125     }
 3126   }
 3127 
 3128   if ((rc = imma_proc_increment_pending_reply(cl_node, true)) != SA_AIS_OK) {
 3129     TRACE_4(
 3130         "ERR_LIBRARY: Overlapping use of IMM OI handle by multiple threads");
 3131     goto mds_send_fail;
 3132   }
 3133 
 3134   rc = imma_evt_fake_evs(cb, &evt, &out_evt, cl_node->syncr_timeout,
 3135                          cl_node->handle, &locked, true);
 3136 
 3137   cl_node = NULL;
 3138 
 3139   if (!locked && m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 3140     rc = SA_AIS_ERR_LIBRARY; /* Overwrites any error from fake_evs() */
 3141     /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
 3142     TRACE_4("ERR_LIBRARY: LOCK failed");
 3143     goto mds_send_fail;
 3144   }
 3145   locked = true;
 3146 
 3147   /* get the client_info */
 3148   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 3149   if (!cl_node || cl_node->isOm) {
 3150     rc = SA_AIS_ERR_BAD_HANDLE;
 3151     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
 3152     goto mds_send_fail;
 3153   }
 3154 
 3155   imma_proc_decrement_pending_reply(cl_node, true);
 3156 
 3157   if (rc != SA_AIS_OK) {
 3158     /* fake_evs returned error */
 3159     goto mds_send_fail;
 3160   }
 3161 
 3162   if (cl_node->stale) {
 3163     rc = SA_AIS_ERR_BAD_HANDLE;
 3164     cl_node->exposed = true;
 3165     TRACE_2("ERR_BAD_HANDLE: Handle %llx is stale", immOiHandle);
 3166     goto mds_send_fail;
 3167   }
 3168 
 3169   osafassert(out_evt);
 3170   osafassert(out_evt->type == IMMSV_EVT_TYPE_IMMA);
 3171   osafassert(out_evt->info.imma.type == IMMA_EVT_ND2A_IMM_ERROR);
 3172   rc = out_evt->info.imma.info.errRsp.error;
 3173 
 3174 mds_send_fail:
 3175   if (evt.info.immnd.info.objCreate.className.buf) { /*free-1 */
 3176     free(evt.info.immnd.info.objCreate.className.buf);
 3177     evt.info.immnd.info.objCreate.className.buf = NULL;
 3178   }
 3179 
 3180   if (parentName && evt.info.immnd.info.objCreate.parentOrObjectDn.buf) {
 3181     free(evt.info.immnd.info.objCreate.parentOrObjectDn.buf);
 3182     evt.info.immnd.info.objCreate.parentOrObjectDn.buf = NULL;
 3183   }
 3184 
 3185   while (evt.info.immnd.info.objCreate.attrValues) {
 3186     IMMSV_ATTR_VALUES_LIST *p = evt.info.immnd.info.objCreate.attrValues;
 3187     evt.info.immnd.info.objCreate.attrValues = p->next;
 3188     p->next = NULL;
 3189     if (p->n.attrName.buf) { /*free-4 */
 3190       free(p->n.attrName.buf);
 3191       p->n.attrName.buf = NULL;
 3192     }
 3193 
 3194     immsv_evt_free_att_val(&(p->n.attrValue),
 3195                            (SaImmValueTypeT)p->n.attrValueType); /*free-5 */
 3196 
 3197     while (p->n.attrMoreValues) {
 3198       IMMSV_EDU_ATTR_VAL_LIST *al = p->n.attrMoreValues;
 3199       p->n.attrMoreValues = al->next;
 3200       al->next = NULL;
 3201       immsv_evt_free_att_val(&(al->n),
 3202                              (SaImmValueTypeT)p->n.attrValueType); /*free-7 */
 3203       free(al);                                                    /*free-6 */
 3204     }
 3205 
 3206     p->next = NULL;
 3207     free(p); /*free-3 */
 3208   }
 3209 clm_left:
 3210 bad_handle:
 3211   if (locked) {
 3212     m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 3213   }
 3214 
 3215 lock_fail:
 3216   if (out_evt) free(out_evt);
 3217 
 3218   TRACE_LEAVE();
 3219   return rc;
 3220 }
 3221 
 3222 static SaAisErrorT rt_object_delete_common(SaImmOiHandleT immOiHandle,
 3223                                            SaConstStringT objectName,
 3224                                            bool isObjectDnUsed);
 3225 
 3226 SaAisErrorT saImmOiRtObjectDelete(SaImmOiHandleT immOiHandle,
 3227                                   const SaNameT *objectName) {
 3228   SaStringT objectNameStr = NULL;
 3229   char objName[SA_MAX_UNEXTENDED_NAME_LENGTH];
 3230 
 3231   if (objectName) {
 3232     if (!osaf_is_extended_name_valid(objectName)) {
 3233       TRACE_2("ERR_INVALID_PARAM: Object name is invalid");
 3234       return SA_AIS_ERR_INVALID_PARAM;
 3235     }
 3236 
 3237     size_t len = osaf_extended_name_length(objectName);
 3238     if (len < SA_MAX_UNEXTENDED_NAME_LENGTH) {
 3239       objectNameStr = objName;
 3240       memcpy(objName, osaf_extended_name_borrow(objectName), len);
 3241       objName[len] = 0;
 3242     } else {
 3243       objectNameStr = (SaStringT)osaf_extended_name_borrow(objectName);
 3244     }
 3245   }
 3246 
 3247   return rt_object_delete_common(immOiHandle, objectNameStr, false);
 3248 }
 3249 
 3250 SaAisErrorT saImmOiRtObjectDelete_o3(SaImmOiHandleT immOiHandle,
 3251                                      SaConstStringT objectName) {
 3252   return rt_object_delete_common(immOiHandle, objectName, true);
 3253 }
 3254 
 3255 static SaAisErrorT rt_object_delete_common(SaImmOiHandleT immOiHandle,
 3256                                            SaConstStringT objectName,
 3257                                            bool isObjectDnUsed) {
 3258   SaAisErrorT rc = SA_AIS_OK;
 3259   IMMA_CB *cb = &imma_cb;
 3260   IMMSV_EVT evt;
 3261   IMMSV_EVT *out_evt = NULL;
 3262   IMMA_CLIENT_NODE *cl_node = NULL;
 3263   bool locked = true;
 3264 
 3265   if (cb->sv_id == 0) {
 3266     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
 3267     return SA_AIS_ERR_BAD_HANDLE;
 3268   }
 3269 
 3270   if (!objectName || !objectName[0]) {
 3271     TRACE_2("ERR_INVALID_PARAM: Empty object-name");
 3272     return SA_AIS_ERR_INVALID_PARAM;
 3273   }
 3274 
 3275   if (!osaf_is_extended_names_enabled() &&
 3276       strlen(objectName) >= SA_MAX_UNEXTENDED_NAME_LENGTH) {
 3277     TRACE_2("ERR_INVALID_PARAM: Object name invalid");
 3278     return SA_AIS_ERR_INVALID_PARAM;
 3279   }
 3280 
 3281   if (cb->is_immnd_up == false) {
 3282     TRACE_2("ERR_TRY_AGAIN: IMMND is DOWN");
 3283     return SA_AIS_ERR_TRY_AGAIN;
 3284   }
 3285 
 3286   /* get the CB Lock */
 3287   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 3288     rc = SA_AIS_ERR_LIBRARY;
 3289     TRACE_4("ERR_LIBRARY: Lock failed");
 3290     goto lock_fail;
 3291   }
 3292   /*locked == true already*/
 3293 
 3294   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 3295   if (!cl_node || cl_node->isOm) {
 3296     rc = SA_AIS_ERR_BAD_HANDLE;
 3297     TRACE_2("ERR_BAD_HANDLE: Not a valid SaImmOiHandleT");
 3298     goto bad_handle;
 3299   }
 3300 
 3301   if (isObjectDnUsed && !cl_node->isImmA2f) {
 3302     rc = SA_AIS_ERR_VERSION;
 3303     TRACE_2("ERR_VERSION: saImmOiRtObjectDelete_o3 is supported from A.2.15");
 3304     goto bad_handle;
 3305   }
 3306   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
 3307     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
 3308     rc = SA_AIS_ERR_UNAVAILABLE;
 3309     goto clm_left;
 3310   }
 3311 
 3312   if (cl_node->stale) {
 3313     TRACE_1("Handle %llx is stale", immOiHandle);
 3314     bool resurrected = imma_oi_resurrect(cb, cl_node, &locked, &rc);
 3315     if (rc == SA_AIS_ERR_TRY_AGAIN) {
 3316       osafassert(!resurrected);
 3317       goto bad_handle; /* Handle is actually not bad yet. */
 3318     }
 3319 
 3320     if (!locked &&
 3321         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 3322       TRACE_4("ERR_LIBRARY: LOCK failed");
 3323       rc = SA_AIS_ERR_LIBRARY;
 3324       goto lock_fail;
 3325     }
 3326     locked = true;
 3327 
 3328     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 3329 
 3330     if (!resurrected || !cl_node || cl_node->isOm || cl_node->stale) {
 3331       TRACE_2("ERR_BAD_HANDLE: Reactive ressurect of handle %llx failed",
 3332               immOiHandle);
 3333       if (cl_node && cl_node->stale) {
 3334         cl_node->exposed = true;
 3335       }
 3336       rc = SA_AIS_ERR_BAD_HANDLE;
 3337       goto bad_handle;
 3338     }
 3339 
 3340     TRACE_1("Reactive resurrect of handle %llx succeeded", immOiHandle);
 3341   }
 3342 
 3343   if (cl_node->mImplementerId == 0) {
 3344     rc = SA_AIS_ERR_BAD_OPERATION;
 3345     LOG_ER(
 3346         "ERR_BAD_OPERATION: The SaImmOiHandleT is not associated with any implementer name");
 3347     goto bad_handle;
 3348   }
 3349 
 3350   if (cl_node->isApplier) {
 3351     rc = SA_AIS_ERR_BAD_OPERATION;
 3352     LOG_ER(
 3353         "ERR_BAD_OPERATION: The SaImmOiHandleT is associated with an >>applier<< name");
 3354     goto bad_handle;
 3355   }
 3356 
 3357   if ((rc = imma_proc_increment_pending_reply(cl_node, true)) != SA_AIS_OK) {
 3358     TRACE_4(
 3359         "ERR_LIBRARY: Overlapping use of IMM OI handle by multiple threads");
 3360     goto bad_handle;
 3361   }
 3362 
 3363   /* Populate the Object-Delete event */
 3364   memset(&evt, 0, sizeof(IMMSV_EVT));
 3365   evt.type = IMMSV_EVT_TYPE_IMMND;
 3366   evt.info.immnd.type = IMMND_EVT_A2ND_OI_OBJ_DELETE;
 3367 
 3368   /* NOTE: should rename member adminOwnerId !!! */
 3369   evt.info.immnd.info.objDelete.adminOwnerId = cl_node->mImplementerId;
 3370 
 3371   evt.info.immnd.info.objDelete.objectName.size = strlen(objectName) + 1;
 3372   evt.info.immnd.info.objDelete.objectName.buf = (char *)objectName;
 3373 
 3374   rc = imma_evt_fake_evs(cb, &evt, &out_evt, cl_node->syncr_timeout,
 3375                          cl_node->handle, &locked, true);
 3376 
 3377   cl_node = NULL;
 3378 
 3379   if (!locked && m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 3380     rc = SA_AIS_ERR_LIBRARY; /* Overwrites any error from fake_evs() */
 3381     /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
 3382     TRACE_4("ERR_LIBRARY: LOCK failed");
 3383     goto fevs_error;
 3384   }
 3385   locked = true;
 3386 
 3387   /* get the client_info */
 3388   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 3389   if (!cl_node || cl_node->isOm) {
 3390     rc = SA_AIS_ERR_BAD_HANDLE;
 3391     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
 3392     goto fevs_error;
 3393   }
 3394 
 3395   imma_proc_decrement_pending_reply(cl_node, true);
 3396 
 3397   if (rc != SA_AIS_OK) {
 3398     /* fake_evs returned error */
 3399     goto fevs_error;
 3400   }
 3401 
 3402   if (cl_node->stale) {
 3403     rc = SA_AIS_ERR_BAD_HANDLE;
 3404     cl_node->exposed = true;
 3405     TRACE_2("ERR_BAD_HANDLE: Handle %llx is stale", immOiHandle);
 3406     goto fevs_error;
 3407   }
 3408 
 3409   osafassert(out_evt);
 3410   osafassert(out_evt->type == IMMSV_EVT_TYPE_IMMA);
 3411   osafassert(out_evt->info.imma.type == IMMA_EVT_ND2A_IMM_ERROR);
 3412   rc = out_evt->info.imma.info.errRsp.error;
 3413 
 3414 clm_left:
 3415 fevs_error:
 3416 bad_handle:
 3417   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 3418 lock_fail:
 3419   if (out_evt) free(out_evt);
 3420 
 3421   return rc;
 3422 }
 3423 
 3424 /*
 3425   Tries to set implementer for resurrected handle.
 3426   If it fails, then resurrection must be reverted
 3427   and stale+exposed must be set on client node by
 3428   invoking code.
 3429 
 3430   cb_lock must NOT be locked on entry.
 3431 */
 3432 static bool imma_implementer_set(IMMA_CB *cb, SaImmOiHandleT immOiHandle) {
 3433   SaAisErrorT err = SA_AIS_OK;
 3434   unsigned int sleep_delay_ms = 200;
 3435   unsigned int max_waiting_time_ms = 1 * 1000; /* 1 secs */
 3436   unsigned int msecs_waited = 0;
 3437   SaImmOiImplementerNameT implName;
 3438   IMMA_CLIENT_NODE *cl_node = NULL;
 3439   bool locked = false;
 3440   TRACE_ENTER();
 3441 
 3442   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 3443     TRACE_3("Lock failure");
 3444     goto fail;
 3445   }
 3446   locked = true;
 3447 
 3448   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 3449   if (!cl_node || cl_node->isOm || cl_node->stale) {
 3450     TRACE_3("client_node_get failed");
 3451     goto fail;
 3452   }
 3453 
 3454   implName = cl_node->mImplementerName;
 3455   cl_node->mImplementerName = NULL;
 3456   cl_node->mImplementerId = 0;
 3457 
 3458   m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 3459   locked = false;
 3460   cl_node = NULL;
 3461 
 3462   if (!implName) {
 3463     /* No implementer to re-connect with. */
 3464     goto success;
 3465   }
 3466 
 3467   err = saImmOiImplementerSet(immOiHandle, implName);
 3468   TRACE_1("saImmOiImplementerSet returned %u", err);
 3469 
 3470   while ((err == SA_AIS_ERR_TRY_AGAIN) &&
 3471          (msecs_waited < max_waiting_time_ms)) {
 3472     usleep(sleep_delay_ms * 1000);
 3473     msecs_waited += sleep_delay_ms;
 3474     err = saImmOiImplementerSet(immOiHandle, implName);
 3475     TRACE_1("saImmOiImplementerSet returned %u", err);
 3476   }
 3477   free(implName);
 3478   /*We dont need to set class/object implementer again
 3479     because that association is still maintained by the
 3480     distributed IMMSv over IMMND crashes.
 3481   */
 3482 
 3483   if (err != SA_AIS_OK) {
 3484     /* Note: cl_node->mImplementerName is now NULL
 3485        The failed implementer-set was then destructive
 3486        on the handle. But the resurrect shall now be
 3487        reverted (handle finalized towards IMMND) and
 3488        cl_node->stale/exposed both set to true.
 3489      */
 3490     goto fail;
 3491   }
 3492 
 3493 success:
 3494   osafassert(!locked);
 3495   TRACE_LEAVE();
 3496   return true;
 3497 
 3498 fail:
 3499   if (locked) {
 3500     m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 3501   }
 3502   TRACE_LEAVE();
 3503   return false;
 3504 }
 3505 
 3506 int imma_oi_resurrect(IMMA_CB *cb, IMMA_CLIENT_NODE *cl_node, bool *locked,
 3507                       SaAisErrorT *err_cli_res) {
 3508   IMMSV_EVT finalize_evt, *out_evt = NULL;
 3509   TRACE_ENTER();
 3510   osafassert(locked && *locked);
 3511   osafassert(cl_node && cl_node->stale);
 3512   SaImmOiHandleT immOiHandle = cl_node->handle;
 3513   SaTimeT timeout = IMMSV_WAIT_TIME;
 3514 
 3515   m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 3516   *locked = false;
 3517   cl_node = NULL;
 3518   if (!imma_proc_resurrect_client(cb, immOiHandle, false, err_cli_res)) {
 3519     TRACE_3("Failed to resurrect OI handle <c:%u, n:%x>",
 3520             m_IMMSV_UNPACK_HANDLE_HIGH(immOiHandle),
 3521             m_IMMSV_UNPACK_HANDLE_LOW(immOiHandle));
 3522     goto fail;
 3523   }
 3524 
 3525   TRACE_1("Successfully resurrected OI handle <c:%u, n:%x>",
 3526           m_IMMSV_UNPACK_HANDLE_HIGH(immOiHandle),
 3527           m_IMMSV_UNPACK_HANDLE_LOW(immOiHandle));
 3528 
 3529   /* Set implementer if needed. */
 3530   if (imma_implementer_set(cb, immOiHandle)) {
 3531     goto success;
 3532   }
 3533 
 3534   TRACE_3(
 3535       "Failed to set implementer for resurrected "
 3536       "OI handle - reverting resurrection");
 3537 
 3538   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 3539     TRACE_3("Lock failure");
 3540     goto fail;
 3541   }
 3542   *locked = true;
 3543 
 3544   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 3545   if (cl_node && !cl_node->isOm) {
 3546     cl_node->stale = true;
 3547     cl_node->exposed = true;
 3548   } else {
 3549     TRACE_3("client_node_get failed");
 3550   }
 3551 
 3552   if (cl_node) {
 3553     timeout = cl_node->syncr_timeout;
 3554   }
 3555 
 3556   m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 3557   *locked = false;
 3558 
 3559   /* Finalize the just resurrected handle ! */
 3560   memset(&finalize_evt, 0, sizeof(IMMSV_EVT));
 3561   finalize_evt.type = IMMSV_EVT_TYPE_IMMND;
 3562   finalize_evt.info.immnd.type = IMMND_EVT_A2ND_IMM_OI_FINALIZE;
 3563   finalize_evt.info.immnd.info.finReq.client_hdl = immOiHandle;
 3564 
 3565   /* send a finalize handle req to the IMMND.
 3566      Dont bother checking the answer. This is just
 3567      an attempt to deallocate the useless resurrected
 3568      handle on the server side.
 3569   */
 3570 
 3571   if (cb->is_immnd_up) {
 3572     imma_mds_msg_sync_send(cb->imma_mds_hdl, &(cb->immnd_mds_dest),
 3573                            &finalize_evt, &out_evt, timeout);
 3574 
 3575     /* Dont care about the response on finalize. */
 3576     if (out_evt) {
 3577       free(out_evt);
 3578     }
 3579   }
 3580 
 3581 /* Even though we finalized the resurrected handle towards IMMND,
 3582    we dont remove the client_node because this is just a dispatch.
 3583    Instead we leave it to the application to explicitly finalize its
 3584    handle.
 3585 */
 3586 
 3587 fail:
 3588   TRACE_LEAVE();
 3589   /* may be locked or unlocked as reflected in *locked */
 3590   return 0;
 3591 
 3592 success:
 3593   TRACE_LEAVE();
 3594   /* may be locked or unlocked as reflected in *locked */
 3595   return 1;
 3596 }
 3597 
 3598 /****************************************************************************
 3599   Name          :  saImmOiCcbSetErrorString
 3600 
 3601   Description   :  Allows the OI implementers to post an error string related
 3602                    to a current ccb-upcall, before returning from the upcall.
 3603                    The string will be transmitted to the OM client if the OI
 3604                    returns with an error code (not ok). This is allowed inside:
 3605                     SaImmOiCcbObjectCreateCallbackT
 3606                     SaImmOiCcbObjectDeleteCallbackT
 3607                     SaImmOiCcbObjectModifyCallbackT
 3608                     SaImmOiCcbCompletedCallbackT
 3609 
 3610 
 3611 
 3612   Arguments     :  immOiHandle - IMM OI handle
 3613                    ccbId  -  The ccbId for the ccb related upcall.
 3614                    errorString - The errorString.
 3615 
 3616   Return Values :  SA_AIS_OK
 3617                    SA_AIS_ERR_BAD_HANDLE
 3618                    SA_AIS_ERR_INVALID_PARAM
 3619                    SA_AIS_ERR_BAD_OPERATION (not inside valid ccb upcall)
 3620                    SA_AIS_ERR_LIBRARY
 3621                    SA_AIS_ERR_TRY_AGAIN
 3622 
 3623 ******************************************************************************/
 3624 SaAisErrorT saImmOiCcbSetErrorString(SaImmOiHandleT immOiHandle,
 3625                                      SaImmOiCcbIdT ccbId,
 3626                                      const SaStringT errorString) {
 3627   SaAisErrorT rc = SA_AIS_OK;
 3628   IMMA_CB *cb = &imma_cb;
 3629   IMMA_CLIENT_NODE *cl_node = NULL;
 3630   bool locked = true;
 3631 
 3632   if (cb->sv_id == 0) {
 3633     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
 3634     return SA_AIS_ERR_BAD_HANDLE;
 3635   }
 3636 
 3637   if ((errorString == NULL) || (strlen(errorString) == 0)) {
 3638     TRACE_2(
 3639         "ERR_INVALID_PARAM: Parameter 'srrorString' is NULL, or is a "
 3640         "string of 0 length");
 3641     return SA_AIS_ERR_INVALID_PARAM;
 3642   }
 3643 
 3644   /* get the CB Lock */
 3645   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 3646     rc = SA_AIS_ERR_LIBRARY;
 3647     TRACE_4("ERR_LIBRARY: Lock failed");
 3648     goto lock_fail;
 3649   }
 3650 
 3651   /*locked == true already */
 3652 
 3653   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 3654   if (!cl_node || cl_node->isOm) {
 3655     rc = SA_AIS_ERR_BAD_HANDLE;
 3656     TRACE_2("ERR_BAD_HANDLE: client_node_get failed");
 3657     goto bad_handle;
 3658   }
 3659   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
 3660     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
 3661     rc = SA_AIS_ERR_UNAVAILABLE;
 3662     goto clm_left;
 3663   }
 3664 
 3665   if (cl_node->stale) {
 3666     TRACE_1("Handle %llx is stale", immOiHandle);
 3667     bool resurrected = imma_oi_resurrect(cb, cl_node, &locked, &rc);
 3668     if (rc == SA_AIS_ERR_TRY_AGAIN) {
 3669       osafassert(!resurrected);
 3670       goto bad_handle; /* Handle is actually not bad yet. */
 3671     }
 3672 
 3673     if (!locked &&
 3674         m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 3675       TRACE_4("ERR_LIBRARY: LOCK failed");
 3676       rc = SA_AIS_ERR_LIBRARY;
 3677       goto lock_fail;
 3678     }
 3679     locked = true;
 3680 
 3681     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 3682 
 3683     if (!resurrected || !cl_node || cl_node->isOm || cl_node->stale) {
 3684       TRACE_2("ERR_BAD_HANDLE: Reactive ressurect of handle %llx failed",
 3685               immOiHandle);
 3686       if (cl_node && cl_node->stale) {
 3687         cl_node->exposed = true;
 3688       }
 3689       rc = SA_AIS_ERR_BAD_HANDLE;
 3690       goto bad_handle;
 3691     }
 3692 
 3693     TRACE_1("Reactive resurrect of handle %llx succeeded", immOiHandle);
 3694   }
 3695 
 3696   if (!(cl_node->isImmA2b)) {
 3697     rc = SA_AIS_ERR_VERSION;
 3698     TRACE_2(
 3699         "ERR_VERSION: saImmOiCcbSetErrorString only supported for A.02.11 and above");
 3700     goto bad_handle;
 3701   }
 3702 
 3703   if (!imma_oi_ccb_record_set_error(cl_node, ccbId, errorString)) {
 3704     TRACE_2(
 3705         "ERR_BAD_OPERATION: Ccb %llu, is not in a state that "
 3706         "accepts an errorString",
 3707         ccbId);
 3708     rc = SA_AIS_ERR_BAD_OPERATION;
 3709     goto bad_handle;
 3710   }
 3711 
 3712 clm_left:
 3713 bad_handle:
 3714   if (locked) m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 3715 
 3716 lock_fail:
 3717   return rc;
 3718 }
 3719 
 3720 extern SaAisErrorT immsv_om_augment_ccb_initialize(
 3721     SaImmOiHandleT privateOmHandle, SaUint32T ccbId, SaUint32T adminOwnerId,
 3722     SaImmCcbHandleT *ccbHandle, SaImmAdminOwnerHandleT *ownerHandle)
 3723     __attribute__((weak));
 3724 
 3725 extern SaAisErrorT immsv_om_augment_ccb_get_admo_name(
 3726     SaImmHandleT privateOmHandle, SaStringT object, SaStringT *admOwnerOut)
 3727     __attribute__((weak));
 3728 
 3729 extern SaAisErrorT immsv_om_handle_initialize(SaImmHandleT *privateOmHandle,
 3730                                               SaVersionT *version)
 3731     __attribute__((weak));
 3732 
 3733 extern SaAisErrorT immsv_om_admo_handle_initialize(
 3734     SaImmHandleT immHandle, const SaImmAdminOwnerNameT adminOwnerName,
 3735     SaImmAdminOwnerHandleT *adminOwnerHandle) __attribute__((weak));
 3736 
 3737 extern void immsv_om_handle_finalize(SaImmHandleT privateOmHandle)
 3738     __attribute__((weak));
 3739 
 3740 static SaAisErrorT getAdmoName(SaImmHandleT privateOmHandle,
 3741                                IMMA_CALLBACK_INFO *cbi, SaStringT object,
 3742                                SaStringT *admOwnerOut) {
 3743   SaAisErrorT rc = SA_AIS_OK;
 3744   const SaImmAttrNameT admoNameAttr = (char *)SA_IMM_ATTR_ADMIN_OWNER_NAME;
 3745   TRACE_ENTER();
 3746 
 3747   /* modify or delete => fetch admo attribute for object from server. */
 3748   if ((cbi->type != IMMA_CALLBACK_OI_CCB_DELETE) &&
 3749       (cbi->type != IMMA_CALLBACK_OI_CCB_MODIFY) &&
 3750       (cbi->type != IMMA_CALLBACK_OI_CCB_COMPLETED)) {
 3751     LOG_ER("Inconsistency in callback type:%u", cbi->type);
 3752     abort();
 3753   }
 3754 
 3755   osafassert(immsv_om_augment_ccb_get_admo_name);
 3756   rc = immsv_om_augment_ccb_get_admo_name(privateOmHandle, object, admOwnerOut);
 3757   if (rc == SA_AIS_ERR_LIBRARY) {
 3758     LOG_ER("Missmatch on attribute %s for delete or modify", admoNameAttr);
 3759   }
 3760 
 3761   /* attrVal found either in create callback, or fetched from server. */
 3762 
 3763   if (rc == SA_AIS_OK) {
 3764     TRACE("Obtained AdmoOwner:%s", *admOwnerOut);
 3765   }
 3766   TRACE_LEAVE();
 3767   return rc;
 3768 }
 3769 
 3770 /****************************************************************************
 3771   Name          :  saImmOiAugmentCcbInitialize
 3772 
 3773   Description   :  Allows the OI implementers to augment ops to a ccb related
 3774                    to a current ccb-upcall, before returning from the upcall.
 3775                    This is allowed inside:
 3776                      SaImmOiCcbObjectCreateCallbackT
 3777                      SaImmOiCcbObjectDeleteCallbackT
 3778                      SaImmOiCcbObjectModifyCallbackT
 3779                   It is NOT allowed inside:
 3780                     SaImmOiCcbCompletedCallbackT
 3781                     SaImmOiApplyCallbackT
 3782                     SaImmOiAbortCallbackT
 3783 
 3784 
 3785   Arguments     :  immOiHandle - IMM OI handle. Received in callback.
 3786                    ccbId  -  The ccbId for the parent ccb. Received in callback.
 3787                    ccbHandle - The ccbHandle that will be initialized to the
 3788 same ccbId as the parent CCB. ownerHandle - The admin owner handle that will be
 3789 initialized to the same admin-owner as used by the parent CCB.
 3790 
 3791   Return Values :  SA_AIS_OK
 3792                    SA_AIS_ERR_BAD_HANDLE
 3793                    SA_AIS_ERR_INVALID_PARAM
 3794                    SA_AIS_ERR_BAD_OPERATION (not inside valid ccb upcall)
 3795                    SA_AIS_ERR_LIBRARY
 3796                    SA_AIS_ERR_TRY_AGAIN
 3797 
 3798 ******************************************************************************/
 3799 SaAisErrorT saImmOiAugmentCcbInitialize(SaImmOiHandleT immOiHandle,
 3800                                         SaImmOiCcbIdT ccbId64,
 3801                                         SaImmCcbHandleT *ccbHandle,
 3802                                         SaImmAdminOwnerHandleT *ownerHandle)
 3803 
 3804 {
 3805   SaAisErrorT rc = SA_AIS_OK;
 3806   IMMSV_EVT init_evt;
 3807   IMMSV_EVT *out_evt = NULL;
 3808   IMMA_CB *cb = &imma_cb;
 3809   IMMA_CLIENT_NODE *cl_node = 0;
 3810   bool locked = true;
 3811   IMMA_CALLBACK_INFO *cbi = NULL;
 3812   SaImmHandleT privateOmHandle = 0LL;
 3813   SaImmAdminOwnerHandleT privateAoHandle = 0LL;
 3814   SaVersionT version = {'A', 2, 17};
 3815   SaUint32T adminOwnerId = 0;
 3816   SaUint32T ccbId = 0;
 3817   struct imma_oi_ccb_record *ccb_oi_record = NULL;
 3818 
 3819   TRACE_ENTER();
 3820 
 3821   if (cb->sv_id == 0) {
 3822     TRACE_2("ERR_BAD_HANDLE: No initialized handle exists!");
 3823     return SA_AIS_ERR_BAD_HANDLE;
 3824   }
 3825 
 3826   if (!ccbHandle) {
 3827     TRACE_2("ERR_INVALID_PARAM: ccbHandle is NULL");
 3828     return SA_AIS_ERR_INVALID_PARAM;
 3829   }
 3830 
 3831   if (!ownerHandle) {
 3832     TRACE_2("ERR_INVALID_PARAM: ownerHandle is NULL");
 3833     return SA_AIS_ERR_INVALID_PARAM;
 3834   }
 3835 
 3836   ccbId = ccbId64;
 3837 
 3838   if (ccbId > 0xffffffff) {
 3839     TRACE_2("Invalid ccbId, must be less than %llx", 0xffffffffLL);
 3840     return SA_AIS_ERR_INVALID_PARAM;
 3841   }
 3842 
 3843   if (ccbId == 0) {
 3844     TRACE_2("Invalid ccbId, must no be zero");
 3845     return SA_AIS_ERR_INVALID_PARAM;
 3846   }
 3847 
 3848   *ccbHandle = 0;
 3849   *ownerHandle = 0;
 3850 
 3851   if (cb->is_immnd_up == false) {
 3852     TRACE_2("ERR_TRY_AGAIN: IMMND_DOWN");
 3853     return SA_AIS_ERR_TRY_AGAIN;
 3854   }
 3855 
 3856   /* Take the CB lock */
 3857   if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 3858     TRACE_4("ERR_LIBRARY: LOCK failed");
 3859     rc = SA_AIS_ERR_LIBRARY;
 3860     goto lock_fail;
 3861   }
 3862   /* locked == true already */
 3863 
 3864   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 3865   if (!cl_node || cl_node->isOm) {
 3866     TRACE_2("ERR_BAD_HANDLE: Bad handle %llx", immOiHandle);
 3867     rc = SA_AIS_ERR_BAD_HANDLE;
 3868     goto done;
 3869   }
 3870   if (cl_node->isImmA2x12 && cl_node->clmExposed) {
 3871     TRACE_2("SA_AIS_ERR_UNAVAILABLE: imma CLM node left the cluster");
 3872     rc = SA_AIS_ERR_UNAVAILABLE;
 3873     goto clm_left;
 3874   }
 3875 
 3876   if (cl_node->stale) {
 3877     TRACE_1("ERR_BAD_HANDLE: Handle %llx is stale", immOiHandle);
 3878     rc = SA_AIS_ERR_BAD_HANDLE;
 3879     goto done;
 3880   }
 3881 
 3882   if (!(cl_node->isImmA2b)) {
 3883     /* Log this error instead of trace, to simplify troubleshooting
 3884        for the OI maintainer. */
 3885     LOG_IN(
 3886         "ERR_VERSION: saImmOiAugmentCcbInitialize "
 3887         "only allowed when OI handle is registered as A.2.11");
 3888     rc = SA_AIS_ERR_VERSION;
 3889     goto done;
 3890   }
 3891 
 3892   ccb_oi_record = imma_oi_ccb_record_find(cl_node, ccbId);
 3893   cbi = imma_oi_ccb_record_ok_augment(cl_node, ccbId, &privateOmHandle,
 3894                                       &privateAoHandle);
 3895   if (!cbi) {
 3896     TRACE_2(
 3897         "ERR_BAD_OPERATION: Ccb %u, is not in a state that "
 3898         "can be augmented",
 3899         ccbId);
 3900     rc = SA_AIS_ERR_BAD_OPERATION;
 3901     goto done;
 3902   }
 3903 
 3904   if (!privateOmHandle) {
 3905     /* The private om-handle is created at most once pe ccb that reaches the OI.
 3906        Likewise for the private admo.
 3907      */
 3908     osafassert(m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE) == NCSCC_RC_SUCCESS);
 3909     locked = false;
 3910     cl_node = NULL; /* avoid unsafe use */
 3911 
 3912     if (immsv_om_handle_initialize) { /*This is always the first immsv_om_ call
 3913                                        */
 3914       rc = immsv_om_handle_initialize(&privateOmHandle, &version);
 3915     } else {
 3916       TRACE(
 3917           "ERR_LIBRARY: Error in library linkage. libSaImmOm.so is not linked");
 3918       rc = SA_AIS_ERR_LIBRARY;
 3919       goto done;
 3920     }
 3921 
 3922     if (rc != SA_AIS_OK) {
 3923       TRACE("ERR_TRY_AGAIN: failed to obtain internal om handle rc:%u", rc);
 3924       rc = SA_AIS_ERR_TRY_AGAIN;
 3925       goto lock_fail; /* We are not locked and nothing to de-allocate.  */
 3926     }
 3927 
 3928     osafassert(m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) == NCSCC_RC_SUCCESS);
 3929     locked = true;
 3930 
 3931     imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 3932     if (!cl_node || cl_node->isOm || cl_node->stale) {
 3933       TRACE_2("ERR_BAD_HANDLE: Bad handle %llx", immOiHandle);
 3934       if (cl_node && cl_node->stale) {
 3935         cl_node->exposed = true;
 3936       }
 3937       rc = SA_AIS_ERR_BAD_HANDLE;
 3938       goto done;
 3939     }
 3940   }
 3941 
 3942   /* Downcall to immnd to get adminOwnerId and augmentation */
 3943   if ((rc = imma_proc_increment_pending_reply(cl_node, true)) != SA_AIS_OK) {
 3944     TRACE_4(
 3945         "ERR_LIBRARY: Overlapping use of IMM OI handle by multiple threads");
 3946     goto done;
 3947   }
 3948 
 3949   /* populate the EVT structure */
 3950   memset(&init_evt, 0, sizeof(IMMSV_EVT));
 3951   init_evt.type = IMMSV_EVT_TYPE_IMMND;
 3952   init_evt.info.immnd.type = IMMND_EVT_A2ND_OI_CCB_AUG_INIT;
 3953   init_evt.info.immnd.info.ccbUpcallRsp.ccbId = ccbId;
 3954   init_evt.info.immnd.info.ccbUpcallRsp.implId = cbi->implId;
 3955   init_evt.info.immnd.info.ccbUpcallRsp.inv = cbi->inv;
 3956   init_evt.info.immnd.info.ccbUpcallRsp.name = cbi->name;
 3957 
 3958   /* Note that we register using the new OM handle as client for the aug-ccb */
 3959   rc = imma_evt_fake_evs(cb, &init_evt, &out_evt, cl_node->syncr_timeout,
 3960                          /*cl_node->handle*/ privateOmHandle, &locked, true);
 3961 
 3962   cl_node = NULL; /* avoid unsafe use */
 3963 
 3964   if (rc != SA_AIS_OK) {
 3965     /* fake_evs returned error */
 3966     goto done;
 3967   }
 3968 
 3969   if (!locked && m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS) {
 3970     rc = SA_AIS_ERR_LIBRARY; /* Overwrites any error from fake_evs() */
 3971     /* Losing track of the pending reply count, but ERR_LIBRARY dominates*/
 3972     TRACE_4("ERR_LIBRARY: LOCK failed");
 3973     goto done;
 3974   }
 3975   locked = true;
 3976 
 3977   /* get the client_info */
 3978   imma_client_node_get(&cb->client_tree, &immOiHandle, &cl_node);
 3979   if (!cl_node || cl_node->isOm) {
 3980     rc = SA_AIS_ERR_BAD_HANDLE;
 3981     TRACE_3("client_node_get failed");
 3982     goto done;
 3983     ;
 3984   }
 3985 
 3986   imma_proc_decrement_pending_reply(cl_node, true);
 3987 
 3988   if (cl_node->stale) {
 3989     cl_node->exposed = true; /* But dont resurrect it either */
 3990     rc = SA_AIS_ERR_BAD_HANDLE;
 3991     TRACE_3("Handle %llx is stale", immOiHandle);
 3992     goto done;
 3993   }
 3994 
 3995   m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 3996   locked = false;
 3997 
 3998   /* Call processed successfully, check result from immnd */
 3999   osafassert(out_evt);
 4000   /* Process the received Event */
 4001   osafassert(out_evt->type == IMMSV_EVT_TYPE_IMMA);
 4002   osafassert((out_evt->info.imma.type == IMMA_EVT_ND2A_CCB_AUG_INIT_RSP) ||
 4003              (out_evt->info.imma.type == IMMA_EVT_ND2A_IMM_ERROR));
 4004   adminOwnerId = out_evt->info.imma.info.admInitRsp.ownerId;
 4005   rc = out_evt->info.imma.info.admInitRsp.error;
 4006 
 4007   if (rc == SA_AIS_ERR_NO_SECTIONS) {
 4008     /* Means almost ok, admo ROF == FALSE. Can not hijack original admo.
 4009        Must instead create new separate admo with same admo-name.
 4010      */
 4011     rc = SA_AIS_OK;
 4012 
 4013     if (!privateAoHandle) {
 4014       TRACE(
 4015           "AugCcbinit: Admo has ReleaseOnFinalize FALSE "
 4016           "=> init separate admo => must fetch admo-name first");
 4017       osafassert(locked == false);
 4018       SaStringT adminOwner =
 4019           NULL; /* Used to get admo string name copied to stack.*/
 4020 
 4021       osafassert(immsv_om_admo_handle_initialize);
 4022       if (ccb_oi_record->adminOwner) {
 4023         rc = immsv_om_admo_handle_initialize(
 4024             privateOmHandle, ccb_oi_record->adminOwner, &privateAoHandle);
 4025       } else {
 4026         rc = getAdmoName(privateOmHandle, cbi, ccb_oi_record->object,
 4027                          &adminOwner);
 4028 
 4029         if (rc != SA_AIS_OK) {
 4030           TRACE("ERR_TRY_AGAIN: failed to obtain SaImmAttrAdminOwnerName %u",
 4031                 rc);
 4032           if (rc != SA_AIS_ERR_TRY_AGAIN) {
 4033             rc = SA_AIS_ERR_TRY_AGAIN;
 4034           }
 4035           goto done;
 4036         }
 4037         /* Allocate private admowner with ReleaseOnFinalize as TRUE */
 4038         rc = immsv_om_admo_handle_initialize(privateOmHandle, adminOwner,
 4039                                              &privateAoHandle);
 4040       }
 4041 
 4042       if (rc != SA_AIS_OK) {
 4043         TRACE("ERR_TRY_AGAIN: failed to obtain internal admo handle rc:%u", rc);
 4044         if (rc != SA_AIS_ERR_TRY_AGAIN) {
 4045           rc = SA_AIS_ERR_TRY_AGAIN;
 4046         }
 4047         if (adminOwner) {
 4048           free(adminOwner);
 4049           adminOwner = NULL;
 4050         }
 4051         goto done;
 4052       }
 4053       if (adminOwner) {
 4054         free(adminOwner);
 4055         adminOwner = NULL;
 4056       }
 4057     }
 4058   } else {
 4059     TRACE("AugCcbinit: Admo has ROF == TRUE");
 4060   }
 4061 
 4062   if (rc != SA_AIS_OK) {
 4063     goto done;
 4064   }
 4065 
 4066   TRACE("adminOwnerId:%u", adminOwnerId);
 4067 
 4068   /* Now dip into the OM library & create mockup ccb-node & admo-node for use by
 4069    * OI */
 4070   osafassert(immsv_om_augment_ccb_initialize);
 4071   rc = immsv_om_augment_ccb_initialize(privateOmHandle, ccbId, adminOwnerId,
 4072                                        ccbHandle, &privateAoHandle);
 4073 clm_left:
 4074 done:
 4075 
 4076   if (locked) {
 4077     m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 4078   }
 4079 
 4080   if (rc == SA_AIS_OK || rc == SA_AIS_ERR_TRY_AGAIN) {
 4081     /* Mark oi_ccb_record with privateOmHandle to avoid repeated open/close
 4082        of private-om-handle for each try again or each ccb op. The handle
 4083        is closed when the ccb is terminated (apply-uc or abort-uc).
 4084 
 4085        And the CCB record could be changed in MDS thread if CCB is aborted.
 4086        Lock/unlock is here to ensure no race-condition b/w the MDS thread
 4087        and IMM application thread. */
 4088     m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 4089 
 4090     imma_oi_ccb_record_augment(cl_node, ccbId, privateOmHandle,
 4091                                privateAoHandle);
 4092 
 4093     m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
 4094 
 4095     if (privateAoHandle) {
 4096       *ownerHandle = privateAoHandle;
 4097     }
 4098 
 4099     TRACE("ownerHandle:%llx", *ownerHandle);
 4100 
 4101   } else if (privateOmHandle &&
 4102                   privateOmHandle != ccb_oi_record->privateAugOmHandle) {
 4103     osafassert(immsv_om_handle_finalize);
 4104     immsv_om_handle_finalize(
 4105         privateOmHandle); /* Also finalizes admo handles & ccb handles*/
 4106   }
 4107 
 4108   if (out_evt) {
 4109     free(out_evt);
 4110     out_evt = NULL;
 4111   }
 4112 
 4113 lock_fail:
 4114   TRACE_LEAVE();
 4115   return rc;
 4116 }