package org.async.rmi.client;
import org.async.rmi.Connection;
import org.async.rmi.OneWay;
import org.async.rmi.messages.CancelInvokeRequest;
import org.async.rmi.messages.Message;
import org.async.rmi.messages.InvokeRequest;
import org.async.rmi.messages.Response;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.CompletableFuture;
/**
* Created by Barak Bar Orion
* 12/17/14.
*/
public class RequestQueue {
private final UnicastRef unicastRef;
private Queue<RequestHolder> requests;
public RequestQueue(UnicastRef unicastRef) {
this.unicastRef = unicastRef;
this.requests = new LinkedList<>();
}
public synchronized boolean add(InvokeRequest invokeRequest, OneWay oneWay, CompletableFuture<Object> userFuture) {
if (invokeRequest instanceof CancelInvokeRequest) {
if (removeRequest(invokeRequest.getRequestId())) {
return false;
}
}
requests.add(new RequestHolder(invokeRequest, oneWay, userFuture));
return true;
}
private boolean removeRequest(long requestId) {
Iterator<RequestHolder> i = requests.iterator();
while (i.hasNext()) {
RequestHolder holder = i.next();
if (holder.invokeRequest.getRequestId() == requestId) {
i.remove();
return true;
}
}
return false;
}
public synchronized void processRequest(Connection<Message> connection, Throwable throwable, CompletableFuture<Response> responseFuture) {
RequestHolder holder = requests.remove();
if (holder.userFuture != null && holder.userFuture.isCancelled()) {
return;
}
if (throwable != null) {
// fail to connect.
responseFuture.completeExceptionally(throwable);
} else {
unicastRef.trace(holder.invokeRequest, connection);
if (holder.oneWay != null || holder.invokeRequest instanceof CancelInvokeRequest) {
connection.sendOneWay(holder.invokeRequest, responseFuture);
} else {
connection.send(holder.invokeRequest);
}
}
}
private class RequestHolder {
InvokeRequest invokeRequest;
OneWay oneWay;
CompletableFuture<Object> userFuture;
public RequestHolder(InvokeRequest invokeRequest, OneWay oneWay, CompletableFuture<Object> userFuture) {
this.invokeRequest = invokeRequest;
this.oneWay = oneWay;
this.userFuture = userFuture;
}
}
}