/****************************************************************************
  Name          : mqa_destroy
 
  Description   : This routine destroys the MQA control block.
 
  Arguments     : destroy_info - ptr to the destroy info
 
  Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 
  Notes         : None
******************************************************************************/
static uns32 mqa_destroy(NCS_LIB_DESTROY *destroy_info)
{
	MQA_CB *cb = 0;

	/* validate the CB */
	cb = (MQA_CB *)ncshm_take_hdl(NCS_SERVICE_ID_MQA, gl_mqa_hdl);
	if (!cb)
		return NCSCC_RC_FAILURE;

	/* return MQA CB */
	ncshm_give_hdl(gl_mqa_hdl);

	/* remove the association with hdl-mngr */
	ncshm_destroy_hdl(NCS_SERVICE_ID_MQA, cb->agent_handle_id);

	if (m_NCS_LOCK(&cb->cb_lock, NCS_LOCK_WRITE) != NCSCC_RC_SUCCESS)	{
		TRACE("mqa_destroy Failed to acquire lock");
		return NCSCC_RC_FAILURE;
	}

	mqa_timer_table_destroy(cb);

	/* Unregister with ASAPi */
	mqa_asapi_unregister(cb);

	/* MDS unregister. */
	mqa_mds_unregister(cb);

	m_NCS_EDU_HDL_FLUSH(&cb->edu_hdl);

	mqa_queue_tree_destroy(cb);

	/* delete all the client info */
	mqa_client_tree_destroy(cb);

	m_NCS_UNLOCK(&cb->cb_lock, NCS_LOCK_WRITE);

	/* destroy the lock */
	m_NCS_LOCK_DESTROY(&cb->cb_lock);

	/* de register with the flex log */
	mqa_flx_log_dereg();

	/* reset the global cb handle */
	gl_mqa_hdl = 0;

	return NCSCC_RC_SUCCESS;
}
/****************************************************************************
  Name          : mqa_create
 
  Description   : This routine creates & initializes the MQA control block.
 
  Arguments     : create_info - ptr to the create info
 
  Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 
  Notes         : None
******************************************************************************/
static uint32_t mqa_create(NCS_LIB_CREATE *create_info)
{
	MQA_CB *cb = &mqa_cb;

	uint32_t rc = NCSCC_RC_SUCCESS;
	TRACE_ENTER();

	/* validate create info */
	if (create_info == NULL)
		return NCSCC_RC_FAILURE;

	memset(cb, 0, sizeof(MQA_CB));

	/* assign the MQA pool-id (used by hdl-mngr) */
	cb->pool_id = NCS_HM_POOL_ID_COMMON;

	/* create the association with hdl-mngr */
	if (!(cb->agent_handle_id = ncshm_create_hdl(cb->pool_id, NCS_SERVICE_ID_MQA, (NCSCONTEXT)cb))) {
		TRACE_2("Handle Registration Failed");
		return NCSCC_RC_FAILURE;
	}

	TRACE_1("Handle Registration Success");
	/* everything went off well.. store the hdl in the global variable */
	gl_mqa_hdl = cb->agent_handle_id;

	/* get the process id */
	cb->process_id = getpid();

	/* initialize the mqa cb lock */
	if ((rc = m_NCS_LOCK_INIT(&cb->cb_lock)) != NCSCC_RC_SUCCESS) {
		TRACE_2("Cotnrol Block Lock Initialisation Failed eith return value %d", rc);
		goto error1;
	}
	TRACE_1("Control Block lock initialization Success");

	/* initialize the client tree */
	if ((rc = mqa_client_tree_init(cb)) != NCSCC_RC_SUCCESS) {
		TRACE_2("FAILURE: Client database Initialization Failed");
		goto error2;
	}

	TRACE_1("Client Database Initialization Success");
	/* initialize the queue tree */
	if ((rc = mqa_queue_tree_init(cb)) != NCSCC_RC_SUCCESS) {
		TRACE_2("FAILURE: Queue database Initialization Failed");
		goto error3;
	}
	TRACE_1("Queue Database Initialization Success");

	/* EDU initialisation */
	if ((rc = m_NCS_EDU_HDL_INIT(&cb->edu_hdl)) != NCSCC_RC_SUCCESS) {
		TRACE_2("Edu Handle Initialization Failed");
		goto error4;
	}

	TRACE_1("EDU Handle Initialization Success");
	/* register with MDS */
	if ((rc = mqa_mds_register(cb)) != NCSCC_RC_SUCCESS) {
		TRACE_2("FAILURE: MDS registration Failed");
		goto error5;
	} else
		TRACE_1("MDS Registration Success");

	/* Update clm_node_joined flag to 1 */

	cb->clm_node_joined = 1;

	mqa_sync_with_mqd(cb);

	mqa_sync_with_mqnd(cb);

	/* initialize the timeout linked list */
	if ((rc = mqa_timer_table_init(cb)) != NCSCC_RC_SUCCESS) {
		TRACE_2("FAILURE: Tmr Initialization Failed");
		goto error6;
	}

	if ((rc = mqa_asapi_register(cb)) != NCSCC_RC_SUCCESS) {
		TRACE_2("FAILURE: Registration with ASAPi Failed");
		goto error7;
	}

	TRACE_LEAVE();
	return NCSCC_RC_SUCCESS;

 error7:
	mqa_timer_table_destroy(cb);

 error6:
	/* MDS unregister. */
	mqa_mds_unregister(cb);

 error5:
	m_NCS_EDU_HDL_FLUSH(&cb->edu_hdl);

 error4:
	/* delete the tree */
	mqa_queue_tree_destroy(cb);

 error3:
	/* delete the tree */
	mqa_client_tree_destroy(cb);
 error2:
	/* destroy the lock */
	m_NCS_LOCK_DESTROY(&cb->cb_lock);

 error1:
	/* remove the association with hdl-mngr */
	ncshm_destroy_hdl(NCS_SERVICE_ID_MQA, cb->agent_handle_id);

	return NCSCC_RC_FAILURE;
}
/****************************************************************************
  Name          : mqa_create
 
  Description   : This routine creates & initializes the MQA control block.
 
  Arguments     : create_info - ptr to the create info
 
  Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
 
  Notes         : None
******************************************************************************/
static uns32 mqa_create(NCS_LIB_CREATE *create_info)
{
	MQA_CB *cb = &mqa_cb;

	uns32 rc = NCSCC_RC_SUCCESS;
	/* validate create info */
	if (create_info == NULL)
		return NCSCC_RC_FAILURE;

	/* Register with Logging subsystem */
	mqa_flx_log_reg();

	memset(cb, 0, sizeof(MQA_CB));

	/* assign the MQA pool-id (used by hdl-mngr) */
	cb->pool_id = NCS_HM_POOL_ID_COMMON;

	/* create the association with hdl-mngr */
	if (!(cb->agent_handle_id = ncshm_create_hdl(cb->pool_id, NCS_SERVICE_ID_MQA, (NCSCONTEXT)cb))) {
		m_LOG_MQSV_A(MQA_CREATE_HANDLE_FAILED, NCSFL_LC_MQSV_INIT, NCSFL_SEV_ERROR, 0, __FILE__, __LINE__);
		goto error1;
	}

	m_LOG_MQSV_A(MQA_CREATE_HANDLE_SUCCESS, NCSFL_LC_MQSV_INIT, NCSFL_SEV_NOTICE, 1, __FILE__, __LINE__);
	/* everything went off well.. store the hdl in the global variable */
	gl_mqa_hdl = cb->agent_handle_id;

	/* get the process id */
	cb->process_id = getpid();

	/* initialize the mqa cb lock */
	if ((rc = m_NCS_LOCK_INIT(&cb->cb_lock)) != NCSCC_RC_SUCCESS) {
		m_LOG_MQSV_A(MQA_CB_LOCK_INIT_FAILED, NCSFL_LC_MQSV_INIT, NCSFL_SEV_ERROR, 0, __FILE__, __LINE__);
		goto error2;
	}
	m_LOG_MQSV_A(MQA_CB_LOCK_INIT_SUCCESS, NCSFL_LC_MQSV_INIT, NCSFL_SEV_NOTICE, rc, __FILE__, __LINE__);

	/* initialize the client tree */
	if ((rc = mqa_client_tree_init(cb)) != NCSCC_RC_SUCCESS) {
		m_LOG_MQSV_A(MQA_CLIENT_TREE_INIT_FAILED, NCSFL_LC_MQSV_INIT, NCSFL_SEV_ERROR, rc, __FILE__, __LINE__);
		goto error3;
	}

	m_LOG_MQSV_A(MQA_CLIENT_TREE_INIT_SUCCESS, NCSFL_LC_MQSV_INIT, NCSFL_SEV_NOTICE, rc, __FILE__, __LINE__);
	/* initialize the queue tree */
	if ((rc = mqa_queue_tree_init(cb)) != NCSCC_RC_SUCCESS) {
		m_LOG_MQSV_A(MQA_QUEUE_TREE_INIT_FAILED, NCSFL_LC_MQSV_INIT, NCSFL_SEV_ERROR, rc, __FILE__, __LINE__);
		goto error4;
	}
	m_LOG_MQSV_A(MQA_QUEUE_TREE_INIT_SUCCESS, NCSFL_LC_MQSV_INIT, NCSFL_SEV_NOTICE, rc, __FILE__, __LINE__);

	/* EDU initialisation */
	if ((rc = m_NCS_EDU_HDL_INIT(&cb->edu_hdl)) != NCSCC_RC_SUCCESS) {
		m_LOG_MQSV_A(MQA_EDU_HDL_INIT_FAILED, NCSFL_LC_MQSV_INIT, NCSFL_SEV_ERROR, rc, __FILE__, __LINE__);
		goto error5;
	}

	m_LOG_MQSV_A(MQA_EDU_HDL_INIT_SUCCESS, NCSFL_LC_MQSV_INIT, NCSFL_SEV_NOTICE, rc, __FILE__, __LINE__);
	/* register with MDS */
	if ((rc = mqa_mds_register(cb)) != NCSCC_RC_SUCCESS) {
		m_LOG_MQSV_A(MQA_MDS_REGISTER_FAILED, NCSFL_LC_MQSV_INIT, NCSFL_SEV_ERROR, rc, __FILE__, __LINE__);
		goto error6;
	} else
		m_LOG_MQSV_A(MQA_MDS_REGISTER_SUCCESS, NCSFL_LC_MQSV_INIT, NCSFL_SEV_INFO, rc, __FILE__, __LINE__);

	/* Update clm_node_joined flag to 1 */

	cb->clm_node_joined = 1;

	mqa_sync_with_mqd(cb);

	mqa_sync_with_mqnd(cb);

	/* initialize the timeout linked list */
	if ((rc = mqa_timer_table_init(cb)) != NCSCC_RC_SUCCESS) {
		m_LOG_MQSV_A(MQA_TIMER_TABLE_INIT_FAILED, NCSFL_LC_MQSV_INIT, NCSFL_SEV_ERROR, rc, __FILE__, __LINE__);
		goto error7;
	}

	if ((rc = mqa_asapi_register(cb)) != NCSCC_RC_SUCCESS) {
		m_LOG_MQSV_A(MQA_REGISTER_WITH_ASAPi_FAILED, NCSFL_LC_MQSV_INIT, NCSFL_SEV_ERROR, rc, __FILE__,
			     __LINE__);
		goto error8;
	}

	return NCSCC_RC_SUCCESS;

 error8:
	mqa_timer_table_destroy(cb);

 error7:
	/* MDS unregister. */
	mqa_mds_unregister(cb);

 error6:
	m_NCS_EDU_HDL_FLUSH(&cb->edu_hdl);

 error5:
	/* delete the tree */
	mqa_queue_tree_destroy(cb);

 error4:
	/* delete the tree */
	mqa_client_tree_destroy(cb);
 error3:
	/* destroy the lock */
	m_NCS_LOCK_DESTROY(&cb->cb_lock);

 error2:
	/* remove the association with hdl-mngr */
	ncshm_destroy_hdl(NCS_SERVICE_ID_MQA, cb->agent_handle_id);
 error1:
	/* de register with the flex log */
	mqa_flx_log_dereg();

	return NCSCC_RC_FAILURE;
}