package ecologylab.oodss.logging;
import java.io.IOException;
import java.net.BindException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.channels.SelectionKey;
import ecologylab.collections.Scope;
import ecologylab.generic.Debug;
import ecologylab.net.NetTools;
import ecologylab.oodss.distributed.common.ServicesHostsAndPorts;
import ecologylab.oodss.distributed.server.DoubleThreadedNIOServer;
import ecologylab.oodss.messages.DefaultServicesTranslations;
import ecologylab.serialization.SimplTypesScope;
/**
* A server that automatically records any incoming log data to a local file. The file is specified
* by the Prologue provided by the Logging client.
*
* @see ecologylab.oodss.logging.Logging
*
* @author Zachary O. Toups (zach@ecologylab.net)
*
*/
public class NIOLoggingServer extends DoubleThreadedNIOServer implements ServicesHostsAndPorts
{
String logFilesPath = "";
public static final String LOG_FILES_PATH = "LOG_FILES_PATH";
public static final Class LOGGING_CLASSES[] =
{ LogOps.class, LogEvent.class,
LogueMessage.class, Prologue.class, SendEpilogue.class, SendPrologue.class,
MixedInitiativeOp.class, Epilogue.class };
public static final int MAX_MESSAGE_SIZE_CHARS_LOGGING = 1024 * 1024; // 1MB
/**
* This is the actual way to create an instance of this.
*
* @param portNumber
* @param translationScope
* @param objectRegistry
* @param authListFilename
* - a file name indicating the location of the authentication list; this should be an
* XML file of an AuthenticationList object.
* @return A server instance, or null if it was not possible to open a ServerSocket on the port on
* this machine.
*/
public static NIOLoggingServer getInstance(InetAddress inetAddress, Scope objectRegistry,
int idleConnectionTimeout, int maxPacketSize)
{
InetAddress[] addr =
{ inetAddress };
return getInstance(addr, objectRegistry, idleConnectionTimeout, maxPacketSize);
}
/**
* This is the actual way to create an instance of this.
*
* @param portNumber
* @param translationScope
* @param objectRegistry
* @param authListFilename
* - a file name indicating the location of the authentication list; this should be an
* XML file of an AuthenticationList object.
* @return A server instance, or null if it was not possible to open a ServerSocket on the port on
* this machine.
*/
public static NIOLoggingServer getInstance(InetAddress[] inetAddress, Scope objectRegistry,
int idleConnectionTimeout, int maxPacketSize)
{
NIOLoggingServer newServer = null;
try
{
newServer = new NIOLoggingServer(LOGGING_PORT, inetAddress, null, objectRegistry,
idleConnectionTimeout, maxPacketSize);
}
catch (IOException e)
{
println("ServicesServer ERROR: can't open ServerSocket on port " + LOGGING_PORT);
e.printStackTrace();
}
return newServer;
}
/**
* Launches an instance of the logging server.
*
* @param args
* the parameters for the server instance: first argument is the local directory to which
* to write files; second argument is the maximum packet size to accept from the client.
* @throws UnknownHostException
*/
public static void main(String args[]) throws UnknownHostException
{
int mPL = MAX_MESSAGE_SIZE_CHARS_LOGGING;
if (args.length > 1)
{
try
{
int newMPL = Integer.parseInt(args[1]);
mPL = newMPL;
}
catch (NumberFormatException e)
{
Debug.println("second argument was not an integer, using MAX_MESSAGE_SIZE_CHARS_LOGGING: "
+ MAX_MESSAGE_SIZE_CHARS_LOGGING);
e.printStackTrace();
}
}
else
{
Debug.println("No max packet length specified, using " + mPL);
}
NIOLoggingServer loggingServer = getInstance(NetTools.getAllInetAddressesForLocalhost(),
new Scope(), -1, mPL);
if (loggingServer != null)
{
if (args.length > 0)
{
loggingServer.setLogFilesPath(args[0]);
}
if (args.length > 2)
Debug.setLoggingFile(args[2]);
loggingServer.start();
}
}
protected NIOLoggingServer(int portNumber, InetAddress[] inetAddresses,
SimplTypesScope requestTranslationSpace, Scope applicationObjectScope,
int idleConnectionTimeout, int maxPacketSize) throws IOException, BindException
{
super(portNumber, inetAddresses, SimplTypesScope.get(connectionTscopeName(inetAddresses,
portNumber), DefaultServicesTranslations.get(), requestTranslationSpace, LOGGING_CLASSES),
applicationObjectScope, idleConnectionTimeout, maxPacketSize);
// add the necessary scope object mappings for logging
// note this is probably null right now...
this.applicationObjectScope.put(LOG_FILES_PATH, this.logFilesPath);
}
/**
* Sets the directory to which to write log files.
*
* @param path
*/
public void setLogFilesPath(String path)
{
logFilesPath = path;
this.applicationObjectScope.put(LOG_FILES_PATH, this.logFilesPath);
}
/**
* @return the log file path.
*/
public String getLogFilesPath()
{
return logFilesPath;
}
@Override
protected LoggingClientSessionManager generateContextManager(String sessionId, SelectionKey sk,
SimplTypesScope translationScopeIn, Scope registryIn)
{
return new LoggingClientSessionManager(sessionId, maxMessageSize, this, this.getBackend(), sk,
translationScopeIn, registryIn);
}
/**
* Displays some information about the logging server, then calls super.start()
*
* @see ecologylab.oodss.distributed.server.DoubleThreadedNIOServer#start()
*/
@Override
public void start()
{
this.debug("------------------------ Logging Server starting ------------------------");
this.debug(" max packet length: " + this.maxMessageSize);
this.debug(" saving logs to: " + this.logFilesPath);
this.debug(" operating on port: " + this.getBackend().getPortNumber());
this.debug("using the following interfaces: ");
for (InetAddress i : this.getBackend().getBoundAddresses())
{
this.debug(" " + i.toString());
}
super.start();
}
}