com.googlecode.protobuf.pro.duplex.execute.SameThreadExecutor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of protobuf-rpc-pro-duplex Show documentation
Show all versions of protobuf-rpc-pro-duplex Show documentation
Protobuf RPC Pro is a java protocol buffers RPC implementation featuring bidirectional RPC calls and TCP socket connection re-use and the option of secure communications.
/**
* Copyright 2010-2014 Peter Klauser
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.protobuf.pro.duplex.execute;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.WeakHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.protobuf.Message;
import com.google.protobuf.RpcCallback;
/**
* An RpcServerCallExecutor which directly calls the RPC service using the same
* thread that is processing the IO data. This strategy is most efficient however
* succeptable to deadlock if you are intending to perform reverse RPC calls from
* server to SAME client when servicing an RPC call. In this case use
* {@link ThreadPoolCallExecutor}.
*
* Furthermore RPC call cancellation works differently with this execution strategy.
* In Netty, the same IO-Thread handles message receipt for a single TCP socket
* connection, therefore although this code allows for cancellation of the RPC
* call, in practice the cancellation will always arrive after the call has finished
* processing ( because in this model the same Thread handles the cancel and the RPC
* call ).
*
* @author Peter Klauser
*
*/
public class SameThreadExecutor implements RpcServerCallExecutor {
private static Logger log = LoggerFactory.getLogger(SameThreadExecutor.class);
//weak hashmap of threads
WeakHashMap runningCalls = new WeakHashMap();
/* (non-Javadoc)
* @see com.googlecode.protobuf.pro.duplex.execute.RpcServerCallExecutor#execute(com.googlecode.protobuf.pro.duplex.execute.PendingServerCallState)
*/
@Override
public void execute(PendingServerCallState call) {
runningCalls.put(Thread.currentThread(), call);
call.setExecutor((Runnable)Thread.currentThread());
BlockingRpcCallback callback = new BlockingRpcCallback();
if ( call.getService() != null ) {
call.getService().callMethod(call.getMethodDesc(), call.getController(), call.getRequest(), callback);
if ( !callback.isDone() ) {
// this is only likely to come in here if another thread executes the callback than the
// one calling callMethod.
synchronized(callback) {
while(!callback.isDone()) {
try {
callback.wait();
} catch (InterruptedException e) {
// if the service off-loaded running to a different thread, the currentThread
// could be waiting here and be interrupted when cancel comes in.
// we "consume" the thread's current thread's interrupt status and finish.
break;
}
}
}
// callback may or may not have finished
}
} else {
// handle blocking call service
try {
Message response = call.getBlockingService().callBlockingMethod(call.getMethodDesc(), call.getController(), call.getRequest());
callback.run(response);
} catch ( com.google.protobuf.ServiceException se ) {
log.warn("BlockingService threw ServiceException.", se);
callback.run(null);
call.getController().setFailed("ServiceException");
}
}
runningCalls.remove(Thread.currentThread());
if ( Thread.interrupted() ) {
//log clearing interrupted flag, which might have been set if we were interrupted
//but not in a blocking wait before.
}
ServerRpcController controller = call.getController();
if ( controller.isCanceled() ) {
// we don't care if there was a response created or error, the
// client is not interested anymore. Just to the notification
if ( controller.getAndSetCancelCallbackNotified() ) {
RpcCallback
© 2015 - 2025 Weber Informatics LLC | Privacy Policy