Hi Neel,

1. Why do we have to keep a list of current member nodes of the cluster?
I think all IMMND wants to know is if it's currently a member node.
It shouldn't care about membership of other nodes.

IMMND_CB.immnd_clm_list is not necessary.
The immnd_clm_node_*() functions in immnd_db.c are also not needed.

The callback can be like this:

for (i = 0; i < notificationBuffer->numberOfItems; i++) {
     node_id = notificationBuffer->notification[i].clusterNode.nodeId;
     if (node_id == immnd_cb->node_id) {
         if (notificationBuffer->notification[i].clusterChange == 
SA_CLM_NODE_LEFT) {
             if (immnd_clm_node_change(true) != NCSCC_RC_SUCCESS) {
                 TRACE_4(" immnd_proc_ckpt_clm_node_left failed");
             }
         }
         if (notificationBuffer->notification[i].clusterChange == 
SA_CLM_NODE_NO_CHANGE
                 || notificationBuffer->notification[i].clusterChange == 
SA_CLM_NODE_JOINED) {
             if (node_id == immnd_cb->node_id) {
                 if (immnd_clm_node_change(false) != NCSCC_RC_SUCCESS) {
                     TRACE_4("immnd_proc_ckpt_clm_node_joined  failed");
                 }
             }
         }
     }
}



2. The trackFlags should include SA_TRACK_LOCAL
rc = saClmClusterTrack_4(immnd_cb->clm_hdl, 
SA_TRACK_CURRENT|SA_TRACK_CHANGES|SA_TRACK_LOCAL, NULL);

So that we can avoid unwanted notifications when other nodes join/leave the 
cluster.



BR,

Hung Nguyen - DEK Technologies


--------------------------------------------------------------------------------
From: Neelakanta Reddy reddy.neelaka...@oracle.com
Sent: Friday, February 24, 2017 8:51PM
To: Hung Nguyen, Zoran Milinkovic
     hung.d.ngu...@dektech.com.au, zoran.milinko...@ericsson.com
Cc: Opensaf-devel
     opensaf-devel@lists.sourceforge.net
