//
// CRAM: CREATE Real-time Applications Manager
// See the copyright and acknowledgment of authors in the file COPYRIGHT
//
//// Node.h -- the CRAM node manager class ////
//
// A node manager is a daemon that has to run on every computer that CRAM manages.
// It handles the create/start/monitor/stop lifecycle of CRAM services on its host.
//
// It also has methods for reporting usage statistics and running simple performance benchmarks.
//

#ifndef __NODE_INCLUDE__
#define __NODE_INCLUDE__

#include "Program.h"
#include "Server.h"
#include <list>

namespace cram {

using namespace std;

// The Node Manager class

class Node : public Server {

protected:						// Data members

	list<ServiceRecord *> mServices;	// the services managed by the node
	
	StatisticsRecord mStatistics;		// my statistics structure
	unsigned short mNextPort;			// port to fork the next service on (or 0 if guessing ports)
	unsigned mParanoia;					// my level of paranoia linking my health to that of my know services
										// if > 0, then take my status as the intersection of my services' status flags;
										// if > 1, then actually ping clients in my ping handler
	pthread_t mHeartThread;				// my service heartbeat thread
	bool mReuseAddresses;				// whether to reuse addresses on new sockets
	bool mGuessPorts;					// whether to make up your own port #s for new service sockets
	bool mPingNewServices;				// whether to wait and ping services after creating them
	
							// Packet processor (command switch) method
	int handle_packet(in_addr_t sender, CRAMPacketHeader * pkt);

							// Service mgmnt operations
												// Create a new service: give a name, command, and an arg string
	int create_service(char * nam, char * cmd, char * args);
	
	ServiceRecord * find_service(char * name);	// Locate a registered service by name
	ServiceRecord * find_service(int pid);		// Locate a registered service by process id
	void remove_service(char * name);			// Remove the service by the given name from the list
												// Get a service's log
	int get_service_log(char * name, char * dest, unsigned short maxChars);
	int get_service_log_after(char * name, char * dest, unsigned offset);
	int get_service_options(char * name, char * dest);
	int truncate_service_log(char * name, char * dest, unsigned short maxChars);
	
							// Messages forwarded to the named service
	int send_to_service(unsigned command, CRAMPacketHeader * pkt);
	int send_to_service(unsigned command, char * name);
											// Send/receive a packet (used to communicate with services)
	int send_packet(char * pkt, unsigned send_size, unsigned recv_size, unsigned short port, bool wait);
		
							// Node-system manager queries
	void set_opt(const char * nam, const char * val);
	void get_statistics();					// Get the system usage statistics
	int get_time();							// get the current system time in msec
	short benchmark_MIPS();					// Answer an estimate of the node's MIPS performance
	short benchmark_MFLOPS();				// Answer an estimate of the node's MFLOPS performance
	
							// We need these to make Nodes concrete
	void start(void) {};		
	void stop(void) {};	

							// Emergency restart utilities
/*	int rediscover_services();
	int reconnect_to_service();
	int terminate_service();
*/
	
public:
	Node(char * name, unsigned short lport, unsigned short eport);
	~Node();
	
};

}

#endif

