package org.infinispan.remoting.transport.jgroups;
import org.infinispan.commons.marshall.StreamingMarshaller;
import java.util.concurrent.Executor;
import org.infinispan.remoting.responses.CacheNotFoundResponse;
import org.jgroups.Address;
import org.jgroups.View;
import org.jgroups.blocks.Request;
import org.jgroups.blocks.RequestCorrelator;
import org.jgroups.blocks.RequestHandler;
import org.jgroups.conf.ClassConfigurator;
import org.jgroups.stack.Protocol;
import org.jgroups.util.Util;
/**
* Extend {@link RequestCorrelator} to use our own marshaller.
*
* @author Dan Berindei
* @since 9.0
*/
class CustomRequestCorrelator extends RequestCorrelator {
private final Executor remoteExecutor;
private final StreamingMarshaller ispnMarshaller;
public CustomRequestCorrelator(Protocol transport, RequestHandler handler, Address local_addr,
Executor remoteExecutor, StreamingMarshaller ispnMarshaller) {
// Make sure we use the same protocol id as the parent class
super(ClassConfigurator.getProtocolId(RequestCorrelator.class), transport, handler, local_addr);
this.remoteExecutor = remoteExecutor;
this.ispnMarshaller = ispnMarshaller;
}
@Override
protected void handleResponse(Request req, Address sender, byte[] buf, int offset, int length,
boolean is_exception) {
Object retval;
if (length == 0) {
// Empty buffer signals the ForkChannel with this name is not running on the remote node
retval = CacheNotFoundResponse.INSTANCE;
} else {
try {
retval = ispnMarshaller.objectFromByteBuffer(buf, offset, length);
} catch (Exception e) {
log.error(Util.getMessage("FailedUnmarshallingBufferIntoReturnValue"), e);
retval = e;
is_exception = true;
}
}
req.receiveResponse(retval, sender, is_exception);
}
@Override
public void receiveView(View new_view) {
// Suspecting a node may unblock some commands, which can potentially block that thread for a long time.
// We don't want to block view handling, so we unblock the commands on a separate thread.
// Ideally, we'd unblock each command on a separate thread.
// For regular responses, it's ok to block the OOB thread that received the response:
remoteExecutor.execute(() -> super.receiveView(new_view));
}
}