Subject: [PATCH 3 of 3] imm: immnd changes for integrating IMM with CLMS 
[#1640] v2


  src/imm/Makefile.am           |    5 +-
  src/imm/immnd/ImmModel.cc     |   44 +++++++-
  src/imm/immnd/ImmModel.h      |    2 +
  src/imm/immnd/immnd_cb.h      |   18 +++
  src/imm/immnd/immnd_clm.c     |  200 
++++++++++++++++++++++++++++++++++++++++++
  src/imm/immnd/immnd_db.c      |  125 ++++++++++++++++++++++++++
  src/imm/immnd/immnd_evt.c     |   31 +++++-
  src/imm/immnd/immnd_init.h    |    7 +
  src/imm/immnd/immnd_main.c    |   42 ++++++++-
  src/imm/immnd/immnd_mds.c     |   30 ++++++-
  src/nid/nodeinit.conf.payload |    2 +-
  11 files changed, 489 insertions(+), 17 deletions(-)


diff --git a/src/imm/Makefile.am b/src/imm/Makefile.am
--- a/src/imm/Makefile.am
+++ b/src/imm/Makefile.am
@@ -2,6 +2,7 @@
  #
  # (C) Copyright 2016 The OpenSAF Foundation
  # Copyright Ericsson AB 2017 - All Rights Reserved.
+# Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
  #
  # This program is distributed in the hope that it will be useful, but
  # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -352,6 +353,7 @@ bin_osafimmnd_SOURCES = \
        src/imm/immnd/immnd_main.c \
        src/imm/immnd/immnd_mds.c \
        src/imm/immnd/immnd_proc.c \
+       src/imm/immnd/immnd_clm.c \
        src/imm/immnd/ImmAttrValue.cc \
        src/imm/immnd/ImmSearchOp.cc \
        src/imm/immnd/ImmModel.cc
@@ -359,7 +361,8 @@ bin_osafimmnd_SOURCES = \
  bin_osafimmnd_LDADD = \
        lib/libimm_common.la \
        lib/libSaAmf.la \
-       lib/libopensaf_core.la
+       lib/libopensaf_core.la \
+       lib/libSaClm.la
  
  bin_osafimmpbed_CXXFLAGS = $(AM_CXXFLAGS)
  
diff --git a/src/imm/immnd/ImmModel.cc b/src/imm/immnd/ImmModel.cc
--- a/src/imm/immnd/ImmModel.cc
+++ b/src/imm/immnd/ImmModel.cc
@@ -2,6 +2,7 @@
   *
   * (C) Copyright 2008 The OpenSAF Foundation
   * Copyright Ericsson AB 2009, 2017 - All Rights Reserved.
+ * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -671,12 +672,12 @@ immModel_pbePrtoPurgeMutations(IMMND_CB
      ConnVector::iterator cvi;
      unsigned int ix = 0;
      ImmModel::instance(&cb->immModel)->pbePrtoPurgeMutations(nodeId, cv);
-    *reqArrSize = (SaUint32T) cv.size();
-    if(*reqArrSize) {
-            *reqConnArr = (SaUint32T *) malloc((*reqArrSize)* 
sizeof(SaUint32T));
-             for(cvi = cv.begin(); cvi!= cv.end();++cvi,++ix) {
-                 (*reqConnArr)[ix] = (*cvi);
-             }
+    if(reqArrSize && reqConnArr && cv.size()){
+        *reqArrSize = (SaUint32T) cv.size();
+        *reqConnArr = (SaUint32T *) malloc((*reqArrSize)* sizeof(SaUint32T));
+        for(cvi = cv.begin(); cvi!= cv.end();++cvi,++ix) {
+            (*reqConnArr)[ix] = (*cvi);
+        }
      }
  }
  
@@ -1162,6 +1163,12 @@ immModel_protocol51Allowed(IMMND_CB *cb)
      return ImmModel::instance(&cb->immModel)->protocol51Allowed();
  }
  
+bool
+immModel_protocol52Allowed(IMMND_CB *cb)
+{
+    return ImmModel::instance(&cb->immModel)->protocol52Allowed();
+}
+
  OsafImmAccessControlModeT
  immModel_accessControlMode(IMMND_CB *cb)
  {
@@ -4056,6 +4063,30 @@ ImmModel::protocol51Allowed()
      return noStdFlags & OPENSAF_IMM_FLAG_PRT51_ALLOW;
  }
  
+bool
+ImmModel::protocol52Allowed()
+{
+    //TRACE_ENTER();
+    /* Assume that all nodes are running the same version when loading
+    if (sImmNodeState == IMM_NODE_LOADING) {
+        return true;
+    }*/
+    ObjectMap::iterator oi = sObjectMap.find(immObjectDn);
+    if(oi == sObjectMap.end()) {
+        return false;
+    }
+
+    ObjectInfo* immObject =  oi->second;
+    ImmAttrValueMap::iterator avi =
+       immObject->mAttrValueMap.find(immAttrNostFlags);
+    osafassert(avi != immObject->mAttrValueMap.end());
+    osafassert(!(avi->second->isMultiValued()));
+    ImmAttrValue* valuep = avi->second;
+    unsigned int noStdFlags = valuep->getValue_int();
+
+    //TRACE_LEAVE();
+    return noStdFlags & OPENSAF_IMM_FLAG_PRT52_ALLOW;
+}
  
  bool
  ImmModel::protocol41Allowed()
@@ -5077,6 +5108,7 @@ ImmModel::adminOwnerDelete(SaUint32T own
  
                          noStdFlags |= OPENSAF_IMM_FLAG_PRT51_ALLOW;
                      }
+                    noStdFlags |= OPENSAF_IMM_FLAG_PRT52_ALLOW;
                      valuep->setValue_int(noStdFlags);
                      LOG_NO("%s changed to: 0x%x", immAttrNostFlags.c_str(), 
noStdFlags);
                      /* END Temporary code. */
diff --git a/src/imm/immnd/ImmModel.h b/src/imm/immnd/ImmModel.h
--- a/src/imm/immnd/ImmModel.h
+++ b/src/imm/immnd/ImmModel.h
@@ -1,6 +1,7 @@
  /*      -*- OpenSAF  -*-
   *
   * (C) Copyright 2008 The OpenSAF Foundation
+ * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -117,6 +118,7 @@ public:
      bool                protocol47Allowed();
      bool                protocol50Allowed();
      bool                protocol51Allowed();
+    bool                protocol52Allowed();
      bool                oneSafe2PBEAllowed();
      bool                purgeSyncRequest(SaUint32T clientId);
      bool                verifySchemaChange(const std::string& className,
diff --git a/src/imm/immnd/immnd_cb.h b/src/imm/immnd/immnd_cb.h
--- a/src/imm/immnd/immnd_cb.h
+++ b/src/imm/immnd/immnd_cb.h
@@ -1,6 +1,7 @@
  /*      -*- OpenSAF  -*-
   *
   * (C) Copyright 2008 The OpenSAF Foundation
+ * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -43,6 +44,11 @@ typedef struct immnd_om_search_node {
        struct immnd_om_search_node *next;
  } IMMND_OM_SEARCH_NODE;
  
+typedef struct immnd_clm_node_list {
+       NCS_PATRICIA_NODE patnode;
+       NCS_NODE_ID node_id;
+} IMMND_CLM_NODE_LIST;
+
  typedef struct immnd_immom_client_node {
        NCS_PATRICIA_NODE patnode;
        SaImmHandleT imm_app_hdl;       /* index for the client tree */
@@ -181,6 +187,11 @@ typedef struct immnd_cb_tag {
        SaSelectionObjectT amf_sel_obj; /* Selection Object for AMF events */
        int nid_started;        /* true if started by NID */
        bool isNodeTypeController; // true node type is controller
+       SaSelectionObjectT clmSelectionObject; /* Selection object to wait for 
clms events*/
+        NCS_SEL_OBJ clm_init_sel_obj; /* Selection object wait for  clms 
intialization*/
+        bool isClmNodeJoined; /* True => If clm joined the cluster*/
+        //bool protocol52Allowed; // True, if protocol52 is allowed.
+       NCS_PATRICIA_TREE immnd_clm_list;       /* IMMND_IMM_CLIENT_NODE - node 
*/
  } IMMND_CB;
  
  /* CB prototypes */
@@ -200,6 +211,13 @@ uint32_t immnd_client_node_tree_init(IMM
  void immnd_client_node_tree_cleanup(IMMND_CB *cb);
  void immnd_client_node_tree_destroy(IMMND_CB *cb);
  
+uint32_t immnd_clm_node_list_init(IMMND_CB *cb);
+void immnd_clm_node_get(IMMND_CB *cb, NODE_ID node, IMMND_CLM_NODE_LIST 
**imm_clm_node);
+uint32_t immnd_clm_node_add(IMMND_CB *cb,  NODE_ID key);
+uint32_t immnd_clm_node_delete(IMMND_CB *cb, IMMND_CLM_NODE_LIST 
*immnd_clm_node);
+void immnd_clm_node_cleanup(IMMND_CB *cb);
+void immnd_clm_node_destroy(IMMND_CB *cb);
+
  /*
    #define m_IMMSV_CONVERT_EXPTIME_TEN_MILLI_SEC(t) \
    SaTimeT now; \
diff --git a/src/imm/immnd/immnd_clm.c b/src/imm/immnd/immnd_clm.c
new file mode 100644
--- /dev/null
+++ b/src/imm/immnd/immnd_clm.c
@@ -0,0 +1,200 @@
+/*      -*- OpenSAF -*-
+ *
+ * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Oracle
+ *
+ */
+
+#include "immnd.h"
+#include "base/osaf_time.h"
+
+/****************************************************************************
+ * Name : immnd_clm_node_change
+ *
+ * Description :
+ *     When the clm clusterchange happens the function is called.
+ *     
+ * Arguments:
+ *     left:  True if clm left the node else false
+ *
+ *  Return Values :
+ *     NCSCC_RC_SUCCESS if change is completed sucessfully.
+ *
+****************************************************************************/
+uint32_t immnd_clm_node_change(bool left){
+       IMMSV_EVT send_evt;
+       TRACE_ENTER();
+        uint32_t rc = NCSCC_RC_SUCCESS;
+       if(left){
+               immnd_cb->isClmNodeJoined = false;
+               TRACE("isClmNodeJoined is set to false, protocol52=%x", 
immModel_protocol52Allowed(immnd_cb));
+       } else {
+               immnd_cb->isClmNodeJoined = true;
+               TRACE("isClmNodeJoined is set to true, protocol52=%x", 
immModel_protocol52Allowed(immnd_cb));
+       }
+       
+       if (immModel_protocol52Allowed(immnd_cb)){
+               SaImmHandleT clientHdl = 0;
+               IMMND_IMM_CLIENT_NODE * client_node = NULL;
+               send_evt.type = IMMSV_EVT_TYPE_IMMA;
+               immnd_client_node_getnext(immnd_cb, 0, &client_node);
+               while(client_node){
+                       memset(&send_evt, '\0', sizeof(IMMSV_EVT));
+                       if (client_node->version.minorVersion >= 0x12 &&
+                                       client_node->version.majorVersion == 
0x2 &&
+                                       client_node->version.releaseCode == 
'A') {
+                               if(immnd_cb->isClmNodeJoined){
+                                        send_evt.info.imma.type = 
IMMA_EVT_ND2A_IMM_CLM_NODE_JOINED;
+                                        TRACE("Sending Node Joined message to 
client handle %llx", client_node->imm_app_hdl);
+                                } else {
+                                        send_evt.info.imma.type = 
IMMA_EVT_ND2A_IMM_CLM_NODE_LEFT;
+                                        TRACE("Sending Node Left message to 
client handle %llx", client_node->imm_app_hdl);
+                                }
+
+                               if(immnd_mds_msg_send(immnd_cb, 
client_node->sv_id,
+                                                       
client_node->agent_mds_dest, &send_evt) != NCSCC_RC_SUCCESS) {
+                                       TRACE("Sending clm change to client id 
%llx failed", client_node->imm_app_hdl);
+                               }else {
+                                        TRACE("immnd_mds_msg_send success");
+                                }
+                       }
+                       clientHdl = client_node->imm_app_hdl;
+                       immnd_client_node_getnext(immnd_cb, clientHdl, 
&client_node);
+               }
+       }
+       TRACE_LEAVE();
+       return rc;
+}
+
+/****************************************************************************
+ * Name : immnd_clm_track_cbk
+ *
+ * Description :
+ *         CLM callback for tracking the node membership status.
+ *         Depending upon the membership status (joining/leaving cluster)
+ *         of a node with node_id of present node clm_join or clm_left will
+ *         be broadcasted to all imma agents.
+ *
+ *  Return Values : None.
+ *
+****************************************************************************/
+static void immnd_clm_track_cbk(const SaClmClusterNotificationBufferT_4 
*notificationBuffer,
+        SaUint32T numberOfMembers, SaInvocationT invocation,
+        const SaNameT *rootCauseEntity, const SaNtfCorrelationIdsT 
*correlationIds,
+        SaClmChangeStepT step, SaTimeT timeSupervision, SaAisErrorT error)
+{
+       NCS_NODE_ID node_id;
+        uint32_t i = 0;
+       IMMND_CLM_NODE_LIST * imm_clm_node = NULL ;
+
+        TRACE_ENTER2("Returned error value from callback is %d",error);
+
+        if (error != SA_AIS_OK)
+                return;
+
+       for (i = 0; i < notificationBuffer->numberOfItems; i++) {
+               switch(step) {
+                       case SA_CLM_CHANGE_COMPLETED:
+                               node_id = 
notificationBuffer->notification[i].clusterNode.nodeId;
+                                immnd_clm_node_get(immnd_cb, node_id, 
&imm_clm_node);
+                               
if(notificationBuffer->notification[i].clusterChange == SA_CLM_NODE_LEFT){
+                                       if(imm_clm_node){
+                                               if( node_id == 
immnd_cb->node_id){
+                                                       if 
(immnd_clm_node_change(true) != NCSCC_RC_SUCCESS) {
+                                                               TRACE_4(" 
immnd_proc_ckpt_clm_node_left failed");
+                                                       }
+                                               }
+                                               immnd_clm_node_delete(immnd_cb, 
imm_clm_node);
+                                               TRACE("Node %x left the CLM 
membership", node_id);
+                                       }else if(node_id == immnd_cb->node_id){
+                                               TRACE("IMMND restarted when 
node is locked");
+                                               if (immnd_clm_node_change(true) 
!= NCSCC_RC_SUCCESS) {
+                                                       TRACE_4(" 
immnd_proc_ckpt_clm_node_left failed");
+                                               }
+                                       }
+                               } else if(!imm_clm_node){
+                                       if 
((notificationBuffer->notification[i].clusterChange == SA_CLM_NODE_NO_CHANGE) ||
+                                                       
(notificationBuffer->notification[i].clusterChange == SA_CLM_NODE_JOINED) ||
+                                                       
(notificationBuffer->notification[i].clusterChange == 
SA_CLM_NODE_RECONFIGURED)) {
+                                               if( node_id == 
immnd_cb->node_id){
+                                                       if 
(immnd_clm_node_change(false) != NCSCC_RC_SUCCESS) {
+                                                               
TRACE_4("immnd_proc_ckpt_clm_node_joined  failed");
+                                                       }
+                                               }
+                                               if 
(immnd_clm_node_add(immnd_cb, node_id) != NCSCC_RC_SUCCESS) {
+                                                       
TRACE_4("immnd_clm_node_add failed");
+                                               }
+
+                                               TRACE("Node %x Joined the CLM 
membership", node_id);
+                                       }
+                               }
+
+                               break;
+                       default:
+                               break;
+               }
+       }
+       TRACE_LEAVE();
+}
+
+static SaVersionT clmVersion = { 'B', 0x04, 0x01 };
+static const SaClmCallbacksT_4 clm_callbacks = {
+       0,
+       immnd_clm_track_cbk /*saClmClusterTrackCallback*/
+};
+
+/****************************************************************************
+ * Name : immnd_clm_init_thread
+ *
+ * Description :
+ *    Registers with the CLM service (B.04.01).
+ *  Return Values : None.
+ *
+ ****************************************************************************/
+void immnd_init_with_clm(void)
+{
+       SaAisErrorT rc = SA_AIS_OK;
+
+       TRACE_ENTER();
+
+       rc = saClmInitialize_4(&immnd_cb->clm_hdl, &clm_callbacks, &clmVersion);
+       while ((rc == SA_AIS_ERR_TRY_AGAIN) || (rc == SA_AIS_ERR_TIMEOUT) ||
+                       (rc == SA_AIS_ERR_UNAVAILABLE)) {
+               osaf_nanosleep(&kHundredMilliseconds);
+               rc = saClmInitialize_4(&immnd_cb->clm_hdl, &clm_callbacks, 
&clmVersion);
+       }
+       if (rc != SA_AIS_OK) {
+               LOG_ER("saClmInitialize failed with error: %d", rc);
+               TRACE_LEAVE();
+               exit(EXIT_FAILURE);
+       }
+
+       rc = saClmSelectionObjectGet(immnd_cb->clm_hdl, 
&immnd_cb->clmSelectionObject);
+       if (rc != SA_AIS_OK) {
+               LOG_ER("saClmSelectionObjectGet failed with error: %d", rc);
+               TRACE_LEAVE();
+               exit(EXIT_FAILURE);
+       }
+       //rc = saClmClusterTrack_4(immnd_cb->clm_hdl, SA_TRACK_CHANGES_ONLY, 
NULL);
+       rc = saClmClusterTrack_4(immnd_cb->clm_hdl, 
SA_TRACK_CURRENT|SA_TRACK_CHANGES, NULL);
+       if (rc != SA_AIS_OK) {
+               LOG_ER("saClmClusterTrack failed with error: %d", rc);
+                TRACE_LEAVE();
+                exit(EXIT_FAILURE);
+        }
+        TRACE("CLM Initialization SUCCESS......");
+        TRACE_LEAVE();
+        //return NULL;
+        return ;
+}
+
diff --git a/src/imm/immnd/immnd_db.c b/src/imm/immnd/immnd_db.c
--- a/src/imm/immnd/immnd_db.c
+++ b/src/imm/immnd/immnd_db.c
@@ -1,6 +1,7 @@
  /*      -*- OpenSAF  -*-
   *
   * (C) Copyright 2008 The OpenSAF Foundation
+ * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -172,6 +173,130 @@ void immnd_client_node_tree_destroy(IMMN
        return;
  }
  
+/****************************************************************************
+  Name          : immnd_clm_node_list_init
+  Description   : This routine is used to initialize the IMMND clm node list 
init
+  Arguments     : cb - pointer to the IMMND Control Block
+  Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
+  Notes         : None
+*****************************************************************************/
+uint32_t immnd_clm_node_list_init(IMMND_CB *cb)
+{
+        NCS_PATRICIA_PARAMS param;
+        memset(&param, 0, sizeof(NCS_PATRICIA_PARAMS));
+
+        param.key_size = sizeof(NODE_ID);
+        if (ncs_patricia_tree_init(&cb->immnd_clm_list, &param) != 
NCSCC_RC_SUCCESS) {
+                return NCSCC_RC_FAILURE;
+        }
+        return NCSCC_RC_SUCCESS;
+}
+
+/****************************************************************************
+ * Name          : immnd_clm_node_get
+ * Description   : Function to get the clm node from the clm list.
+ * Arguments     : IMMND_CB *cb, - IMMND Control Block
+ *               : NODE_ID  - CLM nodeid.
+ * Return Values : IMMND_CLM_NODE_LIST ** immnd_clm_node_list
+ * Notes         : None.
+ *****************************************************************************/
+void immnd_clm_node_get(IMMND_CB *cb, NODE_ID node, IMMND_CLM_NODE_LIST 
**imm_clm_node)
+{
+        *imm_clm_node = (IMMND_CLM_NODE_LIST*)
+            ncs_patricia_tree_get(&cb->immnd_clm_list, (uint8_t *)&node);
+        return;
+}
+
+/****************************************************************************
+  Name          : immnd_clm_node_add
+  Description   : This routine adds the new node to immnd_clm_node_list
+  Arguments     : immnd_tree - IMMND Tree.
+                  NODE_ID -  CLM  Node.
+  Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
+  Notes         : The caller takes the cb lock before calling this function
+*****************************************************************************/
+uint32_t immnd_clm_node_add(IMMND_CB *cb,  NODE_ID key)
+{
+        IMMND_CLM_NODE_LIST *immnd_clm_node = calloc(1, 
sizeof(IMMND_CLM_NODE_LIST));
+        immnd_clm_node->node_id = key;
+        immnd_clm_node->patnode.key_info = (uint8_t *)&immnd_clm_node->node_id;
+
+        if (ncs_patricia_tree_add(&cb->immnd_clm_list, 
&immnd_clm_node->patnode) != NCSCC_RC_SUCCESS) {
+                LOG_ER("IMMND - ncs_patricia_tree_add failed in 
immnd_clm_node_add");
+                free(immnd_clm_node);
+                return NCSCC_RC_FAILURE;
+        }
+
+        return NCSCC_RC_SUCCESS;
+}
+
+/****************************************************************************
+  Name          : immnd_clm_node_delete
+  Description   : This routine deletes the node from immnd_clm_node_list
+  Arguments     : IMMD_CB *cb - IMMD Control Block.
+                : NODE_ID -  CLM  Node.
+  Return Values : None
+*****************************************************************************/
+uint32_t immnd_clm_node_delete(IMMND_CB *cb, IMMND_CLM_NODE_LIST 
*immnd_clm_node)
+{
+        uint32_t rc = NCSCC_RC_SUCCESS;
+
+        /* Remove the Node from the client tree */
+        if (ncs_patricia_tree_del(&cb->immnd_clm_list, (NCS_PATRICIA_NODE 
*)&immnd_clm_node->patnode) != NCSCC_RC_SUCCESS) {
+                LOG_WA("IMMND CLM NODE DELETE FROM PAT TREE FAILED");
+                rc = NCSCC_RC_FAILURE;
+        }
+
+        /* Free the Client Node */
+        if (immnd_clm_node) {
+                free(immnd_clm_node);
+        }
+        return rc;
+}
+
+/****************************************************************************
+  Name          : immnd_clm_node_cleanup
+  Description   : This routine Free all the nodes in clm_node_list.
+  Arguments     : IMMD_CB *cb - IMMD Control Block.
+  Return Values : None
+****************************************************************************/
+void immnd_clm_node_cleanup(IMMND_CB *cb)
+{
+        IMMND_CLM_NODE_LIST *immnd_clm_node;
+        NODE_ID key;
+        memset(&key, 0, sizeof(NODE_ID));
+
+        /* Get the First Node */
+        immnd_clm_node = (IMMND_CLM_NODE_LIST*)
+            ncs_patricia_tree_getnext(&cb->immnd_clm_list, (uint8_t *)&key);
+        while (immnd_clm_node) {
+                key = immnd_clm_node->node_id;
+                immnd_clm_node_delete(cb, immnd_clm_node);
+
+                immnd_clm_node = (IMMND_CLM_NODE_LIST*)
+                    ncs_patricia_tree_getnext(&cb->immnd_clm_list, (uint8_t 
*)&key);
+        }
+
+        return;
+}
+
+/****************************************************************************
+  Name          : immnd_clm_node_destroy
+  Description   : This routine destroys the IMMND clm node list.
+  Arguments     : IMMD_CB *cb - IMMD Control Block.
+  Return Values : None
+*****************************************************************************/
+void immnd_clm_node_destroy(IMMND_CB *cb)
+{
+        /* cleanup the clm list */
+        immnd_clm_node_cleanup(cb);
+
+        /* destroy the tree */
+        ncs_patricia_tree_destroy(&cb->immnd_clm_list);
+
+        return;
+}
+
  /* FEVS MESSAGE QUEUEING */
  
  /*************************************************************************
diff --git a/src/imm/immnd/immnd_evt.c b/src/imm/immnd/immnd_evt.c
--- a/src/imm/immnd/immnd_evt.c
+++ b/src/imm/immnd/immnd_evt.c
@@ -1,6 +1,7 @@
  /*      -*- OpenSAF  -*-
   *
   * (C) Copyright 2008 The OpenSAF Foundation
+ * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -786,6 +787,16 @@ static uint32_t immnd_evt_proc_imm_init(
                }
        }
  
+       if (evt->info.initReq.version.minorVersion >= 0x12 &&
+                       evt->info.initReq.version.majorVersion == 0x2 &&
+                       evt->info.initReq.version.releaseCode == 'A') {
+               if ( immModel_protocol52Allowed(cb) && !cb->isClmNodeJoined && 
cb->mIntroduced != 2) {
+                       error = SA_AIS_ERR_UNAVAILABLE;
+                       LOG_ER("CLM node went down prot=%x 
nodeJoined=%x",immModel_protocol52Allowed(cb), cb->isClmNodeJoined);
+                       goto clm_left;
+               }
+       }
+
        cl_node = calloc(1, sizeof(IMMND_IMM_CLIENT_NODE));
        if (cl_node == NULL) {
                LOG_ER("IMMND - Client Alloc Failed");
@@ -835,6 +846,7 @@ static uint32_t immnd_evt_proc_imm_init(
        send_evt.info.imma.info.initRsp.immHandle = cl_node->imm_app_hdl;
        error = SA_AIS_OK;
  
+ clm_left:
   agent_rsp:
        send_evt.type = IMMSV_EVT_TYPE_IMMA;
        send_evt.info.imma.type = IMMA_EVT_ND2A_IMM_INIT_RSP;
@@ -9419,6 +9431,14 @@ static void immnd_evt_proc_finalize_sync
                                
"SA_IMM_KEEP_REPOSITORY":"SA_IMM_INIT_FROM_FILE");
                }
                immnd_adjustEpoch(cb, true);
+               /* If the node is payload give the indication to 
clm_init_sel_obj
+                *  because payload nodes are not subscribing for AVD up
+                */
+               if(!immnd_cb->isNodeTypeController && !cb->clm_hdl){
+                       TRACE_8("clm_init_sel_obj indication is given at 
payload");
+                       ncs_sel_obj_ind(&immnd_cb->clm_init_sel_obj);
+
+                }
  
                /* Sync completed for client => trigger active resurrect. */
                memset(&send_evt, '\0', sizeof(IMMSV_EVT));
@@ -9429,25 +9449,25 @@ static void immnd_evt_proc_finalize_sync
                        prev_hdl = cl_node->imm_app_hdl;
                        if(!(cl_node->mIsResurrect)) {
                                LOG_WA("Found active client id: %llx version:%c 
%u %u, after sync, should not happen",
-                                        cl_node->imm_app_hdl, 
cl_node->version.releaseCode,
-                                       cl_node->version.majorVersion,
-                                       cl_node->version.minorVersion);
+                                               cl_node->imm_app_hdl, 
cl_node->version.releaseCode,
+                                               cl_node->version.majorVersion,
+                                               cl_node->version.minorVersion);
                                immnd_client_node_getnext(cb, prev_hdl, 
&cl_node);
                                continue;
                        }
                        /* Send resurrect message. */
                        if (immnd_mds_msg_send(cb, cl_node->sv_id,
-                                   cl_node->agent_mds_dest, 
&send_evt)!=NCSCC_RC_SUCCESS)
+                                               cl_node->agent_mds_dest, 
&send_evt)!=NCSCC_RC_SUCCESS)
                        {
                                LOG_WA("Failed to send active resurrect 
message");
  
                        }
+                       ++count;
                        /* Remove the temporary client node. */
                        immnd_client_node_del(cb, cl_node);
                        memset(cl_node, '\0', sizeof(IMMND_IMM_CLIENT_NODE));
                        free(cl_node);
                        cl_node = NULL;
-                       ++count;
                        immnd_client_node_getnext(cb, 0, &cl_node);
                }
                TRACE_2("Triggered %u active resurrects", count);
@@ -10417,6 +10437,7 @@ static uint32_t immnd_evt_proc_mds_evt(I
                        }
                }
                LOG_NO("IMMD SERVICE IS DOWN, HYDRA IS CONFIGURED => 
UNREGISTERING IMMND form MDS");
+
                immnd_mds_unregister(cb);
                /* Discard local clients ...  */
                immnd_proc_discard_other_nodes(cb); /* Isolate from the rest of 
cluster */
diff --git a/src/imm/immnd/immnd_init.h b/src/imm/immnd/immnd_init.h
--- a/src/imm/immnd/immnd_init.h
+++ b/src/imm/immnd/immnd_init.h
@@ -1,6 +1,7 @@
  /*      -*- OpenSAF  -*-
   *
   * (C) Copyright 2008 The OpenSAF Foundation
+ * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -322,6 +323,7 @@ extern "C" {
        bool immModel_protocol46Allowed(IMMND_CB *cb);
        bool immModel_protocol47Allowed(IMMND_CB *cb);
        bool immModel_protocol50Allowed(IMMND_CB *cb);
+       bool immModel_protocol52Allowed(IMMND_CB *cb);
        bool immModel_oneSafe2PBEAllowed(IMMND_CB *cb);
        OsafImmAccessControlModeT immModel_accessControlMode(IMMND_CB *cb);
        const char *immModel_authorizedGroup(IMMND_CB *cb);
@@ -502,4 +504,9 @@ void freeSearchNext(IMMSV_OM_RSP_SEARCH_
  uint32_t immnd_proc_server(uint32_t *timeout);
  /* End : ----  immnd_proc.c  */
  
+/* File : ----  immnd_clm.c */
+uint32_t immnd_clm_node_change(bool left);
+void immnd_init_with_clm();
+/* Ebd : ----  immnd_clm.c */
+
  #endif  // IMM_IMMND_IMMND_INIT_H_
diff --git a/src/imm/immnd/immnd_main.c b/src/imm/immnd/immnd_main.c
--- a/src/imm/immnd/immnd_main.c
+++ b/src/imm/immnd/immnd_main.c
@@ -1,6 +1,7 @@
  /*      -*- OpenSAF  -*-
   *
   * (C) Copyright 2008-2010 The OpenSAF Foundation
+ * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -41,6 +42,8 @@
  #define FD_TERM 0
  #define FD_AMF 1
  #define FD_MBX 2
+#define FD_CLM_INIT 3
+#define FD_CLM 4
  
  static IMMND_CB _immnd_cb;
  IMMND_CB *immnd_cb = &_immnd_cb;
@@ -86,6 +89,7 @@ static uint32_t immnd_cb_db_init(IMMND_C
        if (rc == NCSCC_RC_FAILURE)
                LOG_ER("client node tree init failed");
  
+       rc = immnd_clm_node_list_init(cb);
        return (rc);
  }
  
@@ -144,6 +148,8 @@ static uint32_t immnd_initialize(char *p
        immnd_cb->mProgName = progname;
        immnd_cb->mDir = getenv("IMMSV_ROOT_DIRECTORY");
        immnd_cb->mFile = getenv("IMMSV_LOAD_FILE");
+       immnd_cb->clm_hdl = 0;
+       immnd_cb->clmSelectionObject = -1;
        if ((envVar = getenv("IMMSV_NUM_NODES"))) {
                int numNodes = atoi(envVar);
                if(numNodes > 255) {
@@ -224,6 +230,12 @@ static uint32_t immnd_initialize(char *p
                LOG_ER("m_NCS_IPC_ATTACH FAILED");
                goto done;
        }
+       
+       /* Create a selection object for clm intialization*/
+       if ((rc = ncs_sel_obj_create(&immnd_cb->clm_init_sel_obj)) != 
NCSCC_RC_SUCCESS) {
+               LOG_ER("ncs_sel_obj_create failed for clm intialization");
+               goto done;
+       }
  
        if ((rc = immnd_mds_register(immnd_cb)) != NCSCC_RC_SUCCESS) {
                TRACE("immnd_mds_register FAILED %u", rc);
@@ -278,8 +290,8 @@ int main(int argc, char *argv[])
                                   server task when we are very bussy. */
        int maxEvt = 100;
        struct timespec start_time;
-       struct pollfd fds[3];
-       int term_fd;
+       struct pollfd fds[5];
+       int term_fd, nfds=4;;
  
        daemonize(argc, argv);
  
@@ -310,6 +322,8 @@ int main(int argc, char *argv[])
        fds[FD_AMF].events = POLLIN;
        fds[FD_MBX].fd = mbx_fd.rmv_obj;
        fds[FD_MBX].events = POLLIN;
+       fds[FD_CLM_INIT].fd = immnd_cb->clm_init_sel_obj.rmv_obj;
+        fds[FD_CLM_INIT].events = POLLIN;
  
        while (1) {
                /* Watch out for performance bug. Possibly change from 
event-count
@@ -327,7 +341,7 @@ int main(int argc, char *argv[])
                maxEvt = (timeout == 100) ? 50 : 100;
  
                /* Wait for events */
-               int ret = poll(fds, 3, (passed_time_ms < timeout) ? (timeout - 
passed_time_ms) : 0);
+               int ret = poll(fds, nfds, (passed_time_ms < timeout) ? (timeout 
- passed_time_ms) : 0);
  
                if (ret == -1) {
                        if (errno == EINTR)
@@ -377,6 +391,28 @@ int main(int argc, char *argv[])
                                }
                        }
  
+                       if (fds[FD_CLM_INIT].revents & POLLIN && 
!immnd_cb->clm_hdl) {
+                               TRACE("Initalize CLM ");
+                               
ncs_sel_obj_rmv_ind(&immnd_cb->clm_init_sel_obj, true, true);
+                               immnd_init_with_clm();
+                               nfds=5;
+                               fds[FD_CLM].fd = immnd_cb->clmSelectionObject;
+                               fds[FD_CLM].events = POLLIN;
+                       }
+
+                       if (fds[FD_CLM].revents & POLLIN) {
+                               if ((error = saClmDispatch(immnd_cb->clm_hdl, 
SA_DISPATCH_ALL)) != SA_AIS_OK) {
+                                       LOG_ER("saClmDispatch failed: %u", 
error);
+                                       if(error == SA_AIS_ERR_BAD_HANDLE){
+                                               LOG_NO("Re-initializing with 
CLMS");
+                                               
immnd_clm_node_cleanup(immnd_cb);
+                                               immnd_init_with_clm();
+                                       } else {
+                                               break;
+                                       }
+                               }
+                       }
+
                        if (eventCount >= maxEvt) {
                                /* Make some progress on background task,
                                   even when we are very busy. */
diff --git a/src/imm/immnd/immnd_mds.c b/src/imm/immnd/immnd_mds.c
--- a/src/imm/immnd/immnd_mds.c
+++ b/src/imm/immnd/immnd_mds.c
@@ -1,6 +1,7 @@
  /*      -*- OpenSAF  -*-
   *
   * (C) Copyright 2008 The OpenSAF Foundation
+ * Copyright (C) 2017, Oracle and/or its affiliates. All rights reserved.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -188,6 +189,23 @@ uint32_t immnd_mds_register(IMMND_CB *cb
                goto error1;
        }
  
+       if(cb->isNodeTypeController){
+
+               /* STEP 6: Subscribe to AVD events in MDS. This will be
+                  used for CLM registration at controllers.*/
+
+               svc_id[0]  = NCSMDS_SVC_ID_AVD;
+               svc_info.i_op = MDS_SUBSCRIBE;
+               svc_info.info.svc_subscribe.i_scope = NCSMDS_SCOPE_INTRANODE;
+               svc_info.info.svc_subscribe.i_num_svcs = 1;
+               svc_info.info.svc_subscribe.i_svc_ids = svc_id;
+
+               if (ncsmds_api(&svc_info) == NCSCC_RC_FAILURE) {
+                       LOG_WA("MDS AVD Subscription Failed");
+                       goto error1;
+               }
+       }
+
        cb->node_id = m_NCS_GET_NODE_ID;
        TRACE_2("cb->node_id:%x", cb->node_id);
  
@@ -601,7 +619,17 @@ static uint32_t immnd_mds_svc_evt(IMMND_
                priority = NCS_IPC_PRIORITY_VERY_HIGH;
  
                m_NCS_UNLOCK(&cb->immnd_immd_up_lock, NCS_LOCK_WRITE);
-       }
+       } else if (svc_evt->i_svc_id == NCSMDS_SVC_ID_AVD) {
+               if (svc_evt->i_change == NCSMDS_UP) {
+                       TRACE_8("MDS UP dest: %" PRIx64 ", node ID: %x, svc_id: 
%d",
+                                       svc_evt->i_dest, svc_evt->i_node_id, 
svc_evt->i_svc_id);
+                       //Subscribed for only INTRA NODE, only one ADEST will 
come.
+                       if (m_MDS_DEST_IS_AN_ADEST(svc_evt->i_dest) ) {
+                               TRACE_8("AVD ADEST UP");
+                               ncs_sel_obj_ind(&immnd_cb->clm_init_sel_obj);
+                       }
+               }
+       }
  
        /* IMMA events from other nodes can not happen */
        if ((svc_evt->i_svc_id == NCSMDS_SVC_ID_IMMA_OM) || (svc_evt->i_svc_id 
== NCSMDS_SVC_ID_IMMA_OI))
diff --git a/src/nid/nodeinit.conf.payload b/src/nid/nodeinit.conf.payload
--- a/src/nid/nodeinit.conf.payload
+++ b/src/nid/nodeinit.conf.payload
@@ -54,6 +54,6 @@
  #############################################################################
  
  
xxCLCCLIDIRxx/osaf-transport:TRANSPORT:S:xxCLCCLIDIRxx/osaf-transport:6000:-6:2:1:start:stop
+xxCLCCLIDIRxx/osaf-clmna:CLMNA:S:xxCLCCLIDIRxx/osaf-clmna:4000::9:1:start:stop
  
xxCLCCLIDIRxx/osaf-immnd:IMMND:S:xxCLCCLIDIRxx/osaf-immnd:48000:4:2:1:start:stop
-xxCLCCLIDIRxx/osaf-clmna:CLMNA:S:xxCLCCLIDIRxx/osaf-clmna:4000::9:1:start:stop
  
xxCLCCLIDIRxx/osaf-amfnd:AMFND:S:xxCLCCLIDIRxx/osaf-amfnd:99000::0:1:start:stop


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to