package com.yahoo.dtf.actions.protocol; import java.util.ArrayList; import java.util.Hashtable; import com.yahoo.dtf.actions.protocol.Connect; import com.yahoo.dtf.DTFNode; import com.yahoo.dtf.DTFProperties; import com.yahoo.dtf.NodeInfo; import com.yahoo.dtf.NodeState; import com.yahoo.dtf.actions.Action; import com.yahoo.dtf.actions.component.Attrib; import com.yahoo.dtf.comm.Comm; import com.yahoo.dtf.comm.CommClient; import com.yahoo.dtf.comm.CommRMIClient; import com.yahoo.dtf.exception.CommException; import com.yahoo.dtf.exception.DTFException; import com.yahoo.dtf.exception.ParseException; import com.yahoo.dtf.util.CollectionsUtil; /** * This action is used internally for connecting to the DTFC * * @author Rodney Gomes */ public class Connect extends Action { private String id = null; /** * Sending some settings to the dtfc */ private String address = null; private int port = -1; private String buildid = null; public Connect() {} public Connect(String id) throws DTFException { this.id = id; setAddress(getConfig().getProperty(DTFProperties.DTF_LISTEN_ADDR)); setPort(getConfig().getPropertyAsInt(DTFProperties.DTF_LISTEN_PORT)); addAttrib(new Attrib("dtf.tunneled", getConfig().getProperty(DTFProperties.DTF_TUNNELED,"false"), true)); } public void copy(NodeInfo info) throws DTFException { setId(info.getId()); setAddress(info.getAddress()); setPort(info.getPort()); addAttribs(info.findActions(Attrib.class)); } public String getId() { return id; } public void setId(String id) { this.id = id; } public void execute() throws DTFException { if ( !DTFNode.getBuildID().equals(getBuildid()) ) { throw new DTFException("Build Id mismatch [" + getBuildid() + "] != [" + DTFNode.getBuildID() + "], you" + " can not connect to components from" + " different builds."); } boolean tunneled = Boolean.valueOf(findAttrib(DTFProperties.DTF_TUNNELED)); if ( tunneled && !Comm.tunnelExists(getAddress(), getPort()) ) { throw new DTFException("There are no tunnels setup for [" + getAddress() + ":" + getPort() + "] on DTFC."); } // Register myself on the component that just accepted my // ConnectAction object, make sure I dont' have an older // connection laying around and if so remove it. NodeState ns = NodeState.getInstance(); /* * Check for a previous register. */ ArrayList<NodeInfo> nodes = ns.getRegisteredNodes(); for (int i = 0; i < nodes.size(); i++) { NodeInfo nodeinfo = nodes.get(i); if (nodeinfo.equals(this)) { if (getLogger().isDebugEnabled()) getLogger().debug("Found previous register, deleting..."); ns.removeNode(nodeinfo); } } /* * Create the new register. */ CommClient client = new CommRMIClient(getAddress(), getPort()); if (!client.heartbeat()) { throw new CommException("Unable to heartbeat component [" + getId() + "]"); } copy(ns.addNode(this,client)); getLogger().info("Agent " + getId() + " connected, from " + getAddress() + ":" + getPort()); } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public boolean equals(Object obj) { if (obj instanceof Connect) { Connect other = (Connect)obj; if ( other.getId() == null || getId() == null ) return false; if (other.getId().equals(getId()) && other.getAddress().equals(getAddress()) && other.getPort() == getPort()) return true; } return false; } @Override public int hashCode() { assert false: "No hash code assigned"; return 42; } public void addAttrib(Attrib attrib) { ArrayList current_attribs = findActions(Attrib.class); if (!CollectionsUtil.isIn(attrib, current_attribs)) addAction(attrib); } public void addAttribs(ArrayList attribs) { ArrayList current_attribs = findActions(Attrib.class); for (int i = 0; i < attribs.size(); i++) { if (!CollectionsUtil.isIn((Attrib)attribs.get(i), current_attribs)) addAction((Action)attribs.get(i)); } } public String findAttrib(String name) throws ParseException { ArrayList attribs = findActions(Attrib.class); for (int i = 0; i < attribs.size(); i++) { Attrib attrib = (Attrib) attribs.get(i); if (attrib.getName().equals(name)) return attrib.getValue(); } return null; } /** * Just attaching the attributes dangled on the Connect action as well as * the hostname, port and id associated with this Connect. */ protected Hashtable getAttribs(Class actionClass) { Hashtable result = super.getAttribs(actionClass); ArrayList attribs = findActions(Attrib.class); for (int i = 0; i < attribs.size(); i++) { Attrib attrib = (Attrib)attribs.get(i); try { result.put(attrib.getName(),attrib.getValue()); } catch (ParseException e) { getLogger().warn("Unable to get property names.",e); } } /* * Print the host information for this component incase someone needs * access to the agent in order to debug something */ if (getAddress() != null) result.put("hostname",getAddress()); result.put("port",getPort()); if ( getId() != null ) result.put("id",getId()); return result; } public void setBuildid(String buildid) { this.buildid = buildid; } public String getBuildid() { return buildid; } }