/*
 * IPRPC - Inter Process Remote Procedure Call
 *
 * Copyright (C) 2012-2013 by Hiroyuki KAJIURA. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 *
 *     1:Redistributions of source code must retain the above copyright notice, 
 *       this list of conditions and the following disclaimer.
 *     2:Redistributions in binary form must reproduce the above copyright notice, 
 *       this list of conditions and the following disclaimer in the documentation 
 *       and/or other materials provided with the distribution.
 *     3:Neither the name of copyright owner nor the names of its contributors 
 *       may be used to endorse or promote products derived from this software 
 *       without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#define	IPC_SHM_DB_MAIN

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include	"ipcInfo.h"
#include	"ipcType.h"
#include	"ipcLog.h"
#include	"ipcSyscall.h"
#include	"ipcLib.h"
#include	"ipcShm.h"
#include	"ipcShmDB.h"

#define	IPC_SHM_DATABASE_FUNC_DB_ILLEGAL_FUNC_ID			0

typedef struct {
	uint32_t funcId;
	uint32_t processId;
//	uint16_t accessDeviceType;
//	uint16_t accessProcessType;
	IPC_SkeltonFunc_t skeltonFunc;
	IPC_SkeltonCancelFunc_t cancelFunc;
} IpcFuncDBEntry_t;

typedef struct {
	uint32_t processId;
	RpcTaskID_t taskId;
	uint32_t queId;
//	IpcProcessType_t processType;
} IpcSkeltonDBEntry_t;

#ifdef	USE_MULTICAST_RPC

typedef struct {
	RpcList_t *mltcstFuncEntryTop;
	uint32_t mltcstFuncId;
	uint32_t regProcessId;
} IpcMltcstFuncList_t;

typedef struct {
	RpcMutexID_t mltcstMutexId;
	RpcMutexAttribute_t mltcstMutexAttr;
	RpcList_t *mltcstFuncListTop;
} IpcMltcstFuncDB_t;

#endif	/* USE_MULTICAST_RPC */

typedef struct {
	RpcList_t *funcDB;
	RpcList_t *skeltonDB;
#ifdef	USE_MULTICAST_RPC
	IpcMltcstFuncDB_t *mltcstFuncDB;
#endif	/* USE_MULTICAST_RPC */
	uint32_t *hashRandTable;
	RpcHashEntry_t *funcDBHashTable;
	RpcMutexID_t mutexId;
	RpcMutexAttribute_t mutexAttr;
} IpcDBManage_t;

static IpcDBManage_t *IpcDBManage = (IpcDBManage_t*)NULL;
static int32_t IpcDatabaseSharedMemId = -1;

static RpcResult_t IPC_InitShmHash(RpcBool_t masterProcess);
static RpcResult_t IPC_InitFuncDB(RpcBool_t masterProcess);
static RpcResult_t IPC_InitSkeltonDB(RpcBool_t masterProcess);

static RpcResult_t IPC_addEntryToFuncDBHash(IpcFuncDBEntry_t *entry);
static RpcResult_t IPC_deleteEntryFromFuncDBHash(uint32_t funcId);
static IpcFuncDBEntry_t *IPC_searchEntryFromFuncDBHash(uint32_t funcId);
static RpcBool_t IPC_compareFuncDBbyHash(void *entry, uint8_t *val, uint32_t valSize);
//static uint32_t IPC_nextFuncDBHashEntry(uint32_t hashId);

static RpcBool_t IPC_compareSkeltonDBByProcessId(RpcList_t *list,uint32_t processId);
static RpcBool_t IPC_compareFuncDBByFuncId(RpcList_t *list,uint32_t funcId);

#ifdef	USE_MULTICAST_RPC
static RpcResult_t IPC_initMulticastFuncDB(RpcBool_t masterProcess);
static RpcResult_t IPC_registerMulticastFunction(uint32_t processId,uint32_t mltcstFuncId);
static RpcResult_t IPC_unregisterMulticastFunction(uint32_t processId, uint32_t mltcstFuncId);
static RpcResult_t IPC_registerFunctionInMulticastFunc(uint32_t processId,uint32_t mltcstFuncId,uint32_t funcId);
static RpcResult_t IPC_unregisterFunctionInMulticastFunc(uint32_t processId,uint32_t mltcstFuncId,uint32_t funcId);
static RpcResult_t IPC_GetFuncListFromMulticastFunction(uint32_t mltcstFuncId, RpcList_t **funcList);
static RpcBool_t IPC_compareMulticastFuncId(RpcList_t *list,uint32_t mltcstFuncId);
static RpcBool_t IPC_compareFuncId(RpcList_t *list,uint32_t funcId);
#endif	/* USE_MULTICAST_RPC */

#ifdef	DEBUG
static void IPC_dumpDB(void);
#endif	/* DEBUG */

/* ----- DB APIs - Global Functions ----- */

