/*!
	CGI管理クラス

	CGIの実行は、CGI実行環境を生成してから行う

	CCGIProcessBase -> CFastCGIProcess
	                -> CNormalCGIProcess
*/
#pragma once
#include "TextInfoExceptionBase.h"
#include "InterruptEvents.h"
#include "SortArray.h"
#include "Buffer.h"
#include "Workspace.h"

/*!
	プロセスタイプ
*/
enum CGI_PROCESS_TYPE
{
	CGI_PROCESS_TYPE_EXECUTABLE		= 0,
	CGI_PROCESS_TYPE_SCRIPT			= 1,
};


/*!
	インタフェースタイプ
*/
enum CGI_INTERFACE_TYPE
{
	CGI_INTERFACE_TYPE_CGI			= 0,
	CGI_INTERFACE_TYPE_FASTCGI		= 1,
};

/*!
	エラータイプ
*/
enum CGI_NEW_PROCESS_ERROR
{
	CGI_NEW_PROCESS_ERROR_NOERROR				= 0,

	//!	プロセス数上限
	CGI_NEW_PROCESS_ERROR_OVER_PROCESS			= -10,
};


/*!
	CGIプロセスエラー例外
*/
DEFINE_TEXT_INFO_EXCEPTION(CCGIProcessException);


/*!
	CGI実行環境インターフェース

	インタプリタ＋スクリプトは、クラス生成時に指定
*/
class ICGIInterface
{
public:
	///////////////////////////////////////////////////////////////////////////////
	//	インタフェース
	///////////////////////////////////////////////////////////////////////////////
	/*!
		1:CGI実行開始(throw CCGIProcessException)

		\param envs:CGIの環境変数
	*/
	virtual void StartCGIProcess(CKeyDataArray &envs) = 0;

	/*!
		2:リクエストボディを書き込み(throw CCGIProcessException)

		0書き込みで終了
	*/
	virtual void WriteRequestBody(CBuffer &data, CInterruptEvents &breakEvents) = 0;

	/*!
		3:レスポンスの生成
	*/
	virtual void WaitResponse(CInterruptEvents &breakEvents) = 0;

	/*!
		4:レスポンスヘッダ取得(throw CCGIProcessException)

		SSI実行時は呼び出されない
	*/
	virtual void ReadResponseHeader(CKeyDataArray &resHeaders, CInterruptEvents &breakEvents) = 0;

	/*!
		5:レスポンスボディを読み出し(throw CCGIProcessException)

		0読み出しで終了
	*/
	virtual void ReadResponseBody(CBuffer &data, CInterruptEvents &breakEvents) = 0;

	/*!
		6:CGI実行終了
	*/
	virtual void CleanupCGIProcess() = 0;
};


/*!
	CGI管理クラス

	CGI同時実行数、FastCGIの管理を行う
	マネージャは、開始時を除き、例外をスローしない
*/
class CCGIManager
{
public:
	CCGIManager(void);
	virtual ~CCGIManager(void);

	///////////////////////////////////////////////////////////////////////////////
	//	インタフェース
	///////////////////////////////////////////////////////////////////////////////
	//!	開始(throw CServerStartException)
	void Start(CWorkspaceAccess setting);

	//!	停止
	void Stop();

	//!	プロセス取得(throw CCGIProcessException)
	int GetNewCGIProcess(CString commandLine, int cgiInterfaceType, int cgiProcessType, ICGIInterface **process);

	//!	プロセス使用終了
	void DeleteCGIProcess(ICGIInterface *process);

protected:
	///////////////////////////////////////////////////////////////////////////////
	//	下請け
	///////////////////////////////////////////////////////////////////////////////

	///////////////////////////////////////////////////////////////////////////////
	//	メンバ変数
	///////////////////////////////////////////////////////////////////////////////
	//!	スコープ保護用
	CCriticalSection	m_scopeLock;

	//!	最大CGIプロセス数
	int					m_maxCGIProcessCount;

	//!	実行中のプロセス
	CTypedPtrArray<CPtrArray, ICGIInterface*>	m_processList;
};

