package senseiTests.concurrency;
import sensei.util.Configuration;
import sensei.util.Error;
import sensei.util.ErrorHandler;
import sensei.util.logging.Logger;
import sensei.util.ParameterException;
import sensei.util.Parameters;
import sensei.domains.DomainGroupHandlerImpl;
import sensei.gmns.GroupMembershipBasicServiceImpl;
import sensei.gmns.GroupMembershipNamingServiceImpl;
import sensei.gmns.GroupMembershipNamingServiceFactory;
import sensei.domains.DynamicSubgroupInfoAsStringImpl;
import sensei.domains.GroupMonitorImpl;
import sensei.middleware.gmns.GroupHandlerFactory;
import sensei.middleware.gms.GroupHandler;
import sensei.middleware.gmns.GroupHandlerFactoryImpl;
import sensei.middleware.gmns.GroupMembershipNamingService;
import sensei.middleware.domains.BehaviourOnViewChanges;
import sensei.middleware.domains.DomainGroupUserBaseImpl;
import sensei.middleware.domains.DomainExpulsionReason;
import sensei.middleware.domains.DomainGroupHandler;
import sensei.middleware.domains.GroupMonitor;
import sensei.middleware.domains.MonitorException;
import sensei.middleware.domains.SubgroupsHandlerException;
import sensei.middleware.domains.TransactionException;
import sensei.middleware.util.ObjectsHandling;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
public class TestMonitor extends DomainGroupUserBaseImpl implements Runnable, ErrorHandler
{
DynamicSubgroupInfoAsStringImpl myInfo;
Map monitors;
DomainGroupHandler domainGroup;
String lastInputLine;
GroupMonitor monitor;
int monitorNumber;
ChatMember chat;
Printer printer;
final static int UNKNOWN = 0;
final static int LOCK = 1;
final static int UNLOCK = 4;
final static int START_TRANSACTION = 11;
final static int END_TRANSACTION = 14;
final static int CREATE_MONITOR = 21;
final static int REMOVE_MONITOR = 25;
final static int MENU = 52;
final static int QUIT = 100;
public void run()
{
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int input=UNKNOWN;
printHelp();
while(input!=QUIT)
{
input=readInput(reader);
switch(input)
{
case CREATE_MONITOR:
createMonitor();
break;
case END_TRANSACTION:
endTransaction();
break;
case LOCK:
lockMonitor(monitor, monitorNumber);
break;
case MENU:
printHelp();
break;
case QUIT:
printer.print("Leaving the group....");
domainGroup.leaveGroup();
break;
case REMOVE_MONITOR:
removeMonitor(monitorNumber);
break;
case START_TRANSACTION:
startTransaction(monitor, monitorNumber);
break;
case UNLOCK:
unlockMonitor(monitor, monitorNumber);
break;
case UNKNOWN:
default:
chat.castString(lastInputLine);
}
}
}
catch(Exception ex)
{
ex.printStackTrace();
System.exit(0);
}
}
void createMonitor() throws Exception
{
printer.print("Creating monitor.....");
GroupMonitorImpl.register(myInfo, domainGroup);
}
void removeMonitor(int number) throws Exception
{
printer.print("Removing monitor "+number+"....");
try
{
domainGroup.removeSubgroup(number, myInfo);
}
catch(SubgroupsHandlerException sex)
{
printer.print("Error removing the monitor. Static subgroups can not be removed!");
}
}
void lockMonitor(GroupMonitor who, int number) throws Exception
{
printer.print("Locking monitor "+number+"....");
who.lock();
printer.print("Monitor " + number + " locked!!!!");
}
void unlockMonitor(GroupMonitor who, int number) throws Exception
{
printer.print("Unlocking monitor "+number+"....");
try
{
who.unlock();
printer.print("Monitor "+number+" unlocked!!!!");
}
catch(MonitorException ex)
{
ex.printStackTrace();
printer.print("This monitor "+number+" has not the lock!");
}
}
void startTransaction(GroupMonitor who, int number) throws Exception
{
printer.print("Starting transaction "+number+"....");
domainGroup.startTransaction(who);
printer.print("Transaction " + number + " started!!!!");
}
void endTransaction() throws Exception
{
printer.print("Ending transaction ....");
try
{
domainGroup.endTransaction();
printer.print("Transaction ended!!!!");
}
catch(MonitorException ex)
{
printer.print("Incorrect transaction on the given monitor");
}
catch(TransactionException ex)
{
printer.print("System is not on a transaction");
}
}
int readInput(BufferedReader reader) throws IOException
{
do
{
printer.onInputRequest();
lastInputLine = reader.readLine();
printer.inputGiven();
if (lastInputLine!=null)
return processLine(lastInputLine.toUpperCase());
}
while(lastInputLine!=null);
return QUIT;
}
int processLine(String line)
{
if (line.equals("Q"))
return QUIT;
else if (line.equals("?"))
return MENU;
else if (line.equals("E"))
return END_TRANSACTION;
else if (line.equals("C"))
return CREATE_MONITOR;
else if (line.startsWith("L"))
return isValidMonitor(line.substring(1), LOCK);
else if (line.startsWith("U"))
return isValidMonitor(line.substring(1), UNLOCK);
else if (line.startsWith("S"))
return isValidMonitor(line.substring(1), START_TRANSACTION);
else if (line.startsWith("R"))
return isValidMonitor(line.substring(1), REMOVE_MONITOR);
return UNKNOWN;
}
int isValidMonitor(String line, int ret)
{
try
{
Integer number = Integer.valueOf(line);
monitor = (GroupMonitor) monitors.get(number);
if (monitor!=null)
{
monitorNumber=number.intValue();
return ret;
}
}
catch(NumberFormatException nex){}
return UNKNOWN;
}
void printHelp()
{
printer.print ("----------------------- HELP --------------------------------\n"
+ "~~~~~~ (Lx): lock monitor --------- (Ux): unlock monitor\n"
+ "~~~~~~ (Sx): start Transaction ---- (E): end Transaction\n"
+ "~~~~~~ (C): create monitor -------- (Rx): remove monitor\n"
+ "~~~~~~ (?): shows this help -------- (Q): quit\n"
+ " The initial monitors are x=1,2,3\n"
+ "-------------------------------------------------------------");
}
public void domainAccepted(int id)
{
printer.print("Member accepted; id="+id);
myInfo = new DynamicSubgroupInfoAsStringImpl(String.valueOf(id));
}
public void offendingSubgroup(int who, String reason)
{
printer.print("Detected a problem on subgroup "+who+" ("+reason+"). To be shortly expulsed...");
}
public void stateObtained(boolean assumed)
{
printer.print("State obtained, monitor's functionality becomes available");
new Thread(this).start();
}
public void domainExpulsed(DomainExpulsionReason reason)
{
printer.print("Member expulsed, reason="+reason.value());
System.exit(0);
}
public TestMonitor(Factory factory, Parameters parameters) throws ParameterException, Exception
{
printer = new Printer();
Error.setErrorHandler(this);
String refFile = parameters.hasParameter(REFFILE)? parameters.getParameter(REFFILE) : null;
String connectFile = parameters.hasParameter(CONNECT)? parameters.getParameter(CONNECT) : null;
String groupName = parameters.hasParameter(GROUP)? parameters.getParameter(GROUP) : null;
String name;
if (parameters.hasParameter(NAME))
{
name = parameters.getParameter(NAME);
Logger.setLogName(name);
}
else
name = "unknown";
domainGroup = new DomainGroupHandlerImpl(). theDomainGroupHandler();
domainGroup.setDomainGroupUser(theDomainGroupUser());
domainGroup.setBehaviourMode(BehaviourOnViewChanges.MembersOnTransferExcludedFromGroup);
monitors = Collections.synchronizedMap(new HashMap());
domainGroup.setDynamicSubgroupsUser(new DynamicCreator(domainGroup, monitors, printer).theDynamicSubgroupsUser());
//A GroupHandler is required, obtaining first the appropiated factory
GroupHandler toStore=null;;
GroupHandlerFactory ghFactory=new GroupHandlerFactoryImpl(domainGroup).theGroupHandlerFactory();
GroupMonitorImpl impl = new GroupMonitorImpl(1, domainGroup);
impl.register();
monitors.put(new Integer(1), impl.theGroupMonitor());
impl = new GroupMonitorImpl(2, domainGroup);
impl.register();
monitors.put(new Integer(2), impl.theGroupMonitor());
impl = new GroupMonitorImpl(3, domainGroup);
impl.register();
monitors.put(new Integer(3), impl.theGroupMonitor());
chat = new ChatMember(factory, printer);
domainGroup.registerSubgroup(4, chat.theGroupMember());
if (groupName!=null)
{
GroupMembershipNamingService service = GroupMembershipNamingServiceFactory.load();
if (service==null)
{
printer.print("GroupMembershipNamingService is not available");
System.exit(0);
}
else
{
toStore=service.findAndJoinGroup(groupName, ghFactory, name, null);
}
}
else if (connectFile==null)
{
toStore=GroupMembershipBasicServiceImpl.utilCreateGroup(ghFactory);
if (toStore==null)
{
printer.print("Error, group not created");
System.exit(0);
}
}
else
{
toStore=GroupMembershipBasicServiceImpl.utilJoinGroup(ObjectsHandling.readObject(connectFile), ghFactory);
if (toStore==null)
{
printer.print("Error, member not added to group on " + connectFile);
System.exit(0);
}
}
if (refFile!=null)
ObjectsHandling.writeObject(toStore, refFile);
}
public boolean handleError(String area, String reason)
{
printer.print("ERROR on "+area+": " + reason);
return false;
}
public boolean handleException(String area, Exception exception)
{
exception.printStackTrace();
return handleError(area,exception.toString());
}
//*************************************************************************************
//**************************** READ ARGS **********************************************
//*************************************************************************************
/**
* Reads the command line arguments, and initializes the
* Configuration singleton class; arguments are translated into the Parameter class and
* returned.
* It returns null if arguments are incorrect or they do not require any GMNS processing
**/
public static Parameters readArgs(String args[])
{
Parameters ret = null;
try
{
Vector params=new Vector();
params.add(CONF);
params.add(GROUP);
params.add(NAME);
params.add(CONNECT);
params.add(REFFILE);
params.add(HELP);
ret = new Parameters(args, params, null,0,0);
if (ret.hasParameter(HELP))
{
ret=null;
help();
}
else
{
if (ret.hasParameter(CONF))
Configuration.getSingleton(ret.getParameter(CONF), ret.getDefinitions());
else
Configuration.getSingleton(ret.getDefinitions());
if (ret.hasParameter(GROUP))
if (ret.hasParameter(CONNECT))
throw new ParameterException(CONNECT + " option not compatible with " + GROUP);
else if (ret.hasParameter(REFFILE))
throw new ParameterException(REFFILE + " option not compatible with " + GROUP);
}
}
catch (ParameterException pex)
{
System.err.println("Arguments error: " + pex.getMessage());
help();
}
catch (IOException ioex)
{
System.err.println("Error reading the configuration file: " + ioex.getMessage());
}
return ret;
}
//*************************************************************************************
//**************************** HELP ***************************************************
//*************************************************************************************
static void help()
{
System.out.println("arguments: [options...]\n\tOptions:\n\t\t"
+ CONF + "=configuration file\n\t\t\t--> sensei properties file \n\t\t"
+ GROUP + "=group name\n\t\t\t--> group name if a GMNS service is running \n\t\t"
+ NAME + "=name\n\t\t\t--> Identifies this monitor (logging & GMNS) \n\t\t"
+ CONNECT + "=group member reference file\n\t\t\t--> file with the reference of a group member to join \n\t\t"
+ REFFILE + "=reference file\n\t\t\t--> file to include the reference of this server\n\t\t"
+ HELP + "\n\t\t\t--> shows this brief help \n\n\t"
);
}
//*************************************************************************************
//**************************** DATA MEMBERS *******************************************
//*************************************************************************************
static final String CONF = "config";
static final String GROUP = "group";
static final String NAME = "name";
static final String CONNECT = "connect";
static final String REFFILE = "reffile";
static final String HELP = "help";
}