// $Id: ServerEngine.java,v 3.8 1998/12/11 17:09:53 smg9c Exp $ /////////////////////////////////////////////////////////////////////
//
// File: ServerEngine.java
//
// Purpose: The ServerEngine class is responsible for manipulating the
// master map and sending it out to the clients.
//
// Authors: Steve Geist smg9c@cs.virginia.edu
//
// Modifications:
//
//
// 11-DEC-1998 smg Added shut down method
//
// 08-DEC-1998 smg Modified to take port on command line
//
// 08-DEC-1998 smg Changed to work with one thread per stabilization loop.
//
// 04-DEC-1998 smg Changes made to run with auto and manual modes.
//
// 01-DEC-1998 smg Added automatic destabilization option
//
// 19-NOV-1998 smg Added Error method to pass exceptions up to Server for
// a stack trace
//
// 17-NOV-1998 smg Added second thread to send initial map, added delay
// and propagation_method variables, added functionality
// to deal with demon engine and updating of new variables
//
// 09-NOV-1998 smg Code review changes made
//
// 09-NOV-1998 smg Cleaned up for use with ServerThread
//
// 06-NOV-1998 rgb Added version control header info
//
// 05-NOV-1998 smg Made program structure more event driven
//
// 04-NOV-1998 smg Added comments, FileMgr renaming
//
// 01-NOV-1998 smg Initial creation
//
/////////////////////////////////////////////////////////////////////
import java.io.*;
import java.lang.*;
public class ServerEngine {
private int num_clients; // Number of clients
private Map map; // Server's master copy of the map
private Server server; // Gives access to output
private ServerRMI server_rmi; // Access to RMI
private static final int BUFFER_SIZE = 2048; // Buffer size used for the
// DataOutputStream
private DataInputStream dis; // Used to read in the map
private long delay; // Indicates the delay in
// milliseconds for sending out
// modified maps
private int propagation_method; // Indicates the method to be used
// for propagation of unstable nodes
private boolean all_clients_reported; // Indicates whether all clients have
// reported their changes for the
// current iteration
private boolean demon_reported; // Indicates whether the demon has
// reported the delay and prop.
// method for the current iteration
private ServerThread compute_engine; // Thread that does all stabilization
// computations
private int mode; // Indicates auto or manual mode
private int iterations; // Indicates how many iterations to
// run in auto mode
private final int automatic_mode = 0; // Auto mode
private final int manual_mode = 1; // Manual mode
private boolean thread_running; // Inidicates whether the computation
// thread is currently running
///////////////////////////////////////////////////////////////////
//
// Method: ServerEngine [constructor]
//
// Purpose: Creates a new ServerEngine and reads the file indicated by
// file_name into a Map. The Server is necessary for callbacks.
//
///////////////////////////////////////////////////////////////////
public ServerEngine(Server s, String file_name, int port) {
server = s;
try {
ReadMap(file_name);
}
catch (Exception e) {
Error(e);
return;
}
num_clients = map.GetNumModules();
try {
server_rmi = new ServerRMI(this, port, num_clients);
}
catch(Exception e) {
Error(e);
}
delay = 5000; // Default value
propagation_method = 1; // Default value
all_clients_reported = false;
demon_reported = false;
compute_engine = new ServerThread(server_rmi, this);
}
///////////////////////////////////////////////////////////////////
//
// Method: ReadMap
//
// Purpose: Reads in the file named with the String file_name and
// converts it to a map.
//
///////////////////////////////////////////////////////////////////
public void ReadMap(String file_name)
throws MapReadException {
if(file_name.length() == 0) {
PrintMessage("Input file name is invalid");
return;
}
try {
dis = new DataInputStream(
new BufferedInputStream(
new FileInputStream(file_name)));
}
catch (Exception e) {
throw new MapReadException();
}
try {
String data = dis.readLine();
map = new Map(data);
map.Validate();
map.SetFinal(true);
map.SetEditable(false);
}
catch (Exception e) {
throw new MapReadException();
}
}
///////////////////////////////////////////////////////////////////
//
// Method: UpdateMap
//
// Invoker: ServerRMI
//
// Purpose: UpdateMap copies the values in the module passed in to the
// corresponding module in the server's copy of the map.
//
///////////////////////////////////////////////////////////////////
public void UpdateMap(Module m, int client_id) {
if(! thread_running) {
try {
Module old_module = map.GetModule(client_id);
int num_nodes = m.GetNumNodes();
Node new_node, old_node;
for(int i=0; i<num_nodes; i++) {
new_node = m.GetNode(i);
old_node = old_module.GetNode(i);
old_node.SetStable(new_node.IsStable());
old_node.SetRecovery(new_node.GetRecovery());
}
}
catch (Exception e) {
Error(e);
}
}
}
///////////////////////////////////////////////////////////////////
//
// Method: BeginSimulation
//
// Invoker: ServerRMI
//
// Purpose: BeginSimulation copies the passed values for propagation
// method and delay into the corresponding member variables
// and then starts the thread that propagates the instabilities.
//
///////////////////////////////////////////////////////////////////
public void BeginSimulation(int p, long d) {
delay = d;
propagation_method = p;
map.SetEditable(false);
map.SetFinal(false);
thread_running = true;
compute_engine = new ServerThread(server_rmi, this);
compute_engine.start();
}
///////////////////////////////////////////////////////////////////
//
// Method: SubmitMode
//
// Invoker: ServerRMI
//
// Purpose: SubmitMode sets the mode and iterations variables to the
// passed values. If the mode is manual, the iterations variable
// is set to 1 by default.
//
///////////////////////////////////////////////////////////////////
public boolean SubmitMode(int m, int runs) {
mode = m;
if(mode == manual_mode) {
iterations = 1;
map.SetEditable(true);
}
else {
iterations = runs;
}
return true;
}
///////////////////////////////////////////////////////////////////
//
// Method: PrintMessage
//
// Invoker: ServerRMI, ServerThread
//
// Purpose: PrintMessage prints a message to the screen via the server.
//
///////////////////////////////////////////////////////////////////
public void PrintMessage(String s) {
server.PrintMessage(s);
}
///////////////////////////////////////////////////////////////////
//
// Method: GetMap
//
// Invoker: ServerRMI, ServerThread
//
// Purpose: GetMap returns the current map.
//
///////////////////////////////////////////////////////////////////
public Map GetMap() {
return map;
}
///////////////////////////////////////////////////////////////////
//
// Method: GetNumClients
//
// Invoker: ServerThread
//
// Purpose: GetNumClients returns the current number of clients.
//
///////////////////////////////////////////////////////////////////
public int GetNumClients() {
return num_clients;
}
///////////////////////////////////////////////////////////////////
//
// Method: GetDelay
//
// Invoker: ServerThread
//
// Purpose: GetDelay returns the current delay.
//
///////////////////////////////////////////////////////////////////
public long GetDelay() {
return delay;
}
///////////////////////////////////////////////////////////////////
//
// Method: GetPropagationMethod
//
// Invoker: ServerThread
//
// Purpose: GetPropagationMethod returns the current propagation method.
//
///////////////////////////////////////////////////////////////////
public int GetPropagationMethod() {
return propagation_method;
}
///////////////////////////////////////////////////////////////////
//
// Method: Error
//
// Invoker: ServerRMI, ServerThread
//
// Purpose: Error passes exceptions along to the Server for a stack
// dump.
//
///////////////////////////////////////////////////////////////////
public void Error (Exception e) {
server.Error(e);
}
///////////////////////////////////////////////////////////////////
//
// Method: Abort
//
// Invoker: ServerRMI
//
// Purpose: Abort stops the currently executing thread, stabilizes
// the map, and makes the map final and non-editable.
//
///////////////////////////////////////////////////////////////////
public boolean Abort() {
try {
compute_engine.stop();
map.SetStable(true);
map.SetFinal(true);
map.SetEditable(false);
server_rmi.RunEnded();
}
catch (Exception e) {
Error(e);
}
return true;
}
///////////////////////////////////////////////////////////////////
//
// Method: GetMode
//
// Invoker: ServerThread
//
// Purpose: GetMode returns the current mode (auto or manual).
//
///////////////////////////////////////////////////////////////////
public int GetMode() {
return mode;
}
///////////////////////////////////////////////////////////////////
//
// Method: GetIterations
//
// Invoker: ServerThread
//
// Purpose: Returns the current number of iterations.
//
///////////////////////////////////////////////////////////////////
public int GetIterations() {
return iterations;
}
///////////////////////////////////////////////////////////////////
//
// Method: SetThreadRunning
//
// Invoker: ServerThread
//
// Purpose: SetThreadRunning sets the variable thread_running to the
// passed boolean.
//
///////////////////////////////////////////////////////////////////
public void SetThreadRunning(boolean b) {
thread_running = b;
}
public void ShutDown() {
server.ShutDown();
}
}