package com.yahoo.dtf.comm; import java.io.InvalidClassException; import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RMISecurityManager; import java.rmi.RemoteException; import java.util.Iterator; import java.util.concurrent.atomic.AtomicLong; import com.yahoo.dtf.DTFNode; import com.yahoo.dtf.actions.Action; import com.yahoo.dtf.actions.component.Attrib; import com.yahoo.dtf.actions.protocol.Connect; import com.yahoo.dtf.comm.rpc.ActionResult; import com.yahoo.dtf.comm.rpc.NodeInterface; import com.yahoo.dtf.exception.CommException; import com.yahoo.dtf.exception.DTFException; import com.yahoo.dtf.logger.DTFLogger; import com.yahoo.dtf.state.DTFState; public class CommRMIClient extends CommClient { private static DTFLogger _logger = DTFLogger.getLogger(CommRMIClient.class); private CommServer _server = null; private NodeInterface _node = null; public CommRMIClient(String caddr, int cport) throws DTFException { this(caddr, cport, null); } public CommRMIClient(String caddr, int cport, CommServer server) throws DTFException { super(caddr,cport); System.setSecurityManager(new RMISecurityManager()); _server = server; try { if (_logger.isDebugEnabled()) _logger.debug("Connecting to " + getAddr() + ":" + getPort()); _node = (NodeInterface) Naming.lookup("rmi://" + getAddr() + ":" + getPort() + "/node"); } catch (RemoteException e) { throw new CommException("Unable to connect to DTFC.",e); } catch (NotBoundException e) { throw new CommException("Unable to connect to DTFC.",e); } catch (MalformedURLException e) { throw new CommException("Unable to connect to DTFC.",e); } } public Boolean heartbeat() { try { return _node.heartbeat(); } catch (RemoteException e) { return false; } } public void printStats() { } /** * This little method tries to do its best to only throw exceptions that * are important to the person running the test. This avoids all of the * exception layering that happens when using Communication APIs such as * RMI between the various components. * * @param e * @param message * @throws DTFException */ private void convertException(RemoteException e, String message) throws DTFException { Throwable aux = e.getCause(); while (aux != null) { if (aux instanceof DTFException) { throw (DTFException)aux; } if (aux instanceof InvalidClassException) { throw new RuntimeException("You are running two different " + "builds of DTF and there are " + "incompatible class versions.", e.getCause()); } aux = aux.getCause(); } throw new CommException(message,e); } private AtomicLong actioncounter = new AtomicLong(0); public ActionResult sendAction(String id, Action action) throws DTFException { try { actioncounter.incrementAndGet(); return _node.execute(id, action); } catch (RemoteException e) { convertException(e,"Error sending action."); } finally { actioncounter.decrementAndGet(); } throw new RuntimeException("This line should never be executed."); } @Override public boolean isSendingAction() { return actioncounter.intValue() != 0; } public void shutdown() { } public void unregister(DTFState state) throws DTFException { String id = Action.getLocalID(); if (id == null) return; Connect connect; connect = new Connect(id); /* * Put default Attribs into connect message. */ Iterator objs = _attribs.values().iterator(); while (objs.hasNext()) { Attrib attrib = (Attrib) objs.next(); connect.addAttrib(attrib); } try { _node.unregister(connect).execute(); } catch (RemoteException e) { convertException(e,"Unable to register node."); } } public void register() throws DTFException { String id = Action.getLocalID(); Connect connect; connect = new Connect(id); /* * Put default Attribs into connect message. */ Iterator objs = _attribs.values().iterator(); while (objs.hasNext()) { Attrib attrib = (Attrib) objs.next(); connect.addAttrib(attrib); } connect.setAddress(_server.getAddress()); connect.setPort(_server.getPort()); connect.setBuildid(DTFNode.getBuildID()); if ( _logger.isDebugEnabled() ) { _logger.debug("Registering " + connect); } try { _node.register(connect).execute(); } catch (RemoteException e) { convertException(e, "Unable to register."); } } }