com.zeroc.IceInternal.ConnectRequestHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ice Show documentation
Show all versions of ice Show documentation
Ice is a comprehensive RPC framework that helps you build distributed applications with minimal effort using familiar object-oriented idioms
//
// Copyright (c) ZeroC, Inc. All rights reserved.
//
package com.zeroc.IceInternal;
import java.util.concurrent.Callable;
public class ConnectRequestHandler
implements RequestHandler, Reference.GetConnectionCallback, RouterInfo.AddProxyCallback
{
synchronized public RequestHandler
connect(com.zeroc.Ice._ObjectPrxI proxy)
{
if(!initialized())
{
_proxies.add(proxy);
}
return _requestHandler;
}
@Override
public RequestHandler
update(RequestHandler previousHandler, RequestHandler newHandler)
{
return previousHandler == this ? newHandler : this;
}
@Override
public int
sendAsyncRequest(ProxyOutgoingAsyncBase out)
throws RetryException
{
synchronized(this)
{
if(!_initialized)
{
out.cancelable(this); // This will throw if the request is canceled
}
if(!initialized())
{
_requests.add(out);
return AsyncStatus.Queued;
}
}
return out.invokeRemote(_connection, _compress, _response);
}
@Override
public void
asyncRequestCanceled(OutgoingAsyncBase outAsync, com.zeroc.Ice.LocalException ex)
{
synchronized(this)
{
if(_exception != null)
{
return; // The request has been notified of a failure already.
}
if(!initialized())
{
java.util.Iterator it = _requests.iterator();
while(it.hasNext())
{
OutgoingAsyncBase request = it.next();
if(request == outAsync)
{
it.remove();
if(outAsync.completed(ex))
{
outAsync.invokeCompletedAsync();
}
return;
}
}
assert(false); // The request has to be queued if it timed out and we're not initialized yet.
}
}
_connection.asyncRequestCanceled(outAsync, ex);
}
@Override
public Reference
getReference()
{
return _reference;
}
@Override
synchronized public com.zeroc.Ice.ConnectionI
getConnection()
{
//
// First check for the connection, it's important otherwise the user could first get a connection
// and then the exception if he tries to obtain the proxy cached connection mutiple times (the
// exception can be set after the connection is set if the flush of pending requests fails).
//
if(_connection != null)
{
return _connection;
}
else if(_exception != null)
{
throw (com.zeroc.Ice.LocalException)_exception.fillInStackTrace();
}
return null;
}
//
// Implementation of Reference.GetConnectionCallback
//
@Override
public void
setConnection(com.zeroc.Ice.ConnectionI connection, boolean compress)
{
synchronized(this)
{
assert(!_flushing && _exception == null && _connection == null);
_connection = connection;
_compress = compress;
}
//
// If this proxy is for a non-local object, and we are using a router, then
// add this proxy to the router info object.
//
RouterInfo ri = _reference.getRouterInfo();
if(ri != null && !ri.addProxy(_proxy, this))
{
return; // The request handler will be initialized once addProxy returns.
}
//
// We can now send the queued requests.
//
flushRequests();
}
@Override
public void
setException(final com.zeroc.Ice.LocalException ex)
{
synchronized(this)
{
assert(!_flushing && !_initialized && _exception == null);
_exception = ex;
_flushing = true; // Ensures request handler is removed before processing new requests.
}
//
// NOTE: remove the request handler *before* notifying the requests that the connection
// failed. It's important to ensure that future invocations will obtain a new connect
// request handler once invocations are notified.
//
try
{
_reference.getInstance().requestHandlerFactory().removeRequestHandler(_reference, this);
}
catch(com.zeroc.Ice.CommunicatorDestroyedException exc)
{
// Ignore
}
for(OutgoingAsyncBase outAsync : _requests)
{
if(outAsync.completed(_exception))
{
outAsync.invokeCompletedAsync();
}
}
_requests.clear();
synchronized(this)
{
_flushing = false;
_proxies.clear();
_proxy = null; // Break cyclic reference count.
notifyAll();
}
}
//
// Implementation of RouterInfo.AddProxyCallback
//
@Override
public void
addedProxy()
{
//
// The proxy was added to the router info, we're now ready to send the
// queued requests.
//
flushRequests();
}
public
ConnectRequestHandler(Reference ref, com.zeroc.Ice._ObjectPrxI proxy)
{
_reference = ref;
_response = _reference.getMode() == Reference.ModeTwoway;
_proxy = proxy;
_initialized = false;
_flushing = false;
if(_reference.getInstance().queueRequests())
{
_requestHandler = new QueueRequestHandler(_reference.getInstance(), this);
}
else
{
_requestHandler = this;
}
}
private boolean
initialized()
{
// Must be called with the mutex locked.
if(_initialized)
{
assert(_connection != null);
return true;
}
else
{
//
// This is similar to a mutex lock in that the flag is
// only true for a short period of time.
//
boolean interrupted = false;
while(_flushing)
{
try
{
wait();
}
catch(InterruptedException ex)
{
interrupted = true;
}
}
//
// Restore the interrupted status.
//
if(interrupted)
{
Thread.currentThread().interrupt();
}
if(_exception != null)
{
if(_connection != null)
{
//
// Only throw if the connection didn't get established. If
// it died after being established, we allow the caller to
// retry the connection establishment by not throwing here
// (the connection will throw RetryException).
//
return true;
}
throw (com.zeroc.Ice.LocalException)_exception.fillInStackTrace();
}
else
{
return _initialized;
}
}
}
private void
flushRequests()
{
if(_reference.getInstance().queueRequests())
{
_reference.getInstance().getQueueExecutor().executeNoThrow(new Callable()
{
@Override
public Void call() throws Exception
{
flushRequestsImpl();
return null;
}
});
}
else
{
flushRequestsImpl();
}
}
private void
flushRequestsImpl()
{
synchronized(this)
{
assert(_connection != null && !_initialized);
//
// We set the _flushing flag to true to prevent any additional queuing. Callers
// might block for a little while as the queued requests are being sent but this
// shouldn't be an issue as the request sends are non-blocking.
//
_flushing = true;
}
com.zeroc.Ice.LocalException exception = null;
for(ProxyOutgoingAsyncBase outAsync : _requests)
{
try
{
if((outAsync.invokeRemote(_connection, _compress, _response) & AsyncStatus.InvokeSentCallback) > 0)
{
outAsync.invokeSentAsync();
}
}
catch(RetryException ex)
{
exception = ex.get();
// Remove the request handler before retrying.
_reference.getInstance().requestHandlerFactory().removeRequestHandler(_reference, this);
outAsync.retryException(ex.get());
}
catch(com.zeroc.Ice.LocalException ex)
{
exception = ex;
if(outAsync.completed(ex))
{
outAsync.invokeCompletedAsync();
}
}
}
_requests.clear();
//
// If we aren't caching the connection, don't bother creating a
// connection request handler. Otherwise, update the proxies
// request handler to use the more efficient connection request
// handler.
//
if(_reference.getCacheConnection() && exception == null)
{
RequestHandler previous = _requestHandler;
_requestHandler = new ConnectionRequestHandler(_reference, _connection, _compress);
if(_reference.getInstance().queueRequests())
{
_requestHandler = new QueueRequestHandler(_reference.getInstance(), _requestHandler);
}
for(com.zeroc.Ice._ObjectPrxI proxy : _proxies)
{
proxy._updateRequestHandler(previous, _requestHandler);
}
}
synchronized(this)
{
assert(!_initialized);
_exception = exception;
_initialized = _exception == null;
_flushing = false;
//
// Only remove once all the requests are flushed to
// guarantee serialization.
//
_reference.getInstance().requestHandlerFactory().removeRequestHandler(_reference, this);
_proxies.clear();
_proxy = null; // Break cyclic reference count.
notifyAll();
}
}
private final Reference _reference;
private boolean _response;
private com.zeroc.Ice._ObjectPrxI _proxy;
private java.util.Set _proxies = new java.util.HashSet<>();
private com.zeroc.Ice.ConnectionI _connection;
private boolean _compress;
private com.zeroc.Ice.LocalException _exception;
private boolean _initialized;
private boolean _flushing;
private java.util.List _requests = new java.util.LinkedList<>();
private RequestHandler _requestHandler;
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy