package alma.acs.monitoring.blobber; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; /** * A "stack" of size one for a given data item: First the data must be stored (in method {@link #put(Object)}), then it * can alternately be popped (method {@link #take()}) and pushed again. The pushing and popping get blocked until the * stack is free or full respectively. */ public class DataLock<C> { private final BlockingQueue<C> delegate = new ArrayBlockingQueue<C>(1); /** * Timeout in seconds. Used to make tests fail rather than hang. */ public static final int timeoutSec = 100; private final Logger logger; private final String name; /** * @param logger * @param name Used for debug logs */ public DataLock(Logger logger, String name) { this.logger = logger; this.name = name; } /** * Stores the given data as soon as previously stored data gets taken. * @param inData The data. * @throws InterruptedException If interrupted (e.g. by timeout) while blocking. */ public void put(C inData) throws InterruptedException { logger.finer("DataLock " + name + ": Got a call to put(" + inData.getClass().getSimpleName() + "); thread = " + Thread.currentThread().getName() + "; lockReady=" + (delegate.size() == 0)); if (delegate.offer(inData, timeoutSec, TimeUnit.SECONDS)) { logger.finer("DataLock " + name + ": Returning from put(" + inData.getClass().getSimpleName() + ")."); } else { logger.warning("DataLock " + name + ": Timed out in put(" + inData.getClass().getSimpleName() + ")."); throw new InterruptedException("Storing data was interrupted by timeout=" + timeoutSec + " s."); } } /** * Retrieves data, as soon as data becomes available. * @return The data. * @throws InterruptedException If the call gets interrupted while waiting for data, e.g. timeout. */ public C take() throws InterruptedException { logger.finer("DataLock " + name + ": Got a call to take(); thread = " + Thread.currentThread().getName() + "; lockReady=" + (delegate.size() > 0)); C data = delegate.poll(timeoutSec, TimeUnit.SECONDS); if (data != null) { logger.finer("DataLock " + name + ": Returning from take()."); return data; } else { logger.warning("DataLock " + name + ": Timed out in take()."); throw new InterruptedException("Fetching data was interrupted by timeout=" + timeoutSec + " s."); } } }