/*****************************************************************************
** al_database.c: AL Layer Database Source Code
**
** Description: the common interface of database module.
**
** Copyright(c) 2011 Sunmedia Technologies - All Rights Reserved
**
** Author : kun.dai
**
** $Id$
*****************************************************************************/

/******************************************************************************
 *	Include Files
 ******************************************************************************/
#include "al_database.h"
#include "ai_database.h"
#include "ai_datasaving.h"
#include "umf_debug.h"

/******************************************************************************
 *	Debug and Error Print
 ******************************************************************************/
#define DATABASE_DEBUG_FLAG (0)
#define DATABASE_ERROR_FLAG (1)

#if DATABASE_DEBUG_FLAG
	#define DB_DEBUG_MSG(fmt, arg...) \
	do { \
		UMFDBG(0,"[Debug]%s: %d Line ", __FUNCTION__, __LINE__); \
		UMFDBG(0,fmt, ##arg); \
	} while(0)
#else
	#define DB_DEBUG_MSG(fmt, arg...);
#endif

#if DATABASE_ERROR_FLAG
	#define DB_ERROR_MSG(fmt, arg...) \
	do { \
		UMFDBG(0,"[Error]%s: %d Line ", __FUNCTION__, __LINE__); \
		UMFDBG(0,fmt, ##arg); \
	} while(0)
#else
	#define DB_ERROR_MSG(fmt, arg...);
#endif
#define ALDB_RESULT(ret) ((DB_SUCCESS == (ret)) ? AL_SUCCESS : AL_FAILURE)

/******************************************************************************
 *	Macros
 ******************************************************************************/


/******************************************************************************
 *	Global Variables
 ******************************************************************************/

/******************************************************************************
 *	Common APIs
 ******************************************************************************/
  /****************************************************//**
 * @brief Initialise database module
 *
 * @note This API must be called before any other APIs of this module
 *
 * @param pstInitParam	[in] specify the start address of the database in
 *						nonvolatile device, such as flash, EEPROM
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_Init(const AL_DB_Init_t *pstInitParam)
{
	AL_Return_t eRet = AL_SUCCESS;

	if (pstInitParam == NULL)
	{
		DB_ERROR_MSG("Invalid pstInitParam pointer.\n");
		return AL_INVALID_PARAM;
	}

	if (CDBIInitialize((DBNVMOperate_t*)pstInitParam) != DB_SUCCESS)
	{
		eRet = AL_FAILURE;
		DB_ERROR_MSG("CDBIInitialize() failed");
	}

	return eRet;
}

 /****************************************************//**
 * @brief Synchronize data to physical storage .
 *
 * @note This API must be called after initialize function is called,
 * and must be called before terminate function is called.
 *
 * @param eDBType		[in]Database type.
 * @param bIsBlocking	[in]If set al_true, this API will not return until saving
 *			 		data to flash is finished;if set al_false, no need to wait.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_Sync(AL_DB_EDBType_t eDBType, al_bool bIsBlocking)
{
	AL_Return_t eRet = AL_FAILURE;
	al_uint32 u32ReqId = 0;
	al_uint32 u32BlockingTime = 10;

	if (AL_DBTYPE_DVB_ATV == (eDBType & AL_DBTYPE_DVB_ATV))
	{
		eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_ATV_STORE |
			AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_ATV, &u32ReqId);

		if (bIsBlocking)
		{
			while(!AI_DataSaving_IsFinished(u32ReqId))
			{
				GL_TaskSleep(u32BlockingTime);
			}
		}
	}

	if (AL_DBTYPE_DVB_DTVALL == (eDBType & AL_DBTYPE_DVB_DTVALL))
	{
		if (AL_DBTYPE_DVB_DTVALL == (eDBType & AL_DBTYPE_DVB_DTVALL))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_STORE_ALL|
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_DTVALL, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}
	}
	else
	{
		if (AL_DBTYPE_DVB_T == (eDBType & AL_DBTYPE_DVB_T))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_STORE_SINGLE |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_T, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}
#ifdef CONFIG_ISDB_SYSTEM
		if (AL_DBTYPE_DVB_SBTVD == (eDBType & AL_DBTYPE_DVB_SBTVD))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_STORE_SINGLE |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_SBTVD, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}
#endif
		if (AL_DBTYPE_DVB_C== (eDBType & AL_DBTYPE_DVB_C))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_STORE_SINGLE |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_C, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}

		if (AL_DBTYPE_DVB_S == (eDBType & AL_DBTYPE_DVB_S))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_STORE_SINGLE |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_S, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}
	}

	return eRet;
}

 /****************************************************//**
 * @brief Register Match function for each record type
 *
 * @note This API must be called after initialize function is called,
 * and must be called before terminate function is called.
 *
 * @param eDBType	[in]Database type.
 * @param pstMatchFuc	[in]pionter to Match function for each record type
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_RegisterDupliChkFunc(AL_DB_EDBType_t eDBType, AL_DB_RecDupliChkFunc_t const *pstMatchFuc)
 {
 	AL_Return_t eRet = AL_SUCCESS;

	if (al_null == pstMatchFuc)
	{
		DB_ERROR_MSG("Invalid pstMatchFuc pointer.\n");
		return AL_INVALID_PARAM;
	}

	switch (eDBType)
	{
		case AL_DBTYPE_DVB_T:
			CDBIRegisterRecMatchFunc(CDBI_DBTYPE_DVB_T, (CDBIRecDupliChk_t *)pstMatchFuc);
			break;
#ifdef CONFIG_ISDB_SYSTEM
		case AL_DBTYPE_DVB_SBTVD:
			CDBIRegisterRecMatchFunc(CDBI_DBTYPE_DVB_SBTVD, (CDBIRecDupliChk_t *)pstMatchFuc);
			break;
#endif
		case AL_DBTYPE_DVB_C:
			CDBIRegisterRecMatchFunc(CDBI_DBTYPE_DVB_C, (CDBIRecDupliChk_t *)pstMatchFuc);
			break;

		case AL_DBTYPE_DVB_S:
			CDBIRegisterRecMatchFunc(CDBI_DBTYPE_DVB_S, (CDBIRecDupliChk_t *)pstMatchFuc);
			break;

		default:
			DB_ERROR_MSG("Invalid DBtype\n");
			eRet =  AL_INVALID_PARAM;
			break;
	}

	return eRet;

 }

  /****************************************************//**
 * @brief Register callback to process duplicate service
 *
 * @param pFunc[in] Function Pointer to get the process strategy when duplicate services exist.
 * @param peTuneType[in] Current tune type.
 * @param pePriSpec[in] Private spec.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_RegisterDupliRecStrategy(fpCDBIGetDupliRecStrategy pFunc, AL_DBTuneType_t *peTuneType, AL_DBPrivateSpec_t *pePriSpec)
{
 	AL_Return_t eRet = AL_SUCCESS;

	CDBIRegisterDupliRecStrategy(pFunc, (EDBTuneType_t*)peTuneType, (EDBPrivateSpec_t*)pePriSpec);

	return eRet;
}

 /****************************************************//**
 * @brief Register Reset default value function
 *
 * @note Only used for ATV service at now.
 *
 * @param eDBType		[in]Database type.
 * @param pfResetFuc	[in]pionter to Reset function
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_RegisterResetDefValFunc(AL_DB_ResetDefValFunc *pfResetFuc)
 {
 	AL_Return_t eRet = AL_SUCCESS;

	if (al_null == pfResetFuc)
	{
		DB_ERROR_MSG("Invalid pstMatchFuc pointer.\n");
		return AL_INVALID_PARAM;
	}

	CDBIRegisterDBRecDefValSetter((CDBISetRec2DefVal_t *)pfResetFuc);

	return eRet;

 }
 /****************************************************//**
 * @brief Load deafault data setting to database.
 *
 * @note This API must be called after initialize function is called,
 * and must be called before terminate function is called.
 *
 * @param eDBType		[in]Database type.
 * @param bIsBlocking	[in]If set al_true, this API will not return until saving
 *			 		data to flash is finished;if set al_false, no need to wait.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_SetDefault(AL_DB_EDBType_t eDBType, al_bool bIsBlocking)
{
	AL_Return_t eRet = AL_FAILURE;
	al_uint32 u32ReqId = 0;
	al_uint32 u32BlockingTime = 10;

	if (AL_DBTYPE_DVB_ATV == (eDBType & AL_DBTYPE_DVB_ATV))
	{
		eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_ATV_RST|
			AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_ATV, &u32ReqId);

		if (bIsBlocking)
		{
			while(!AI_DataSaving_IsFinished(u32ReqId))
			{
				GL_TaskSleep(u32BlockingTime);
			}
		}
	}

	if (AL_DBTYPE_DVB_DTVALL == (eDBType & AL_DBTYPE_DVB_DTVALL))
	{
		if (AL_DBTYPE_DVB_DTVALL == (eDBType & AL_DBTYPE_DVB_DTVALL))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_RST_ALL |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_DTVALL, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}
	}
	else
	{
		if (AL_DBTYPE_DVB_T == (eDBType & AL_DBTYPE_DVB_T))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_RST_SINGLE |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_T, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}
#ifdef CONFIG_ISDB_SYSTEM
		if (AL_DBTYPE_DVB_SBTVD== (eDBType & AL_DBTYPE_DVB_SBTVD))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_RST_SINGLE |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_SBTVD, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}
#endif
		if (AL_DBTYPE_DVB_C== (eDBType & AL_DBTYPE_DVB_C))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_RST_SINGLE |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_C, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}

		if (AL_DBTYPE_DVB_S == (eDBType & AL_DBTYPE_DVB_S))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_RST_SINGLE |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_S, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}
	}

	return eRet;
}

/****************************************************//**
 * @brief Reset database to empty.
 *
 * @note This API must be called after initialize function is called,
 * and must be called before terminate function is called.
 *
 * @param eDBType		[in]Database type.
 * @param bIsBlocking	[in]If set al_true, this API will not return until saving
 *			 		data to flash is finished;if set al_false, no need to wait.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_Reset(AL_DB_EDBType_t eDBType, al_bool bIsBlocking)
{
	AL_Return_t eRet = AL_FAILURE;
	al_uint32 u32ReqId = 0;
	al_uint32 u32BlockingTime = 10;

	if (AL_DBTYPE_DVB_ATV == (eDBType & AL_DBTYPE_DVB_ATV))
	{
		eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_ATV_EMPTY |
			AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_ATV, &u32ReqId);

		if (bIsBlocking)
		{
			while(!AI_DataSaving_IsFinished(u32ReqId))
			{
				GL_TaskSleep(u32BlockingTime);
			}
		}
	}

	if (AL_DBTYPE_DVB_DTVALL == (eDBType & AL_DBTYPE_DVB_DTVALL))
	{
		if (AL_DBTYPE_DVB_DTVALL == (eDBType & AL_DBTYPE_DVB_DTVALL))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_EMPTY_ALL |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_DTVALL, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}
	}
	else
	{
		if (AL_DBTYPE_DVB_T == (eDBType & AL_DBTYPE_DVB_T))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_EMPTY_SINGLE |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_T, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}
#ifdef CONFIG_ISDB_SYSTEM
		if (AL_DBTYPE_DVB_SBTVD== (eDBType & AL_DBTYPE_DVB_SBTVD))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_EMPTY_SINGLE |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_SBTVD, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}
#endif
		if (AL_DBTYPE_DVB_C== (eDBType & AL_DBTYPE_DVB_C))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_EMPTY_SINGLE |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_C, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}

		if (AL_DBTYPE_DVB_S == (eDBType & AL_DBTYPE_DVB_S))
		{
			eRet = AI_DataSaving_Request(AI_NVMSTORE_CMD_DTV_EMPTY_SINGLE |
				AI_NVMSTORE_BUSY_WAIT, AL_DBTYPE_DVB_S, &u32ReqId);

			if (bIsBlocking)
			{
				while(!AI_DataSaving_IsFinished(u32ReqId))
				{
					GL_TaskSleep(u32BlockingTime);
				}
			}
		}
	}

	return eRet;
}

/****************************************************//**
 * @brief  Get every component capabitlity of databse
 *
 * @param eDBType			[in]Record handle.
 * @param pstCapability	[in]Offset of field item in record detail.
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_GetCapability(AL_DB_EDBType_t eDBType,AL_DBCapability_t *pstCapability)
{
	AL_Return_t eRet = AL_FAILURE;

	if (al_null == pstCapability)
	{
		DB_ERROR_MSG("Invalid capability pointer.\n");
		return AL_INVALID_PARAM;
	}

	eRet = AI_DB_GetCapability(eDBType, pstCapability);

	return eRet;
}

/****************************************************//**
 * @brief Add new record to database.
 *
 * @param eDBType			[in]Database type.
 * @param eRecType		[in]Record type.
 * @param pstRecDetail		[in]Added record detail, depend on practical detail type.
 * @param hParentHdl		[in]If adding service record, the param must be multiplex handle;
 *							if adding multiplex record, the param must be network handle
 *							others, it will be ignored and assigned default #AL_DB_INVALIDHDL.
 * @param phRecHdl			[out]Record handle, return #AL_DB_INVALIDHDL when adding failed.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
 AL_Return_t AL_DB_AddRecord(AL_DB_EDBType_t eDBType,
	AL_DB_ERecordType_t eRecType, const al_void * pstRecDetail,
	AL_RecHandle_t hParentHdl, AL_RecHandle_t *phRecHdl)
{
	AL_Return_t eRet = AL_FAILURE;

	if (al_null == phRecHdl)
	{
		DB_ERROR_MSG("Invalid record handle pointer.\n");
		return AL_INVALID_PARAM;
	}

	eRet = AI_DB_AddRecord(eDBType, eRecType, pstRecDetail, hParentHdl, phRecHdl);

	return eRet;
}

/****************************************************//**
 * @brief Get record handle without deleted or unused record.
 *
 * @param eRequetCmd	[in]Getting request command.
 * @param eDBType		[in]Database type.
 * @param eRecType	[in]Record type.
 * @param phRecHdl		[in/out]Record handle.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_GetRecord(AL_DB_ERecordRequest_t eRequetCmd,
	AL_DB_EDBType_t eDBType, AL_DB_ERecordType_t eRecType, AL_RecHandle_t *phRecHdl)
{
	AL_Return_t eRet = AL_FAILURE;

	if (al_null == phRecHdl)
	{
		DB_ERROR_MSG("Invalid record handle pointer.\n");
		return AL_INVALID_PARAM;
	}

	switch(eRequetCmd)
	{
		case AL_DB_REQ_GETFIRST:
			eRet = AI_DB_GetFistRecord(eDBType, eRecType, phRecHdl);
			break;
		case AL_DB_REQ_GETLAST:
			eRet = AI_DB_GetLastRecord(eDBType, eRecType, phRecHdl);
			break;
		case AL_DB_REQ_GETNEXT:
			eRet = AI_DB_GetNextRecord(*phRecHdl, eRecType, phRecHdl);
			break;
		case AL_DB_REQ_GETPREV:
			eRet = AI_DB_GetPrevRecord(*phRecHdl, eRecType, phRecHdl);
			break;
		case AL_DB_REQ_GETPARENT:
			eRet = AI_DB_GetParentRecord(*phRecHdl, phRecHdl);
			break;
		default:
			DB_ERROR_MSG("Unsupported operate type.\n");
			eRet = AL_INVALID_PARAM;
			break;
	}

	return eRet;
}

/****************************************************//**
 * @brief Get record handle by Index.
 *
 * @param eDBType		[in]Database type.
 * @param eRecType		[in]Record type.
 * @param bIndex		[in]Record Index.
 * @param phRecHdl		[out]Record handle.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_GetRecordByIndex(AL_DB_EDBType_t eDBType, AL_DB_ERecordType_t eRecType,
	al_uint8 bIndex, AL_RecHandle_t *phRecHdl)
{
	AL_Return_t eRet = AL_FAILURE;
	al_uint8 bNum;

	if (al_null == phRecHdl)
	{
		DB_ERROR_MSG("Invalid record handle pointer.\n");
		return AL_INVALID_PARAM;
	}

	bNum = bIndex;
	eRet = AI_DB_GetFistRecord(eDBType, eRecType, phRecHdl);
	while((eRet == AL_SUCCESS) && (bNum--))
	{
		eRet = AI_DB_GetNextRecord(*phRecHdl, eRecType, phRecHdl);
	}

	return eRet;
}

/****************************************************//**
 * @brief Get sorted record list.
 *
 * @note If wanna get service list, it will get all type services.
 *
 * @param eDBType		[in]Databse type.
 * @param eRecType	[in]Record type.
 * @param pRecList		[in]Record list.
 * @param pRecNum		[in]Number of records in list.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_GetRecordList (
	AL_DB_EDBType_t eDBType,
	AL_DB_ERecordType_t eRecType,
	AL_RecHandle_t *pRecList,
	al_uint16 *pRecNum)
{
	EDBError_t eRet = DB_FAILURE;

	if (al_null != pRecList)
	{
		eRet = CDBIGetRecSortList(eDBType, eRecType, (CDBIHandle_t *)pRecList, pRecNum);
	}

	return ALDB_RESULT(eRet);
}

/****************************************************//**
 * @brief Sort record logical sequence by specified command.
 *
 * @note This operation can not influence record physical sequence.
 *
 * @param eDBType		[in]Databse type.
 * @param eDBType		[in]Record type.
 * @param eSortCmd	[in]Specify sort command type.
 * @param bAscending	[in]al_true indecates sort by ascending,
 *						and sort by descending will be set al_false.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_SortRecords(
	AL_DB_EDBType_t eDBType,
	AL_DB_ERecordType_t eRecType,
	AL_DB_ESortType_t eSortCmd,
	al_bool bAscending)
{
	AL_Return_t eRet = AL_FAILURE;

	eRet = AI_DB_SortRecords(eDBType, eRecType, eSortCmd, bAscending);

	return eRet;
}

/**
 * @brief Sort record logical sequence by specified sorting method provide by user.
 *
 * @note This operation can not influence record physical sequence.
 *
 * @param eDBType		[in]Databse type.
 * @param eDBType		[in]Record type.
 * @param fRecUserCmpCB	[in]Specify sort method provided by user.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_SortRecordsByUser(
	AL_DB_EDBType_t eDBType,
	AL_DB_ERecordType_t eRecType,
	AL_DB_RecordUserCmp fRecUserCmpCB)
{
	AL_Return_t eRet = AL_FAILURE;

	eRet = AI_DB_SortRecordsByUser(eDBType, eRecType, fRecUserCmpCB);

	return eRet;
}

/****************************************************//**
 * @brief Get children record number by its parent handle.
 *
 * @param hParentHdl	[in]Parent record handle.
 * @param puiRecCnt		[out]Record number.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_GetChildRecordNum(AL_RecHandle_t hParentHdl, al_uint32 *puiRecCnt)
{
	AL_Return_t eRet = AL_FAILURE;

	if (al_null == puiRecCnt)
	{
		DB_ERROR_MSG("Invalid parameter.\n");
		return AL_INVALID_PARAM;
	}

	eRet = AI_DB_GetChildRecordNum(hParentHdl, puiRecCnt);

	return eRet;
}

/****************************************************//**
 * @brief Get record handle by its parent handle.
 *
 * @note
 *		If the input record is invalid record, will return the first child handle;@n
 *		and if the input record is one valid child record, will return the next child handle.
 * @param hParentHdl	[in]Parent record handle.
 * @param phRecHdl		[in/out]Record handle.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_GetChildRecord(AL_RecHandle_t hParentHdl, AL_RecHandle_t *phRecHdl)
{
	AL_Return_t eRet = AL_FAILURE;

	if (al_null == phRecHdl)
	{
		DB_ERROR_MSG("Invalid record handle pointer.\n");
		return AL_INVALID_PARAM;
	}

	eRet = AI_DB_GetChildRecord(hParentHdl, phRecHdl);

	return eRet;
}

/****************************************************//**
 * @brief check whether has child record.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_HasChildRecord(AL_RecHandle_t hRecHdl, al_bool *bHasChild, al_bool *bHasGrandChild)
{
	EDBError_t eRet = DB_FAILURE;
	
	if (al_null == bHasChild)
	{
		DB_ERROR_MSG("Invalid record handle pointer.\n");
		return AL_INVALID_PARAM;
	}

	eRet = CDBIHasChildRec((CDBIHandle_t)hRecHdl, (bool*)bHasChild, (bool*)bHasGrandChild);

	return ALDB_RESULT(eRet);
}


/****************************************************//**
 * @brief Get record handle by user-defined matching function.
 *
 * @param fRecMatch	[in]Record matching function, implemented by user.
 * @param pMatchParam	[in]Needed parameters of match function.
 * @param eDBType		[in]Database tuye.
 * @param eRecType	[in]Record type.
 * @param phRecHdl		[out]The first matched record which behind of the referenced record;<br>
 * 						if hRefHdl = AL_DB_INVALIDHDL, indicates getting first matched record in database.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_GetMatchedRecord(AL_DB_RecordMatchFunc fRecMatch,
	al_void *pMatchParam, AL_DB_EDBType_t eDBType, AL_DB_ERecordType_t eRecType,
	AL_DB_ERecordRequest_t eReqCmd, AL_RecHandle_t *phRecHdl)
{
	AL_Return_t eRet = AL_FAILURE;

	if (al_null == fRecMatch)
	{
		DB_ERROR_MSG("Invalid match function pointer.\n");
		return AL_INVALID_PARAM;
	}

	if (al_null == phRecHdl)
	{
		DB_ERROR_MSG("Invalid record handle pointer.\n");
		return AL_INVALID_PARAM;
	}

	if (AL_DB_REQ_GETFIRST == eReqCmd)
	{
		*phRecHdl = AL_DB_INVALIDHDL;
		eRet = AI_DB_MatchRecord(fRecMatch, pMatchParam, eDBType, eRecType, al_true, phRecHdl);
	}
	else if (AL_DB_REQ_GETLAST == eReqCmd)
	{
		*phRecHdl = AL_DB_INVALIDHDL;
		eRet = AI_DB_MatchRecord(fRecMatch, pMatchParam, eDBType, eRecType, al_false, phRecHdl);
	}
	else if (AL_DB_REQ_GETNEXT == eReqCmd)
	{
		eRet = AI_DB_MatchRecord(fRecMatch, pMatchParam, eDBType, eRecType, al_true, phRecHdl);
	}
	else if (AL_DB_REQ_GETPREV == eReqCmd)
	{
		eRet = AI_DB_MatchRecord(fRecMatch, pMatchParam, eDBType, eRecType, al_false, phRecHdl);
	}
	else if (AL_DB_REQ_GETPARENT == eReqCmd)
	{
		eRet = AI_DB_MatchRecord(fRecMatch, pMatchParam, eDBType, eRecType, al_true, phRecHdl);
		eRet = AI_DB_GetParentRecord(*phRecHdl, phRecHdl);
	}

	return eRet;
}

/****************************************************//**
 * @brief Get database type and record type of record.
 *
 * @param hRecHdl		[in]Record handle.
 * @param peDBType	[out]Database type.
 * @param peRecType	[out]Record type.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_GetRecordType(AL_RecHandle_t hRecHdl,
	AL_DB_EDBType_t *peDBType, AL_DB_ERecordType_t *peRecType)
{
	AL_Return_t eRet = AL_FAILURE;

	if ((al_null == peDBType) && (al_null == peRecType))
	{
		DB_ERROR_MSG("Invalid parameter pointer.\n");
		return AL_INVALID_PARAM;
	}

	eRet = AI_DB_GetRecordType(hRecHdl, peDBType, peRecType);

	return eRet;
}

/****************************************************//**
 * @brief Move record to another place on logical sequence (in sorted list).
 *
 * @note
 *		1.Move record, the rest of records will be moved;
 *		2.Swap record, the rest of records won't be moved.
 *
 * @param eMoveCmd	[in]Specify move command, contain move and swap commands.
 * @param hCurrRecHdl	[in]Current rec handle.
 * @param hRefRecHdl	[in]Referenced service handle,
 *						its using depends on move command.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_MoveRecord(AL_DB_EMoveType_t eMoveCmd,
	AL_RecHandle_t hCurrRecHdl, AL_RecHandle_t hRefRecHdl)
{
	AL_Return_t eRet = AL_FAILURE;

	switch (eMoveCmd)
	{
		case AL_DB_MV_FIRST:
			eRet = AI_DB_MoveRecordToFirst(hCurrRecHdl);
			break;
		case AL_DB_MV_LAST:
			eRet = AI_DB_MoveRecordToLast(hCurrRecHdl);
			break;
		case AL_DB_MV_FRONT:
			eRet = AI_DB_MoveRecordToFront(hCurrRecHdl, hRefRecHdl);
			break;
		case AL_DB_MV_BEHIND:
			eRet = AI_DB_MoveRecordToBehind(hCurrRecHdl, hRefRecHdl);
			break;
		case AL_DB_MV_SWAP:
			eRet = AI_DB_SwapRecord(hCurrRecHdl, hRefRecHdl);
			break;
		default:
			DB_ERROR_MSG("Unsupported operate type.\n");
			eRet = AL_INVALID_PARAM;
			break;
	}
	return eRet;
}

/****************************************************//**
 * @brief Remove record from physical storage.
 *
 * @note
 * 	1.When remove one multiplex, all services belonged it will be removed;
 * 	2.when remove one network, all muliplexes and services belonged it will be removed.
 *
 * @param hRecHdl	[in]Record handle.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_RemoveRecord(AL_RecHandle_t Al_DBHdl)
{
	AL_Return_t eRet = AL_FAILURE;

	eRet = AI_DB_RemoveRecord(Al_DBHdl);

	return eRet;
}

 /****************************************************//**
 * @brief Get total number of records, without deleted records.
 *
 * @note
 *		1.For Analog service, get number of all inused services;
 *		2.For DVB service, get number of all undeleted services.
 *
 * @param eDBType		[in]Databse type.
 * @param eRecType	[in]Record type.
 * @param pu32Num	[out]Total number of records.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_GetRecordsTotalNum(AL_DB_EDBType_t eDBType,
	AL_DB_ERecordType_t eRecType, al_uint32 *pu32Num)
{
	AL_Return_t eRet = AL_FAILURE;

	eRet = AI_DB_GetTotalNum(eDBType, eRecType, pu32Num);

	return eRet;
}

/****************************************************//**
 * @brief Get searched service list which match the searching condition.
 *
 * @param fRecMatch		[in]Match function, refers to prototype #AL_DB_RecordMatchFunc.
 * @param pMatchParam		[in]Parameter provided for match function, the type indicated by user.
 * @param eDBType			[in]Database type.
 * @param eRecType		[in]Record type.
 * @param hRecHdl		[in]Record handle.
 * @param u32NeedNum		[in]Specify upper limitation of searched records number.
 * @param u32SearchOffset	[in]Specify passed records number,
 * 							and the rest of matched records will be add to the list.
 * @param pu32TotalNum	[out]Total number of matched records.
 * @param pu32GotNum		[out]The number of gotten records.
 * @param pstRecList		[out]Searched records list.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 *
 ********************************************************/
AL_Return_t AL_DB_SearchChildRecords(AL_DB_RecordMatchFunc fRecMatch, al_void *pMatchParam,
	AL_DB_EDBType_t eDBType, AL_DB_ERecordType_t eRecType, AL_RecHandle_t hRecHdl,
	al_uint32 u32NeedNum, al_uint32 u32SearchOffset,
	al_uint32 *pu32TotalNum, al_uint32 *pu32GotNum, AL_RecHandle_t *pstRecList)
{
	AL_Return_t eRet = AL_FAILURE;
	AL_RecHandle_t hTempHdl = AL_DB_INVALIDHDL;
	ECDBIDBType_t enDBType = 0;
	ECDBIRecordType_t enRecType = 0;
	al_uint32 totalNum = 0;
	al_uint32 gotNum = 0;

	if (al_null != pstRecList)
	{
		memset(pstRecList, AL_DB_INVALIDHDL, u32NeedNum * sizeof(AL_RecHandle_t));
	}

	CDBIGetRecTypeAndDBType(hRecHdl, &enDBType, &enRecType);
	if (eDBType != ((AL_DB_EDBType_t)enDBType))
	{
		return AL_FAILURE;
	}

	if (eRecType & CDBI_RECTYPE_DVBNETWORK)
	{
		return AL_FAILURE;
	}

	if ((eRecType & CDBI_RECTYPE_DVBMULTIPLEX) && (enRecType == CDBI_RECTYPE_DVBNETWORK))
	{
		AI_DB_SearchChildRecords(fRecMatch, pMatchParam, eDBType, eRecType, hRecHdl, u32NeedNum,
			u32SearchOffset, &totalNum, &gotNum, pstRecList);
	}
	else if ((eRecType & CDBI_RECTYPE_DVBSERVICE) && (enRecType == CDBI_RECTYPE_DVBNETWORK))
	{
		al_uint32 totalNumTmp = 0;
		al_uint32 gotNumTmp = 0;

		while (AL_SUCCESS == AI_DB_GetChildRecord(hRecHdl, &hTempHdl))
		{
			totalNumTmp = 0;
			gotNumTmp = 0;

			AI_DB_SearchChildRecords(fRecMatch, pMatchParam, eDBType, eRecType, hTempHdl, u32NeedNum,
				u32SearchOffset, &totalNumTmp, &gotNumTmp, pstRecList);
			totalNum += totalNumTmp;
			gotNum += gotNumTmp;
			pstRecList += gotNumTmp;
			if (u32NeedNum > gotNumTmp)
			{
				u32NeedNum -= gotNumTmp;
			}
			else
			{
				u32NeedNum = 0;
			}
			if (u32SearchOffset > gotNumTmp)
			{
				u32SearchOffset -= gotNumTmp;
			}
			else
			{
				u32SearchOffset = 0;
			}
		}
	}
	else if ((eRecType & CDBI_RECTYPE_DVBSERVICE) && (enRecType == CDBI_RECTYPE_DVBMULTIPLEX))
	{
		AI_DB_SearchChildRecords(fRecMatch, pMatchParam, eDBType, eRecType, hRecHdl, u32NeedNum,
			u32SearchOffset, &totalNum, &gotNum, pstRecList);
	}

	if (al_null != pu32TotalNum)
	{
		*pu32TotalNum = totalNum;
	}

	if (al_null != pu32GotNum)
	{
		*pu32GotNum = gotNum;
	}

	return eRet;
}

/****************************************************//**
 * @brief Get searched service list which match the searching condition.
 *
 * @param fRecMatch		[in]Match function, refers to prototype #AL_DB_RecordMatchFunc.
 * @param pMatchParam		[in]Parameter provided for match function, the type indicated by user.
 * @param eDBType			[in]Database type.
 * @param eRecType		[in]Record type.
 * @param u32NeedNum		[in]Specify upper limitation of searched records number.
 * @param u32SearchOffset	[in]Specify passed records number,
 * 							and the rest of matched records will be add to the list.
 * @param pu32TotalNum	[out]Total number of matched records.
 * @param pu32GotNum		[out]The number of gotten records.
 * @param pstRecList		[out]Searched records list.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 *
 ********************************************************/
AL_Return_t AL_DB_SearchRecords(AL_DB_RecordMatchFunc fRecMatch, al_void *pMatchParam,
	AL_DB_EDBType_t eDBType, AL_DB_ERecordType_t eRecType, al_uint32 u32NeedNum,
	al_uint32 u32SearchOffset, al_uint32 *pu32TotalNum, al_uint32 *pu32GotNum, AL_RecHandle_t *pstRecList)
{
	AL_Return_t eRet = AL_FAILURE;

	if (al_null != pstRecList)
	{
		memset(pstRecList, AL_DB_INVALIDHDL, u32NeedNum * sizeof(AL_RecHandle_t));
	}

	eRet = AI_DB_SearchRecords(fRecMatch, pMatchParam, eDBType, eRecType, u32NeedNum,
							u32SearchOffset, pu32TotalNum, pu32GotNum, pstRecList);

	return eRet;
}

AL_Return_t AL_DB_SearchRecordsExt(AL_DB_RecordMatchFunc fRecMatch, al_void *pMatchParam,
	AL_DB_EDBType_t eDBType, AL_DB_ERecordType_t eRecType, al_uint32 uiSkipNum, AL_RecHandle_t *pstRecList, al_uint32 *puiRecNum)
{
	AL_Return_t eRet = AL_FAILURE;

	if (al_null != pstRecList)
	{
		memset(pstRecList, AL_DB_INVALIDHDL, *puiRecNum * sizeof(AL_RecHandle_t));
	}

	if (eRecType & AL_RECTYPE_DVBSERVICE)
	{
		eRet = AI_DB_MatchRecordExt(fRecMatch, pMatchParam, eDBType, eRecType, al_true, uiSkipNum, pstRecList, puiRecNum);
	}
	
	return eRet;
}


/****************************************************//**
 * @brief  Querys record detail.
 *
 * @param hRecHdl			[in]Record handle.
 * @param pItemData		[out]Record detail data.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_QueryDetail(AL_RecHandle_t hRecHdl, al_void *pDetailData)
{
	AL_Return_t eRet = AL_FAILURE;


	if (al_null == pDetailData)
	{
		DB_ERROR_MSG("Invalid detail data pointer.\n");
		return AL_INVALID_PARAM;
	}

	eRet = AI_DB_QueryDetail(hRecHdl, pDetailData);

	return eRet;
}

/****************************************************//**
 * @brief  Update record detail.
 *
 * @param hRecHdl			[in]Record handle.
 * @param pItemData		[in]Record detail data.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_UpdateDetail(AL_RecHandle_t hRecHdl, const al_void *pDetailData)
{
	AL_Return_t eRet = AL_FAILURE;


	if (al_null == pDetailData)
	{
		DB_ERROR_MSG("Invalid detail data pointer.\n");
		return AL_INVALID_PARAM;
	}

	eRet = AI_DB_UpdateDetail(hRecHdl, pDetailData);

	return eRet;
}

/****************************************************//**
 * @brief  Query any one field of detail.
 *
 * @param hRecHdl			[in]Record handle.
 * @param u32ItemOffset	[in]Offset of field item in record detail.
 * @param u16ItemBytes		[in]Byte length of field data.
 * @param pItemData		[out]Specified detail field data.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_QueryDetailField(AL_RecHandle_t hRecHdl,
	al_uint16 u16ItemOffset, al_uint16 u16ItemBytes, al_void *pItemData)
{
	AL_Return_t eRet = AL_FAILURE;

	if (al_null == pItemData)
	{
		DB_ERROR_MSG("Invalid detail data pointer.\n");
		return AL_INVALID_PARAM;
	}

	eRet = AI_DB_QueryDetailField(hRecHdl, u16ItemOffset, u16ItemBytes, pItemData);

	return eRet;
}

/****************************************************//**
 * @brief  Query any one field of detail by field name.
 *
 * @param hRecHdl			[in]Record handle.
 * @param pItemName		[in]Field name, defined in detail structure.
 * @param pItemData		[in]Specified detail field data.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_QueryDetailFieldByName(AL_RecHandle_t hRecHdl,
	al_uint8 *pItemName, al_void *pItemData)
{
	AL_Return_t eRet = AL_FAILURE;

	if (al_null == pItemData)
	{
		DB_ERROR_MSG("Invalid detail data pointer.\n");
		return AL_INVALID_PARAM;
	}

	eRet = AI_DB_QueryDetailFieldByName(hRecHdl, pItemName, pItemData);

	return eRet;
}

/****************************************************//**
 * @brief  Update any one field of detail.
 *
 * @param hRecHdl			[in]Record handle.
 * @param u32ItemOffset	[in]Offset of field item in record detail.
 * @param u16ItemBytes		[in]Byte length of field data.
 * @param pItemData		[in]Specified detail field data.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_UpdateDetailField(AL_RecHandle_t hRecHdl,
	al_uint16 u16ItemOffset, al_uint16 u16ItemBytes, al_void *pItemData)
{
	AL_Return_t eRet = AL_FAILURE;

	if (al_null == pItemData)
	{
		DB_ERROR_MSG("Invalid detail data pointer.\n");
		return AL_INVALID_PARAM;
	}

	eRet = AI_DB_UpdateDetailField(hRecHdl, u16ItemOffset, u16ItemBytes, pItemData);

	return eRet;
}

/****************************************************//**
 * @brief  Update any one field of detail by field name.
 *
 * @param hRecHdl			[in]Record handle.
 * @param pItemName		[in]Field name, defined in detail structure.
 * @param pItemData		[in]Specified detail field data.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
AL_Return_t AL_DB_UpdateDetailFieldByName(AL_RecHandle_t hRecHdl,
	al_uint8 *pItemName, al_void *pItemData)
{
	AL_Return_t eRet = AL_FAILURE;

	if (al_null == pItemData)
	{
		DB_ERROR_MSG("Invalid detail data pointer.\n");
		return AL_INVALID_PARAM;
	}

	eRet = AI_DB_UpdateDetailFieldByName(hRecHdl, pItemName, pItemData);

	return eRet;
}

/****************************************************//**
 * @brief  check whether has valid services.
 *
 * @param eDBType			[in]Database type.
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
static AL_DB_EDBType_t myDBType = AL_DBTYPE_DVB_T;
static al_bool chkVisRecMatch(void *param, void const*pRec)
{
	al_bool ret = al_false;
	switch (myDBType)
	{
		case AL_DBTYPE_DVB_T:
			ret = ((STDBServInfo_t*)pRec)->stProgAttrib.notvisible == al_false 
				&& ((STDBServInfo_t*)pRec)->stProgAttrib.notselectable == al_false
				&& ((STDBServInfo_t*)pRec)->stProgAttrib.delete == al_false;
			break;
		case AL_DBTYPE_DVB_C:
			ret = ((SCDBServInfo_t*)pRec)->stProgAttrib.notvisible == al_false 
				&& ((SCDBServInfo_t*)pRec)->stProgAttrib.notselectable == al_false
				&& ((SCDBServInfo_t*)pRec)->stProgAttrib.delete == al_false;
			break;				
		case AL_DBTYPE_DVB_S:
			ret = ((SDBServInfo_t*)pRec)->stProgAttrib.notvisible == al_false 
				&& ((SDBServInfo_t*)pRec)->stProgAttrib.notselectable == al_false
				&& ((SDBServInfo_t*)pRec)->stProgAttrib.delete == al_false;
			break;
#ifdef CONFIG_ISDB_SYSTEM
		case AL_DBTYPE_DVB_SBTVD:
			ret = ((SSBTVDDBServInfo_t*)pRec)->stProgAttrib.notvisible == al_false 
				&& ((SSBTVDDBServInfo_t*)pRec)->stProgAttrib.notselectable == al_false
				&& ((SSBTVDDBServInfo_t*)pRec)->stProgAttrib.delete == al_false;
			break;
#endif
		default:
			break;
	}
	return ret;
}

al_bool AL_DB_HasVisibleService(AL_DB_EDBType_t eDBType)
{
	al_bool eRet = al_false;
	CDBIHandle_t hRec = CDBI_INVALID_HDL;
	myDBType = eDBType;

	if (CDBIFindRecord(eDBType, AL_RECTYPE_DVBSERVICE, (fpCDBIRecMatch)chkVisRecMatch, al_null, al_true, &hRec) == DB_SUCCESS)
	{
		eRet = al_true;
	}

	return eRet;
}

/****************************************************//**
 * @brief Get channel list with special attributs(like scramble channel list, free channel list etc.)
 *
 * @param pSortParam sort parameters
 *
 * @param phRec input buffer
 *
 * @param uiRecNum buffer size
 *
 * @retval  DB_SUCCESS means succss.  DB_FAILURE means failed.
 ********************************************************/
AL_Return_t AL_DB_GetRecSortListWithGivenParams(AL_DB_SearchParam_t *pSortParam, AL_RecHandle_t **phRec, UINT32 *puiRecNum)
{
	al_uint32 u32TotalNum = 0;
	al_uint32 u32ActualNum = 0;
	AL_RecHandle_t *phdllist = al_null;

	if (puiRecNum == al_null || pSortParam == al_null || phRec == al_null)
	{
		DB_ERROR_MSG("NULL ptr\n");
		return AL_INVALID_PARAM;
	}

	AL_DB_SearchRecords((AL_DB_RecordMatchFunc)(pSortParam->fpMatchFunc),
                        (al_void *)(pSortParam->pMatchParam), pSortParam->enDBType,  pSortParam->enRecType,  0,  0,  &u32TotalNum, al_null, al_null);

	if (u32TotalNum == 0)
	{
		*puiRecNum = 0;
		*phRec = al_null;
		return AL_SUCCESS;
	}

	phdllist = (AL_RecHandle_t *)malloc(u32TotalNum * sizeof(AL_RecHandle_t));

	if (phdllist == al_null)
	{
		DB_ERROR_MSG("out of memory\n");
		*puiRecNum = 0;
		*phRec = al_null;
        // CPPCHECK will report Memory leak: phdllist. it is an error report,
        //But it's ok.
		return AL_FAILURE;
		
	}

	AL_DB_SearchRecords((AL_DB_RecordMatchFunc)(pSortParam->fpMatchFunc),
                        (al_void *)(pSortParam->pMatchParam), pSortParam->enDBType,  pSortParam->enRecType,  u32TotalNum,  0,  al_null, &u32ActualNum,  phdllist);

	*phRec = phdllist;
	*puiRecNum = u32ActualNum;

	return AL_SUCCESS;
	
}

/****************************************************//**
 * @brief  check record handle is valid
 *
 * @param hRecHdl			[in]record handle
 *
 * @return
 * 	#AL_SUCCESS indicates success,
 * 	On failure, #AL_FAILURE is returned.
 ********************************************************/
al_bool AL_DB_CheckRecValid(AL_RecHandle_t hRecHdl)
{
	bool bIsValid;
	
	CDBICheckRecValid(hRecHdl, &bIsValid);

	return bIsValid;
}

