//
// CRAM: CREATE Real-time Applications Manager
// See the copyright and acknowledgment of authors in the file COPYRIGHT
//
//// CRAM.h -- the main include file for all CRAM
//
// Define the packet header data structure, command flags, error codes,
// default ports, compile options, and other system defaults
//

#ifndef __CRAM_INCLUDE__
#define __CRAM_INCLUDE__

// CRAM message packet header (12 bytes) -- the core CRAM protocol data structure

typedef struct {
	unsigned magic;				// Magic number ( = 0x004200XX, whereby XX is the command)
	unsigned short size;		// Size of packet (including header)
	unsigned short sequence;	// Sequence number (out-of-sequence packets may or may not be flagged as errors)
	int value;					// Single 32-bit argument or return value
} CRAMPacketHeader;

// NB: for packets with more arguments or return values, the data immediately follows the header, 
// and is always terminated by a 32-bit footer with the magic number repeated.

// Useful macros for managing packet I/O

#define CRAM_HEADER_SIZE (sizeof(CRAMPacketHeader))	// Size of UDP request/response packets

#define CRAM_PACKET_MAGIC 	0x00420000		// UDP packet magic number; the command is or'ed into the least-significant byte

#define CRAM_SMALL_MSG 		64				// Small packet size
#define CRAM_MEDIUM_MSG		256				// Medium packet size
#define CRAM_MAX_MSG 		8192			// Max packet size -- things break if you try using really long packets

//
// Remote commands (see the pseudo-IDL for descriptions) 
//

// All programs implement the first two groups of commands

#define CRAM_PING			40		// Ping message (no arg; respond with general status flag)
#define CRAM_TEST			41		// Test message (no arg; respond with port #s and detailed 
									// status; update log; possibly check app status)
#define CRAM_GET_NAME		42		// Name query message (no arg; respond with my name)
#define CRAM_GET_OPTS		43		// Answer program options (response = list of (key, value))
#define CRAM_SET_OPTS		44		// Configure a program (arg = option_string)

#define CRAM_GET_LOG		50		// Get the log text (arg = max_len (< 8kB); respond with string)
#define CRAM_GET_LOGAFTER	51		// Get the log text (arg = from_pos (< 8kB); respond with string)
#define CRAM_TRUNC_LOG		52		// Truncate the logging file (arg = short len)

// Program emergency messages (sent only by NodeManager to emergency port)

#define CRAM_EMER_PING		101		// Ping message  (no arg; respond with general status flag)
#define CRAM_EMER_PORTS		102		// Port query  (no arg; respond with listener port #, status, 
									// and last timestamp)
#define CRAM_EMER_RESTART	103		// Restart listener thread (no arg; respond with new listener 
									// port # & status)
// Services add these (all except start/stop are optional)

#define CRAM_INITIALIZE		60		// Reinitialize the service (e.g., after re-configuration)
#define CRAM_START			61		// Start the server (no arg; respond with general status flag)
#define CRAM_STOP			62		// Stop (and exit) the server (no arg; respond with general status flag)
#define CRAM_SUSPEND		63		// Pause the server (no arg; respond with general status flag)
#define CRAM_RESUME			64		// Continue the server (no arg; respond with general status flag)

// Node managers support these, the main operations of CRAM

#define CRAM_CREATE_SVC		70		// Create a new service (arg = name, cmd, args; respond with port #s)
#define CRAM_PING_SVC		71		// Ping a service (arg = name; respond with status)
#define CRAM_TEST_SVC		72		// Test a service (arg = name; respond with port #s and detailed status)
#define CRAM_LIST_SVCS		73		// List services (respond with list of strings)

#define CRAM_INIT_SVC		74		// Initialize a service (arg = name)
#define CRAM_START_SVC		75		// Start a service (arg = name)
#define CRAM_STOP_SVC		76		// Stop/kill a service (arg = name)
#define CRAM_SUSPEND_SVC	77		// Suspend a service (arg = name)
#define CRAM_RESUME_SVC		78		// Resume a service (arg = name)

#define CRAM_GET_SVC_LOG	79		// Get a service's log (arg = max_len; respond with string)
#define CRAM_GET_SVC_AFTER	80		// Get the tail of a service's log (arg = offset; respond with string)
#define CRAM_TRUNC_SVC_LOG	81		// Get a service's log (arg = max_len; respond with string)
#define CRAM_GET_SVC_OPTS	82		// Answer program options (response = list of (key, value))
#define CRAM_SET_SVC_OPTS	83		// Configure a program (arg = option_string)

#define CRAM_PING_NODE		85		// Ping a the node manager (respond with intersection of service status)
#define CRAM_PING_CAREFUL	86		// Ping a the node manager (respond after getting status of services)
#define CRAM_WATCH_SVC		87		// Watch a service (args = name, period; respond with status)
#define CRAM_WATCH_SVCs		88		// Watch all services (arg = period for heartbeat)

