Hi Lennart,

I guess it's an ACK from you? Vu and Praveen gave ACK on V2 and if don't 
have any comment on V3, can you please push it?

Thanks,
Minh

On 17/03/16 23:09, Lennart Lund wrote:
> Hi Minh
>
> See my comments inline [Lennart]
>
> Thanks
> Lennart
>
>> -----Original Message-----
>> From: Minh Chau H
>> Sent: den 16 mars 2016 15:58
>> To: Lennart Lund; praveen.malv...@oracle.com; Vu Minh Nguyen
>> Cc: opensaf-devel@lists.sourceforge.net; Anders Widell; Minh Chau H
>> Subject: Re: [PATCH 2 of 5] NTF: Add support cloud resilience for NTF Agent
>> [#1180] V3
>>
>> Hi Lennart,
>>
>> Please see my comment in line with [Minh]
>>
>> Thanks,
>> Minh
>>
>> On 15/03/16 21:05, Lennart Lund wrote:
>>> Hi Minh,
>>>
>>> I still think it is better to have all the mutex handling in the API 
>>> function.
>> Mutex handling is actually not taken away from the API function by doing it 
>> in
>> a function called from the API function it's only hidden and the risk of
>> creating deadlocks increase. However in this case it is under control and
>> anyway the usage of global variables within the function is hidden as well. I
>> give it to you to decide.
>> [Minh] The reason I suggest that handling cb_lock mutex in separate
>> function, because I have seen the deadlock reported in #1521, it should
>> be generalized as below:
>>          saNtfFinalize() in thread 1        Unsubscribe() in thread 2
>>          // take handle
>>
>>          // lock cb_lock
>>
>>          // give handle
>>                                                          // take handle
>>
>>                                                          // lock cb_lock
>>                                                          -> I'm locked
>>          // destroy handle
>>          -> I'm locked too
>>
>> I think the similar deadlock scenarios still there in other APIs
>> (readFinalize vs readNext , ...), the reason is when locking cb (or take
>> handle), the next is not unlocking cb (or give handle) respectively. And
>> the fact that in current APIs code, a mix of cb_lock/handle usage where
>> a lot of "go to" in the middle of function  would increase the risk of
>> running into the above scenario. Separating cb_lock in function should
>> be helpful.
>> The cb_lock is used to protect cb resource,
>> subscriptionListAdd()/subscriberListItemRemove() are example of this.
>> However, the code is not using cb_lock in consistent way to protect cb
>> resource, ntfa_reader_hdl_rec_add/ntfa_reader_hdl_rec_del for instance,
>> which increases the risk of above deadlock.
>> The hidden deadlock you mentioned I guess, it happens because *cb_lock -
>> separate - function* called after locking cb. But this case should not
>> happen given that it's *glanced* over in advance, like locking cb should
>> not be called just before calling subscriptionListAdd()
>>
>> So I think that protects cb variables of #1180 in separate function is
>> not ideal to fit with current APIs code but it's acceptable in the scope
>> of cloud resilience.
>>
> [Lennart] I am OK with your decision
>>> I don't think handling a cb_lock in functions called from the API functions 
>>> is
>> a solution for the future. Instead the global cb structure and other global
>> structures e.g. client structure , reader structure etc. should be removed as
>> global variables.
>>> Instead all variables should be owned by the functionality that actually use
>> them cf. private variables in C++.
>>> E.g. Client handles and client structures shall be owned by a client handler
>> that can do all needed operations related to a client. If this handler must 
>> use
>> locks it shall own its own mutex.
>>> There is no need to lock a whole cb structure with a lot of unrelated
>> variables if one client variable is read or changed. The client handler has 
>> no
>> interest in how MDS is initiated and what handles needed for that purpose
>> etc...
>>> When writing C-code, variables that must be shared by several functions
>> within a handler, can be isolated within that handler by giving the handler 
>> its
>> own file and not exposing the variables in any .h file. The handler .h file 
>> shall
>> only expose its interface which consists of functions but no variables.
>>> This will make the API functions clean from any handling of mutexes.
>> [Minh] This raises a good idea that how to make API functions stay clean
>> from mutexes handling. So we may need some sort of cb handler (or
>> manager) that only exposes interfaces to be called in API functions.
>> These interfaces give access (add/remove/...) to each specific cb
>> resource (client_rec, filters, ...) , and has cb_lock protection at
>> entry/exit point. The body of interfaces consist of actual functions
>> that performing activities on cb resource.
>>
>> Another refactoring I think it would be useful that the data structure
>> relates to client_rec/reader_rec/subscriber_rec should reflect the
>> object orientation as mentioned in specification, where client could be
>> producer/reader/subscriber. Currently a client_rec contains a list of
>> reader, but a list of subscriber is declared globally outside
>> client_rec. Also, the reader_list declared in ntfa_cb_t structure seems
>> not being used at all. I think refactoring object orientation would give
>> a support to the idea of implementation of cb handler as above.
>>
>> If this sounds right to you, there seems to be some things to do
> [Lennart] Yes it would be nice to do some refactoring to fix this kind of 
> problems. We should try to get rid of all system global variables e.g. the cb 
> structure. The cb structure tends to be some sort of "all purpose" collection 
> of globals that are used for different things (not related). This means that 
> we may end up in situations where one thread wants to handle some variables 
> and at the same time another thread wants to handle other variables unrelated 
> but still protected by the same mutex.
> Another thing we can do is to start using C++ also for the agent except for a 
> thin C wrapper for the external API. This will make it much easier to create 
> clean code and we can also get rid of some complicated things like Patricia 
> trees via ncs API (not a very good API). Yes, this will work. It has been 
> tested in AMF but has not yet been contributed. It is likely that it will be 
> contributed.
>
>>> Thanks
>>> Lennart
>>>
>>>> -----Original Message-----
>>>> From: minh chau [mailto:minh.c...@dektech.com.au]
>>>> Sent: den 15 mars 2016 02:05
>>>> To: Lennart Lund; praveen.malv...@oracle.com; Vu Minh Nguyen
>>>> Cc: opensaf-devel@lists.sourceforge.net; Anders Widell; Minh Chau H
>>>> Subject: Re: [PATCH 2 of 5] NTF: Add support cloud resilience for NTF
>> Agent
>>>> [#1180] V3
>>>>
>>>> Hi Lennart,
>>>>
>>>> The current code in agent now is using both protection of ncshm handle
>>>> and global cb_lock mutex, and this happens in most of APIs with below
>>>> patterns
>>>>
>>>> // take lock
>>>> // doing something
>>>> // if not success
>>>>       // unlock
>>>>       // goto done
>>>> // unlock
>>>> // continue doing something
>>>> // done:
>>>>
>>>> // take lock
>>>> // doing something
>>>> // if not success
>>>>       // goto done
>>>> // done:
>>>>       // unlock
>>>>
>>>> These two patterns are now used in mix of both ncshm handle and
>> cb_lock
>>>> as well. Because of this, a lot of release locking at the end of
>>>> function, and it becomes harder to maintain and easy to makes mistake
>>>> that leads to deadlock.
>>>> In this case for cloud resilience, if ntfa_ntfsv_state is protected by
>>>> cb_lock inside of calling functions which are APIs, that also introduces
>>>> more duplicated above patterns, not only checkNtfServerState() but also
>>>> somewhere just ntfa_ntfsv_state to be checked (Finalize, Unsubscribed,
>>>> ReadFinalize).
>>>> Your comment is right also, there would be a risk that overlapping
>>>> protection and this should be avoided in normal cases.
>>>> But I think in NTF API function it'd better:
>>>>        - cb_lock is taken away from API function, accessing cb resource
>>>> should be written in separate function in which the cb_lock is used
>>>>        - Only ncshm handle protection is used in API, don't worry about
>>>> cb_lock
>>>>
>>>> Doing this way, I think the API code would look clear and reduce
>>>> duplicated pattern.
>>>>
>>>> I think we had a quick discussion and agreed that a ticket should be
>>>> raised for this matter, but haven't come up a generic solution. The
>>>> above is not final solution but I hope it makes the code a bit clearer.
>>>> And that's the way I was trying to thread safe the cloud resilience
>>>> variables. If it sounds right to you I think we can leave the rest for
>>>> another ticket. Otherwise, I can also change back to the way that
>>>> cb_lock has being used in above patterns so far. Then we may have
>>>> further discussion on this.
>>>>
>>>> Thanks,
>>>> Minh
>>>>
>>>>
>>>>
>>>> On 14/03/16 22:59, Lennart Lund wrote:
>>>>> Hi Minh,
>>>>>
>>>>> I see that you are using mutexes inside the checkNtfServerState(). I
>> don't
>>>> think this is a good solution since the same mutex  is used directly in the
>>>> function calling checkNtfServerState(). The mutex usage in the
>>>> checkNtfServerState() is hidden and there is a risk that this function may
>> be
>>>> placed within a protected area in the calling function. It is better to 
>>>> write a
>>>> note in the checkNtfServerState() function head clearly telling that this
>>>> function is not thread safe and has to be protected with the cb_lock
>> mutex
>>>> and then use the mutex in the calling function.
>>>>> Also I found a lot more unprotected usage of the global ntfa_cb
>> structure
>>>> but that is not directly related to the resilience update e.g a lot of
>> functions
>>>> taking a pointer to this structure. I think a ticket for this should be 
>>>> written
>>>> now. The fix for checkNtfServerState() will just make sure that the
>> resilience
>>>> patch don't add even more thread related issues.
>>>>> Thanks
>>>>> Lennart
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Minh Hon Chau [mailto:minh.c...@dektech.com.au]
>>>>>> Sent: den 14 mars 2016 03:08
>>>>>> To: Lennart Lund; praveen.malv...@oracle.com; Vu Minh Nguyen;
>> Minh
>>>>>> Chau H
>>>>>> Cc: opensaf-devel@lists.sourceforge.net
>>>>>> Subject: [PATCH 2 of 5] NTF: Add support cloud resilience for NTF Agent
>>>>>> [#1180] V3
>>>>>>
>>>>>>     osaf/libs/agents/saf/ntfa/ntfa.h      |   31 +-
>>>>>>     osaf/libs/agents/saf/ntfa/ntfa_api.c  |  702
>>>>>> +++++++++++++++++++++++++++------
>>>>>>     osaf/libs/agents/saf/ntfa/ntfa_mds.c  |   14 +-
>>>>>>     osaf/libs/agents/saf/ntfa/ntfa_util.c |  465
>> +++++++++++++++++++++-
>>>>>>     4 files changed, 1057 insertions(+), 155 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,61 @@
>>>>>>     /* 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 Down and No Active (temporary
>> no
>>>>>> active)
>>>>>> + */
>>>>>> +static SaAisErrorT checkNtfServerState()
>>>>>> +{
>>>>>> +        SaAisErrorT rc = SA_AIS_ERR_NOT_SUPPORTED;
>>>>>> +
>>>>>> +        osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0);
>>>>>> +
>>>>>> +        /* 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;
>>>>>> +        } 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);
>>>>>> +
>>>>>> +        osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
>>>>>> +
>>>>>> +        return rc;
>>>>>> +}
>>>>>> +
>>>>>> +/*
>>>>>> + * @Brief: Return ntf server state in thread safe manner
>>>>>> + * @Param: None
>>>>>> + * @Return: Server state
>>>>>> + */
>>>>>> +static ntfa_ntfsv_state_t getServerState()
>>>>>> +{
>>>>>> +        osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0);
>>>>>> +
>>>>>> +        ntfa_ntfsv_state_t state = ntfa_cb.ntfa_ntfsv_state;
>>>>>> +
>>>>>> +        osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
>>>>>> +        return state;
>>>>>> +}
>>>>>> +
>>>>>>     static SaAisErrorT checkNtfValueTypeRange(SaNtfValueTypeT type)
>>>>>>     {
>>>>>>          return (type < SA_NTF_VALUE_UINT8 || type >
>>>>>> SA_NTF_VALUE_ARRAY)? SA_AIS_ERR_INVALID_PARAM
>>>>>> @@ -871,7 +921,271 @@ 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);
>>>>>> +        osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0);
>>>>>> +
>>>>>> +        if (client_hdl->valid == true)
>>>>>> +                goto done;
>>>>>> +
>>>>>> +        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:
>>>>>> +        osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0);
>>>>>> +        TRACE_LEAVE();
>>>>>> +        return rc;
>>>>>> +}
>>>>>>
>>>>>>
>> /**********************************************************
>>>>>> *****************
>>>>>>      * 8.4.1
>>>>>>      *
>>>>>> @@ -923,15 +1237,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 +1290,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 +1303,7 @@ SaAisErrorT saNtfInitialize(SaNtfHandleT
>>>>>>
>>>>>>          if (rc != SA_AIS_OK) {
>>>>>>                  TRACE_2("NTFA INIT FAILED\n");
>>>>>> -                ntfa_shutdown();
>>>>>> +                ntfa_shutdown(false);
>>>>>>          }
>>>>>>
>>>>>>      done:
>>>>>> @@ -1101,6 +1414,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 +1480,13 @@ SaAisErrorT saNtfFinalize(SaNtfHandleT n
>>>>>>
>>>>>>          TRACE_ENTER();
>>>>>>
>>>>>> +        /* Check NTF server availability */
>>>>>> +        if (getServerState() == 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 +1494,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 +1541,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 +1685,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 +1755,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 +1835,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 +1943,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 +1958,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 +1998,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 +2017,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 +2057,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 +2083,7 @@ SaAisErrorT saNtfNotificationSubscribe(c
>>>>>>          if (o_msg)
>>>>>>                  ntfa_msg_destroy(o_msg);
>>>>>>          done:
>>>>>> +
>>>>>>          ncshm_give_hdl(ntfHandle);
>>>>>>          if (notificationFilterHandles) {
>>>>>>                  if (notificationFilterHandles-
>>>>>>> attributeChangeFilterHandle)
>>>>>> @@ -1737,6 +2097,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 +2362,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 +2426,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 +2467,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 +2598,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 +3066,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.
>>>>>> @@ -2727,9 +3098,8 @@ SaAisErrorT saNtfNotificationFilterFree(
>>>>>>     SaAisErrorT saNtfNotificationUnsubscribe(SaNtfSubscriptionIdT
>>>>>> subscriptionId)
>>>>>>     {
>>>>>>          TRACE_ENTER();
>>>>>> -        SaAisErrorT rc = SA_AIS_ERR_NOT_EXIST;
>>>>>> +        SaAisErrorT rc = SA_AIS_OK;
>>>>>>          SaNtfHandleT ntfHandle;
>>>>>> -
>>>>>>          ntfa_client_hdl_rec_t *client_hdl_rec;
>>>>>>
>>>>>>          ntfsv_msg_t msg, *o_msg = NULL;
>>>>>> @@ -2737,6 +3107,12 @@ SaAisErrorT saNtfNotificationUnsubscribe
>>>>>>          ntfsv_unsubscribe_req_t *send_param;
>>>>>>          uint32_t timeout = NTFS_WAIT_TIME;
>>>>>>
>>>>>> +        /* Check NTF server availability */
>>>>>> +        if (getServerState() == NTFA_NTFSV_NO_ACTIVE) {
>>>>>> +                TRACE("NTFS server is temporarily unavailable");
>>>>>> +                rc = SA_AIS_ERR_TRY_AGAIN;
>>>>>> +                goto done;
>>>>>> +        }
>>>>>>
>>>>>>          ntfHandle = ntfHandleGet(subscriptionId);
>>>>>>          if (ntfHandle == 0) {
>>>>>> @@ -2753,9 +3129,10 @@ SaAisErrorT saNtfNotificationUnsubscribe
>>>>>>                  goto done;
>>>>>>          }
>>>>>>
>>>>>> -        /**
>>>>>> -         ** Populate a sync MDS message
>>>>>> -         **/
>>>>>> +        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 +3141,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 +3155,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 +3186,19 @@ SaAisErrorT saNtfNotificationUnsubscribe
>>>>>>      done_give_hdl:
>>>>>>          if (o_msg)
>>>>>>                   ntfa_msg_destroy(o_msg);
>>>>>> +
>>>>>> +        if (!client_hdl_rec->valid && getServerState() ==
>>>>>> NTFA_NTFSV_UP) {
>>>>>> +                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 +3222,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 +3257,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 +3281,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 +3315,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 +3341,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;
>>>>>> @@ -2955,7 +3355,7 @@ done:
>>>>>>     /*  3.15.4.2 saNtfNotificationReadFinalize()  */
>>>>>>     SaAisErrorT saNtfNotificationReadFinalize(SaNtfReadHandleT
>>>> readhandle)
>>>>>>     {
>>>>>> -        SaAisErrorT rc = SA_AIS_ERR_NOT_SUPPORTED;
>>>>>> +        SaAisErrorT rc = SA_AIS_OK;
>>>>>>          uint32_t oas_rc = NCSCC_RC_FAILURE;
>>>>>>
>>>>>>          ntfa_client_hdl_rec_t *client_hdl_rec;
>>>>>> @@ -2966,6 +3366,12 @@ SaAisErrorT saNtfNotificationReadFinaliz
>>>>>>          uint32_t timeout = NTFS_WAIT_TIME;
>>>>>>
>>>>>>          TRACE_ENTER();
>>>>>> +        /* Check NTF server availability */
>>>>>> +        if (getServerState() == NTFA_NTFSV_NO_ACTIVE) {
>>>>>> +                TRACE("NTFS server is temporarily unavailable");
>>>>>> +                rc = SA_AIS_ERR_TRY_AGAIN;
>>>>>> +                goto done;
>>>>>> +        }
>>>>>>
>>>>>>          /* retrieve notification filter hdl rec */
>>>>>>          reader_hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_NTFA,
>>>>>> readhandle);
>>>>>> @@ -2983,42 +3389,39 @@ 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;
>>>>>> +        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;
>>>>>> +                }
>>>>>>          }
>>>>>>
>>>>>> -        /* 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(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 +3432,20 @@ SaAisErrorT saNtfNotificationReadFinaliz
>>>>>>      done_give_hdls:
>>>>>>          if (o_msg)
>>>>>>                   ntfa_msg_destroy(o_msg);
>>>>>> +
>>>>>> +        if (!client_hdl_rec->valid && getServerState() ==
>>>>>> NTFA_NTFSV_UP) {
>>>>>> +                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 +3499,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 +3526,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,12 @@ 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;
>>>>>> +
>>>>>> +                        if (mds_cb_info-
>>>>>>> info.svc_evt.i_change == NCSMDS_NO_ACTIVE) {
>>>>>> +
>>>>>>  ntfa_update_ntfsv_state(NTFA_NTFSV_NO_ACTIVE);
>>>>>> +                        } else
>>>>>> +
>>>>>>  ntfa_update_ntfsv_state(NTFA_NTFSV_DOWN);
>>>>>> +
>>>>>>
>>>>>>  pthread_mutex_unlock(&ntfa_cb.cb_lock);
>>>>>>                  }
>>>>>>                  break;
>>>>>> @@ -382,7 +387,12 @@ 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;
>>>>>> +
>>>>>> +                        if (mds_cb_info-
>>>>>>> info.svc_evt.i_change == NCSMDS_NEW_ACTIVE) {
>>>>>> +
>>>>>>  ntfa_update_ntfsv_state(NTFA_NTFSV_NEW_ACTIVE);
>>>>>> +                        } else
>>>>>> +
>>>>>>  ntfa_update_ntfsv_state(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_s
>>>>>> ync_sel), 30000);
>>>>>> +
>>>>>>  osaf_poll_one_fd(m_GET_FD_FROM_SEL_OBJ(ntfa_cb.ntfs_s
>>>>>> ync_sel), 10000);
>>>>>>
>>>>>>          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 */
>>>>>> +                        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;
>>>>>> +}
>


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to