osaf/libs/agents/saf/ntfa/ntfa.h | 31 +- osaf/libs/agents/saf/ntfa/ntfa_api.c | 672 +++++++++++++++++++++++++++------ osaf/libs/agents/saf/ntfa/ntfa_mds.c | 6 +- osaf/libs/agents/saf/ntfa/ntfa_util.c | 465 ++++++++++++++++++++++- 4 files changed, 1022 insertions(+), 152 deletions(-)
The patch contains support for cloud resilience feature in NTF Agent code. Please refer README.HYDRA for content of the changes diff --git a/osaf/libs/agents/saf/ntfa/ntfa.h b/osaf/libs/agents/saf/ntfa/ntfa.h --- a/osaf/libs/agents/saf/ntfa/ntfa.h +++ b/osaf/libs/agents/saf/ntfa/ntfa.h @@ -91,6 +91,7 @@ typedef struct ntfa_filter_hdl_rec { typedef struct subscriberList { SaNtfHandleT subscriberListNtfHandle; SaNtfSubscriptionIdT subscriberListSubscriptionId; + ntfsv_filter_ptrs_t filters; /* remember the filters used by this subscriber */ struct subscriberList *prev; struct subscriberList *next; } ntfa_subscriber_list_t; @@ -100,6 +101,10 @@ typedef struct ntfa_reader_hdl_rec { unsigned int reader_id; /* handle value returned by NTFS for this client */ SaNtfHandleT ntfHandle; unsigned int reader_hdl; /* READER handle from handle mgr */ + + ntfsv_filter_ptrs_t filters; /* remember the filters used by this reader */ + SaNtfSearchCriteriaT searchCriteria; /* remember the searchCriteria for recovery */ + struct ntfa_reader_hdl_rec *next; /* next pointer for the list in ntfa_cb_t */ struct ntfa_client_hdl_rec *parent_hdl; /* Back Pointer to the client instantiation */ } ntfa_reader_hdl_rec_t; @@ -114,24 +119,35 @@ typedef struct ntfa_client_hdl_rec { ntfa_reader_hdl_rec_t *reader_list; SYSF_MBX mbx; /* priority q mbx b/w MDS & Library */ struct ntfa_client_hdl_rec *next; /* next pointer for the list in ntfa_cb_t */ + bool valid; /* handle is valid if it's known by NTF server, used for headless hydra */ + SaVersionT version; /* the API version is being used by client, used for recover after headless */ } ntfa_client_hdl_rec_t; /* * The NTFA control block is the master anchor structure for all NTFA * instantiations within a process. */ +typedef enum { + NTFA_NTFSV_NONE = 0, + NTFA_NTFSV_DOWN, + NTFA_NTFSV_NO_ACTIVE, + NTFA_NTFSV_NEW_ACTIVE, + NTFA_NTFSV_UP +}ntfa_ntfsv_state_t; + typedef struct { pthread_mutex_t cb_lock; /* CB lock */ ntfa_client_hdl_rec_t *client_list; /* NTFA client handle database */ ntfa_reader_hdl_rec_t *reader_list; MDS_HDL mds_hdl; /* MDS handle */ MDS_DEST ntfs_mds_dest; /* NTFS absolute/virtual address */ - int ntfs_up; /* Indicate that MDS subscription - * is complete */ + /* NTFS NTFA sync params */ int ntfs_sync_awaited; NCS_SEL_OBJ ntfs_sync_sel; SaUint32T ntf_var_data_limit; /* max allowed variableDataSize */ + /* NTF Server state */ + ntfa_ntfsv_state_t ntfa_ntfsv_state; } ntfa_cb_t; /* ntfa_saf_api.c */ @@ -149,7 +165,7 @@ extern void ntfsv_ntfa_evt_free(struct n /* ntfa_init.c */ extern unsigned int ntfa_startup(void); -extern unsigned int ntfa_shutdown(void); +extern unsigned int ntfa_shutdown(bool forced); /* ntfa_hdl.c */ extern SaAisErrorT ntfa_hdl_cbk_dispatch(ntfa_cb_t *, ntfa_client_hdl_rec_t *, SaDispatchFlagsT); @@ -159,6 +175,7 @@ extern ntfa_notification_hdl_rec_t *ntfa extern ntfa_filter_hdl_rec_t *ntfa_filter_hdl_rec_add(ntfa_client_hdl_rec_t **hdl_rec); extern void ntfa_hdl_list_del(ntfa_client_hdl_rec_t **); extern uint32_t ntfa_hdl_rec_del(ntfa_client_hdl_rec_t **, ntfa_client_hdl_rec_t *); +extern void ntfa_hdl_rec_force_del(ntfa_client_hdl_rec_t **, ntfa_client_hdl_rec_t *); extern uint32_t ntfa_notification_hdl_rec_del(ntfa_notification_hdl_rec_t **, ntfa_notification_hdl_rec_t *); extern uint32_t ntfa_filter_hdl_rec_del(ntfa_filter_hdl_rec_t **, ntfa_filter_hdl_rec_t *); extern bool ntfa_validate_ntfa_client_hdl(ntfa_cb_t *ntfa_cb, ntfa_client_hdl_rec_t *find_hdl_rec); @@ -166,11 +183,15 @@ extern bool ntfa_validate_ntfa_client_hd /* ntfa_util.c */ extern ntfa_client_hdl_rec_t *ntfa_find_hdl_rec_by_client_id(ntfa_cb_t *ntfa_cb, uint32_t client_id); extern void ntfa_msg_destroy(ntfsv_msg_t *msg); -extern void ntfa_hdl_rec_destructor(ntfa_notification_hdl_rec_t *instance); -extern void ntfa_filter_hdl_rec_destructor(ntfa_filter_hdl_rec_t +extern void ntfa_notification_destructor(ntfa_notification_hdl_rec_t *instance); +extern void ntfa_filter_destructor(ntfa_filter_hdl_rec_t *notificationFilterInstance); extern ntfa_reader_hdl_rec_t *ntfa_reader_hdl_rec_add(ntfa_client_hdl_rec_t **hdl_rec); extern uint32_t ntfa_reader_hdl_rec_del(ntfa_reader_hdl_rec_t **, ntfa_reader_hdl_rec_t *); extern void ntfa_add_to_async_cbk_msg_list(ntfsv_msg_t ** head, ntfsv_msg_t * new_node); extern uint32_t ntfa_ntfs_msg_proc(ntfa_cb_t *cb, ntfsv_msg_t *ntfsv_msg, MDS_SEND_PRIORITY_TYPE prio); +extern void ntfa_update_ntfsv_state(ntfa_ntfsv_state_t changedState); +extern SaAisErrorT ntfa_copy_ntf_filter_ptrs(ntfsv_filter_ptrs_t* pDes, + const ntfsv_filter_ptrs_t* pSrc); +extern SaAisErrorT ntfa_del_ntf_filter_ptrs(ntfsv_filter_ptrs_t* filter_ptrs); #endif /* !NTFA_H */ diff --git a/osaf/libs/agents/saf/ntfa/ntfa_api.c b/osaf/libs/agents/saf/ntfa/ntfa_api.c --- a/osaf/libs/agents/saf/ntfa/ntfa_api.c +++ b/osaf/libs/agents/saf/ntfa/ntfa_api.c @@ -34,11 +34,42 @@ /* The main controle block */ ntfa_cb_t ntfa_cb = { .cb_lock = PTHREAD_MUTEX_INITIALIZER, + .ntfa_ntfsv_state = NTFA_NTFSV_NONE, }; /* list of subscriptions for this process */ ntfa_subscriber_list_t *subscriberNoList = NULL; +/* + * @Brief: Determine the common "availability" of API, which depends on the + * NTF Server state + * @Param: None + * @Return: OK - If Server state is UP + * TRY_AGAIN - If Server state is No Active (temporary no active) + * BAD_HANDLE - If Server state is completely Down (no active at all). + * This error code will be returned to client calling API + */ +static SaAisErrorT checkNtfServerState() +{ + SaAisErrorT rc = SA_AIS_ERR_NOT_SUPPORTED; + /* Check NTF server availability */ + if (ntfa_cb.ntfa_ntfsv_state == NTFA_NTFSV_UP) { + rc = SA_AIS_OK; + } else if (ntfa_cb.ntfa_ntfsv_state == NTFA_NTFSV_DOWN) { + TRACE("NTFS server is down"); + rc = SA_AIS_ERR_TRY_AGAIN; + } else if (ntfa_cb.ntfa_ntfsv_state == NTFA_NTFSV_NO_ACTIVE) { + TRACE("NTFS server is unavailable"); + rc = SA_AIS_ERR_TRY_AGAIN; + } else if (ntfa_cb.ntfa_ntfsv_state == NTFA_NTFSV_NONE) { + TRACE("No NTF server is detected, or API is called during headless"); + rc = SA_AIS_ERR_TRY_AGAIN; + } else + TRACE("Not supported API call under NTF Server state (%u)", + ntfa_cb.ntfa_ntfsv_state); + return rc; +} + static SaAisErrorT checkNtfValueTypeRange(SaNtfValueTypeT type) { return (type < SA_NTF_VALUE_UINT8 || type > SA_NTF_VALUE_ARRAY)? SA_AIS_ERR_INVALID_PARAM @@ -871,7 +902,266 @@ SaAisErrorT getFilters(const SaNtfNotifi } /* end help functions */ - +/**************************************************************************** + Name : reinitializeClient + + Description : This routine sends initialize messages to NTF Server in + order to obtain new client id + + Arguments : client_hdl* [IN]: client handle + + Return Values : SA_AIS_OK if success, others are failure + + Notes : None +******************************************************************************/ +SaAisErrorT reinitializeClient(ntfa_client_hdl_rec_t* client_hdl) { + uint32_t mds_rc; + SaAisErrorT rc = SA_AIS_OK; + ntfsv_msg_t i_msg, *o_msg = NULL; + + TRACE_ENTER(); + + memset(&i_msg, 0, sizeof(ntfsv_msg_t)); + i_msg.type = NTFSV_NTFA_API_MSG; + i_msg.info.api_info.type = NTFSV_INITIALIZE_REQ; + i_msg.info.api_info.param.init.version = client_hdl->version; + + mds_rc = ntfa_mds_msg_sync_send(&ntfa_cb, &i_msg, &o_msg, NTFS_WAIT_TIME); + switch (mds_rc) { + case NCSCC_RC_SUCCESS: + break; + case NCSCC_RC_REQ_TIMOUT: + rc = SA_AIS_ERR_TRY_AGAIN; + goto done; + default: + rc = SA_AIS_ERR_BAD_HANDLE; + goto done; + } + + osafassert(o_msg != NULL); + /* Check response msg: type, rc */ + if (o_msg->info.api_resp_info.type != NTFSV_INITIALIZE_RSP) { + TRACE("info.api_resp_info.type:%u", o_msg->info.api_resp_info.type); + rc = SA_AIS_ERR_LIBRARY; + goto done; + } + if ((rc = o_msg->info.api_resp_info.rc) != SA_AIS_OK) { + TRACE("info.api_resp_info.rc:%u", o_msg->info.api_resp_info.rc); + rc = SA_AIS_ERR_BAD_HANDLE; + goto done; + } + + client_hdl->ntfs_client_id = o_msg->info.api_resp_info.param.init_rsp.client_id; + TRACE("Successfully recover client_id, new client_id:%u", + client_hdl->ntfs_client_id); + +done: + if (o_msg) + ntfa_msg_destroy(o_msg); + TRACE_LEAVE(); + return rc; +} +/**************************************************************************** + Name : recoverReader + + Description : This routine sends read_initialize messages to NTF Server in + order to reintroduce this reader to NTF Server + + Arguments : client_hdl* [IN]: client handle + reader_hdl* [IN]: reader handle + + Return Values : SA_AIS_OK if success, others are failure + + Notes : None +******************************************************************************/ +SaAisErrorT recoverReader(ntfa_client_hdl_rec_t* client_hdl, ntfa_reader_hdl_rec_t* reader_hdl) { + uint32_t mds_rc; + SaAisErrorT rc = SA_AIS_OK; + ntfsv_msg_t i_msg, *o_msg = NULL; + ntfsv_reader_init_req_2_t *send_param; + + TRACE_ENTER(); + + /* Make sure the filters have not been deleted */ + if (reader_hdl->filters.alarm_filter == NULL && + reader_hdl->filters.att_ch_filter == NULL && + reader_hdl->filters.obj_cr_del_filter == NULL && + reader_hdl->filters.sec_al_filter == NULL && + reader_hdl->filters.sta_ch_filter == NULL) + return SA_AIS_ERR_BAD_HANDLE; + + memset(&i_msg, 0, sizeof(ntfsv_msg_t)); + i_msg.type = NTFSV_NTFA_API_MSG; + i_msg.info.api_info.type = NTFSV_READER_INITIALIZE_REQ_2; + send_param = &i_msg.info.api_info.param.reader_init_2; + send_param->head.client_id = client_hdl->ntfs_client_id; + send_param->head.searchCriteria = reader_hdl->searchCriteria; + send_param->f_rec = reader_hdl->filters; + + mds_rc = ntfa_mds_msg_sync_send(&ntfa_cb, &i_msg, &o_msg, NTFS_WAIT_TIME); + + switch (mds_rc) { + case NCSCC_RC_SUCCESS: + break; + case NCSCC_RC_REQ_TIMOUT: + rc = SA_AIS_ERR_TRY_AGAIN; + goto done; + default: + rc = SA_AIS_ERR_BAD_HANDLE; + goto done; + } + + osafassert(o_msg != NULL); + if ((rc = o_msg->info.api_resp_info.rc) != SA_AIS_OK) { + TRACE("o_msg->info.api_resp_info.rc:%u", o_msg->info.api_resp_info.rc); + rc = SA_AIS_ERR_BAD_HANDLE; + goto done; + } + + if (o_msg->info.api_resp_info.type != NTFSV_READER_INITIALIZE_RSP) { + TRACE("msg type (%d) failed", (int)o_msg->info.api_resp_info.type); + rc = SA_AIS_ERR_LIBRARY; + goto done; + } + /* Update reader_id since it may be changed */ + reader_hdl->reader_id = o_msg->info.api_resp_info.param.reader_init_rsp.readerId; + + TRACE("Recover reader successfully"); +done: + if (o_msg) + ntfa_msg_destroy(o_msg); + TRACE_LEAVE(); + return rc; +} +/**************************************************************************** + Name : recoverSubscriber + + Description : This routine sends subscribe messages to NTF Server in + order to reintroduce this subscriber to NTF Server + + Arguments : client_hdl* [IN]: client handle + subscriber_hdl* [IN]: subscriber handle + + Return Values : SA_AIS_OK if success, others are failure + + Notes : None +******************************************************************************/ +SaAisErrorT recoverSubscriber(ntfa_client_hdl_rec_t* client_hdl, + ntfa_subscriber_list_t* subscriber_hdl) { + uint32_t mds_rc; + SaAisErrorT rc = SA_AIS_OK; + ntfsv_msg_t i_msg, *o_msg = NULL; + ntfsv_subscribe_req_t *send_param; + + TRACE_ENTER(); + + /* Make sure the filters have not been deleted */ + if (subscriber_hdl->filters.alarm_filter == NULL && + subscriber_hdl->filters.att_ch_filter == NULL && + subscriber_hdl->filters.obj_cr_del_filter == NULL && + subscriber_hdl->filters.sec_al_filter == NULL && + subscriber_hdl->filters.sta_ch_filter == NULL) + return SA_AIS_ERR_BAD_HANDLE; + + memset(&i_msg, 0, sizeof(ntfsv_msg_t)); + i_msg.type = NTFSV_NTFA_API_MSG; + i_msg.info.api_info.type = NTFSV_SUBSCRIBE_REQ; + send_param = &i_msg.info.api_info.param.subscribe; + + send_param->client_id = client_hdl->ntfs_client_id; + send_param->subscriptionId = subscriber_hdl->subscriberListSubscriptionId; + send_param->f_rec = subscriber_hdl->filters; + + mds_rc = ntfa_mds_msg_sync_send(&ntfa_cb, &i_msg, &o_msg, NTFS_WAIT_TIME); + + switch (mds_rc) { + case NCSCC_RC_SUCCESS: + break; + case NCSCC_RC_REQ_TIMOUT: + rc = SA_AIS_ERR_TRY_AGAIN; + goto done; + default: + rc = SA_AIS_ERR_BAD_HANDLE; + goto done; + } + + osafassert(o_msg != NULL); + + if ((rc = o_msg->info.api_resp_info.rc) != SA_AIS_OK) { + TRACE("o_msg->info.api_resp_info.rc:%u", o_msg->info.api_resp_info.rc); + rc = SA_AIS_ERR_BAD_HANDLE; + goto done; + } + + if (o_msg->info.api_resp_info.type != NTFSV_SUBSCRIBE_RSP) { + TRACE("msg type (%d) failed", (int)o_msg->info.api_resp_info.type); + rc = SA_AIS_ERR_LIBRARY; + goto done; + } + TRACE("Recover subscriber successfully"); +done: + if (o_msg) + ntfa_msg_destroy(o_msg); + + TRACE_LEAVE(); + return rc; +} +/**************************************************************************** + Name : recoverClient + + Description : In NTF-A.03.01, section 2.1.2. A client can be producer, + subscriber, and reader at the same time. + This routine will recovery: + (1) client_id + (2) Then it will continue the recovery if this client also + has instance of subscriber or reader. + Arguments : client_hdl* [IN]: client handle + + Return Values : SA_AIS_OK if success, others are failure + + Notes : None +******************************************************************************/ +SaAisErrorT recoverClient(ntfa_client_hdl_rec_t *client_hdl) { + + TRACE_ENTER(); + SaAisErrorT rc = SA_AIS_OK; + + osafassert(client_hdl); + + if ((rc = reinitializeClient(client_hdl)) == SA_AIS_OK) { + /* Restore reader */ + ntfa_reader_hdl_rec_t* reader_hdl = client_hdl->reader_list; + while (reader_hdl != NULL && rc == SA_AIS_OK) { + rc = recoverReader(client_hdl, reader_hdl); + reader_hdl = reader_hdl->next; + } + if (rc != SA_AIS_OK) { + TRACE("Failed to restore reader (readerId:%d)", + reader_hdl->reader_id); + goto done; + } + /* Restore subscriber */ + ntfa_subscriber_list_t* subscriber_hdl = subscriberNoList; + while (subscriber_hdl != NULL && rc == SA_AIS_OK) { + if (client_hdl->local_hdl == subscriber_hdl->subscriberListNtfHandle) + rc = recoverSubscriber(client_hdl, subscriber_hdl); + subscriber_hdl = subscriber_hdl->next; + } + if (rc != SA_AIS_OK) { + TRACE("Failed to restore subscriber (subscriptionId:%d)", + subscriber_hdl->subscriberListSubscriptionId); + goto done; + } + client_hdl->valid = true; + } else { + TRACE("Failed to restore client (id:%d)", client_hdl->ntfs_client_id); + goto done; + } + +done: + TRACE_LEAVE(); + return rc; +} /*************************************************************************** * 8.4.1 * @@ -923,15 +1213,14 @@ SaAisErrorT saNtfInitialize(SaNtfHandleT version->releaseCode = NTF_RELEASE_CODE; version->majorVersion = NTF_MAJOR_VERSION; version->minorVersion = NTF_MINOR_VERSION; - ntfa_shutdown(); + ntfa_shutdown(false); rc = SA_AIS_ERR_VERSION; goto done; } - if (!ntfa_cb.ntfs_up) { - ntfa_shutdown(); - TRACE("NTFS server is down"); - rc = SA_AIS_ERR_TRY_AGAIN; + /* Check NTF server availability */ + if ((rc = checkNtfServerState()) != SA_AIS_OK) { + ntfa_shutdown(false); goto done; } @@ -977,7 +1266,7 @@ SaAisErrorT saNtfInitialize(SaNtfHandleT rc = SA_AIS_ERR_NO_MEMORY; goto err; } - + ntfa_hdl_rec->version = *version; /* pass the handle value to the appl */ if (SA_AIS_OK == rc) *ntfHandle = ntfa_hdl_rec->local_hdl; @@ -990,7 +1279,7 @@ SaAisErrorT saNtfInitialize(SaNtfHandleT if (rc != SA_AIS_OK) { TRACE_2("NTFA INIT FAILED\n"); - ntfa_shutdown(); + ntfa_shutdown(false); } done: @@ -1101,6 +1390,28 @@ SaAisErrorT saNtfDispatch(SaNtfHandleT n goto done; } + /* Need to check NTF server availability here + * Because if the notificationCallback just comes after MDS_DOWN + * it will go to recovery then result in failure due to no director + */ + if ((rc = checkNtfServerState()) != SA_AIS_OK) { + ncshm_give_hdl(ntfHandle); + goto done; + } + + if (!hdl_rec->valid) { + /* recovery */ + if ((rc = recoverClient(hdl_rec)) != SA_AIS_OK) { + if (rc == SA_AIS_ERR_BAD_HANDLE) { + ncshm_give_hdl(ntfHandle); + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0); + ntfa_hdl_rec_force_del(&ntfa_cb.client_list, hdl_rec); + osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0); + ntfa_shutdown(false); + goto done; + } + } + } if ((rc = ntfa_hdl_cbk_dispatch(&ntfa_cb, hdl_rec, dispatchFlags)) != SA_AIS_OK) TRACE("NTFA_DISPATCH_FAILURE"); @@ -1145,6 +1456,13 @@ SaAisErrorT saNtfFinalize(SaNtfHandleT n TRACE_ENTER(); + /* Check NTF server availability */ + if (ntfa_cb.ntfa_ntfsv_state == NTFA_NTFSV_NO_ACTIVE) { + TRACE("NTFS server is temporarily unavailable"); + rc = SA_AIS_ERR_TRY_AGAIN; + goto done; + } + /* retrieve hdl rec */ hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_NTFA, ntfHandle); if (hdl_rec == NULL) { @@ -1152,43 +1470,37 @@ SaAisErrorT saNtfFinalize(SaNtfHandleT n rc = SA_AIS_ERR_BAD_HANDLE; goto done; } - - /* Check Whether NTFS is up or not */ - if (!ntfa_cb.ntfs_up) { - TRACE("NTFS down"); - rc = SA_AIS_ERR_TRY_AGAIN; - goto done_give_hdl; + if (hdl_rec->valid) { + /** populate & send the finalize message + ** and make sure the finalize from the server + ** end returned before deleting the local records. + **/ + memset(&msg, 0, sizeof(ntfsv_msg_t)); + msg.type = NTFSV_NTFA_API_MSG; + msg.info.api_info.type = NTFSV_FINALIZE_REQ; + msg.info.api_info.param.finalize.client_id = hdl_rec->ntfs_client_id; + + mds_rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg, NTFS_WAIT_TIME); + switch (mds_rc) { + case NCSCC_RC_SUCCESS: + break; + case NCSCC_RC_REQ_TIMOUT: + rc = SA_AIS_ERR_TIMEOUT; + TRACE("ntfa_mds_msg_sync_send FAILED: %u", rc); + goto done_give_hdl; + default: + TRACE("ntfa_mds_msg_sync_send FAILED: %u", rc); + rc = SA_AIS_ERR_NO_RESOURCES; + goto done_give_hdl; + } + + if (o_msg != NULL) { + rc = o_msg->info.api_resp_info.rc; + ntfa_msg_destroy(o_msg); + } else + rc = SA_AIS_ERR_NO_RESOURCES; } - /** populate & send the finalize message - ** and make sure the finalize from the server - ** end returned before deleting the local records. - **/ - memset(&msg, 0, sizeof(ntfsv_msg_t)); - msg.type = NTFSV_NTFA_API_MSG; - msg.info.api_info.type = NTFSV_FINALIZE_REQ; - msg.info.api_info.param.finalize.client_id = hdl_rec->ntfs_client_id; - - mds_rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg, NTFS_WAIT_TIME); - switch (mds_rc) { - case NCSCC_RC_SUCCESS: - break; - case NCSCC_RC_REQ_TIMOUT: - rc = SA_AIS_ERR_TIMEOUT; - TRACE("ntfa_mds_msg_sync_send FAILED: %u", rc); - goto done_give_hdl; - default: - TRACE("ntfa_mds_msg_sync_send FAILED: %u", rc); - rc = SA_AIS_ERR_NO_RESOURCES; - goto done_give_hdl; - } - - if (o_msg != NULL) { - rc = o_msg->info.api_resp_info.rc; - ntfa_msg_destroy(o_msg); - } else - rc = SA_AIS_ERR_NO_RESOURCES; - if (rc == SA_AIS_OK) { /** delete the hdl rec ** including all resources allocated by client if MDS send is @@ -1205,7 +1517,7 @@ SaAisErrorT saNtfFinalize(SaNtfHandleT n ncshm_give_hdl(ntfHandle); if (rc == SA_AIS_OK) { - rc = ntfa_shutdown(); + rc = ntfa_shutdown(false); if (rc != NCSCC_RC_SUCCESS) TRACE_1("ntfa_shutdown failed"); } @@ -1349,7 +1661,7 @@ SaAisErrorT saNtfNotificationFree(SaNtfN } /* free the resources allocated by saNtf<ntfType>NotificationAllocate */ - ntfa_hdl_rec_destructor(notification_hdl_rec); + ntfa_notification_destructor(notification_hdl_rec); /** Delete the resources related to the notificationHandle & * remove reference in the client. @@ -1419,6 +1731,24 @@ SaAisErrorT saNtfNotificationSend(SaNtfN } osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0); + /* Check NTF server availability */ + if ((rc = checkNtfServerState()) != SA_AIS_OK) + goto done_give_hdls; + + /* Recover if this is invalid handle */ + if (!client_rec->valid) { + if ((rc = recoverClient(client_rec)) != SA_AIS_OK) { + ncshm_give_hdl(client_handle); + ncshm_give_hdl(notificationHandle); + if (rc == SA_AIS_ERR_BAD_HANDLE) { + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0); + ntfa_hdl_rec_force_del(&ntfa_cb.client_list, client_rec); + osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0); + ntfa_shutdown(false); + } + goto err_free; + } + } /** ** Populate a sync MDS message **/ @@ -1481,13 +1811,6 @@ SaAisErrorT saNtfNotificationSend(SaNtfN goto done_give_hdls; } - /* Check whether NTFS is up or not */ - if (!ntfa_cb.ntfs_up) { - TRACE("NTFS down"); - rc = SA_AIS_ERR_TRY_AGAIN; - goto done_give_hdls; - } - /* Send a sync MDS message to obtain a notification id */ mds_rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg, timeout); switch (mds_rc) { @@ -1596,7 +1919,8 @@ static SaNtfHandleT ntfHandleGet(SaNtfS return ntfHandle; } -static SaAisErrorT subscriptionListAdd(SaNtfHandleT ntfHandle, SaNtfSubscriptionIdT subscriptionId) +static SaAisErrorT subscriptionListAdd(SaNtfHandleT ntfHandle, SaNtfSubscriptionIdT subscriptionId, + ntfsv_filter_ptrs_t filters) { SaAisErrorT rc = SA_AIS_OK; ntfa_subscriber_list_t* ntfSubscriberList; @@ -1610,7 +1934,9 @@ static SaAisErrorT subscriptionListAdd(S /* Add ntfHandle and subscriptionId into list */ ntfSubscriberList->subscriberListNtfHandle = ntfHandle; ntfSubscriberList->subscriberListSubscriptionId = subscriptionId; - + memset(&ntfSubscriberList->filters, 0, sizeof(ntfsv_filter_ptrs_t)); + ntfa_copy_ntf_filter_ptrs(&ntfSubscriberList->filters, &filters); + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0); if (NULL == subscriberNoList) { subscriberNoList = ntfSubscriberList; @@ -1648,6 +1974,7 @@ static void subscriberListItemRemove(SaN subscriberNoList = NULL; } TRACE_1("REMOVE: listPtr->SubscriptionId %d", listPtr->subscriberListSubscriptionId); + ntfa_del_ntf_filter_ptrs(&listPtr->filters); free(listPtr); osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0); } @@ -1666,20 +1993,33 @@ SaAisErrorT saNtfNotificationSubscribe(c ntfsv_msg_t msg, *o_msg = NULL; ntfsv_subscribe_req_t *send_param; uint32_t timeout = NTFS_WAIT_TIME; - + bool recovery_failed = false; TRACE_ENTER(); + rc = getFilters(notificationFilterHandles, &filters, &ntfHandle, &client_hdl_rec); if (rc != SA_AIS_OK) { TRACE("getFilters failed"); goto done; } + /* Check NTF server availability */ + if ((rc = checkNtfServerState()) != SA_AIS_OK) + goto done; + + /* recovery */ + if (client_hdl_rec != NULL && !client_hdl_rec->valid) { + if ((rc = recoverClient(client_hdl_rec)) != SA_AIS_OK) { + recovery_failed = true; + goto done; + } + } + tmpHandle = ntfHandleGet(subscriptionId); if (tmpHandle != 0) { rc = SA_AIS_ERR_EXIST; goto done; } - rc = subscriptionListAdd(ntfHandle, subscriptionId); + rc = subscriptionListAdd(ntfHandle, subscriptionId, filters); if (rc != SA_AIS_OK) { goto done; } @@ -1693,29 +2033,24 @@ SaAisErrorT saNtfNotificationSubscribe(c send_param->client_id = client_hdl_rec->ntfs_client_id; send_param->subscriptionId = subscriptionId; send_param->f_rec = filters; - /* Check whether NTFS is up or not */ - if (ntfa_cb.ntfs_up) { - uint32_t rv; - /* Send a sync MDS message to obtain a log stream id */ - rv = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg, timeout); - if (rv == NCSCC_RC_SUCCESS) { - osafassert(o_msg != NULL); - if (SA_AIS_OK == o_msg->info.api_resp_info.rc) { - TRACE_1("subscriptionId from server %u", - o_msg->info.api_resp_info.param.subscribe_rsp.subscriptionId); - } else { - rc = o_msg->info.api_resp_info.rc; - TRACE("Bad return status!!! rc = %d", rc); - } + + uint32_t rv; + /* Send a sync MDS message to obtain a log stream id */ + rv = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg, timeout); + if (rv == NCSCC_RC_SUCCESS) { + osafassert(o_msg != NULL); + if (SA_AIS_OK == o_msg->info.api_resp_info.rc) { + TRACE_1("subscriptionId from server %u", + o_msg->info.api_resp_info.param.subscribe_rsp.subscriptionId); } else { - if(rv == NCSCC_RC_INVALID_INPUT) - rc = SA_AIS_ERR_INVALID_PARAM; - else - rc = SA_AIS_ERR_TRY_AGAIN; + rc = o_msg->info.api_resp_info.rc; + TRACE("Bad return status!!! rc = %d", rc); } } else { - TRACE_1("NTFS down"); - rc = SA_AIS_ERR_TRY_AGAIN; + if(rv == NCSCC_RC_INVALID_INPUT) + rc = SA_AIS_ERR_INVALID_PARAM; + else + rc = SA_AIS_ERR_TRY_AGAIN; } if (rc != SA_AIS_OK) { @@ -1724,6 +2059,7 @@ SaAisErrorT saNtfNotificationSubscribe(c if (o_msg) ntfa_msg_destroy(o_msg); done: + ncshm_give_hdl(ntfHandle); if (notificationFilterHandles) { if (notificationFilterHandles->attributeChangeFilterHandle) @@ -1737,6 +2073,13 @@ SaAisErrorT saNtfNotificationSubscribe(c if (notificationFilterHandles->alarmFilterHandle) ncshm_give_hdl(notificationFilterHandles->alarmFilterHandle); } + if (recovery_failed && rc == SA_AIS_ERR_BAD_HANDLE) { + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0); + ntfa_hdl_rec_force_del(&ntfa_cb.client_list, client_hdl_rec); + osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0); + ntfa_shutdown(false); + } + TRACE_LEAVE(); return rc; } @@ -1995,6 +2338,7 @@ SaAisErrorT saNtfSecurityAlarmNotificati rc = SA_AIS_ERR_INVALID_PARAM; goto done; } + /* retrieve hdl rec */ hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_NTFA, ntfHandle); if (hdl_rec == NULL) { @@ -2058,6 +2402,7 @@ SaAisErrorT saNtfPtrValAllocate(SaNtfNot rc = SA_AIS_ERR_INVALID_PARAM; goto done; } + notification_hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_NTFA, notificationHandle); if (notification_hdl_rec == NULL) { TRACE("ncshm_take_hdl notificationHandle failed"); @@ -2098,6 +2443,7 @@ SaAisErrorT saNtfArrayValAllocate(SaNtfN rc = SA_AIS_ERR_INVALID_PARAM; goto done; } + notification_hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_NTFA, notificationHandle); if (notification_hdl_rec == NULL) { TRACE("ncshm_take_hdl notificationHandle failed"); @@ -2228,6 +2574,7 @@ SaAisErrorT saNtfArrayValGet(SaNtfNotifi rc = SA_AIS_ERR_INVALID_PARAM; goto done; } + notification_hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_NTFA, notificationHandle); if (notification_hdl_rec == NULL) { TRACE("ncshm_take_hdl notificationHandle failed"); @@ -2695,7 +3042,7 @@ SaAisErrorT saNtfNotificationFilterFree( } /* free the resources allocated by saNtf<ntfType>FilterAllocate */ - ntfa_filter_hdl_rec_destructor(filter_hdl_rec); + ntfa_filter_destructor(filter_hdl_rec); /** Delete the resources related to the notificationFilterHandle & * remove reference in the client. @@ -2729,7 +3076,6 @@ SaAisErrorT saNtfNotificationUnsubscribe TRACE_ENTER(); SaAisErrorT rc = SA_AIS_ERR_NOT_EXIST; SaNtfHandleT ntfHandle; - ntfa_client_hdl_rec_t *client_hdl_rec; ntfsv_msg_t msg, *o_msg = NULL; @@ -2737,7 +3083,6 @@ SaAisErrorT saNtfNotificationUnsubscribe ntfsv_unsubscribe_req_t *send_param; uint32_t timeout = NTFS_WAIT_TIME; - ntfHandle = ntfHandleGet(subscriptionId); if (ntfHandle == 0) { TRACE_1("ntfHandleGet failed, subscription not exist"); @@ -2753,9 +3098,16 @@ SaAisErrorT saNtfNotificationUnsubscribe goto done; } - /** - ** Populate a sync MDS message - **/ + /* Check NTF server availability */ + if ((rc = checkNtfServerState()) != SA_AIS_OK) { + ncshm_give_hdl(ntfHandle); + goto done; + } + + if (client_hdl_rec->valid) { + /** + ** Populate a sync MDS message + **/ memset(&msg, 0, sizeof(ntfsv_msg_t)); msg.type = NTFSV_NTFA_API_MSG; msg.info.api_info.type = NTFSV_UNSUBSCRIBE_REQ; @@ -2764,13 +3116,6 @@ SaAisErrorT saNtfNotificationUnsubscribe send_param->client_id = client_hdl_rec->ntfs_client_id; send_param->subscriptionId = subscriptionId; - /* Check whether NTFS is up or not */ - if (!ntfa_cb.ntfs_up) { - TRACE_1("NTFS down"); - rc = SA_AIS_ERR_TRY_AGAIN; - goto done_give_hdl; - } - /* Send a sync MDS message to obtain a log stream id */ rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg, timeout); if (rc != NCSCC_RC_SUCCESS) { @@ -2785,6 +3130,7 @@ SaAisErrorT saNtfNotificationUnsubscribe TRACE_1("Bad return status! rc = %d", rc); goto done_give_hdl; } + } subscriberListItemRemove(subscriptionId); /*Remove msg for subscriptionId from mailbox*/ @@ -2815,6 +3161,19 @@ SaAisErrorT saNtfNotificationUnsubscribe done_give_hdl: if (o_msg) ntfa_msg_destroy(o_msg); + + if (!client_hdl_rec->valid) { + if ((rc = recoverClient(client_hdl_rec)) != SA_AIS_OK) { + if (rc == SA_AIS_ERR_BAD_HANDLE) { + ncshm_give_hdl(ntfHandle); + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0); + ntfa_hdl_rec_force_del(&ntfa_cb.client_list, client_hdl_rec); + osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0); + ntfa_shutdown(false); + goto done; + } + } + } ncshm_give_hdl(ntfHandle); done: TRACE_LEAVE(); @@ -2838,6 +3197,7 @@ SaAisErrorT saNtfNotificationReadInitial ntfsv_reader_init_req_2_t *send_param; uint32_t timeout = NTFS_WAIT_TIME; + bool recovery_failed = false; TRACE_ENTER(); if (notificationFilterHandles == NULL || readHandle == NULL) { rc = SA_AIS_ERR_INVALID_PARAM; @@ -2872,6 +3232,18 @@ SaAisErrorT saNtfNotificationReadInitial goto done_give_client_hdl; } + /* Check NTF server availability */ + if ((rc = checkNtfServerState()) != SA_AIS_OK) + goto done_give_client_hdl; + + /* recovery */ + if (client_hdl_rec != NULL && !client_hdl_rec->valid) { + if ((rc = recoverClient(client_hdl_rec)) != SA_AIS_OK) { + recovery_failed = true; + goto done_give_client_hdl; + } + } + /** ** Populate a sync MDS message **/ @@ -2884,13 +3256,6 @@ SaAisErrorT saNtfNotificationReadInitial send_param->head.searchCriteria = searchCriteria; send_param->f_rec = filters; - /* Check whether NTFS is up or not */ - if (!ntfa_cb.ntfs_up) { - TRACE("NTFS down"); - rc = SA_AIS_ERR_TRY_AGAIN; - goto done_give_client_hdl; - } - /* Send a sync MDS message to obtain a log stream id */ rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg, timeout); if (rc != NCSCC_RC_SUCCESS) { @@ -2925,12 +3290,16 @@ SaAisErrorT saNtfNotificationReadInitial reader_hdl_rec->ntfHandle = ntfHandle; /* Store the readerId returned from server */ reader_hdl_rec->reader_id = o_msg->info.api_resp_info.param.reader_init_rsp.readerId; + memset(&reader_hdl_rec->filters, 0, sizeof(ntfsv_filter_ptrs_t)); + ntfa_copy_ntf_filter_ptrs(&reader_hdl_rec->filters, &filters); + reader_hdl_rec->searchCriteria = searchCriteria; /** UnLock ntfa_CB **/ osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0); done_give_client_hdl: if (o_msg) ntfa_msg_destroy(o_msg); + if (client_hdl_rec) ncshm_give_hdl(client_hdl_rec->local_hdl); if (notificationFilterHandles) { @@ -2947,6 +3316,12 @@ done_give_client_hdl: } ncshm_give_hdl(notificationFilterHandles->alarmFilterHandle); + if (recovery_failed && rc == SA_AIS_ERR_BAD_HANDLE) { + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0); + ntfa_hdl_rec_force_del(&ntfa_cb.client_list, client_hdl_rec); + osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0); + ntfa_shutdown(false); + } done: TRACE_LEAVE(); return rc; @@ -2983,42 +3358,46 @@ SaAisErrorT saNtfNotificationReadFinaliz } TRACE_1("reader_hdl_rec = %u", reader_hdl_rec->reader_hdl); - /** - ** Populate a sync MDS message - **/ - memset(&msg, 0, sizeof(ntfsv_msg_t)); - msg.type = NTFSV_NTFA_API_MSG; - msg.info.api_info.type = NTFSV_READER_FINALIZE_REQ; - send_param = &msg.info.api_info.param.reader_finalize; - send_param->client_id = client_hdl_rec->ntfs_client_id; - send_param->readerId = reader_hdl_rec->reader_id; - - /* Check whether NTFS is up or not */ - if (!ntfa_cb.ntfs_up) { - TRACE("NTFS down"); - rc = SA_AIS_ERR_TRY_AGAIN; - goto done_give_hdls; + /* Check NTF server availability */ + if ((rc = checkNtfServerState()) != SA_AIS_OK) { + ncshm_give_hdl(client_hdl_rec->local_hdl); + ncshm_give_hdl(readhandle); + goto done; } - /* Send a sync MDS message */ - rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg, timeout); - if (rc != NCSCC_RC_SUCCESS) { - rc = SA_AIS_ERR_TRY_AGAIN; - goto done_give_hdls; + if (client_hdl_rec->valid) { + /** + ** Populate a sync MDS message + **/ + memset(&msg, 0, sizeof(ntfsv_msg_t)); + msg.type = NTFSV_NTFA_API_MSG; + msg.info.api_info.type = NTFSV_READER_FINALIZE_REQ; + send_param = &msg.info.api_info.param.reader_finalize; + send_param->client_id = client_hdl_rec->ntfs_client_id; + send_param->readerId = reader_hdl_rec->reader_id; + + + /* Send a sync MDS message */ + rc = ntfa_mds_msg_sync_send(&ntfa_cb, &msg, &o_msg, timeout); + if (rc != NCSCC_RC_SUCCESS) { + rc = SA_AIS_ERR_TRY_AGAIN; + goto done_give_hdls; + } + + osafassert(o_msg != NULL); + if (SA_AIS_OK != o_msg->info.api_resp_info.rc) { + rc = o_msg->info.api_resp_info.rc; + TRACE("Bad return status!!! rc = %d", rc); + goto done_give_hdls; + } + + if (o_msg->info.api_resp_info.type != NTFSV_READER_FINALIZE_RSP) { + TRACE("msg type (%d) failed", (int)o_msg->info.api_resp_info.type); + rc = SA_AIS_ERR_LIBRARY; + goto done_give_hdls; + } } - osafassert(o_msg != NULL); - if (SA_AIS_OK != o_msg->info.api_resp_info.rc) { - rc = o_msg->info.api_resp_info.rc; - TRACE("Bad return status!!! rc = %d", rc); - goto done_give_hdls; - } - - if (o_msg->info.api_resp_info.type != NTFSV_READER_FINALIZE_RSP) { - TRACE("msg type (%d) failed", (int)o_msg->info.api_resp_info.type); - rc = SA_AIS_ERR_LIBRARY; - goto done_give_hdls; - } osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0); oas_rc = ntfa_reader_hdl_rec_del(&client_hdl_rec->reader_list, reader_hdl_rec); if (oas_rc != NCSCC_RC_SUCCESS) { @@ -3029,6 +3408,20 @@ SaAisErrorT saNtfNotificationReadFinaliz done_give_hdls: if (o_msg) ntfa_msg_destroy(o_msg); + + if (!client_hdl_rec->valid) { + if ((rc = recoverClient(client_hdl_rec)) != SA_AIS_OK) { + if (rc == SA_AIS_ERR_BAD_HANDLE) { + ncshm_give_hdl(client_hdl_rec->local_hdl); + ncshm_give_hdl(readhandle); + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0); + ntfa_hdl_rec_force_del(&ntfa_cb.client_list, client_hdl_rec); + osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0); + ntfa_shutdown(false); + goto done; + } + } + } ncshm_give_hdl(client_hdl_rec->local_hdl); done_give_read_hdl: ncshm_give_hdl(readhandle); @@ -3082,6 +3475,23 @@ SaAisErrorT saNtfNotificationReadNext(Sa } TRACE_1("reader_hdl_rec = %u", reader_hdl_rec->reader_hdl); + /* Check NTF server availability */ + if ((rc = checkNtfServerState()) != SA_AIS_OK) + goto done_give_hdls; + + if (!client_hdl_rec->valid) { + if ((rc = recoverClient(client_hdl_rec)) != SA_AIS_OK) { + ncshm_give_hdl(client_hdl_rec->local_hdl); + ncshm_give_hdl(readHandle); + if (rc == SA_AIS_ERR_BAD_HANDLE) { + osafassert(pthread_mutex_lock(&ntfa_cb.cb_lock) == 0); + ntfa_hdl_rec_force_del(&ntfa_cb.client_list, client_hdl_rec); + osafassert(pthread_mutex_unlock(&ntfa_cb.cb_lock) == 0); + ntfa_shutdown(false); + } + goto done; + } + } /** ** Populate a sync MDS message **/ @@ -3092,12 +3502,6 @@ SaAisErrorT saNtfNotificationReadNext(Sa send_param->client_id = client_hdl_rec->ntfs_client_id; send_param->readerId = reader_hdl_rec->reader_id; send_param->searchDirection = searchDirection; - /* Check whether NTFS is up or not */ - if (!ntfa_cb.ntfs_up) { - TRACE("NTFS down"); - rc = SA_AIS_ERR_TRY_AGAIN; - goto done_give_hdls; - } do { /* Send a sync MDS message */ diff --git a/osaf/libs/agents/saf/ntfa/ntfa_mds.c b/osaf/libs/agents/saf/ntfa/ntfa_mds.c --- a/osaf/libs/agents/saf/ntfa/ntfa_mds.c +++ b/osaf/libs/agents/saf/ntfa/ntfa_mds.c @@ -369,7 +369,8 @@ static uint32_t ntfa_mds_svc_evt(struct TRACE("NTFS down"); pthread_mutex_lock(&ntfa_cb.cb_lock); memset(&ntfa_cb.ntfs_mds_dest, 0, sizeof(MDS_DEST)); - ntfa_cb.ntfs_up = 0; + ntfa_update_ntfsv_state(mds_cb_info->info.svc_evt.i_change == NCSMDS_NO_ACTIVE ? + NTFA_NTFSV_NO_ACTIVE : NTFA_NTFSV_DOWN); pthread_mutex_unlock(&ntfa_cb.cb_lock); } break; @@ -382,7 +383,8 @@ static uint32_t ntfa_mds_svc_evt(struct TRACE_2("MSG from NTFS NCSMDS_NEW_ACTIVE/UP"); pthread_mutex_lock(&ntfa_cb.cb_lock); ntfa_cb.ntfs_mds_dest = mds_cb_info->info.svc_evt.i_dest; - ntfa_cb.ntfs_up = 1; + ntfa_update_ntfsv_state(mds_cb_info->info.svc_evt.i_change == NCSMDS_NEW_ACTIVE ? + NTFA_NTFSV_NEW_ACTIVE : NTFA_NTFSV_UP); if (ntfa_cb.ntfs_sync_awaited) { /* signal waiting thread */ m_NCS_SEL_OBJ_IND(&ntfa_cb.ntfs_sync_sel); diff --git a/osaf/libs/agents/saf/ntfa/ntfa_util.c b/osaf/libs/agents/saf/ntfa/ntfa_util.c --- a/osaf/libs/agents/saf/ntfa/ntfa_util.c +++ b/osaf/libs/agents/saf/ntfa/ntfa_util.c @@ -49,7 +49,7 @@ static unsigned int ntfa_create(void) } /* Block and wait for indication from MDS meaning NTFS is up */ - osaf_poll_one_fd(m_GET_FD_FROM_SEL_OBJ(ntfa_cb.ntfs_sync_sel), 30000); + osaf_poll_one_fd(m_GET_FD_FROM_SEL_OBJ(ntfa_cb.ntfs_sync_sel), 10000); 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; +} ------------------------------------------------------------------------------ _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel