osaf/services/saf/logsv/lgs/Makefile.am |    7 +-
 osaf/services/saf/logsv/lgs/lgs_cb.h    |   15 +++
 osaf/services/saf/logsv/lgs/lgs_clm.cc  |  142 +++++++++++++++++++++++++++++++
 osaf/services/saf/logsv/lgs/lgs_clm.h   |   25 +++++
 osaf/services/saf/logsv/lgs/lgs_evt.cc  |  143 ++++++++++++++++++++++++++++++++
 osaf/services/saf/logsv/lgs/lgs_evt.h   |    2 +
 osaf/services/saf/logsv/lgs/lgs_main.cc |   28 ++++++
 osaf/services/saf/logsv/lgs/lgs_mds.cc  |   38 ++++++++-
 osaf/services/saf/logsv/lgs/lgs_util.cc |   83 ++++++++++++++++++
 9 files changed, 480 insertions(+), 3 deletions(-)


diff --git a/osaf/services/saf/logsv/lgs/Makefile.am 
b/osaf/services/saf/logsv/lgs/Makefile.am
--- a/osaf/services/saf/logsv/lgs/Makefile.am
+++ b/osaf/services/saf/logsv/lgs/Makefile.am
@@ -37,7 +37,8 @@ noinst_HEADERS = \
        lgs_mbcsv_v3.h \
        lgs_mbcsv_v5.h \
        lgs_recov.h \
-       lgs_imm_gcfg.h
+       lgs_imm_gcfg.h \
+       lgs_clm.h
 
 osaf_execbindir = $(pkglibdir)
 osaf_execbin_PROGRAMS = osaflogd
@@ -67,7 +68,8 @@ osaflogd_SOURCES = \
        lgs_mbcsv_v3.cc \
        lgs_mbcsv_v5.cc \
        lgs_recov.cc \
-       lgs_imm_gcfg.cc
+       lgs_imm_gcfg.cc \
+       lgs_clm.cc
 
 osaflogd_LDADD = \
        $(top_builddir)/osaf/tools/safimm/src/libimmutil.la \
@@ -75,4 +77,5 @@ osaflogd_LDADD = \
        $(top_builddir)/osaf/libs/saf/libSaAmf/libSaAmf.la \
        $(top_builddir)/osaf/libs/saf/libSaImm/libSaImmOi.la \
        $(top_builddir)/osaf/libs/saf/libSaImm/libSaImmOm.la \
+       $(top_builddir)/osaf/libs/saf/libSaClm/libSaClm.la \
        $(top_builddir)/osaf/libs/agents/infrastructure/rda/librda.la
diff --git a/osaf/services/saf/logsv/lgs/lgs_cb.h 
b/osaf/services/saf/logsv/lgs/lgs_cb.h
--- a/osaf/services/saf/logsv/lgs/lgs_cb.h
+++ b/osaf/services/saf/logsv/lgs/lgs_cb.h
@@ -21,6 +21,7 @@
 #include <stdbool.h>
 #include <saLog.h>
 #include <saImmOi.h>
+#include <saClm.h>
 #include <mbcsv_papi.h>
 #include <ncs_edu_pub.h>
 
