package scs.execution_node.servant;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Properties;
import org.omg.PortableServer.POAPackage.ServantNotActive;
import org.omg.PortableServer.POAPackage.WrongPolicy;
import scs.core.IComponent;
import scs.core.ShutdownFailed;
import scs.core.InvalidName;
import scs.event_service.servant.EventManagerServant;
import scs.execution_node.ContainerAlreadyExists;
import scs.execution_node.ContainerDescription;
import scs.execution_node.ExecutionNodePOA;
import scs.execution_node.Property;
/**
* Servant que implementa a interface scs::execution_node::ExecutionNode
* @author Eduardo Fonseca / Luiz Marques
*/
public class ExecutionNodeServant extends ExecutionNodePOA {
/**
* Container de "containers" do SCS
*/
private ArrayList<ContainerDescription> containers = null;
/**
* Tempo de espera para criacao do container em milissegundos
*/
private long timeout = 10000;
/**
* Timeout default para criacao do container
*/
private final static long DEFAULT_TIMEOUT = 10; //s
/**
* Tempo de espera entre duas verificacoes do status do container executado
*/
private final static int SLEEP_TIME = 500;
/**
* Container de configuracoes do ExecutionNode
*/
private Properties config;
/**
* ExecutionNodeComponent
*/
private IComponent execNodeComponent;
/**
* Referencia para o event manager instanciado para auxiliar na notificacao de metodos
*/
private EventManagerServant evMgr = new EventManagerServant();
private org.omg.CORBA.Object objEvMgr=null;
/**
* Objeto que gerencia a notificacao dos containers executados
*/
ContainerManagerServant containerMgr = new ContainerManagerServant();
org.omg.CORBA.Object containerMgrObj=null;
/**
* @param myComponent IComponent que serve esta faceta, passado para o container
* @param configProp Propriedades lidas da configuracao
*/
public ExecutionNodeServant( IComponent myComponent, Properties configProp ) {
containers = new ArrayList<ContainerDescription>();
this.config = configProp;
this.timeout = Long.parseLong(this.config.getProperty("timeout", String.valueOf(DEFAULT_TIMEOUT))) * 1000;
this.execNodeComponent = myComponent;
}
/* (non-Javadoc)
* @see SCS.ExecutionNodeOperations#getContainer(java.lang.String)
*/
public IComponent getContainer(String container_name) {
ContainerDescription cont = this.findContainer(container_name);
if(cont!=null) {
return cont.container;
}
return null;
}
/* (non-Javadoc)
* @see SCS.ExecutionNodeOperations#getContainers()
*/
public ContainerDescription[] getContainers() {
return this.containers.toArray(new ContainerDescription[this.containers.size()]);
}
/**
* Metodo privado para localizar o container por nome na estrutura de containers
* @param name
* @return
*/
private ContainerDescription findContainer(String name) {
for (Iterator<ContainerDescription> iter = this.containers.iterator(); iter.hasNext();) {
ContainerDescription cont = iter.next();
if( cont.container_name.equals(name))
return cont;
}
return null;
}
/**
* Executa o processo do container, passando os parametros:
* - IOR do objeto container manager
* - IOR do objeto EventManager criado para notificacao de chamadas de metodos
* - nome do container sendo criado
*
* A linha de comando para a execucao do container vem do arquivo de configuracao
*
* Apos a execucao do container, aguarda a notificacao atraves da interface
* ContainerManger, por um tempo definido pela variavel membro timeout
*
* @return container
*/
private IComponent executeContainer(String containerName) {
String cmdline = this.config.getProperty("container.java");
if(cmdline == null) {
System.err.println("Parameter container.java not found.");
return null;
}
try {
containerMgrObj = this._poa().servant_to_reference(containerMgr);
objEvMgr = this._poa().servant_to_reference(evMgr);
} catch (ServantNotActive e) {
e.printStackTrace();
} catch (WrongPolicy e) {
e.printStackTrace();
}
if( containerMgrObj== null || objEvMgr==null )
return null;
/*
* Adiciona o IOR do ContainerManager criado na linha de comando do container
*/
String cmgrIOR = this._orb().object_to_string(containerMgrObj);
String evMgrIOR = this._orb().object_to_string(objEvMgr);
cmdline += " " + cmgrIOR + " " + evMgrIOR + " "+ containerName;
IComponent container=null;
synchronized (this) {
try {
System.out.println("Executing container: " + cmdline );
Runtime.getRuntime().exec(cmdline);
Thread.sleep(SLEEP_TIME);
int elapsed = SLEEP_TIME;
while( (container=containerMgr.getContainer(containerName)) == null ) {
if( timeout!=0 && elapsed > this.timeout ) {
System.err.println("Timeout for container expired, exiting ...");
return null;
}
Thread.sleep(SLEEP_TIME);
elapsed += SLEEP_TIME;
}
} catch (IOException e) {
System.err.println("IOException ocurred while executing " + cmdline);
} catch (InterruptedException e) {
System.err.println("InterruptedException ocurred while executing " + cmdline);
}
}
return container;
}
/* (non-Javadoc)
* @see SCS.ExecutionNodeOperations#startContainer(java.lang.String, SCS.Property[])
*/
public IComponent startContainer(String container_name, Property[] props)
throws ContainerAlreadyExists {
IComponent container = null;
if( this.findContainer(container_name) != null )
throw new ContainerAlreadyExists();
container = this.executeContainer(container_name);
if( container == null ) {
System.err.println("Error executing container " + container_name);
return null;
}
ContainerDescription desc = new ContainerDescription();
desc.container = container;
desc.container_name = container_name;
desc.execution_node = this.execNodeComponent;
this.containers.add(desc);
return container;
}
public void stopContainer(String container_name) throws InvalidName {
ContainerDescription container = findContainer(container_name);
if(containers.contains(container))
{
containers.remove(container);
containerMgr.unregisterContainer(container_name);
}
try {
container.container.shutdown();
System.out.println(container_name + " was stopped");
} catch (ShutdownFailed e) {
System.err.println("Error stopping container " + container_name);
e.printStackTrace();
}
}
public String getName() {
InetAddress addr;
try {
addr = InetAddress.getLocalHost();
return addr.getHostName();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return "no name";
}
}