/*******************************************************************************
 * Copyright (c) 2005, 2009 Intel Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Karla Callaghan, Intel - Initial API and Implementation
 *
 * $Id: TPTPProcessController.h,v 1.26 2009/02/03 16:40:17 jwest Exp $ 
 *******************************************************************************/ 

#ifndef __TPTP_PROCESS_CONTROLLER_H__
#define __TPTP_PROCESS_CONTROLLER_H__

#include "tptp/agents/BaseAgentImpl.h"
#include "tptp/ProcCtlUtils.h"
#include "tptp/hashtable.h"

#define  PARAM_STDOUT "-stdout"
#define  PARAM_STDIN "-stdin"
#define  PARAM_STDERR "-stderr"

class ProcessController : public BaseAgentImpl
{
	private:
		tptp_list_t runningProcessList; //List of processes started by ProcessController that are still alive
		Lock_t runningProcessListLock;	//mutex used by msg handler thread and event processing thread	
		
		tptp_list_t eventListenerList; //List of listeners that wish to be notified of events

		tptp_list_t startProcessList; //List of start process requests		
		Lock_t startProcessListLock;  //mutex used by msg handler thread and start processes thread

		// consoleConnected and processConnId are only valid during short periods.
		// They get reset after being read (during startProcess activity).
		bool consoleConnected;       //Indicates if console connection completed successfully.
		Lock_t consoleConnectedLock; //mutex used by msg handler thread and start processes thread

		int processConnId ;			 //Connection Id of the last process launched w/console.
									 //Use the consoleConnectedLock for read/write mutex on processConnId.
		tptp_list_t *appAliasesList; //List of aliases which can be specified in a startProcess appName.
		bool launchAliasesOnly;		 //Requires app to be defined in the appAliasesList or refuse to launch it
		HashTable *pidUUIDHashTable;

#ifdef _WIN32
		TPTP_HANDLE hProcListChangedEvent; //Used to sync msg handler thread and handle process events thread
#endif

	public:
		ProcessController(char* agentName);
		~ProcessController();
		int preRegisterInitialization();
		void handleProcessEvents(void);
		int processCommand(CmdBlock* cmd);
		int processFlagCommand(MsgBlock* msg);
		int startProcess(void);

		// XML Cmd fragments map to the following commands
		int validateProcessToLaunch(const char* appName, const char* workingDir,
									const int replyDest, const int replyContext);
		int startProcess(tptp_process_t* process);
		int stopProcess(const PID pid, const int replyDest, const int replyContext);
		int getProcessUUID(const PID pid, const int replyDest, const int replyContext);

		int monitorProcessState(const PID pid, const int replyDest, const int replyContext);
		int terminateChildProcesses(const int ownerSourceID, const int replyDest, const int replyContext);
		int addEventListener(const char* eventsIID, const int listenerID,
							 const int replyDest, const int replyContext);
		int terminateAllChildProcesses();

		void removeRunningProcess(PID pid);
		void sendEventNotifications(const PID pid, const unsigned long exitStatus);


#ifndef _WIN32
		void handleChildExited(PID pid, int status);
#endif

	private:
		// Utilities for working with the runningProcessList
		int numRunningProcesses(void);
		int findRunningProcessByPid(const PID pid, tptp_process_t** proc);
		int addProcessMonitor(const PID pid, tptp_listener_t* monitor);
#ifdef _WIN32
		int findRunningProcessByHandle(const TPTP_HANDLE hProc, tptp_process_t** proc);
		void closeRunningProcessHandles(void);		
		long getRunningProcessHandleList(TPTP_HANDLE* &procHandles);
#endif
		void addRunningProcess(tptp_process_t* proc);

		int validateExecutable(const char* appName, unsigned long& errCode);
		int validateDirectory(const char* dir, unsigned long& errCode);
		int doCreateProcess(tptp_process_t* proc, unsigned long &errCode);
		int doStopProcess(const PID pid, const int requestorID, const int requestorCtxt);
		int doMonitorProcessState(const PID pid, const int requestorID, const int requestorCtxt);
		int doTerminateChildProcesses(const int ownerSourceID);
		int sendCONNECT_CONSOLECommand(char *pUniqueId, int *processConnId);
		int sendCONSOLE_PROCESS_LAUNCHEDCommand(int processConnId, PID pid);

		void addStartProcessInfo(tptp_process_t* proc);
		int getStartProcessInfo(tptp_process_t** proc);

		void closeConsoleIOConnections(RemoteConsole_t *console);
		int createConsoleIOConnections(char *pUniqueID, RemoteConsole_t *console);
		int openConsoleIOConnections(char *pUniqueID, RemoteConsole_t *console);

#ifdef _WIN32
		void handleProcessEvents_win32(void);
/* AK -- Linux is now using a sighandler to get child process closed events
#else
		void handleProcessEvents_linux(void);
*/
#endif

};

#endif /* __TPTP_PROCESS_CONTROLLER_H__ */
