package cassandra;
import cassandra.protocol.CassandraMessage.Request;
import cassandra.protocol.CassandraMessage.Response;
import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.EventExecutorGroup;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.Promise;
import io.netty.util.internal.PlatformDependent;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
public class CassandraFuture {
public static interface Listener {
public static final Listener CLOSE = new Listener() {
@Override
public void completed(CassandraFuture future) throws Exception {
future.connection().close();
}
};
public static final Listener CLOSE_ON_FAILURE = new Listener() {
@Override
public void completed(CassandraFuture future) throws Exception {
if (!future.isSuccess()) {
future.connection().close();
}
}
};
void completed(CassandraFuture future) throws Exception;
}
public static final long DEADLINE = 10000;
private final CassandraConnection connection;
private final Request request;
private final Promise<Response> promise;
private final long createdAt;
public CassandraFuture(EventExecutorGroup eventExecutor, CassandraConnection connection, Request request) {
this.connection = connection;
this.request = request;
promise = new DefaultPromise<Response>(eventExecutor.next());
createdAt = System.currentTimeMillis();
}
public CassandraConnection connection() {
return connection;
}
public Request request() {
return request;
}
public Future<Response> asJavaFuture() {
return promise;
}
public CassandraFuture await() {
await(DEADLINE);
return this;
}
public boolean await(long timeout) {
return promise.awaitUninterruptibly(timeout(timeout));
}
public Response get() {
return get(promise, DEADLINE);
}
public Response get(long timeout) {
return get(promise, timeout);
}
public boolean isDone() {
return promise.isDone();
}
public boolean isSuccess() {
return promise.isSuccess();
}
public boolean setSuccess(Response result) {
return promise.trySuccess(result);
}
public Throwable cause() {
return promise.cause();
}
public boolean setFailure(Throwable cause) {
return promise.tryFailure(cause);
}
public boolean isExpired() {
return isExpired(System.currentTimeMillis());
}
public boolean isExpired(long now) {
return (createdAt + DEADLINE) < now;
}
public long createdAt() {
return createdAt;
}
public CassandraFuture addListener(final Listener listener) {
if (listener == null) {
throw new NullPointerException("listener");
}
promise.addListener(new GenericFutureListener<io.netty.util.concurrent.Future<Response>>() {
@Override
public void operationComplete(io.netty.util.concurrent.Future<Response> future) throws Exception {
listener.completed(CassandraFuture.this);
}
});
return this;
}
static <T> T get(Promise<T> promise, long timeout) {
Throwable cause;
if (!promise.awaitUninterruptibly(timeout(timeout))) {
cause = new TimeoutException();
} else {
cause = promise.cause();
}
if (cause != null) {
PlatformDependent.throwException(cause);
}
return promise.getNow();
}
static long timeout(long timeout) {
if (timeout <= 0) {
throw new IllegalArgumentException(String.format("timeout: %d (expected: >= 0)", timeout));
}
return Math.min(timeout, DEADLINE);
}
}