Hi Alex,

Good work. Ack for patch 1 with some minor comments.

1)  +     ver.releaseCode > 'B')
This condition could be changed to >= ?

2) +  if (notificationBuffer->notification[i].clusterChange ==
SA_CLM_NODE_LEFT) {

Just a thought ,I think its possible for a node to become unconfigured too?
But perhaps, the usecase would be via a node lock or shutdown which would
eventually translate to NODE_LEFT.
So, i guesss it is okay to handle only SA_CLM_NODE_LEFT only.

3) +    SaVersionT version = { 'B', 4, 0 };

The minor version is irrelevant, but may be we could use use the currently
supported minor version, instead of 0.

4) +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version) &&

This is a generic comment about use of macros. May be we could begin to
move away from such macros.
But, i understand GLSv is one of those services still heavily using macros.

Cheers,
Mathi.


On Wed, Apr 12, 2017 at 6:43 PM, Alex Jones <[email protected]> wrote:

> This patch integrates LCK with CLM.
> ---
>  src/lck/Makefile.am          |   8 +-
>  src/lck/agent/gla_api.c      |  96 +++++++++++++++++
>  src/lck/agent/gla_cb.h       |   4 +
>  src/lck/agent/gla_evt.h      |  11 +-
>  src/lck/agent/gla_init.c     |  27 +++++
>  src/lck/agent/gla_mds.c      |  56 ++++++++++
>  src/lck/common/glsv_defs.h   |   9 +-
>  src/lck/lckd/gld_api.c       |  29 ++++-
>  src/lck/lckd/gld_cb.h        |   2 +-
>  src/lck/lckd/gld_clm.cc      | 131 +++++++++++++++++++++++
>  src/lck/lckd/gld_clm.h       |  17 +++
>  src/lck/lckd/gld_evt.c       | 115 +++++++++++---------
>  src/lck/lckd/gld_evt.h       |  16 +++
>  src/lck/lcknd/glnd_agent.c   |  23 ++++
>  src/lck/lcknd/glnd_api.c     |  35 ++++--
>  src/lck/lcknd/glnd_cb.c      |  10 ++
>  src/lck/lcknd/glnd_cb.h      |  12 +++
>  src/lck/lcknd/glnd_client.c  |  92 ++++++++++++++++
>  src/lck/lcknd/glnd_client.h  |  10 ++
>  src/lck/lcknd/glnd_clm.cc    | 183 +++++++++++++++++++++++++++++++
>  src/lck/lcknd/glnd_clm.h     |  17 +++
>  src/lck/lcknd/glnd_evt.c     | 250 ++++++++++++++++++++++++++++++
> +++++++------
>  src/lck/lcknd/glnd_mds.c     |  39 +++++++
>  src/lck/lcknd/glnd_mds.h     |   8 ++
>  src/lck/lcknd/glnd_res.c     |   4 +
>  src/lck/lcknd/glnd_res_req.c |  50 +++++++++
>  26 files changed, 1159 insertions(+), 95 deletions(-)
>  create mode 100644 src/lck/lckd/gld_clm.cc
>  create mode 100644 src/lck/lckd/gld_clm.h
>  create mode 100644 src/lck/lcknd/glnd_clm.cc
>  create mode 100644 src/lck/lcknd/glnd_clm.h
>
> diff --git a/src/lck/Makefile.am b/src/lck/Makefile.am
> index b7fb47b..fe8a34c 100644
> --- a/src/lck/Makefile.am
> +++ b/src/lck/Makefile.am
> @@ -152,11 +152,13 @@ bin_osaflcknd_SOURCES = \
>         src/lck/lcknd/glnd_res_req.c \
>         src/lck/lcknd/glnd_restart.c \
>         src/lck/lcknd/glnd_shm.c \
> -       src/lck/lcknd/glnd_tmr.c
> +       src/lck/lcknd/glnd_tmr.c \
> +       src/lck/lcknd/glnd_clm.cc
>
>  bin_osaflcknd_LDADD = \
>         lib/liblck_common.la \
>         lib/libSaAmf.la \
> +       lib/libSaClm.la \
>         lib/libopensaf_core.la
>
>  bin_osaflckd_CPPFLAGS = \
> @@ -175,11 +177,13 @@ bin_osaflckd_SOURCES = \
>         src/lck/lckd/gld_red.c \
>         src/lck/lckd/gld_rsc.c \
>         src/lck/lckd/gld_standby.c \
> -       src/lck/lckd/gld_tmr.c
> +       src/lck/lckd/gld_tmr.c \
> +       src/lck/lckd/gld_clm.cc
>
>  bin_osaflckd_LDADD = \
>         lib/liblck_common.la \
>         lib/libSaAmf.la \
> +       lib/libSaClm.la \
>         lib/libosaf_common.la \
>         lib/libSaImmOi.la \
>         lib/libSaImmOm.la \
> diff --git a/src/lck/agent/gla_api.c b/src/lck/agent/gla_api.c
> index 539c71b..dbe75cd 100644
> --- a/src/lck/agent/gla_api.c
> +++ b/src/lck/agent/gla_api.c
> @@ -145,6 +145,9 @@ SaAisErrorT saLckInitialize(SaLckHandleT *lckHandle,
>         }
>         rc = out_evt->error;
>         if (rc == SA_AIS_OK) {
> +    /* if the call succeeds we know glnd is a member of the cluster */
> +         gla_cb->isClusterMember = true;
> +
>                 /* create the client node and populate it */
>                 client_info =
>                     gla_client_tree_find_and_add(gla_cb, out_evt->handle,
> true);
> @@ -154,6 +157,9 @@ SaAisErrorT saLckInitialize(SaLckHandleT *lckHandle,
>                         goto err;
>                 }
>
> +    client_info->isStale = false;
> +         memcpy(&client_info->version, version, sizeof(SaVersionT));
> +
>                 /* copy the callbacks */
>                 if (lckCallbacks)
>                         memcpy((void *)&client_info->lckCallbk,
> @@ -259,6 +265,14 @@ SaAisErrorT saLckSelectionObjectGet(SaLckHandleT
> lckHandle,
>                 goto done;
>         }
>
> +  /* are we a member of the cluster? */
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version)) {
> +    if (!gla_cb->isClusterMember || client_info->isStale) {
> +      rc = SA_AIS_ERR_UNAVAILABLE;
> +      goto done;
> +    }
> +  }
> +
>         /* everything's fine.. pass the sel obj to the appl */
>         *o_sel_obj = (SaSelectionObjectT)m_GET_FD_FROM_SEL_OBJ(
>             m_NCS_IPC_GET_SEL_OBJ(&client_info->callbk_mbx));
> @@ -319,6 +333,14 @@ SaAisErrorT saLckOptionCheck(SaLckHandleT hdl,
> SaLckOptionsT *lckOptions)
>                 goto done;
>         }
>
> +  /* are we a member of the cluster? */
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version)) {
> +    if (!gla_cb->isClusterMember || client_info->isStale) {
> +      rc = SA_AIS_ERR_UNAVAILABLE;
> +      goto done;
> +    }
> +  }
> +
>         /* populate the options - as this implementation support both
> Deadlock
>            and orphan , set the values */
>         *lckOptions = SA_LCK_OPT_ORPHAN_LOCKS |
> SA_LCK_OPT_DEADLOCK_DETECTION;
> @@ -377,6 +399,14 @@ SaAisErrorT saLckDispatch(SaLckHandleT lckHandle,
> const SaDispatchFlagsT flags)
>                 goto done;
>         }
>
> +  /* are we a member of the cluster? */
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version)) {
> +    if (!gla_cb->isClusterMember || client_info->isStale) {
> +      rc = SA_AIS_ERR_UNAVAILABLE;
> +      goto done;
> +    }
> +  }
> +
>         switch (flags) {
>         case SA_DISPATCH_ONE:
>                 rc = gla_hdl_callbk_dispatch_one(gla_cb, client_info);
> @@ -599,6 +629,14 @@ SaAisErrorT saLckResourceOpen(SaLckHandleT lckHandle,
>                 goto done;
>         }
>
> +  /* are we a member of the cluster? */
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version)) {
> +    if (!gla_cb->isClusterMember || client_info->isStale) {
> +      rc = SA_AIS_ERR_UNAVAILABLE;
> +      goto done;
> +    }
> +  }
> +
>         /* check whether GLND is up or not */
>         if (!gla_cb->glnd_svc_up) {
>                 ncshm_give_hdl(client_info->lcl_lock_handle_id);
> @@ -763,6 +801,15 @@ SaAisErrorT saLckResourceOpenAsync(SaLckHandleT
> lckHandle,
>                 rc = SA_AIS_ERR_INIT;
>                 goto done;
>         }
> +
> +  /* are we a member of the cluster? */
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version)) {
> +    if (!gla_cb->isClusterMember || client_info->isStale) {
> +      rc = SA_AIS_ERR_UNAVAILABLE;
> +      goto done;
> +    }
> +  }
> +
>         /* check whether GLND is up or not */
>         if (!gla_cb->glnd_svc_up) {
>                 ncshm_give_hdl(client_info->lcl_lock_handle_id);
> @@ -887,6 +934,14 @@ SaAisErrorT saLckResourceClose(SaLckResourceHandleT
> lockResourceHandle)
>                 goto done;
>         }
>
> +  /* are we a member of the cluster? */
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version)) {
> +    if (!gla_cb->isClusterMember || client_info->isStale) {
> +      rc = SA_AIS_ERR_UNAVAILABLE;
> +      goto done;
> +    }
> +  }
> +
>         /* check whether GLND is up or not */
>         if (!gla_cb->glnd_svc_up) {
>                 ncshm_give_hdl(lockResourceHandle);
> @@ -1060,6 +1115,15 @@ SaAisErrorT saLckResourceLock(SaLckResourceHandleT
> lockResourceHandle,
>                 rc = SA_AIS_ERR_BAD_HANDLE;
>                 goto done;
>         }
> +
> +  /* are we a member of the cluster? */
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version)) {
> +    if (!gla_cb->isClusterMember || client_info->isStale) {
> +      rc = SA_AIS_ERR_UNAVAILABLE;
> +      goto done;
> +    }
> +  }
> +
>         /* check whether GLND is up or not */
>         if (!gla_cb->glnd_svc_up) {
>                 ncshm_give_hdl(lockResourceHandle);
> @@ -1252,6 +1316,14 @@ SaAisErrorT saLckResourceLockAsync(SaLckResourceHandleT
> lockResourceHandle,
>                 goto done;
>         }
>
> +  /* are we a member of the cluster? */
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version)) {
> +    if (!gla_cb->isClusterMember || client_info->isStale) {
> +      rc = SA_AIS_ERR_UNAVAILABLE;
> +      goto done;
> +    }
> +  }
> +
>         /* check whether GLND is up or not */
>         if (!gla_cb->glnd_svc_up) {
>                 ncshm_give_hdl(lockResourceHandle);
> @@ -1409,6 +1481,14 @@ SaAisErrorT saLckResourceUnlock(SaLckLockIdT
> lockId, SaTimeT timeout)
>                 goto done;
>         }
>
> +  /* are we a member of the cluster? */
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version)) {
> +    if (!gla_cb->isClusterMember || client_info->isStale) {
> +      rc = SA_AIS_ERR_UNAVAILABLE;
> +      goto done;
> +    }
> +  }
> +
>         /* check whether GLND is up or not */
>         if (!gla_cb->glnd_svc_up) {
>                 ncshm_give_hdl(lockId);
> @@ -1548,6 +1628,14 @@ SaAisErrorT saLckResourceUnlockAsync(SaInvocationT
> invocation,
>                 goto done;
>         }
>
> +  /* are we a member of the cluster? */
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version)) {
> +    if (!gla_cb->isClusterMember || client_info->isStale) {
> +      rc = SA_AIS_ERR_UNAVAILABLE;
> +      goto done;
> +    }
> +  }
> +
>         /* check whether GLND is up or not */
>         if (!gla_cb->glnd_svc_up) {
>                 ncshm_give_hdl(lockId);
> @@ -1671,6 +1759,14 @@ SaAisErrorT saLckLockPurge(SaLckResourceHandleT
> lockResourceHandle)
>                 goto done;
>         }
>
> +  /* are we a member of the cluster? */
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version)) {
> +    if (!gla_cb->isClusterMember || client_info->isStale) {
> +      rc = SA_AIS_ERR_UNAVAILABLE;
> +      goto done;
> +    }
> +  }
> +
>         /* check whether GLND is up or not */
>         if (!gla_cb->glnd_svc_up) {
>                 ncshm_give_hdl(lockResourceHandle);
> diff --git a/src/lck/agent/gla_cb.h b/src/lck/agent/gla_cb.h
> index 961c252..c99e0ac 100644
> --- a/src/lck/agent/gla_cb.h
> +++ b/src/lck/agent/gla_cb.h
> @@ -40,6 +40,8 @@ typedef struct gla_client_info_tag {
>    uint32_t client_context_id;
>    SaLckCallbacksT lckCallbk;
>    SaTimeT lcktimer;
> +  bool isStale;
> +  SaVersionT version;
>    /* Mailbox Queue to store the messages for the clients */
>    SYSF_MBX callbk_mbx;
>    NCS_PATRICIA_TREE client_res_tree;
> @@ -108,6 +110,7 @@ typedef struct gla_cb_tag {
>    MDS_DEST glnd_mds_dest;
>    bool glnd_svc_up;
>    bool glnd_crashed;
> +  bool isClusterMember;
>
>    /* GLA data */
>    NCS_PATRICIA_TREE gla_client_tree; /* GLA_CLIENT_INFO - node */
> @@ -134,6 +137,7 @@ void gla_client_tree_destroy(GLA_CB *gla_cb);
>  void gla_client_tree_cleanup(GLA_CB *gla_cb);
>  GLA_CLIENT_INFO *gla_client_tree_find_and_add(GLA_CB *gla_cb,
>                                                SaLckHandleT hdl_id, bool
> flag);
> +GLA_CLIENT_INFO *gla_client_tree_find_next(GLA_CB *gla_cb, SaLckHandleT
> hdl_id);
>  uint32_t gla_client_tree_delete_node(GLA_CB *gla_cb,
>                                       GLA_CLIENT_INFO *client_info,
>                                       bool give_hdl);
> diff --git a/src/lck/agent/gla_evt.h b/src/lck/agent/gla_evt.h
> index 3b341d2..864bdf1 100644
> --- a/src/lck/agent/gla_evt.h
> +++ b/src/lck/agent/gla_evt.h
> @@ -34,6 +34,7 @@
>  typedef enum glsv_gla_evt_type {
>    GLSV_GLA_CALLBK_EVT,
>    GLSV_GLA_API_RESP_EVT,
> +  GLSV_GLA_CLM_EVT,
>    GLSV_GLA_EVT_MAX
>  } GLSV_GLA_EVT_TYPE;
>
> @@ -45,7 +46,9 @@ typedef enum glsv_gla_api_resp_evt_type_tag {
>    GLSV_GLA_LOCK_SYNC_LOCK,
>    GLSV_GLA_LOCK_SYNC_UNLOCK,
>    GLSV_GLA_NODE_OPERATIONAL,
> -  GLSV_GLA_LOCK_PURGE
> +  GLSV_GLA_LOCK_PURGE,
> +  GLSV_GLA_NODE_LEFT,
> +  GLSV_GLA_NODE_JOINED
>  } GLSV_GLA_API_RESP_EVT_TYPE;
>
>  typedef struct glsv_gla_evt_lock_initialise_param_tag {
> @@ -87,6 +90,11 @@ typedef struct glsv_gla_api_resp_info {
>    } param;
>  } GLSV_GLA_API_RESP_INFO;
>
> +/* CLM param definitions */
> +typedef struct glsv_gla_clm_info {
> +  bool isClusterMember;
> +} GLSV_GLA_CLM_INFO;
> +
>  /* For GLND to GLA communication */
>  typedef struct glsv_gla_evt {
>    SaLckHandleT handle;
> @@ -95,6 +103,7 @@ typedef struct glsv_gla_evt {
>    union {
>      GLSV_GLA_CALLBACK_INFO gla_clbk_info; /* callbk info */
>      GLSV_GLA_API_RESP_INFO gla_resp_info; /* api response info */
> +    GLSV_GLA_CLM_INFO      gla_clm_info;       /* clm info */
>    } info;
>  } GLSV_GLA_EVT;
>
> diff --git a/src/lck/agent/gla_init.c b/src/lck/agent/gla_init.c
> index 8a81669..ee81d6a 100644
> --- a/src/lck/agent/gla_init.c
> +++ b/src/lck/agent/gla_init.c
> @@ -473,6 +473,33 @@ end:
>  }
>
>  /***********************************************************
> *****************
> +  Name          : gla_client_tree_find_next
> +
> +  Description   : This routine returns the next client
> +
> +  Arguments     :
> +                  gla_cb : pointer to the gla control block.
> +                  hdl_id : the handle id.
> +
> +  Return Values : returns the client_info node.
> +
> +  Notes         : None
> +***********************************************************
> *******************/
> +GLA_CLIENT_INFO *gla_client_tree_find_next(GLA_CB *gla_cb, SaLckHandleT
> hdl_id)
> +{
> +       GLA_CLIENT_INFO *client_info = NULL;
> +       TRACE_ENTER();
> +
> +       /* take the cb lock */
> +       m_NCS_LOCK(&gla_cb->cb_lock, NCS_LOCK_READ);
> +       client_info = (GLA_CLIENT_INFO *)ncs_patricia_tree_getnext(
> +    &gla_cb->gla_client_tree, (uint8_t *)&hdl_id);
> +       m_NCS_UNLOCK(&gla_cb->cb_lock, NCS_LOCK_READ);
> +
> +  return client_info;
> +}
> +
> +/**********************************************************
> ******************
>    Name          : gla_client_info_send
>
>    Description   :
> diff --git a/src/lck/agent/gla_mds.c b/src/lck/agent/gla_mds.c
> index b910f69..5f6e6f5 100644
> --- a/src/lck/agent/gla_mds.c
> +++ b/src/lck/agent/gla_mds.c
> @@ -60,6 +60,7 @@ static uint32_t glsv_gla_dec_callbk_evt(NCS_UBAID *uba,
>                                         GLSV_GLA_CALLBACK_INFO *evt);
>  static uint32_t glsv_gla_dec_api_resp_evt(NCS_UBAID *uba,
>                                           GLSV_GLA_API_RESP_INFO *evt);
> +static uint32_t glsv_gla_dec_clm_evt(NCS_UBAID *uba, GLSV_GLA_CLM_INFO
> *evt);
>
>  uint32_t gla_mds_get_handle(GLA_CB *cb);
>
> @@ -520,6 +521,10 @@ static uint32_t gla_mds_dec(GLA_CB *cb,
> MDS_CALLBACK_DEC_INFO *info)
>
> &evt->info.gla_resp_info);
>                         break;
>
> +    case GLSV_GLA_CLM_EVT:
> +                       glsv_gla_dec_clm_evt(uba, &evt->info.gla_clm_info);
> +                       break;
> +
>                 default:
>                         goto end;
>                 }
> @@ -648,6 +653,21 @@ static uint32_t gla_mds_rcv(GLA_CB *cb,
> MDS_CALLBACK_RECEIVE_INFO *rcv_info)
>                         m_MMGR_FREE_GLA_CALLBACK_INFO(gla_callbk_info);
>                 }
>                 goto end;
> +  } else if (evt->type == GLSV_GLA_CLM_EVT) {
> +    cb->isClusterMember = evt->info.gla_clm_info.isClusterMember;
> +
> +    if (!cb->isClusterMember) {
> +      /* tell all clients they are stale now */
> +      GLA_CLIENT_INFO *client_info;
> +      SaLckHandleT lckHandle = 0;
> +      for (client_info = gla_client_tree_find_next(cb, lckHandle);
> +           client_info;
> +           client_info = gla_client_tree_find_next(
> +             cb, client_info->lock_handle_id)) {
> +        client_info->isStale = true;
> +      }
> +    }
> +               m_MMGR_FREE_GLA_EVT(evt);
>         } else {
>                 if (evt)
>                         m_MMGR_FREE_GLA_EVT(evt);
> @@ -1462,3 +1482,39 @@ end:
>         TRACE_LEAVE();
>         return rc;
>  }
> +
> +/**********************************************************
> ******************
> +  Name          : glsv_gla_DEC_clm_evt
> +
> +  Description   : This routine decodes clm info.
> +
> +  Arguments     : uba , clm info.
> +
> +  Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
> +
> +  Notes         : None.
> +***********************************************************
> *******************/
> +static uint32_t glsv_gla_dec_clm_evt(NCS_UBAID *uba, GLSV_GLA_CLM_INFO
> *evt)
> +{
> +       uint8_t *p8, local_data[20], size;
> +       uint32_t rc = NCSCC_RC_SUCCESS;
> +       TRACE_ENTER();
> +
> +  do {
> +    /** decode the type of message **/
> +         size = (4);
> +         p8 = ncs_dec_flatten_space(uba, local_data, size);
> +         if (!p8) {
> +                 TRACE_2("GLA mds dec failure");
> +           rc = NCSCC_RC_FAILURE;
> +                 break;
> +         }
> +
> +         osaf_decode_bool(uba, &evt->isClusterMember);
> +
> +         ncs_dec_skip_space(uba, size);
> +  } while (false);
> +
> +       TRACE_LEAVE();
> +       return rc;
> +}
> diff --git a/src/lck/common/glsv_defs.h b/src/lck/common/glsv_defs.h
> index a638965..60fa910 100644
> --- a/src/lck/common/glsv_defs.h
> +++ b/src/lck/common/glsv_defs.h
> @@ -42,13 +42,18 @@ typedef unsigned int GLSV_TIMER_ID;
>
>  /* Version Constants */
>  #define REQUIRED_RELEASECODE 'B'
> -#define REQUIRED_MAJORVERSION 01
> -#define REQUIRED_MINORVERSION 01
> +#define REQUIRED_MAJORVERSION 3
> +#define REQUIRED_MINORVERSION 1
>
>  #define m_GLA_VER_IS_VALID(ver)                  \
>    ((ver->releaseCode == REQUIRED_RELEASECODE) && \
>     (ver->majorVersion <= REQUIRED_MAJORVERSION))
>
> +#define m_GLA_VER_IS_AT_LEAST_B_3(ver) \
> +   ((ver.releaseCode == 'B' && \
> +     ver.majorVersion >= 3) || \
> +     ver.releaseCode > 'B')
> +
>  #define MSG_FRMT_VER uint32_t
>  /*** Macro used to get the AMF version used ****/
>  #define m_GLSV_GET_AMF_VER(amf_ver) \
> diff --git a/src/lck/lckd/gld_api.c b/src/lck/lckd/gld_api.c
> index ad1ec6c..256a180 100644
> --- a/src/lck/lckd/gld_api.c
> +++ b/src/lck/lckd/gld_api.c
> @@ -29,12 +29,13 @@
>  #include <string.h>
>  #include <stdlib.h>
>  #include "gld_imm.h"
> +#include "gld_clm.h"
>
>  uint32_t gl_gld_hdl;
>
>  void gld_main_process(SYSF_MBX *mbx);
>
> -enum { FD_TERM = 0, FD_AMF, FD_MBCSV, FD_MBX, FD_IMM, NUM_FD };
> +enum { FD_TERM = 0, FD_AMF, FD_MBCSV, FD_MBX, FD_IMM, FD_CLM, NUM_FD };
>
>  static struct pollfd fds[NUM_FD];
>  static nfds_t nfds = NUM_FD;
> @@ -199,6 +200,13 @@ uint32_t gld_se_lib_init(NCS_LIB_REQ_INFO *req_info)
>         } else
>                 TRACE_1("AMF Health Check started");
>
> +  amf_error = gld_clm_init(gld_cb);
> +  if (amf_error != SA_AIS_OK) {
> +               LOG_ER("CLM Init Failed %u", amf_error);
> +               res = NCSCC_RC_FAILURE;
> +               goto end;
> +  }
> +
>         if ((res = initialize_for_assignment(gld_cb, gld_cb->ha_state)) !=
>             NCSCC_RC_SUCCESS) {
>                 LOG_ER("initialize_for_assignment FAILED %u",
> (unsigned)res);
> @@ -501,7 +509,7 @@ void gld_main_process(SYSF_MBX *mbx)
>         SaAisErrorT error = SA_AIS_OK;
>         GLSV_GLD_CB *gld_cb = NULL;
>         NCS_MBCSV_ARG mbcsv_arg;
> -       SaSelectionObjectT amf_sel_obj;
> +       SaSelectionObjectT amf_sel_obj, clm_sel_obj;
>         int term_fd;
>
>         TRACE_ENTER();
> @@ -520,6 +528,13 @@ void gld_main_process(SYSF_MBX *mbx)
>                 goto end;
>         }
>
> +  error = saClmSelectionObjectGet(gld_cb->clm_hdl, &clm_sel_obj);
> +
> +       if (error != SA_AIS_OK) {
> +               LOG_ER("CLM Selection object get error: %i", error);
> +               goto end;
> +       }
> +
>         daemon_sigterm_install(&term_fd);
>
>         /* Set up all file descriptors to listen to */
> @@ -531,6 +546,8 @@ void gld_main_process(SYSF_MBX *mbx)
>         fds[FD_MBX].events = POLLIN;
>         fds[FD_IMM].fd = gld_cb->imm_sel_obj;
>         fds[FD_IMM].events = POLLIN;
> +  fds[FD_CLM].fd = clm_sel_obj;
> +       fds[FD_CLM].events = POLLIN;
>
>         while (1) {
>                 fds[FD_MBCSV].fd = gld_cb->mbcsv_sel_obj;
> @@ -622,6 +639,14 @@ void gld_main_process(SYSF_MBX *mbx)
>                                 break;
>                         }
>                 }
> +
> +    if (fds[FD_CLM].revents & POLLIN) {
> +      /* dispatch all the CLM pending function */
> +      error = saClmDispatch(gld_cb->clm_hdl, SA_DISPATCH_ALL);
> +      if (error != SA_AIS_OK) {
> +        LOG_ER("CLM dispatch failed: %i", error);
> +      }
> +    }
>         }
>  end:
>         TRACE_LEAVE();
> diff --git a/src/lck/lckd/gld_cb.h b/src/lck/lckd/gld_cb.h
> index c35961e..fabd39c 100644
> --- a/src/lck/lckd/gld_cb.h
> +++ b/src/lck/lckd/gld_cb.h
> @@ -81,7 +81,7 @@ typedef struct glsv_gld_cb_tag {
>    uint8_t hm_poolid;  /* For use with handle manager               */
>    NCSCONTEXT task_hdl;
>    uint32_t my_hdl;  /* Handle manager handle                     */
> -  uint32_t clm_hdl; /* Handle manager handle                     */
> +  SaClmHandleT clm_hdl; /* CLM handle */
>    NCS_MBCSV_HDL mbcsv_handle;
>    NCS_MBCSV_CKPT_HDL o_ckpt_hdl;
>    SaSelectionObjectT mbcsv_sel_obj;
> diff --git a/src/lck/lckd/gld_clm.cc b/src/lck/lckd/gld_clm.cc
> new file mode 100644
> index 0000000..3ed82aa
> --- /dev/null
> +++ b/src/lck/lckd/gld_clm.cc
> @@ -0,0 +1,131 @@
> +#include "clm/saf/saClm.h"
> +#include "lck/lckd/gld_clm.h"
> +#include "base/osaf_time.h"
> +
> +static void handleClmNodeUpdate(GLSV_GLD_CB& cb,
> +                                SaClmNodeIdT nodeId,
> +                                bool isClusterMember) {
> +  TRACE_ENTER();
> +
> +  GLSV_GLD_EVT *evt(m_MMGR_ALLOC_GLSV_GLD_EVT);
> +
> +  if (evt == GLSV_GLD_EVT_NULL) {
> +    LOG_CR("Event alloc failed: Error %s", strerror(errno));
> +    assert(false);
> +  }
> +
> +  memset(evt, 0, sizeof(GLSV_GLD_EVT));
> +  evt->gld_cb = &cb;
> +  evt->evt_type = GLSV_GLD_EVT_GLND_DOWN_CLM;
> +  evt->info.glnd_clm_info.nodeId = nodeId;
> +
> +  // Push the event and we are done
> +  if (m_NCS_IPC_SEND(&cb.mbx, evt, NCS_IPC_PRIORITY_NORMAL) ==
> NCSCC_RC_FAILURE) {
> +    LOG_ER("IPC send failed");
> +    gld_evt_destroy(evt);
> +  }
> +
> +  TRACE_LEAVE();
> +}
> +
> +static void clusterTrackCallback(
> +  const SaClmClusterNotificationBufferT_4 *notificationBuffer,
> +  SaUint32T numberOfMembers,
> +  SaInvocationT invocation,
> +  const SaNameT *rootCauseEntity,
> +  const SaNtfCorrelationIdsT *correlationIds,
> +  SaClmChangeStepT step,
> +  SaTimeT timeSupervision,
> +  SaAisErrorT error) {
> +
> +  TRACE_ENTER();
> +
> +  do {
> +    if (error != SA_AIS_OK) {
> +      LOG_ER("clusterTrackCallback sent failure: %i", error);
> +      break;
> +    }
> +
> +    GLSV_GLD_CB *cb(static_cast<GLSV_GLD_CB *>(m_GLSV_GLD_RETRIEVE_GLD_CB)
> );
> +
> +    if (!cb) {
> +      LOG_ER("GLD cb take handle failed");
> +      break;
> +    }
> +
> +    TRACE("number of items: %i", notificationBuffer->numberOfItems);
> +
> +    for (SaUint32T i(0); i < notificationBuffer->numberOfItems; i++) {
> +      TRACE("cluster change: %i", notificationBuffer->
> notification[i].clusterChange);
> +      /*
> +       * We only care about nodes leaving; lcknd will send an up message
> when
> +       * it is operational
> +       */
> +      if (notificationBuffer->notification[i].clusterChange ==
> SA_CLM_NODE_LEFT) {
> +        handleClmNodeUpdate(
> +          *cb,
> +          notificationBuffer->notification[i].clusterNode.nodeId,
> +          false);
> +      }
> +    }
> +
> +    m_GLSV_GLD_GIVEUP_GLD_CB;
> +
> +  } while (false);
> +
> +  TRACE_LEAVE();
> +}
> +
> +SaAisErrorT gld_clm_init(GLSV_GLD_CB *cb) {
> +  TRACE_ENTER();
> +
> +  SaAisErrorT rc(SA_AIS_OK);
> +
> +  do {
> +    SaClmCallbacksT_4 callbacks = {
> +      0,
> +      clusterTrackCallback
> +    };
> +
> +    SaVersionT version = { 'B', 4, 0 };
> +
> +    while (true) {
> +      rc = saClmInitialize_4(&cb->clm_hdl, &callbacks, &version);
> +
> +      if (rc == SA_AIS_ERR_TRY_AGAIN) {
> +        osaf_nanosleep(&kHundredMilliseconds);
> +        continue;
> +      } else if (rc != SA_AIS_OK) {
> +        LOG_ER("saClmInitialize_4 failed: %i", rc);
> +        break;
> +      } else {
> +        break;
> +      }
> +    }
> +
> +    rc = saClmClusterTrack_4(cb->clm_hdl, SA_TRACK_CHANGES_ONLY, 0);
> +
> +    if (rc != SA_AIS_OK) {
> +      LOG_ER("saClmClusterTrack failed: %i", rc);
> +      break;
> +    }
> +  } while (false);
> +
> +  if (rc != SA_AIS_OK && cb->clm_hdl)
> +    gld_clm_deinit(cb);
> +
> +  TRACE_LEAVE();
> +  return rc;
> +}
> +
> +SaAisErrorT gld_clm_deinit(GLSV_GLD_CB *cb)
> +{
> +  SaAisErrorT rc(saClmFinalize(cb->clm_hdl));
> +
> +  if (rc != SA_AIS_OK)
> +    LOG_ER("saClmFinalize failed: %i", rc);
> +
> +  cb->clm_hdl = 0;
> +
> +  return rc;
> +}
> diff --git a/src/lck/lckd/gld_clm.h b/src/lck/lckd/gld_clm.h
> new file mode 100644
> index 0000000..407b9a8
> --- /dev/null
> +++ b/src/lck/lckd/gld_clm.h
> @@ -0,0 +1,17 @@
> +#ifndef LCK_LCKD_GLD_CLM_H_
> +#define LCK_LCKD_GLD_CLM_H_
> +
> +#include "lck/lckd/gld.h"
> +
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
> +SaAisErrorT gld_clm_init(GLSV_GLD_CB *);
> +SaAisErrorT gld_clm_deinit(GLSV_GLD_CB *);
> +
> +#ifdef  __cplusplus
> +}
> +#endif
> +
> +#endif  // LCK_LCKND_GLND_CLM_H_
> diff --git a/src/lck/lckd/gld_evt.c b/src/lck/lckd/gld_evt.c
> index aea7579..dc85179 100644
> --- a/src/lck/lckd/gld_evt.c
> +++ b/src/lck/lckd/gld_evt.c
> @@ -45,6 +45,7 @@ static uint32_t gld_process_send_non_master_status(
>  static uint32_t gld_process_send_non_master_info(
>      GLSV_GLD_CB *gld_cb, GLSV_GLD_GLND_RSC_REF *glnd_rsc,
>      GLSV_GLD_GLND_DETAILS *node_details, uint32_t status);
> +static uint32_t gld_clm_glnd_down(GLSV_GLD_EVT *evt);
>
>  /* GLD dispatch table */
>  static const GLSV_GLD_EVT_HANDLER
> @@ -57,7 +58,8 @@ static const GLSV_GLD_EVT_HANDLER
>         gld_debug_dump_cb,
>         gld_process_tmr_resource_reelection_wait_timeout,
>         gld_process_tmr_node_restart_wait_timeout,
> -       gld_quisced_process};
> +       gld_quisced_process,
> +  gld_clm_glnd_down};
>
>  /***********************************************************
> *****************
>   * Name          : gld_process_evt
> @@ -683,8 +685,6 @@ end:
>  static uint32_t gld_mds_glnd_down(GLSV_GLD_EVT *evt)
>  {
>         GLSV_GLD_CB *gld_cb = evt->gld_cb;
> -       GLSV_GLD_GLND_DETAILS *node_details = NULL;
> -       GLSV_GLD_RSC_INFO *rsc_info;
>         uint32_t node_id;
>         uint32_t rc = NCSCC_RC_FAILURE;
>         TRACE_ENTER2("mds identification %u", gld_cb->my_dest_id);
> @@ -692,54 +692,11 @@ static uint32_t gld_mds_glnd_down(GLSV_GLD_EVT *evt)
>         node_id =
>             m_NCS_NODE_ID_FROM_MDS_DEST(evt->info.glnd_mds_info.mds_
> dest_id);
>
> -       if ((evt == GLSV_GLD_EVT_NULL) || (gld_cb == NULL))
> -               goto end;
> -
> -       memcpy(&evt->fr_dest_id, &evt->info.glnd_mds_info.mds_dest_id,
> -              sizeof(MDS_DEST));
> +  evt->info.glnd_clm_info.nodeId          = node_id;
> +  evt->info.glnd_clm_info.isClusterMember = false;
>
> -       if ((node_details = (GLSV_GLD_GLND_DETAILS *)ncs_patricia_tree_get(
> -                &gld_cb->glnd_details, (uint8_t *)&node_id)) == NULL) {
> -               TRACE_1("Resource details is empty for glnd on node_id %u
> ",
> -                       node_id);
> -               rc = NCSCC_RC_SUCCESS;
> -               goto end;
> -       }
> -       node_details->status = GLND_RESTART_STATE;
> -
> -       TRACE("EVT Processing MDS GLND DOWN: node_id %u",
> -             node_details->node_id);
> -       memcpy(&node_details->restart_timer.mdest_id,
> &node_details->dest_id,
> -              sizeof(MDS_DEST));
> -
> -       /* Start GLSV_GLD_GLND_RESTART_TIMEOUT timer */
> -       gld_start_tmr(gld_cb, &node_details->restart_timer,
> -                     GLD_TMR_NODE_RESTART_TIMEOUT,
> GLD_NODE_RESTART_TIMEOUT,
> -                     0);
> -
> -       /* Check whether this node is master for any resource, if yes send
> the
> -          status to all the non master nodes */
> -       if (gld_cb->ha_state == SA_AMF_HA_ACTIVE) {
> -               /* Check whether this node is master for any resource, if
> yes
> -                * send the status to all the non master nodes */
> -               rsc_info = gld_cb->rsc_info;
> -               while (rsc_info != NULL) {
> -                       if (rsc_info->node_list) {
> -                               if (rsc_info->node_list->node_id ==
> -                                   node_details->node_id)
> -                                       gld_snd_master_status(
> -                                           gld_cb, rsc_info,
> -                                           GLND_RESOURCE_MASTER_
> RESTARTED);
> -                       }
> -                       rsc_info = rsc_info->next;
> -               }
> +  gld_clm_glnd_down(evt);
>
> -               /* If this node is non master for any resource, then send
> node
> -                * status to the master */
> -               gld_process_send_non_master_status(gld_cb, node_details,
> -                                                  GLND_RESTART_STATE);
> -       }
> -end:
>         TRACE_LEAVE2("Return value: %u", rc);
>         return rc;
>  }
> @@ -1073,3 +1030,63 @@ end:
>         TRACE_LEAVE();
>         return res;
>  }
> +
> +/**********************************************************
> ******************
> + * Name          : gld_clm_glnd_down
> + *
> + * Description   : CLM indicated that a glnd has gone down
> + *
> + * Arguments     : evt  - Event structure
> + *
> + * Return Values : NCSCC_RC_SUCCESS/ NCSCC_RC_FAILURE
> + *
> + * Notes         : None.
> + ************************************************************
> *****************/
> +static uint32_t gld_clm_glnd_down(GLSV_GLD_EVT *evt)
> +{
> +       GLSV_GLD_CB *gld_cb = evt->gld_cb;
> +       GLSV_GLD_GLND_DETAILS *node_details = NULL;
> +       GLSV_GLD_RSC_INFO *rsc_info;
> +       uint32_t node_id;
> +       uint32_t rc = NCSCC_RC_FAILURE;
> +       TRACE_ENTER2("mds identification %u",gld_cb->my_dest_id );
> +
> +       node_id = evt->info.glnd_clm_info.nodeId;
> +
> +       if ((node_details = (GLSV_GLD_GLND_DETAILS
> *)ncs_patricia_tree_get(&gld_cb->glnd_details,
> +
> (uint8_t *)&node_id)) == NULL) {
> +               TRACE_1("Resource details is empty for glnd on node_id %u
> ", node_id);
> +               rc = NCSCC_RC_SUCCESS;
> +               goto end;
> +       }
> +       node_details->status = GLND_RESTART_STATE;
> +
> +       TRACE("EVT Processing CLM GLND DOWN: node_id %u",
> node_details->node_id);
> +       memcpy(&node_details->restart_timer.mdest_id,
> &node_details->dest_id, sizeof(MDS_DEST));
> +
> +       /* Start GLSV_GLD_GLND_RESTART_TIMEOUT timer */
> +       gld_start_tmr(gld_cb, &node_details->restart_timer,
> GLD_TMR_NODE_RESTART_TIMEOUT, GLD_NODE_RESTART_TIMEOUT, 0);
> +
> +       /* Check whether this node is master for any resource, if yes send
> the status to all
> +          the
> +          non master nodes */
> +       if (gld_cb->ha_state == SA_AMF_HA_ACTIVE) {
> +               /* Check whether this node is master for any resource, if
> yes send the status to all the non master nodes */
> +               rsc_info = gld_cb->rsc_info;
> +               while (rsc_info != NULL) {
> +                       if (rsc_info->node_list) {
> +                               if (rsc_info->node_list->node_id ==
> node_details->node_id)
> +                                       gld_snd_master_status(gld_cb,
> rsc_info, GLND_RESOURCE_MASTER_RESTARTED);
> +                       }
> +                       rsc_info = rsc_info->next;
> +               }
> +
> +               /* If this node is non master for any resource, then send
> node status to the master */
> +               gld_process_send_non_master_status(gld_cb, node_details,
> GLND_RESTART_STATE);
> +
> +       }
> + end:
> +       TRACE_LEAVE2("Return value: %u", rc);
> +       return rc;
> +}
> +
> diff --git a/src/lck/lckd/gld_evt.h b/src/lck/lckd/gld_evt.h
> index 1484fb0..9a2e7f6 100644
> --- a/src/lck/lckd/gld_evt.h
> +++ b/src/lck/lckd/gld_evt.h
> @@ -18,6 +18,10 @@
>  #ifndef LCK_LCKD_GLD_EVT_H_
>  #define LCK_LCKD_GLD_EVT_H_
>
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
>  /***********************************************************
> ******************
>   * Message Type of GLND
>   ************************************************************
> *****************/
> @@ -36,6 +40,8 @@ typedef enum glsv_gld_evt_type {
>    GLSV_GLD_EVT_RESTART_TIMEOUT,
>    GLSV_GLD_EVT_QUISCED_STATE,
>
> +  GLSV_GLD_EVT_GLND_DOWN_CLM,
> +
>    GLSV_GLD_EVT_MAX
>  } GLSV_GLD_EVT_TYPE;
>
> @@ -66,6 +72,11 @@ typedef struct gld_evt_tmr_tag {
>    uint32_t opq_hdl;
>  } GLD_EVT_TMR;
>
> +typedef struct gld_evt_node_info {
> +  uint32_t nodeId;
> +  bool isClusterMember;
> +} GLSV_GLD_GLND_NODE_INFO;
> +
>  /***********************************************************
> ******************
>   * GLD msg data structure.
>   ************************************************************
> *****************/
> @@ -79,6 +90,7 @@ typedef struct glsv_gld_evt_tag {
>      GLSV_RSC_DETAILS rsc_details;
>      GLSV_GLD_GLND_MDS_INFO glnd_mds_info;
>      GLD_EVT_TMR tmr;
> +    GLSV_GLD_GLND_NODE_INFO glnd_clm_info;
>    } info;
>  } GLSV_GLD_EVT;
>
> @@ -90,4 +102,8 @@ typedef uint32_t (*GLSV_GLD_EVT_HANDLER)(struct
> glsv_gld_evt_tag *evt);
>  void gld_evt_destroy(GLSV_GLD_EVT *evt);
>  uint32_t gld_process_evt(GLSV_GLD_EVT *evt);
>
> +#ifdef  __cplusplus
> +}
> +#endif
> +
>  #endif  // LCK_LCKD_GLD_EVT_H_
> diff --git a/src/lck/lcknd/glnd_agent.c b/src/lck/lcknd/glnd_agent.c
> index 36e5668..a7f7a79 100644
> --- a/src/lck/lcknd/glnd_agent.c
> +++ b/src/lck/lcknd/glnd_agent.c
> @@ -55,6 +55,29 @@ GLND_AGENT_INFO *glnd_agent_node_find(GLND_CB *glnd_cb,
> MDS_DEST agent_mds_dest)
>  }
>
>  /***********************************************************
> ******************
> +  PROCEDURE NAME : glnd_agent_node_find_next
> +
> +  DESCRIPTION    : Finds the Agent info node from the tree.
> +
> +  ARGUMENTS      :glnd_cb      - ptr to the GLND control block
> +                  mds_handle_id  - vcard id of the agent.
> +
> +  RETURNS        :The pointer to the agent info node
> +
> +  NOTES         : None
> +***********************************************************
> ******************/
> +GLND_AGENT_INFO *glnd_agent_node_find_next(GLND_CB *glnd_cb,
> +                                           MDS_DEST agent_mds_dest)
> +{
> +       GLND_AGENT_INFO *agent_info;
> +
> +       /* search for the agent id */
> +       agent_info = (GLND_AGENT_INFO *)ncs_patricia_tree_getnext(
> +    &glnd_cb->glnd_agent_tree, (uint8_t *)&agent_mds_dest);
> +
> +       return agent_info;
> +}
> +/**********************************************************
> *******************
>    PROCEDURE NAME : glnd_agent_node_add
>
>    DESCRIPTION    : Adds the Agent node to the Agent tree.
> diff --git a/src/lck/lcknd/glnd_api.c b/src/lck/lcknd/glnd_api.c
> index 93723c3..7534386 100644
> --- a/src/lck/lcknd/glnd_api.c
> +++ b/src/lck/lcknd/glnd_api.c
> @@ -33,7 +33,7 @@
>  #include "lck/lcknd/glnd.h"
>  #include "base/osaf_poll.h"
>
> -enum { FD_TERM = 0, FD_AMF, FD_MBX, NUM_FD };
> +enum { FD_TERM = 0, FD_AMF, FD_MBX, FD_CLM, NUM_FD };
>
>  void glnd_main_process(SYSF_MBX *mbx);
>
> @@ -192,9 +192,10 @@ void glnd_main_process(SYSF_MBX *mbx)
>         TRACE_ENTER();
>
>         SaAmfHandleT amf_hdl;
> +       SaClmHandleT clm_hdl;
>
> -       SaSelectionObjectT amf_sel_obj;
> -       SaAisErrorT amf_error;
> +       SaSelectionObjectT amf_sel_obj, clm_sel_obj;
> +       SaAisErrorT ais_error;
>
>         struct pollfd sel[NUM_FD];
>         int term_fd;
> @@ -207,16 +208,23 @@ void glnd_main_process(SYSF_MBX *mbx)
>         }
>
>         amf_hdl = glnd_cb->amf_hdl;
> +  clm_hdl = glnd_cb->clm_hdl;
>
>         /*giveup the handle */
>         m_GLND_GIVEUP_GLND_CB;
>
> -       amf_error = saAmfSelectionObjectGet(amf_hdl, &amf_sel_obj);
> -       if (amf_error != SA_AIS_OK) {
> +       ais_error = saAmfSelectionObjectGet(amf_hdl, &amf_sel_obj);
> +       if (ais_error != SA_AIS_OK) {
>                 LOG_ER("GLND amf get sel obj error");
>                 goto end;
>         }
>
> +  ais_error = saClmSelectionObjectGet(clm_hdl, &clm_sel_obj);
> +       if (ais_error != SA_AIS_OK) {
> +               LOG_ER("GLND clm get sel obj error: %i", ais_error);
> +               goto end;
> +       }
> +
>         daemon_sigterm_install(&term_fd);
>
>         sel[FD_TERM].fd = term_fd;
> @@ -225,6 +233,8 @@ void glnd_main_process(SYSF_MBX *mbx)
>         sel[FD_AMF].events = POLLIN;
>         sel[FD_MBX].fd = m_GET_FD_FROM_SEL_OBJ(mbx_fd);
>         sel[FD_MBX].events = POLLIN;
> +  sel[FD_CLM].fd = clm_sel_obj;
> +       sel[FD_CLM].events = POLLIN;
>
>         while (osaf_poll(&sel[0], NUM_FD, -1) > 0) {
>
> @@ -232,7 +242,7 @@ void glnd_main_process(SYSF_MBX *mbx)
>                         daemon_exit();
>                 }
>
> -               if (((sel[FD_AMF].revents | sel[FD_MBX].revents) &
> +               if (((sel[FD_AMF].revents | sel[FD_MBX].revents |
> sel[FD_CLM].revents) &
>                      (POLLERR | POLLHUP | POLLNVAL)) != 0) {
>                         LOG_ER("GLND poll() failure: %hd %hd",
>                                sel[FD_AMF].revents, sel[FD_MBX].revents);
> @@ -242,8 +252,8 @@ void glnd_main_process(SYSF_MBX *mbx)
>                 /* process all the AMF messages */
>                 if (sel[FD_AMF].revents & POLLIN) {
>                         /* dispatch all the AMF pending function */
> -                       amf_error = saAmfDispatch(amf_hdl,
> SA_DISPATCH_ALL);
> -                       if (amf_error != SA_AIS_OK) {
> +                       ais_error = saAmfDispatch(amf_hdl,
> SA_DISPATCH_ALL);
> +                       if (ais_error != SA_AIS_OK) {
>                                 TRACE_2("GLND amf dispatch failure");
>                         }
>                 }
> @@ -257,6 +267,15 @@ void glnd_main_process(SYSF_MBX *mbx)
>                         } else
>                                 break;
>                 }
> +
> +       /* process all the AMF messages */
> +               if (sel[FD_CLM].revents & POLLIN) {
> +                       /* dispatch all the CLM pending function */
> +                       ais_error = saClmDispatch(clm_hdl,
> SA_DISPATCH_ALL);
> +                       if (ais_error != SA_AIS_OK) {
> +                               TRACE_2("GLND clm dispatch failure: %i",
> ais_error);
> +                       }
> +               }
>         }
>
>         TRACE("DANGER: Exiting the Select loop of GLND");
> diff --git a/src/lck/lcknd/glnd_cb.c b/src/lck/lcknd/glnd_cb.c
> index 8928825..ebf917b 100644
> --- a/src/lck/lcknd/glnd_cb.c
> +++ b/src/lck/lcknd/glnd_cb.c
> @@ -27,6 +27,7 @@
>  ************************************************************
> ******************/
>
>  #include "lck/lcknd/glnd.h"
> +#include "lck/lcknd/glnd_clm.h"
>
>  uint32_t gl_glnd_hdl;
>  NCSCONTEXT gl_glnd_task_hdl;
> @@ -119,6 +120,13 @@ GLND_CB *glnd_cb_create(uint32_t pool_id)
>         } else
>                 TRACE_1("GLND mds register success");
>
> +  /* Initialise with the CLM service */
> +       if (glnd_clm_init(glnd_cb) != NCSCC_RC_SUCCESS) {
> +               LOG_ER("GLND clm init failed");
> +               goto clm_init_err;
> +       } else
> +               TRACE_1("GLND clm init success");
> +
>         /* Initialise with the AMF service */
>         if (glnd_amf_init(glnd_cb) != NCSCC_RC_SUCCESS) {
>                 LOG_ER("GLND amf init failed");
> @@ -179,6 +187,8 @@ amf_reg_err:
>         glnd_amf_de_init(glnd_cb);
>  amf_init_err:
>         glnd_mds_unregister(glnd_cb);
> +clm_init_err:
> +  glnd_clm_deinit(glnd_cb);
>  mds_err:
>         m_NCS_EDU_HDL_FLUSH(&glnd_cb->glnd_edu_hdl);
>         m_NCS_IPC_DETACH(&glnd_cb->glnd_mbx, glnd_cleanup_mbx, glnd_cb);
> diff --git a/src/lck/lcknd/glnd_cb.h b/src/lck/lcknd/glnd_cb.h
> index 2c96e72..3c38b12 100644
> --- a/src/lck/lcknd/glnd_cb.h
> +++ b/src/lck/lcknd/glnd_cb.h
> @@ -23,6 +23,10 @@
>  #include "glnd_tmr.h"
>  #include "lck/lcknd/glnd_evt.h"
>
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
>  /* global variables */
>  uint32_t gl_glnd_hdl;
>  NCSCONTEXT gl_glnd_task_hdl;
> @@ -178,6 +182,7 @@ typedef struct glnd_cb_tag {
>    /* Information about the GLD */
>    MDS_DEST gld_mdest_id;
>    bool gld_card_up;
> +  bool isClusterMember;
>
>    /* GLND data */
>    NCS_PATRICIA_TREE glnd_client_tree; /* GLND_CLIENT_INFO - node */
> @@ -189,6 +194,7 @@ typedef struct glnd_cb_tag {
>    struct glsv_glnd_evt
>        *evt_bckup_q; /* backup the events incase of mastership change */
>
> +  SaClmHandleT clm_hdl;        /* CLM handle, obtained thru CLM init
>   */
>    SaAmfHandleT amf_hdl;   /* AMF handle, obtained thru AMF init        */
>    SaAmfHAStateT ha_state; /* present AMF HA state of the component     */
>    EDU_HDL glnd_edu_hdl;   /* edu handle used for encode/decode         */
> @@ -203,6 +209,7 @@ typedef struct glnd_cb_tag {
>  /* prototypes */
>  GLND_AGENT_INFO *glnd_agent_node_find(GLND_CB *glnd_cb,
>                                        MDS_DEST agent_mds_dest);
> +GLND_AGENT_INFO *glnd_agent_node_find_next(GLND_CB *, MDS_DEST);
>  GLND_AGENT_INFO *glnd_agent_node_add(GLND_CB *glnd_cb, MDS_DEST
> agent_mds_dest,
>                                       uint32_t process_id);
>  void glnd_agent_node_del(GLND_CB *glnd_cb, GLND_AGENT_INFO *agent_info);
> @@ -219,6 +226,7 @@ GLND_RESOURCE_REQ_LIST *glnd_resource_req_node_add(
>      MDS_SYNC_SND_CTXT *mds_ctxt, SaLckResourceIdT lcl_resource_id);
>  GLND_RESOURCE_REQ_LIST *glnd_resource_req_node_find(GLND_CB *glnd_cb,
>                                                      SaNameT
> *resource_name);
> +void glnd_resource_req_node_down(GLND_CB *glnd_cb);
>  void glnd_resource_req_node_del(GLND_CB *glnd_cb, uint32_t res_req_hdl);
>
>  /* Amf prototypes */
> @@ -244,4 +252,8 @@ uint8_t glnd_cpsv_initilize(GLND_CB *glnd_cb);
>  uint32_t glnd_shm_create(GLND_CB *cb);
>  uint32_t glnd_shm_destroy(GLND_CB *cb, char shm_name[]);
>
> +#ifdef  __cplusplus
> +}
> +#endif
> +
>  #endif  // LCK_LCKND_GLND_CB_H_
> diff --git a/src/lck/lcknd/glnd_client.c b/src/lck/lcknd/glnd_client.c
> index 86659c0..02f1358 100644
> --- a/src/lck/lcknd/glnd_client.c
> +++ b/src/lck/lcknd/glnd_client.c
> @@ -138,6 +138,98 @@ GLND_CLIENT_INFO *glnd_client_node_add(GLND_CB
> *glnd_cb,
>  }
>
>  /***********************************************************
> ******************
> +  PROCEDURE NAME : glnd_client_node_down
> +
> +  DESCRIPTION    : Sends responses to any waiting calls since the node is
> down.
> +
> +  ARGUMENTS      :glnd_cb      - ptr to the GLND control block
> +                  agent_mds_dest   - mds dest id for the agent.
> +
> +
> +  RETURNS        :None
> +
> +  NOTES         : None
> +***********************************************************
> ******************/
> +void glnd_client_node_down(GLND_CB *glnd_cb, GLND_CLIENT_INFO
> *client_info)
> +{
> +  GLND_CLIENT_LIST_RESOURCE *res_list;
> +  TRACE_ENTER();
> +
> +       for (res_list = client_info->res_list;
> +       res_list != NULL;
> +       res_list = res_list->next) {
> +               GLND_CLIENT_LIST_RESOURCE_LOCK_REQ *lckList;
> +
> +    for (lckList = res_list->lck_list; lckList; lckList = lckList->next) {
> +      GLND_RES_LOCK_LIST_INFO *lckListInfo = lckList->lck_req;
> +
> +      if (lckListInfo) {
> +        GLSV_GLA_EVT gla_evt;
> +
> +        // respond to any blocked unlock calls
> +        if (lckListInfo->unlock_call_type == GLSV_SYNC_CALL) {
> +          glnd_stop_tmr(&lckListInfo->timeout_tmr);
> +
> +          gla_evt.error = SA_AIS_ERR_UNAVAILABLE;
> +          gla_evt.handle = lckListInfo->lock_info.handleId;
> +          gla_evt.type = GLSV_GLA_API_RESP_EVT;
> +          gla_evt.info.gla_resp_info.type = GLSV_GLA_LOCK_SYNC_UNLOCK;
> +
> +          glnd_mds_msg_send_rsp_gla(glnd_cb,
> +                                    &gla_evt,
> +                                    lckListInfo->lock_info.agent_
> mds_dest,
> +                                    &lckListInfo->glnd_res_lock_
> mds_ctxt);
> +        } else if (lckListInfo->unlock_call_type == GLSV_ASYNC_CALL) {
> +          m_GLND_RESOURCE_ASYNC_LCK_UNLOCK_FILL(
> +            gla_evt,
> +            SA_AIS_ERR_UNAVAILABLE,
> +            lckListInfo->lock_info.invocation,
> +            lckListInfo->lcl_resource_id,
> +            lckListInfo->lock_info.lcl_lockid,
> +            0);
> +          gla_evt.handle = lckListInfo->lock_info.handleId;
> +
> +          glnd_mds_msg_send_gla(glnd_cb,
> +                                &gla_evt,
> +                                lckListInfo->lock_info.agent_mds_dest);
> +        }
> +
> +        // respond to any blocked lock calls
> +        if (lckListInfo->lock_info.call_type == GLSV_SYNC_CALL) {
> +          glnd_stop_tmr(&lckListInfo->timeout_tmr);
> +
> +          gla_evt.error = SA_AIS_ERR_UNAVAILABLE;
> +          gla_evt.handle = lckListInfo->lock_info.handleId;
> +          gla_evt.type = GLSV_GLA_API_RESP_EVT;
> +          gla_evt.info.gla_resp_info.type = GLSV_GLA_LOCK_SYNC_LOCK;
> +
> +          glnd_mds_msg_send_rsp_gla(glnd_cb,
> +                                    &gla_evt,
> +                                    lckListInfo->lock_info.agent_
> mds_dest,
> +                                    &lckListInfo->glnd_res_lock_
> mds_ctxt);
> +        } else if (lckListInfo->lock_info.call_type == GLSV_ASYNC_CALL) {
> +          m_GLND_RESOURCE_ASYNC_LCK_GRANT_FILL(
> +            gla_evt,
> +            SA_AIS_ERR_UNAVAILABLE,
> +            0,
> +            lckListInfo->lock_info.lcl_lockid,
> +            lckListInfo->lock_info.lock_type,
> +            lckListInfo->lcl_resource_id,
> +            lckListInfo->lock_info.invocation,
> +            0,
> +            lckListInfo->lock_info.handleId);
> +
> +          glnd_mds_msg_send_gla(glnd_cb,
> +                                &gla_evt,
> +                                lckListInfo->lock_info.agent_mds_dest);
> +        }
> +      }
> +    }
> +  }
> +
> +  TRACE_LEAVE();
> +}
> +/**********************************************************
> *******************
>    PROCEDURE NAME : glnd_client_node_del
>
>    DESCRIPTION    : Deletes the client node from the tree.
> diff --git a/src/lck/lcknd/glnd_client.h b/src/lck/lcknd/glnd_client.h
> index 025a352..fff2342 100644
> --- a/src/lck/lcknd/glnd_client.h
> +++ b/src/lck/lcknd/glnd_client.h
> @@ -18,6 +18,10 @@
>  #ifndef LCK_LCKND_GLND_CLIENT_H_
>  #define LCK_LCKND_GLND_CLIENT_H_
>
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
>  typedef struct glnd_client_list_resource_lock_req_tag {
>    GLND_RES_LOCK_LIST_INFO *lck_req;
>    struct glnd_client_list_resource_lock_req_tag *prev, *next;
> @@ -53,6 +57,8 @@ GLND_CLIENT_INFO *glnd_client_node_add(GLND_CB *glnd_cb,
>                                         MDS_DEST agent_mds_dest,
>                                         SaLckHandleT app_handle_id);
>
> +void glnd_client_node_down(GLND_CB *glnd_cb, GLND_CLIENT_INFO
> *client_info);
> +
>  uint32_t glnd_client_node_del(GLND_CB *glnd_cb, GLND_CLIENT_INFO
> *client_info);
>
>  uint32_t glnd_client_node_resource_add(GLND_CLIENT_INFO *client_info,
> @@ -86,4 +92,8 @@ uint32_t glnd_client_node_resource_
> lock_find_duplicate_ex(
>      GLND_CLIENT_INFO *client_info, SaLckResourceIdT res_id,
>      SaLckResourceIdT lcl_res_id);
>
> +#ifdef  __cplusplus
> +}
> +#endif
> +
>  #endif  // LCK_LCKND_GLND_CLIENT_H_
> diff --git a/src/lck/lcknd/glnd_clm.cc b/src/lck/lcknd/glnd_clm.cc
> new file mode 100644
> index 0000000..5ee8596
> --- /dev/null
> +++ b/src/lck/lcknd/glnd_clm.cc
> @@ -0,0 +1,183 @@
> +#include "clm/saf/saClm.h"
> +#include "lck/lcknd/glnd_clm.h"
> +#include "base/osaf_time.h"
> +
> +static void handleClmNodeUpdate(GLND_CB& cb, bool isClusterMember) {
> +  TRACE_ENTER();
> +  cb.isClusterMember = isClusterMember;
> +
> +  GLSV_GLA_EVT gla_evt;
> +
> +  gla_evt.error = SA_AIS_OK;
> +  gla_evt.type = GLSV_GLA_CLM_EVT;
> +  gla_evt.info.gla_clm_info.isClusterMember = isClusterMember;
> +
> +
> +  // send replies to outstanding callbacks first, then notify all the
> agents
> +  glnd_resource_req_node_down(&cb);
> +
> +  for (GLND_AGENT_INFO *agentInfo(glnd_agent_node_find_next(&cb, 0));
> +       agentInfo;
> +       agentInfo = glnd_agent_node_find_next(&cb,
> agentInfo->agent_mds_id)) {
> +    if (!isClusterMember) {
> +      // behave internally as if all clients went down
> +      for (GLND_CLIENT_INFO *clientInfo(
> +             glnd_client_node_find_next(&cb, 0,
> agentInfo->agent_mds_id));
> +           clientInfo;
> +           clientInfo = glnd_client_node_find_next(&cb,
> +
>  clientInfo->app_handle_id,
> +
>  agentInfo->agent_mds_id)) {
> +        glnd_client_node_down(&cb, clientInfo);
> +        glnd_client_node_del(&cb, clientInfo);
> +      }
> +    }
> +
> +    glnd_mds_msg_send_gla(&cb, &gla_evt, agentInfo->agent_mds_id);
> +  }
> +
> +  TRACE_LEAVE();
> +}
> +
> +static void clusterNodeGetCallback(
> +  SaInvocationT invocation,
> +  const SaClmClusterNodeT_4 *clusterNode,
> +  SaAisErrorT error) {
> +
> +  TRACE_ENTER();
> +
> +  do {
> +    if (error != SA_AIS_OK) {
> +      LOG_ER("clusterNodeGetCallback sent failure: %i", error);
> +      break;
> +    }
> +
> +    GLND_CB *cb(static_cast<GLND_CB *>(m_GLND_TAKE_GLND_CB));
> +
> +    if (!cb) {
> +      LOG_ER("GLND cb take handle failed");
> +      break;
> +    }
> +
> +    cb->glnd_node_id = clusterNode->nodeId;
> +
> +    m_GLND_GIVEUP_GLND_CB;
> +
> +    // now that we know our node id start the tracking
> +    SaAisErrorT rc(saClmClusterTrack_4(cb->clm_hdl,
> +                                       SA_TRACK_CURRENT |
> SA_TRACK_CHANGES,
> +                                       0));
> +
> +    if (rc != SA_AIS_OK) {
> +      LOG_ER("saClmClusterTrack failed: %i", rc);
> +      break;
> +    }
> +  } while (false);
> +
> +  TRACE_LEAVE();
> +}
> +
> +static void clusterTrackCallback(
> +  const SaClmClusterNotificationBufferT_4 *notificationBuffer,
> +  SaUint32T numberOfMembers,
> +  SaInvocationT invocation,
> +  const SaNameT *rootCauseEntity,
> +  const SaNtfCorrelationIdsT *correlationIds,
> +  SaClmChangeStepT step,
> +  SaTimeT timeSupervision,
> +  SaAisErrorT error) {
> +
> +  TRACE_ENTER();
> +
> +  do {
> +    if (error != SA_AIS_OK) {
> +      LOG_ER("clusterTrackCallback sent failure: %i", error);
> +      break;
> +    }
> +
> +    GLND_CB *cb(static_cast<GLND_CB *>(m_GLND_TAKE_GLND_CB));
> +
> +    if (!cb) {
> +      LOG_ER("GLND cb take handle failed");
> +      break;
> +    }
> +
> +    TRACE("number of items: %i", notificationBuffer->numberOfItems);
> +
> +    for (SaUint32T i(0); i < notificationBuffer->numberOfItems; i++) {
> +      TRACE("our node id: %i clm node id: %i", cb->glnd_node_id,
> notificationBuffer->notification[i].clusterNode.nodeId);
> +      TRACE("cluster change: %i", notificationBuffer->
> notification[i].clusterChange);
> +      // don't care about other nodes
> +      if (cb->glnd_node_id == notificationBuffer->
> notification[i].clusterNode.nodeId) {
> +        if (notificationBuffer->notification[i].clusterChange ==
> SA_CLM_NODE_LEFT) {
> +          handleClmNodeUpdate(*cb, false);
> +        } else if (notificationBuffer->notification[i].clusterChange ==
> +                     SA_CLM_NODE_JOINED ||
> +                   notificationBuffer->notification[i].clusterChange ==
> +                     SA_CLM_NODE_NO_CHANGE) {
> +          handleClmNodeUpdate(*cb, true);
> +        }
> +      }
> +    }
> +
> +    m_GLND_GIVEUP_GLND_CB;
> +
> +  } while (false);
> +
> +  TRACE_LEAVE();
> +}
> +
> +SaAisErrorT glnd_clm_init(GLND_CB *cb) {
> +  TRACE_ENTER();
> +
> +  SaAisErrorT rc(SA_AIS_OK);
> +
> +  do {
> +    SaClmCallbacksT_4 callbacks = {
> +      clusterNodeGetCallback,
> +      clusterTrackCallback
> +    };
> +
> +    SaVersionT version = { 'B', 4, 0 };
> +
> +    while (true) {
> +      rc = saClmInitialize_4(&cb->clm_hdl, &callbacks, &version);
> +
> +      if (rc == SA_AIS_ERR_TRY_AGAIN) {
> +        osaf_nanosleep(&kHundredMilliseconds);
> +        continue;
> +      } else if (rc != SA_AIS_OK) {
> +        LOG_ER("saClmInitialize_4 failed: %i", rc);
> +        break;
> +      } else {
> +        break;
> +      }
> +    }
> +
> +    rc = saClmClusterNodeGetAsync(cb->clm_hdl,
> +                                  1,
> +                                  SA_CLM_LOCAL_NODE_ID);
> +
> +    if (rc != SA_AIS_OK) {
> +      LOG_ER("saClmClusterNodeGetAsync failed: %i", rc);
> +      break;
> +    }
> +  } while (false);
> +
> +  if (rc != SA_AIS_OK && cb->clm_hdl)
> +    glnd_clm_deinit(cb);
> +
> +  return rc;
> +  TRACE_LEAVE();
> +}
> +
> +SaAisErrorT glnd_clm_deinit(GLND_CB *cb)
> +{
> +  SaAisErrorT rc(saClmFinalize(cb->clm_hdl));
> +
> +  if (rc != SA_AIS_OK)
> +    LOG_ER("saClmFinalize failed: %i", rc);
> +
> +  cb->clm_hdl = 0;
> +
> +  return rc;
> +}
> diff --git a/src/lck/lcknd/glnd_clm.h b/src/lck/lcknd/glnd_clm.h
> new file mode 100644
> index 0000000..dd8ec14
> --- /dev/null
> +++ b/src/lck/lcknd/glnd_clm.h
> @@ -0,0 +1,17 @@
> +#ifndef LCK_LCKND_GLND_CLM_H_
> +#define LCK_LCKND_GLND_CLM_H_
> +
> +#include "lck/lcknd/glnd.h"
> +
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
> +SaAisErrorT glnd_clm_init(GLND_CB *);
> +SaAisErrorT glnd_clm_deinit(GLND_CB *);
> +
> +#ifdef  __cplusplus
> +}
> +#endif
> +
> +#endif  // LCK_LCKND_GLND_CLM_H_
> diff --git a/src/lck/lcknd/glnd_evt.c b/src/lck/lcknd/glnd_evt.c
> index 75351c9..7eaea3a 100644
> --- a/src/lck/lcknd/glnd_evt.c
> +++ b/src/lck/lcknd/glnd_evt.c
> @@ -71,6 +71,7 @@ dump the cb.
>  ************************************************************
> ******************/
>
>  #include "lck/lcknd/glnd.h"
> +#include "lck/common/glsv_defs.h"
>
>  /***********************************************************
> *******************/
>
> @@ -529,6 +530,20 @@ static uint32_t 
> glnd_process_gla_client_initialize(GLND_CB
> *glnd_cb,
>         memset(&gla_evt, 0, sizeof(GLSV_GLA_EVT));
>         gla_evt.type = GLSV_GLA_API_RESP_EVT;
>
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version) &&
> +      !glnd_cb->isClusterMember) {
> +               TRACE_2("gla client initialize failed, node is not cluster
> member");
> +               /* initialise the gla_evt */
> +               gla_evt.error = SA_AIS_ERR_UNAVAILABLE;
> +               gla_evt.type = GLSV_GLA_API_RESP_EVT;
> +               gla_evt.info.gla_resp_info.type =
> GLSV_GLA_LOCK_INITIALIZE;
> +
> +               /* send the evt */
> +               glnd_mds_msg_send_rsp_gla(glnd_cb, &gla_evt,
> client_info->agent_mds_dest, &evt->mds_context);
> +
> +               goto end;
> +  }
> +
>         if (glnd_cb->node_state != GLND_OPERATIONAL_STATE ||
>             glnd_cb->gld_card_up != true) {
>                 TRACE_2("gla client initialize failed, glnd state %d",
> @@ -680,6 +695,7 @@ static uint32_t glnd_process_gla_resource_open(GLND_CB
> *glnd_cb,
>                                                GLSV_GLND_EVT *evt)
>  {
>         GLSV_EVT_RSC_INFO *rsc_info;
> +  GLND_CLIENT_INFO *client_info;
>         GLND_RESOURCE_INFO *resource_node;
>         GLND_RESOURCE_REQ_LIST *res_req_node;
>         GLSV_GLA_EVT gla_evt;
> @@ -689,6 +705,52 @@ static uint32_t glnd_process_gla_resource_open(GLND_CB
> *glnd_cb,
>
>         rsc_info = (GLSV_EVT_RSC_INFO *)&evt->info.rsc_info;
>
> +       /* get the client handle */
> +       client_info = glnd_client_node_find(glnd_cb,
> rsc_info->client_handle_id);
> +       if (!client_info) {
> +               /* initialise the gla_evt */
> +               memset(&gla_evt, 0, sizeof(GLSV_GLA_EVT));
> +
> +               gla_evt.error = SA_AIS_ERR_BAD_HANDLE;
> +               gla_evt.handle = rsc_info->client_handle_id;
> +               gla_evt.type = GLSV_GLA_API_RESP_EVT;
> +               gla_evt.info.gla_resp_info.type = GLSV_GLA_LOCK_RES_CLOSE;
> +               glnd_mds_msg_send_rsp_gla(glnd_cb, &gla_evt,
> rsc_info->agent_mds_dest, &evt->mds_context);
> +
> +               TRACE_2("GLND Client node find failed");
> +               rc = NCSCC_RC_FAILURE;
> +               goto end;
> +       }
> +
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version) &&
> +      !glnd_cb->isClusterMember) {
> +               TRACE_2("resource open failed, node is not cluster
> member");
> +               memset(&gla_evt, 0, sizeof(GLSV_GLA_EVT));
> +               gla_evt.handle = rsc_info->client_handle_id;
> +
> +               if (rsc_info->call_type == GLSV_SYNC_CALL) {
> +                 /* initialise the gla_evt */
> +                 gla_evt.error = SA_AIS_ERR_UNAVAILABLE;
> +                 gla_evt.type = GLSV_GLA_API_RESP_EVT;
> +                 gla_evt.info.gla_resp_info.type =
> GLSV_GLA_LOCK_RES_OPEN;
> +
> +                 /* send the evt */
> +                 glnd_mds_msg_send_rsp_gla(glnd_cb, &gla_evt,
> rsc_info->agent_mds_dest, &evt->mds_context);
> +
> +                 goto end;
> +    } else {
> +                       gla_evt.type = GLSV_GLA_CALLBK_EVT;
> +                       gla_evt.info.gla_clbk_info.callback_type =
> GLSV_LOCK_RES_OPEN_CBK;
> +                       gla_evt.info.gla_clbk_info.resourceId =
> rsc_info->lcl_resource_id;
> +                       gla_evt.info.gla_clbk_info.params.res_open.resourceId
> = 0;
> +                       gla_evt.info.gla_clbk_info.params.res_open.invocation
> = rsc_info->invocation;
> +                       gla_evt.info.gla_clbk_info.params.res_open.error
> = SA_AIS_ERR_UNAVAILABLE;
> +                       /* send the evt */
> +                       glnd_mds_msg_send_gla(glnd_cb, &gla_evt,
> rsc_info->agent_mds_dest);
> +
> +                       goto end;
> +    }
> +  }
>         if (glnd_cb->node_state != GLND_OPERATIONAL_STATE ||
>             glnd_cb->gld_card_up != true) {
>                 TRACE_2("resource open failed, glnd state %d",
> @@ -927,40 +989,58 @@ static uint32_t glnd_process_gla_resource_close(GLND_CB
> *glnd_cb,
>
>         rsc_info = (GLSV_EVT_RSC_INFO *)&evt->info.rsc_info;
>
> -       if (glnd_cb->node_state != GLND_OPERATIONAL_STATE ||
> -           glnd_cb->gld_card_up != true) {
> -               TRACE_2("resource close failed, glnd state %d",
> -                       glnd_cb->node_state);
> +       /* get the client handle */
> +       client_info =
> +           glnd_client_node_find(glnd_cb, rsc_info->client_handle_id);
> +       if (!client_info) {
>                 /* initialise the gla_evt */
>                 memset(&gla_evt, 0, sizeof(GLSV_GLA_EVT));
>
> -               gla_evt.error = SA_AIS_ERR_TRY_AGAIN;
> +               gla_evt.error = SA_AIS_ERR_BAD_HANDLE;
>                 gla_evt.handle = rsc_info->client_handle_id;
>                 gla_evt.type = GLSV_GLA_API_RESP_EVT;
>                 gla_evt.info.gla_resp_info.type = GLSV_GLA_LOCK_RES_CLOSE;
>                 glnd_mds_msg_send_rsp_gla(glnd_cb, &gla_evt,
>                                           rsc_info->agent_mds_dest,
>                                           &evt->mds_context);
> +
> +               TRACE_2("GLND Client node find failed");
> +               rc = NCSCC_RC_FAILURE;
>                 goto end;
>         }
>
> -       /* get the client handle */
> -       client_info =
> -           glnd_client_node_find(glnd_cb, rsc_info->client_handle_id);
> -       if (!client_info) {
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version) &&
> +      !glnd_cb->isClusterMember) {
> +               TRACE_2("resource close failed, node is not cluster
> member");
> +               /* initialise the gla_evt */
> +               gla_evt.error = SA_AIS_ERR_UNAVAILABLE;
> +    gla_evt.handle = rsc_info->client_handle_id;
> +               gla_evt.type = GLSV_GLA_API_RESP_EVT;
> +               gla_evt.info.gla_resp_info.type = GLSV_GLA_LOCK_RES_CLOSE;
> +
> +               glnd_mds_msg_send_rsp_gla(glnd_cb,
> +                              &gla_evt,
> +                              rsc_info->agent_mds_dest,
> +                              &evt->mds_context);
> +
> +               goto end;
> +  }
> +
> +
> +       if (glnd_cb->node_state != GLND_OPERATIONAL_STATE ||
> +           glnd_cb->gld_card_up != true) {
> +               TRACE_2("resource close failed, glnd state %d",
> +                       glnd_cb->node_state);
>                 /* initialise the gla_evt */
>                 memset(&gla_evt, 0, sizeof(GLSV_GLA_EVT));
>
> -               gla_evt.error = SA_AIS_ERR_BAD_HANDLE;
> +               gla_evt.error = SA_AIS_ERR_TRY_AGAIN;
>                 gla_evt.handle = rsc_info->client_handle_id;
>                 gla_evt.type = GLSV_GLA_API_RESP_EVT;
>                 gla_evt.info.gla_resp_info.type = GLSV_GLA_LOCK_RES_CLOSE;
>                 glnd_mds_msg_send_rsp_gla(glnd_cb, &gla_evt,
>                                           rsc_info->agent_mds_dest,
>                                           &evt->mds_context);
> -
> -               TRACE_2("GLND Client node find failed");
> -               rc = NCSCC_RC_FAILURE;
>                 goto end;
>         }
>
> @@ -1088,6 +1168,50 @@ static uint32_t glnd_process_gla_resource_lock(GLND_CB
> *glnd_cb,
>
>         rsc_lock_info = (GLSV_EVT_RSC_LOCK_INFO *)&evt->info.rsc_lock_info;
>
> +       /* get the client handle */
> +       client_info =
> +           glnd_client_node_find(glnd_cb, rsc_lock_info->client_handle_
> id);
> +       if (!client_info) {
> +               LOG_ER("GLND Client node find failed");
> +               rc = NCSCC_RC_FAILURE;
> +               goto end;
> +       }
> +
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version) &&
> +      !glnd_cb->isClusterMember) {
> +               TRACE_2("resource lock failed, node is not cluster
> member");
> +               if (rsc_lock_info->call_type == GLSV_SYNC_CALL) {
> +                 gla_evt.error = SA_AIS_ERR_UNAVAILABLE;
> +      gla_evt.handle = rsc_lock_info->client_handle_id;
> +                 gla_evt.type = GLSV_GLA_API_RESP_EVT;
> +                 gla_evt.info.gla_resp_info.type =
> GLSV_GLA_LOCK_SYNC_LOCK;
> +
> +                 glnd_mds_msg_send_rsp_gla(glnd_cb,
> +                                &gla_evt,
> +                                rsc_lock_info->agent_mds_dest,
> +                                &evt->mds_context);
> +
> +                       rc = NCSCC_RC_FAILURE;
> +                 goto end;
> +    } else {
> +                       m_GLND_RESOURCE_ASYNC_LCK_GRANT_FILL(
> +        gla_evt,
> +        SA_AIS_ERR_UNAVAILABLE,
> +                               0,
> +                               rsc_lock_info->lcl_lockid,
> +                               rsc_lock_info->lock_type,
> +                               rsc_lock_info->lcl_resource_id,
> +                               rsc_lock_info->invocation,
> +                               0,
> +        rsc_lock_info->client_handle_id);
> +
> +                       /* send the evt to GLA */
> +                       glnd_mds_msg_send_gla(glnd_cb, &gla_evt,
> rsc_lock_info->agent_mds_dest);
> +                       rc = NCSCC_RC_FAILURE;
> +                       goto end;
> +    }
> +  }
> +
>         /* check for the resource node  */
>         res_node = glnd_resource_node_find(glnd_cb,
> rsc_lock_info->resource_id);
>         if (!res_node) {
> @@ -1131,15 +1255,6 @@ static uint32_t glnd_process_gla_resource_lock(GLND_CB
> *glnd_cb,
>                 }
>         }
>
> -       /* get the client handle */
> -       client_info =
> -           glnd_client_node_find(glnd_cb, rsc_lock_info->client_handle_
> id);
> -       if (!client_info) {
> -               LOG_ER("GLND Client node find failed");
> -               rc = NCSCC_RC_FAILURE;
> -               goto end;
> -       }
> -
>         gla_evt.handle = rsc_lock_info->client_handle_id;
>
>         if (res_node->status == GLND_RESOURCE_NOT_INITIALISED) {
> @@ -1347,6 +1462,42 @@ static uint32_t 
> glnd_process_gla_resource_unlock(GLND_CB
> *glnd_cb,
>             (GLSV_EVT_RSC_UNLOCK_INFO *)&evt->info.rsc_unlock_info;
>         memset(&lck_info, 0, sizeof(GLSV_LOCK_REQ_INFO));
>
> +       /* get the client handle */
> +       client_info =
> +           glnd_client_node_find(glnd_cb, rsc_unlock_info->client_
> handle_id);
> +       if (!client_info) {
> +               LOG_ER("GLND Client node find failed");
> +               goto end;
> +       }
> +
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version) &&
> +      !glnd_cb->isClusterMember) {
> +               TRACE_2("resource unlock failed, node is not cluster
> member");
> +               if (rsc_unlock_info->call_type == GLSV_SYNC_CALL) {
> +                 gla_evt.error = SA_AIS_ERR_UNAVAILABLE;
> +      gla_evt.handle = rsc_unlock_info->client_handle_id;
> +                 gla_evt.type = GLSV_GLA_API_RESP_EVT;
> +                 gla_evt.info.gla_resp_info.type =
> GLSV_GLA_LOCK_SYNC_UNLOCK;
> +
> +                 glnd_mds_msg_send_rsp_gla(glnd_cb,
> +                                &gla_evt,
> +                                rsc_unlock_info->agent_mds_dest,
> +                                &evt->mds_context);
> +
> +                 goto end;
> +    } else {
> +                       m_GLND_RESOURCE_ASYNC_LCK_UNLOCK_FILL(gla_evt,
> SA_AIS_ERR_UNAVAILABLE,
> +
>  rsc_unlock_info->invocation,
> +
>  rsc_unlock_info->lcl_resource_id,
> +
>  rsc_unlock_info->lcl_lockid, 0);
> +                       gla_evt.handle = rsc_unlock_info->client_
> handle_id;
> +
> +                       /* send the evt to GLA */
> +                       glnd_mds_msg_send_gla(glnd_cb, &gla_evt,
> rsc_unlock_info->agent_mds_dest);
> +                       goto end;
> +    }
> +  }
> +
>         /* get the resource node */
>         res_node =
>             glnd_resource_node_find(glnd_cb,
> rsc_unlock_info->resource_id);
> @@ -1390,14 +1541,6 @@ static uint32_t 
> glnd_process_gla_resource_unlock(GLND_CB
> *glnd_cb,
>                 }
>         }
>
> -       /* get the client handle */
> -       client_info =
> -           glnd_client_node_find(glnd_cb, rsc_unlock_info->client_
> handle_id);
> -       if (!client_info) {
> -               LOG_ER("GLND Client node find failed");
> -               goto end;
> -       }
> -
>         if (res_node->status == GLND_RESOURCE_NOT_INITIALISED) {
>                 /* sleep for relection time and resend the event */
>                 uint32_t tm = GLSV_GLND_MASTER_REELECTION_WAIT_TIME /
> 10000000;
> @@ -1609,6 +1752,7 @@ static uint32_t glnd_process_gla_resource_purge(GLND_CB
> *glnd_cb,
>  {
>         GLSV_EVT_RSC_INFO *rsc_info;
>         GLND_RESOURCE_INFO *res_node = NULL;
> +  GLND_CLIENT_INFO *client_info;
>         rsc_info = (GLSV_EVT_RSC_INFO *)&evt->info.rsc_info;
>         GLSV_GLA_EVT gla_evt;
>         SaAisErrorT error = SA_AIS_ERR_LIBRARY;
> @@ -1618,6 +1762,44 @@ static uint32_t glnd_process_gla_resource_purge(GLND_CB
> *glnd_cb,
>         memset(&gla_evt, 0, sizeof(GLSV_GLA_EVT));
>         gla_evt.type = GLSV_GLA_API_RESP_EVT;
>
> +       /* get the client handle */
> +       client_info = glnd_client_node_find(glnd_cb,
> rsc_info->client_handle_id);
> +       if (!client_info) {
> +               /* initialise the gla_evt */
> +               memset(&gla_evt, 0, sizeof(GLSV_GLA_EVT));
> +
> +               gla_evt.error = SA_AIS_ERR_BAD_HANDLE;
> +               gla_evt.handle = rsc_info->client_handle_id;
> +               gla_evt.type = GLSV_GLA_API_RESP_EVT;
> +               gla_evt.info.gla_resp_info.type = GLSV_GLA_LOCK_RES_CLOSE;
> +               glnd_mds_msg_send_rsp_gla(glnd_cb,
> +                              &gla_evt,
> +                              rsc_info->agent_mds_dest,
> +                              &evt->mds_context);
> +
> +               TRACE_2("GLND Client node find failed");
> +               rc = NCSCC_RC_FAILURE;
> +               goto end;
> +       }
> +
> +  if (m_GLA_VER_IS_AT_LEAST_B_3(client_info->version) &&
> +      !glnd_cb->isClusterMember) {
> +               TRACE_2("resource purge failed, node is not cluster
> member");
> +               /* initialise the gla_evt */
> +               gla_evt.error = SA_AIS_ERR_UNAVAILABLE;
> +               gla_evt.handle = rsc_info->client_handle_id;
> +               gla_evt.type = GLSV_GLA_API_RESP_EVT;
> +               gla_evt.info.gla_resp_info.type =
> GLSV_GLA_LOCK_INITIALIZE;
> +
> +               /* send the evt */
> +               glnd_mds_msg_send_rsp_gla(glnd_cb,
> +                              &gla_evt,
> +                              rsc_info->agent_mds_dest,
> +                              &evt->mds_context);
> +
> +               goto end;
> +  }
> +
>         /* get the resource node */
>         res_node = glnd_resource_node_find(glnd_cb,
> rsc_info->resource_id);
>         if (!res_node) {
> @@ -2336,6 +2518,14 @@ static uint32_t 
> glnd_process_glnd_lck_waiter_clbk(GLND_CB
> *glnd_cb,
>
>         waiter_clbk = (GLSV_EVT_GLND_LCK_INFO *)&evt->info.node_lck_info;
>
> +  /* don't send the callback if we are not a cluster member */
> +  if (!glnd_cb->isClusterMember) {
> +    TRACE("not sending waiter callback because this node is not in the "
> +          "cluster");
> +               rc = NCSCC_RC_FAILURE;
> +    goto end;
> +  }
> +
>         res_node = glnd_resource_node_find(glnd_cb,
> waiter_clbk->resource_id);
>         if (!res_node) {
>                 LOG_ER("GLND Rsc node find failed");
> diff --git a/src/lck/lcknd/glnd_mds.c b/src/lck/lcknd/glnd_mds.c
> index 7f4a692..69ac0c1 100644
> --- a/src/lck/lcknd/glnd_mds.c
> +++ b/src/lck/lcknd/glnd_mds.c
> @@ -68,6 +68,7 @@ static uint32_t glsv_gla_enc_callbk_evt(NCS_UBAID *uba,
>                                         GLSV_GLA_CALLBACK_INFO *evt);
>  static uint32_t glsv_gla_enc_api_resp_evt(NCS_UBAID *uba,
>                                           GLSV_GLA_API_RESP_INFO *evt);
> +static uint32_t glsv_gla_enc_clm_evt(NCS_UBAID *uba, GLSV_GLA_CLM_INFO
> *evt);
>
>  uint32_t glnd_mds_get_handle(GLND_CB *cb);
>
> @@ -382,6 +383,10 @@ static uint32_t glnd_mds_enc(GLND_CB *cb,
> MDS_CALLBACK_ENC_INFO *info)
>                                     uba, &evt->info.gla_resp_info);
>                                 break;
>
> +      case GLSV_GLA_CLM_EVT:
> +                               rc = glsv_gla_enc_clm_evt(uba,
> &evt->info.gla_clm_info);
> +                               break;
> +
>                         default:
>                                 goto end;
>                         }
> @@ -1652,3 +1657,37 @@ static uint32_t glsv_gla_enc_api_resp_evt(NCS_UBAID
> *uba,
>
>         return NCSCC_RC_SUCCESS;
>  }
> +
> +/**********************************************************
> ******************
> +  Name          : glsv_gla_enc_clm_evt
> +
> +  Description   : This routine encodes api response info.
> +
> +  Arguments     : uba , api response info.
> +
> +  Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
> +
> +  Notes         : None.
> +***********************************************************
> *******************/
> +static uint32_t glsv_gla_enc_clm_evt(NCS_UBAID *uba, GLSV_GLA_CLM_INFO
> *evt)
> +{
> +       uint8_t *p8, size;
> +  uint32_t rc = NCSCC_RC_SUCCESS;
> +
> +  do {
> +         size = (4);
> +   /** encode the type of message **/
> +         p8 = ncs_enc_reserve_space(uba, size);
> +         if (!p8) {
> +                 TRACE_2("GLND enc failed");
> +                 rc =  NCSCC_RC_FAILURE;
> +      break;
> +         }
> +
> +         osaf_encode_bool(uba, evt->isClusterMember);
> +
> +         ncs_enc_claim_space(uba, size);
> +  } while (false);
> +
> +       return rc;
> +}
> diff --git a/src/lck/lcknd/glnd_mds.h b/src/lck/lcknd/glnd_mds.h
> index e258a3f..d7c47b1 100644
> --- a/src/lck/lcknd/glnd_mds.h
> +++ b/src/lck/lcknd/glnd_mds.h
> @@ -30,6 +30,10 @@
>  #ifndef LCK_LCKND_GLND_MDS_H_
>  #define LCK_LCKND_GLND_MDS_H_
>
> +#ifdef  __cplusplus
> +extern "C" {
> +#endif
> +
>  /***********************************************************
> ******************/
>
>  #define SVC_SUBPART_VER uns32
> @@ -175,4 +179,8 @@ typedef uint32_t (*GLSV_GLND_EVT_HANDLER)(struct
> glnd_cb_tag *,
>      (l_evt).info.gla_clbk_info.params.unlock.error = (l_err);
>    \
>    } while (0);
>
> +#ifdef  __cplusplus
> +}
> +#endif
> +
>  #endif  // LCK_LCKND_GLND_MDS_H_
> diff --git a/src/lck/lcknd/glnd_res.c b/src/lck/lcknd/glnd_res.c
> index 4e4f47a..90f6770 100644
> --- a/src/lck/lcknd/glnd_res.c
> +++ b/src/lck/lcknd/glnd_res.c
> @@ -1396,6 +1396,10 @@ static void glnd_master_process_lock_
> initiate_waitercallbk(
>
>  lock_list_info->req_mdest_id);
>
>                 } else {
> +      /* don't send the callback if we are not a cluster member */
> +      if (!cb->isClusterMember)
> +        break;
> +
>                         GLSV_GLA_EVT gla_evt;
>                         GLND_CLIENT_INFO *client_info;
>                         /* send it to the local GLA component */
> diff --git a/src/lck/lcknd/glnd_res_req.c b/src/lck/lcknd/glnd_res_req.c
> index 7d3e5e9..1490ba5 100644
> --- a/src/lck/lcknd/glnd_res_req.c
> +++ b/src/lck/lcknd/glnd_res_req.c
> @@ -171,3 +171,53 @@ void glnd_resource_req_node_del(GLND_CB *glnd_cb,
> uint32_t res_req_hdl)
>         }
>         return;
>  }
> +
> +/**********************************************************
> *******************
> +  PROCEDURE NAME : glnd_resource_req_node_down
> +
> +  DESCRIPTION    : Sends callback responses to outstanding requests from
> node
> +                   down
> +
> +  ARGUMENTS      :glnd_cb      - ptr to the GLND control block
> +
> +
> +  RETURNS        :The pointer to the resource req node info on success.
> +                  else returns NULL.
> +
> +  NOTES         : Delete the returned pointer immediately.
> +***********************************************************
> ******************/
> +void glnd_resource_req_node_down(GLND_CB *glnd_cb)
> +{
> +       GLND_RESOURCE_REQ_LIST *res_req_info;
> +
> +       for (res_req_info = glnd_cb->res_req_list;
> +       res_req_info;
> +       res_req_info = res_req_info->next) {
> +               GLSV_GLA_EVT gla_evt;
> +
> +    if (res_req_info->call_type == GLSV_SYNC_CALL) {
> +      glnd_stop_tmr(&res_req_info->timeout);
> +
> +      gla_evt.error = SA_AIS_ERR_UNAVAILABLE;
> +      gla_evt.handle = res_req_info->client_handle_id;
> +      gla_evt.type = GLSV_GLA_API_RESP_EVT;
> +      gla_evt.info.gla_resp_info.type = GLSV_GLA_LOCK_RES_OPEN;
> +
> +      glnd_mds_msg_send_rsp_gla(glnd_cb,
> +                                &gla_evt,
> +                                res_req_info->agent_mds_dest,
> +                                &res_req_info->glnd_res_mds_ctxt);
> +    } else if (res_req_info->call_type == GLSV_ASYNC_CALL) {
> +      gla_evt.type = GLSV_GLA_CALLBK_EVT;
> +      gla_evt.info.gla_clbk_info.callback_type = GLSV_LOCK_RES_OPEN_CBK;
> +      gla_evt.info.gla_clbk_info.resourceId =
> res_req_info->lcl_resource_id;
> +      gla_evt.info.gla_clbk_info.params.res_open.resourceId = 0;
> +      gla_evt.info.gla_clbk_info.params.res_open.invocation =
> +        res_req_info->invocation;
> +      gla_evt.info.gla_clbk_info.params.res_open.error =
> SA_AIS_ERR_UNAVAILABLE;
> +
> +      glnd_mds_msg_send_gla(glnd_cb, &gla_evt,
> res_req_info->agent_mds_dest);
> +    }
> +  }
> +}
> +
> --
> 2.7.4
>
>
------------------------------------------------------------------------------
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to