Please see responses with [Lennart]

Thanks
Lennart

> -----Original Message-----
> From: praveen malviya [mailto:praveen.malv...@oracle.com]
> Sent: den 18 februari 2016 14:02
> To: Minh Chau H; Lennart Lund; Vu Minh Nguyen
> Cc: opensaf-devel@lists.sourceforge.net
> Subject: Re: [PATCH 1 of 5] NTF: Add support cloud resilience for NTF Agent
> [#1180]
> 
> Please see the responses with [Praveen]
> 
> Thanks,
> Praveen
> 
> On 12-Feb-16 8:52 PM, minh chau wrote:
> > Hi Praveen,
> >
> > Please find my comments inline [Minh]
> >
> > Thanks,
> > Minh
> >
> > On 12/02/16 22:10, praveen malviya wrote:
> >> Hi Minh,
> >>
> >> Please find some initial comments and questions marked with [Praveen].
> >>
> >> One question regarding the approach.
> >> In most of the changed APIs from saNtfInitialize() to
> >> saNtfNotificationReadFinalize(), clients are being recovered. Why the
> >> idea of recovering them is not considered in mds callback itself in
> >> the function call ntfa_update_ntfsv_state() when server state changes
> >> from DOWN to UP. It will save changes in APIs for recovering the
> >> clients. Clients are being marked invalid in the mds_callback itself.
> >>
> > [Minh] From memory I did try to recover clients in mds callback
> > (svc_evt) where indicates server UP. Though recovery needs to send
> > messages (reintroducing client id, read id, ...) to server, that will
> > end up another mds enc callback inside of first callback. That results
> > into fail to send *recovery* messages, there are two mds callback but
> > only one return. To solve this, I need to start a thread the recover
> > clients in background. That would cause another problem where up calls
> > from client could be blocked, since the recovery thread needs to block
> > mutual resource handles.
> > Another realistic reason, client can give up to send/read/receive
> > notification after receiving couple times of TRY_AGAIN due to server
> > down, and doing nothing until finalize handle. And after client stops
> > TRY_AGAIN loop, server can be restarted. In such cases, no needs to
> > recover client handles.
> >> Thanks,
> >> Praveen
> >>
> >> On 23-Dec-15 9:32 AM, Minh Hon Chau wrote:
> >>>   osaf/libs/agents/saf/ntfa/ntfa.h |   31 +-
> >>>   osaf/libs/agents/saf/ntfa/ntfa_api.c  |  672
> >>> +++++++++++++++++++++++++++------
> >>>   osaf/libs/agents/saf/ntfa/ntfa_mds.c  |    6 +-
> >>>   osaf/libs/agents/saf/ntfa/ntfa_util.c |  465
> ++++++++++++++++++++++-
> >>>   4 files changed, 1022 insertions(+), 152 deletions(-)
> >>>
> >>>
> >>> The patch contains support for cloud resilience feature
> >>> in NTF Agent code. Please refer README.HYDRA for content
> >>> of the changes
> >>>
> >>> diff --git a/osaf/libs/agents/saf/ntfa/ntfa.h
> >>> b/osaf/libs/agents/saf/ntfa/ntfa.h
> >>> --- a/osaf/libs/agents/saf/ntfa/ntfa.h
> >>> +++ b/osaf/libs/agents/saf/ntfa/ntfa.h
> >>> @@ -91,6 +91,7 @@ typedef struct ntfa_filter_hdl_rec {
> >>>   typedef struct subscriberList {
> >>>       SaNtfHandleT subscriberListNtfHandle;
> >>>       SaNtfSubscriptionIdT subscriberListSubscriptionId;
> >>> +    ntfsv_filter_ptrs_t filters; /* remember the filters used by
> >>> this subscriber */
> >>>       struct subscriberList *prev;
> >>>       struct subscriberList *next;
> >>>   } ntfa_subscriber_list_t;
> >>> @@ -100,6 +101,10 @@ typedef struct ntfa_reader_hdl_rec {
> >>>       unsigned int reader_id;    /* handle value returned by NTFS for
> >>> this client */
> >>>       SaNtfHandleT ntfHandle;
> >>>       unsigned int reader_hdl;    /* READER handle from handle mgr */
> >>> +
> >>> +    ntfsv_filter_ptrs_t filters; /* remember the filters used by
> >>> this reader */
> >>> +    SaNtfSearchCriteriaT searchCriteria; /* remember the
> >>> searchCriteria for recovery */
> >>> +
> >>>       struct ntfa_reader_hdl_rec *next;    /* next pointer for the
> >>> list in ntfa_cb_t */
> >>>       struct ntfa_client_hdl_rec *parent_hdl;    /* Back Pointer to
> >>> the client instantiation */
> >>>   } ntfa_reader_hdl_rec_t;
> >>> @@ -114,24 +119,35 @@ typedef struct ntfa_client_hdl_rec {
> >>>       ntfa_reader_hdl_rec_t *reader_list;
> >>>       SYSF_MBX mbx;        /* priority q mbx b/w MDS & Library */
> >>>       struct ntfa_client_hdl_rec *next;    /* next pointer for the
> >>> list in ntfa_cb_t */
> >>> +    bool valid;        /* handle is valid if it's known by NTF
> >>> server, used for headless hydra */
> >>> +    SaVersionT version; /* the API version is being used by client,
> >>> used for recover after headless */
> >>>   } ntfa_client_hdl_rec_t;
> >>>
> >>>   /*
> >>>    * The NTFA control block is the master anchor structure for all NTFA
> >>>    * instantiations within a process.
> >>>    */
> >>> +typedef enum {
> >>> +    NTFA_NTFSV_NONE = 0,
> >>> +    NTFA_NTFSV_DOWN,
> >>> +    NTFA_NTFSV_NO_ACTIVE,
> >>> +    NTFA_NTFSV_NEW_ACTIVE,
> >>> +    NTFA_NTFSV_UP
> >>> +}ntfa_ntfsv_state_t;
> >>> +
> >>>   typedef struct {
> >>>       pthread_mutex_t cb_lock;    /* CB lock */
> >>>       ntfa_client_hdl_rec_t *client_list;    /* NTFA client handle
> >>> database */
> >>>       ntfa_reader_hdl_rec_t *reader_list;
> >>>       MDS_HDL mds_hdl;    /* MDS handle */
> >>>       MDS_DEST ntfs_mds_dest;    /* NTFS absolute/virtual address */
> >>> -    int ntfs_up;        /* Indicate that MDS subscription
> >>> -                 * is complete */
> >>> +
> >>>       /* NTFS NTFA sync params */
> >>>       int ntfs_sync_awaited;
> >>>       NCS_SEL_OBJ ntfs_sync_sel;
> >>>       SaUint32T ntf_var_data_limit;    /* max allowed
> >>> variableDataSize */
> >>> +    /* NTF Server state */
> >>> +    ntfa_ntfsv_state_t ntfa_ntfsv_state;
> >>>   } ntfa_cb_t;
> >>>
> >>>   /* ntfa_saf_api.c */
> >>> @@ -149,7 +165,7 @@ extern void ntfsv_ntfa_evt_free(struct n
> >>>
> >>>   /* ntfa_init.c */
> >>>   extern unsigned int ntfa_startup(void);
> >>> -extern unsigned int ntfa_shutdown(void);
> >>> +extern unsigned int ntfa_shutdown(bool forced);
> >>>
> >>>   /* ntfa_hdl.c */
> >>>   extern SaAisErrorT ntfa_hdl_cbk_dispatch(ntfa_cb_t *,
> >>> ntfa_client_hdl_rec_t *, SaDispatchFlagsT);
> >>> @@ -159,6 +175,7 @@ extern ntfa_notification_hdl_rec_t *ntfa
> >>>   extern ntfa_filter_hdl_rec_t
> >>> *ntfa_filter_hdl_rec_add(ntfa_client_hdl_rec_t **hdl_rec);
> >>>   extern void ntfa_hdl_list_del(ntfa_client_hdl_rec_t **);
> >>>   extern uint32_t ntfa_hdl_rec_del(ntfa_client_hdl_rec_t **,
> >>> ntfa_client_hdl_rec_t *);
> >>> +extern void ntfa_hdl_rec_force_del(ntfa_client_hdl_rec_t **,
> >>> ntfa_client_hdl_rec_t *);
> >>>   extern uint32_t
> >>> ntfa_notification_hdl_rec_del(ntfa_notification_hdl_rec_t **,
> >>> ntfa_notification_hdl_rec_t *);
> >>>   extern uint32_t ntfa_filter_hdl_rec_del(ntfa_filter_hdl_rec_t **,
> >>> ntfa_filter_hdl_rec_t *);
> >>>   extern bool ntfa_validate_ntfa_client_hdl(ntfa_cb_t *ntfa_cb,
> >>> ntfa_client_hdl_rec_t *find_hdl_rec);
> >>> @@ -166,11 +183,15 @@ extern bool ntfa_validate_ntfa_client_hd
> >>>   /* ntfa_util.c */
> >>>   extern ntfa_client_hdl_rec_t
> >>> *ntfa_find_hdl_rec_by_client_id(ntfa_cb_t *ntfa_cb, uint32_t
> client_id);
> >>>   extern void ntfa_msg_destroy(ntfsv_msg_t *msg);
> >>> -extern void ntfa_hdl_rec_destructor(ntfa_notification_hdl_rec_t
> >>> *instance);
> >>> -extern void ntfa_filter_hdl_rec_destructor(ntfa_filter_hdl_rec_t
> >>> +extern void ntfa_notification_destructor(ntfa_notification_hdl_rec_t
> >>> *instance);
> >>> +extern void ntfa_filter_destructor(ntfa_filter_hdl_rec_t
> >>>                          *notificationFilterInstance);
> >>>   extern ntfa_reader_hdl_rec_t
> >>> *ntfa_reader_hdl_rec_add(ntfa_client_hdl_rec_t **hdl_rec);
> >>>   extern uint32_t ntfa_reader_hdl_rec_del(ntfa_reader_hdl_rec_t **,
> >>> ntfa_reader_hdl_rec_t *);
> >>>   extern void ntfa_add_to_async_cbk_msg_list(ntfsv_msg_t ** head,
> >>> ntfsv_msg_t * new_node);
> >>>   extern uint32_t ntfa_ntfs_msg_proc(ntfa_cb_t *cb, ntfsv_msg_t
> >>> *ntfsv_msg, MDS_SEND_PRIORITY_TYPE prio);
> >>> +extern void ntfa_update_ntfsv_state(ntfa_ntfsv_state_t
> changedState);
> >>> +extern SaAisErrorT ntfa_copy_ntf_filter_ptrs(ntfsv_filter_ptrs_t*
> pDes,
> >>> +                                const ntfsv_filter_ptrs_t* pSrc);
> >>> +extern SaAisErrorT ntfa_del_ntf_filter_ptrs(ntfsv_filter_ptrs_t*
> >>> filter_ptrs);
> >>>   #endif   /* !NTFA_H */
> >>> diff --git a/osaf/libs/agents/saf/ntfa/ntfa_api.c
> >>> b/osaf/libs/agents/saf/ntfa/ntfa_api.c
> >>> --- a/osaf/libs/agents/saf/ntfa/ntfa_api.c
> >>> +++ b/osaf/libs/agents/saf/ntfa/ntfa_api.c
> >>> @@ -34,11 +34,42 @@
> >>>   /* The main controle block */
> >>>   ntfa_cb_t ntfa_cb = {
> >>>       .cb_lock = PTHREAD_MUTEX_INITIALIZER,
> >>> +    .ntfa_ntfsv_state = NTFA_NTFSV_NONE,
> >>>   };
> >>>
> >>>   /* list of subscriptions for this process */
> >>>   ntfa_subscriber_list_t *subscriberNoList = NULL;
> >>>
> >>> +/*
> >>> + * @Brief: Determine the common "availability" of API, which depends
> >>> on the
> >>> + *         NTF Server state
> >>> + * @Param: None
> >>> + * @Return: OK - If Server state is UP
> >>> + *          TRY_AGAIN - If Server state is No Active (temporary no
> >>> active)
> >>> + *          BAD_HANDLE - If Server state is completely Down (no
> >>> active at all).
> >>> + *                       This error code will be returned to client
> >>> calling API
> >>> + */
> >>> +static SaAisErrorT checkNtfServerState()
> >>> +{
> >>> +    SaAisErrorT rc = SA_AIS_ERR_NOT_SUPPORTED;
> >>> +    /* Check NTF server availability */
> >>> +    if (ntfa_cb.ntfa_ntfsv_state == NTFA_NTFSV_UP) {
> >>> +        rc = SA_AIS_OK;
> >>> +    } else if (ntfa_cb.ntfa_ntfsv_state == NTFA_NTFSV_DOWN) {
> >>> +        TRACE("NTFS server is down");
> >>> +        rc = SA_AIS_ERR_TRY_AGAIN;
> >> [Praveen] 1. Function header says BAD_HANDLE for "down" but here
> >> TRY_AGAIN is returned.
> > [Minh]: I got similar comments from Lennart, I will correct the function
> > description
> >> 2. If server state is down, it means both ntfs are not up which means
> >> headless cluster. But in case of normal cluster also application will
> >> get TRY_AGAIN. Are you relying on the              fact that in normal
> >> cluster case payloads will be rebooted? if answer is yes then what if
> >> reboot is delayed by changing the opensaf_reboot script which is
> >> customizable?
> > [Minh]: I don't get your question. No impact if payloads reboot
> [Praveen] Actually I want draw attention to two problems here:
> 1) Normal cluster case: Both controllers are up in normal cluster
> (attribute commented in immd.conf) and some ntf application is running
> on the payload. Now if opensaf is stopped on the payload, application
> will still get TRY_AGIAN. Now if a fresh controller is started and
> payload is not started, the application API will be successful. But this
> application should not be able to get a success for any API since its
> payload  is down.
> 2) Headless cluster case: Same case when with headless cluster
> configured (attribute un-commented in immd.conf).
> 
> I think this may be the generic problem with all the service with two
> tier architecture and a fix is needed. There should be a mechanism
> though which agent should detect opensaf shutdown on local node and
> clear all clients data.
> 
> 
[Lennart] I cannot see that there is a problem if an OpenSAF service that has 
no node director (ntf and log) can recover and continue to work
after a headless situation. For this service there is no OpenSAF running on a 
payload node.
For the "normal" case (attribute  commented in immd.conf) the current behavior 
shall apply which is to invalidate all clients if no server is available 
(SC-nodes down). There should be no impact at all in any mode on the ntf and 
log service if OpenSAF is stopped on the payload node.
> >>
> >>> +    } else if (ntfa_cb.ntfa_ntfsv_state == NTFA_NTFSV_NO_ACTIVE) {
> >>> +        TRACE("NTFS server is unavailable");
> >>> +        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> +    } else if (ntfa_cb.ntfa_ntfsv_state == NTFA_NTFSV_NONE) {
> >>> +        TRACE("No NTF server is detected, or API is called during
> >>> headless");
> >>> +        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> +    } else
> >>> +        TRACE("Not supported API call under NTF Server state (%u)",
> >>> +                ntfa_cb.ntfa_ntfsv_state);
> >>> +    return rc;
> >>> +}
> >>> +
> >>>   static SaAisErrorT checkNtfValueTypeRange(SaNtfValueTypeT type)
> >>>   {
> >>>       return (type < SA_NTF_VALUE_UINT8 || type >
> >>> SA_NTF_VALUE_ARRAY)? SA_AIS_ERR_INVALID_PARAM
> >>> @@ -871,7 +902,266 @@ SaAisErrorT getFilters(const SaNtfNotifi
> >>>   }
> >>>
> >>>   /* end help functions */
> >>> -
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : reinitializeClient
> >>> +
> >>> +  Description   : This routine sends initialize messages to NTF
> >>> Server in
> >>> +          order to obtain new client id
> >>> +
> >>> +  Arguments     : client_hdl* [IN]: client handle
> >>> +
> >>> +  Return Values : SA_AIS_OK if success, others are failure
> >>> +
> >>> +  Notes         : None
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +SaAisErrorT reinitializeClient(ntfa_client_hdl_rec_t* client_hdl) {
> >>> +    uint32_t mds_rc;
> >>> +    SaAisErrorT rc = SA_AIS_OK;
> >>> +    ntfsv_msg_t i_msg, *o_msg = NULL;
> >>> +
> >>> +    TRACE_ENTER();
> >>> +
> >>> +    memset(&i_msg, 0, sizeof(ntfsv_msg_t));
> >>> +    i_msg.type = NTFSV_NTFA_API_MSG;
> >>> +    i_msg.info.api_info.type = NTFSV_INITIALIZE_REQ;
> >>> +    i_msg.info.api_info.param.init.version = client_hdl->version;
> >>> +
> >>> +    mds_rc = ntfa_mds_msg_sync_send(&ntfa_cb, &i_msg, &o_msg,
> >>> NTFS_WAIT_TIME);
> >>> +    switch (mds_rc) {
> >>> +    case NCSCC_RC_SUCCESS:
> >>> +        break;
> >>> +    case NCSCC_RC_REQ_TIMOUT:
> >>> +        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> +        goto done;
> >>> +    default:
> >>> +        rc = SA_AIS_ERR_BAD_HANDLE;
> >>> +        goto done;
> >>> +    }
> >>> +
> >>> +    osafassert(o_msg != NULL);
> >>> +    /* Check response msg: type, rc */
> >>> +    if (o_msg->info.api_resp_info.type != NTFSV_INITIALIZE_RSP) {
> >>> +        TRACE("info.api_resp_info.type:%u",
> >>> o_msg->info.api_resp_info.type);
> >>> +        rc = SA_AIS_ERR_LIBRARY;
> >>> +        goto done;
> >>> +    }
> >>> +    if ((rc = o_msg->info.api_resp_info.rc) != SA_AIS_OK) {
> >>> +        TRACE("info.api_resp_info.rc:%u",
> >>> o_msg->info.api_resp_info.rc);
> >>> +        rc = SA_AIS_ERR_BAD_HANDLE;
> >>> +        goto done;
> >>> +    }
> >>> +
> >>> +    client_hdl->ntfs_client_id =
> >>> o_msg->info.api_resp_info.param.init_rsp.client_id;
> >>> +    TRACE("Successfully recover client_id, new client_id:%u",
> >>> +            client_hdl->ntfs_client_id);
> >>> +
> >>> +done:
> >>> +    if (o_msg)
> >>> +        ntfa_msg_destroy(o_msg);
> >>> +    TRACE_LEAVE();
> >>> +    return rc;
> >>> +}
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : recoverReader
> >>> +
> >>> +  Description   : This routine sends read_initialize messages to NTF
> >>> Server in
> >>> +          order to reintroduce this reader to NTF Server
> >>> +
> >>> +  Arguments     : client_hdl* [IN]: client handle
> >>> +          reader_hdl* [IN]: reader handle
> >>> +
> >>> +  Return Values : SA_AIS_OK if success, others are failure
> >>> +
> >>> +  Notes         : None
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +SaAisErrorT recoverReader(ntfa_client_hdl_rec_t* client_hdl,
> >>> ntfa_reader_hdl_rec_t* reader_hdl) {
> >>> +    uint32_t mds_rc;
> >>> +    SaAisErrorT rc = SA_AIS_OK;
> >>> +    ntfsv_msg_t i_msg, *o_msg = NULL;
> >>> +    ntfsv_reader_init_req_2_t *send_param;
> >>> +
> >>> +    TRACE_ENTER();
> >>> +
> >>> +    /* Make sure the filters have not been deleted */
> >>> +    if (reader_hdl->filters.alarm_filter == NULL &&
> >>> +        reader_hdl->filters.att_ch_filter == NULL &&
> >>> +        reader_hdl->filters.obj_cr_del_filter == NULL &&
> >>> +        reader_hdl->filters.sec_al_filter == NULL &&
> >>> +        reader_hdl->filters.sta_ch_filter == NULL)
> >>> +        return SA_AIS_ERR_BAD_HANDLE;
> >>> +
> >>> +    memset(&i_msg, 0, sizeof(ntfsv_msg_t));
> >>> +    i_msg.type = NTFSV_NTFA_API_MSG;
> >>> +    i_msg.info.api_info.type = NTFSV_READER_INITIALIZE_REQ_2;
> >>> +    send_param = &i_msg.info.api_info.param.reader_init_2;
> >>> +    send_param->head.client_id = client_hdl->ntfs_client_id;
> >>> +    send_param->head.searchCriteria = reader_hdl->searchCriteria;
> >>> +    send_param->f_rec = reader_hdl->filters;
> >>> +
> >>> +    mds_rc = ntfa_mds_msg_sync_send(&ntfa_cb, &i_msg, &o_msg,
> >>> NTFS_WAIT_TIME);
> >>> +
> >>> +    switch (mds_rc) {
> >>> +    case NCSCC_RC_SUCCESS:
> >>> +        break;
> >>> +    case NCSCC_RC_REQ_TIMOUT:
> >>> +        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> +        goto done;
> >>> +    default:
> >>> +        rc = SA_AIS_ERR_BAD_HANDLE;
> >>> +        goto done;
> >>> +    }
> >>> +
> >>> +    osafassert(o_msg != NULL);
> >>> +    if ((rc = o_msg->info.api_resp_info.rc) != SA_AIS_OK) {
> >>> +        TRACE("o_msg->info.api_resp_info.rc:%u",
> >>> o_msg->info.api_resp_info.rc);
> >>> +        rc = SA_AIS_ERR_BAD_HANDLE;
> >>> +        goto done;
> >>> +    }
> >>> +
> >>> +    if (o_msg->info.api_resp_info.type !=
> >>> NTFSV_READER_INITIALIZE_RSP) {
> >>> +        TRACE("msg type (%d) failed",
> >>> (int)o_msg->info.api_resp_info.type);
> >>> +        rc = SA_AIS_ERR_LIBRARY;
> >>> +        goto done;
> >>> +    }
> >>> +    /* Update reader_id since it may be changed */
> >>> +    reader_hdl->reader_id =
> >>> o_msg->info.api_resp_info.param.reader_init_rsp.readerId;
> >>> +
> >>> +    TRACE("Recover reader successfully");
> >>> +done:
> >>> +    if (o_msg)
> >>> +        ntfa_msg_destroy(o_msg);
> >>> +    TRACE_LEAVE();
> >>> +    return rc;
> >>> +}
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : recoverSubscriber
> >>> +
> >>> +  Description   : This routine sends subscribe messages to NTF
> >>> Server in
> >>> +          order to reintroduce this subscriber to NTF Server
> >>> +
> >>> +  Arguments     : client_hdl* [IN]: client handle
> >>> +          subscriber_hdl* [IN]: subscriber handle
> >>> +
> >>> +  Return Values : SA_AIS_OK if success, others are failure
> >>> +
> >>> +  Notes         : None
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +SaAisErrorT recoverSubscriber(ntfa_client_hdl_rec_t* client_hdl,
> >>> +                                    ntfa_subscriber_list_t*
> >>> subscriber_hdl) {
> >>> +    uint32_t mds_rc;
> >>> +    SaAisErrorT rc = SA_AIS_OK;
> >>> +    ntfsv_msg_t i_msg, *o_msg = NULL;
> >>> +    ntfsv_subscribe_req_t *send_param;
> >>> +
> >>> +    TRACE_ENTER();
> >>> +
> >>> +    /* Make sure the filters have not been deleted */
> >>> +    if (subscriber_hdl->filters.alarm_filter == NULL &&
> >>> +        subscriber_hdl->filters.att_ch_filter == NULL &&
> >>> +        subscriber_hdl->filters.obj_cr_del_filter == NULL &&
> >>> +        subscriber_hdl->filters.sec_al_filter == NULL &&
> >>> +        subscriber_hdl->filters.sta_ch_filter == NULL)
> >>> +        return SA_AIS_ERR_BAD_HANDLE;
> >>> +
> >>> +    memset(&i_msg, 0, sizeof(ntfsv_msg_t));
> >>> +    i_msg.type = NTFSV_NTFA_API_MSG;
> >>> +    i_msg.info.api_info.type = NTFSV_SUBSCRIBE_REQ;
> >>> +    send_param = &i_msg.info.api_info.param.subscribe;
> >>> +
> >>> +    send_param->client_id = client_hdl->ntfs_client_id;
> >>> +    send_param->subscriptionId =
> >>> subscriber_hdl->subscriberListSubscriptionId;
> >>> +    send_param->f_rec = subscriber_hdl->filters;
> >>> +
> >>> +    mds_rc = ntfa_mds_msg_sync_send(&ntfa_cb, &i_msg, &o_msg,
> >>> NTFS_WAIT_TIME);
> >>> +
> >>> +    switch (mds_rc) {
> >>> +    case NCSCC_RC_SUCCESS:
> >>> +        break;
> >>> +    case NCSCC_RC_REQ_TIMOUT:
> >>> +        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> +        goto done;
> >>> +    default:
> >>> +        rc = SA_AIS_ERR_BAD_HANDLE;
> >>> +        goto done;
> >>> +    }
> >>> +
> >>> +    osafassert(o_msg != NULL);
> >>> +
> >>> +    if ((rc = o_msg->info.api_resp_info.rc) != SA_AIS_OK) {
> >>> +        TRACE("o_msg->info.api_resp_info.rc:%u",
> >>> o_msg->info.api_resp_info.rc);
> >>> +        rc = SA_AIS_ERR_BAD_HANDLE;
> >>> +        goto done;
> >>> +    }
> >>> +
> >>> +    if (o_msg->info.api_resp_info.type != NTFSV_SUBSCRIBE_RSP) {
> >>> +        TRACE("msg type (%d) failed",
> >>> (int)o_msg->info.api_resp_info.type);
> >>> +        rc = SA_AIS_ERR_LIBRARY;
> >>> +        goto done;
> >>> +    }
> >>> +    TRACE("Recover subscriber successfully");
> >>> +done:
> >>> +    if (o_msg)
> >>> +        ntfa_msg_destroy(o_msg);
> >>> +
> >>> +    TRACE_LEAVE();
> >>> +    return rc;
> >>> +}
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : recoverClient
> >>> +
> >>> +  Description   : In NTF-A.03.01, section 2.1.2. A client can be
> >>> producer,
> >>> +          subscriber, and reader at the same time.
> >>> +          This routine will recovery:
> >>> +          (1) client_id
> >>> +          (2) Then it will continue the recovery if this client also
> >>> +          has instance of subscriber or reader.
> >>> +  Arguments     : client_hdl* [IN]: client handle
> >>> +
> >>> +  Return Values : SA_AIS_OK if success, others are failure
> >>> +
> >>> +  Notes         : None
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +SaAisErrorT recoverClient(ntfa_client_hdl_rec_t *client_hdl) {
> >>> +
> >>> +    TRACE_ENTER();
> >>> +    SaAisErrorT rc = SA_AIS_OK;
> >>> +
> >>> +    osafassert(client_hdl);
> >>> +
> >>> +    if ((rc = reinitializeClient(client_hdl)) == SA_AIS_OK) {
> >>> +        /* Restore reader */
> >>> +        ntfa_reader_hdl_rec_t* reader_hdl = client_hdl->reader_list;
> >>> +        while (reader_hdl != NULL && rc == SA_AIS_OK) {
> >>> +            rc = recoverReader(client_hdl, reader_hdl);
> >>> +            reader_hdl = reader_hdl->next;
> >>> +        }
> >>> +        if (rc != SA_AIS_OK) {
> >>> +            TRACE("Failed to restore reader (readerId:%d)",
> >>> +                    reader_hdl->reader_id);
> >>> +            goto done;
> >>> +        }
> >>> +        /* Restore subscriber */
> >>> +        ntfa_subscriber_list_t* subscriber_hdl = subscriberNoList;
> >>> +        while (subscriber_hdl != NULL && rc == SA_AIS_OK) {
> >>> +            if (client_hdl->local_hdl ==
> >>> subscriber_hdl->subscriberListNtfHandle)
> >>> +                rc = recoverSubscriber(client_hdl, subscriber_hdl);
> >>> +            subscriber_hdl = subscriber_hdl->next;
> >>> +        }
> >>> +        if (rc != SA_AIS_OK) {
> >>> +            TRACE("Failed to restore subscriber (subscriptionId:%d)",
> >>> + subscriber_hdl->subscriberListSubscriptionId);
> >>> +            goto done;
> >>> +        }
> >>> +        client_hdl->valid = true;
> >>> +    } else {
> >>> +        TRACE("Failed to restore client (id:%d)",
> >>> client_hdl->ntfs_client_id);
> >>> +        goto done;
> >>> +    }
> >>> +
> >>> +done:
> >>> +    TRACE_LEAVE();
> >>> +    return rc;
> >>> +}
> >>>
> /**********************************************************
> *****************
> >>>
> >>>    * 8.4.1
> >>>    *
> >>> @@ -923,15 +1213,14 @@ SaAisErrorT saNtfInitialize(SaNtfHandleT
> >>>           version->releaseCode = NTF_RELEASE_CODE;
> >>>           version->majorVersion = NTF_MAJOR_VERSION;
> >>>           version->minorVersion = NTF_MINOR_VERSION;
> >>> -        ntfa_shutdown();
> >>> +        ntfa_shutdown(false);
> >>>           rc = SA_AIS_ERR_VERSION;
> >>>           goto done;
> >>>       }
> >>>
> >>> -    if (!ntfa_cb.ntfs_up) {
> >>> -        ntfa_shutdown();
> >>> -        TRACE("NTFS server is down");
> >>> -        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> +    /* Check NTF server availability */
> >>> +    if ((rc = checkNtfServerState()) != SA_AIS_OK) {
> >>> +        ntfa_shutdown(false);
> >>>           goto done;
> >>>       }
> >>>
> >>> @@ -977,7 +1266,7 @@ SaAisErrorT saNtfInitialize(SaNtfHandleT
> >>>           rc = SA_AIS_ERR_NO_MEMORY;
> >>>           goto err;
> >>>       }
> >>> -
> >>> +    ntfa_hdl_rec->version = *version;
> >>>       /* pass the handle value to the appl */
> >>>       if (SA_AIS_OK == rc)
> >>>           *ntfHandle = ntfa_hdl_rec->local_hdl;
> >>> @@ -990,7 +1279,7 @@ SaAisErrorT saNtfInitialize(SaNtfHandleT
> >>>
> >>>       if (rc != SA_AIS_OK) {
> >>>           TRACE_2("NTFA INIT FAILED\n");
> >>> -        ntfa_shutdown();
> >>> +        ntfa_shutdown(false);
> >>>       }
> >>>
> >>>    done:
> >>> @@ -1101,6 +1390,28 @@ SaAisErrorT saNtfDispatch(SaNtfHandleT n
> >>>           goto done;
> >>>       }
> >>>
> >>> +    /* Need to check NTF server availability here
> >>> +     * Because if the notificationCallback just comes after MDS_DOWN
> >>> +     * it will go to recovery then result in failure due to no director
> >>> +     */
> >>> +    if ((rc = checkNtfServerState()) != SA_AIS_OK) {
> >>> +        ncshm_give_hdl(ntfHandle);
> >>> +        goto done;
> >>> +    }
> >>> +
> >>> +    if (!hdl_rec->valid) {
> >>> +        /* recovery */
> >>> +        if ((rc = recoverClient(hdl_rec)) != SA_AIS_OK) {
> >>> +            if (rc == SA_AIS_ERR_BAD_HANDLE) {
> >>> +                ncshm_give_hdl(ntfHandle);
> >>> + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0);
> >>> + ntfa_hdl_rec_force_del(&ntfa_cb.client_list, hdl_rec);
> >>> + osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
> >>> +                ntfa_shutdown(false);
> >>> +                goto done;
> >>> +            }
> >>> +        }
> >>> +    }
> >>>       if ((rc = ntfa_hdl_cbk_dispatch(&ntfa_cb, hdl_rec,
> >>> dispatchFlags)) != SA_AIS_OK)
> >>>           TRACE("NTFA_DISPATCH_FAILURE");
> >>>
> >>> @@ -1145,6 +1456,13 @@ SaAisErrorT saNtfFinalize(SaNtfHandleT n
> >>>
> >>>       TRACE_ENTER();
> >>>
> >>> +    /* Check NTF server availability */
> >>> +    if (ntfa_cb.ntfa_ntfsv_state == NTFA_NTFSV_NO_ACTIVE) {
> >>> +        TRACE("NTFS server is temporarily unavailable");
> >>> +        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> +        goto done;
> >>> +    }
> >>> +
> >>>       /* retrieve hdl rec */
> >>>       hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_NTFA, ntfHandle);
> >>>       if (hdl_rec == NULL) {
> >>> @@ -1152,43 +1470,37 @@ SaAisErrorT saNtfFinalize(SaNtfHandleT n
> >>>           rc = SA_AIS_ERR_BAD_HANDLE;
> >>>           goto done;
> >>>       }
> >>> -
> >>> -    /* Check Whether NTFS is up or not */
> >>> -    if (!ntfa_cb.ntfs_up) {
> >>> -        TRACE("NTFS down");
> >>> -        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> -        goto done_give_hdl;
> >>> +    if (hdl_rec->valid) {
> >>> +        /** populate & send the finalize message
> >>> +         ** and make sure the finalize from the server
> >>> +         ** end returned before deleting the local records.
> >>> +         **/
> >>> +        memset(&msg, 0, sizeof(ntfsv_msg_t));
> >>> +        msg.type = NTFSV_NTFA_API_MSG;
> >>> +        msg.info.api_info.type = NTFSV_FINALIZE_REQ;
> >>> +        msg.info.api_info.param.finalize.client_id =
> >>> hdl_rec->ntfs_client_id;
> >>> +
> >>> +        mds_rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg,
> >>> NTFS_WAIT_TIME);
> >>> +        switch (mds_rc) {
> >>> +        case NCSCC_RC_SUCCESS:
> >>> +            break;
> >>> +        case NCSCC_RC_REQ_TIMOUT:
> >>> +            rc = SA_AIS_ERR_TIMEOUT;
> >>> +            TRACE("ntfa_mds_msg_sync_send FAILED: %u", rc);
> >>> +            goto done_give_hdl;
> >>> +        default:
> >>> +            TRACE("ntfa_mds_msg_sync_send FAILED: %u", rc);
> >>> +            rc = SA_AIS_ERR_NO_RESOURCES;
> >>> +            goto done_give_hdl;
> >>> +        }
> >>> +
> >>> +        if (o_msg != NULL) {
> >>> +            rc = o_msg->info.api_resp_info.rc;
> >>> +            ntfa_msg_destroy(o_msg);
> >>> +        } else
> >>> +            rc = SA_AIS_ERR_NO_RESOURCES;
> >>>       }
> >>>
> >>> -    /** populate & send the finalize message
> >>> -     ** and make sure the finalize from the server
> >>> -     ** end returned before deleting the local records.
> >>> -     **/
> >>> -    memset(&msg, 0, sizeof(ntfsv_msg_t));
> >>> -    msg.type = NTFSV_NTFA_API_MSG;
> >>> -    msg.info.api_info.type = NTFSV_FINALIZE_REQ;
> >>> -    msg.info.api_info.param.finalize.client_id =
> >>> hdl_rec->ntfs_client_id;
> >>> -
> >>> -    mds_rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg,
> >>> NTFS_WAIT_TIME);
> >>> -    switch (mds_rc) {
> >>> -    case NCSCC_RC_SUCCESS:
> >>> -        break;
> >>> -    case NCSCC_RC_REQ_TIMOUT:
> >>> -        rc = SA_AIS_ERR_TIMEOUT;
> >>> -        TRACE("ntfa_mds_msg_sync_send FAILED: %u", rc);
> >>> -        goto done_give_hdl;
> >>> -    default:
> >>> -        TRACE("ntfa_mds_msg_sync_send FAILED: %u", rc);
> >>> -        rc = SA_AIS_ERR_NO_RESOURCES;
> >>> -        goto done_give_hdl;
> >>> -    }
> >>> -
> >>> -    if (o_msg != NULL) {
> >>> -        rc = o_msg->info.api_resp_info.rc;
> >>> -        ntfa_msg_destroy(o_msg);
> >>> -    } else
> >>> -        rc = SA_AIS_ERR_NO_RESOURCES;
> >>> -
> >>>       if (rc == SA_AIS_OK) {
> >>>       /** delete the hdl rec
> >>>            ** including all resources allocated by client if MDS send is
> >>> @@ -1205,7 +1517,7 @@ SaAisErrorT saNtfFinalize(SaNtfHandleT n
> >>>       ncshm_give_hdl(ntfHandle);
> >>>
> >>>       if (rc == SA_AIS_OK) {
> >>> -        rc = ntfa_shutdown();
> >>> +        rc = ntfa_shutdown(false);
> >>>           if (rc != NCSCC_RC_SUCCESS)
> >>>               TRACE_1("ntfa_shutdown failed");
> >>>       }
> >>> @@ -1349,7 +1661,7 @@ SaAisErrorT saNtfNotificationFree(SaNtfN
> >>>       }
> >>>
> >>>       /* free the resources allocated by
> >>> saNtf<ntfType>NotificationAllocate */
> >>> -    ntfa_hdl_rec_destructor(notification_hdl_rec);
> >>> +    ntfa_notification_destructor(notification_hdl_rec);
> >>>
> >>>       /** Delete the resources related to the notificationHandle &
> >>>        *  remove reference in the client.
> >>> @@ -1419,6 +1731,24 @@ SaAisErrorT saNtfNotificationSend(SaNtfN
> >>>       }
> >>>       osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
> >>>
> >>> +    /* Check NTF server availability */
> >>> +    if ((rc = checkNtfServerState()) != SA_AIS_OK)
> >>> +        goto done_give_hdls;
> >>> +
> >>> +    /* Recover if this is invalid handle */
> >>> +    if (!client_rec->valid) {
> >>> +        if ((rc = recoverClient(client_rec)) != SA_AIS_OK) {
> >>> +            ncshm_give_hdl(client_handle);
> >>> +            ncshm_give_hdl(notificationHandle);
> >>> +            if (rc == SA_AIS_ERR_BAD_HANDLE) {
> >>> + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0);
> >>> + ntfa_hdl_rec_force_del(&ntfa_cb.client_list, client_rec);
> >>> + osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
> >>> +                ntfa_shutdown(false);
> >>> +            }
> >>> +            goto err_free;
> >>> +        }
> >>> +    }
> >>>       /**
> >>>        ** Populate a sync MDS message
> >>>        **/
> >>> @@ -1481,13 +1811,6 @@ SaAisErrorT saNtfNotificationSend(SaNtfN
> >>>           goto done_give_hdls;
> >>>       }
> >>>
> >>> -    /* Check whether NTFS is up or not */
> >>> -    if (!ntfa_cb.ntfs_up) {
> >>> -        TRACE("NTFS down");
> >>> -        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> -        goto done_give_hdls;
> >>> -    }
> >>> -
> >>>       /* Send a sync MDS message to obtain a notification id */
> >>>       mds_rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg,
> timeout);
> >>>       switch (mds_rc) {
> >>> @@ -1596,7 +1919,8 @@ static  SaNtfHandleT ntfHandleGet(SaNtfS
> >>>       return ntfHandle;
> >>>   }
> >>>
> >>> -static SaAisErrorT subscriptionListAdd(SaNtfHandleT ntfHandle,
> >>> SaNtfSubscriptionIdT subscriptionId)
> >>> +static SaAisErrorT subscriptionListAdd(SaNtfHandleT ntfHandle,
> >>> SaNtfSubscriptionIdT subscriptionId,
> >>> +                                        ntfsv_filter_ptrs_t filters)
> >>>   {
> >>>       SaAisErrorT rc = SA_AIS_OK;
> >>>       ntfa_subscriber_list_t* ntfSubscriberList;
> >>> @@ -1610,7 +1934,9 @@ static SaAisErrorT subscriptionListAdd(S
> >>>       /* Add ntfHandle and subscriptionId into list */
> >>>       ntfSubscriberList->subscriberListNtfHandle = ntfHandle;
> >>>       ntfSubscriberList->subscriberListSubscriptionId = subscriptionId;
> >>> -
> >>> +    memset(&ntfSubscriberList->filters, 0,
> >>> sizeof(ntfsv_filter_ptrs_t));
> >>> + ntfa_copy_ntf_filter_ptrs(&ntfSubscriberList->filters, &filters);
> >>> +
> >>>       osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0);
> >>>       if (NULL == subscriberNoList) {
> >>>           subscriberNoList = ntfSubscriberList;
> >>> @@ -1648,6 +1974,7 @@ static void subscriberListItemRemove(SaN
> >>>               subscriberNoList = NULL;
> >>>       }
> >>>       TRACE_1("REMOVE: listPtr->SubscriptionId %d",
> >>> listPtr->subscriberListSubscriptionId);
> >>> +    ntfa_del_ntf_filter_ptrs(&listPtr->filters);
> >>>       free(listPtr);
> >>>       osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
> >>>   }
> >>> @@ -1666,20 +1993,33 @@ SaAisErrorT saNtfNotificationSubscribe(c
> >>>       ntfsv_msg_t msg, *o_msg = NULL;
> >>>       ntfsv_subscribe_req_t *send_param;
> >>>       uint32_t timeout = NTFS_WAIT_TIME;
> >>> -
> >>> +    bool recovery_failed = false;
> >>>       TRACE_ENTER();
> >>> +
> >>>       rc = getFilters(notificationFilterHandles, &filters,
> >>> &ntfHandle, &client_hdl_rec);
> >>>       if (rc != SA_AIS_OK) {
> >>>           TRACE("getFilters failed");
> >>>           goto done;
> >>>       }
> >>>
> >>> +    /* Check NTF server availability */
> >>> +    if ((rc = checkNtfServerState()) != SA_AIS_OK)
> >>> +        goto done;
> >>> +
> >>> +    /* recovery */
> >>> +    if (client_hdl_rec != NULL && !client_hdl_rec->valid) {
> >>> +        if ((rc = recoverClient(client_hdl_rec)) != SA_AIS_OK) {
> >>> +            recovery_failed = true;
> >>> +            goto done;
> >>> +        }
> >>> +    }
> >>> +
> >>>       tmpHandle = ntfHandleGet(subscriptionId);
> >>>       if (tmpHandle != 0) {
> >>>           rc = SA_AIS_ERR_EXIST;
> >>>           goto done;
> >>>       }
> >>> -    rc = subscriptionListAdd(ntfHandle, subscriptionId);
> >>> +    rc = subscriptionListAdd(ntfHandle, subscriptionId, filters);
> >>>       if (rc != SA_AIS_OK) {
> >>>           goto done;
> >>>       }
> >>> @@ -1693,29 +2033,24 @@ SaAisErrorT saNtfNotificationSubscribe(c
> >>>       send_param->client_id = client_hdl_rec->ntfs_client_id;
> >>>       send_param->subscriptionId = subscriptionId;
> >>>       send_param->f_rec = filters;
> >>> -    /* Check whether NTFS is up or not */
> >>> -    if (ntfa_cb.ntfs_up) {
> >>> -        uint32_t rv;
> >>> -        /* Send a sync MDS message to obtain a log stream id */
> >>> -        rv = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg,
> timeout);
> >>> -        if (rv == NCSCC_RC_SUCCESS) {
> >>> -            osafassert(o_msg != NULL);
> >>> -            if (SA_AIS_OK == o_msg->info.api_resp_info.rc) {
> >>> -                TRACE_1("subscriptionId from server %u",
> >>> - o_msg->info.api_resp_info.param.subscribe_rsp.subscriptionId);
> >>> -            } else {
> >>> -                rc = o_msg->info.api_resp_info.rc;
> >>> -                TRACE("Bad return status!!! rc = %d", rc);
> >>> -            }
> >>> +
> >>> +    uint32_t rv;
> >>> +    /* Send a sync MDS message to obtain a log stream id */
> >>> +    rv = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg, timeout);
> >>> +    if (rv == NCSCC_RC_SUCCESS) {
> >>> +        osafassert(o_msg != NULL);
> >>> +        if (SA_AIS_OK == o_msg->info.api_resp_info.rc) {
> >>> +            TRACE_1("subscriptionId from server %u",
> >>> + o_msg->info.api_resp_info.param.subscribe_rsp.subscriptionId);
> >>>           } else {
> >>> -            if(rv == NCSCC_RC_INVALID_INPUT)
> >>> -                rc = SA_AIS_ERR_INVALID_PARAM;
> >>> -            else
> >>> -                rc = SA_AIS_ERR_TRY_AGAIN;
> >>> +            rc = o_msg->info.api_resp_info.rc;
> >>> +            TRACE("Bad return status!!! rc = %d", rc);
> >>>           }
> >>>       } else {
> >>> -        TRACE_1("NTFS down");
> >>> -        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> +        if(rv == NCSCC_RC_INVALID_INPUT)
> >>> +            rc = SA_AIS_ERR_INVALID_PARAM;
> >>> +        else
> >>> +            rc = SA_AIS_ERR_TRY_AGAIN;
> >>>       }
> >>>
> >>>       if (rc != SA_AIS_OK) {
> >>> @@ -1724,6 +2059,7 @@ SaAisErrorT saNtfNotificationSubscribe(c
> >>>       if (o_msg)
> >>>           ntfa_msg_destroy(o_msg);
> >>>       done:
> >>> +
> >>>       ncshm_give_hdl(ntfHandle);
> >>>       if (notificationFilterHandles) {
> >>>           if (notificationFilterHandles->attributeChangeFilterHandle)
> >>> @@ -1737,6 +2073,13 @@ SaAisErrorT saNtfNotificationSubscribe(c
> >>>           if (notificationFilterHandles->alarmFilterHandle)
> >>> ncshm_give_hdl(notificationFilterHandles->alarmFilterHandle);
> >>>       }
> >>> +    if (recovery_failed && rc == SA_AIS_ERR_BAD_HANDLE) {
> >>> +        osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0);
> >>> +        ntfa_hdl_rec_force_del(&ntfa_cb.client_list, client_hdl_rec);
> >>> +        osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
> >>> +        ntfa_shutdown(false);
> >>> +    }
> >>> +
> >>>       TRACE_LEAVE();
> >>>       return rc;
> >>>   }
> >>> @@ -1995,6 +2338,7 @@ SaAisErrorT saNtfSecurityAlarmNotificati
> >>>           rc = SA_AIS_ERR_INVALID_PARAM;
> >>>           goto done;
> >>>       }
> >>> +
> >>>       /* retrieve hdl rec */
> >>>       hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_NTFA, ntfHandle);
> >>>       if (hdl_rec == NULL) {
> >>> @@ -2058,6 +2402,7 @@ SaAisErrorT saNtfPtrValAllocate(SaNtfNot
> >>>           rc = SA_AIS_ERR_INVALID_PARAM;
> >>>           goto done;
> >>>       }
> >>> +
> >>>       notification_hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_NTFA,
> >>> notificationHandle);
> >>>       if (notification_hdl_rec == NULL) {
> >>>           TRACE("ncshm_take_hdl notificationHandle failed");
> >>> @@ -2098,6 +2443,7 @@ SaAisErrorT saNtfArrayValAllocate(SaNtfN
> >>>           rc = SA_AIS_ERR_INVALID_PARAM;
> >>>           goto done;
> >>>       }
> >>> +
> >>>       notification_hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_NTFA,
> >>> notificationHandle);
> >>>       if (notification_hdl_rec == NULL) {
> >>>           TRACE("ncshm_take_hdl notificationHandle failed");
> >>> @@ -2228,6 +2574,7 @@ SaAisErrorT saNtfArrayValGet(SaNtfNotifi
> >>>           rc = SA_AIS_ERR_INVALID_PARAM;
> >>>           goto done;
> >>>       }
> >>> +
> >>>       notification_hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_NTFA,
> >>> notificationHandle);
> >>>       if (notification_hdl_rec == NULL) {
> >>>           TRACE("ncshm_take_hdl notificationHandle failed");
> >>> @@ -2695,7 +3042,7 @@ SaAisErrorT saNtfNotificationFilterFree(
> >>>       }
> >>>
> >>>       /* free the resources allocated by saNtf<ntfType>FilterAllocate */
> >>> -    ntfa_filter_hdl_rec_destructor(filter_hdl_rec);
> >>> +    ntfa_filter_destructor(filter_hdl_rec);
> >>>
> >>>       /** Delete the resources related to the notificationFilterHandle &
> >>>        *  remove reference in the client.
> >>> @@ -2729,7 +3076,6 @@ SaAisErrorT saNtfNotificationUnsubscribe
> >>>       TRACE_ENTER();
> >>>       SaAisErrorT rc = SA_AIS_ERR_NOT_EXIST;
> >>>       SaNtfHandleT ntfHandle;
> >>> -
> >>>       ntfa_client_hdl_rec_t *client_hdl_rec;
> >>>
> >>>       ntfsv_msg_t msg, *o_msg = NULL;
> >>> @@ -2737,7 +3083,6 @@ SaAisErrorT saNtfNotificationUnsubscribe
> >>>       ntfsv_unsubscribe_req_t *send_param;
> >>>       uint32_t timeout = NTFS_WAIT_TIME;
> >>>
> >>> -
> >>>       ntfHandle = ntfHandleGet(subscriptionId);
> >>>       if (ntfHandle == 0) {
> >>>           TRACE_1("ntfHandleGet failed, subscription not exist");
> >>> @@ -2753,9 +3098,16 @@ SaAisErrorT saNtfNotificationUnsubscribe
> >>>           goto done;
> >>>       }
> >>>
> >>> -    /**
> >>> -         ** Populate a sync MDS message
> >>> -         **/
> >>> +    /* Check NTF server availability */
> >>> +    if ((rc = checkNtfServerState()) != SA_AIS_OK) {
> >> [Praveen] Here in both unavailability and down case, API will return
> >> without clean up of subscriber information. But README in patch 3 tals
> >> differently for the two cases.
> >> I think handling like saNtfFinalize() way needs to be done here.
> > [Minh]: I will have to check the history commit, to see if any reason
> > that agent doesn't silently release subscriber's resource here as
> > described in README. But it looks to me a bug, can I get back to you later?
> [Praveen] This needs to be corrected otherwise the same application will
> not be able to reuse old subscription_id. It will get ERR_EXIST.
> >>
> >>> +        ncshm_give_hdl(ntfHandle);
> >>> +        goto done;
> >>> +    }
> >>> +
> >>> +    if (client_hdl_rec->valid) {
> >>> +        /**
> >>> +          ** Populate a sync MDS message
> >>> +         **/
> >>>           memset(&msg, 0, sizeof(ntfsv_msg_t));
> >>>           msg.type = NTFSV_NTFA_API_MSG;
> >>>           msg.info.api_info.type = NTFSV_UNSUBSCRIBE_REQ;
> >>> @@ -2764,13 +3116,6 @@ SaAisErrorT saNtfNotificationUnsubscribe
> >>>           send_param->client_id = client_hdl_rec->ntfs_client_id;
> >>>           send_param->subscriptionId = subscriptionId;
> >>>
> >>> -        /* Check whether NTFS is up or not */
> >>> -        if (!ntfa_cb.ntfs_up) {
> >>> -            TRACE_1("NTFS down");
> >>> -            rc = SA_AIS_ERR_TRY_AGAIN;
> >>> -            goto done_give_hdl;
> >>> -        }
> >>> -
> >>>           /* Send a sync MDS message to obtain a log stream id */
> >>>           rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg,
> timeout);
> >>>           if (rc != NCSCC_RC_SUCCESS) {
> >>> @@ -2785,6 +3130,7 @@ SaAisErrorT saNtfNotificationUnsubscribe
> >>>               TRACE_1("Bad return status! rc = %d", rc);
> >>>               goto done_give_hdl;
> >>>           }
> >>> +    }
> >>>           subscriberListItemRemove(subscriptionId);
> >>>
> >>>           /*Remove msg for subscriptionId from mailbox*/
> >>> @@ -2815,6 +3161,19 @@ SaAisErrorT saNtfNotificationUnsubscribe
> >>>    done_give_hdl:
> >>>       if (o_msg)
> >>>            ntfa_msg_destroy(o_msg);
> >>> +
> >>> +    if (!client_hdl_rec->valid) {
> >>> +        if ((rc = recoverClient(client_hdl_rec)) != SA_AIS_OK) {
> >>> +            if (rc == SA_AIS_ERR_BAD_HANDLE) {
> >>> +                ncshm_give_hdl(ntfHandle);
> >>> + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0);
> >>> + ntfa_hdl_rec_force_del(&ntfa_cb.client_list, client_hdl_rec);
> >>> + osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
> >>> +                ntfa_shutdown(false);
> >>> +                goto done;
> >>> +            }
> >>> +        }
> >>> +    }
> >>>       ncshm_give_hdl(ntfHandle);
> >>>    done:
> >>>       TRACE_LEAVE();
> >>> @@ -2838,6 +3197,7 @@ SaAisErrorT saNtfNotificationReadInitial
> >>>       ntfsv_reader_init_req_2_t *send_param;
> >>>       uint32_t timeout = NTFS_WAIT_TIME;
> >>>
> >>> +    bool recovery_failed = false;
> >>>       TRACE_ENTER();
> >>>       if (notificationFilterHandles == NULL || readHandle == NULL) {
> >>>           rc = SA_AIS_ERR_INVALID_PARAM;
> >>> @@ -2872,6 +3232,18 @@ SaAisErrorT saNtfNotificationReadInitial
> >>>           goto done_give_client_hdl;
> >>>       }
> >>>
> >>> +    /* Check NTF server availability */
> >>> +    if ((rc = checkNtfServerState()) != SA_AIS_OK)
> >>> +        goto done_give_client_hdl;
> >>> +
> >>> +    /* recovery */
> >>> +    if (client_hdl_rec != NULL && !client_hdl_rec->valid) {
> >>> +        if ((rc = recoverClient(client_hdl_rec)) != SA_AIS_OK) {
> >>> +            recovery_failed = true;
> >>> +            goto done_give_client_hdl;
> >>> +        }
> >>> +    }
> >>> +
> >>>       /**
> >>>        ** Populate a sync MDS message
> >>>        **/
> >>> @@ -2884,13 +3256,6 @@ SaAisErrorT saNtfNotificationReadInitial
> >>>       send_param->head.searchCriteria = searchCriteria;
> >>>       send_param->f_rec = filters;
> >>>
> >>> -    /* Check whether NTFS is up or not */
> >>> -    if (!ntfa_cb.ntfs_up) {
> >>> -        TRACE("NTFS down");
> >>> -        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> -        goto done_give_client_hdl;
> >>> -    }
> >>> -
> >>>       /* Send a sync MDS message to obtain a log stream id */
> >>>       rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg, timeout);
> >>>       if (rc != NCSCC_RC_SUCCESS) {
> >>> @@ -2925,12 +3290,16 @@ SaAisErrorT saNtfNotificationReadInitial
> >>>       reader_hdl_rec->ntfHandle = ntfHandle;
> >>>       /* Store the readerId returned from server */
> >>>       reader_hdl_rec->reader_id =
> >>> o_msg->info.api_resp_info.param.reader_init_rsp.readerId;
> >>> +    memset(&reader_hdl_rec->filters, 0, sizeof(ntfsv_filter_ptrs_t));
> >>> +    ntfa_copy_ntf_filter_ptrs(&reader_hdl_rec->filters, &filters);
> >>> +    reader_hdl_rec->searchCriteria = searchCriteria;
> >>>       /**                  UnLock ntfa_CB            **/
> >>>       osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
> >>>
> >>>   done_give_client_hdl:
> >>>       if (o_msg)
> >>>           ntfa_msg_destroy(o_msg);
> >>> +
> >>>      if (client_hdl_rec)
> >>>           ncshm_give_hdl(client_hdl_rec->local_hdl);
> >>>       if (notificationFilterHandles) {
> >>> @@ -2947,6 +3316,12 @@ done_give_client_hdl:
> >>>       }
> >>>
> >>> ncshm_give_hdl(notificationFilterHandles->alarmFilterHandle);
> >>> +    if (recovery_failed && rc == SA_AIS_ERR_BAD_HANDLE) {
> >>> +        osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0);
> >>> +        ntfa_hdl_rec_force_del(&ntfa_cb.client_list, client_hdl_rec);
> >>> +        osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
> >>> +        ntfa_shutdown(false);
> >>> +    }
> >>>   done:
> >>>       TRACE_LEAVE();
> >>>       return rc;
> >>> @@ -2983,42 +3358,46 @@ SaAisErrorT saNtfNotificationReadFinaliz
> >>>       }
> >>>       TRACE_1("reader_hdl_rec = %u", reader_hdl_rec->reader_hdl);
> >>>
> >>> -    /**
> >>> -     ** Populate a sync MDS message
> >>> -     **/
> >>> -    memset(&msg, 0, sizeof(ntfsv_msg_t));
> >>> -    msg.type = NTFSV_NTFA_API_MSG;
> >>> -    msg.info.api_info.type = NTFSV_READER_FINALIZE_REQ;
> >>> -    send_param = &msg.info.api_info.param.reader_finalize;
> >>> -    send_param->client_id = client_hdl_rec->ntfs_client_id;
> >>> -    send_param->readerId = reader_hdl_rec->reader_id;
> >>> -
> >>> -    /* Check whether NTFS is up or not */
> >>> -    if (!ntfa_cb.ntfs_up) {
> >>> -        TRACE("NTFS down");
> >>> -        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> -        goto done_give_hdls;
> >>> +    /* Check NTF server availability */
> >>> +    if ((rc = checkNtfServerState()) != SA_AIS_OK) {
> >> [Praveen] Same comment here as in Unsubscribe().
> >> [Minh] As above in Unsubscribed()
> 
> >>> + ncshm_give_hdl(client_hdl_rec->local_hdl);
> >>> +        ncshm_give_hdl(readhandle);
> >>> +        goto done;
> >>>       }
> >>>
> >>> -    /* Send a sync MDS message */
> >>> -    rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg, timeout);
> >>> -    if (rc != NCSCC_RC_SUCCESS) {
> >>> -        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> -        goto done_give_hdls;
> >>> +    if (client_hdl_rec->valid) {
> >>> +        /**
> >>> +         ** Populate a sync MDS message
> >>> +         **/
> >>> +        memset(&msg, 0, sizeof(ntfsv_msg_t));
> >>> +        msg.type = NTFSV_NTFA_API_MSG;
> >>> +        msg.info.api_info.type = NTFSV_READER_FINALIZE_REQ;
> >>> +        send_param = &msg.info.api_info.param.reader_finalize;
> >>> +        send_param->client_id = client_hdl_rec->ntfs_client_id;
> >>> +        send_param->readerId = reader_hdl_rec->reader_id;
> >>> +
> >>> +
> >>> +        /* Send a sync MDS message */
> >>> +        rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg,
> timeout);
> >>> +        if (rc != NCSCC_RC_SUCCESS) {
> >>> +            rc = SA_AIS_ERR_TRY_AGAIN;
> >>> +            goto done_give_hdls;
> >>> +        }
> >>> +
> >>> +        osafassert(o_msg != NULL);
> >>> +        if (SA_AIS_OK != o_msg->info.api_resp_info.rc) {
> >>> +            rc = o_msg->info.api_resp_info.rc;
> >>> +            TRACE("Bad return status!!! rc = %d", rc);
> >>> +            goto done_give_hdls;
> >>> +        }
> >>> +
> >>> +        if (o_msg->info.api_resp_info.type !=
> >>> NTFSV_READER_FINALIZE_RSP) {
> >>> +            TRACE("msg type (%d) failed",
> >>> (int)o_msg->info.api_resp_info.type);
> >>> +            rc = SA_AIS_ERR_LIBRARY;
> >>> +            goto done_give_hdls;
> >>> +        }
> >>>       }
> >>>
> >>> -    osafassert(o_msg != NULL);
> >>> -    if (SA_AIS_OK != o_msg->info.api_resp_info.rc) {
> >>> -        rc = o_msg->info.api_resp_info.rc;
> >>> -        TRACE("Bad return status!!! rc = %d", rc);
> >>> -        goto done_give_hdls;
> >>> -    }
> >>> -
> >>> -    if (o_msg->info.api_resp_info.type !=
> NTFSV_READER_FINALIZE_RSP) {
> >>> -        TRACE("msg type (%d) failed",
> >>> (int)o_msg->info.api_resp_info.type);
> >>> -        rc = SA_AIS_ERR_LIBRARY;
> >>> -        goto done_give_hdls;
> >>> -    }
> >>>       osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0);
> >>>       oas_rc = ntfa_reader_hdl_rec_del(&client_hdl_rec->reader_list,
> >>> reader_hdl_rec);
> >>>       if (oas_rc != NCSCC_RC_SUCCESS) {
> >>> @@ -3029,6 +3408,20 @@ SaAisErrorT saNtfNotificationReadFinaliz
> >>>    done_give_hdls:
> >>>       if (o_msg)
> >>>            ntfa_msg_destroy(o_msg);
> >>> +
> >>> +    if (!client_hdl_rec->valid) {
> >>> +        if ((rc = recoverClient(client_hdl_rec)) != SA_AIS_OK) {
> >>> +            if (rc == SA_AIS_ERR_BAD_HANDLE) {
> >>> +                ncshm_give_hdl(client_hdl_rec->local_hdl);
> >>> +                ncshm_give_hdl(readhandle);
> >>> + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0);
> >>> + ntfa_hdl_rec_force_del(&ntfa_cb.client_list, client_hdl_rec);
> >>> + osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
> >>> +                ntfa_shutdown(false);
> >>> +                goto done;
> >>> +            }
> >>> +        }
> >>> +    }
> >>>       ncshm_give_hdl(client_hdl_rec->local_hdl);
> >>>    done_give_read_hdl:
> >>>       ncshm_give_hdl(readhandle);
> >>> @@ -3082,6 +3475,23 @@ SaAisErrorT saNtfNotificationReadNext(Sa
> >>>       }
> >>>       TRACE_1("reader_hdl_rec = %u", reader_hdl_rec->reader_hdl);
> >>>
> >>> +    /* Check NTF server availability */
> >>> +    if ((rc = checkNtfServerState()) != SA_AIS_OK)
> >>> +        goto done_give_hdls;
> >>> +
> >>> +    if (!client_hdl_rec->valid) {
> >>> +        if ((rc = recoverClient(client_hdl_rec)) != SA_AIS_OK) {
> >>> +            ncshm_give_hdl(client_hdl_rec->local_hdl);
> >>> +            ncshm_give_hdl(readHandle);
> >>> +            if (rc == SA_AIS_ERR_BAD_HANDLE) {
> >>> + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0);
> >>> + ntfa_hdl_rec_force_del(&ntfa_cb.client_list, client_hdl_rec);
> >>> + osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
> >>> +                ntfa_shutdown(false);
> >>> +            }
> >>> +            goto done;
> >>> +        }
> >>> +    }
> >>>       /**
> >>>        ** Populate a sync MDS message
> >>>        **/
> >>> @@ -3092,12 +3502,6 @@ SaAisErrorT saNtfNotificationReadNext(Sa
> >>>       send_param->client_id = client_hdl_rec->ntfs_client_id;
> >>>       send_param->readerId = reader_hdl_rec->reader_id;
> >>>       send_param->searchDirection = searchDirection;
> >>> -    /* Check whether NTFS is up or not */
> >>> -    if (!ntfa_cb.ntfs_up) {
> >>> -        TRACE("NTFS down");
> >>> -        rc = SA_AIS_ERR_TRY_AGAIN;
> >>> -        goto done_give_hdls;
> >>> -    }
> >>>
> >>>       do {
> >>>           /* Send a sync MDS message */
> >>> diff --git a/osaf/libs/agents/saf/ntfa/ntfa_mds.c
> >>> b/osaf/libs/agents/saf/ntfa/ntfa_mds.c
> >>> --- a/osaf/libs/agents/saf/ntfa/ntfa_mds.c
> >>> +++ b/osaf/libs/agents/saf/ntfa/ntfa_mds.c
> >>> @@ -369,7 +369,8 @@ static uint32_t ntfa_mds_svc_evt(struct
> >>>               TRACE("NTFS down");
> >>>               pthread_mutex_lock(&ntfa_cb.cb_lock);
> >>>               memset(&ntfa_cb.ntfs_mds_dest, 0, sizeof(MDS_DEST));
> >>> -            ntfa_cb.ntfs_up = 0;
> >>> + ntfa_update_ntfsv_state(mds_cb_info->info.svc_evt.i_change ==
> >>> NCSMDS_NO_ACTIVE ?
> >>> +                    NTFA_NTFSV_NO_ACTIVE : NTFA_NTFSV_DOWN);
> >>>               pthread_mutex_unlock(&ntfa_cb.cb_lock);
> >>>           }
> >>>           break;
> >>> @@ -382,7 +383,8 @@ static uint32_t ntfa_mds_svc_evt(struct
> >>>               TRACE_2("MSG from NTFS NCSMDS_NEW_ACTIVE/UP");
> >>>               pthread_mutex_lock(&ntfa_cb.cb_lock);
> >>>               ntfa_cb.ntfs_mds_dest = mds_cb_info->info.svc_evt.i_dest;
> >>> -            ntfa_cb.ntfs_up = 1;
> >>> + ntfa_update_ntfsv_state(mds_cb_info->info.svc_evt.i_change ==
> >>> NCSMDS_NEW_ACTIVE ?
> >>> +                    NTFA_NTFSV_NEW_ACTIVE : NTFA_NTFSV_UP);
> >>>               if (ntfa_cb.ntfs_sync_awaited) {
> >>>                   /* signal waiting thread */
> >>>                   m_NCS_SEL_OBJ_IND(&ntfa_cb.ntfs_sync_sel);
> >>> diff --git a/osaf/libs/agents/saf/ntfa/ntfa_util.c
> >>> b/osaf/libs/agents/saf/ntfa/ntfa_util.c
> >>> --- a/osaf/libs/agents/saf/ntfa/ntfa_util.c
> >>> +++ b/osaf/libs/agents/saf/ntfa/ntfa_util.c
> >>> @@ -49,7 +49,7 @@ static unsigned int ntfa_create(void)
> >>>       }
> >>>
> >>>       /* Block and wait for indication from MDS meaning NTFS is up */
> >>> -
> osaf_poll_one_fd(m_GET_FD_FROM_SEL_OBJ(ntfa_cb.ntfs_sync_sel),
> 30000);
> >>> +
> osaf_poll_one_fd(m_GET_FD_FROM_SEL_OBJ(ntfa_cb.ntfs_sync_sel),
> 10000);
> >> [Praveen] Did not get why it is changed to 10 seconds.
> >> [Minh] I think 30 seconds is just too long
> >>>
> >>>       pthread_mutex_lock(&ntfa_cb.cb_lock);
> >>>       ntfa_cb.ntfs_sync_awaited = 0;
> >>> @@ -108,7 +108,25 @@ static bool ntfa_clear_mbx(NCSCONTEXT ar
> >>>       }
> >>>       return true;
> >>>   }
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : ntfa_notification_list_del
> >>>
> >>> +  Description   : This routine free element allocated in list of
> >>> notification
> >>> +
> >>> +  Arguments     : pointer to the list of notification records anchor.
> >>> +
> >>> +  Return Values : None
> >>> +
> >>> +  Notes         :
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +static void ntfa_notification_list_del(ntfa_notification_hdl_rec_t
> >>> **plstr_hdl)
> >>> +{
> >>> +    ntfa_notification_hdl_rec_t *lstr_hdl = *plstr_hdl;
> >>> +    while (lstr_hdl != NULL) {
> >>> +        ntfa_notification_destructor(lstr_hdl);
> >>> +        lstr_hdl = lstr_hdl->next;
> >>> +    }
> >>> +}
> >>>
> /**********************************************************
> ******************
> >>>
> >>>     Name          : ntfa_notification_hdl_rec_list_del
> >>>
> >>> @@ -130,6 +148,70 @@ static void ntfa_notification_hdl_rec_li
> >>>           lstr_hdl = NULL;
> >>>       }
> >>>   }
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : ntfa_filter_list_del
> >>> +
> >>> +  Description   : This routine free element allocated in list of filter
> >>> +
> >>> +  Arguments     : pointer to the list of filters records anchor.
> >>> +
> >>> +  Return Values : None
> >>> +
> >>> +  Notes         :
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +static void ntfa_filter_list_del(ntfa_filter_hdl_rec_t **plstr_hdl)
> >>> +{
> >>> +    ntfa_filter_hdl_rec_t *lstr_hdl = *plstr_hdl;
> >>> +
> >>> +    while (lstr_hdl != NULL) {
> >>> +        ntfa_filter_destructor(lstr_hdl);
> >>> +        lstr_hdl = lstr_hdl->next;
> >>> +    }
> >>> +}
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : ntfa_filter_hdl_rec_list_del
> >>> +
> >>> +  Description   : This routine deletes a list of allocated filters
> >>> +
> >>> +  Arguments     : pointer to the list of filters records anchor.
> >>> +
> >>> +  Return Values : None
> >>> +
> >>> +  Notes         :
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +static void ntfa_filter_hdl_rec_list_del(ntfa_filter_hdl_rec_t
> >>> **plstr_hdl)
> >>> +{
> >>> +    ntfa_filter_hdl_rec_t *lstr_hdl;
> >>> +
> >>> +    while ((lstr_hdl = *plstr_hdl) != NULL) {
> >>> +        *plstr_hdl = lstr_hdl->next;
> >>> +        ncshm_destroy_hdl(NCS_SERVICE_ID_NTFA, lstr_hdl->filter_hdl);
> >>> +        free(lstr_hdl);
> >>> +        lstr_hdl = NULL;
> >>> +    }
> >>> +}
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : ntfa_reader_hdl_rec_list_del
> >>> +
> >>> +  Description   : This routine deletes a list of allocated readers
> >>> +
> >>> +  Arguments     : pointer to the list of readers records anchor.
> >>> +
> >>> +  Return Values : None
> >>> +
> >>> +  Notes         :
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +static void ntfa_reader_hdl_rec_list_del(ntfa_reader_hdl_rec_t
> >>> **plstr_hdl)
> >>> +{
> >>> +    ntfa_reader_hdl_rec_t *lstr_hdl;
> >>> +    while ((lstr_hdl = *plstr_hdl) != NULL) {
> >>> +        *plstr_hdl = lstr_hdl->next;
> >>> +        ncshm_destroy_hdl(NCS_SERVICE_ID_NTFA, lstr_hdl-
> >reader_hdl);
> >>> +        ntfa_del_ntf_filter_ptrs(&lstr_hdl->filters);
> >>> +        free(lstr_hdl);
> >>> +        lstr_hdl = NULL;
> >>> +    }
> >>> +}
> >>>
> >>>   static SaAisErrorT
> >>> ntfa_alloc_callback_notification(SaNtfNotificationsT *notification,
> >>>                               ntfsv_send_not_req_t *not_cbk,
> >>> ntfa_client_hdl_rec_t *hdl_rec)
> >>> @@ -407,6 +489,10 @@ static SaAisErrorT ntfa_hdl_cbk_rec_prc(
> >>> free(cbk_info->param.discarded_cbk.discardedNotificationIdentifiers);
> >>>           }
> >>>           break;
> >>> +    case NTFSV_DUMMY_CALLBACK:
> >>> +        TRACE("Do nothing with dummy callback, just return OK");
> >>> +        rc = SA_AIS_OK;
> >>> +        break;
> >>>       default:
> >>>           TRACE("unsupported callback type: %d", cbk_info->type);
> >>>           rc = SA_AIS_ERR_LIBRARY;
> >>> @@ -544,20 +630,21 @@ unsigned int ntfa_startup(void)
> >>>    *
> >>>    * @return unsigned int
> >>>    */
> >>> -unsigned int ntfa_shutdown(void)
> >>> +unsigned int ntfa_shutdown(bool forced)
> >>>   {
> >>>       unsigned int rc = NCSCC_RC_SUCCESS;
> >>>
> >>> -    TRACE_ENTER2("ntfa_use_count: %u", ntfa_use_count);
> >>> +    TRACE_ENTER2("ntfa_use_count: %u, forced: %u", ntfa_use_count,
> >>> forced);
> >>>       pthread_mutex_lock(&ntfa_lock);
> >>>
> >>> -    if (ntfa_use_count > 1) {
> >>> -        /* Users still exist, just decrement the use count */
> >>> -        ntfa_use_count--;
> >>> -    } else if (ntfa_use_count == 1) {
> >>> +    if ((forced && (ntfa_use_count > 0)) || (ntfa_use_count == 1)) {
> >>>           ntfa_destroy();
> >>>           rc = ncs_agents_shutdown();
> >>>           ntfa_use_count = 0;
> >>> +        ntfa_cb.ntfa_ntfsv_state = NTFA_NTFSV_NONE;
> >>> +    } else if (ntfa_use_count > 1) {
> >>> +        /* Users still exist, just decrement the use count */
> >>> +        ntfa_use_count--;
> >>>       }
> >>>
> >>>       pthread_mutex_unlock(&ntfa_lock);
> >>> @@ -633,7 +720,27 @@ ntfa_client_hdl_rec_t *ntfa_find_hdl_rec
> >>>
> >>>       return NULL;
> >>>   }
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : ntfa_subscriber_list_del
> >>>
> >>> +  Description   : This routine deletes a list of allocated subscribers
> >>> +
> >>> +  Arguments     : pointer to the list of subscribers records anchor.
> >>> +
> >>> +  Return Values : None
> >>> +
> >>> +  Notes         :
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +void ntfa_subscriber_list_del()
> >>> +{
> >>> +    ntfa_subscriber_list_t *listPtr = subscriberNoList;
> >>> +    while (listPtr != NULL) {
> >>> +        ntfa_subscriber_list_t* tmpSub = listPtr;
> >>> +        listPtr = listPtr->next;
> >>> +        free(tmpSub);
> >>> +    }
> >>> +    subscriberNoList = NULL;
> >>> +}
> >>>
> /**********************************************************
> ******************
> >>>
> >>>     Name          : ntfa_hdl_list_del
> >>>
> >>> @@ -651,15 +758,24 @@ void ntfa_hdl_list_del(ntfa_client_hdl_r
> >>>
> >>>       while ((client_hdl = *p_client_hdl) != NULL) {
> >>>           *p_client_hdl = client_hdl->next;
> >>> +        m_NCS_IPC_DETACH(&client_hdl->mbx, ntfa_clear_mbx, NULL);
> >>> +        m_NCS_IPC_RELEASE(&client_hdl->mbx, NULL);
> >>>           ncshm_destroy_hdl(NCS_SERVICE_ID_NTFA, client_hdl-
> >local_hdl);
> >>>       /** clean up the channel records for this ntfa-client
> >>>            **/
> >>> + ntfa_notification_list_del(&client_hdl->notification_list);
> >>> ntfa_notification_hdl_rec_list_del(&client_hdl->notification_list);
> >>> +
> >>> +        ntfa_filter_list_del(&client_hdl->filter_list);
> >>> + ntfa_filter_hdl_rec_list_del(&client_hdl->filter_list);
> >>> +
> >>> + ntfa_reader_hdl_rec_list_del(&client_hdl->reader_list);
> >>>       /** remove the association with hdl-mngr
> >>>            **/
> >>>           free(client_hdl);
> >>>           client_hdl = 0;
> >>>       }
> >>> +    ntfa_subscriber_list_del();
> >>>   }
> >>>
> >>>
> /**********************************************************
> ******************
> >>>
> >>> @@ -757,10 +873,80 @@ uint32_t ntfa_filter_hdl_rec_del(ntfa_fi
> >>>       TRACE("The node couldn't be deleted");
> >>>       return NCSCC_RC_FAILURE;
> >>>   }
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : ntfa_hdl_rec_force_del
> >>>
> >>> +  Description   : This routine deletes all memory allocated to client.
> >>> +
> >>> +  Arguments     : NTFA_CLIENT_HDL_REC **list_head
> >>> +          NTFA_CLIENT_HDL_REC *rm_node
> >>> +
> >>> +  Return Values : None
> >>> +
> >>> +  Notes         :
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +void ntfa_hdl_rec_force_del(ntfa_client_hdl_rec_t **list_head,
> >>> ntfa_client_hdl_rec_t *rm_node)
> >>> +{
> >>> +    ntfa_client_hdl_rec_t *list_iter = *list_head;
> >>> +    TRACE_ENTER();
> >>> +    /* First remove the rm_node out of the list of client */
> >>> +    if (list_iter == rm_node)
> >>> +        *list_head = rm_node->next;
> >>> +    else {
> >>> +        while (list_iter) {
> >>> +            if (list_iter->next == rm_node) {
> >>> +                list_iter->next = rm_node->next;
> >>> +                break;
> >>> +            }
> >>> +            list_iter = list_iter->next;
> >>> +        }
> >>> +    }
> >>> +    /* Release all msgs in mailbox */
> >>> +    ntfsv_msg_t *cbk_msg;
> >>> +    while((cbk_msg =
> >>> (ntfsv_msg_t*)m_NCS_IPC_NON_BLK_RECEIVE(&rm_node->mbx,
> cbk_msg))
> >>> +        != NULL) {
> >>> +        ntfa_msg_destroy(cbk_msg);
> >>> +    }
> >>> +    /* delete subscriber of this client out of the subcriberNoList*/
> >>> +    ntfa_subscriber_list_t* subscriber_hdl = subscriberNoList;
> >>> +    while (subscriber_hdl != NULL) {
> >>> +        ntfa_subscriber_list_t *rm_subscriber = subscriber_hdl;
> >>> +        subscriber_hdl = subscriber_hdl->next;
> >>> +        if (rm_node->local_hdl ==
> >>> rm_subscriber->subscriberListNtfHandle) {
> >>> +            if (rm_subscriber->next != NULL) {
> >>> +                rm_subscriber->next->prev = rm_subscriber->prev;
> >>> +            }
> >>> +
> >>> +            if (rm_subscriber->prev != NULL) {
> >>> +                rm_subscriber->prev->next = rm_subscriber->next;
> >>> +            } else {
> >>> +                if (rm_subscriber->next != NULL)
> >>> +                    subscriberNoList = rm_subscriber->next;
> >>> +                else
> >>> +                    subscriberNoList = NULL;
> >>> +            }
> >>> + ntfa_del_ntf_filter_ptrs(&rm_subscriber->filters);
> >>> +            free(rm_subscriber);
> >>> +        }
> >>> +    }
> >>> +    /* Now delete client */
> >>> +    m_NCS_IPC_DETACH(&rm_node->mbx, ntfa_clear_mbx, NULL);
> >>> +    m_NCS_IPC_RELEASE(&rm_node->mbx, NULL);
> >>> +    ncshm_destroy_hdl(NCS_SERVICE_ID_NTFA, rm_node->local_hdl);
> >>> + ntfa_notification_list_del(&rm_node->notification_list);
> >>> + ntfa_notification_hdl_rec_list_del(&rm_node->notification_list);
> >>> +
> >>> +    ntfa_filter_list_del(&rm_node->filter_list);
> >>> +    ntfa_filter_hdl_rec_list_del(&rm_node->filter_list);
> >>> +
> >>> +    ntfa_reader_hdl_rec_list_del(&rm_node->reader_list);
> >>> +    free(rm_node);
> >>> +
> >>> +    TRACE_LEAVE();
> >>> +}
> >>>
> /**********************************************************
> ******************
> >>>
> >>>     Name          : ntfa_hdl_rec_del
> >>> -
> >>> +
> >>>     Description   : This routine deletes the a client handle record from
> >>>                     a list of client hdl records.
> >>>
> >>> @@ -962,7 +1148,7 @@ ntfa_client_hdl_rec_t *ntfa_hdl_rec_add(
> >>>       /** Associate with the client_id obtained from NTFS
> >>>        **/
> >>>       rec->ntfs_client_id = client_id;
> >>> -
> >>> +    rec->valid = true;
> >>>       /** Initialize and attach the IPC/Priority queue
> >>>        **/
> >>>
> >>> @@ -1063,7 +1249,7 @@ static void logtrace_init_constructor(vo
> >>>    *
> >>>    * @param instance
> >>>    */
> >>> -void ntfa_hdl_rec_destructor(ntfa_notification_hdl_rec_t *instance)
> >>> +void ntfa_notification_destructor(ntfa_notification_hdl_rec_t
> >>> *instance)
> >>>   {
> >>>       ntfa_notification_hdl_rec_t *notificationInstance = instance;
> >>>
> >>> @@ -1111,7 +1297,7 @@ void ntfa_hdl_rec_destructor(ntfa_notifi
> >>>    *
> >>>    * @param instance
> >>>    */
> >>> -void ntfa_filter_hdl_rec_destructor(ntfa_filter_hdl_rec_t *filter_rec)
> >>> +void ntfa_filter_destructor(ntfa_filter_hdl_rec_t *filter_rec)
> >>>   {
> >>>       switch (filter_rec->ntfType) {
> >>>       case SA_NTF_TYPE_OBJECT_CREATE_DELETE:
> >>> @@ -1202,6 +1388,7 @@ uint32_t ntfa_reader_hdl_rec_del(ntfa_re
> >>>            **/
> >>>           ncshm_give_hdl(rm_node->reader_hdl);
> >>>           ncshm_destroy_hdl(NCS_SERVICE_ID_NTFA, rm_node-
> >reader_hdl);
> >>> +        ntfa_del_ntf_filter_ptrs(&rm_node->filters);
> >>>           free(rm_node);
> >>>           return NCSCC_RC_SUCCESS;
> >>>       } else {        /* find the rec */
> >>> @@ -1213,6 +1400,7 @@ uint32_t ntfa_reader_hdl_rec_del(ntfa_re
> >>>                    **/
> >>>                   ncshm_give_hdl(rm_node->reader_hdl);
> >>>                   ncshm_destroy_hdl(NCS_SERVICE_ID_NTFA,
> >>> rm_node->reader_hdl);
> >>> + ntfa_del_ntf_filter_ptrs(&rm_node->filters);
> >>>                   free(rm_node);
> >>>                   return NCSCC_RC_SUCCESS;
> >>>               }
> >>> @@ -1258,3 +1446,258 @@ void ntfa_add_to_async_cbk_msg_list(ntfs
> >>>
> >>>       TRACE_LEAVE();
> >>>   }
> >>> +
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : ntfa_notify_handle_invalid
> >>> +
> >>> +  Description   : This routine sends a dummy callback msg to
> >>> client's mailbox
> >>> +          so that the client polls in and calls saNtfDispatch.
> >>> +  Arguments     :
> >>> +
> >>> +  Return Values : None
> >>> +
> >>> +  Notes         : None
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +void ntfa_notify_handle_invalid() {
> >>> +    ntfa_client_hdl_rec_t *client_hdl = ntfa_cb.client_list;
> >>> +    TRACE_ENTER();
> >>> +    while (client_hdl != NULL) {
> >>> +        /* Only applicable for subscriber */
> >>> +        if (client_hdl->reg_cbk.saNtfNotificationCallback != NULL ||
> >>> + client_hdl->reg_cbk.saNtfNotificationDiscardedCallback != NULL) {
> >>> +            /* Create a dummy msg */
> >>> +            ntfsv_msg_t *msg = malloc(sizeof(ntfsv_msg_t));
> >>> +            memset(msg, 0, sizeof(ntfsv_msg_t));
> >>> +            msg->info.cbk_info.type = NTFSV_DUMMY_CALLBACK;
> >>> +            /* Send dummy msg to client mailbox */
> >> [Praveen] Is this dummy callback being sent to client in a way to
> >> force it to recover client and subscriber?
> > [Minh] Because agent doesn't recover client in mds callback, so in case
> > of subscriber who is just waiting for notification, agent needs to send
> > dummy callback to client's mailbox to wake up client's polling loop.
> > Then client will call saAmfDispatch, and from there agent will recover
> > client handles. This dummy callback is invisible to client.
> >>> +            if (m_NCS_IPC_SEND(&client_hdl->mbx, msg,
> >>> MDS_SEND_PRIORITY_HIGH) != NCSCC_RC_SUCCESS) {
> >>> +                TRACE_1("m_NCS_IPC_SEND Failed to client(id:%u)",
> >>> client_hdl->ntfs_client_id);
> >>> +                ntfa_msg_destroy(msg);
> >>> +            }
> >>> +        }
> >>> +
> >>> +        client_hdl = client_hdl->next;
> >>> +    }
> >>> +    TRACE_LEAVE();
> >>> +}
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : ntfa_update_ntfsv_state
> >>> +
> >>> +  Description   : Update current NTF Server state by the
> >>> @changedState indicated
> >>> +          by MDS event
> >>> +  Arguments     : @changedState [IN]: state to be changed of NTF Server
> >>> +
> >>> +  Return Values : None
> >>> +
> >>> +  Notes         : None
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +void ntfa_update_ntfsv_state(ntfa_ntfsv_state_t changedState)
> >>> +{
> >>> +    TRACE_ENTER();
> >>> +    TRACE_1("Current state: %u, Changed state: %u",
> >>> ntfa_cb.ntfa_ntfsv_state,
> >>> +                                                changedState);
> >>> +
> >>> +    ntfa_client_hdl_rec_t *client_hdl = ntfa_cb.client_list;
> >>> +
> >>> +    switch (ntfa_cb.ntfa_ntfsv_state){
> >>> +    case NTFA_NTFSV_NONE:
> >>> +        ntfa_cb.ntfa_ntfsv_state = changedState;
> >>> +        break;
> >>> +    case NTFA_NTFSV_DOWN:
> >>> +        if (changedState == NTFA_NTFSV_NEW_ACTIVE ||
> >>> +            changedState == NTFA_NTFSV_UP) {
> >>> +            TRACE("Active NTF server has been restarted");
> >>> +            ntfa_cb.ntfa_ntfsv_state = NTFA_NTFSV_UP;
> >>> +            ntfa_notify_handle_invalid();
> >>> +        } else
> >>> +            TRACE("Unexpected state changes");
> >>> +        break;
> >>> +    case NTFA_NTFSV_NO_ACTIVE:
> >>> +        if (changedState == NTFA_NTFSV_NEW_ACTIVE) {
> >>> +            TRACE("Standby NTF server becomes new Active");
> >>> +            /* NTF server is functioning normally */
> >>> +            ntfa_cb.ntfa_ntfsv_state = NTFA_NTFSV_UP;
> >>> +        } else if (changedState == NTFA_NTFSV_DOWN) {
> >>> +            TRACE("Active NTF Server is Down");
> >>> +            ntfa_cb.ntfa_ntfsv_state = NTFA_NTFSV_DOWN;
> >>> +            /* Mark all client handles are invalid */
> >>> +            while (client_hdl != NULL) {
> >>> +                client_hdl->valid = false;
> >>> +                client_hdl = client_hdl->next;
> >>> +            }
> >>> +        }
> >>> +        break;
> >>> +    case NTFA_NTFSV_NEW_ACTIVE:
> >>> +        TRACE("Unknown");
> >>> +        break;
> >>> +    case NTFA_NTFSV_UP:
> >>> +        if (changedState == NTFA_NTFSV_NO_ACTIVE) {
> >>> +            TRACE("Active NTF server temporarily unavailable");
> >>> +            /* Failover/Switchover is happening
> >>> +             * Any API calls result in TRY_AGAIN
> >>> +             */
> >>> +            ntfa_cb.ntfa_ntfsv_state = NTFA_NTFSV_NO_ACTIVE;
> >>> +        } else
> >>> +            TRACE("Unexpected state changes");
> >>> +        break;
> >>> +    default:
> >>> +        osafassert(false);
> >>> +    }
> >>> +
> >>> +    TRACE_LEAVE();
> >>> +}
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : ntfa_copy_ntf_filter_ptrs
> >>> +
> >>> +  Description   : Copy a list of filter from pSrc to pDes
> >>> +
> >>> +  Arguments     : pDes* [OUT]: list of outcome filter
> >>> +          pSrc* [IN]: list of input filter
> >>> +
> >>> +  Return Values : SA_AIS_OK if succeed, other values as failed
> >>> +
> >>> +  Notes         : None
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +SaAisErrorT ntfa_copy_ntf_filter_ptrs(ntfsv_filter_ptrs_t* pDes,
> >>> +                                const ntfsv_filter_ptrs_t* pSrc) {
> >>> +    SaAisErrorT rc = SA_AIS_OK;
> >>> +    SaNtfNotificationFilterHeaderT *des_header;
> >>> +    SaNtfNotificationFilterHeaderT *src_header;
> >>> +    TRACE_ENTER();
> >>> +
> >>> +    if (pSrc->alarm_filter) {
> >>> +        pDes->alarm_filter = calloc(1,
> >>> sizeof(SaNtfAlarmNotificationFilterT));
> >>> +        des_header = &(pDes->alarm_filter->notificationFilterHeader);
> >>> +        src_header = &(pSrc->alarm_filter->notificationFilterHeader);
> >>> +        if ((rc = ntfsv_filter_header_alloc(des_header,
> >>> src_header->numEventTypes,
> >>> + src_header->numNotificationObjects,
> >>> + src_header->numNotifyingObjects,
> >>> + src_header->numNotificationClassIds)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +        if ((rc = ntfsv_filter_alarm_alloc(pDes->alarm_filter,
> >>> + pSrc->alarm_filter->numProbableCauses,
> >>> + pSrc->alarm_filter->numPerceivedSeverities,
> >>> + pSrc->alarm_filter->numTrends)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +        if ((rc = ntfsv_copy_ntf_filter_alarm(pDes->alarm_filter,
> >>> + pSrc->alarm_filter)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +    }
> >>> +
> >>> +    if (pSrc->sec_al_filter) {
> >>> +        pDes->sec_al_filter = calloc(1,
> >>> sizeof(SaNtfSecurityAlarmNotificationFilterT));
> >>> +        des_header = &(pDes->sec_al_filter->notificationFilterHeader);
> >>> +        src_header = &(pSrc->sec_al_filter->notificationFilterHeader);
> >>> +        if ((rc = ntfsv_filter_header_alloc(des_header,
> >>> src_header->numEventTypes,
> >>> + src_header->numNotificationObjects,
> >>> + src_header->numNotifyingObjects,
> >>> + src_header->numNotificationClassIds)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +        if ((rc = ntfsv_filter_sec_alarm_alloc(pDes->sec_al_filter,
> >>> + pSrc->sec_al_filter->numProbableCauses,
> >>> + pSrc->sec_al_filter->numSeverities,
> >>> + pSrc->sec_al_filter->numSecurityAlarmDetectors,
> >>> + pSrc->sec_al_filter->numServiceUsers,
> >>> + pSrc->sec_al_filter->numServiceProviders)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +        if ((rc = ntfsv_copy_ntf_filter_sec_alarm(pDes->sec_al_filter,
> >>> + pSrc->sec_al_filter)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +    }
> >>> +
> >>> +    if (pSrc->sta_ch_filter) {
> >>> +        pDes->sta_ch_filter = calloc(1,
> >>> sizeof(SaNtfStateChangeNotificationFilterT));
> >>> +        des_header = &(pDes->sta_ch_filter->notificationFilterHeader);
> >>> +        src_header = &(pSrc->sta_ch_filter->notificationFilterHeader);
> >>> +        if ((rc = ntfsv_filter_header_alloc(des_header,
> >>> src_header->numEventTypes,
> >>> + src_header->numNotificationObjects,
> >>> + src_header->numNotifyingObjects,
> >>> + src_header->numNotificationClassIds)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +        if ((rc = ntfsv_filter_state_ch_alloc(pDes->sta_ch_filter,
> >>> + pSrc->sta_ch_filter->numSourceIndicators,
> >>> + pSrc->sta_ch_filter->numStateChanges)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +        if ((rc = ntfsv_copy_ntf_filter_state_ch(pDes->sta_ch_filter,
> >>> + pSrc->sta_ch_filter)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +    }
> >>> +
> >>> +    if (pSrc->obj_cr_del_filter) {
> >>> +        pDes->obj_cr_del_filter = calloc(1,
> >>> sizeof(SaNtfObjectCreateDeleteNotificationFilterT));
> >>> +        des_header =
> >>> &(pDes->obj_cr_del_filter->notificationFilterHeader);
> >>> +        src_header =
> >>> &(pSrc->obj_cr_del_filter->notificationFilterHeader);
> >>> +        if ((rc = ntfsv_filter_header_alloc(des_header,
> >>> src_header->numEventTypes,
> >>> + src_header->numNotificationObjects,
> >>> + src_header->numNotifyingObjects,
> >>> + src_header->numNotificationClassIds)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +        if ((rc =
> >>> ntfsv_filter_obj_cr_del_alloc(pDes->obj_cr_del_filter,
> >>> + pSrc->obj_cr_del_filter->numSourceIndicators)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +        if ((rc =
> >>> ntfsv_copy_ntf_filter_obj_cr_del(pDes->obj_cr_del_filter,
> >>> + pSrc->obj_cr_del_filter)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +    }
> >>> +
> >>> +    if (pSrc->att_ch_filter) {
> >>> +        pDes->att_ch_filter = calloc(1,
> >>> sizeof(SaNtfAttributeChangeNotificationFilterT));
> >>> +        des_header = &(pDes->att_ch_filter->notificationFilterHeader);
> >>> +        src_header = &(pSrc->att_ch_filter->notificationFilterHeader);
> >>> +        if ((rc = ntfsv_filter_header_alloc(des_header,
> >>> src_header->numEventTypes,
> >>> + src_header->numNotificationObjects,
> >>> + src_header->numNotifyingObjects,
> >>> + src_header->numNotificationClassIds)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +        if ((rc = ntfsv_filter_attr_change_alloc(pDes->att_ch_filter,
> >>> + pSrc->att_ch_filter->numSourceIndicators)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +        if ((rc = ntfsv_copy_ntf_filter_attr_ch(pDes->att_ch_filter,
> >>> + pSrc->att_ch_filter)) != SA_AIS_OK)
> >>> +            goto done;
> >>> +    }
> >>> +done:
> >>> +    TRACE_LEAVE();
> >>> +    return rc;
> >>> +}
> >>> +
> >>>
> +/*********************************************************
> *******************
> >>>
> >>> +  Name          : ntfa_del_ntf_filter_ptrs
> >>> +
> >>> +  Description   : Delete the filter pointers
> >>> +
> >>> +  Arguments     : filter_ptrs* [IN/OUT]: filter pointers
> >>> +
> >>> +  Return Values : SA_AIS_OK if succeed, other values as failed
> >>> +
> >>> +  Notes         : None
> >>>
> +*********************************************************
> *********************/
> >>>
> >>> +SaAisErrorT ntfa_del_ntf_filter_ptrs(ntfsv_filter_ptrs_t* filter_ptrs)
> >>> +{
> >>> +    SaAisErrorT rc = SA_AIS_OK;
> >>> +    if (filter_ptrs->alarm_filter) {
> >>> +        ntfsv_filter_alarm_free(filter_ptrs->alarm_filter, true);
> >>> +        free(filter_ptrs->alarm_filter);
> >>> +    }
> >>> +
> >>> +    if (filter_ptrs->sec_al_filter) {
> >>> + ntfsv_filter_sec_alarm_free(filter_ptrs->sec_al_filter, true);
> >>> +        free(filter_ptrs->sec_al_filter);
> >>> +    }
> >>> +
> >>> +    if (filter_ptrs->sta_ch_filter) {
> >>> + ntfsv_filter_state_ch_free(filter_ptrs->sta_ch_filter, true);
> >>> +        free(filter_ptrs->sta_ch_filter);
> >>> +    }
> >>> +
> >>> +    if (filter_ptrs->obj_cr_del_filter) {
> >>> + ntfsv_filter_obj_cr_del_free(filter_ptrs->obj_cr_del_filter, true);
> >>> +        free(filter_ptrs->obj_cr_del_filter);
> >>> +    }
> >>> +
> >>> +    if (filter_ptrs->att_ch_filter) {
> >>> + ntfsv_filter_attr_ch_free(filter_ptrs->att_ch_filter, true);
> >>> +        free(filter_ptrs->att_ch_filter);
> >>> +    }
> >>> +    return rc;
> >>> +}
> >>>
> >>
> >

------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to