/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

	【機能概要】	: 共有メモリ生成プログラム
					  共有メモリ定義ファイルに従って、shmat / shmget により共有メモリ
					  領域の確保を行う。
					  注）windows版の実装部は、未試験のため動作不可

	【作成日】		: 2021.04.23

	【呼出形式】	: GG_SHM1001			# 引数なし
											# 但し、本コマンド起動のためには３つの環境変数が必要
											#  1. GG_SHMID_MNGFILE 		共有メモリ定義ファイル
											#  2. GG_SHM1001_MEMORYID 	共有メモリID（全体管理領域）
											#  3. GG_SHM1001_MEMORYSZ 	共有メモリサイズ（全体管理領域）
	【戻り値1】		: int					# 0 : 正常終了、-1 : 異常終了

_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */


#include "GG_SHMCOM.h"

int main(
	int argc,
	char* argv[])
{
	CLSSharedMemory shmAcPtMng;			// 使用面管理領域の共有メモリ
	CLSSharedMemory shmAcPtPtr_A[ GG_SHM1001_SHMIDNUM ];	// Ａ面の共有メモリ
	CLSSharedMemory shmAcPtPtr_B[ GG_SHM1001_SHMIDNUM ];	// Ｂ面の共有メモリ

	ST_ShmDef	*s_ShmDef ;				// 使用面管理領域
	void		*s_A_ShmPtr ;			// Ａ面
	void		*s_B_ShmPtr ;			// Ｂ面

	key_t keyShmMainMem;				// 主管理面ID
	long  lShmMainMemSize;				// 主管理面のサイズ

	long lShmMngSize;					// 使用面管理領域のサイズ
	long lShmPtrSize;					// 面領域のサイズ
	char szLogFileTmpPath[ MAX_PATH ];	// ログファイル一時名称
	char szLogFilePath   [ MAX_PATH ];	// ログファイル名
	char szAccessDate[30];				// YYYY/MM/DD HH:MM:SS.mmmmmm
	
	char ShmMng_ID  [ GG_SHM1001_SHMIDNUM ][ 32 ] ;
	int iShmId_A_ID [ GG_SHM1001_SHMIDNUM ] ;
	int iShmId_B_ID [ GG_SHM1001_SHMIDNUM ] ;
	int iShmId_Len  [ GG_SHM1001_SHMIDNUM ] ;

	/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
					ログファイル名取得
	_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

	getEnvString(szLogFileTmpPath,"GG_LogFileName",GG_SHM1001_LOGPATH,sizeof(szLogFileTmpPath));
	getLocalTimeString(szLogFilePath,sizeof(szLogFilePath),szLogFileTmpPath);

	getLocalTimeString(szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U");
	GG_MsgOut(szLogFilePath,1,"**** ( %s ) **** GG_SHM1001 共有メモリ確保 ****  START  ****",szAccessDate);

	/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
					共有メモリ定義ファイルの解析
	_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

	int rc = GG_SHM1002 ( ShmMng_ID , iShmId_A_ID , iShmId_B_ID , iShmId_Len ) ;
	if ( rc != 0 ) {
		printf ( "Usage : GG_SHM1001 入力ファイルエラー！！\n",rc) ;
		return ( -1 ) ;
	}

	/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
					共有メモリ（全体管理領域）の宣言
	_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

	keyShmMainMem   = getEnvLong("GG_SHM1001_MEMORYID",GG_SHM1001_MEMORYID);
	lShmMainMemSize = getEnvLong("GG_SHM1001_MEMORYSZ",GG_SHM1001_MEMORYSZ);

	GG_MsgOut(szLogFilePath,4,"共有メモリ 管理領域確保 Key=%d Size=%d",keyShmMainMem,lShmMainMemSize);
	char *c_ShmMngPtr = (char *)shmAcPtMng.CreateSheredMemory(keyShmMainMem,lShmMainMemSize);
	GG_MsgOut(szLogFilePath,9,"ShmID=%d",shmAcPtMng.getSharedMemory());

	if(c_ShmMngPtr == NULL){
		GG_MsgOut(szLogFilePath,0,"!!!  ERROR  !!! 共有メモリ管理領域確保エラー Key=%d Size=%d"
				,keyShmMainMem,lShmMainMemSize);
		GG_MsgOut(szLogFilePath,0,"ErrNo=%d Msg=%s",shmAcPtMng.getErrorNo(),shmAcPtMng.getErrorMsg());
		printf ( "Usage : GG_SHM1001 共有メモリ管理領域確保エラー Key=%d Size=%d"
				,(int)keyShmMainMem,(int)lShmMainMemSize);
		exit (-1);
	}

	// 先頭は、ログレベル(long型)の設定に使用
	s_ShmDef = (ShmDefType *)( c_ShmMngPtr + sizeof(long) ) ;
	GG_MsgOut ( szLogFilePath,1,"共有メモリ 管理領域確保成功 Key=%d Size=%d"
				,keyShmMainMem,lShmMainMemSize ) ;

	/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
			共有メモリ定義ファイルに従い、管理領域設定およびA/B面メモリ確保/
	_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

	for ( int i = 0 ; ShmMng_ID[i][0] != '\0' ; i++ , s_ShmDef ++ ) {

//		printf ( "ShmMng_ID[%d]=[%s} iShmId_A_ID[%d]=[%d] iShmId_B_ID[%d]=[%d] iShmId_Len[%d]=[%d]\n"
//		,i , ShmMng_ID[i] ,i , iShmId_A_ID[i] , i , iShmId_B_ID[i] , i , iShmId_Len[i] );

		/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
									管理領域の設定
		_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

		strcpy ( s_ShmDef->ShmName , ShmMng_ID[i] ) ;
		s_ShmDef->ShmFlg    = 0 ;
		s_ShmDef->ShmID_A   = iShmId_A_ID[i] ;
		s_ShmDef->ShmID_B   = iShmId_B_ID[i] ;
		s_ShmDef->ShmLength = iShmId_Len[i] ;

		/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 
							共有メモリポインタ取得 ( Ａ面 )
		 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

		GG_MsgOut(szLogFilePath,4,"共有メモリ Ａ面領域確保 Key=%d Size=%d"
					,s_ShmDef->ShmID_A,s_ShmDef->ShmLength);
		s_A_ShmPtr = shmAcPtPtr_A[i].CreateSheredMemory(s_ShmDef->ShmID_A,s_ShmDef->ShmLength);
		GG_MsgOut(szLogFilePath,9,"ShmID=%d",shmAcPtPtr_A[i].getSharedMemory());
		if(s_A_ShmPtr == NULL){
			GG_MsgOut(szLogFilePath,0
					,"!!!  ERROR  !!! 共有メモリ Ａ面領域の確保に失敗しました Key=%d Size=%d"
					,s_ShmDef->ShmID_A,s_ShmDef->ShmLength);
			GG_MsgOut(szLogFilePath,4,"ErrNo=%d Msg=%s"
					,shmAcPtPtr_A[i].getErrorNo(),shmAcPtPtr_A[i].getErrorMsg());
			exit (-1);
		}
		GG_MsgOut(szLogFilePath,1,"共有メモリ Ａ面領域確保成功 Key=%d Size=%d"
			,s_ShmDef->ShmID_A,s_ShmDef->ShmLength);

		/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
							共有メモリポインタ取得 ( Ｂ面 )
		_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

		GG_MsgOut(szLogFilePath,4,"共有メモリ Ｂ面領域確保 Key=%d Size=%d"
			,s_ShmDef->ShmID_B,s_ShmDef->ShmLength);
		s_B_ShmPtr = shmAcPtPtr_B[i].CreateSheredMemory(s_ShmDef->ShmID_B,s_ShmDef->ShmLength);
		GG_MsgOut(szLogFilePath,9,"ShmID=%d",shmAcPtPtr_B[i].getSharedMemory());
		if(s_B_ShmPtr == NULL){
			GG_MsgOut(szLogFilePath,0
				,"!!!  ERROR  !!! 共有メモリ Ｂ面領域の確保に失敗しました Key=%d Size=%d"
				,s_ShmDef->ShmID_B,s_ShmDef->ShmLength);
			GG_MsgOut(szLogFilePath,4,"ErrNo=%d Msg=%s"
				,shmAcPtPtr_B[i].getErrorNo(),shmAcPtPtr_B[i].getErrorMsg());
			exit (-1);
		}
		GG_MsgOut(szLogFilePath,1,"共有メモリ Ｂ面領域確保成功 Key=%d Size=%d"
			,s_ShmDef->ShmID_B,s_ShmDef->ShmLength);

	}

	// テーブルストッパ設定
	s_ShmDef->ShmName[0] = '\0' ;

	/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
						共有メモリ 管理領域確保完了
	_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

	getLocalTimeString(szAccessDate,sizeof(szAccessDate),"%Y/%m/%d %H:%M:%S.%U");
	GG_MsgOut(szLogFilePath,1,"**** ( %s ) **** GG_SHM1001 共有メモリ確保 ****  END  ****",szAccessDate);

//無限ループ（終了するまで共有メモリを保持するため）・・・サービス化が完了するまで
#ifdef WIN32
	while(1){
		Sleep(1000);
	}
#endif
	return 0;
}
