package freenet.store; import java.io.IOException; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class WriteBlockableFreenetStore<T extends StorableBlock> extends ProxyFreenetStore<T> { private boolean blocked; private int countBlocked; private final Lock lock = new ReentrantLock(); private final Condition blockedChanged = lock.newCondition(); private final Condition countBlockedIncreased = lock.newCondition(); public WriteBlockableFreenetStore(FreenetStore<T> backDatastore, boolean initialValue) { super(backDatastore); blocked = initialValue; } @Override public void put(T block, byte[] data, byte[] header, boolean overwrite, boolean oldBlock) throws IOException, KeyCollisionException { waitForUnblocked(); super.put(block, data, header, overwrite, oldBlock); } void waitForUnblocked() { lock.lock(); try { countBlocked++; countBlockedIncreased.signalAll(); while(blocked) { blockedChanged.awaitUninterruptibly(); } } finally { countBlocked--; lock.unlock(); } } public void setBlocked(boolean blocked) { lock.lock(); try { this.blocked = blocked; blockedChanged.signalAll(); } finally { lock.unlock(); } } public void unblock() { setBlocked(false); } public void block() { setBlocked(true); } public int countBlocked() { lock.lock(); try { return countBlocked; } finally { lock.unlock(); } } public void waitForSomeBlocked(int minBlocked) { lock.lock(); try { while(countBlocked < minBlocked) { countBlockedIncreased.awaitUninterruptibly(); } } finally { lock.unlock(); } } public void waitForSomeBlocked() { waitForSomeBlocked(1); } }