package freenet.support.api;
import java.io.DataOutputStream;
import java.io.IOException;
import freenet.client.async.ClientContext;
import freenet.support.io.ResumeFailedException;
/** A RandomAccessBuffer which allows you to lock it open for a brief period to indicate that you are
* using it and it would be a bad idea to close the pooled fd. Locking the RAF open does not provide
* any concurrency guarantees but the implementation must guarantee to do the right thing, either
* using a mutex or supporting concurrent writes. Also has methods for persisting itself to a
* DataOutputStream. Implementations must register with BucketTools.restoreRAFFrom().
* @author toad
*/
public interface LockableRandomAccessBuffer extends RandomAccessBuffer {
/** Keep the RAF open. Does not prevent others from writing to it. Will block until a slot is available
* if necessary. Hence can deadlock. */
public RAFLock lockOpen() throws IOException;
public abstract class RAFLock {
private boolean locked;
public RAFLock() {
locked = true;
}
public final void unlock() {
synchronized(this) {
if(!locked)
throw new IllegalStateException("Already unlocked");
locked = false;
}
innerUnlock();
}
protected abstract void innerUnlock();
}
/** Called on resuming, i.e. after serialization. Use to e.g. register with the list of
* temporary files. */
public void onResume(ClientContext context) throws ResumeFailedException;
/** Write enough data to reconstruct the Bucket, or throw UnsupportedOperationException. Used
* for recovering in emergencies, should be versioned if necessary. To make this work, write
* a fixed, unique integer magic value for the class, and add a clause to
* BucketTools.restoreRAFFrom().
* @throws IOException */
public void storeTo(DataOutputStream dos) throws IOException;
/** Must reimplement equals(). Sometimes we will need to compare two RAFs to see if they
* represent the same stored object, notably during resuming a splitfile insert. */
@Override
public abstract boolean equals(Object o);
/** Must reimplement hashCode() if we change equals(). */
@Override
public abstract int hashCode();
}