extern RpcResult_t IPC_InitShmDB(RpcBool_t masterProcess) {
	void *startArea;uint32_t gapSize;
	uint32_t fd; void *addr; uint32_t size;RpcResult_t ret;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"IN IPC_InitShmDB PID:0x%x; masterProcess:%d;",RPC_GetPid(), masterProcess);
	if(masterProcess) {
		if(IPC_GetShmInfo(IPC_DATABASE_SHARED_MEM_NAME, &fd, &addr, &size) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
		if((fd < 0)||(addr == (void*)NULL)||(size == 0)) {
			return RPC_FATAL_ERROR;
		}
		if(( ret = IPC_InitShmGapArea(fd, IPC_SHM_DATABASE_GAP_SIZE)) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
		if((ret = IPC_InitShmAllocArea(fd, IPC_SHM_DATABASE_MEM_SIZE, IPC_SHM_DATABASE_NUM_OF_DEV, IPC_SHM_DATAABSE_MIN_SIZE, IPC_SHM_DATABASE_RATE_OF_MAGNIFY)) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
		if((ret = IPC_GetShmGapData(fd,&startArea,&gapSize)) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
		IpcDBManage = (IpcDBManage_t*)startArea;
		IpcDBManage->funcDB = (RpcList_t*)NULL;
		IpcDBManage->skeltonDB = (RpcList_t*)NULL;
		IpcDBManage->hashRandTable = (uint32_t*)NULL;
		IpcDBManage->funcDBHashTable = (RpcHashEntry_t*)NULL;
#ifdef	USE_MULTICAST_RPC
		IpcDBManage->mltcstFuncDB = (IpcMltcstFuncDB_t*)NULL;
#endif	/* USE_MULTICAST_RPC */
		if(RPC_MutexAttrInit(&(IpcDBManage->mutexAttr)) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
#ifdef	_LINUX_
		if(RPC_MutexAttrSetType(&(IpcDBManage->mutexAttr), PTHREAD_MUTEX_ADAPTIVE_NP) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
#else	/* _LINUX_ */
		if(RPC_MutexAttrSetType(&(IpcDBManage->mutexAIpcHashEntry_tttr), PTHREAD_MUTEX_RECURSIVE) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
			}
	#endif	/* _LINUX_ */
		if(RPC_MutexAttrSetPshared(&(IpcDBManage->mutexAttr), PTHREAD_PROCESS_SHARED) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
		if(RPC_InitMutex(&(IpcDBManage->mutexId),&(IpcDBManage->mutexAttr)) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
		IpcDatabaseSharedMemId = fd;
	}
	else {
		if(IPC_GetShmInfo(IPC_DATABASE_SHARED_MEM_NAME, &fd, &addr, &size) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
		if((ret = IPC_GetShmGapData(fd,&startArea,&gapSize)) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
		IpcDBManage = (IpcDBManage_t*)startArea;
		IpcDatabaseSharedMemId = fd;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG3," NOW CALL IPC_InitShmHash");
	if((ret = IPC_InitShmHash(masterProcess)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_InitShmHash RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG3," NOW CALL IPC_InitFuncDB");
	if((ret = IPC_InitFuncDB(masterProcess)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_InitFuncDB RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG3," NOW CALL IPC_InitSkeltonDB");
	if((ret = IPC_InitSkeltonDB(masterProcess)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_InitSkeltonDB RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError;
	}
#ifdef	USE_MULTICAST_RPC
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG3," NOW CALL IPC_initMulticastFuncDB");
	if((ret = IPC_initMulticastFuncDB(masterProcess)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_initMulticastFuncDB RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError;
	}
#endif	/* USE_MULTICAST_RPC */
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"OUR IPC_InitShmDB PID:0x%x; IpcDBManage:0x%x;",RPC_GetPid(),IpcDBManage);
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"    funcDB:0x%x; skeltonDB:0x%x; hashRandtable:0x%x; funcDBHashTable:0x%x;",
//		IpcDBManage->funcDB, IpcDBManage->skeltonDB, IpcDBManage->hashRandTable, IpcDBManage->funcDBHashTable);
	return RPC_SUCCESS;

goError:
	(void)IPC_DettachSharedMem();
	(void)IPC_DestroySharedMem();
	return ret;
}

//RpcResult_t IPC_RegisterFuncDBEntry(uint32_t funcId, uint32_t processId, uint16_t accessDevice, uint16_t accessProcess, IPC_SkeltonFunc_t func,IPC_SkeltonCancelFunc_t cancelFunc) {
extern RpcResult_t IPC_RegisterFuncDBEntry(uint32_t funcId, uint32_t processId, IPC_SkeltonFunc_t func,IPC_SkeltonCancelFunc_t cancelFunc) {
	IpcFuncDBEntry_t *entry;RpcResult_t ret;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"IN IPC_RegisterFuncDBEntry funcId:0x%x; processId:0x%x; func:0x%x; cancelFunc:0x%x;",funcId,processId,func,cancelFunc);
	if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
		return RPC_NOT_READY;
	}
	if((ret = RPC_MutexLock(&(IpcDBManage->mutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if(RPC_SearchListEntryById(IpcDBManage->funcDB,funcId,IPC_compareFuncDBByFuncId) != NULL) {
		(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
		return RPC_PARAM_ERROR;
	}
	if((entry = (IpcFuncDBEntry_t*)RPC_AllocListData(&(IpcDBManage->funcDB),sizeof(IpcFuncDBEntry_t),IpcDatabaseSharedMemId,RPC_ShmAllocMemWrapper,RPC_ShmFreeMemWrapper)) == (IpcFuncDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
		return RPC_FATAL_ERROR;
	}
	entry->funcId = funcId;
	entry->processId = processId;
//	if(accessDevice == (uint16_t)DEVICE_TYPE_UNKNOWN)
//		entry->accessDeviceType = (uint16_t)(((uint32_t)DEVICE_TYPE_OWN_DEV)|((uint32_t)DEVICE_TYPE_OTHER_DEV));
//	else
//		entry->accessDeviceType = accessDevice;
//	if(accessProcess == (uint16_t)PROCESS_TYPE_UNKNOWN)
//		entry->accessProcessType = (uint16_t)(((uint32_t)PROCESS_TYPE_OWN_PRO)|((uint32_t)PROCESS_TYPE_OTHER_PRO));
//	else
//		entry->accessProcessType = accessProcess;
	entry->skeltonFunc = func;
	entry->cancelFunc = cancelFunc;
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1," Entry:0x%x; funcId:%d; processId:%d; func:0x%x; cancelFunc:0x%x;",entry,entry->funcId,entry->processId,entry->skeltonFunc,entry->cancelFunc);
//	IPC_dumpDB();
	if((ret = IPC_addEntryToFuncDBHash(entry)) != RPC_SUCCESS) {
		RPC_SearchAndFreeListData(&(IpcDBManage->funcDB),funcId,IpcDatabaseSharedMemId,IPC_compareFuncDBByFuncId,RPC_ShmFreeMemWrapper);
		(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
		return ret;
	}
	(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_RegisterFuncDBEntry");
	return RPC_SUCCESS;
}

extern RpcResult_t IPC_SerachProcessIdFromFuncDB(uint32_t funcId,uint32_t *processId) {
	IpcFuncDBEntry_t *entry;RpcResult_t ret;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG2,"IN IPC_SerachProcessIdFromFuncDB PID:0x%x; funcId:0x%x;",RPC_GetPid(),funcId);
	if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
		return RPC_NOT_READY;
	}
	if((ret = RPC_MutexLock(&(IpcDBManage->mutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((entry = IPC_searchEntryFromFuncDBHash(funcId)) == (IpcFuncDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
		return RPC_PARAM_ERROR;
	}
	*processId = entry->processId;
	(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG2,"OUT IPC_SerachProcessIdFromFuncDB PID:0x%x; processId:0x%x;",RPC_GetPid(),*processId);
	return RPC_SUCCESS;
}

//extern RpcResult_t IPC_SearchFunctionFromFuncDB(uint32_t funcId,IPC_SkeltonFunc_t *func,IPC_SkeltonCancelFunc_t *cancelFunc,uint16_t *accessProcessType, uint16_t *accessDeviceType) {
extern RpcResult_t IPC_SearchFunctionFromFuncDB(uint32_t funcId,IPC_SkeltonFunc_t *func,IPC_SkeltonCancelFunc_t *cancelFunc) {
	IpcFuncDBEntry_t *entry;RpcResult_t ret;

	if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
		return RPC_NOT_READY;
	}
	if((ret = RPC_MutexLock(&(IpcDBManage->mutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((entry = IPC_searchEntryFromFuncDBHash(funcId)) == (IpcFuncDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
		return RPC_PARAM_ERROR;
	}
	*func = entry->skeltonFunc;
	*cancelFunc = entry->cancelFunc;
//	*accessProcessType = entry->accessProcessType;
//	*accessDeviceType = entry->accessDeviceType;
	(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
	return RPC_SUCCESS;
}

extern RpcResult_t IPC_DeleteFuncDBEntry(uint32_t funcId) {
	RpcResult_t ret;

	if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
		return RPC_NOT_READY;
	}
	if((ret = RPC_MutexLock(&(IpcDBManage->mutexId))) != RPC_SUCCESS) {
		return ret;
	}
	RPC_SearchAndFreeListData(&(IpcDBManage->funcDB),funcId,IpcDatabaseSharedMemId,IPC_compareFuncDBByFuncId,RPC_ShmFreeMemWrapper);
	if((ret = IPC_deleteEntryFromFuncDBHash(funcId)) != RPC_SUCCESS) {
		(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
		return ret;		
	}
	(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
	return RPC_SUCCESS;
}

//extern RpcResult_t IPC_RegisterSkeltonDBEntry(uint32_t processId,RpcTaskID_t taskId, uint32_t queId,IpcProcessType_t processType) {
extern RpcResult_t IPC_RegisterSkeltonDBEntry(uint32_t processId,RpcTaskID_t taskId, uint32_t queId) {
	IpcSkeltonDBEntry_t *entry;RpcResult_t ret;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB, RPC_LOG_LEVEL_DEBUG1, "IN IPC_RegisterSkeltonDBEntry processId:0x%x; taskId:0x%Lx; queId:0x%x; ipcDBMange:0x%x;",
//		processId, taskId, queId,IpcDBManage);
	if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
		return RPC_NOT_READY;
	}
	if((ret = RPC_MutexLock(&(IpcDBManage->mutexId))) != RPC_SUCCESS) {
		return ret;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB, RPC_LOG_LEVEL_DEBUG1, "CALL RPC_SearchListEntryById ipDBManage:0x%x; IPC_compareSkeltonDBByProcessId+0x%x;",
//		IpcDBManage, IPC_compareSkeltonDBByProcessId);	
	if(RPC_SearchListEntryById(IpcDBManage->skeltonDB,processId,IPC_compareSkeltonDBByProcessId) != NULL) {
		(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
		return RPC_PARAM_ERROR;	
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB, RPC_LOG_LEVEL_DEBUG1, "CALL RPC_AllocListData ");	
	if((entry = (IpcSkeltonDBEntry_t*)RPC_AllocListData(&(IpcDBManage->skeltonDB),sizeof(IpcSkeltonDBEntry_t),IpcDatabaseSharedMemId,RPC_ShmAllocMemWrapper,RPC_ShmFreeMemWrapper)) == (IpcSkeltonDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
		return RPC_FATAL_ERROR;	
	}
	entry->processId = processId;
	entry->taskId = taskId;
	entry->queId = queId;
	//	entry->processType = processType;
	//	IPC_dumpDB();
	(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB, RPC_LOG_LEVEL_DEBUG1, "OUT IPC_RegisterSkeltonDBEntry ENTRY:0x%x;",entry);
	return RPC_SUCCESS;
}

extern RpcResult_t IPC_SearchSkeltonDB(uint32_t processId, RpcTaskID_t *taskId,uint32_t *queId) {
	IpcSkeltonDBEntry_t *entry;RpcResult_t ret;

	if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
		return RPC_NOT_READY;
	}
	if((ret = RPC_MutexLock(&(IpcDBManage->mutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((entry = (IpcSkeltonDBEntry_t*)RPC_SearchListEntryById(IpcDBManage->skeltonDB,processId,IPC_compareSkeltonDBByProcessId)) == (IpcSkeltonDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
		return RPC_PARAM_ERROR;
	}
	*taskId = entry->taskId;
	*queId = entry->queId;
	(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
	return RPC_SUCCESS;
}

extern RpcResult_t IPC_DeleteSkeltonDBEntry(uint32_t processId) {
	RpcResult_t ret;

	if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
		return RPC_FATAL_ERROR;
	}
	if((ret = RPC_MutexLock(&(IpcDBManage->mutexId))) != RPC_SUCCESS) {
		return ret;
	}
	RPC_SearchAndFreeListData(&(IpcDBManage->skeltonDB),processId,IpcDatabaseSharedMemId,IPC_compareSkeltonDBByProcessId,RPC_ShmFreeMemWrapper);
	(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
	return RPC_SUCCESS;
}

#if	0
extern RpcResult_t IPC_registerProcessData(uint32_t processId,IpcProcessType_t processType) {
	return IPC_registerSkeltonDBEntry(processId,0,0,processType);
}

extern RpcResult_t IPC_delegateProcessData(uint32_t processId) {
	return IPC_DeleteSkeltonDBEntry(processId);
}

extern RpcResult_t IPC_searchProcessType(uint32_t processId, IpcProcessType_t *processType) {
	IpcSkeltonDBEntry_t *entry;RpcResult_t ret;

	if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
		return RPC_NOT_READY;
	}
	if((ret = RPC_MutexLock(&(IpcDBManage->mutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((entry = IPC_SearchEntryFromSkeltonDBList(processId)) == (IpcSkeltonDBEntry_t*)NULL) {
		(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
		return RPC_PARAM_ERROR;		
	}
	*processType = entry->processType;
	(void)RPC_MutexUnlock(&(IpcDBManage->mutexId));
	return RPC_SUCCESS;
}
#endif	/* 0 */

#ifdef	USE_MULTICAST_RPC

extern RpcResult_t IPC_RegisterMulticastFunc(uint32_t mltcstFuncId) {
	uint32_t pid;

	pid = RPC_GetPid();
	return IPC_registerMulticastFunction(pid,mltcstFuncId);
}

extern RpcResult_t IPC_SignupMulticastFunc(uint32_t mltcstFuncId, uint32_t funcId) {
	uint32_t pid;

	pid = RPC_GetPid();
	return IPC_registerFunctionInMulticastFunc(pid, mltcstFuncId, funcId);
}

extern RpcResult_t IPC_ResignMulticastFunc(uint32_t mltcstFuncId, uint32_t funcId) {
	uint32_t pid;

	pid = RPC_GetPid();
	return IPC_unregisterFunctionInMulticastFunc(pid, mltcstFuncId, funcId);
}

extern RpcResult_t IPC_UnregisterMulticastFunc(uint32_t mltcstFuncId) {
	uint32_t pid;

	pid = RPC_GetPid();
	return IPC_unregisterMulticastFunction(pid, mltcstFuncId);
}

extern RpcResult_t IPC_GetFuncListByMltcstFuncId(uint32_t mltcstFuncId, RpcList_t **funcList) {
	return IPC_GetFuncListFromMulticastFunction(mltcstFuncId,funcList);
}

extern void IPC_FreeFuncList(RpcList_t *funcList) {
	while(funcList != (RpcList_t*)NULL) {
		RPC_FreeListData(&funcList,(void*)(funcList->entry),0,RPC_LclFreeMemWrapper);
	}
}

#endif	/* USE_MULTICAST_RPC */

/* ----- INTERNAL FUNCTIONS ----- */

static RpcResult_t IPC_InitShmHash(RpcBool_t masterProcess) {
	static RpcBool_t initHashFlag = RPC_FALSE;
	uint32_t *hashRandTable;RpcResult_t ret;
//	int fd;void *addr;uint32_t size;
	uint32_t i,j;struct timeval curTime;uint32_t errCode;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"IN IPC_InitHash");
	if(initHashFlag) {
		return RPC_SUCCESS;
	}
	initHashFlag = RPC_TRUE;
	if(masterProcess) {
//		if(IPC_GetShmInfo(IPC_DATABASE_SHARED_MEM_NAME, &fd, &addr, &size) != RPC_SUCCESS) {
//			return RPC_FATAL_ERROR;
//		}
		if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
			return RPC_FATAL_ERROR;
		}
		if((hashRandTable = (uint32_t*)IPC_AllocShmMem(IpcDatabaseSharedMemId, IPC_HASH_RAND_NUM_SIZE_OF_TBL_NUM*IPC_HASH_RAND_NUM_SIZE_OF_TABLE*sizeof(uint32_t))) == (void*)NULL) {
			return RPC_FATAL_ERROR;
		}
		if((ret = RPC_GetTimeOfDay(&curTime,NULL,&errCode)) != RPC_SUCCESS) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN GetTimeOfDay:%s; errCode:%d;",RPC_LogConvertResultCode(ret),errCode);
			return ret;
		}
		RPC_Srand((uint32_t)(curTime.tv_sec + curTime.tv_usec));
		for(i = 0; i < IPC_HASH_RAND_NUM_SIZE_OF_TBL_NUM;i++) {
			for(j = 0;j < IPC_HASH_RAND_NUM_SIZE_OF_TABLE;j++) {
				hashRandTable[i*IPC_HASH_RAND_NUM_SIZE_OF_TABLE + j] = RPC_Rand();
			}
		}
		IpcDBManage->hashRandTable = hashRandTable;
		RPC_RegisterHashTable(hashRandTable);
	}
	else {
		RPC_RegisterHashTable(IpcDBManage->hashRandTable);
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_InitHash");
	return RPC_SUCCESS;
}

static RpcResult_t IPC_InitFuncDB(RpcBool_t masterProcess) {
//	int fd;void *addr;uint32_t size;
	uint32_t i;RpcHashEntry_t *funcDBHashTable;

	if(masterProcess) {
//		if(IPC_GetShmInfo(IPC_DATABASE_SHARED_MEM_NAME, &fd, &addr, &size) != RPC_SUCCESS) {
//			return RPC_FATAL_ERROR;
//		}
		if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
			return RPC_FATAL_ERROR;
		}
		if((funcDBHashTable = (RpcHashEntry_t*)IPC_AllocShmMem(IpcDatabaseSharedMemId, IPC_SHM_DATABASE_FUNC_DB_HASH_TABLE*sizeof(RpcHashEntry_t))) == (RpcHashEntry_t*)NULL) {
			return RPC_FATAL_ERROR;
		}
		for(i = 0;i < IPC_SHM_DATABASE_FUNC_DB_HASH_TABLE;i++) {
			funcDBHashTable[i].entry = (void *)NULL;
			funcDBHashTable[i].usedFlag = RPC_FALSE;
		}
		IpcDBManage->funcDBHashTable = funcDBHashTable;
	}
	return RPC_SUCCESS;
}

static RpcResult_t IPC_InitSkeltonDB(RpcBool_t masterProcess) {
	if(masterProcess) {
	}
	return RPC_SUCCESS;
}

static RpcResult_t IPC_addEntryToFuncDBHash(IpcFuncDBEntry_t *entry) {
//	uint32_t hashId;RpcHashEntry_t *hashTbl;int i;

	if(entry->funcId == IPC_SHM_DATABASE_FUNC_DB_ILLEGAL_FUNC_ID)
		return RPC_PARAM_ERROR;
	return RPC_AddHashEntry((void*)IpcDBManage->funcDBHashTable,(void*)entry,(void*)&(entry->funcId),sizeof(entry->funcId),IPC_SHM_DATABASE_FUNC_DB_HASH_TABLE);
}

static RpcResult_t IPC_deleteEntryFromFuncDBHash(uint32_t funcId) {
//	uint32_t hashId,nextId;RpcHashEntry_t *hashTbl,*nextTbl;int i;

	if(funcId == IPC_SHM_DATABASE_FUNC_DB_ILLEGAL_FUNC_ID)
		return RPC_PARAM_ERROR;
	return RPC_DeleteHashEntry((void*)IpcDBManage->funcDBHashTable,(void*)&funcId,sizeof(funcId),IPC_SHM_DATABASE_FUNC_DB_HASH_TABLE,IPC_compareFuncDBbyHash);
}

static IpcFuncDBEntry_t *IPC_searchEntryFromFuncDBHash(uint32_t funcId) {
//	uint32_t hashId;RpcHashEntry_t *hashTbl;int i;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG2,"IN IPC_searchEntryFromFuncDBHash PID:0x%x; funcId:0x%x;(ADDR:0x%x)", RPC_GetPid(), funcId,&funcId);
	if(funcId == IPC_SHM_DATABASE_FUNC_DB_ILLEGAL_FUNC_ID)
		return (IpcFuncDBEntry_t*)NULL;
	return (IpcFuncDBEntry_t*)RPC_SearchEntryByHash((void*)(IpcDBManage->funcDBHashTable),(void*)&funcId,sizeof(funcId),IPC_SHM_DATABASE_FUNC_DB_HASH_TABLE,IPC_compareFuncDBbyHash);
}

static RpcBool_t IPC_compareFuncDBbyHash(void *entry, uint8_t *val, uint32_t valSize) {
#if	0
	uint32_t compVal;

#ifdef	__BYTE_ORDER
#if	__BYTE_ORDER == __BIG_ENDIAN
	compVal = (uint32_t)(((*(val))<<24)+((*(val+1))<<16)+((*(val+2))<<8)+(*(val+3)));
#elif	__BYTE_ORDER == __LITTLE_ENDIAN
	compVal = (uint32_t)(((*(val+3))<<24)+((*(val+2))<<16)+((*(val+1))<<8)+(*val));
#else
	unknown endian, gcc will fail here.
#endif
	error !
#endif
	if(valSize != sizeof(uint32_t))
		return RPC_FALSE;
	if(((IpcFuncDBEntry_t*)entry)->funcId == compVal)
		return RPC_TRUE;
	else
		return RPC_FALSE;
#else	/* 0 */
	return (memcmp((void*)&(((IpcFuncDBEntry_t*)entry)->funcId),val,valSize)==0)?RPC_TRUE:RPC_FALSE; 
#endif	/* 0 */
}

static RpcBool_t IPC_compareFuncDBByFuncId(RpcList_t *list,uint32_t funcId) {
	if(((IpcFuncDBEntry_t*)list->entry)->funcId == funcId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}

static RpcBool_t IPC_compareSkeltonDBByProcessId(RpcList_t *list,uint32_t processId) {
	if(((IpcSkeltonDBEntry_t*)list->entry)->processId == processId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}

#ifdef	USE_MULTICAST_RPC

static RpcResult_t IPC_initMulticastFuncDB(RpcBool_t masterProcess) {
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG2,"IN IPC_initMulticastFuncDB masterProcess:%d;",masterProcess);
	if(masterProcess) {
		if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
			return RPC_NOT_READY;
		}
		if(IpcDBManage->mltcstFuncDB != (IpcMltcstFuncDB_t*)NULL) {
			return RPC_TRUE;
		}
		if((IpcDBManage->mltcstFuncDB = IPC_AllocShmMem(IpcDatabaseSharedMemId,sizeof(IpcMltcstFuncDB_t))) == (IpcMltcstFuncDB_t*)NULL) {
			return RPC_NO_MORE_RESOURCE;
		}
		(void)memset((void*)(IpcDBManage->mltcstFuncDB),0,sizeof(IpcMltcstFuncDB_t));
		if(RPC_MutexAttrInit(&(IpcDBManage->mltcstFuncDB->mltcstMutexAttr)) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
#ifdef	_LINUX_
		if(RPC_MutexAttrSetType(&(IpcDBManage->mltcstFuncDB->mltcstMutexAttr), PTHREAD_MUTEX_ADAPTIVE_NP) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
#else	/* _LINUX_ */
		if(RPC_MutexAttrSetType(&(IpcDBManage->mltcstFuncDB->mltcstMutexAttr), PTHREAD_MUTEX_RECURSIVE) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
#endif	/* _LINUX_ */
		if(RPC_MutexAttrSetPshared(&(IpcDBManage->mltcstFuncDB->mltcstMutexAttr), PTHREAD_PROCESS_SHARED) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
		if(RPC_InitMutex(&(IpcDBManage->mltcstFuncDB->mltcstMutexId),&(IpcDBManage->mltcstFuncDB->mltcstMutexAttr)) != RPC_SUCCESS) {
			return RPC_FATAL_ERROR;
		}
		IpcDBManage->mltcstFuncDB->mltcstFuncListTop = (RpcList_t*)NULL;
	}
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG2,"OUT IPC_initMulticastFuncDB");
	return RPC_SUCCESS;
}

static RpcResult_t IPC_registerMulticastFunction(uint32_t processId,uint32_t mltcstFuncId) {
	RpcResult_t ret;IpcMltcstFuncDB_t *mltcstFuncDB;IpcMltcstFuncList_t *funcList;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"IN IPC_registerMulticastFunction processId:0x%x; mltcstFuncId:0x%x;",
//		processId,mltcstFuncId);
	if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
		return RPC_NOT_READY;
	}
	if(IpcDBManage->mltcstFuncDB == (IpcMltcstFuncDB_t*)NULL) {
		return RPC_FATAL_ERROR;
	}
	mltcstFuncDB = IpcDBManage->mltcstFuncDB;
	if((ret = RPC_MutexLock(&(mltcstFuncDB->mltcstMutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((funcList = (IpcMltcstFuncList_t*)RPC_SearchListEntryById(mltcstFuncDB->mltcstFuncListTop,mltcstFuncId,IPC_compareMulticastFuncId)) == (IpcMltcstFuncList_t*)NULL) {
		if((funcList = (IpcMltcstFuncList_t*)RPC_AllocListData(&(mltcstFuncDB->mltcstFuncListTop),sizeof(IpcMltcstFuncList_t),IpcDatabaseSharedMemId,RPC_ShmAllocMemWrapper,RPC_ShmFreeMemWrapper)) == (IpcMltcstFuncList_t*)NULL) {
			(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
			return RPC_NO_MORE_RESOURCE;			
		}
		funcList->mltcstFuncId = mltcstFuncId;
		funcList->regProcessId = processId;
		funcList->mltcstFuncEntryTop = (RpcList_t*)NULL;
	}
	(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_registerMulticastFunction ");
	return RPC_SUCCESS;
}

static RpcResult_t IPC_unregisterMulticastFunction(uint32_t processId, uint32_t mltcstFuncId) {
	RpcResult_t ret;IpcMltcstFuncDB_t *mltcstFuncDB;IpcMltcstFuncList_t *funcList;RpcList_t *entry;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"IN IPC_unregisterMulticastFunction processId:0x%x; mltcstFuncId:0x%x;",
//		processId, mltcstFuncId);
	if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
		return RPC_NOT_READY;
	}
	if(IpcDBManage->mltcstFuncDB == (IpcMltcstFuncDB_t*)NULL) {
		return RPC_FATAL_ERROR;
	}
	mltcstFuncDB = IpcDBManage->mltcstFuncDB;
	if((ret = RPC_MutexLock(&(mltcstFuncDB->mltcstMutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((funcList = (IpcMltcstFuncList_t*)RPC_SearchListEntryById(mltcstFuncDB->mltcstFuncListTop,mltcstFuncId,IPC_compareMulticastFuncId)) == (IpcMltcstFuncList_t*)NULL) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_ERROR,"NOT FIND MULTICAST FUNCTION MULTICAST-FUNC:0x%x;",
			mltcstFuncId);
		(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
		return RPC_PARAM_ERROR;
	}
	if(funcList->regProcessId != processId) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_ERROR,"FAIL IN FREE MULTICAST FUNCTION processId:0x%x; multicastFuncId:0x%;",
			processId,mltcstFuncId);
		(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
		return RPC_PARAM_ERROR;
	}
	while((entry = funcList->mltcstFuncEntryTop) != (RpcList_t*)NULL) {
		RPC_FreeListData(&(funcList->mltcstFuncEntryTop),(void*)(entry->entry),IpcDatabaseSharedMemId,RPC_ShmFreeMemWrapper);
	}
	RPC_FreeListData(&(mltcstFuncDB->mltcstFuncListTop),(void*)funcList,IpcDatabaseSharedMemId,RPC_ShmFreeMemWrapper);
	(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_unregisterMulticastFunction ");
	return RPC_SUCCESS;
}

static RpcResult_t IPC_registerFunctionInMulticastFunc(uint32_t processId,uint32_t mltcstFuncId,uint32_t funcId) {
	RpcResult_t ret;IpcMltcstFuncDB_t *mltcstFuncDB;IpcMltcstFuncList_t *funcList;IpcMltcstFuncEntry_t *entry;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"IN IPC_registerFunctionInMulticastFunc processId:0x%x; mltcstFuncId:0x%x;",
//		processId,mltcstFuncId);
	if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
		return RPC_NOT_READY;
	}
	if(IpcDBManage->mltcstFuncDB == (IpcMltcstFuncDB_t*)NULL) {
		return RPC_FATAL_ERROR;
	}
	mltcstFuncDB = IpcDBManage->mltcstFuncDB;
	if((ret = RPC_MutexLock(&(mltcstFuncDB->mltcstMutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((funcList = (IpcMltcstFuncList_t*)RPC_SearchListEntryById(mltcstFuncDB->mltcstFuncListTop,mltcstFuncId,IPC_compareMulticastFuncId)) == (IpcMltcstFuncList_t*)NULL) {
		if((funcList = (IpcMltcstFuncList_t*)RPC_AllocListData(&(mltcstFuncDB->mltcstFuncListTop),sizeof(IpcMltcstFuncList_t),IpcDatabaseSharedMemId,RPC_ShmAllocMemWrapper,RPC_ShmFreeMemWrapper)) == (IpcMltcstFuncList_t*)NULL) {
			(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
			return RPC_NO_MORE_RESOURCE;			
		}
		funcList->mltcstFuncId = mltcstFuncId;
		funcList->regProcessId = processId;
		funcList->mltcstFuncEntryTop = (RpcList_t*)NULL;
	}
	if((entry = (IpcMltcstFuncEntry_t*)RPC_SearchListEntryById(funcList->mltcstFuncEntryTop,funcId,IPC_compareFuncId)) == (IpcMltcstFuncEntry_t*)NULL) {
		if((entry = (IpcMltcstFuncEntry_t*)RPC_AllocListData(&(funcList->mltcstFuncEntryTop),sizeof(IpcMltcstFuncEntry_t),IpcDatabaseSharedMemId,RPC_ShmAllocMemWrapper,RPC_ShmFreeMemWrapper)) == (IpcMltcstFuncEntry_t*)NULL) {
			(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
			return RPC_NO_MORE_RESOURCE;			
		}
		entry->funcId = funcId;
		entry->processId = processId;
	}
	else {
		if(entry->processId != processId) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_ERROR,"FAIL IN REGISTER processId:0x%x; mltcstFuncId:0x%; funcId:0x%x;",
				processId, mltcstFuncId,funcId);
			(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
			return RPC_PARAM_ERROR;
		}
		else {
			entry->funcId = funcId;
		}
	}
	(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_registerFunctionInMulticastFunc ");
	return RPC_SUCCESS;
}

static RpcResult_t IPC_unregisterFunctionInMulticastFunc(uint32_t processId,uint32_t mltcstFuncId,uint32_t funcId) {
	RpcResult_t ret;IpcMltcstFuncDB_t *mltcstFuncDB;IpcMltcstFuncList_t *funcList;IpcMltcstFuncEntry_t *entry;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"IN IPC_unregisterFunctionInMulticastFunc processId:0x%x; mltcstFuncId:0x%x; callFuncId:0x%x;",
//		processId, mltcstFuncId,funcId);
	if((IpcDatabaseSharedMemId == -1)||(IpcDBManage == (IpcDBManage_t*)NULL)) {
		return RPC_NOT_READY;
	}
	if(IpcDBManage->mltcstFuncDB == (IpcMltcstFuncDB_t*)NULL) {
		return RPC_FATAL_ERROR;
	}
	mltcstFuncDB = IpcDBManage->mltcstFuncDB;
	if((ret = RPC_MutexLock(&(mltcstFuncDB->mltcstMutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((funcList = (IpcMltcstFuncList_t*)RPC_SearchListEntryById(mltcstFuncDB->mltcstFuncListTop,mltcstFuncId,IPC_compareMulticastFuncId)) == (IpcMltcstFuncList_t*)NULL) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_ERROR,"NOT FIND MULTICAST FUNCTION MULTICAST-FUNC:0x%x;",
			mltcstFuncId);
		(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
		return RPC_PARAM_ERROR;
	}
	if((entry = (IpcMltcstFuncEntry_t*)RPC_SearchListEntryById(funcList->mltcstFuncEntryTop,funcId,IPC_compareFuncId)) == (IpcMltcstFuncEntry_t*)NULL) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_ERROR,"NOT FIND REGISTERED FUNCTION FUNC:0x%x;",
			funcId);
		(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
		return RPC_PARAM_ERROR;

	}
	if(entry->processId != processId) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_ERROR,"FAIL IN UNREGISTER processId:0x%x; mltcstFuncId:0x%; funcId:0x%x;",
			processId, mltcstFuncId,funcId);
		(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
		return RPC_PARAM_ERROR;
	}
	RPC_FreeListData(&(funcList->mltcstFuncEntryTop),(void*)entry,IpcDatabaseSharedMemId,RPC_ShmFreeMemWrapper);
	(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_unregisterFunctionInMulticastFunc ");
	return RPC_SUCCESS;
}

static RpcResult_t IPC_GetFuncListFromMulticastFunction(uint32_t mltcstFuncId, RpcList_t **newFuncList) {
	RpcResult_t ret;IpcMltcstFuncDB_t *mltcstFuncDB;IpcMltcstFuncList_t *funcList;IpcMltcstFuncEntry_t *newEntry;
	RpcList_t *entryList;

//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"IN IPC_GetFuncListFromMulticastFunction mltcstFuncId:0x%x;",mltcstFuncId);
	*newFuncList = (RpcList_t*)NULL;
	if(IpcDBManage == (IpcDBManage_t*)NULL) {
		return RPC_NOT_READY;
	}
	if(IpcDBManage->mltcstFuncDB == (IpcMltcstFuncDB_t*)NULL) {
		return RPC_FATAL_ERROR;
	}
	mltcstFuncDB = IpcDBManage->mltcstFuncDB;
	if((ret = RPC_MutexLock(&(mltcstFuncDB->mltcstMutexId))) != RPC_SUCCESS) {
		return ret;
	}
	if((funcList = (IpcMltcstFuncList_t*)RPC_SearchListEntryById(mltcstFuncDB->mltcstFuncListTop,mltcstFuncId,IPC_compareMulticastFuncId)) == (IpcMltcstFuncList_t*)NULL) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_ERROR,"NOT FIND MULTICAST FUNCTION MULTICAST-FUNC:0x%x;",
			mltcstFuncId);
		(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
		return RPC_PARAM_ERROR;
	}
	for(entryList = funcList->mltcstFuncEntryTop; entryList != (RpcList_t*)NULL; entryList = entryList->next) {
		if((newEntry = (IpcMltcstFuncEntry_t*)RPC_AllocListData(newFuncList,sizeof(IpcMltcstFuncEntry_t),0,RPC_LclAllocMemWrapper,RPC_LclFreeMemWrapper)) == (IpcMltcstFuncEntry_t*)NULL) {
			while(*newFuncList != (RpcList_t*)NULL) {
				RPC_FreeListData(newFuncList,(void*)((*newFuncList)->entry),0,RPC_LclFreeMemWrapper);
			}
			(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_ERROR,"CAN NOT COPY MULTICAST FUNCTIONS LIST, AS NOT MORE MEMORY");
			(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
			return RPC_NO_MORE_RESOURCE;			
		}
		newEntry->funcId = ((IpcMltcstFuncEntry_t*)(entryList->entry))->funcId;
		newEntry->processId = ((IpcMltcstFuncEntry_t*)(entryList->entry))->processId;
	}
	(void)RPC_MutexUnlock(&(mltcstFuncDB->mltcstMutexId));
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_GetFuncListFromMulticastFunction FuncList:0x%x; ",*funcList);
	return RPC_SUCCESS;
}

static RpcBool_t IPC_compareMulticastFuncId(RpcList_t *list,uint32_t mltcstFuncId) {
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG3,"IN IPC_compareMulticastFuncId FUNCID:0x%x; ORG:0x%x;",
//		mltcstFuncId, ((IpcMltcstFuncList_t*)list->entry)->mltcstFuncId);
	if(((IpcMltcstFuncList_t*)list->entry)->mltcstFuncId == mltcstFuncId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}

static RpcBool_t IPC_compareFuncId(RpcList_t *list,uint32_t funcId) {
//	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG3,"IN IPC_compareFuncId FUNCID:0x%x; ORG:0x%x;",
//		funcId, ((IpcMltcstFuncEntry_t*)list->entry)->funcId);
	if(((IpcMltcstFuncEntry_t*)list->entry)->funcId == funcId)
		return RPC_TRUE;
	else
		return RPC_FALSE;
}

#endif	/* USE_MULTICAST_RPC */

#ifdef	DEBUG
static void IPC_dumpDB(void) {
	RpcList_t *funcList;RpcList_t *skeltonList;RpcList_t *mDBList;

	if(IpcDBManage == NULL) {
		(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"DBMANGE:NULL\n");
		return;
	}
#if	__WORDSIZE == 64
	(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"--- DBManage:0x%Lx; funcDB:0x%Lx; skeltonDB:0x%Lx; hashRandTable:0x%Lx; funcDBHashTable:0x:%Lx;---\n",
			(uint64_t)IpcDBManage,(uint64_t)IpcDBManage->funcDB,(uint64_t)IpcDBManage->skeltonDB,(uint64_t)IpcDBManage->hashRandTable,(uint64_t)IpcDBManage->funcDBHashTable);
#else	/* __WORDSIZE */
	(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"--- DBManage:0x%x; funcDB:0x%x; skeltonDB:0x%x; hashRandTable:0x%x; funcDBHashTable:0x:%x;---\n",
			(uint32_t)IpcDBManage,(uint32_t)IpcDBManage->funcDB,(uint32_t)IpcDBManage->skeltonDB,(uint32_t)IpcDBManage->hashRandTable,(uint32_t)IpcDBManage->funcDBHashTable);
#endif	/* __WORDSIZE */
	(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"  -- FUNC DB --\n");
	for(funcList = IpcDBManage->funcDB;funcList != NULL;funcList = (RpcList_t*)funcList->next) {
#if	__WORDSIZE == 64
		(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"   funcId:%d; processId:%d; skelton:0x%Lx; cancel:0x%Lx; ",
				((IpcFuncDBEntry_t*)funcList->entry)->funcId,((IpcFuncDBEntry_t*)funcList->entry)->processId,(uint64_t)((IpcFuncDBEntry_t*)funcList->entry)->skeltonFunc,(uint64_t)((IpcFuncDBEntry_t*)funcList->entry)->cancelFunc);
		(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"  NEXT:0x%Lx;\n",(uint64_t)funcList->next);
#else	/* __WORDSIZE */
		(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"   funcId:%d; processId:%d; skelton:0x%x; cancel:0x%x; ",
				((IpcFuncDBEntry_t*)funcList->entry)->funcId,((IpcFuncDBEntry_t*)funcList->entry)->processId,(uint32_t)((IpcFuncDBEntry_t*)funcList->entry)->skeltonFunc,(uint32_t)((IpcFuncDBEntry_t*)funcList->entry)->cancelFunc);
		(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"  NEXT:0x%x;\n",(uint32_t)funcList->next);
#endif	/* __WORDSIZE */
	}
	(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"  -- SKELTON DB --\n");
	for(skeltonList = IpcDBManage->skeltonDB;skeltonList != NULL;skeltonList = (RpcList_t*)skeltonList->next) {
#if	__WORDSIZE == 64
		(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"   processId:%d; taskId:%Ld; queId:%d; ",
				((IpcSkeltonDBEntry_t*)skeltonList->entry)->processId,((IpcSkeltonDBEntry_t*)skeltonList->entry)->taskId,((IpcSkeltonDBEntry_t*)skeltonList->entry)->queId);
		(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"  NEXT:0x%Lx;\n",(uint64_t)skeltonList->next);
#else	/* __WORDSIZE */
		(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"   processId:%d; taskId:%d; queId:%d; ",
				((IpcSkeltonDBEntry_t*)skeltonList->entry)->processId,((IpcSkeltonDBEntry_t*)skeltonList->entry)->taskId,((IpcSkeltonDBEntry_t*)skeltonList->entry)->queId);
		(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"  NEXT:0x%x;\n",(uint32_t)skeltonList->next);
#endif	/* __WORDSIZE */
	}
#ifdef	USE_MULTICAST_RPC
	(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"  -- MULTICAST FUNC DB --\n");
	if(IpcDBManage->mltcstFuncDB != NULL) {
#if	__WORDSIZE == 64
		(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"   MutexID:0x%Lx; MutexAttr:0x%Lx FuncListTop:0x%Lx;\n",(uint64_t)(&(IpcDBManage->mltcstFuncDB->mltcstMutexId)),(uint64_t)(&(IpcDBManage->mltcstFuncDB->mltcstMutexAttr)),(uint64_t)(IpcDBManage->mltcstFuncDB->mltcstFuncListTop));
#else	/* __WORDSIZE */
		(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"   MutexID:0x%x; MutexAttr:0x%x FuncListTop:0x%x;\n",(uint32_t)(&(IpcDBManage->mltcstFuncDB->mltcstMutexId)),(uint32_t)(&(IpcDBManage->mltcstFuncDB->mltcstMutexAttr)),(uint32_t)(IpcDBManage->mltcstFuncDB->mltcstFuncListTop));
#endif	/* __WORDSIZE */
		for(mDBList = IpcDBManage->mltcstFuncDB->mltcstFuncListTop;mDBList != NULL;mDBList = (RpcList_t*)mDBList->next) {
#if	__WORDSIZE == 64
			(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"     mtlcstFuncId:0x%x; regProcessId:0x%x; FuncEntryTop:0x%Lx;\n",((IpcMltcstFuncList_t*)mDBList->entry)->mltcstFuncId, ((IpcMltcstFuncList_t*)mDBList->entry)->regProcessId, (uint64_t)(((IpcMltcstFuncList_t*)mDBList->entry)->mltcstFuncEntryTop));
#else	/* __WORDSIZE */
			(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"     mtlcstFuncId:0x%x; regProcessId:0x%x; FuncEntryTop:0x%x;\n",((IpcMltcstFuncList_t*)mDBList->entry)->mltcstFuncId, ((IpcMltcstFuncList_t*)mDBList->entry)->regProcessId, (uint32_t)(((IpcMltcstFuncList_t*)mDBList->entry)->mltcstFuncEntryTop));
#endif	/* __WORDSIZE */
			(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"        --- MULTICAST FUNC LIST ---\n");
			for(funcList = ((IpcMltcstFuncList_t*)mDBList->entry)->mltcstFuncEntryTop;funcList != NULL; funcList = funcList->next) {
				(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"          processId:0x%x; funcId:0x%x;\n",((IpcMltcstFuncEntry_t*)funcList->entry)->processId,((IpcMltcstFuncEntry_t*)funcList->entry)->funcId);
			}
		}
	}
	else {
		(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"   DATA BASE IS NULL\n");
	}
#endif	/*USE_MULTICAST_RPC */
	(void)RPC_LogPrintNomark(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"--- END ---\n");
}
#endif	/* DEBUG */

/* ----- TEST Functions ----- */

#ifdef	DEBUG

#include	"rpcFunc.h"

static int32_t skeltonFunc1(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut);
static int32_t skeltonFunc2(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut);
static int32_t skeltonFunc3(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut);
static int32_t skeltonFunc4(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut);
static int32_t skeltonFunc5(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut);
static int32_t skeltonFunc6(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOu);
static int32_t cancelFunc1(uint32_t processId, uint32_t seqNum);
static int32_t cancelFunc2(uint32_t processId, uint32_t seqNum);
static int32_t cancelFunc3(uint32_t processId, uint32_t seqNum);
static int32_t cancelFunc4(uint32_t processId, uint32_t seqNum);
static int32_t cancelFunc5(uint32_t processId, uint32_t seqNum);
static int32_t cancelFunc6(uint32_t processId, uint32_t seqNum);

static int32_t WaveDice(void);
RpcResult_t DBTest(void);

RpcResult_t DBTest(void) {
	RpcResult_t ret;int i,j;int dice;
	IpcSkeltonDBEntry_t skelDB[20];
	IpcFuncDBEntry_t funcDB[20];uint32_t processId,queId;//void *func,*cancelFunc;
	RpcTaskID_t taskId;
	int32_t (*func)(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut);
	int32_t (*cancelFunc)(uint32_t processId, uint32_t seqNum);
//	uint16_t accessProcessType;uint16_t accessDeviceType;

#if	0
	fprintf(stdout,"STEP1\n");
	if((ret = IPC_InitSharedMem(RPC_TRUE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_InitSharedMem ret:%s;",RPC_LogConvertResultCode(ret));
		return ret;
	}
//	fprintf(stdout,"STEP2\n");
	if((ret = IPC_AttachSharedMem()) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_AttachSharedMem ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DestroySharedMem();
		return ret;
	}
	if((ret = IPC_InitShmDB(RPC_TRUE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_InitShmDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;
	}
	if((ret = IPC_InitShmHash(RPC_TRUE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_InitShmHash ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;
	}
	if((ret = IPC_InitFuncDB(RPC_TRUE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_InitFuncDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;
	}
	if((ret = IPC_InitSkeltonDB()) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_InitSkeltonDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;
	}
	fprintf(stdout,"INIT END\n");
#endif	/* 0 */
	for(i = 0;i < 20;i++) {
		funcDB[i].funcId = i+1;
		funcDB[i].processId = i+1;
//		funcDB[i].accessProcessType = (uint16_t)PROCESS_TYPE_UNKNOWN;
//		funcDB[i].accessDeviceType = (uint16_t)DEVICE_TYPE_UNKNOWN;
		dice = WaveDice();
		switch(dice) {
		case 1:
			funcDB[i].skeltonFunc = skeltonFunc1;
			funcDB[i].cancelFunc = cancelFunc1;
			break;
		case 2:
			funcDB[i].skeltonFunc = skeltonFunc2;
			funcDB[i].cancelFunc = cancelFunc2;
			break;
		case 3:
			funcDB[i].skeltonFunc = skeltonFunc3;
			funcDB[i].cancelFunc = cancelFunc3;
			break;
		case 4:
			funcDB[i].skeltonFunc = skeltonFunc4;
			funcDB[i].cancelFunc = cancelFunc4;
			break;
		case 5:
			funcDB[i].skeltonFunc = skeltonFunc5;
			funcDB[i].cancelFunc = cancelFunc5;
			break;
		case 6:
		default:
			funcDB[i].skeltonFunc = skeltonFunc6;
			funcDB[i].cancelFunc = cancelFunc6;
			break;
		}
//		fprintf(stdout,"i:%d; funcId:%d; processId:%d; skeltonFunc:0x%x; cancelFunc:0x%x;\n",
//				i,funcDB[i].funcId,funcDB[i].processId,funcDB[i].skeltonFunc,funcDB[i].cancelFunc);
	}
//		fprintf(stdout,"OK\n");
	for(j = 0;j < 20;j++) {
//		(void)IPC_RegisterFuncDBEntry(funcDB[j].funcId, funcDB[j].processId, funcDB[i].accessDeviceType,funcDB[i].accessProcessType,funcDB[j].skeltonFunc,funcDB[j].cancelFunc);
		(void)IPC_RegisterFuncDBEntry(funcDB[j].funcId, funcDB[j].processId,funcDB[j].skeltonFunc,funcDB[j].cancelFunc);
	}
	for(i = 0;i < 20;i++) {
		skelDB[i].processId = i+1;
		skelDB[i].taskId = (RpcTaskID_t)(i+1);
		skelDB[i].queId = i+1;
//		skelDB[i].processType = PROCESS_TYPE_TEST;
	}
	for(j = 0;j < 20;j++) {
//		(void)IPC_RegisterSkeltonDBEntry(skelDB[j].processId,skelDB[j].taskId,skelDB[j].queId,skelDB[i].processType);
		(void)IPC_RegisterSkeltonDBEntry(skelDB[j].processId,skelDB[j].taskId,skelDB[j].queId);
	}
//	fprintf(stdout,"@@@ BEFORE DEELTE @@@\n");
//	IPC_dumpDB();
//	RPC_MemDump(IpcDBManage->funcDBHashTable,IPC_SHM_DATABASE_FUNC_DB_HASH_TABLE*sizeof(RpcHashEntry_t),"HASH TABLE");
	(void)IPC_DeleteFuncDBEntry(1);
	(void)IPC_DeleteFuncDBEntry(10);
	(void)IPC_DeleteFuncDBEntry(20);
	if((ret = IPC_DeleteFuncDBEntry(10)) == RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_DeleteFuncDBEntry ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;		
	}
	(void)IPC_DeleteSkeltonDBEntry(1);
	(void)IPC_DeleteSkeltonDBEntry(10);
	(void)IPC_DeleteSkeltonDBEntry(20);
	if((ret = IPC_DeleteSkeltonDBEntry(10)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_DeleteSkeltonDBEntry ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;				
	}
	/* */
#ifdef	USE_MULTICAST_RPC
	(void)IPC_registerMulticastFunction(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_1);
	(void)IPC_registerFunctionInMulticastFunc(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_1,IPC_FUNC_ID_MLTCST_FUNC_1);
	(void)IPC_registerFunctionInMulticastFunc(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_1,IPC_FUNC_ID_MLTCST_FUNC_2);
	(void)IPC_registerFunctionInMulticastFunc(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_1,IPC_FUNC_ID_MLTCST_FUNC_3);
	(void)IPC_registerFunctionInMulticastFunc(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_2,IPC_FUNC_ID_MLTCST_FUNC_4);
	(void)IPC_registerFunctionInMulticastFunc(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_2,IPC_FUNC_ID_MLTCST_FUNC_5);
	(void)IPC_registerFunctionInMulticastFunc(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_2,IPC_FUNC_ID_MLTCST_FUNC_6);
	(void)IPC_unregisterFunctionInMulticastFunc(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_2,IPC_FUNC_ID_MLTCST_FUNC_6);
	(void)IPC_unregisterFunctionInMulticastFunc(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_2,IPC_FUNC_ID_MLTCST_FUNC_7);
	(void)IPC_unregisterMulticastFunction(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_1);
	(void)IPC_unregisterMulticastFunction(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_3);
	(void)IPC_registerMulticastFunction(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_1);
	(void)IPC_registerFunctionInMulticastFunc(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_1,IPC_FUNC_ID_MLTCST_FUNC_1);
	(void)IPC_registerFunctionInMulticastFunc(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_1,IPC_FUNC_ID_MLTCST_FUNC_2);
	(void)IPC_registerFunctionInMulticastFunc(RPC_GetPid(),IPC_FUNC_ID_MLTCST_TST_1,IPC_FUNC_ID_MLTCST_FUNC_3);
#endif	/* USE_MULTICAST_RPC */
	/* */
	fprintf(stdout,"@@@ AFTER DEELTE @@@\n");
	IPC_dumpDB();
	RPC_MemDump((uint8_t*)IpcDBManage->funcDBHashTable,IPC_SHM_DATABASE_FUNC_DB_HASH_TABLE*sizeof(RpcHashEntry_t),"HASH TABLE");
	
	if((ret = IPC_SerachProcessIdFromFuncDB(2,&processId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_SerachProcessIdFromFuncDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;						
	}
	fprintf(stdout,"== SEARCH OK funcId:2; processId:%d;\n",processId);
	if((ret = IPC_SerachProcessIdFromFuncDB(11,&processId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_SerachProcessIdFromFuncDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;						
	}
	fprintf(stdout,"== SEARCH OK funcId:11; processId:%d;\n",processId);
	if((ret = IPC_SerachProcessIdFromFuncDB(19,&processId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_SerachProcessIdFromFuncDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;						
	}
	fprintf(stdout,"== SEARCH OK funcId:19; processId:%d;\n",processId);
	if((ret = IPC_SerachProcessIdFromFuncDB(1,&processId)) == RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_SerachProcessIdFromFuncDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;						
	}
	fprintf(stdout,"== SEARCH OK funcId:1; processId:NOTHING;\n");

//	if((ret = IPC_SearchFunctionFromFuncDB(2,&func,&cancelFunc,&accessProcessType,&accessDeviceType)) != RPC_SUCCESS) {
	if((ret = IPC_SearchFunctionFromFuncDB(2,&func,&cancelFunc)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_SearchFunctionFromFuncDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;								
	}
#if	__WORDSIZE ==64
	fprintf(stdout,"== SEARCH OK funcId:2; func:0x%Lx; cancelFunc:0x%Lx;\n",(uint64_t)func,(uint64_t)cancelFunc);
#else	/* __WORDSIZE */
	fprintf(stdout,"== SEARCH OK funcId:2; func:0x%x; cancelFunc:0x%x;\n",(uint32_t)func,(uint32_t)cancelFunc);
#endif	/* __WORDSIZE */
//	if((ret = IPC_SearchFunctionFromFuncDB(11,&func,&cancelFunc,&accessProcessType,&accessDeviceType)) != RPC_SUCCESS) {
	if((ret = IPC_SearchFunctionFromFuncDB(11,&func,&cancelFunc)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_SearchFunctionFromFuncDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;								
	}
#if	__WORDSIZE == 64
	fprintf(stdout,"== SEARCH OK funcId:11; func:0x%Lx; cancelFunc:0x%Lx;\n",(uint64_t)func,(uint64_t)cancelFunc);
#else	/* __WORDSIZE */
	fprintf(stdout,"== SEARCH OK funcId:11; func:0x%x; cancelFunc:0x%x;\n",(uint32_t)func,(uint32_t)cancelFunc);
#endif	/* __WORDSIZE */
//	if((ret = IPC_SearchFunctionFromFuncDB(19,&func,&cancelFunc,&accessProcessType,&accessDeviceType)) != RPC_SUCCESS) {
	if((ret = IPC_SearchFunctionFromFuncDB(19,&func,&cancelFunc)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_SearchFunctionFromFuncDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;								
	}
#if	__WORDSIZE == 64
	fprintf(stdout,"== SEARCH OK funcId:19; func:0x%Lx; cancelFunc:0x%Lx;\n",(uint64_t)func,(uint64_t)cancelFunc);
#else	/* __WORDSIZE */
	fprintf(stdout,"== SEARCH OK funcId:19; func:0x%x; cancelFunc:0x%x;\n",(uint32_t)func,(uint32_t)cancelFunc);
#endif	/* __WORDSIZE */
//	if((ret = IPC_SearchFunctionFromFuncDB(10,&func,&cancelFunc,&accessProcessType,&accessDeviceType)) == RPC_SUCCESS) {
	if((ret = IPC_SearchFunctionFromFuncDB(10,&func,&cancelFunc)) == RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_SearchFunctionFromFuncDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;								
	}
	fprintf(stdout,"== SEARCH OK funcId:10; func:NULL; cancelFunc:NULL;\n");
	if((ret = IPC_SearchSkeltonDB(2, &taskId,&queId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_SearchSkeltonDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;								
	}
	fprintf(stdout,"== SEARCH OK processId:2; taskId:%Ld; queId:%d;\n",taskId,queId);
	if((ret = IPC_SearchSkeltonDB(11, &taskId,&queId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_SearchSkeltonDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;								
	}
	fprintf(stdout,"== SEARCH OK processId:19; taskId:%Ld; queId:%d;\n",taskId,queId);
	if((ret = IPC_SearchSkeltonDB(11, &taskId,&queId)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_SearchSkeltonDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;								
	}
	fprintf(stdout,"== SEARCH OK processId:19; taskId:%Ld; queId:%d;\n",taskId,queId);
	if((ret = IPC_SearchSkeltonDB(10, &taskId,&queId)) == RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_SearchSkeltonDB ret:%s;",RPC_LogConvertResultCode(ret));
		(void)IPC_DettachSharedMem();
		(void)IPC_DestroySharedMem();
		return ret;								
	}
	fprintf(stdout,"== SEARCH OK processId:10; taskId:NOTHING; queId:NOTHING;\n");

	
	
	(void)IPC_DettachSharedMem();
	(void)IPC_DestroySharedMem();
	return RPC_SUCCESS;
}

static int32_t skeltonFunc1(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut) {
	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"SKELTON FUNCTION 1");
	return 1;
}

static int32_t skeltonFunc2(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut) {
	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"SKELTON FUNCTION 2");
	return 1;
}

static int32_t skeltonFunc3(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOu) {
	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"SKELTON FUNCTION 3");
	return 1;
}

static int32_t skeltonFunc4(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut) {
	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"SKELTON FUNCTION 4");
	return 1;
}

static int32_t skeltonFunc5(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut) {
	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"SKELTON FUNCTION 5");
	return 1;
}

static int32_t skeltonFunc6(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut) {
	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"SKELTON FUNCTION 6");
	return 1;
}

static int32_t cancelFunc1(uint32_t processId, uint32_t seqNum) {
	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"SKELTON CANCEL FUNCTION 1");
	return 1;
}

static int32_t cancelFunc2(uint32_t processId, uint32_t seqNum) {
	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"SKELTON CANCEL FUNCTION 2");
	return 1;
}

static int32_t cancelFunc3(uint32_t processId, uint32_t seqNum) {
	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"SKELTON CANCEL FUNCTION 3");
	return 1;
}

static int32_t cancelFunc4(uint32_t processId, uint32_t seqNum) {
	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"SKELTON CANCEL FUNCTION 4");
	return 1;
}

static int32_t cancelFunc5(uint32_t processId, uint32_t seqNum) {
	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"SKELTON CANCEL FUNCTION 5");
	return 1;
}

static int32_t cancelFunc6(uint32_t processId, uint32_t seqNum) {
	(void)RPC_LogPrint(RPC_LOG_MODULE_SHM_DB,RPC_LOG_LEVEL_DEBUG1,"SKELTON CANCEL FUNCTION 6");
	return 1;
}

static int32_t WaveDice(void) {
	uint32_t val;

	val = RPC_Rand();
	if(val > RAND_MAX/6*5)
		return 1;
	else if(val > RAND_MAX/6*4)
		return 2;
	else if(val > RAND_MAX/6*3)
		return 3;
	else if(val >RAND_MAX/6*2)
		return 4;
	else if(val >RAND_MAX/6)
		return 5;
	else
		return 6;
}

#endif	/* DEBUG */