#define CRAM_GET_TIME		95		// Get the node's clock time (respond with long time value)
#define CRAM_GET_STATS		96		// Get performance statistics (no arg; respond with statistics struct)
#define CRAM_NODE_BENCH		97		// Get an estimate of the node's MIPS/MFLOPS (respond with 2 shorts)

//
// Command return codes (sent in size field of response packets)
//

#define CRAM_AOK 				30000	// AOK = no error
#define CRAM_WARN 				30001	// Potential problem
#define CRAM_ERROR 				30002	// Error state

// Service status flags

#define CRAM_INIT	 			30100	// Component initialized
#define CRAM_ON	 				30101	// Component running
#define CRAM_SUSPENDED 			30102	// Component suspended
#define CRAM_OFF	 			30103	// Component turned off
#define CRAM_TIMEOUT 			30104	// Component timeout state
#define CRAM_FAILED 			30105	// Component App failed state
#define CRAM_CONFUSED	 		30106	// Component state indeterminate
#define CRAM_ZOMBIE	 			30107	// Component state frozen
#define CRAM_UNKNOWN	 		30108	// Unknown component state

// Error flags (higher numbers)

#define CRAM_HEADER_ERROR		30200	// Bad packet header
#define CRAM_ARGUMENT_ERROR		30201	// Bad command arguments
#define CRAM_COMMAND_ERROR		30202	// Bad command flag
#define CRAM_PROCESSING_ERROR	30203	// Error processing command
#define CRAM_IO_ERROR			30204	// IO error while processing command
#define CRAM_NO_SERVICE_ERROR	30205	// Service not found error
#define CRAM_SVC_EXISTS_ERROR	30206	// Service already exists
#define CRAM_TIMEOUT_ERROR		30207	// Client timeout error
#define CRAM_OTHER_ERROR		30208	// Other error

//
// Default I/O ports
//

#define CRAM_NODE_PORT 			12090	// Default port for Manager listener
#define CRAM_EMERGENCY_PORT 	12092	// Default port for Manager emergency listener
#define CRAM_SERVICE_PORT		12341	// Default base port for server listeners

// Directory name definitions (generally under /usr/local or /tmp)

#define CRAM_LOG_DIR "/usr/local/CRAM/logs/"	// Default location of logging files
#define CRAM_PID_DIR "/usr/local/CRAM/pids/"	// Default location of pid files

//
// Compile-time options
//

// All Programs

#define REUSE_ADDRESSES true			// Be sloppy about reusing socket addresses, brittle but safer
#define GUESS_PORTS true				// Always let node managers choose the ports for services
// #define CHECK_SEQUENCE				// Be picky about packet sequence errors from managers
#define CRAM_MAX_OPTS			32		// Max # of configurable options
#define CRAM_SELECT_TIME		10		// Default timeout on socket read selects

// Logging options

#define LOG_TO_FILE true				// Set for logging to file vs. stdout (can be changed at run-time)
#define LOG_TO_STDOUT true				// Copy log messages to stdout (for debugging)
#define LOG_TO_SOCKET true				// Allow log messages to a socket (for node managers reporting 
										// to the system manager)
#define LOG_TO_CACHE true				// Allow log messages to an in-memory cache (for real-time systems)
#define DEFAULT_LOG_LEVEL 3				// Default  verbosity (4 = debugging; 3 = verbose; ..., 0 = quiet)
#define LOG_CACHE_SIZE 8192				// Default logging cache size

// Compile-time-only flags

#define SPAWN_EMERGENCY_THREAD			// Create a second listener thread for emergency commands
#define USE_SELECT						// Use select() to pause for socket input with timeouts
										// (otherwise, use blocking recvfrom() calls)
#define CREATE_PID_FILE					// Create debugging pid/port file in CRAM_PID_DIR

// Node-specific compile-time options

#define NODE_KILLS_SERVICES				// Node destructor kills services
#define PING_NEW_SERVICES false			// Always ping newly created services to test
#define PING_NEW_SVC_DELAY 3			// Time to wait before ping new services (in sec.)
#define SUPPORT_GET_STATS				// Support the usage statistics code (top-like)
#define SUPPORT_GET_TIME				// Support the clock latency/offset commands
#define CRAM_DEFAULT_HEARTRATE  15		// Default heartrate (period, actually), in seconds
#define CRAM_MAX_SVCS			16		// Max # of services on a node

//
// Statistics struct (only the first 2 elements are used at present)
//

typedef struct {
	float cpu;			// CPU usage %
	float mem;			// Memory usage %
//	float disk;			// Disk I/O usage %
//	float net;			// Network I/O usage %
//	float frames;		// Graphics frames/sec
} StatisticsRecord;

#endif

