package org.dcache.util; import javax.security.auth.Subject; import java.util.concurrent.TimeUnit; import diskCacheV111.util.CacheException; import diskCacheV111.util.FsPath; import diskCacheV111.util.PnfsHandler; import diskCacheV111.util.TimeoutCacheException; import org.dcache.auth.attributes.Restriction; import static org.dcache.util.MathUtils.addWithInfinity; import static org.dcache.util.MathUtils.subWithInfinity; /** * A transfer where the mover can send a redirect message to the door. */ public class RedirectedTransfer<T> extends Transfer { private boolean _isRedirected; private T _redirectObject; public RedirectedTransfer(PnfsHandler pnfs, Subject namespaceSubject, Restriction restriction, Subject subject, FsPath path) { super(pnfs, namespaceSubject, restriction, subject, path); } public RedirectedTransfer(PnfsHandler pnfs, Subject subject, Restriction restriction, FsPath path) { super(pnfs, subject, restriction, path); } /** * Signals that the transfer is redirected. */ public synchronized void redirect(T object) { _isRedirected = true; _redirectObject = object; notifyAll(); } /** * Returns the redirect object injected through a call to * <code>redirect</code>, or null if <code>redirect</code> has not * been called. */ public synchronized T getRedirect() { return _redirectObject; } /** * Blocks until the mover of this transfer has send a redirect * notification, until a timeout is reached, or until the mover * failed. Relies on the redirect being injected into the transfer * through the <code>redirect</code> method. * * @param millis The timeout in milliseconds * @return The redirect object * @throws CacheException if the mover failed * @throws TimeoutCacheException when the timeout was reached * @throws InterruptedException if the thread was interrupted */ public synchronized T waitForRedirect(long millis) throws CacheException, InterruptedException { try { setStatus("Mover " + getPool() + "/" + getMoverId() + ": Waiting for redirect"); long deadline = addWithInfinity(System.currentTimeMillis(), Math.max(0, millis)); while (hasMover() && !_isRedirected && System.currentTimeMillis() < deadline) { wait(subWithInfinity(deadline, System.currentTimeMillis())); } if (waitForMover(0)) { throw new CacheException("Mover finished without redirect"); } else if (!_isRedirected) { throw new TimeoutCacheException("No redirect from mover"); } } finally { setStatus(null); } return _redirectObject; } public synchronized T waitForRedirect(long timeout, TimeUnit unit) throws CacheException, InterruptedException { return waitForRedirect(unit.toMillis(timeout)); } }