package com.yahoo.dtf.actions.protocol; import com.yahoo.dtf.actions.protocol.Connect; import com.yahoo.dtf.actions.protocol.SetupAgent; 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.comm.Comm; import com.yahoo.dtf.comm.rpc.ActionResult; import com.yahoo.dtf.comm.rpc.Node; import com.yahoo.dtf.exception.DTFException; import com.yahoo.dtf.exception.LockException; import com.yahoo.dtf.util.ThreadUtil; public class Lock extends Connect { private String owner = null; private String name = null; /* * Used for direct connection between executer and agents. */ private String address = null; private long timeout = 0; private boolean tunneled = false; public Lock() { } public Lock(String id, String refid, long timeout) throws DTFException{ setId(id); setOwner(Action.getLocalID()); setAddress(getConfig().getProperty(DTFProperties.DTF_LISTEN_ADDR)); setPort(getConfig().getPropertyAsInt(DTFProperties.DTF_LISTEN_PORT)); setName(refid); setTimeout(timeout); } public void execute() throws DTFException { if (getLogger().isDebugEnabled()) getLogger().debug("Attemtping to lock: " + this); NodeState ns = NodeState.getInstance(); NodeInfo[] nis = null; long start = System.currentTimeMillis(); LockException excep = null; do { try { /* * If the node is no longer here then give up on the lock and * don't bother locking anything. */ if ( !ns.isNodeRegistered(getOwner()) ) { if ( getLogger().isDebugEnabled() ) getLogger().debug("Lock owner disconnected, throwing lock request away."); return; } nis = ns.lockNodes(new Lock[]{this}); break; } catch (LockException e) { //if (getLogger().isDebugEnabled()) getLogger().info("Retrying lock: " + this + " for " + getOwner()); excep = e; ThreadUtil.pause(1000); } } while (System.currentTimeMillis() - start < getTimeout()); if (excep != null && nis == null) throw excep; for (NodeInfo ni : nis) setupLock(ni); } protected void setupLock(NodeInfo ni) throws DTFException { /* * Communicate with locked component to register the owner information * that can be later used to identify who locked this component as well * as allow communication between a locked component and the component * that holds this lock. */ SetupAgent sa = new SetupAgent(this); // set the tunneled attribute. sa.setTunneled(Comm.isTunneled()); setTunneled(Comm.isTunneled()); ActionResult ar = ni.getClient().sendAction(ni.getId(), sa); // must check that we did in fact succeed to send the action. ar.execute(); /* * Now that we have a NodeInfo that means we've locked a * component and we can return with this NodeInfo object * the direct connection information for the node requested. */ setAddress(ni.getAddress()); setPort(ni.getPort()); copy(ni); getLogger().info("Locked node " + ni + " for " + ni.getOwner()); ar = (ActionResult) getContext(Node.ACTION_RESULT_CONTEXT); ar.addAction(this); } public void setName(String name) { this.name = name; } public String getName() { return name; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public void setTimeout(long timeout) { this.timeout = timeout; } public long getTimeout() { return timeout; } public void setTunneled(boolean tunneled) { this.tunneled = tunneled; } public boolean getTunneled() { return tunneled; } @Override public boolean equals(Object obj) { return super.equals(obj); } @Override public int hashCode() { return super.hashCode(); } }