Esempio n. 1
0
/*************************************************************************** 
@brief		: MDS rcv callback. In this context called if any MDS msg is 
		  received by SMFA.
@param[in]	: rcv_evt - MDS rcv callback info.
@return		: NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
*****************************************************************************/
uint32_t smfa_mds_rcv_cbk(MDS_CALLBACK_RECEIVE_INFO *rcv_evt)
{
	SMFSV_EVT *smfsv_evt = rcv_evt->i_msg;
	SMF_EVT *evt = &smfsv_evt->info.smfa.event.cbk_req_rsp;
	SMFA_CLIENT_INFO *client_info = NULL;
	SMFA_CB *cb = &_smfa_cb;
	uint32_t filter_match = false;
	SMFSV_EVT resp_evt;

	if (NULL == evt){
		LOG_NO("SMFA: evt is NULL in rcv_cbk");
		return NCSCC_RC_SUCCESS;
	}

	if (SMF_CLBK_EVT != evt->evt_type){
		LOG_NO("SMFA: evt_type is : %d",evt->evt_type);
		return NCSCC_RC_SUCCESS;
	}

	/* TODO: I need to take READ LOCK here. But in MDS thread ???*/
	client_info = cb->smfa_client_info_list;
	while (NULL != client_info){
		/* If filter matches, post the evt to the corresponding MBX.*/
		if (NCSCC_RC_SUCCESS == smfa_cbk_filter_match(client_info,&evt->evt.cbk_evt))
			filter_match = true;
		client_info = client_info->next_client;
	}

	/* If filters dont match, respond to ND as SA_AIS_OK*/
	if (false == filter_match){
		memset(&resp_evt,0,sizeof(SMFSV_EVT));
		resp_evt.type = SMFSV_EVT_TYPE_SMFND;
		resp_evt.info.smfnd.type = SMFND_EVT_CBK_RSP;
		resp_evt.info.smfnd.event.cbk_req_rsp.evt_type = SMF_RSP_EVT;
		resp_evt.info.smfnd.event.cbk_req_rsp.evt.resp_evt.inv_id = evt->evt.cbk_evt.inv_id;
		resp_evt.info.smfnd.event.cbk_req_rsp.evt.resp_evt.err = SA_AIS_OK;

		if (NCSCC_RC_SUCCESS != smfa_to_smfnd_mds_async_send((NCSCONTEXT)&resp_evt)){
			LOG_ER("SMFA: MDS send to SMFND FAILED.");
			/* TODO: What should I do?? ND is waiting for my response.*/
		}
	}

	/* This is not the same evt we are putting in client MBX, so free it.*/
	free(evt->evt.cbk_evt.params);
	free(evt->evt.cbk_evt.cbk_label.label);
	free(smfsv_evt);

	return NCSCC_RC_SUCCESS;
}
Esempio n. 2
0
/*************************************************************************** 
@brief		: saSmfResponse
@param[in]	: smfHandle - Handle returned by successful intialize. 
@param[in]	: invocation - inv is provided by SMF in the cbk. The same
		  inv id is to be passed in the response.
@param[in]	: error - err code returned by the application in response 
		  to the cbk.
@return		: SA_AIS_OK if successful otherwise appropiate err code.
*****************************************************************************/
SaAisErrorT saSmfResponse(
		SaSmfHandleT smfHandle,
		SaInvocationT invocation,
		SaAisErrorT error)
{
	SMFA_CB *cb = &_smfa_cb;
	SMFSV_EVT resp_evt;
	SMFA_CLIENT_INFO *client_info;
	
	TRACE_ENTER2("SMFA: Response: Hdl : %llu, Inv_id: %llu, err: %d",smfHandle,invocation,error);
	if (cb->is_finalized){
		LOG_ER("SMFA: Response is called after finalized.");
		TRACE_LEAVE();
		return SA_AIS_ERR_BAD_HANDLE;
	}

	/* If the SMFND is not up, then return TRY_AGAIN.*/
	if (!cb->is_smfnd_up){
		LOG_ER("SMFA: SMFND is not UP.");
		TRACE_LEAVE();
		return SA_AIS_ERR_TRY_AGAIN;
	}
	
	if ((SA_AIS_ERR_NOT_SUPPORTED != error) && (SA_AIS_ERR_FAILED_OPERATION != error) && (SA_AIS_OK != error)){
		LOG_ER("SMFA: Invalid response. %d",error);
		TRACE_LEAVE();
		return SA_AIS_ERR_INVALID_PARAM;
	}
	
	if (!invocation){
		LOG_ER("SMFA: Invocation id is Zero.");
		TRACE_LEAVE();
		return SA_AIS_ERR_INVALID_PARAM;

	}

	if (NCSCC_RC_SUCCESS != m_NCS_LOCK(&cb->cb_lock,NCS_LOCK_WRITE)){
		LOG_ER("SMFA: Cb lock acquire FAILED.");
		TRACE_LEAVE();
		return SA_AIS_ERR_NO_RESOURCES;
	}
	
	/* Get the client info structure for the handle.*/
	client_info = smfa_client_info_get(smfHandle);
	if (NULL == client_info){
		LOG_ER("SMFA: Bad handle.");
		m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
		TRACE_LEAVE();
		return SA_AIS_ERR_BAD_HANDLE;
	}
	
	/* Drop the duplicate/delay response.*/
	if (NULL == cb->cbk_list){
		LOG_ER("SMFA: Duplicate/Delay/Invalid resp: Hdl : %llu, Inv_id: %llu",smfHandle,invocation);
		m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
		TRACE_LEAVE();
		/* The correct return code is NOT_EXIST but this is not part of this spec version. 
		 We are returning INVALID_PARAM. */
		return SA_AIS_ERR_INVALID_PARAM;
	}
	
	if (SA_AIS_ERR_FAILED_OPERATION == error){
		TRACE_2("SMFA: Not OK resp from hdl: %llu for inv: %llu.",smfHandle,invocation);
		/* Clean up every thing related to this inv id.*/
		if (NCSCC_RC_SUCCESS != smfa_cbk_err_resp_process(invocation,smfHandle)){
			LOG_ER("SMFA: Duplicate/delay/invalid response. Hdl: %llu, inv: %llu",smfHandle,invocation);
			m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
			TRACE_LEAVE();
			return SA_AIS_ERR_INVALID_PARAM;
		}
	}else{
		TRACE_2("SMFA: OK resp from hdl: %llu for inv: %llu.",smfHandle,invocation);
		/* Preocess the response before sending to ND.*/
		if (NCSCC_RC_SUCCESS != smfa_cbk_ok_resp_process(smfHandle,invocation)) {
			LOG_ER("SMFA: Duplicate/delay/invalid response. Hdl: %llu, inv: %llu",smfHandle,invocation);
			m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
			TRACE_LEAVE();
			return SA_AIS_ERR_INVALID_PARAM;
		}
	}

	TRACE_2("SMFA: Sending consolidated resp to ND for hdl: %llu for inv: %llu.",smfHandle,invocation);
	/* Populate the resp and send to SMFND.*/
	memset(&resp_evt,0,sizeof(SMFSV_EVT));
	resp_evt.type = SMFSV_EVT_TYPE_SMFND;
	resp_evt.info.smfnd.type = SMFND_EVT_CBK_RSP;
	resp_evt.info.smfnd.event.cbk_req_rsp.evt_type = SMF_RSP_EVT;
	resp_evt.info.smfnd.event.cbk_req_rsp.evt.resp_evt.inv_id = invocation;
	resp_evt.info.smfnd.event.cbk_req_rsp.evt.resp_evt.err = error;

	if (NCSCC_RC_SUCCESS != smfa_to_smfnd_mds_async_send((NCSCONTEXT)&resp_evt)){
		LOG_ER("SMFA: MDS send to SMFND FAILED.");
		/* TODO: What can we do?? We have already cleaned up our database.*/
	}

	m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);
	TRACE_LEAVE();
	return SA_AIS_OK;
}
Esempio n. 3
0
/*************************************************************************** 
@brief		: 1. Find out if there is any pending response from this client
		  be traversing the list cb->cbk_list.
		  2. If yes, then clean up the data structure and check if this 
		  is the last client for which this agent is waiting for the response.
		  3. If yes, then send OK response to SMFND.
@param[in]	: hdl - Handle for which the cbk_list is to be cleaned up. 
@return		: NCSCC_RC_FAILURE/NCSCC_RC_SUCCESS.
***************************************************************************/ 
uint32_t smfa_cbk_list_cleanup(SaSmfHandleT hdl)
{
	SMFA_CB *cb = &_smfa_cb;
	SMFA_CBK_LIST *cbk_list = cb->cbk_list, *prev_cbk = cb->cbk_list;
	SMFA_CBK_HDL_LIST *hdl_list, *prev_hdl;
	SMFSV_EVT resp_evt;
	uint32_t is_cbk_del;

	while (cbk_list){
		is_cbk_del = 0;
		hdl_list = cbk_list->hdl_list;
		prev_hdl = hdl_list;
		while(hdl_list){
			if (hdl == hdl_list->hdl){
				prev_hdl->next_hdl = hdl_list->next_hdl;
				/* Head node deleted. */
				if (prev_hdl->hdl == hdl_list->hdl){
					cbk_list->hdl_list = prev_hdl->next_hdl;
					free(hdl_list);
					/* No more resp expected.*/
					if (NULL == cbk_list->hdl_list){
						/* Send OK resp to SMFND.*/
						{
							/* Populate the resp and send to SMFND.*/
							memset(&resp_evt,0,sizeof(SMFSV_EVT));
							resp_evt.type = SMFSV_EVT_TYPE_SMFND;
							resp_evt.info.smfnd.type = SMFND_EVT_CBK_RSP;
							resp_evt.info.smfnd.event.cbk_req_rsp.evt_type = SMF_RSP_EVT;
							resp_evt.info.smfnd.event.cbk_req_rsp.evt.resp_evt.inv_id = 
							cbk_list->inv_id;;
							resp_evt.info.smfnd.event.cbk_req_rsp.evt.resp_evt.err = 
							SA_AIS_OK;

							if (NCSCC_RC_SUCCESS != smfa_to_smfnd_mds_async_send(
							(NCSCONTEXT)&resp_evt)){
							LOG_ER("SMFA: MDS send to SMFND FAILED.");
							/* TODO: What can we do?? */
							}
						}
						/* Delete the inv node.*/
						prev_cbk->next_cbk = cbk_list->next_cbk;
						is_cbk_del = 1;
						/* inv node deleted from the head of the list.*/
						if (prev_cbk->inv_id == cbk_list->inv_id){
							cb->cbk_list = prev_cbk->next_cbk;
							free(cbk_list);
							cbk_list = cb->cbk_list;
							prev_cbk = cbk_list;
						}else {
							free(cbk_list);
							// Since cbk_list was freed, the following mechanism needed to prevent dereferencing prev_cbk.
							// That case only happens when the previous round of the loop went to "if case",
							// where prev_cbk = cbk_list.
							if(prev_cbk != cbk_list)
								cbk_list = prev_cbk->next_cbk;
							else {
								cbk_list = NULL;
								// since prev_cbk = cbk_list, and cbk_list was freed,
								// prev_cbk can be set to NULL
								prev_cbk = NULL;
							}
						}
					}
				}else{
					free(hdl_list);
				}
				/* Needed for optimization.*/	
				break; 
			}
			prev_hdl = hdl_list;
			hdl_list = hdl_list->next_hdl;
		}
		if (!cbk_list)
			break;
		if (!is_cbk_del){
			prev_cbk = cbk_list;
			cbk_list = cbk_list->next_cbk;
		}
	}
	return NCSCC_RC_SUCCESS; 
}