@@ -55,6 +56,11 @@ typedef struct lgs_stream_list {
 } lgs_stream_list_t;
 
 typedef struct {
+       NCS_PATRICIA_NODE patnode;
+       NODE_ID node_id;
+} lgs_clm_node_t;
+
+typedef struct {
        NCS_PATRICIA_NODE pat_node;
        uint32_t client_id;
        uint32_t client_id_net;
@@ -73,6 +79,7 @@ typedef struct lgs_cb {
        MDS_DEST vaddr;         /* My identification in MDS                  */
        SaVersionT log_version; /* The version currently supported           */
        NCS_PATRICIA_TREE client_tree;  /* LGA/Library/Client instantiation 
pat. tree */
+       NCS_PATRICIA_TREE clm_node_tree;  /* LGA/Library/Client instantiation 
pat. tree */
        SaNameT comp_name;      /* Components's name LGS                     */
        SaAmfHandleT amf_hdl;   /* AMF handle, obtained thru AMF init        */
        SaSelectionObjectT amfSelectionObject;  /* Selection Object to wait for 
AMF events */
@@ -80,6 +87,9 @@ typedef struct lgs_cb {
        bool is_quiesced_set;
        SaImmOiHandleT immOiHandle;     /* IMM OI handle                        
   */
        SaSelectionObjectT immSelectionObject;  /* Selection Object to wait for 
IMM events */
+       SaSelectionObjectT clmSelectionObject;  /* Selection Object to wait for 
clms events */
+       SaClmHandleT clm_hdl;   /* CLM handle, obtained through CLM init        
*/
+       bool clm_initialized; //For CLM init status;
        SaAmfHAStateT ha_state; /* present AMF HA state of the component     */
        uint32_t last_client_id;        /* Value of last client_id assigned     
     */
        uint32_t async_upd_cnt; /* Async Update Count for Warmsync */
@@ -94,6 +104,7 @@ typedef struct lgs_cb {
                                                    down events Processing */
        LGA_DOWN_LIST *lga_down_list_tail;
 
+       NCS_SEL_OBJ clm_init_sel_obj; /* Selection object for CLM 
initialization.*/
        bool nid_started;       /**< true if started by NID */
        SaUint32T scAbsenceAllowed; /* OpenSAF global configuration for 
recovery handling */
        lgs_state_t lgs_recovery_state; /* Indicate current recovery state for 
the server */
@@ -106,5 +117,9 @@ typedef struct lgs_cb {
 extern uint32_t lgs_cb_init(lgs_cb_t *);
 extern void lgs_process_mbx(SYSF_MBX *mbx);
 extern uint32_t lgs_stream_add(lgs_cb_t *cb, log_stream_t *stream);
+extern uint32_t lgs_clm_node_del(NODE_ID node_id);
+extern uint32_t lgs_clm_node_add(NODE_ID node_id);
+extern uint32_t lgs_clm_node_find(NODE_ID node_id);
+extern bool is_client_clm_member(NODE_ID node_id, SaVersionT *ver);
 
 #endif
diff --git a/osaf/services/saf/logsv/lgs/lgs_clm.cc 
b/osaf/services/saf/logsv/lgs/lgs_clm.cc
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/logsv/lgs/lgs_clm.cc
@@ -0,0 +1,142 @@
+/*      -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * 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 "lgs.h"
+#include "lgs_clm.h"
+
+/*
+ * @brief  CLM callback for tracking node membership status.
+ *        Depending upon the membership status (joining/leaving cluster) 
+ *        of a node, LGS will add or remove node from its data base.
+ *        A node is added when it is part of the cluster and is removed
+ *        when it leaves the cluster membership. An update of status is 
+ *        sent to the clients on that node. Based on this status LGA 
+ *        will decide return code for different API calls.
+ *          
+ */
+static void lgs_clm_track_cbk(const SaClmClusterNotificationBufferT_4 
*notificationBuffer,
+               SaUint32T numberOfMembers, SaInvocationT invocation,
+               const SaNameT *rootCauseEntity, const SaNtfCorrelationIdsT 
*correlationIds,
+               SaClmChangeStepT step, SaTimeT timeSupervision, SaAisErrorT 
error)
+{
+       NODE_ID node_id;
+       SaClmClusterChangesT cluster_change;
+       SaBoolT is_member;
+       uint32_t i = 0;
+
+       TRACE_ENTER2("'%llu' '%u' '%u'", invocation, step, error);
+       if (error != SA_AIS_OK) {
+               TRACE_1("Error received in ClmTrackCallback");
+               goto done;
+       }
+       lgs_cb->clm_initialized = true;
+
+       for (i = 0; i < notificationBuffer->numberOfItems; i++) {
+               switch(step) {
+                       case SA_CLM_CHANGE_COMPLETED:
+                               is_member = 
notificationBuffer->notification[i].clusterNode.member;
+                               node_id = 
notificationBuffer->notification[i].clusterNode.nodeId;
+                               if (lgs_clm_node_find(node_id) == 
NCSCC_RC_SUCCESS) {
+                                       TRACE_1("'%x' is present in LGS db", 
node_id);
+                                       if (!is_member) {
+                                               TRACE("CLM Node : %x Left the 
cluster", node_id);
+                                               cluster_change = 
SA_CLM_NODE_LEFT;
+                                               if (lgs_clm_node_del(node_id) 
== NCSCC_RC_SUCCESS){
+                                                       if (lgs_cb->ha_state == 
SA_AMF_HA_ACTIVE)
+                                                               
send_clm_node_status_change(cluster_change, node_id);
+                                               }
+                                       }
+                               } else {
+                                       TRACE_1("'%x' is not present in LGS 
db", node_id);
+                                       if (is_member) {
+                                               TRACE("CLM Node : %x Joined the 
cluster", node_id);
+                                               cluster_change = 
SA_CLM_NODE_JOINED;
+                                               if(lgs_clm_node_add(node_id) == 
NCSCC_RC_SUCCESS) {
+                                                       if (lgs_cb->ha_state == 
SA_AMF_HA_ACTIVE)
+                                                               
send_clm_node_status_change(cluster_change, node_id);
+                                               }
+                                       } 
+                               }
+                               break;
+                       default:
+                               break;
+               }
+       }
+done:
+       TRACE_LEAVE();
+       return;
+}
+
+static const SaClmCallbacksT_4 clm_callbacks = {
+       0,
+       lgs_clm_track_cbk /*saClmClusterTrackCallback*/ 
+};
+
+/*
+ * @brief   Registers with the CLM service (B.04.01). 
+ *
+ * @return  SaAisErrorT 
+ */
+void *lgs_clm_init_thread(void *cb)
+{
+       static SaVersionT clmVersion = { 'B', 0x04, 0x01 };
+       lgs_cb_t *_lgs_cb = (lgs_cb_t *) cb;
+       SaAisErrorT rc = SA_AIS_OK;
+       TRACE_ENTER();
+       rc = saClmInitialize_4(&_lgs_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(_lgs_cb->clm_hdl, 
&lgs_cb->clmSelectionObject);
+       if (rc != SA_AIS_OK) {
+               LOG_ER("saClmSelectionObjectGet failed with error: %d", rc);
+               TRACE_LEAVE();
+               exit(EXIT_FAILURE);
+       } 
+       //TODO:subscribe for SA_TRACK_START_STEP also.
+       rc = saClmClusterTrack_4(_lgs_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;
+}
+
+/*
+ * @brief  Creates a thread to initialize with CLM. 
+ */
+void lgs_init_with_clm(void)
+{
+       pthread_t thread;
+       pthread_attr_t attr;
+       TRACE_ENTER();
+
+       pthread_attr_init(&attr);
+       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+       if (pthread_create(&thread, &attr, lgs_clm_init_thread, lgs_cb) != 0) {
+               LOG_ER("pthread_create FAILED: %s", strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+       pthread_attr_destroy(&attr);
+       TRACE_LEAVE();
+}
diff --git a/osaf/services/saf/logsv/lgs/lgs_clm.h 
b/osaf/services/saf/logsv/lgs/lgs_clm.h
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/logsv/lgs/lgs_clm.h
@@ -0,0 +1,25 @@
+/*      -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * 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 <saClm.h>
+
+#define m_LGS_GET_NODE_ID_FROM_ADEST(adest) (NODE_ID) ((uint64_t)adest >> 32)
+
+/*      
+ * @brief  Creates a thread to initialize with CLM. 
+ */     
+void lgs_init_with_clm(void);
diff --git a/osaf/services/saf/logsv/lgs/lgs_evt.cc 
b/osaf/services/saf/logsv/lgs/lgs_evt.cc
--- a/osaf/services/saf/logsv/lgs/lgs_evt.cc
+++ b/osaf/services/saf/logsv/lgs/lgs_evt.cc
@@ -23,6 +23,7 @@
 #include "lgs_mbcsv_v2.h"
 #include "lgs_recov.h"
 #include "lgs_imm_gcfg.h"
+#include "lgs_clm.h"
 
 /* Macro to validate the version */
 #define m_LOG_VER_IS_VALID(ver)   \
@@ -56,6 +57,94 @@ LGSV_LGS_LGA_API_MSG_HANDLER lgs_lga_api
 };
 
 /**
+ * Name          : lgs_clm_node_tree_init
+ * Description   : This routine is used to initialize the clm_node_tree
+ * Arguments     : lgs_cb - pointer to the lgs Control Block
+ * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
+ * Notes         : None
+ */
+uint32_t lgs_clm_node_tree_init(lgs_cb_t *lgs_cb)
+{
+       TRACE_ENTER();
+       NCS_PATRICIA_PARAMS param;
+       memset(&param, 0, sizeof(NCS_PATRICIA_PARAMS));
+
+       param.key_size = sizeof(NODE_ID);
+       if (ncs_patricia_tree_init(&lgs_cb->clm_node_tree, &param) != 
NCSCC_RC_SUCCESS) {
+               LOG_ER("lgs patricia tee init failed for clm_node_tree");
+               return NCSCC_RC_FAILURE;
+       }
+       TRACE_LEAVE();
+       return NCSCC_RC_SUCCESS;
+}
+
+/**
+ * Name          : lgs_clm_node_find 
+ * Description   : This routine finds the clm_node .
+ * Arguments     : node_id - CLM Node id
+ * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
+ * Notes         : None
+ */
+uint32_t lgs_clm_node_find(NODE_ID node_id)
+{
+       uint32_t rc = NCSCC_RC_FAILURE;
+       lgs_clm_node_t *clm_node = (lgs_clm_node_t *)
+               ncs_patricia_tree_get(&lgs_cb->clm_node_tree, (uint8_t 
*)&node_id);
+
+       if (clm_node !=  NULL)
+               rc = NCSCC_RC_SUCCESS;
+       else 
+               TRACE("node_id find in DB failed : %x",node_id);
+
+       return rc;
+}
+
+/**
+ * Name          : lgs_clm_node_add
+ * Description   : This routine adds the new node to clm_node_tree.
+ * Arguments     : node_id - CLM Node id
+ * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
+ * Notes         : None 
+ */
+uint32_t lgs_clm_node_add(NODE_ID node_id)
+{
+       TRACE_ENTER();
+       uint32_t rc = NCSCC_RC_FAILURE;
+       lgs_clm_node_t *clm_node;
+
+       clm_node = (lgs_clm_node_t *) malloc(sizeof(lgs_clm_node_t));
+       clm_node->node_id = node_id;
+       clm_node->patnode.key_info = (uint8_t *)&clm_node->node_id;
+       rc = ncs_patricia_tree_add(&lgs_cb->clm_node_tree, (NCS_PATRICIA_NODE 
*)&clm_node->patnode);
+       if (rc != NCSCC_RC_SUCCESS)
+               TRACE("node_id add to DB failed : %x",node_id);
+       TRACE_LEAVE();
+       return rc;
+}
+
+/**
+ * Name          : lgs_clm_node_del
+ * Description   : Function to Delete the clm_node.
+ * Arguments     : node_id - CLM Node id
+ * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE 
+ * Notes         : None.
+ */
+uint32_t lgs_clm_node_del(NODE_ID node_id)
+{
+       TRACE_ENTER();
+       uint32_t rc = NCSCC_RC_FAILURE;
+
+       lgs_clm_node_t *clm_node = (lgs_clm_node_t *)
+               ncs_patricia_tree_get(&lgs_cb->clm_node_tree, (uint8_t 
*)&node_id);
+       if (clm_node != NULL)
+               rc = ncs_patricia_tree_del(&lgs_cb->clm_node_tree, 
(NCS_PATRICIA_NODE *)&clm_node->patnode);
+       if (rc != NCSCC_RC_SUCCESS)
+               TRACE("node_id delete to DB failed : %x",node_id);
+       TRACE_LEAVE();
+       return rc;
+}
+
+/**
  * Get client record from client ID
  * @param client_id
  * 
@@ -583,6 +672,9 @@ uint32_t lgs_cb_init(lgs_cb_t *lgs_cb)
        lgs_cb->amfSelectionObject = -1;
        lgs_cb->immSelectionObject = -1;
        lgs_cb->mbcsv_sel_obj = -1;
+       lgs_cb->clm_hdl = 0;
+       lgs_cb->clm_initialized = false;
+       lgs_cb->clmSelectionObject = -1;
 
        /* Assign Version. Currently, hardcoded, This will change later */
        lgs_cb->log_version.releaseCode = LOG_RELEASE_CODE;
@@ -598,6 +690,12 @@ uint32_t lgs_cb_init(lgs_cb_t *lgs_cb)
        if (NCSCC_RC_SUCCESS != ncs_patricia_tree_init(&lgs_cb->client_tree, 
&reg_param))
                return NCSCC_RC_FAILURE;
 
+       /* Initialize patricia tree for CLM Node list */
+       if (NCSCC_RC_SUCCESS != lgs_clm_node_tree_init(lgs_cb)) {
+               LOG_ER("LGS: ncs_patricia_tree_init FAILED");
+               return NCSCC_RC_FAILURE;
+       }
+
        done:
        TRACE_LEAVE();
        return rc;
@@ -637,6 +735,12 @@ static uint32_t proc_initialize_msg(lgs_
                goto snd_rsp;
        }
 
+       if (is_client_clm_member(evt->fr_node_id, version) != true){
+               ais_rc = SA_AIS_ERR_UNAVAILABLE;
+               TRACE("client not a CLM member FAILED");
+               goto snd_rsp;
+       }
+
        if ((client = lgs_client_new(evt->fr_dest, 0, NULL)) == NULL) {
                ais_rc = SA_AIS_ERR_NO_MEMORY;
                goto snd_rsp;
@@ -1451,3 +1555,42 @@ void lgs_process_mbx(SYSF_MBX *mbx)
                lgs_evt_destroy(msg);
        }
 }
+
+/**
+ * @brief  Sends CLM membership status of the node to all the clients
+ *         on the node except A11 clients.
+ * @param  cluster_change (CLM membership status of node).
+ * @param  NCS node_id.
+ * @return NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE.
+ */
+uint32_t send_cluster_membership_msg_to_clients(SaClmClusterChangesT 
cluster_change, NODE_ID node_id) {
+       uint32_t rc = NCSCC_RC_SUCCESS;
+       log_client_t *rp = NULL;
+       uint32_t client_id_net;
+
+       TRACE_ENTER();
+       TRACE_3("node_id: %x, change:%u", node_id, cluster_change);
+
+       rp = reinterpret_cast<log_client_t 
*>(ncs_patricia_tree_getnext(&lgs_cb->client_tree, NULL));
+
+       while (rp != NULL) {
+               /** Store the client_id_net for get Next  */
+               client_id_net = rp->client_id_net;
+               NODE_ID tmp_node_id = 
m_LGS_GET_NODE_ID_FROM_ADEST(rp->mds_dest);
+               //Do not send to A11 client. Send only to specific Node
+               if (tmp_node_id == node_id)
+                       rc = send_clm_node_status_lib(cluster_change, 
rp->client_id, rp->mds_dest);
+
+               rp = reinterpret_cast<log_client_t *>(ncs_patricia_tree_getnext(
+                                       &lgs_cb->client_tree, 
reinterpret_cast<uint8_t *>(&client_id_net)));
+       }
+
+       TRACE_LEAVE();
+       return rc;
+}
+
+uint32_t send_clm_node_status_change(SaClmClusterChangesT cluster_change, 
NODE_ID node_id) {
+       return (send_cluster_membership_msg_to_clients(cluster_change, 
node_id));
+
+}
+
diff --git a/osaf/services/saf/logsv/lgs/lgs_evt.h 
b/osaf/services/saf/logsv/lgs/lgs_evt.h
--- a/osaf/services/saf/logsv/lgs/lgs_evt.h
+++ b/osaf/services/saf/logsv/lgs/lgs_evt.h
@@ -77,6 +77,8 @@ extern bool lgs_lga_entry_valid(lgs_cb_t
 extern uint32_t lgs_remove_lga_down_rec(lgs_cb_t *cb, MDS_DEST mds_dest);
 extern void lgs_send_write_log_ack(uint32_t client_id, SaInvocationT 
invocation, SaAisErrorT error, MDS_DEST mds_dest);
 extern void lgs_free_write_log(const lgsv_write_log_async_req_t *param);
+extern uint32_t send_clm_node_status_lib(SaClmClusterChangesT cluster_change, 
unsigned int client_id, MDS_DEST mdsDest);
+extern uint32_t send_clm_node_status_change(SaClmClusterChangesT 
cluster_change, NODE_ID node_id);
 
 SaAisErrorT create_new_app_stream(
                lgsv_stream_open_req_t *open_sync_param,
diff --git a/osaf/services/saf/logsv/lgs/lgs_main.cc 
b/osaf/services/saf/logsv/lgs/lgs_main.cc
--- a/osaf/services/saf/logsv/lgs/lgs_main.cc
+++ b/osaf/services/saf/logsv/lgs/lgs_main.cc
@@ -38,6 +38,7 @@
 #include "osaf_utility.h"
 #include "lgs_recov.h"
 #include "immutil.h"
+#include "lgs_clm.h"
 
 /* ========================================================================
  *   DEFINITIONS
@@ -49,6 +50,7 @@ enum {
        FD_MBCSV,
        FD_MBX,
        FD_CLTIMER,
+       FD_CLM,
        FD_IMM,         /* Must be the last in the fds array */
        FD_NUM
 };
@@ -332,6 +334,13 @@ static uint32_t log_initialize(void)
                goto done;
        }
 
+       /* Create a CLM selection object */
+       if ((rc = ncs_sel_obj_create(&lgs_cb->clm_init_sel_obj)) != 
NCSCC_RC_SUCCESS)
+       {
+               LOG_ER("lgsv: CLM ncs_sel_obj_create failed");
+               goto done;
+        }
+
        /*
         * Initialize a signal handler that will use the selection object.
         * The signal is sent from our script when AMF does instantiate.
@@ -501,6 +510,8 @@ int main(int argc, char *argv[])
        fds[FD_IMM].fd = lgs_cb->immSelectionObject;
        fds[FD_IMM].events = POLLIN;
 
+       lgs_cb->clmSelectionObject = lgs_cb->clm_init_sel_obj.rmv_obj;
+
        while (1) {
                if (cltimer_fd < 0 && log_rtobj_list_no() != 0) {
                        /* Needed only if any "lost" objects are found
@@ -513,6 +524,8 @@ int main(int argc, char *argv[])
                fds[FD_CLTIMER].events = POLLIN;
                fds[FD_MBCSV].fd = lgs_cb->mbcsv_sel_obj;
                fds[FD_MBCSV].events = POLLIN;
+               fds[FD_CLM].fd = lgs_cb->clmSelectionObject;
+               fds[FD_CLM].events = POLLIN;
 
                /* Protect since the reinit thread may be in the process of
                 * changing the values
@@ -567,6 +580,21 @@ int main(int argc, char *argv[])
                        }
                }
 
+               if (fds[FD_CLM].revents & POLLIN) {
+                       if (lgs_cb->clm_hdl != 0) {
+                               if ((error = saClmDispatch(lgs_cb->clm_hdl, 
SA_DISPATCH_ALL)) != SA_AIS_OK) {
+                                       LOG_ER("saClmDispatch failed: %u", 
error);
+                                       break;
+                               }
+                       } else {
+                               TRACE("init CLM ");
+                               ncs_sel_obj_rmv_ind(&lgs_cb->clm_init_sel_obj, 
true, true);
+                               ncs_sel_obj_destroy(&lgs_cb->clm_init_sel_obj); 
                        
+                               lgs_cb->clmSelectionObject = -1;
+                               lgs_init_with_clm();
+                       }
+               }
+
                if (fds[FD_CLTIMER].revents & POLLIN) {
                        /* To avoid 'stray objects', after a timeout all runtime
                         * objects that has not been restored shall be deleted
diff --git a/osaf/services/saf/logsv/lgs/lgs_mds.cc 
b/osaf/services/saf/logsv/lgs/lgs_mds.cc
--- a/osaf/services/saf/logsv/lgs/lgs_mds.cc
+++ b/osaf/services/saf/logsv/lgs/lgs_mds.cc
@@ -763,11 +763,19 @@ static uint32_t mds_enc(struct ncsmds_ca
                                goto err;
                        }
                        ncs_encode_32bit(&p8, 
msg->info.cbk_info.write_cbk.error);
+                       TRACE_8("LGSV_WRITE_LOG_CALLBACK_IND");
+               } else if (msg->info.cbk_info.type == 
LGSV_CLM_NODE_STATUS_CALLBACK) {
+                       p8 = ncs_enc_reserve_space(uba, 4);
+                       if (!p8) {
+                               TRACE("ncs_enc_reserve_space failed");
+                               goto err;
+                       }
+                       ncs_encode_32bit(&p8, 
msg->info.cbk_info.clm_node_status_cbk.clm_node_status);
+                       TRACE_8("LGSV_CLM_NODE_STATUS_CALLBACK");
                } else {
                        TRACE("unknown callback type %d", 
msg->info.cbk_info.type);
                        goto err;
                }
-               TRACE_8("LGSV_WRITE_LOG_CALLBACK_IND");
        } else {
                TRACE("unknown msg type %d", msg->type);
                goto err;
@@ -1167,6 +1175,16 @@ static uint32_t mds_svc_event(struct ncs
                                osafassert(rc == NCSCC_RC_SUCCESS);
                        }
                }
+       } else if (info->info.svc_evt.i_svc_id == NCSMDS_SVC_ID_AVD) {
+               if (info->info.svc_evt.i_change == NCSMDS_UP) {
+                       TRACE_8("MDS UP dest: %" PRIx64 ", node ID: %x, svc_id: 
%d",
+                                       info->info.svc_evt.i_dest, 
info->info.svc_evt.i_node_id, info->info.svc_evt.i_svc_id);
+                       //Subscribed for only INTRA NODE, only one ADEST will 
come.
+                       if (m_MDS_DEST_IS_AN_ADEST(info->info.svc_evt.i_dest)) {
+                               TRACE_8("AVD ADEST UP");
+                               ncs_sel_obj_ind(&lgs_cb->clm_init_sel_obj);
+                       }
+               }
        }
 
  done:
@@ -1334,6 +1352,24 @@ uint32_t lgs_mds_init(lgs_cb_t *cb, SaAm
                return rc;
        }
 
+
+       svc = NCSMDS_SVC_ID_AVD;
+        /* Now subscribe for AVD events in MDS. This will be 
+           used for CLM registration.*/
+        memset(&mds_info, '\0', sizeof(NCSMDS_INFO));
+        mds_info.i_mds_hdl = cb->mds_hdl;
+        mds_info.i_svc_id = NCSMDS_SVC_ID_LGS;
+        mds_info.i_op = MDS_SUBSCRIBE;
+        mds_info.info.svc_subscribe.i_scope = NCSMDS_SCOPE_INTRANODE;
+        mds_info.info.svc_subscribe.i_num_svcs = 1;
+        mds_info.info.svc_subscribe.i_svc_ids = &svc;
+ 
+        rc = ncsmds_api(&mds_info);
+        if (rc != NCSCC_RC_SUCCESS) {
+                LOG_ER("MDS for AVD subscribe FAILED");
+                return rc;
+        }
+
        TRACE_LEAVE();
        return rc;
 }
diff --git a/osaf/services/saf/logsv/lgs/lgs_util.cc 
b/osaf/services/saf/logsv/lgs/lgs_util.cc
--- a/osaf/services/saf/logsv/lgs/lgs_util.cc
+++ b/osaf/services/saf/logsv/lgs/lgs_util.cc
@@ -415,6 +415,89 @@ void lgs_send_write_log_ack(uint32_t cli
 }
 
 /**
+ * @brief  Send Membership status of node to a lib on that node.
+ *  
+ * @param SaClmClusterChangesT (CLM status of node) 
+ * @param client_id 
+ * @param mdsDest of client
+ *
+ * @return NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE.
+ */
+uint32_t send_clm_node_status_lib(SaClmClusterChangesT cluster_change, 
unsigned int client_id, MDS_DEST mdsDest)
+{
+       uint32_t rc = NCSCC_RC_SUCCESS;
+       NCSMDS_INFO mds_info = {0};
+       lgsv_msg_t msg;
+
+       TRACE_ENTER();
+       TRACE_3("change:%u, client_id: %u", cluster_change, client_id);
+
+       memset(&msg, 0, sizeof(lgsv_msg_t));
+       msg.type = LGSV_LGS_CBK_MSG;
+       msg.info.cbk_info.type = LGSV_CLM_NODE_STATUS_CALLBACK;
+       msg.info.cbk_info.lgs_client_id = client_id;
+       msg.info.cbk_info.inv = 0;
+       msg.info.cbk_info.clm_node_status_cbk.clm_node_status = cluster_change;
+
+       mds_info.i_mds_hdl = lgs_cb->mds_hdl;
+       mds_info.i_svc_id = NCSMDS_SVC_ID_LGS;
+       mds_info.i_op = MDS_SEND;       
+       mds_info.info.svc_send.i_msg = &msg;
+       mds_info.info.svc_send.i_to_svc = NCSMDS_SVC_ID_LGA;
+       mds_info.info.svc_send.i_priority = MDS_SEND_PRIORITY_HIGH;
+       mds_info.info.svc_send.i_sendtype = MDS_SENDTYPE_SND;
+       mds_info.info.svc_send.info.snd.i_to_dest = mdsDest;
+
+       rc = ncsmds_api(&mds_info);
+       if (rc != NCSCC_RC_SUCCESS)
+               LOG_NO("Failed (%u) to send of WRITE ack to: %" PRIx64, rc, 
mdsDest);
+
+       TRACE_LEAVE();
+        return rc;
+}
+ 
+/**
+ * @brief Checks if LGSV has already initialized with CLM service. 
+ *
+ * @return true/false.
+ */
+bool is_clm_init()
+{
+        return (((lgs_cb->clm_hdl != 0) && (lgs_cb->clm_initialized == true)) 
? true : false);
+}
+
+/**
+ * @brief  Checks CLM membership status of a client.
+ *         A.02.01 clients are always CLM member.
+ * @param  Client MDS_DEST
+ * @param  Client saf version.
+ * @return NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE.
+ */
+bool is_client_clm_member(NODE_ID node_id, SaVersionT *ver) {
+
+  //Before CLM init all clients are clm member.
+  if (is_clm_init() == false)
+    return true;
+
+  TRACE("client Version: %d.%d.%d", ver->releaseCode, ver->majorVersion, 
ver->minorVersion);
+  //CLM integration is supported from A.02.02. So old clients A.02.01 are 
always clm member.
+  if ((ver->releaseCode == LOG_RELEASE_CODE_0) &&
+      (ver->majorVersion == LOG_MAJOR_VERSION_0) &&
+      (ver->minorVersion == LOG_MINOR_VERSION_0))
+    return true;
+  /*
+    It means CLM initialization is successful and this is atleast a A.02.02 
client.
+    So check CLM membership status of client's node.
+  */
+  if (lgs_clm_node_find(node_id) != NCSCC_RC_SUCCESS)
+         return false;
+  else
+         return true;
+}
+
+
+
+/**
  * Free all dynamically allocated memory for a WRITE
  * @param param
  */

------------------------------------------------------------------------------
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to