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.


>>
>>> +    } 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