/*
 * 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_INIT_MAIN

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

#include	"ipcInfo.h"
#include	"ipcLog.h"
#include	"ipcType.h"
#include	"ipcSyscall.h"
#include	"ipcShmDB.h"
#include	"ipcShm.h"
#include	"ipcQue.h"
#include	"ipcStub.h"
#include	"ipcSkelton.h"
#include	"ipcMarshal.h"
#include	"ipcInit.h"

/* ----- IPC INIT APIs ----- */

extern RpcResult_t IPC_InitIprpc(RpcBool_t masterProcess, RpcBool_t useSkelton, RpcBool_t useStub,RpcLogLevel_t logLevel) {
	RpcResult_t ret = RPC_SUCCESS;

	/* INIT LOG SYSTEM */
//	(void)RPC_LogPrint(RPC_LOG_MODULE_INIT,RPC_LOG_LEVEL_DEBUG1,"IN RPC_InitIpc PID:0x%x; master:%d; useSkelton:%d; useStub:%d;",RPC_GetPid(),masterProcess, useSkelton, useStub);
	if((ret = RPC_LogInit()) != RPC_SUCCESS) {
		return ret;
	}
#if	1
	if((ret = RPC_LogSetAll(logLevel)) != RPC_SUCCESS) {
		return ret;
	}
#else	/*  */
	if((ret = RPC_LogSetAll(RPC_LOG_LEVEL_DEBUG3)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_INIT,RPC_LOG_LEVEL_FATAL,"ERROR IN RpcLogSetAll ret:0x%x;",ret);
		return 1;
	}
#endif	/*  */
	/* INIT SHM */
	if((ret = IPC_InitSharedMem(masterProcess)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_INIT, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_InitSharedMem RET:%s;",RPC_LogConvertResultCode(ret));
		return ret;
	}
	if((ret = IPC_AttachSharedMem()) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_INIT, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_AttachSharedMem RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError0;
	}
	/* INIT SHM DB */
	if((ret = IPC_InitShmDB(masterProcess)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_INIT, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_InitShmDB RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError1;
	}
//	printFixedAreaList(0x4);
//	printFreeAreaLIst(0x4);
	/* INIT QUE SYSTEM */
	if((ret = IPC_InitQue(masterProcess,RPC_TRUE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_INIT, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_InitQue - EXTERNAL RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError1;
	}
	if((ret = IPC_InitQue(masterProcess,RPC_FALSE)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_INIT, RPC_LOG_LEVEL_FATAL, "FATAL ERROR in IPC_InitQue - INTERNAL RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError1;
	}
	/* INIT MARSHAL LIBRARY */
	if((ret = IPC_InitMarshal(masterProcess)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_INIT,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_InitMarshal RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError1;	
	}
	/* INIT SKELTON */
	if(useSkelton) {
//		(void)RPC_LogPrint(RPC_LOG_MODULE_INIT,RPC_LOG_LEVEL_DEBUG1,"NOW CALL IPC_InitSkelton PID:0x%x;",RPC_GetPid());
		if((ret = IPC_InitSkelton(masterProcess)) != RPC_SUCCESS) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_INIT,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_InitSkelton RET:%s;",RPC_LogConvertResultCode(ret));
			goto goError1;			
		}
//		(void)RPC_LogPrint(RPC_LOG_MODULE_INIT,RPC_LOG_LEVEL_DEBUG1,"END CALL IPC_InitSkelton PID:0x%x;",RPC_GetPid());
	}
	else {
//		(void)RPC_LogPrint(RPC_LOG_MODULE_INIT,RPC_LOG_LEVEL_DEBUG1,"NOT CALL IPC_InitSkelton AS useSkelton:%d; PID:0x%x;",useSkelton, RPC_GetPid());
	}
	/* INIT STUB */
	if(useStub) {
		if((ret = IPC_InitStub(masterProcess)) != RPC_SUCCESS) {
			(void)RPC_LogPrint(RPC_LOG_MODULE_INIT,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_InitStub RET:%s;",RPC_LogConvertResultCode(ret));
			goto goError1;					
		}
	}
	else {
//		(void)RPC_LogPrint(RPC_LOG_MODULE_INIT,RPC_LOG_LEVEL_DEBUG1,"NOT CALL IPC_InitStub AS useStub:%d; PID:0x%x;",useStub, RPC_GetPid());
	}
#ifdef	USE_RENDEZVOUS
	if((ret = IPC_InitRendezv(masterProcess)) != RPC_SUCCESS) {
		(void)RPC_LogPrint(RPC_LOG_MODULE_INIT,RPC_LOG_LEVEL_FATAL,"ERROR IN IPC_InitRendezv RET:%s;",RPC_LogConvertResultCode(ret));
		goto goError1;
	}
#endif	/* USE_RENDEZVOUS */
//	IPC_PrintQueData();
//	(void)RPC_LogPrint(RPC_LOG_MODULE_INIT,RPC_LOG_LEVEL_DEBUG1,"OUT IPC_InitIpc PID:0x%x;",RPC_GetPid());
	return ret;

goError1:
	(void)IPC_DettachSharedMem();
goError0:
	(void)IPC_DestroySharedMem();
	return ret;
}

/* ----- Internal Functions ----- */

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