package com.yahoo.dtf.rendezvous;
import com.yahoo.dtf.actions.Action;
import com.yahoo.dtf.actions.rendezvous.Rendezvous_reset;
import com.yahoo.dtf.actions.rendezvous.Rendezvous_visit;
import com.yahoo.dtf.exception.DTFException;
import com.yahoo.dtf.exception.ParseException;
import com.yahoo.dtf.exception.RendezvousException;
import com.yahoo.dtf.logger.DTFLogger;
public class RendezvousPoint {
private static DTFLogger _logger = DTFLogger.getLogger(RendezvousPoint.class);
private String _id = null;
private String _cid = null;
private int _parties = 0;
private int _current = 0;
public RendezvousPoint(String id,
int parties,
String cid) {
_cid = cid;
_id = id;
_parties = parties;
}
public boolean isLocal() throws ParseException {
// localid is null when you haven't connected to the controller
return (Action.getLocalID() == null || Action.getLocalID().equals(_cid) || _cid == null );
}
public void visit() throws RendezvousException { visit(-1); }
public String getId() { return _id; }
public int getParties() { return _parties; }
public void visit(long timeout) throws RendezvousException {
try {
if ( !isLocal() ) {
if ( _logger.isDebugEnabled() )
_logger.debug("Remote rendezvous visit [" + getId() +
"] on [" + _cid + "] ");
Rendezvous_visit visit = new Rendezvous_visit();
visit.setId(getId());
visit.setTimeout(""+timeout);
Action.getComm().sendActionToCaller(_cid, visit).execute();
} else {
if ( _logger.isDebugEnabled() )
_logger.debug("Local rendezvous visit [" + getId() +
"] on [" + _cid + "]");
synchronized (this) {
_current++;
if ( _current == _parties )
notifyAll();
if ( _current < _parties ) {
try {
if ( timeout == -1 )
wait();
else
wait(timeout);
} catch (InterruptedException ignore) { }
if ( _current < _parties )
throw new RendezvousException("Timedout on SyncPoint.");
}
}
}
} catch (DTFException e) {
throw new RendezvousException("Unable to access remote rendezvous point.",e);
}
}
/**
* Check if the current SyncPoint has enough visitors with this visitor that
* is currently checking.
*
* @return
* @throws RendezvousException
*/
public boolean check() throws RendezvousException {
try {
if (!isLocal()) {
if (_logger.isDebugEnabled()) {
_logger.debug("Remote rendezvous check [" + getId()
+ "] on [" + _cid + "] ");
}
RendezvousCheck check = new RendezvousCheck();
check.setId(getId());
Action result = Action.getComm().sendActionToCaller(_cid, check);
RemoteResult rr = (RemoteResult) result
.findFirstAction(RemoteResult.class);
assert (rr != null) : "Fatal error no RemoteResults.";
return rr.getBool();
} else {
synchronized (this) {
return (_parties <= (_current + 1));
}
}
} catch (DTFException e) {
throw new RendezvousException(
"Unable to access remote rendezvous point.", e);
}
}
/**
* Reset the _current parties counter and make sure that all currently
* waiting parties are notified.
* @throws RendezvousException
*/
public void reset() throws RendezvousException {
try {
if (!isLocal()) {
if (_logger.isDebugEnabled()) {
_logger.debug("Remote rendezvous reset [" + getId()
+ "] on [" + _cid + "] ");
}
Rendezvous_reset reset = new Rendezvous_reset();
reset.setId(getId());
Action.getComm().sendActionToCaller(_cid, reset).execute();
} else {
synchronized (this) {
_current = 0;
notifyAll();
}
}
} catch (DTFException e) {
throw new RendezvousException(
"Unable to access remote rendezvous point.", e);
}
}
public String toString() {
return getClass().getSimpleName() + " [id: " + _id + ", parties: " +
_parties + ", current: " + _current + "]";
}
}