package net.varkhan.serv.p2p.message.dispatch; import net.varkhan.serv.p2p.connect.PeerAddress; import net.varkhan.serv.p2p.message.MesgPayload; /** * <b></b>. * <p/> * * @author varkhan * @date 5/30/11 * @time 7:54 AM */ public class SingleReceiver implements MesgReceiver { private volatile long timeout; private final long starttime; private volatile boolean cancelled=false; private volatile boolean received =false; private PeerAddress src =null; private PeerAddress dst =null; private String method =null; private MesgPayload message =null; /** * Creates a reply handler for CALL message that will receive and store a single REPL message * * @param timeout the maximum time (in milliseconds) the hanler will wait for a reply before being released * @throws IllegalArgumentException if the value of timeout is negative */ public SingleReceiver(long timeout) throws IllegalArgumentException { if(timeout<=0) throw new IllegalArgumentException("Timeout must be positive or zero"); this.timeout = timeout; this.starttime = System.currentTimeMillis(); } public void receive(PeerAddress src, PeerAddress dst, String method, MesgPayload message) { this.src = src; this.dst= dst; this.method = method; this.message = message; this.received = true; this.notifyAll(); } /** * Indicate whether a single message has been received. * <p/> * This method will block until either a message was received, or the operation failed, timed out, or was cancelled * * @param timeout the maximum time to wait in milliseconds (or {@code 0} to wait forever) * @return {@code true} if a message was successfully received * @throws IllegalArgumentException if the value of timeout is negative * @see #isReceived() * @see #isCancelled() */ public boolean isReceived(long timeout) throws IllegalArgumentException { if(timeout<=0) throw new IllegalArgumentException("Timeout must be positive or zero"); if(timeout==0) { while(!finished() && !cancelled) try { // We need synchronization to allow us to wait() synchronized(this) { this.wait(); } } catch (InterruptedException e) { // Ignore spurious interrupts } return received; } else { long time = System.currentTimeMillis(); while(!finished() && timeout>0) try { // We need synchronization to allow us to wait() synchronized(this) { this.wait(timeout); } } catch (InterruptedException e) { // Ignore spurious interrupts, but update the timer long t = System.currentTimeMillis(); timeout = timeout+time-t; time = t; } return received; } } /** * Indicate whether a single message has been received. * <p/> * This method return immediately. * * @return {@code true} if a message was successfully received * @see #isReceived(long) */ public boolean isReceived() { return received; } public void cancel() { this.cancelled = true; this.notifyAll(); } public boolean isCancelled() { return cancelled; } public PeerAddress getSrc() { if(!received) return null; return src; } public PeerAddress getDst() { if(!received) return null; return dst; } public String getMethod() { if(!received) return null; return method; } public MesgPayload getMessage() { if(!received) return null; return message; } public void release() { this.cancelled = true; this.notifyAll(); } public boolean finished() { return received || cancelled || timeout<(System.currentTimeMillis()-starttime); } /** * Set the maximum amount of time the handler will wait for a reply * * @param timeout the maximum reply time, in milliseconds */ public void setMaxDelay(long timeout) { this.timeout = timeout; } public long getMaxDelay() { return timeout; } public long getMaxCount() { return 1; } }