summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpp/include/Ice/AsyncResult.h353
-rw-r--r--cpp/include/Ice/AsyncResultF.h26
-rw-r--r--cpp/include/Ice/Initialize.h1
-rw-r--r--cpp/include/Ice/Outgoing.h106
-rw-r--r--cpp/include/Ice/OutgoingAsync.h589
-rw-r--r--cpp/include/Ice/OutgoingAsyncF.h41
-rw-r--r--cpp/include/Ice/Proxy.h4
-rw-r--r--cpp/include/Ice/RequestHandlerF.h4
-rw-r--r--cpp/src/Ice/AsyncResult.cpp602
-rw-r--r--cpp/src/Ice/CollocatedRequestHandler.cpp104
-rw-r--r--cpp/src/Ice/CollocatedRequestHandler.h24
-rw-r--r--cpp/src/Ice/CommunicatorI.cpp19
-rw-r--r--cpp/src/Ice/ConnectRequestHandler.cpp43
-rw-r--r--cpp/src/Ice/ConnectRequestHandler.h12
-rw-r--r--cpp/src/Ice/ConnectionFactory.cpp5
-rw-r--r--cpp/src/Ice/ConnectionFactory.h4
-rw-r--r--cpp/src/Ice/ConnectionI.cpp176
-rw-r--r--cpp/src/Ice/ConnectionI.h25
-rw-r--r--cpp/src/Ice/ConnectionRequestHandler.cpp14
-rw-r--r--cpp/src/Ice/ConnectionRequestHandler.h8
-rw-r--r--cpp/src/Ice/Exception.cpp7
-rw-r--r--cpp/src/Ice/Makefile1
-rw-r--r--cpp/src/Ice/Makefile.mak1
-rw-r--r--cpp/src/Ice/ObjectAdapterFactory.cpp2
-rw-r--r--cpp/src/Ice/ObjectAdapterFactory.h2
-rw-r--r--cpp/src/Ice/ObjectAdapterI.cpp2
-rw-r--r--cpp/src/Ice/ObjectAdapterI.h2
-rw-r--r--cpp/src/Ice/Outgoing.cpp232
-rw-r--r--cpp/src/Ice/OutgoingAsync.cpp1268
-rw-r--r--cpp/src/Ice/Proxy.cpp94
-rw-r--r--cpp/src/Ice/ProxyFactory.cpp2
-rw-r--r--cpp/src/Ice/RequestHandler.cpp5
-rw-r--r--cpp/src/Ice/RequestHandler.h19
-rw-r--r--cpp/src/Ice/RetryQueue.cpp58
-rw-r--r--cpp/src/Ice/RetryQueue.h15
-rw-r--r--cpp/src/Ice/winrt/Makefile.mak3
-rw-r--r--cpp/src/IceDiscovery/LocatorI.h2
-rw-r--r--cpp/src/IceDiscovery/LookupI.h1
-rw-r--r--cpp/src/IceGrid/AdapterCache.h2
-rw-r--r--cpp/src/slice2cpp/Gen.cpp20
-rw-r--r--cpp/src/slice2cs/Gen.cpp8
-rw-r--r--cpp/src/slice2java/Gen.cpp8
-rw-r--r--cpp/test/Ice/ami/AllTests.cpp75
-rw-r--r--cpp/test/Ice/retry/AllTests.cpp91
-rw-r--r--cpp/test/Ice/retry/Client.cpp2
-rw-r--r--cpp/test/Ice/retry/Collocated.cpp2
-rw-r--r--cpp/test/Ice/retry/InstrumentationI.cpp7
-rw-r--r--cpp/test/Ice/retry/Test.ice4
-rw-r--r--cpp/test/Ice/retry/TestI.cpp30
-rw-r--r--cpp/test/Ice/retry/TestI.h2
-rw-r--r--cs/src/Ice/AsyncResult.cs701
-rw-r--r--cs/src/Ice/CollocatedRequestHandler.cs82
-rw-r--r--cs/src/Ice/CommunicatorI.cs8
-rw-r--r--cs/src/Ice/ConnectRequestHandler.cs23
-rw-r--r--cs/src/Ice/ConnectionFactory.cs4
-rw-r--r--cs/src/Ice/ConnectionI.cs109
-rw-r--r--cs/src/Ice/ConnectionRequestHandler.cs6
-rw-r--r--cs/src/Ice/Makefile1
-rw-r--r--cs/src/Ice/Makefile.mak1
-rw-r--r--cs/src/Ice/ObjectAdapterFactory.cs2
-rw-r--r--cs/src/Ice/ObjectAdapterI.cs2
-rw-r--r--cs/src/Ice/OutgoingAsync.cs2196
-rw-r--r--cs/src/Ice/Proxy.cs128
-rw-r--r--cs/src/Ice/ProxyFactory.cs2
-rw-r--r--cs/src/Ice/RequestHandler.cs11
-rw-r--r--cs/src/Ice/RetryQueue.cs64
-rw-r--r--cs/test/Ice/ami/AllTests.cs95
-rw-r--r--cs/test/Ice/retry/AllTests.cs94
-rw-r--r--cs/test/Ice/retry/Client.cs2
-rw-r--r--cs/test/Ice/retry/Collocated.cs2
-rw-r--r--cs/test/Ice/retry/Instrumentation.cs9
-rw-r--r--cs/test/Ice/retry/RetryI.cs18
-rw-r--r--cs/test/Ice/retry/Test.ice4
-rw-r--r--java/src/Ice/AsyncResult.java7
-rw-r--r--java/src/Ice/CommunicatorI.java10
-rw-r--r--java/src/Ice/ConnectionI.java96
-rw-r--r--java/src/Ice/ObjectAdapterI.java4
-rw-r--r--java/src/Ice/ObjectPrxHelperBase.java108
-rw-r--r--java/src/IceInternal/AsyncResultI.java475
-rw-r--r--java/src/IceInternal/BatchOutgoingAsync.java117
-rw-r--r--java/src/IceInternal/CancellationHandler.java15
-rw-r--r--java/src/IceInternal/CollocatedRequestHandler.java65
-rw-r--r--java/src/IceInternal/CommunicatorFlushBatch.java (renamed from java/src/IceInternal/CommunicatorBatchOutgoingAsync.java)123
-rw-r--r--java/src/IceInternal/ConnectRequestHandler.java32
-rw-r--r--java/src/IceInternal/ConnectionBatchOutgoingAsync.java107
-rw-r--r--java/src/IceInternal/ConnectionFlushBatch.java128
-rw-r--r--java/src/IceInternal/ConnectionRequestHandler.java12
-rw-r--r--java/src/IceInternal/GetConnectionOutgoingAsync.java148
-rw-r--r--java/src/IceInternal/IncomingConnectionFactory.java2
-rw-r--r--java/src/IceInternal/ObjectAdapterFactory.java2
-rw-r--r--java/src/IceInternal/OutgoingAsync.java623
-rw-r--r--java/src/IceInternal/OutgoingAsyncBase.java571
-rw-r--r--java/src/IceInternal/OutgoingAsyncMessageCallback.java53
-rw-r--r--java/src/IceInternal/OutgoingConnectionFactory.java2
-rw-r--r--java/src/IceInternal/ProxyBatchOutgoingAsync.java97
-rw-r--r--java/src/IceInternal/ProxyFactory.java2
-rw-r--r--java/src/IceInternal/ProxyFlushBatch.java71
-rw-r--r--java/src/IceInternal/ProxyGetConnection.java59
-rw-r--r--java/src/IceInternal/ProxyOutgoingAsyncBase.java278
-rw-r--r--java/src/IceInternal/QueueRequestHandler.java13
-rw-r--r--java/src/IceInternal/RequestHandler.java6
-rw-r--r--java/src/IceInternal/RetryQueue.java13
-rw-r--r--java/src/IceInternal/RetryTask.java44
-rw-r--r--java/test/Ice/ami/AMI.java96
-rw-r--r--java/test/Ice/ami/lambda/AMI.java9
-rw-r--r--java/test/Ice/retry/AllTests.java94
-rw-r--r--java/test/Ice/retry/Client.java2
-rw-r--r--java/test/Ice/retry/Collocated.java2
-rw-r--r--java/test/Ice/retry/Instrumentation.java9
-rw-r--r--java/test/Ice/retry/RetryI.java25
-rw-r--r--java/test/Ice/retry/Test.ice4
-rw-r--r--js/test/Ice/retry/Test.ice2
-rw-r--r--py/modules/IcePy/Operation.cpp23
-rw-r--r--py/modules/IcePy/Operation.h2
-rw-r--r--py/modules/IcePy/Types.h2
-rw-r--r--py/test/Ice/ami/AllTests.py60
-rw-r--r--slice/Ice/LocalException.ice12
117 files changed, 5779 insertions, 5537 deletions
diff --git a/cpp/include/Ice/AsyncResult.h b/cpp/include/Ice/AsyncResult.h
new file mode 100644
index 00000000000..5452c5de970
--- /dev/null
+++ b/cpp/include/Ice/AsyncResult.h
@@ -0,0 +1,353 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#ifndef ICE_ASYNC_RESULT_H
+#define ICE_ASYNC_RESULT_H
+
+#include <IceUtil/Monitor.h>
+#include <IceUtil/Mutex.h>
+#include <IceUtil/UniquePtr.h>
+#include <Ice/LocalObject.h>
+#include <Ice/CommunicatorF.h>
+#include <Ice/ConnectionF.h>
+#include <Ice/ProxyF.h>
+#include <Ice/InstanceF.h>
+#include <Ice/RequestHandlerF.h>
+#include <Ice/AsyncResultF.h>
+#include <Ice/ObserverHelper.h>
+#include <Ice/BasicStream.h>
+
+#ifdef ICE_CPP11
+# include <functional> // for std::function
+#endif
+
+namespace IceInternal
+{
+
+class CallbackBase;
+typedef IceUtil::Handle<CallbackBase> CallbackBasePtr;
+
+}
+
+namespace Ice
+{
+
+class ICE_API AsyncResult : public Ice::LocalObject, private IceUtil::noncopyable
+{
+public:
+
+ void cancel();
+
+ Int getHash() const;
+
+ CommunicatorPtr getCommunicator() const;
+ virtual ConnectionPtr getConnection() const;
+ virtual ObjectPrx getProxy() const;
+
+ bool isCompleted() const;
+ void waitForCompleted();
+
+ bool isSent() const;
+ void waitForSent();
+
+ void throwLocalException() const;
+
+ bool sentSynchronously() const;
+ LocalObjectPtr getCookie() const;
+ const std::string& getOperation() const;
+
+ ::IceInternal::BasicStream* __startReadParams()
+ {
+ _is.startReadEncaps();
+ return &_is;
+ }
+ void __endReadParams()
+ {
+ _is.endReadEncaps();
+ }
+ void __readEmptyParams()
+ {
+ _is.skipEmptyEncaps();
+ }
+ void __readParamEncaps(const ::Ice::Byte*& encaps, ::Ice::Int& sz)
+ {
+ _is.readEncaps(encaps, sz);
+ }
+ void __throwUserException();
+
+ bool __wait();
+
+ static void __check(const AsyncResultPtr&, const ::IceProxy::Ice::Object*, const ::std::string&);
+ static void __check(const AsyncResultPtr&, const Connection*, const ::std::string&);
+ static void __check(const AsyncResultPtr&, const Communicator*, const ::std::string&);
+
+protected:
+
+ static void __check(const AsyncResultPtr&, const ::std::string&);
+
+ AsyncResult(const CommunicatorPtr&, const IceInternal::InstancePtr&, const std::string&,
+ const IceInternal::CallbackBasePtr&, const LocalObjectPtr&);
+ virtual ~AsyncResult(); // Must be heap-allocated
+
+ bool sent(bool);
+ bool finished(bool);
+ bool finished(const Exception&);
+
+ void invokeSentAsync();
+ void invokeCompletedAsync();
+
+ void invokeSent();
+ void invokeCompleted();
+
+ void cancel(const LocalException&);
+ void cancelable(const IceInternal::CancellationHandlerPtr&);
+ void checkCanceled();
+
+ void warning(const std::exception&) const;
+ void warning() const;
+
+ //
+ // This virtual method is necessary for the communicator flush
+ // batch requests implementation.
+ //
+ virtual IceInternal::InvocationObserver& getObserver()
+ {
+ return _observer;
+ }
+
+ const IceInternal::InstancePtr _instance;
+ IceInternal::InvocationObserver _observer;
+ Ice::ConnectionPtr _cachedConnection;
+ bool _sentSynchronously;
+
+ IceInternal::BasicStream _is;
+
+ IceUtil::Monitor<IceUtil::Mutex> _monitor;
+
+private:
+
+ const CommunicatorPtr _communicator;
+ const std::string& _operation;
+ const IceInternal::CallbackBasePtr _callback;
+ const LocalObjectPtr _cookie;
+ IceUtil::UniquePtr<Exception> _exception;
+
+ IceInternal::CancellationHandlerPtr _cancellationHandler;
+ IceUtil::UniquePtr<Ice::LocalException> _cancellationException;
+
+ static const unsigned char OK;
+ static const unsigned char Done;
+ static const unsigned char Sent;
+ static const unsigned char EndCalled;
+ static const unsigned char Canceled;
+ unsigned char _state;
+};
+
+}
+
+namespace IceInternal
+{
+
+//
+// Base class for all callbacks.
+//
+class ICE_API CallbackBase : public IceUtil::Shared
+{
+public:
+
+ void checkCallback(bool, bool);
+
+ virtual void completed(const ::Ice::AsyncResultPtr&) const = 0;
+ virtual CallbackBasePtr verify(const ::Ice::LocalObjectPtr&) = 0;
+ virtual void sent(const ::Ice::AsyncResultPtr&) const = 0;
+ virtual bool hasSentCallback() const = 0;
+};
+
+//
+// Base class for generic callbacks.
+//
+class ICE_API GenericCallbackBase : virtual public CallbackBase
+{
+};
+
+//
+// See comments in OutgoingAsync.cpp
+//
+extern ICE_API CallbackBasePtr __dummyCallback;
+
+//
+// Generic callback template that requires the caller to down-cast the
+// proxy and the cookie that are obtained from the AsyncResult.
+//
+template<class T>
+class AsyncCallback : public GenericCallbackBase
+{
+public:
+
+ typedef T callback_type;
+ typedef IceUtil::Handle<T> TPtr;
+
+ typedef void (T::*Callback)(const ::Ice::AsyncResultPtr&);
+
+ AsyncCallback(const TPtr& instance, Callback cb, Callback sentcb = 0) :
+ _callback(instance), _completed(cb), _sent(sentcb)
+ {
+ checkCallback(instance, cb != 0);
+ }
+
+ virtual void completed(const ::Ice::AsyncResultPtr& result) const
+ {
+ (_callback.get()->*_completed)(result);
+ }
+
+ virtual CallbackBasePtr verify(const ::Ice::LocalObjectPtr&)
+ {
+ return this; // Nothing to do, the cookie is not type-safe.
+ }
+
+ virtual void sent(const ::Ice::AsyncResultPtr& result) const
+ {
+ if(_sent)
+ {
+ (_callback.get()->*_sent)(result);
+ }
+ }
+
+ virtual bool hasSentCallback() const
+ {
+ return _sent != 0;
+ }
+
+private:
+
+ TPtr _callback;
+ Callback _completed;
+ Callback _sent;
+};
+
+#ifdef ICE_CPP11
+
+template<typename T> struct callback_type
+{
+ static const int value = 1;
+};
+
+template<> struct callback_type<void(const ::Ice::AsyncResultPtr&)>
+{
+ static const int value = 2;
+};
+
+template<> struct callback_type<void(const ::Ice::Exception&)>
+{
+ static const int value = 3;
+};
+
+template<typename Callable, typename = void> struct callable_type
+{
+ static const int value = 1;
+};
+
+template<class Callable> struct callable_type<Callable, typename ::std::enable_if<
+ ::std::is_class<Callable>::value &&
+ !::std::is_bind_expression<Callable>::value>::type>
+{
+ template<typename T, T> struct TypeCheck;
+ template<typename T> struct AsyncResultCallback
+ {
+ typedef void (T::*ok)(const ::Ice::AsyncResultPtr&) const;
+ };
+ template<typename T> struct ExceptionCallback
+ {
+ typedef void (T::*ok)(const ::Ice::Exception&) const;
+ };
+
+ typedef char (&other)[1];
+ typedef char (&asyncResult)[2];
+ typedef char (&exception)[3];
+
+ template<typename T> static other check(...);
+ template<typename T> static asyncResult check(TypeCheck<typename AsyncResultCallback<T>::ok, &T::operator()>*);
+ template<typename T> static exception check(TypeCheck<typename ExceptionCallback<T>::ok, &T::operator()>*);
+
+ enum { value = sizeof(check<Callable>(0)) };
+};
+
+template<> struct callable_type<void(*)(const ::Ice::AsyncResultPtr&)>
+{
+ static const int value = 2;
+};
+
+template<> struct callable_type<void(*)(const ::Ice::Exception&)>
+{
+ static const int value = 3;
+};
+
+template<typename Callable, typename Callback> struct is_callable
+{
+ static const bool value = callable_type<Callable>::value == callback_type<Callback>::value;
+};
+
+template<class S> class Function : public std::function<S>
+{
+
+public:
+
+ template<typename T> Function(T f, typename ::std::enable_if<is_callable<T, S>::value>::type* = 0)
+ : std::function<S>(f)
+ {
+ }
+
+ Function()
+ {
+ }
+
+ Function(::std::nullptr_t) : ::std::function<S>(nullptr)
+ {
+ }
+};
+
+#endif
+
+}
+
+namespace Ice
+{
+
+typedef IceUtil::Handle< ::IceInternal::GenericCallbackBase> CallbackPtr;
+
+template<class T> CallbackPtr
+newCallback(const IceUtil::Handle<T>& instance,
+ void (T::*cb)(const AsyncResultPtr&),
+ void (T::*sentcb)(const AsyncResultPtr&) = 0)
+{
+ return new ::IceInternal::AsyncCallback<T>(instance, cb, sentcb);
+}
+
+template<class T> CallbackPtr
+newCallback(T* instance,
+ void (T::*cb)(const AsyncResultPtr&),
+ void (T::*sentcb)(const AsyncResultPtr&) = 0)
+{
+ return new ::IceInternal::AsyncCallback<T>(instance, cb, sentcb);
+}
+
+#ifdef ICE_CPP11
+
+ICE_API CallbackPtr
+newCallback(const ::IceInternal::Function<void (const AsyncResultPtr&)>&,
+ const ::IceInternal::Function<void (const AsyncResultPtr&)>& =
+ ::IceInternal::Function<void (const AsyncResultPtr&)>());
+#endif
+
+//
+// Operation callbacks are specified in Proxy.h
+//
+}
+
+#endif
diff --git a/cpp/include/Ice/AsyncResultF.h b/cpp/include/Ice/AsyncResultF.h
new file mode 100644
index 00000000000..dac5f9b68cf
--- /dev/null
+++ b/cpp/include/Ice/AsyncResultF.h
@@ -0,0 +1,26 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#ifndef ICE_ASYNC_RESULT_F_H
+#define ICE_ASYNC_RESULT_F_H
+
+#include <IceUtil/Shared.h>
+
+#include <Ice/Handle.h>
+
+namespace Ice
+{
+
+class AsyncResult;
+ICE_API IceUtil::Shared* upCast(::Ice::AsyncResult*);
+typedef IceInternal::Handle<AsyncResult> AsyncResultPtr;
+
+}
+
+#endif
diff --git a/cpp/include/Ice/Initialize.h b/cpp/include/Ice/Initialize.h
index 04271017221..7331d12dae5 100644
--- a/cpp/include/Ice/Initialize.h
+++ b/cpp/include/Ice/Initialize.h
@@ -10,6 +10,7 @@
#ifndef ICE_INITIALIZE_H
#define ICE_INITIALIZE_H
+#include <IceUtil/Timer.h>
#include <Ice/CommunicatorF.h>
#include <Ice/PropertiesF.h>
#include <Ice/InstanceF.h>
diff --git a/cpp/include/Ice/Outgoing.h b/cpp/include/Ice/Outgoing.h
index e6697387603..c50b0a28aae 100644
--- a/cpp/include/Ice/Outgoing.h
+++ b/cpp/include/Ice/Outgoing.h
@@ -35,38 +35,63 @@ namespace IceInternal
class CollocatedRequestHandler; // Forward declaration
-class ICE_API OutgoingMessageCallback : private IceUtil::noncopyable
+class ICE_API OutgoingBase : private IceUtil::noncopyable
{
public:
- virtual ~OutgoingMessageCallback() { }
+ virtual ~OutgoingBase() { }
virtual bool send(const Ice::ConnectionIPtr&, bool, bool) = 0;
virtual void invokeCollocated(CollocatedRequestHandler*) = 0;
virtual void sent() = 0;
- virtual void finished(const Ice::Exception&) = 0;
+ virtual void completed(const Ice::Exception&) = 0;
+
+ BasicStream* os() { return &_os; }
+
+ void attachRemoteObserver(const Ice::ConnectionInfoPtr& c, const Ice::EndpointPtr& endpt, Ice::Int requestId)
+ {
+ const Ice::Int size = static_cast<Ice::Int>(_os.b.size() - IceInternal::headerSize - 4);
+ _childObserver.attach(_observer.getRemoteObserver(c, endpt, requestId, size));
+ }
+
+ void attachCollocatedObserver(const Ice::ObjectAdapterPtr& adapter, Ice::Int requestId)
+ {
+ const Ice::Int size = static_cast<Ice::Int>(_os.b.size() - IceInternal::headerSize - 4);
+ _childObserver.attach(_observer.getCollocatedObserver(adapter, requestId, size));
+ }
+
+protected:
+
+ OutgoingBase(Instance*, const std::string&);
+
+ BasicStream _os;
+ IceUtil::UniquePtr<Ice::Exception> _exception;
+ bool _sent;
+ InvocationObserver _observer;
+ ObserverHelperT<Ice::Instrumentation::ChildInvocationObserver> _childObserver;
+
+ IceUtil::Monitor<IceUtil::Mutex> _monitor;
};
-class ICE_API Outgoing : public OutgoingMessageCallback
+class ICE_API Outgoing : public OutgoingBase
{
public:
Outgoing(IceProxy::Ice::Object*, const std::string&, Ice::OperationMode, const Ice::Context*);
~Outgoing();
- bool invoke(); // Returns true if ok, false if user exception.
- void abort(const Ice::LocalException&);
-
virtual bool send(const Ice::ConnectionIPtr&, bool, bool);
virtual void invokeCollocated(CollocatedRequestHandler*);
+
virtual void sent();
- virtual void finished(const Ice::Exception&);
+ virtual void completed(const Ice::Exception&);
- void finished(BasicStream&);
+ bool invoke(); // Returns true if ok, false if user exception.
+ void abort(const Ice::LocalException&);
+ void completed(BasicStream&);
// Inlined for speed optimization.
- BasicStream* os() { return &_os; }
BasicStream* startReadParams()
{
_is.startReadEncaps();
@@ -117,20 +142,6 @@ public:
void throwUserException();
- void attachRemoteObserver(const Ice::ConnectionInfoPtr& c, const Ice::EndpointPtr& endpt,
- Ice::Int requestId, Ice::Int size)
- {
- _childObserver.attach(_observer.getRemoteObserver(c, endpt, requestId, size));
- }
-
- void attachCollocatedObserver(const Ice::ObjectAdapterPtr& adapter, Ice::Int requestId)
- {
- _childObserver.attach(_observer.getCollocatedObserver(adapter,
- requestId,
- static_cast<Ice::Int>(_os.b.size() -
- IceInternal::headerSize - 4)));
- }
-
private:
//
@@ -140,9 +151,7 @@ private:
IceProxy::Ice::Object* _proxy;
Ice::OperationMode _mode;
RequestHandlerPtr _handler;
- IceUtil::UniquePtr<Ice::Exception> _exception;
- InvocationObserver _observer;
- ObserverHelperT<Ice::Instrumentation::ChildInvocationObserver> _childObserver;
+ IceUtil::Time _invocationTimeoutDeadline;
enum
{
@@ -156,60 +165,27 @@ private:
Ice::EncodingVersion _encoding;
BasicStream _is;
- BasicStream _os;
- bool _sent;
-
- //
- // NOTE: we use an attribute for the monitor instead of inheriting
- // from the monitor template. Otherwise, the template would be
- // exported from the DLL on Windows and could cause linker errors
- // because of multiple definition of IceUtil::Monitor<IceUtil::Mutex>,
- // see bug 1541.
- //
- IceUtil::Monitor<IceUtil::Mutex> _monitor;
};
-class BatchOutgoing : public OutgoingMessageCallback
+class FlushBatch : public OutgoingBase
{
public:
- BatchOutgoing(IceProxy::Ice::Object*, const std::string&);
- BatchOutgoing(Ice::ConnectionI*, Instance*, const std::string&);
+ FlushBatch(IceProxy::Ice::Object*, const std::string&);
+ FlushBatch(Ice::ConnectionI*, Instance*, const std::string&);
void invoke();
virtual bool send(const Ice::ConnectionIPtr&, bool, bool);
virtual void invokeCollocated(CollocatedRequestHandler*);
- virtual void sent();
- virtual void finished(const Ice::Exception&);
-
- BasicStream* os() { return &_os; }
- void attachRemoteObserver(const Ice::ConnectionInfoPtr& connection, const Ice::EndpointPtr& endpt, Ice::Int sz)
- {
- _childObserver.attach(_observer.getRemoteObserver(connection, endpt, 0, sz));
- }
-
- void attachCollocatedObserver(const Ice::ObjectAdapterPtr& adapter, Ice::Int requestId)
- {
- _childObserver.attach(_observer.getCollocatedObserver(adapter,
- requestId,
- static_cast<Ice::Int>(_os.b.size() -
- IceInternal::headerSize - 4)));
- }
+ virtual void sent();
+ virtual void completed(const Ice::Exception&);
private:
- IceUtil::Monitor<IceUtil::Mutex> _monitor;
IceProxy::Ice::Object* _proxy;
Ice::ConnectionI* _connection;
- bool _sent;
- IceUtil::UniquePtr<Ice::Exception> _exception;
-
- BasicStream _os;
-
- InvocationObserver _observer;
- ObserverHelperT<Ice::Instrumentation::ChildInvocationObserver> _childObserver;
};
}
diff --git a/cpp/include/Ice/OutgoingAsync.h b/cpp/include/Ice/OutgoingAsync.h
index 422ad6d65db..a81419465fa 100644
--- a/cpp/include/Ice/OutgoingAsync.h
+++ b/cpp/include/Ice/OutgoingAsync.h
@@ -10,276 +10,151 @@
#ifndef ICE_OUTGOING_ASYNC_H
#define ICE_OUTGOING_ASYNC_H
-#include <IceUtil/Monitor.h>
-#include <IceUtil/Mutex.h>
#include <IceUtil/Timer.h>
-#include <IceUtil/Exception.h>
-#include <IceUtil/UniquePtr.h>
#include <Ice/OutgoingAsyncF.h>
-#include <Ice/RequestHandlerF.h>
-#include <Ice/InstanceF.h>
-#include <Ice/ReferenceF.h>
+#include <Ice/AsyncResult.h>
#include <Ice/CommunicatorF.h>
#include <Ice/ConnectionIF.h>
-#include <Ice/Current.h>
-#include <Ice/BasicStream.h>
-#include <Ice/ObserverHelper.h>
#include <Ice/ObjectAdapterF.h>
-#include <Ice/ThreadPoolF.h>
-
-#ifdef ICE_CPP11
-# include <functional> // for std::function
-#endif
namespace IceInternal
{
-class CallbackBase;
-typedef IceUtil::Handle<CallbackBase> CallbackBasePtr;
-
-}
-
-namespace Ice
-{
+class RetryException;
+class CollocatedRequestHandler;
-class ICE_API AsyncResult : virtual public Ice::LocalObject, protected IceUtil::TimerTask, private IceUtil::noncopyable
+//
+// Base class for handling asynchronous invocations. This class is
+// responsible for the handling of the output stream and the child
+// invocation observer.
+//
+class ICE_API OutgoingAsyncBase : public Ice::AsyncResult
{
public:
- virtual Int getHash() const;
-
- virtual CommunicatorPtr getCommunicator() const
- {
- return _communicator;
- }
-
- virtual ConnectionPtr getConnection() const
- {
- return 0;
- }
-
- virtual ObjectPrx getProxy() const
- {
- return 0;
- }
-
- bool isCompleted() const;
- void waitForCompleted();
+ //
+ // Those methods must be overriden if the invocation is sent
+ // through a request handler.
+ //
+ virtual AsyncStatus send(const Ice::ConnectionIPtr&, bool, bool) { assert(false); return AsyncStatusQueued; }
+ virtual AsyncStatus invokeCollocated(CollocatedRequestHandler*) { assert(false); return AsyncStatusQueued; }
- bool isSent() const;
- void waitForSent();
+ virtual bool sent();
+ virtual bool completed(const Ice::Exception&);
- void throwLocalException() const;
+ // Those methods are public when called from an OutgoingAsyncBase reference.
+ using Ice::AsyncResult::cancelable;
+ using Ice::AsyncResult::invokeSent;
+ using Ice::AsyncResult::invokeCompleted;
+ using Ice::AsyncResult::invokeCompletedAsync;
- bool sentSynchronously() const
+ void attachRemoteObserver(const Ice::ConnectionInfoPtr& c, const Ice::EndpointPtr& endpt, Ice::Int requestId)
{
- return _sentSynchronously; // No lock needed, immutable once __send() is called
+ const Ice::Int size = static_cast<Ice::Int>(_os.b.size() - headerSize - 4);
+ _childObserver.attach(getObserver().getRemoteObserver(c, endpt, requestId, size));
}
-
- LocalObjectPtr getCookie() const
+
+ void attachCollocatedObserver(const Ice::ObjectAdapterPtr& adapter, Ice::Int requestId)
{
- return _cookie; // No lock needed, cookie is immutable
+ const Ice::Int size = static_cast<Ice::Int>(_os.b.size() - headerSize - 4);
+ _childObserver.attach(getObserver().getCollocatedObserver(adapter, requestId, size));
}
- const std::string& getOperation() const
- {
- return _operation;
- }
-
- ::IceInternal::BasicStream*
- __getOs()
+ BasicStream* getOs()
{
return &_os;
}
- ::IceInternal::BasicStream* __startReadParams()
- {
- _is.startReadEncaps();
- return &_is;
- }
- void __endReadParams()
- {
- _is.endReadEncaps();
- }
- void __readEmptyParams()
- {
- _is.skipEmptyEncaps();
- }
- void __readParamEncaps(const ::Ice::Byte*& encaps, ::Ice::Int& sz)
- {
- _is.readEncaps(encaps, sz);
- }
-
- bool __wait();
- void __throwUserException();
- virtual void __invokeExceptionAsync(const Exception&);
- void __invokeCompleted();
-
- static void __check(const AsyncResultPtr&, const ::IceProxy::Ice::Object*, const ::std::string&);
- static void __check(const AsyncResultPtr&, const Connection*, const ::std::string&);
- static void __check(const AsyncResultPtr&, const Communicator*, const ::std::string&);
-
- virtual void __invokeException(const Exception&); // Required to be public for AsynchronousException
- void __invokeSent(); // Required to be public for AsynchronousSent
-
- void __attachRemoteObserver(const Ice::ConnectionInfoPtr& c, const Ice::EndpointPtr& endpt,
- Ice::Int requestId, Ice::Int sz)
- {
- _childObserver.attach(_observer.getRemoteObserver(c, endpt, requestId, sz));
- }
-
- void __attachCollocatedObserver(const Ice::ObjectAdapterPtr& adapter, Ice::Int requestId)
- {
- _childObserver.attach(_observer.getCollocatedObserver(adapter,
- requestId,
- static_cast<Ice::Int>(_os.b.size() -
- IceInternal::headerSize - 4)));
- }
-
- //
- // Called by the retry queue to process retry.
- //
- virtual void __processRetry() = 0;
-
protected:
- static void __check(const AsyncResultPtr&, const ::std::string&);
-
- AsyncResult(const CommunicatorPtr&, const IceInternal::InstancePtr&, const std::string&,
- const IceInternal::CallbackBasePtr&, const LocalObjectPtr&);
-
- void __invokeSentAsync();
-
- void runTimerTask(); // Implementation of TimerTask::runTimerTask()
-
- void __warning(const std::exception&) const;
- void __warning() const;
-
- virtual ~AsyncResult(); // Must be heap-allocated.
-
- const CommunicatorPtr _communicator;
- const IceInternal::InstancePtr _instance;
- const std::string& _operation;
- Ice::ConnectionPtr _cachedConnection;
- const IceInternal::CallbackBasePtr _callback;
- const LocalObjectPtr _cookie;
+ OutgoingAsyncBase(const Ice::CommunicatorPtr&, const InstancePtr&, const std::string&, const CallbackBasePtr&,
+ const Ice::LocalObjectPtr&);
- IceUtil::Monitor<IceUtil::Mutex> _monitor;
- IceInternal::BasicStream _is;
- IceInternal::BasicStream _os;
+ bool sent(bool);
+ bool finished(const Ice::Exception&);
- IceInternal::RequestHandlerPtr _timeoutRequestHandler;
+ ObserverHelperT<Ice::Instrumentation::ChildInvocationObserver> _childObserver;
- static const unsigned char OK;
- static const unsigned char Done;
- static const unsigned char Sent;
- static const unsigned char EndCalled;
-
- unsigned char _state;
- bool _sentSynchronously;
- IceUtil::UniquePtr<Exception> _exception;
- IceInternal::InvocationObserver _observer;
- IceInternal::ObserverHelperT<Ice::Instrumentation::ChildInvocationObserver> _childObserver;
+ BasicStream _os;
};
-}
-
-namespace IceInternal
-{
-
//
-// See comments in OutgoingAsync.cpp
+// Base class for proxy based invocations. This class handles the
+// retry for proxy invocations. It also ensures the child observer is
+// correct notified of failures and make sure the retry task is
+// correctly canceled when the invocation completes.
//
-extern ICE_API CallbackBasePtr __dummyCallback;
-
-class CollocatedRequestHandler;
-
-//
-// This interface is used by the connection to handle OutgoingAsync
-// and BatchOutgoingAsync messages.
-//
-class ICE_API OutgoingAsyncMessageCallback : virtual public Ice::LocalObject
+class ICE_API ProxyOutgoingAsyncBase : public OutgoingAsyncBase, protected IceUtil::TimerTask
{
public:
- virtual ~OutgoingAsyncMessageCallback()
- {
- }
+ virtual Ice::ObjectPrx getProxy() const;
- //
- // Called by the request handler to send the request over the connection.
- //
- virtual IceInternal::AsyncStatus __send(const Ice::ConnectionIPtr&, bool, bool) = 0;
+ virtual bool sent();
+ virtual bool completed(const Ice::Exception&);
- //
- // Called by the collocated request handler to invoke the request.
- //
- virtual IceInternal::AsyncStatus __invokeCollocated(CollocatedRequestHandler*) = 0;
+ void retry();
+ void abort(const Ice::Exception&);
- //
- // Called by the connection when the message is confirmed sent. The connection is locked
- // when this is called so this method can't call the sent callback. Instead, this method
- // returns true if there's a sent callback and false otherwise. If true is returned, the
- // connection will call the __invokeSentCallback() method bellow (which in turn should
- // call the sent callback).
- //
- virtual bool __sent() = 0;
+protected:
- //
- // Called by the connection to call the user sent callback.
- //
- virtual void __invokeSent() = 0;
+ ProxyOutgoingAsyncBase(const Ice::ObjectPrx&, const std::string&, const CallbackBasePtr&,
+ const Ice::LocalObjectPtr&);
- //
- // Called by the connection when the request failed.
- //
- virtual void __finished(const Ice::Exception&) = 0;
+ void invokeImpl(bool);
- //
- // Helper to dispatch invocation timeout.
- //
- void __dispatchInvocationTimeout(const ThreadPoolPtr&, const Ice::ConnectionPtr&);
+ bool sent(bool);
+ bool finished(const Ice::Exception&);
+ bool finished(bool);
+
+ virtual void handleRetryException(const RetryException&);
+ virtual int handleException(const Ice::Exception&);
+ virtual void runTimerTask();
+
+ const Ice::ObjectPrx _proxy;
+ RequestHandlerPtr _handler;
+ Ice::OperationMode _mode;
+
+private:
+
+ int _cnt;
+ bool _sent;
};
-class ICE_API OutgoingAsync : public OutgoingAsyncMessageCallback, public Ice::AsyncResult
+//
+// Class for handling Slice operation invocations
+//
+class ICE_API OutgoingAsync : public ProxyOutgoingAsyncBase
{
public:
OutgoingAsync(const Ice::ObjectPrx&, const std::string&, const CallbackBasePtr&, const Ice::LocalObjectPtr&);
- void __prepare(const std::string&, Ice::OperationMode, const Ice::Context*);
+ void prepare(const std::string&, Ice::OperationMode, const Ice::Context*);
- virtual Ice::ObjectPrx
- getProxy() const
- {
- return _proxy;
- }
+ virtual AsyncStatus send(const Ice::ConnectionIPtr&, bool, bool);
+ virtual AsyncStatus invokeCollocated(CollocatedRequestHandler*);
- virtual IceInternal::AsyncStatus __send(const Ice::ConnectionIPtr&, bool, bool);
- virtual IceInternal::AsyncStatus __invokeCollocated(CollocatedRequestHandler*);
- virtual bool __sent();
- virtual void __invokeSent();
- virtual void __finished(const Ice::Exception&);
- virtual void __invokeExceptionAsync(const Ice::Exception&);
- virtual void __processRetry();
+ void abort(const Ice::Exception&);
- bool __finished();
- bool __invoke(bool);
+ void invoke();
+ using ProxyOutgoingAsyncBase::completed;
+ bool completed();
- BasicStream* __startWriteParams(Ice::FormatType format)
+ BasicStream* startWriteParams(Ice::FormatType format)
{
_os.startWriteEncaps(_encoding, format);
return &_os;
}
- void __endWriteParams()
+ void endWriteParams()
{
_os.endWriteEncaps();
}
- void __writeEmptyParams()
+ void writeEmptyParams()
{
_os.writeEmptyEncaps(_encoding);
}
- void __writeParamEncaps(const ::Ice::Byte* encaps, ::Ice::Int size)
+ void writeParamEncaps(const ::Ice::Byte* encaps, ::Ice::Int size)
{
if(size == 0)
{
@@ -291,315 +166,95 @@ public:
}
}
- ::IceInternal::BasicStream*
- __getIs()
+ BasicStream* getIs()
{
return &_is;
}
private:
- void handleException(const Ice::Exception&);
-
- const Ice::ObjectPrx _proxy;
const Ice::EncodingVersion _encoding;
-
- RequestHandlerPtr _handler;
- int _cnt;
- bool _sent;
- Ice::OperationMode _mode;
-};
-
-class ICE_API BatchOutgoingAsync : public OutgoingAsyncMessageCallback, public Ice::AsyncResult
-{
-public:
-
- BatchOutgoingAsync(const Ice::CommunicatorPtr&, const InstancePtr&, const std::string&, const CallbackBasePtr&,
- const Ice::LocalObjectPtr&);
-
- virtual IceInternal::AsyncStatus __send(const Ice::ConnectionIPtr&, bool, bool);
- virtual IceInternal::AsyncStatus __invokeCollocated(CollocatedRequestHandler*);
- virtual bool __sent();
- virtual void __invokeSent();
- virtual void __finished(const Ice::Exception&);
- virtual void __processRetry();
-};
-
-class ICE_API ProxyBatchOutgoingAsync : public BatchOutgoingAsync
-{
-public:
-
- ProxyBatchOutgoingAsync(const Ice::ObjectPrx&, const std::string&, const CallbackBasePtr&,
- const Ice::LocalObjectPtr&);
-
- void __invoke();
-
- virtual Ice::ObjectPrx
- getProxy() const
- {
- return _proxy;
- }
-
-private:
-
- const Ice::ObjectPrx _proxy;
};
-class ICE_API ConnectionBatchOutgoingAsync : public BatchOutgoingAsync
-{
-public:
-
- ConnectionBatchOutgoingAsync(const Ice::ConnectionIPtr&, const Ice::CommunicatorPtr&, const InstancePtr&,
- const std::string&, const CallbackBasePtr&, const Ice::LocalObjectPtr&);
-
- void __invoke();
-
- virtual Ice::ConnectionPtr getConnection() const;
-
-private:
-
- const Ice::ConnectionIPtr _connection;
-};
-
-class ICE_API CommunicatorBatchOutgoingAsync : public Ice::AsyncResult
-{
-public:
-
- CommunicatorBatchOutgoingAsync(const Ice::CommunicatorPtr&, const InstancePtr&, const std::string&,
- const CallbackBasePtr&, const Ice::LocalObjectPtr&);
-
- void flushConnection(const Ice::ConnectionIPtr&);
- void ready();
-
- virtual void __processRetry();
-
-private:
-
- void check(bool);
-
- int _useCount;
-};
-
-class ICE_API GetConnectionOutgoingAsync : public OutgoingAsyncMessageCallback, public Ice::AsyncResult
+//
+// Class for handling the proxy's begin_ice_flushBatchRequest request.
+//
+class ICE_API ProxyFlushBatch : public ProxyOutgoingAsyncBase
{
public:
- GetConnectionOutgoingAsync(const Ice::ObjectPrx&, const std::string&, const CallbackBasePtr&,
- const Ice::LocalObjectPtr&);
+ ProxyFlushBatch(const Ice::ObjectPrx&, const std::string&, const CallbackBasePtr&, const Ice::LocalObjectPtr&);
- void __invoke();
+ virtual bool sent();
- virtual Ice::ObjectPrx
- getProxy() const
- {
- return _proxy;
- }
+ virtual AsyncStatus send(const Ice::ConnectionIPtr&, bool, bool);
+ virtual AsyncStatus invokeCollocated(CollocatedRequestHandler*);
- virtual AsyncStatus __send(const Ice::ConnectionIPtr&, bool, bool);
- virtual AsyncStatus __invokeCollocated(CollocatedRequestHandler*);
- virtual bool __sent();
- virtual void __invokeSent();
- virtual void __finished(const Ice::Exception&);
- virtual void __processRetry();
+ void invoke();
private:
- void handleException(const Ice::Exception&);
-
- Ice::ObjectPrx _proxy;
- RequestHandlerPtr _handler;
- int _cnt;
+ virtual void handleRetryException(const RetryException&);
+ virtual int handleException(const Ice::Exception&);
};
+typedef IceUtil::Handle<ProxyFlushBatch> ProxyFlushBatchPtr;
//
-// Base class for all callbacks.
+// Class for handling the proxy's begin_ice_getConnection request.
//
-class ICE_API CallbackBase : public IceUtil::Shared
+class ICE_API ProxyGetConnection : public ProxyOutgoingAsyncBase
{
public:
- void checkCallback(bool, bool);
+ ProxyGetConnection(const Ice::ObjectPrx&, const std::string&, const CallbackBasePtr&, const Ice::LocalObjectPtr&);
- virtual void completed(const ::Ice::AsyncResultPtr&) const = 0;
- virtual CallbackBasePtr verify(const ::Ice::LocalObjectPtr&) = 0;
- virtual void sent(const ::Ice::AsyncResultPtr&) const = 0;
- virtual bool hasSentCallback() const = 0;
-};
+ virtual AsyncStatus send(const Ice::ConnectionIPtr&, bool, bool);
+ virtual AsyncStatus invokeCollocated(CollocatedRequestHandler*);
-//
-// Base class for generic callbacks.
-//
-class ICE_API GenericCallbackBase : virtual public CallbackBase
-{
+ void invoke();
};
+typedef IceUtil::Handle<ProxyGetConnection> ProxyGetConnectionPtr;
//
-// Generic callback template that requires the caller to down-cast the
-// proxy and the cookie that are obtained from the AsyncResult.
+// Class for handling Ice::Connection::begin_flushBatchRequests
//
-template<class T>
-class AsyncCallback : public GenericCallbackBase
+class ICE_API ConnectionFlushBatch : public OutgoingAsyncBase
{
public:
- typedef T callback_type;
- typedef IceUtil::Handle<T> TPtr;
-
- typedef void (T::*Callback)(const ::Ice::AsyncResultPtr&);
-
- AsyncCallback(const TPtr& instance, Callback cb, Callback sentcb = 0) :
- _callback(instance), _completed(cb), _sent(sentcb)
- {
- checkCallback(instance, cb != 0);
- }
-
- virtual void completed(const ::Ice::AsyncResultPtr& result) const
- {
- (_callback.get()->*_completed)(result);
- }
-
- virtual CallbackBasePtr verify(const ::Ice::LocalObjectPtr&)
- {
- return this; // Nothing to do, the cookie is not type-safe.
- }
-
- virtual void sent(const ::Ice::AsyncResultPtr& result) const
- {
- if(_sent)
- {
- (_callback.get()->*_sent)(result);
- }
- }
+ ConnectionFlushBatch(const Ice::ConnectionIPtr&, const Ice::CommunicatorPtr&, const InstancePtr&,
+ const std::string&, const CallbackBasePtr&, const Ice::LocalObjectPtr&);
+
+ virtual Ice::ConnectionPtr getConnection() const;
- virtual bool hasSentCallback() const
- {
- return _sent != 0;
- }
+ void invoke();
private:
- TPtr _callback;
- Callback _completed;
- Callback _sent;
-};
-
-#ifdef ICE_CPP11
-
-template<typename T> struct callback_type
-{
- static const int value = 1;
-};
-
-template<> struct callback_type<void(const ::Ice::AsyncResultPtr&)>
-{
- static const int value = 2;
-};
-
-template<> struct callback_type<void(const ::Ice::Exception&)>
-{
- static const int value = 3;
-};
-
-template<typename Callable, typename = void> struct callable_type
-{
- static const int value = 1;
-};
-
-template<class Callable> struct callable_type<Callable, typename ::std::enable_if<
- ::std::is_class<Callable>::value &&
- !::std::is_bind_expression<Callable>::value>::type>
-{
- template<typename T, T> struct TypeCheck;
- template<typename T> struct AsyncResultCallback
- {
- typedef void (T::*ok)(const ::Ice::AsyncResultPtr&) const;
- };
- template<typename T> struct ExceptionCallback
- {
- typedef void (T::*ok)(const ::Ice::Exception&) const;
- };
-
- typedef char (&other)[1];
- typedef char (&asyncResult)[2];
- typedef char (&exception)[3];
-
- template<typename T> static other check(...);
- template<typename T> static asyncResult check(TypeCheck<typename AsyncResultCallback<T>::ok, &T::operator()>*);
- template<typename T> static exception check(TypeCheck<typename ExceptionCallback<T>::ok, &T::operator()>*);
-
- enum { value = sizeof(check<Callable>(0)) };
-};
-
-template<> struct callable_type<void(*)(const ::Ice::AsyncResultPtr&)>
-{
- static const int value = 2;
-};
-
-template<> struct callable_type<void(*)(const ::Ice::Exception&)>
-{
- static const int value = 3;
-};
-
-template<typename Callable, typename Callback> struct is_callable
-{
- static const bool value = callable_type<Callable>::value == callback_type<Callback>::value;
+ const Ice::ConnectionIPtr _connection;
};
+typedef IceUtil::Handle<ConnectionFlushBatch> ConnectionFlushBatchPtr;
-template<class S> class Function : public std::function<S>
+//
+// Class for handling Ice::Communicator::begin_flushBatchRequests
+//
+class ICE_API CommunicatorFlushBatch : public Ice::AsyncResult
{
-
public:
- template<typename T> Function(T f, typename ::std::enable_if<is_callable<T, S>::value>::type* = 0)
- : std::function<S>(f)
- {
- }
-
- Function()
- {
- }
-
- Function(::std::nullptr_t) : ::std::function<S>(nullptr)
- {
- }
-};
-
-#endif
-
-}
-
-namespace Ice
-{
+ CommunicatorFlushBatch(const Ice::CommunicatorPtr&, const InstancePtr&, const std::string&,
+ const CallbackBasePtr&, const Ice::LocalObjectPtr&);
-typedef IceUtil::Handle< ::IceInternal::GenericCallbackBase> CallbackPtr;
-
-template<class T> CallbackPtr
-newCallback(const IceUtil::Handle<T>& instance,
- void (T::*cb)(const AsyncResultPtr&),
- void (T::*sentcb)(const AsyncResultPtr&) = 0)
-{
- return new ::IceInternal::AsyncCallback<T>(instance, cb, sentcb);
-}
+ void flushConnection(const Ice::ConnectionIPtr&);
+ void ready();
-template<class T> CallbackPtr
-newCallback(T* instance,
- void (T::*cb)(const AsyncResultPtr&),
- void (T::*sentcb)(const AsyncResultPtr&) = 0)
-{
- return new ::IceInternal::AsyncCallback<T>(instance, cb, sentcb);
-}
+private:
-#ifdef ICE_CPP11
+ void check(bool);
-ICE_API CallbackPtr
-newCallback(const ::IceInternal::Function<void (const AsyncResultPtr&)>&,
- const ::IceInternal::Function<void (const AsyncResultPtr&)>& =
- ::IceInternal::Function<void (const AsyncResultPtr&)>());
-#endif
+ int _useCount;
+};
-//
-// Operation callbacks are specified in Proxy.h
-//
}
#endif
diff --git a/cpp/include/Ice/OutgoingAsyncF.h b/cpp/include/Ice/OutgoingAsyncF.h
index 9675fa6c468..811a588e0b3 100644
--- a/cpp/include/Ice/OutgoingAsyncF.h
+++ b/cpp/include/Ice/OutgoingAsyncF.h
@@ -14,45 +14,24 @@
#include <Ice/Handle.h>
-namespace Ice
-{
-
-class AsyncResult;
-ICE_API IceUtil::Shared* upCast(::Ice::AsyncResult*);
-typedef IceInternal::Handle<AsyncResult> AsyncResultPtr;
-
-}
-
namespace IceInternal
{
+class OutgoingAsyncBase;
+ICE_API IceUtil::Shared* upCast(OutgoingAsyncBase*);
+typedef IceInternal::Handle<OutgoingAsyncBase> OutgoingAsyncBasePtr;
+
class OutgoingAsync;
ICE_API IceUtil::Shared* upCast(OutgoingAsync*);
typedef IceInternal::Handle<OutgoingAsync> OutgoingAsyncPtr;
-class OutgoingAsyncMessageCallback;
-ICE_API IceUtil::Shared* upCast(OutgoingAsyncMessageCallback*);
-typedef IceInternal::Handle<OutgoingAsyncMessageCallback> OutgoingAsyncMessageCallbackPtr;
-
-class BatchOutgoingAsync;
-ICE_API IceUtil::Shared* upCast(BatchOutgoingAsync*);
-typedef IceInternal::Handle<BatchOutgoingAsync> BatchOutgoingAsyncPtr;
-
-class ProxyBatchOutgoingAsync;
-ICE_API IceUtil::Shared* upCast(ProxyBatchOutgoingAsync*);
-typedef IceInternal::Handle<ProxyBatchOutgoingAsync> ProxyBatchOutgoingAsyncPtr;
-
-class ConnectionBatchOutgoingAsync;
-ICE_API IceUtil::Shared* upCast(ConnectionBatchOutgoingAsync*);
-typedef IceInternal::Handle<ConnectionBatchOutgoingAsync> ConnectionBatchOutgoingAsyncPtr;
-
-class CommunicatorBatchOutgoingAsync;
-ICE_API IceUtil::Shared* upCast(CommunicatorBatchOutgoingAsync*);
-typedef IceInternal::Handle<CommunicatorBatchOutgoingAsync> CommunicatorBatchOutgoingAsyncPtr;
+class ProxyOutgoingAsyncBase;
+ICE_API IceUtil::Shared* upCast(ProxyOutgoingAsyncBase*);
+typedef IceInternal::Handle<ProxyOutgoingAsyncBase> ProxyOutgoingAsyncBasePtr;
-class GetConnectionOutgoingAsync;
-ICE_API IceUtil::Shared* upCast(GetConnectionOutgoingAsync*);
-typedef IceInternal::Handle<GetConnectionOutgoingAsync> GetConnectionOutgoingAsyncPtr;
+class CommunicatorFlushBatch;
+ICE_API IceUtil::Shared* upCast(CommunicatorFlushBatch*);
+typedef IceInternal::Handle<CommunicatorFlushBatch> CommunicatorFlushBatchPtr;
}
diff --git a/cpp/include/Ice/Proxy.h b/cpp/include/Ice/Proxy.h
index 6bbd1c7ffe7..0600916d324 100644
--- a/cpp/include/Ice/Proxy.h
+++ b/cpp/include/Ice/Proxy.h
@@ -21,7 +21,7 @@
#include <Ice/ObjectF.h>
#include <Ice/ObjectAdapterF.h>
#include <Ice/ReferenceF.h>
-#include <Ice/OutgoingAsync.h>
+#include <Ice/AsyncResult.h>
//#include <Ice/RouterF.h> // Can't include RouterF.h here, otherwise we have cyclic includes
//#include <Ice/LocatorF.h> // Can't include RouterF.h here, otherwise we have cyclic includes
#include <Ice/Current.h>
@@ -1378,8 +1378,6 @@ public:
}
};
-
-
template<class T, typename CT>
class TwowayCallback : public Callback<T, CT>
{
diff --git a/cpp/include/Ice/RequestHandlerF.h b/cpp/include/Ice/RequestHandlerF.h
index 09013ba6fc8..3d63656edc5 100644
--- a/cpp/include/Ice/RequestHandlerF.h
+++ b/cpp/include/Ice/RequestHandlerF.h
@@ -20,6 +20,10 @@ class RequestHandler;
ICE_API IceUtil::Shared* upCast(RequestHandler*);
typedef IceInternal::Handle<RequestHandler> RequestHandlerPtr;
+class CancellationHandler;
+ICE_API IceUtil::Shared* upCast(CancellationHandler*);
+typedef IceInternal::Handle<CancellationHandler> CancellationHandlerPtr;
+
}
#endif
diff --git a/cpp/src/Ice/AsyncResult.cpp b/cpp/src/Ice/AsyncResult.cpp
new file mode 100644
index 00000000000..03abc55e020
--- /dev/null
+++ b/cpp/src/Ice/AsyncResult.cpp
@@ -0,0 +1,602 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceUtil/DisableWarnings.h>
+#include <Ice/AsyncResult.h>
+#include <Ice/ThreadPool.h>
+#include <Ice/Instance.h>
+#include <Ice/LoggerUtil.h>
+#include <Ice/Properties.h>
+#include <Ice/RequestHandler.h>
+#include <Ice/OutgoingAsync.h>
+
+using namespace std;
+using namespace Ice;
+using namespace IceInternal;
+
+IceUtil::Shared* Ice::upCast(AsyncResult* p) { return p; }
+
+const unsigned char Ice::AsyncResult::OK = 0x1;
+const unsigned char Ice::AsyncResult::Done = 0x2;
+const unsigned char Ice::AsyncResult::Sent = 0x4;
+const unsigned char Ice::AsyncResult::EndCalled = 0x8;
+
+void
+AsyncResult::cancel()
+{
+ cancel(InvocationCanceledException(__FILE__, __LINE__));
+}
+
+Int
+AsyncResult::getHash() const
+{
+ return static_cast<Int>(reinterpret_cast<Long>(this) >> 4);
+}
+
+CommunicatorPtr
+AsyncResult::getCommunicator() const
+{
+ return _communicator;
+}
+
+ConnectionPtr
+AsyncResult::getConnection() const
+{
+ return 0;
+}
+
+ObjectPrx
+AsyncResult::getProxy() const
+{
+ return 0;
+}
+
+bool
+AsyncResult::isCompleted() const
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ return _state & Done;
+}
+
+void
+AsyncResult::waitForCompleted()
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ while(!(_state & Done))
+ {
+ _monitor.wait();
+ }
+}
+
+bool
+AsyncResult::isSent() const
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ return _state & Sent;
+}
+
+void
+AsyncResult::waitForSent()
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ while(!(_state & Sent) && !_exception.get())
+ {
+ _monitor.wait();
+ }
+}
+
+void
+AsyncResult::throwLocalException() const
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ if(_exception.get())
+ {
+ _exception.get()->ice_throw();
+ }
+}
+
+bool
+AsyncResult::sentSynchronously() const
+{
+ return _sentSynchronously;
+}
+
+LocalObjectPtr
+AsyncResult::getCookie() const
+{
+ return _cookie;
+}
+
+const std::string&
+AsyncResult::getOperation() const
+{
+ return _operation;
+}
+
+void
+AsyncResult::__throwUserException()
+{
+ try
+ {
+ _is.startReadEncaps();
+ _is.throwException();
+ }
+ catch(const Ice::UserException&)
+ {
+ _is.endReadEncaps();
+ throw;
+ }
+}
+
+bool
+AsyncResult::__wait()
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ if(_state & EndCalled)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "end_ method called more than once");
+ }
+ _state |= EndCalled;
+ while(!(_state & Done))
+ {
+ _monitor.wait();
+ }
+ if(_exception.get())
+ {
+ _exception.get()->ice_throw();
+ }
+ return _state & OK;
+}
+
+void
+AsyncResult::__check(const AsyncResultPtr& r, const IceProxy::Ice::Object* prx, const string& operation)
+{
+ __check(r, operation);
+ if(r->getProxy().get() != prx)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Proxy for call to end_" + operation +
+ " does not match proxy that was used to call corresponding begin_" +
+ operation + " method");
+ }
+}
+
+void
+AsyncResult::__check(const AsyncResultPtr& r, const Ice::Communicator* com, const string& operation)
+{
+ __check(r, operation);
+ if(r->getCommunicator().get() != com)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Communicator for call to end_" + operation +
+ " does not match communicator that was used to call corresponding " +
+ "begin_" + operation + " method");
+ }
+}
+
+void
+AsyncResult::__check(const AsyncResultPtr& r, const Ice::Connection* con, const string& operation)
+{
+ __check(r, operation);
+ if(r->getConnection().get() != con)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Connection for call to end_" + operation +
+ " does not match connection that was used to call corresponding " +
+ "begin_" + operation + " method");
+ }
+}
+
+void
+AsyncResult::__check(const AsyncResultPtr& r, const string& operation)
+{
+ if(!r)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "AsyncResult == null");
+ }
+ else if(&r->_operation != &operation)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Incorrect operation for end_" + operation +
+ " method: " + r->_operation);
+ }
+}
+
+AsyncResult::AsyncResult(const CommunicatorPtr& communicator,
+ const IceInternal::InstancePtr& instance,
+ const string& op,
+ const CallbackBasePtr& del,
+ const LocalObjectPtr& cookie) :
+ _instance(instance),
+ _sentSynchronously(false),
+ _is(instance.get(), Ice::currentProtocolEncoding),
+ _communicator(communicator),
+ _operation(op),
+ _callback(del),
+ _cookie(cookie),
+ _state(0)
+{
+ if(!_callback)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__);
+ }
+ const_cast<CallbackBasePtr&>(_callback) = _callback->verify(_cookie);
+}
+
+AsyncResult::~AsyncResult()
+{
+}
+
+bool
+AsyncResult::sent(bool done)
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ assert(!_exception.get());
+
+ bool alreadySent = _state & Sent;
+ _state |= Sent;
+ if(done)
+ {
+ _state |= Done | OK;
+ _cancellationHandler = 0;
+ if(!_callback || !_callback->hasSentCallback())
+ {
+ _observer.detach();
+ }
+ }
+
+ _monitor.notifyAll();
+ return !alreadySent && _callback && _callback->hasSentCallback();
+}
+
+bool
+AsyncResult::finished(bool ok)
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ _state |= Done;
+ if(ok)
+ {
+ _state |= OK;
+ }
+ _cancellationHandler = 0;
+ if(!_callback)
+ {
+ _observer.detach();
+ }
+ _monitor.notifyAll();
+ return _callback;
+}
+
+bool
+AsyncResult::finished(const Ice::Exception& ex)
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ _state |= Done;
+ _exception.reset(ex.ice_clone());
+ _cancellationHandler = 0;
+ _observer.failed(ex.ice_name());
+ if(!_callback)
+ {
+ _observer.detach();
+ }
+ _monitor.notifyAll();
+ return _callback;
+}
+
+void
+AsyncResult::invokeSentAsync()
+{
+ class AsynchronousSent : public DispatchWorkItem
+ {
+ public:
+
+ AsynchronousSent(const ConnectionPtr& connection, const AsyncResultPtr& result) :
+ DispatchWorkItem(connection), _result(result)
+ {
+ }
+
+ virtual void
+ run()
+ {
+ _result->invokeSent();
+ }
+
+ private:
+
+ const AsyncResultPtr _result;
+ };
+
+ //
+ // This is called when it's not safe to call the sent callback
+ // synchronously from this thread. Instead the exception callback
+ // is called asynchronously from the client thread pool.
+ //
+ try
+ {
+ _instance->clientThreadPool()->dispatch(new AsynchronousSent(_cachedConnection, this));
+ }
+ catch(const Ice::CommunicatorDestroyedException&)
+ {
+ }
+}
+
+void
+AsyncResult::invokeCompletedAsync()
+{
+ class AsynchronousCompleted : public DispatchWorkItem
+ {
+ public:
+
+ AsynchronousCompleted(const ConnectionPtr& connection, const AsyncResultPtr& result) :
+ DispatchWorkItem(connection), _result(result)
+ {
+ }
+
+ virtual void
+ run()
+ {
+ _result->invokeCompleted();
+ }
+
+ private:
+
+ const AsyncResultPtr _result;
+ };
+
+ //
+ // CommunicatorDestroyedCompleted is the only exception that can propagate directly
+ // from this method.
+ //
+ _instance->clientThreadPool()->dispatch(new AsynchronousCompleted(_cachedConnection, this));
+}
+
+void
+AsyncResult::invokeSent()
+{
+ assert(_callback);
+
+ try
+ {
+ AsyncResultPtr self(this);
+ _callback->sent(self);
+ }
+ catch(const std::exception& ex)
+ {
+ warning(ex);
+ }
+ catch(...)
+ {
+ warning();
+ }
+
+ if(_observer)
+ {
+ ObjectPrx proxy = getProxy();
+ if(!proxy || !proxy->ice_isTwoway())
+ {
+ _observer.detach();
+ }
+ }
+}
+
+void
+AsyncResult::invokeCompleted()
+{
+ assert(_callback);
+
+ try
+ {
+ AsyncResultPtr self(this);
+ _callback->completed(self);
+ }
+ catch(const std::exception& ex)
+ {
+ warning(ex);
+ }
+ catch(...)
+ {
+ warning();
+ }
+
+ _observer.detach();
+}
+
+void
+AsyncResult::cancel(const Ice::LocalException& ex)
+{
+ {
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ _cancellationException.reset(ex.ice_clone());
+ if(!_cancellationHandler)
+ {
+ return;
+ }
+ }
+ _cancellationHandler->asyncRequestCanceled(OutgoingAsyncBasePtr::dynamicCast(this), ex);
+}
+
+void
+AsyncResult::cancelable(const CancellationHandlerPtr& handler)
+{
+ {
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ if(!_cancellationException.get())
+ {
+ _cancellationHandler = handler;
+ return;
+ }
+ }
+ handler->asyncRequestCanceled(OutgoingAsyncBasePtr::dynamicCast(this), *_cancellationException.get());
+}
+
+void
+AsyncResult::checkCanceled()
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ if(_cancellationException.get())
+ {
+ _cancellationException->ice_throw();
+ }
+}
+
+void
+AsyncResult::warning(const std::exception& exc) const
+{
+ if(_instance->initializationData().properties->getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0)
+ {
+ Warning out(_instance->initializationData().logger);
+ const Exception* ex = dynamic_cast<const Exception*>(&exc);
+ if(ex)
+ {
+ out << "Ice::Exception raised by AMI callback:\n" << *ex;
+ }
+ else
+ {
+ out << "std::exception raised by AMI callback:\n" << exc.what();
+ }
+ }
+}
+
+void
+AsyncResult::warning() const
+{
+ if(_instance->initializationData().properties->getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0)
+ {
+ Warning out(_instance->initializationData().logger);
+ out << "unknown exception raised by AMI callback";
+ }
+}
+
+
+namespace
+{
+
+//
+// Dummy class derived from CallbackBase
+// We use this class for the __dummyCallback extern pointer in OutgoingAsync. In turn,
+// this allows us to test whether the user supplied a null delegate instance to the
+// generated begin_ method without having to generate a separate test to throw IllegalArgumentException
+// in the inlined versions of the begin_ method. In other words, this reduces the amount of generated
+// object code.
+//
+class DummyCallback : public CallbackBase
+{
+public:
+
+ DummyCallback()
+ {
+ }
+
+ virtual void
+ completed(const Ice::AsyncResultPtr&) const
+ {
+ assert(false);
+ }
+
+ virtual CallbackBasePtr
+ verify(const Ice::LocalObjectPtr&)
+ {
+ //
+ // Called by the AsyncResult constructor to verify the delegate. The dummy
+ // delegate is passed when the user used a begin_ method without delegate.
+ // By returning 0 here, we tell the AsyncResult that no delegates was
+ // provided.
+ //
+ return 0;
+ }
+
+ virtual void
+ sent(const AsyncResultPtr&) const
+ {
+ assert(false);
+ }
+
+ virtual bool
+ hasSentCallback() const
+ {
+ assert(false);
+ return false;
+ }
+};
+
+}
+
+//
+// This gives a pointer value to compare against in the generated
+// begin_ method to decide whether the caller passed a null pointer
+// versus the generated inline version of the begin_ method having
+// passed a pointer to the dummy delegate.
+//
+CallbackBasePtr IceInternal::__dummyCallback = new DummyCallback;
+
+#ifdef ICE_CPP11
+
+Ice::CallbackPtr
+Ice::newCallback(const ::IceInternal::Function<void (const AsyncResultPtr&)>& completed,
+ const ::IceInternal::Function<void (const AsyncResultPtr&)>& sent)
+{
+ class Cpp11CB : public GenericCallbackBase
+ {
+ public:
+
+ Cpp11CB(const ::std::function<void (const AsyncResultPtr&)>& completed,
+ const ::std::function<void (const AsyncResultPtr&)>& sent) :
+ _completed(completed),
+ _sent(sent)
+ {
+ checkCallback(true, completed != nullptr);
+ }
+
+ virtual void
+ completed(const AsyncResultPtr& result) const
+ {
+ _completed(result);
+ }
+
+ virtual CallbackBasePtr
+ verify(const LocalObjectPtr&)
+ {
+ return this; // Nothing to do, the cookie is not type-safe.
+ }
+
+ virtual void
+ sent(const AsyncResultPtr& result) const
+ {
+ if(_sent != nullptr)
+ {
+ _sent(result);
+ }
+ }
+
+ virtual bool
+ hasSentCallback() const
+ {
+ return _sent != nullptr;
+ }
+
+ private:
+
+ ::std::function< void (const AsyncResultPtr&)> _completed;
+ ::std::function< void (const AsyncResultPtr&)> _sent;
+ };
+
+ return new Cpp11CB(completed, sent);
+}
+#endif
+
+void
+IceInternal::CallbackBase::checkCallback(bool obj, bool cb)
+{
+ if(!obj)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "callback object cannot be null");
+ }
+ if(!cb)
+ {
+ throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "callback cannot be null");
+ }
+}
+
+
diff --git a/cpp/src/Ice/CollocatedRequestHandler.cpp b/cpp/src/Ice/CollocatedRequestHandler.cpp
index 0b08198726a..3fc321735cb 100644
--- a/cpp/src/Ice/CollocatedRequestHandler.cpp
+++ b/cpp/src/Ice/CollocatedRequestHandler.cpp
@@ -14,6 +14,8 @@
#include <Ice/Reference.h>
#include <Ice/Instance.h>
#include <Ice/TraceLevels.h>
+#include <Ice/Outgoing.h>
+#include <Ice/OutgoingAsync.h>
#include <Ice/TraceUtil.h>
@@ -28,7 +30,7 @@ class InvokeAll : public DispatchWorkItem
{
public:
- InvokeAll(OutgoingMessageCallback* out,
+ InvokeAll(OutgoingBase* out,
BasicStream* os,
CollocatedRequestHandler* handler,
Int requestId,
@@ -49,7 +51,7 @@ public:
private:
- OutgoingMessageCallback* _out;
+ OutgoingBase* _out;
BasicStream* _os;
CollocatedRequestHandlerPtr _handler;
Int _requestId;
@@ -61,7 +63,7 @@ class InvokeAllAsync : public DispatchWorkItem
{
public:
- InvokeAllAsync(const OutgoingAsyncMessageCallbackPtr& outAsync,
+ InvokeAllAsync(const OutgoingAsyncBasePtr& outAsync,
BasicStream* os,
CollocatedRequestHandler* handler,
Int requestId,
@@ -82,7 +84,7 @@ public:
private:
- OutgoingAsyncMessageCallbackPtr _outAsync;
+ OutgoingAsyncBasePtr _outAsync;
BasicStream* _os;
CollocatedRequestHandlerPtr _handler;
Int _requestId;
@@ -113,7 +115,7 @@ public:
private:
const CollocatedRequestHandlerPtr _handler;
- const OutgoingAsyncMessageCallbackPtr _outAsync;
+ const OutgoingAsyncBasePtr _outAsync;
BasicStream _stream;
Int _invokeNum;
};
@@ -261,24 +263,24 @@ CollocatedRequestHandler::abortBatchRequest()
}
bool
-CollocatedRequestHandler::sendRequest(OutgoingMessageCallback* out)
+CollocatedRequestHandler::sendRequest(OutgoingBase* out)
{
out->invokeCollocated(this);
return !_response && _reference->getInvocationTimeout() == 0;
}
AsyncStatus
-CollocatedRequestHandler::sendAsyncRequest(const OutgoingAsyncMessageCallbackPtr& outAsync)
+CollocatedRequestHandler::sendAsyncRequest(const OutgoingAsyncBasePtr& outAsync)
{
- return outAsync->__invokeCollocated(this);
+ return outAsync->invokeCollocated(this);
}
void
-CollocatedRequestHandler::requestTimedOut(OutgoingMessageCallback* out)
+CollocatedRequestHandler::requestCanceled(OutgoingBase* out, const LocalException& ex)
{
Lock sync(*this);
- map<OutgoingMessageCallback*, Int>::iterator p = _sendRequests.find(out);
+ map<OutgoingBase*, Int>::iterator p = _sendRequests.find(out);
if(p != _sendRequests.end())
{
if(p->second > 0)
@@ -286,7 +288,7 @@ CollocatedRequestHandler::requestTimedOut(OutgoingMessageCallback* out)
_requests.erase(p->second);
}
InvocationTimeoutException ex(__FILE__, __LINE__);
- out->finished(ex);
+ out->completed(ex);
_sendRequests.erase(p);
return;
}
@@ -299,7 +301,7 @@ CollocatedRequestHandler::requestTimedOut(OutgoingMessageCallback* out)
if(q->second == o)
{
InvocationTimeoutException ex(__FILE__, __LINE__);
- o->finished(ex);
+ o->completed(ex);
_requests.erase(q);
return; // We're done.
}
@@ -307,12 +309,12 @@ CollocatedRequestHandler::requestTimedOut(OutgoingMessageCallback* out)
}
}
-void
-CollocatedRequestHandler::asyncRequestTimedOut(const OutgoingAsyncMessageCallbackPtr& outAsync)
+void
+CollocatedRequestHandler::asyncRequestCanceled(const OutgoingAsyncBasePtr& outAsync, const LocalException& ex)
{
Lock sync(*this);
-
- map<OutgoingAsyncMessageCallbackPtr, Int>::iterator p = _sendAsyncRequests.find(outAsync);
+
+ map<OutgoingAsyncBasePtr, Int>::iterator p = _sendAsyncRequests.find(outAsync);
if(p != _sendAsyncRequests.end())
{
if(p->second > 0)
@@ -320,7 +322,10 @@ CollocatedRequestHandler::asyncRequestTimedOut(const OutgoingAsyncMessageCallbac
_asyncRequests.erase(p->second);
}
_sendAsyncRequests.erase(p);
- outAsync->__dispatchInvocationTimeout(_reference->getInstance()->clientThreadPool(), 0);
+ if(outAsync->completed(ex))
+ {
+ outAsync->invokeCompletedAsync();
+ }
return;
}
@@ -332,7 +337,10 @@ CollocatedRequestHandler::asyncRequestTimedOut(const OutgoingAsyncMessageCallbac
if(q->second.get() == o.get())
{
_asyncRequests.erase(q);
- outAsync->__dispatchInvocationTimeout(_reference->getInstance()->clientThreadPool(), 0);
+ if(outAsync->completed(ex))
+ {
+ outAsync->invokeCompletedAsync();
+ }
return;
}
}
@@ -391,16 +399,17 @@ CollocatedRequestHandler::invokeAsyncRequest(OutgoingAsync* outAsync)
{
_sendAsyncRequests.insert(make_pair(outAsync, requestId));
}
+ outAsync->cancelable(this);
}
- outAsync->__attachCollocatedObserver(_adapter, requestId);
+ outAsync->attachCollocatedObserver(_adapter, requestId);
- _adapter->getThreadPool()->dispatch(new InvokeAllAsync(outAsync, outAsync->__getOs(), this, requestId, 1, false));
+ _adapter->getThreadPool()->dispatch(new InvokeAllAsync(outAsync, outAsync->getOs(), this, requestId, 1, false));
return AsyncStatusQueued;
}
void
-CollocatedRequestHandler::invokeBatchRequests(BatchOutgoing* out)
+CollocatedRequestHandler::invokeBatchRequests(OutgoingBase* out)
{
Int invokeNum;
{
@@ -457,7 +466,7 @@ CollocatedRequestHandler::invokeBatchRequests(BatchOutgoing* out)
}
AsyncStatus
-CollocatedRequestHandler::invokeAsyncBatchRequests(BatchOutgoingAsync* outAsync)
+CollocatedRequestHandler::invokeAsyncBatchRequests(OutgoingAsyncBase* outAsync)
{
Int invokeNum;
{
@@ -473,10 +482,12 @@ CollocatedRequestHandler::invokeAsyncBatchRequests(BatchOutgoingAsync* outAsync)
if(_reference->getInvocationTimeout() > 0)
{
_sendAsyncRequests.insert(make_pair(outAsync, 0));
+
+ outAsync->cancelable(this);
}
assert(!_batchStream.b.empty());
- _batchStream.swap(*outAsync->__getOs());
+ _batchStream.swap(*outAsync->getOs());
//
// Reset the batch stream.
@@ -488,14 +499,14 @@ CollocatedRequestHandler::invokeAsyncBatchRequests(BatchOutgoingAsync* outAsync)
}
}
- outAsync->__attachCollocatedObserver(_adapter, 0);
+ outAsync->attachCollocatedObserver(_adapter, 0);
if(invokeNum > 0)
{
- _adapter->getThreadPool()->dispatch(new InvokeAllAsync(outAsync, outAsync->__getOs(), this, 0, invokeNum,true));
+ _adapter->getThreadPool()->dispatch(new InvokeAllAsync(outAsync, outAsync->getOs(), this, 0, invokeNum,true));
return AsyncStatusQueued;
}
- else if(outAsync->__sent())
+ else if(outAsync->sent())
{
return static_cast<AsyncStatus>(AsyncStatusSent | AsyncStatusInvokeSentCallback);
}
@@ -512,7 +523,7 @@ CollocatedRequestHandler::sendResponse(Int requestId, BasicStream* os, Byte)
{
Lock sync(*this);
assert(_response);
-
+
os->i = os->b.begin() + sizeof(replyHdr) + 4;
if(_traceLevels->protocol >= 1)
@@ -524,7 +535,7 @@ CollocatedRequestHandler::sendResponse(Int requestId, BasicStream* os, Byte)
map<int, Outgoing*>::iterator p = _requests.find(requestId);
if(p != _requests.end())
{
- p->second->finished(*os);
+ p->second->completed(*os);
_requests.erase(p);
}
else
@@ -532,17 +543,21 @@ CollocatedRequestHandler::sendResponse(Int requestId, BasicStream* os, Byte)
map<int, OutgoingAsyncPtr>::iterator q = _asyncRequests.find(requestId);
if(q != _asyncRequests.end())
{
- os->swap(*q->second->__getIs());
- outAsync = q->second;
+ os->swap(*q->second->getIs());
+ if(q->second->completed())
+ {
+ outAsync = q->second;
+ }
_asyncRequests.erase(q);
}
}
}
- if(outAsync && outAsync->__finished())
+ if(outAsync)
{
- outAsync->__invokeCompleted();
+ outAsync->invokeCompleted();
}
+
_adapter->decDirectCount();
}
@@ -563,12 +578,7 @@ CollocatedRequestHandler::systemException(Int requestId, const SystemException&
void
CollocatedRequestHandler::invokeException(Int requestId, const LocalException& ex, int invokeNum)
{
- if(requestId > 0)
- {
- Lock sync(*this);
- _requests.erase(requestId);
- _asyncRequests.erase(requestId);
- }
+ handleException(requestId, ex);
_adapter->decDirectCount();
}
@@ -585,7 +595,7 @@ CollocatedRequestHandler::waitForConnection()
}
bool
-CollocatedRequestHandler::sent(OutgoingMessageCallback* out)
+CollocatedRequestHandler::sent(OutgoingBase* out)
{
if(_reference->getInvocationTimeout() > 0)
{
@@ -600,7 +610,7 @@ CollocatedRequestHandler::sent(OutgoingMessageCallback* out)
}
bool
-CollocatedRequestHandler::sentAsync(OutgoingAsyncMessageCallback* outAsync)
+CollocatedRequestHandler::sentAsync(OutgoingAsyncBase* outAsync)
{
if(_reference->getInvocationTimeout() > 0)
{
@@ -610,9 +620,9 @@ CollocatedRequestHandler::sentAsync(OutgoingAsyncMessageCallback* outAsync)
return false; // The request timed-out.
}
}
- if(outAsync->__sent())
+ if(outAsync->sent())
{
- outAsync->__invokeSent();
+ outAsync->invokeSent();
}
return true;
}
@@ -684,7 +694,7 @@ CollocatedRequestHandler::handleException(int requestId, const Exception& ex)
map<int, Outgoing*>::iterator p = _requests.find(requestId);
if(p != _requests.end())
{
- p->second->finished(ex);
+ p->second->completed(ex);
_requests.erase(p);
}
else
@@ -692,13 +702,17 @@ CollocatedRequestHandler::handleException(int requestId, const Exception& ex)
map<int, OutgoingAsyncPtr>::iterator q = _asyncRequests.find(requestId);
if(q != _asyncRequests.end())
{
- outAsync = q->second;
+ if(q->second->completed(ex))
+ {
+ outAsync = q->second;
+ }
_asyncRequests.erase(q);
}
}
}
+
if(outAsync)
{
- outAsync->__finished(ex);
+ outAsync->invokeCompleted();
}
}
diff --git a/cpp/src/Ice/CollocatedRequestHandler.h b/cpp/src/Ice/CollocatedRequestHandler.h
index a3ac1387045..3930c12ce1c 100644
--- a/cpp/src/Ice/CollocatedRequestHandler.h
+++ b/cpp/src/Ice/CollocatedRequestHandler.h
@@ -31,10 +31,10 @@ typedef IceUtil::Handle<ObjectAdapterI> ObjectAdapterIPtr;
namespace IceInternal
{
+class OutgoingBase;
class Outgoing;
-class BatchOutgoing;
+class OutgoingAsyncBase;
class OutgoingAsync;
-class BatchOutgoingAsync;
class CollocatedRequestHandler : public RequestHandler, public ResponseHandler, private IceUtil::Monitor<IceUtil::Mutex>
{
@@ -50,11 +50,11 @@ public:
virtual void finishBatchRequest(BasicStream*);
virtual void abortBatchRequest();
- virtual bool sendRequest(OutgoingMessageCallback*);
- virtual AsyncStatus sendAsyncRequest(const OutgoingAsyncMessageCallbackPtr&);
+ virtual bool sendRequest(OutgoingBase*);
+ virtual AsyncStatus sendAsyncRequest(const OutgoingAsyncBasePtr&);
- virtual void requestTimedOut(OutgoingMessageCallback*);
- virtual void asyncRequestTimedOut(const OutgoingAsyncMessageCallbackPtr&);
+ virtual void requestCanceled(OutgoingBase*, const Ice::LocalException&);
+ virtual void asyncRequestCanceled(const OutgoingAsyncBasePtr&, const Ice::LocalException&);
virtual void sendResponse(Ice::Int, BasicStream*, Ice::Byte);
virtual void sendNoResponse();
@@ -68,11 +68,11 @@ public:
void invokeRequest(Outgoing*);
AsyncStatus invokeAsyncRequest(OutgoingAsync*);
- void invokeBatchRequests(BatchOutgoing*);
- AsyncStatus invokeAsyncBatchRequests(BatchOutgoingAsync*);
+ void invokeBatchRequests(OutgoingBase*);
+ AsyncStatus invokeAsyncBatchRequests(OutgoingAsyncBase*);
- bool sent(OutgoingMessageCallback*);
- bool sentAsync(OutgoingAsyncMessageCallback*);
+ bool sent(OutgoingBase*);
+ bool sentAsync(OutgoingAsyncBase*);
void invokeAll(BasicStream*, Ice::Int, Ice::Int, bool);
@@ -88,8 +88,8 @@ private:
int _requestId;
- std::map<OutgoingMessageCallback*, Ice::Int> _sendRequests;
- std::map<OutgoingAsyncMessageCallbackPtr, Ice::Int> _sendAsyncRequests;
+ std::map<OutgoingBase*, Ice::Int> _sendRequests;
+ std::map<OutgoingAsyncBasePtr, Ice::Int> _sendAsyncRequests;
std::map<Ice::Int, Outgoing*> _requests;
std::map<Ice::Int, OutgoingAsyncPtr> _asyncRequests;
diff --git a/cpp/src/Ice/CommunicatorI.cpp b/cpp/src/Ice/CommunicatorI.cpp
index 9b7ce8b8cd8..a7c2aee35d2 100644
--- a/cpp/src/Ice/CommunicatorI.cpp
+++ b/cpp/src/Ice/CommunicatorI.cpp
@@ -21,6 +21,7 @@
#include <Ice/DefaultsAndOverrides.h>
#include <Ice/TraceLevels.h>
#include <Ice/Router.h>
+#include <Ice/OutgoingAsync.h>
#include <IceUtil/Mutex.h>
#include <IceUtil/MutexPtrLock.h>
#include <IceUtil/UUID.h>
@@ -198,8 +199,7 @@ Ice::CommunicatorI::getPluginManager() const
void
Ice::CommunicatorI::flushBatchRequests()
{
- AsyncResultPtr r = begin_flushBatchRequests();
- end_flushBatchRequests(r);
+ end_flushBatchRequests(begin_flushBatchRequests());
}
AsyncResultPtr
@@ -223,9 +223,8 @@ Ice::CommunicatorI::begin_flushBatchRequests(const Callback_Communicator_flushBa
#ifdef ICE_CPP11
AsyncResultPtr
-Ice::CommunicatorI::begin_flushBatchRequests(
- const IceInternal::Function<void (const Exception&)>& exception,
- const IceInternal::Function<void (bool)>& sent)
+Ice::CommunicatorI::begin_flushBatchRequests(const IceInternal::Function<void (const Exception&)>& exception,
+ const IceInternal::Function<void (bool)>& sent)
{
class Cpp11CB : public IceInternal::Cpp11FnCallbackNC
{
@@ -268,8 +267,7 @@ const ::std::string __flushBatchRequests_name = "flushBatchRequests";
}
AsyncResultPtr
-Ice::CommunicatorI::__begin_flushBatchRequests(const IceInternal::CallbackBasePtr& cb,
- const LocalObjectPtr& cookie)
+Ice::CommunicatorI::__begin_flushBatchRequests(const IceInternal::CallbackBasePtr& cb, const LocalObjectPtr& cookie)
{
OutgoingConnectionFactoryPtr connectionFactory = _instance->outgoingConnectionFactory();
ObjectAdapterFactoryPtr adapterFactory = _instance->objectAdapterFactory();
@@ -278,8 +276,11 @@ Ice::CommunicatorI::__begin_flushBatchRequests(const IceInternal::CallbackBasePt
// This callback object receives the results of all invocations
// of Connection::begin_flushBatchRequests.
//
- CommunicatorBatchOutgoingAsyncPtr result =
- new CommunicatorBatchOutgoingAsync(this, _instance, __flushBatchRequests_name, cb, cookie);
+ CommunicatorFlushBatchPtr result = new CommunicatorFlushBatch(this,
+ _instance,
+ __flushBatchRequests_name,
+ cb,
+ cookie);
connectionFactory->flushAsyncBatchRequests(result);
adapterFactory->flushAsyncBatchRequests(result);
diff --git a/cpp/src/Ice/ConnectRequestHandler.cpp b/cpp/src/Ice/ConnectRequestHandler.cpp
index 5a9a84c83b1..7d7f4a9291c 100644
--- a/cpp/src/Ice/ConnectRequestHandler.cpp
+++ b/cpp/src/Ice/ConnectRequestHandler.cpp
@@ -49,7 +49,7 @@ class FlushSentRequests : public DispatchWorkItem
{
public:
- FlushSentRequests(const Ice::ConnectionPtr& connection, const vector<OutgoingAsyncMessageCallbackPtr>& callbacks) :
+ FlushSentRequests(const Ice::ConnectionPtr& connection, const vector<OutgoingAsyncBasePtr>& callbacks) :
DispatchWorkItem(connection), _callbacks(callbacks)
{
}
@@ -57,15 +57,15 @@ public:
virtual void
run()
{
- for(vector<OutgoingAsyncMessageCallbackPtr>::const_iterator p = _callbacks.begin(); p != _callbacks.end(); ++p)
+ for(vector<OutgoingAsyncBasePtr>::const_iterator p = _callbacks.begin(); p != _callbacks.end(); ++p)
{
- (*p)->__invokeSent();
+ (*p)->invokeSent();
}
}
private:
- vector<OutgoingAsyncMessageCallbackPtr> _callbacks;
+ vector<OutgoingAsyncBasePtr> _callbacks;
};
};
@@ -202,7 +202,7 @@ ConnectRequestHandler::abortBatchRequest()
}
bool
-ConnectRequestHandler::sendRequest(OutgoingMessageCallback* out)
+ConnectRequestHandler::sendRequest(OutgoingBase* out)
{
{
Lock sync(*this);
@@ -225,7 +225,7 @@ ConnectRequestHandler::sendRequest(OutgoingMessageCallback* out)
}
AsyncStatus
-ConnectRequestHandler::sendAsyncRequest(const OutgoingAsyncMessageCallbackPtr& out)
+ConnectRequestHandler::sendAsyncRequest(const OutgoingAsyncBasePtr& out)
{
{
Lock sync(*this);
@@ -236,6 +236,7 @@ ConnectRequestHandler::sendAsyncRequest(const OutgoingAsyncMessageCallbackPtr& o
Request req;
req.outAsync = out;
_requests.push_back(req);
+ out->cancelable(this);
return AsyncStatusQueued;
}
}
@@ -244,11 +245,11 @@ ConnectRequestHandler::sendAsyncRequest(const OutgoingAsyncMessageCallbackPtr& o
throw RetryException(ex);
}
}
- return out->__send(_connection, _compress, _response);
+ return out->send(_connection, _compress, _response);
}
void
-ConnectRequestHandler::requestTimedOut(OutgoingMessageCallback* out)
+ConnectRequestHandler::requestCanceled(OutgoingBase* out, const Ice::LocalException& ex)
{
{
Lock sync(*this);
@@ -263,8 +264,7 @@ ConnectRequestHandler::requestTimedOut(OutgoingMessageCallback* out)
{
if(p->out == out)
{
- Ice::InvocationTimeoutException ex(__FILE__, __LINE__);
- out->finished(ex);
+ out->completed(ex);
_requests.erase(p);
return;
}
@@ -272,11 +272,11 @@ ConnectRequestHandler::requestTimedOut(OutgoingMessageCallback* out)
assert(false); // The request has to be queued if it timed out and we're not initialized yet.
}
}
- _connection->requestTimedOut(out);
+ _connection->requestCanceled(out, ex);
}
void
-ConnectRequestHandler::asyncRequestTimedOut(const OutgoingAsyncMessageCallbackPtr& outAsync)
+ConnectRequestHandler::asyncRequestCanceled(const OutgoingAsyncBasePtr& outAsync, const Ice::LocalException& ex)
{
{
Lock sync(*this);
@@ -292,14 +292,16 @@ ConnectRequestHandler::asyncRequestTimedOut(const OutgoingAsyncMessageCallbackPt
if(p->outAsync.get() == outAsync.get())
{
_requests.erase(p);
- outAsync->__dispatchInvocationTimeout(_reference->getInstance()->clientThreadPool(), 0);
+ 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->asyncRequestTimedOut(outAsync);
+ _connection->asyncRequestCanceled(outAsync, ex);
}
Ice::ConnectionIPtr
@@ -451,7 +453,7 @@ ConnectRequestHandler::flushRequests()
_flushing = true;
}
- vector<OutgoingAsyncMessageCallbackPtr> sentCallbacks;
+ vector<OutgoingAsyncBasePtr> sentCallbacks;
try
{
while(!_requests.empty()) // _requests is immutable when _flushing = true
@@ -463,7 +465,7 @@ ConnectRequestHandler::flushRequests()
}
else if(req.outAsync)
{
- if(req.outAsync->__send(_connection, _compress, _response) & AsyncStatusInvokeSentCallback)
+ if(req.outAsync->send(_connection, _compress, _response) & AsyncStatusInvokeSentCallback)
{
sentCallbacks.push_back(req.outAsync);
}
@@ -551,11 +553,14 @@ ConnectRequestHandler::flushRequestsWithException()
{
if(p->out)
{
- p->out->finished(*_exception.get());
+ p->out->completed(*_exception.get());
}
else if(p->outAsync)
{
- p->outAsync->__finished(*_exception.get());
+ if(p->outAsync->completed(*_exception.get()))
+ {
+ p->outAsync->invokeCompleted();
+ }
}
else
{
diff --git a/cpp/src/Ice/ConnectRequestHandler.h b/cpp/src/Ice/ConnectRequestHandler.h
index 095edda6123..c5bc6602766 100644
--- a/cpp/src/Ice/ConnectRequestHandler.h
+++ b/cpp/src/Ice/ConnectRequestHandler.h
@@ -42,11 +42,11 @@ public:
virtual void finishBatchRequest(BasicStream*);
virtual void abortBatchRequest();
- virtual bool sendRequest(OutgoingMessageCallback*);
- virtual AsyncStatus sendAsyncRequest(const OutgoingAsyncMessageCallbackPtr&);
+ virtual bool sendRequest(OutgoingBase*);
+ virtual AsyncStatus sendAsyncRequest(const OutgoingAsyncBasePtr&);
- virtual void requestTimedOut(OutgoingMessageCallback*);
- virtual void asyncRequestTimedOut(const OutgoingAsyncMessageCallbackPtr&);
+ virtual void requestCanceled(OutgoingBase*, const Ice::LocalException&);
+ virtual void asyncRequestCanceled(const OutgoingAsyncBasePtr&, const Ice::LocalException&);
virtual Ice::ConnectionIPtr getConnection();
virtual Ice::ConnectionIPtr waitForConnection();
@@ -69,8 +69,8 @@ private:
{
}
- OutgoingMessageCallback* out;
- OutgoingAsyncMessageCallbackPtr outAsync;
+ OutgoingBase* out;
+ OutgoingAsyncBasePtr outAsync;
BasicStream* os;
};
diff --git a/cpp/src/Ice/ConnectionFactory.cpp b/cpp/src/Ice/ConnectionFactory.cpp
index f859ac3fa58..f1fc0380727 100644
--- a/cpp/src/Ice/ConnectionFactory.cpp
+++ b/cpp/src/Ice/ConnectionFactory.cpp
@@ -24,6 +24,7 @@
#include <Ice/RouterInfo.h>
#include <Ice/LocalException.h>
#include <Ice/Functional.h>
+#include <Ice/OutgoingAsync.h>
#include <IceUtil/Random.h>
#include <iterator>
@@ -432,7 +433,7 @@ IceInternal::OutgoingConnectionFactory::removeAdapter(const ObjectAdapterPtr& ad
}
void
-IceInternal::OutgoingConnectionFactory::flushAsyncBatchRequests(const CommunicatorBatchOutgoingAsyncPtr& outAsync)
+IceInternal::OutgoingConnectionFactory::flushAsyncBatchRequests(const CommunicatorFlushBatchPtr& outAsync)
{
list<ConnectionIPtr> c;
@@ -1357,7 +1358,7 @@ IceInternal::IncomingConnectionFactory::connections() const
}
void
-IceInternal::IncomingConnectionFactory::flushAsyncBatchRequests(const CommunicatorBatchOutgoingAsyncPtr& outAsync)
+IceInternal::IncomingConnectionFactory::flushAsyncBatchRequests(const CommunicatorFlushBatchPtr& outAsync)
{
list<ConnectionIPtr> c = connections(); // connections() is synchronized, so no need to synchronize here.
diff --git a/cpp/src/Ice/ConnectionFactory.h b/cpp/src/Ice/ConnectionFactory.h
index bd0bbe30804..92603a55b04 100644
--- a/cpp/src/Ice/ConnectionFactory.h
+++ b/cpp/src/Ice/ConnectionFactory.h
@@ -66,7 +66,7 @@ public:
const CreateConnectionCallbackPtr&);
void setRouterInfo(const RouterInfoPtr&);
void removeAdapter(const Ice::ObjectAdapterPtr&);
- void flushAsyncBatchRequests(const CommunicatorBatchOutgoingAsyncPtr&);
+ void flushAsyncBatchRequests(const CommunicatorFlushBatchPtr&);
private:
@@ -178,7 +178,7 @@ public:
EndpointIPtr endpoint() const;
std::list<Ice::ConnectionIPtr> connections() const;
- void flushAsyncBatchRequests(const CommunicatorBatchOutgoingAsyncPtr&);
+ void flushAsyncBatchRequests(const CommunicatorFlushBatchPtr&);
//
// Operations from EventHandler
diff --git a/cpp/src/Ice/ConnectionI.cpp b/cpp/src/Ice/ConnectionI.cpp
index 1bdbeb12448..92dc4a1693d 100644
--- a/cpp/src/Ice/ConnectionI.cpp
+++ b/cpp/src/Ice/ConnectionI.cpp
@@ -242,7 +242,7 @@ Ice::ConnectionI::OutgoingMessage::adopt(BasicStream* str)
}
void
-Ice::ConnectionI::OutgoingMessage::timedOut(bool adoptStream)
+Ice::ConnectionI::OutgoingMessage::canceled(bool adoptStream)
{
assert((out || outAsync)); // Only requests can timeout.
out = 0;
@@ -253,7 +253,7 @@ Ice::ConnectionI::OutgoingMessage::timedOut(bool adoptStream)
}
else
{
- assert(!adopted && !stream);
+ assert(!adopted);
}
}
@@ -273,25 +273,28 @@ Ice::ConnectionI::OutgoingMessage::sent()
else if(outAsync)
{
#if defined(ICE_USE_IOCP) || defined(ICE_OS_WINRT)
- invokeSent = outAsync->__sent();
+ invokeSent = outAsync->sent();
return invokeSent || receivedReply;
#else
- return outAsync->__sent();
+ return outAsync->sent();
#endif
}
return false;
}
void
-Ice::ConnectionI::OutgoingMessage::finished(const Ice::LocalException& ex)
+Ice::ConnectionI::OutgoingMessage::completed(const Ice::LocalException& ex)
{
if(out)
{
- out->finished(ex);
+ out->completed(ex);
}
else if(outAsync)
{
- outAsync->__finished(ex);
+ if(outAsync->completed(ex))
+ {
+ outAsync->invokeCompleted();
+ }
}
if(adopted)
@@ -651,8 +654,7 @@ Ice::ConnectionI::sendRequest(Outgoing* out, bool compress, bool response)
#endif
}
- out->attachRemoteObserver(initConnectionInfo(), _endpoint, requestId,
- static_cast<Int>(os->b.size() - headerSize - 4));
+ out->attachRemoteObserver(initConnectionInfo(), _endpoint, requestId);
//
// Send the message. If it can't be sent without blocking the message is added
@@ -685,7 +687,7 @@ Ice::ConnectionI::sendRequest(Outgoing* out, bool compress, bool response)
AsyncStatus
Ice::ConnectionI::sendAsyncRequest(const OutgoingAsyncPtr& out, bool compress, bool response)
{
- BasicStream* os = out->__getOs();
+ BasicStream* os = out->getOs();
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
if(_exception.get())
@@ -731,8 +733,7 @@ Ice::ConnectionI::sendAsyncRequest(const OutgoingAsyncPtr& out, bool compress, b
#endif
}
- out->__attachRemoteObserver(initConnectionInfo(), _endpoint, requestId,
- static_cast<Int>(os->b.size() - headerSize - 4));
+ out->attachRemoteObserver(initConnectionInfo(), _endpoint, requestId);
AsyncStatus status = AsyncStatusQueued;
try
@@ -747,6 +748,11 @@ Ice::ConnectionI::sendAsyncRequest(const OutgoingAsyncPtr& out, bool compress, b
_exception->ice_throw();
}
+ if(response || status & AsyncStatusQueued)
+ {
+ out->cancelable(this); // Notify the request that it's cancelable
+ }
+
if(response)
{
//
@@ -961,7 +967,7 @@ Ice::ConnectionI::abortBatchRequest()
void
Ice::ConnectionI::flushBatchRequests()
{
- BatchOutgoing out(this, _instance.get(), __flushBatchRequests_name);
+ FlushBatch out(this, _instance.get(), __flushBatchRequests_name);
out.invoke();
}
@@ -986,9 +992,8 @@ Ice::ConnectionI::begin_flushBatchRequests(const Callback_Connection_flushBatchR
#ifdef ICE_CPP11
AsyncResultPtr
-Ice::ConnectionI::begin_flushBatchRequests(
- const IceInternal::Function<void (const Exception&)>& exception,
- const IceInternal::Function<void (bool)>& sent)
+Ice::ConnectionI::begin_flushBatchRequests(const IceInternal::Function<void (const Exception&)>& exception,
+ const IceInternal::Function<void (bool)>& sent)
{
class Cpp11CB : public IceInternal::Cpp11FnCallbackNC
@@ -1026,16 +1031,13 @@ Ice::ConnectionI::begin_flushBatchRequests(
AsyncResultPtr
Ice::ConnectionI::__begin_flushBatchRequests(const CallbackBasePtr& cb, const LocalObjectPtr& cookie)
{
- ConnectionBatchOutgoingAsyncPtr result =
- new ConnectionBatchOutgoingAsync(this, _communicator, _instance, __flushBatchRequests_name, cb, cookie);
- try
- {
- result->__invoke();
- }
- catch(const LocalException& __ex)
- {
- result->__invokeExceptionAsync(__ex);
- }
+ ConnectionFlushBatchPtr result = new ConnectionFlushBatch(this,
+ _communicator,
+ _instance,
+ __flushBatchRequests_name,
+ cb,
+ cookie);
+ result->invoke();
return result;
}
@@ -1047,7 +1049,7 @@ Ice::ConnectionI::end_flushBatchRequests(const AsyncResultPtr& r)
}
bool
-Ice::ConnectionI::flushBatchRequests(BatchOutgoing* out)
+Ice::ConnectionI::flushBatchRequests(OutgoingBase* out)
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
while(_batchStreamInUse && !_exception.get())
@@ -1075,12 +1077,10 @@ Ice::ConnectionI::flushBatchRequests(BatchOutgoing* out)
#else
copy(p, p + sizeof(Int), _batchStream.b.begin() + headerSize);
#endif
-
- out->attachRemoteObserver(initConnectionInfo(), _endpoint,
- static_cast<Int>(_batchStream.b.size() - headerSize - 4));
-
_batchStream.swap(*out->os());
+ out->attachRemoteObserver(initConnectionInfo(), _endpoint, 0);
+
//
// Send the batch stream.
//
@@ -1109,7 +1109,7 @@ Ice::ConnectionI::flushBatchRequests(BatchOutgoing* out)
}
AsyncStatus
-Ice::ConnectionI::flushAsyncBatchRequests(const BatchOutgoingAsyncPtr& outAsync)
+Ice::ConnectionI::flushAsyncBatchRequests(const OutgoingAsyncBasePtr& outAsync)
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
while(_batchStreamInUse && !_exception.get())
@@ -1125,7 +1125,7 @@ Ice::ConnectionI::flushAsyncBatchRequests(const BatchOutgoingAsyncPtr& outAsync)
if(_batchRequestNum == 0)
{
AsyncStatus status = AsyncStatusSent;
- if(outAsync->__sent())
+ if(outAsync->sent())
{
status = static_cast<AsyncStatus>(status | AsyncStatusInvokeSentCallback);
}
@@ -1141,11 +1141,9 @@ Ice::ConnectionI::flushAsyncBatchRequests(const BatchOutgoingAsyncPtr& outAsync)
#else
copy(p, p + sizeof(Int), _batchStream.b.begin() + headerSize);
#endif
+ _batchStream.swap(*outAsync->getOs());
- outAsync->__attachRemoteObserver(initConnectionInfo(), _endpoint, 0,
- static_cast<Int>(_batchStream.b.size() - headerSize - 4));
-
- _batchStream.swap(*outAsync->__getOs());
+ outAsync->attachRemoteObserver(initConnectionInfo(), _endpoint, 0);
//
// Send the batch stream.
@@ -1153,7 +1151,7 @@ Ice::ConnectionI::flushAsyncBatchRequests(const BatchOutgoingAsyncPtr& outAsync)
AsyncStatus status = AsyncStatusQueued;
try
{
- OutgoingMessage message(outAsync, outAsync->__getOs(), _batchRequestCompress, 0);
+ OutgoingMessage message(outAsync, outAsync->getOs(), _batchRequestCompress, 0);
status = sendMessage(message);
}
catch(const Ice::LocalException& ex)
@@ -1163,6 +1161,11 @@ Ice::ConnectionI::flushAsyncBatchRequests(const BatchOutgoingAsyncPtr& outAsync)
_exception->ice_throw();
}
+ if(status & AsyncStatusQueued)
+ {
+ outAsync->cancelable(this); // Notify the request that it's cancelable.
+ }
+
//
// Reset the batch stream.
//
@@ -1276,9 +1279,14 @@ Ice::ConnectionI::getACM()
}
void
-Ice::ConnectionI::requestTimedOut(OutgoingMessageCallback* out)
+Ice::ConnectionI::requestCanceled(OutgoingBase* out, const Ice::LocalException& ex)
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
+ if(_state >= StateClosed)
+ {
+ return; // The request has already been or will be shortly notified of the failure.
+ }
+
for(deque<OutgoingMessage>::iterator o = _sendStreams.begin(); o != _sendStreams.end(); ++o)
{
if(o->out == out)
@@ -1302,16 +1310,15 @@ Ice::ConnectionI::requestTimedOut(OutgoingMessageCallback* out)
//
if(o == _sendStreams.begin())
{
- o->timedOut(true); // true = adopt the stream.
+ o->canceled(true); // true = adopt the stream.
}
else
{
- o->timedOut(false);
+ o->canceled(false);
_sendStreams.erase(o);
}
- InvocationTimeoutException ex(__FILE__, __LINE__);
- out->finished(ex);
+ out->completed(ex);
return;
}
}
@@ -1321,8 +1328,7 @@ Ice::ConnectionI::requestTimedOut(OutgoingMessageCallback* out)
{
if(_requestsHint != _requests.end() && _requestsHint->second == o)
{
- InvocationTimeoutException ex(__FILE__, __LINE__);
- o->finished(ex);
+ o->completed(ex);
_requests.erase(_requestsHint);
_requestsHint = _requests.end();
}
@@ -1332,8 +1338,7 @@ Ice::ConnectionI::requestTimedOut(OutgoingMessageCallback* out)
{
if(p->second == o)
{
- InvocationTimeoutException ex(__FILE__, __LINE__);
- o->finished(ex);
+ o->completed(ex);
assert(p != _requestsHint);
_requests.erase(p);
return; // We're done.
@@ -1344,10 +1349,18 @@ Ice::ConnectionI::requestTimedOut(OutgoingMessageCallback* out)
}
void
-Ice::ConnectionI::asyncRequestTimedOut(const OutgoingAsyncMessageCallbackPtr& outAsync)
+Ice::ConnectionI::asyncRequestCanceled(const OutgoingAsyncBasePtr& outAsync, const LocalException& ex)
{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
+ //
+ // NOTE: This isn't called from a thread pool thread.
+ //
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this);
+ if(_state >= StateClosed)
+ {
+ return; // The request has already been or will be shortly notified of the failure.
+ }
+
for(deque<OutgoingMessage>::iterator o = _sendStreams.begin(); o != _sendStreams.end(); ++o)
{
if(o->outAsync.get() == outAsync.get())
@@ -1365,25 +1378,29 @@ Ice::ConnectionI::asyncRequestTimedOut(const OutgoingAsyncMessageCallbackPtr& ou
_asyncRequests.erase(o->requestId);
}
}
-
+
//
// If the request is being sent, don't remove it from the send streams,
// it will be removed once the sending is finished.
//
if(o == _sendStreams.begin())
{
- o->timedOut(true); // true = adopt the stream
+ o->canceled(true); // true = adopt the stream
}
else
{
- o->timedOut(false);
+ o->canceled(false);
_sendStreams.erase(o);
}
- outAsync->__dispatchInvocationTimeout(_threadPool, this);
- return; // We're done
+ if(outAsync->completed(ex))
+ {
+ sync.release();
+ outAsync->invokeCompleted();
+ }
+ return;
}
}
-
+
OutgoingAsyncPtr o = OutgoingAsyncPtr::dynamicCast(outAsync);
if(o)
{
@@ -1393,19 +1410,25 @@ Ice::ConnectionI::asyncRequestTimedOut(const OutgoingAsyncMessageCallbackPtr& ou
{
_asyncRequests.erase(_asyncRequestsHint);
_asyncRequestsHint = _asyncRequests.end();
- outAsync->__dispatchInvocationTimeout(_threadPool, this);
- return; // We're done
+ if(outAsync->completed(ex))
+ {
+ outAsync->invokeCompletedAsync();
+ }
+ return;
}
}
-
+
for(map<Int, OutgoingAsyncPtr>::iterator p = _asyncRequests.begin(); p != _asyncRequests.end(); ++p)
{
if(p->second.get() == o.get())
{
assert(p != _asyncRequestsHint);
_asyncRequests.erase(p);
- outAsync->__dispatchInvocationTimeout(_threadPool, this);
- return; // We're done
+ if(outAsync->completed(ex))
+ {
+ outAsync->invokeCompletedAsync();
+ }
+ return;
}
}
}
@@ -1972,18 +1995,18 @@ ConnectionI::dispatch(const StartCallbackPtr& startCB, const vector<OutgoingMess
#if defined(ICE_USE_IOCP) || defined(ICE_OS_WINRT)
if(p->invokeSent)
{
- p->outAsync->__invokeSent();
+ p->outAsync->invokeSent();
}
if(p->receivedReply)
{
OutgoingAsyncPtr outAsync = OutgoingAsyncPtr::dynamicCast(p->outAsync);
- if(outAsync->__finished())
+ if(outAsync->completed())
{
- outAsync->__invokeCompleted();
+ outAsync->invokeCompleted();
}
}
#else
- p->outAsync->__invokeSent();
+ p->outAsync->invokeSent();
#endif
}
++dispatchedCount;
@@ -1995,7 +2018,7 @@ ConnectionI::dispatch(const StartCallbackPtr& startCB, const vector<OutgoingMess
//
if(outAsync)
{
- outAsync->__invokeCompleted();
+ outAsync->invokeCompleted();
++dispatchedCount;
}
@@ -2147,14 +2170,14 @@ Ice::ConnectionI::finish()
{
if(message->sent() && message->invokeSent)
{
- message->outAsync->__invokeSent();
+ message->outAsync->invokeSent();
}
if(message->receivedReply)
{
OutgoingAsyncPtr outAsync = OutgoingAsyncPtr::dynamicCast(message->outAsync);
- if(outAsync->__finished())
+ if(outAsync->completed())
{
- outAsync->__invokeCompleted();
+ outAsync->invokeCompleted();
}
}
_sendStreams.pop_front();
@@ -2164,7 +2187,7 @@ Ice::ConnectionI::finish()
for(deque<OutgoingMessage>::iterator o = _sendStreams.begin(); o != _sendStreams.end(); ++o)
{
- o->finished(*_exception.get());
+ o->completed(*_exception.get());
if(o->requestId) // Make sure finished isn't called twice.
{
if(o->out)
@@ -2182,13 +2205,16 @@ Ice::ConnectionI::finish()
for(map<Int, Outgoing*>::const_iterator p = _requests.begin(); p != _requests.end(); ++p)
{
- p->second->finished(*_exception.get());
+ p->second->completed(*_exception.get());
}
_requests.clear();
for(map<Int, OutgoingAsyncPtr>::const_iterator q = _asyncRequests.begin(); q != _asyncRequests.end(); ++q)
{
- q->second->__finished(*_exception.get());
+ if(q->second->completed(*_exception.get()))
+ {
+ q->second->invokeCompleted();
+ }
}
_asyncRequests.clear();
@@ -3481,7 +3507,7 @@ Ice::ConnectionI::parseMessage(BasicStream& stream, Int& invokeNum, Int& request
if(p != _requests.end())
{
- p->second->finished(stream);
+ p->second->completed(stream);
if(p == _requestsHint)
{
@@ -3508,7 +3534,7 @@ Ice::ConnectionI::parseMessage(BasicStream& stream, Int& invokeNum, Int& request
_asyncRequests.erase(q);
}
- stream.swap(*outAsync->__getIs());
+ stream.swap(*outAsync->getIs());
#if defined(ICE_USE_IOCP) || defined(ICE_OS_WINRT)
//
@@ -3522,7 +3548,7 @@ Ice::ConnectionI::parseMessage(BasicStream& stream, Int& invokeNum, Int& request
message->receivedReply = true;
outAsync = 0;
}
- else if(outAsync->__finished())
+ else if(outAsync->completed())
{
++dispatchCount;
}
@@ -3531,7 +3557,7 @@ Ice::ConnectionI::parseMessage(BasicStream& stream, Int& invokeNum, Int& request
outAsync = 0;
}
#else
- if(outAsync->__finished())
+ if(outAsync->completed())
{
++dispatchCount;
}
diff --git a/cpp/src/Ice/ConnectionI.h b/cpp/src/Ice/ConnectionI.h
index 32c474d20da..3ecec79a247 100644
--- a/cpp/src/Ice/ConnectionI.h
+++ b/cpp/src/Ice/ConnectionI.h
@@ -30,6 +30,7 @@
#include <Ice/TraceLevelsF.h>
#include <Ice/OutgoingAsyncF.h>
#include <Ice/EventHandler.h>
+#include <Ice/RequestHandler.h>
#include <Ice/ResponseHandler.h>
#include <Ice/Dispatcher.h>
#include <Ice/ObserverHelper.h>
@@ -43,8 +44,7 @@ namespace IceInternal
{
class Outgoing;
-class BatchOutgoing;
-class OutgoingMessageCallback;
+class OutgoingBase;
}
@@ -56,6 +56,7 @@ class LocalException;
class ConnectionI : public Connection,
public IceInternal::EventHandler,
public IceInternal::ResponseHandler,
+ public IceInternal::CancellationHandler,
public IceUtil::Monitor<IceUtil::Mutex>
{
class Observer : public IceInternal::ObserverHelperT<Ice::Instrumentation::ConnectionObserver>
@@ -89,7 +90,7 @@ public:
{
}
- OutgoingMessage(IceInternal::OutgoingMessageCallback* o, IceInternal::BasicStream* str, bool comp, int rid) :
+ OutgoingMessage(IceInternal::OutgoingBase* o, IceInternal::BasicStream* str, bool comp, int rid) :
stream(str), out(o), compress(comp), requestId(rid), adopted(false)
#if defined(ICE_USE_IOCP) || defined(ICE_OS_WINRT)
, isSent(false), invokeSent(false), receivedReply(false)
@@ -97,7 +98,7 @@ public:
{
}
- OutgoingMessage(const IceInternal::OutgoingAsyncMessageCallbackPtr& o, IceInternal::BasicStream* str,
+ OutgoingMessage(const IceInternal::OutgoingAsyncBasePtr& o, IceInternal::BasicStream* str,
bool comp, int rid) :
stream(str), out(0), outAsync(o), compress(comp), requestId(rid), adopted(false)
#if defined(ICE_USE_IOCP) || defined(ICE_OS_WINRT)
@@ -107,13 +108,13 @@ public:
}
void adopt(IceInternal::BasicStream*);
- void timedOut(bool);
+ void canceled(bool);
bool sent();
- void finished(const Ice::LocalException&);
+ void completed(const Ice::LocalException&);
IceInternal::BasicStream* stream;
- IceInternal::OutgoingMessageCallback* out;
- IceInternal::OutgoingAsyncMessageCallbackPtr outAsync;
+ IceInternal::OutgoingBase* out;
+ IceInternal::OutgoingAsyncBasePtr outAsync;
bool compress;
int requestId;
bool adopted;
@@ -178,8 +179,8 @@ public:
virtual void end_flushBatchRequests(const AsyncResultPtr&);
- bool flushBatchRequests(IceInternal::BatchOutgoing*);
- IceInternal::AsyncStatus flushAsyncBatchRequests(const IceInternal::BatchOutgoingAsyncPtr&);
+ bool flushBatchRequests(IceInternal::OutgoingBase*);
+ IceInternal::AsyncStatus flushAsyncBatchRequests(const IceInternal::OutgoingAsyncBasePtr&);
virtual void setCallback(const ConnectionCallbackPtr&);
virtual void setACM(const IceUtil::Optional<int>&,
@@ -187,8 +188,8 @@ public:
const IceUtil::Optional<ACMHeartbeat>&);
virtual ACM getACM();
- void requestTimedOut(IceInternal::OutgoingMessageCallback*);
- void asyncRequestTimedOut(const IceInternal::OutgoingAsyncMessageCallbackPtr&);
+ virtual void requestCanceled(IceInternal::OutgoingBase*, const LocalException&);
+ virtual void asyncRequestCanceled(const IceInternal::OutgoingAsyncBasePtr&, const LocalException&);
virtual void sendResponse(Int, IceInternal::BasicStream*, Byte);
virtual void sendNoResponse();
diff --git a/cpp/src/Ice/ConnectionRequestHandler.cpp b/cpp/src/Ice/ConnectionRequestHandler.cpp
index 43dda1b88ed..a94d3e7180a 100644
--- a/cpp/src/Ice/ConnectionRequestHandler.cpp
+++ b/cpp/src/Ice/ConnectionRequestHandler.cpp
@@ -91,27 +91,27 @@ ConnectionRequestHandler::abortBatchRequest()
}
bool
-ConnectionRequestHandler::sendRequest(OutgoingMessageCallback* out)
+ConnectionRequestHandler::sendRequest(OutgoingBase* out)
{
return out->send(_connection, _compress, _response) && !_response; // Finished if sent and no response
}
AsyncStatus
-ConnectionRequestHandler::sendAsyncRequest(const OutgoingAsyncMessageCallbackPtr& out)
+ConnectionRequestHandler::sendAsyncRequest(const OutgoingAsyncBasePtr& out)
{
- return out->__send(_connection, _compress, _response);
+ return out->send(_connection, _compress, _response);
}
void
-ConnectionRequestHandler::requestTimedOut(OutgoingMessageCallback* out)
+ConnectionRequestHandler::requestCanceled(OutgoingBase* out, const Ice::LocalException& ex)
{
- _connection->requestTimedOut(out);
+ _connection->requestCanceled(out, ex);
}
void
-ConnectionRequestHandler::asyncRequestTimedOut(const OutgoingAsyncMessageCallbackPtr& outAsync)
+ConnectionRequestHandler::asyncRequestCanceled(const OutgoingAsyncBasePtr& outAsync, const Ice::LocalException& ex)
{
- _connection->asyncRequestTimedOut(outAsync);
+ _connection->asyncRequestCanceled(outAsync, ex);
}
Ice::ConnectionIPtr
diff --git a/cpp/src/Ice/ConnectionRequestHandler.h b/cpp/src/Ice/ConnectionRequestHandler.h
index 5ab5a4c9ea7..211e8f02819 100644
--- a/cpp/src/Ice/ConnectionRequestHandler.h
+++ b/cpp/src/Ice/ConnectionRequestHandler.h
@@ -31,11 +31,11 @@ public:
virtual void finishBatchRequest(BasicStream*);
virtual void abortBatchRequest();
- virtual bool sendRequest(OutgoingMessageCallback*);
- virtual AsyncStatus sendAsyncRequest(const OutgoingAsyncMessageCallbackPtr&);
+ virtual bool sendRequest(OutgoingBase*);
+ virtual AsyncStatus sendAsyncRequest(const OutgoingAsyncBasePtr&);
- virtual void requestTimedOut(OutgoingMessageCallback*);
- virtual void asyncRequestTimedOut(const OutgoingAsyncMessageCallbackPtr&);
+ virtual void requestCanceled(OutgoingBase*, const Ice::LocalException&);
+ virtual void asyncRequestCanceled(const OutgoingAsyncBasePtr&, const Ice::LocalException&);
virtual Ice::ConnectionIPtr getConnection();
virtual Ice::ConnectionIPtr waitForConnection();
diff --git a/cpp/src/Ice/Exception.cpp b/cpp/src/Ice/Exception.cpp
index a8bb8c6f81a..e5a3aed5b9f 100644
--- a/cpp/src/Ice/Exception.cpp
+++ b/cpp/src/Ice/Exception.cpp
@@ -502,6 +502,13 @@ Ice::InvocationTimeoutException::ice_print(ostream& out) const
}
void
+Ice::InvocationCanceledException::ice_print(ostream& out) const
+{
+ Exception::ice_print(out);
+ out << ":\ninvocation canceled";
+}
+
+void
Ice::ProtocolException::ice_print(ostream& out) const
{
Exception::ice_print(out);
diff --git a/cpp/src/Ice/Makefile b/cpp/src/Ice/Makefile
index 1398ab5d07a..f44e0c977a8 100644
--- a/cpp/src/Ice/Makefile
+++ b/cpp/src/Ice/Makefile
@@ -57,6 +57,7 @@ SLICE_OBJS = BuiltinSequences.o \
OBJS = Acceptor.o \
ACM.o \
Application.o \
+ AsyncResult.o \
Base64.o \
BasicStream.o \
Buffer.o \
diff --git a/cpp/src/Ice/Makefile.mak b/cpp/src/Ice/Makefile.mak
index 75cf8c26a68..fcc4d3eb3e9 100644
--- a/cpp/src/Ice/Makefile.mak
+++ b/cpp/src/Ice/Makefile.mak
@@ -59,6 +59,7 @@ WINDOWS_OBJS = .\DLLMain.obj
OBJS = .\Acceptor.obj \
.\ACM.obj \
.\Application.obj \
+ .\AsyncResult.obj \
.\Base64.obj \
.\BasicStream.obj \
.\Buffer.obj \
diff --git a/cpp/src/Ice/ObjectAdapterFactory.cpp b/cpp/src/Ice/ObjectAdapterFactory.cpp
index ca7938bcc55..35ca16ea03e 100644
--- a/cpp/src/Ice/ObjectAdapterFactory.cpp
+++ b/cpp/src/Ice/ObjectAdapterFactory.cpp
@@ -211,7 +211,7 @@ IceInternal::ObjectAdapterFactory::removeObjectAdapter(const ObjectAdapterPtr& a
}
void
-IceInternal::ObjectAdapterFactory::flushAsyncBatchRequests(const CommunicatorBatchOutgoingAsyncPtr& outAsync) const
+IceInternal::ObjectAdapterFactory::flushAsyncBatchRequests(const CommunicatorFlushBatchPtr& outAsync) const
{
list<ObjectAdapterIPtr> adapters;
{
diff --git a/cpp/src/Ice/ObjectAdapterFactory.h b/cpp/src/Ice/ObjectAdapterFactory.h
index 7faa8ef73f4..37b3853497c 100644
--- a/cpp/src/Ice/ObjectAdapterFactory.h
+++ b/cpp/src/Ice/ObjectAdapterFactory.h
@@ -33,7 +33,7 @@ public:
::Ice::ObjectAdapterPtr createObjectAdapter(const std::string&, const Ice::RouterPrx&);
::Ice::ObjectAdapterPtr findObjectAdapter(const ::Ice::ObjectPrx&);
void removeObjectAdapter(const ::Ice::ObjectAdapterPtr&);
- void flushAsyncBatchRequests(const CommunicatorBatchOutgoingAsyncPtr&) const;
+ void flushAsyncBatchRequests(const CommunicatorFlushBatchPtr&) const;
private:
diff --git a/cpp/src/Ice/ObjectAdapterI.cpp b/cpp/src/Ice/ObjectAdapterI.cpp
index 422cdb8fd01..c9a05c091ca 100644
--- a/cpp/src/Ice/ObjectAdapterI.cpp
+++ b/cpp/src/Ice/ObjectAdapterI.cpp
@@ -743,7 +743,7 @@ Ice::ObjectAdapterI::isLocal(const ObjectPrx& proxy) const
}
void
-Ice::ObjectAdapterI::flushAsyncBatchRequests(const CommunicatorBatchOutgoingAsyncPtr& outAsync)
+Ice::ObjectAdapterI::flushAsyncBatchRequests(const CommunicatorFlushBatchPtr& outAsync)
{
vector<IncomingConnectionFactoryPtr> f;
{
diff --git a/cpp/src/Ice/ObjectAdapterI.h b/cpp/src/Ice/ObjectAdapterI.h
index 3897c0ef557..30f499d96c0 100644
--- a/cpp/src/Ice/ObjectAdapterI.h
+++ b/cpp/src/Ice/ObjectAdapterI.h
@@ -87,7 +87,7 @@ public:
bool isLocal(const ObjectPrx&) const;
- void flushAsyncBatchRequests(const IceInternal::CommunicatorBatchOutgoingAsyncPtr&);
+ void flushAsyncBatchRequests(const IceInternal::CommunicatorFlushBatchPtr&);
void updateConnectionObservers();
void updateThreadObservers();
diff --git a/cpp/src/Ice/Outgoing.cpp b/cpp/src/Ice/Outgoing.cpp
index 66509a2bedc..4815b9796fb 100644
--- a/cpp/src/Ice/Outgoing.cpp
+++ b/cpp/src/Ice/Outgoing.cpp
@@ -7,36 +7,44 @@
//
// **********************************************************************
+#include <IceUtil/DisableWarnings.h>
#include <Ice/Outgoing.h>
-#include <Ice/Object.h>
-#include <Ice/CollocatedRequestHandler.h>
#include <Ice/ConnectionI.h>
+#include <Ice/CollocatedRequestHandler.h>
#include <Ice/Reference.h>
-#include <Ice/Endpoint.h>
-#include <Ice/LocalException.h>
-#include <Ice/Protocol.h>
#include <Ice/Instance.h>
+#include <Ice/LocalException.h>
#include <Ice/ReplyStatus.h>
-#include <Ice/ProxyFactory.h>
+#include <Ice/ImplicitContextI.h>
using namespace std;
using namespace Ice;
using namespace Ice::Instrumentation;
using namespace IceInternal;
-IceInternal::Outgoing::Outgoing(IceProxy::Ice::Object* proxy, const string& operation, OperationMode mode,
- const Context* context) :
+OutgoingBase::OutgoingBase(Instance* instance, const string& operation) :
+ _os(instance, Ice::currentProtocolEncoding), _sent(false)
+{
+}
+
+Outgoing::Outgoing(IceProxy::Ice::Object* proxy, const string& operation, OperationMode mode, const Context* context) :
+ OutgoingBase(proxy->__reference()->getInstance().get(), operation),
_proxy(proxy),
_mode(mode),
- _observer(proxy, operation, context),
_state(StateUnsent),
_encoding(getCompatibleEncoding(proxy->__reference()->getEncoding())),
- _is(proxy->__reference()->getInstance().get(), Ice::currentProtocolEncoding),
- _os(proxy->__reference()->getInstance().get(), Ice::currentProtocolEncoding),
- _sent(false)
+ _is(proxy->__reference()->getInstance().get(), Ice::currentProtocolEncoding)
{
checkSupportedProtocol(getCompatibleProtocol(proxy->__reference()->getProtocol()));
+ _observer.attach(proxy, operation, context);
+
+ int invocationTimeout = _proxy->__reference()->getInvocationTimeout();
+ if(invocationTimeout > 0)
+ {
+ _invocationTimeoutDeadline = IceUtil::Time::now() + IceUtil::Time::milliSeconds(invocationTimeout);
+ }
+
switch(_proxy->__reference()->getMode())
{
case Reference::ModeTwoway:
@@ -129,7 +137,66 @@ Outgoing::~Outgoing()
}
bool
-IceInternal::Outgoing::invoke()
+Outgoing::send(const Ice::ConnectionIPtr& connection, bool compress, bool response)
+{
+ return connection->sendRequest(this, compress, response);
+}
+
+void
+Outgoing::invokeCollocated(CollocatedRequestHandler* handler)
+{
+ handler->invokeRequest(this);
+}
+
+void
+Outgoing::sent()
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ if(_proxy->__reference()->getMode() != Reference::ModeTwoway)
+ {
+ _childObserver.detach();
+ _state = StateOK;
+ }
+ _sent = true;
+ _monitor.notify();
+
+ //
+ // NOTE: At this point the stack allocated Outgoing object can be destroyed
+ // since the notify() on the monitor will release the thread waiting on the
+ // synchronous Ice call.
+ //
+}
+
+void
+Outgoing::completed(const Exception& ex)
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ //assert(_state <= StateInProgress);
+ if(_state > StateInProgress)
+ {
+ //
+ // Response was already received but message
+ // didn't get removed first from the connection
+ // send message queue so it's possible we can be
+ // notified of failures. In this case, ignore the
+ // failure and assume the outgoing has been sent.
+ //
+ assert(_state != StateFailed);
+ _sent = true;
+ _monitor.notify();
+ return;
+ }
+
+ _childObserver.failed(ex.ice_name());
+ _childObserver.detach();
+
+ _state = StateFailed;
+ _exception.reset(ex.ice_clone());
+ _monitor.notify();
+}
+
+bool
+Outgoing::invoke()
{
assert(_state == StateUnsent);
@@ -146,6 +213,11 @@ IceInternal::Outgoing::invoke()
{
try
{
+ if(_invocationTimeoutDeadline != IceUtil::Time() && _invocationTimeoutDeadline <= IceUtil::Time::now())
+ {
+ throw Ice::InvocationTimeoutException(__FILE__, __LINE__);
+ }
+
_state = StateInProgress;
_exception.reset(0);
_sent = false;
@@ -164,19 +236,18 @@ IceInternal::Outgoing::invoke()
//
// If the handler says it's not finished, we wait until we're done.
//
- int invocationTimeout = _proxy->__reference()->getInvocationTimeout();
- if(invocationTimeout > 0)
+ if(_invocationTimeoutDeadline != IceUtil::Time())
{
IceUtil::Time now = IceUtil::Time::now();
- IceUtil::Time deadline = now + IceUtil::Time::milliSeconds(invocationTimeout);
+ timedOut = now >= _invocationTimeoutDeadline;
while((_state == StateInProgress || !_sent) && _state != StateFailed && !timedOut)
{
- _monitor.timedWait(deadline - now);
+ _monitor.timedWait(_invocationTimeoutDeadline - now);
if((_state == StateInProgress || !_sent) && _state != StateFailed)
{
now = IceUtil::Time::now();
- timedOut = now >= deadline;
+ timedOut = now >= _invocationTimeoutDeadline;
}
}
}
@@ -191,15 +262,15 @@ IceInternal::Outgoing::invoke()
if(timedOut)
{
- _handler->requestTimedOut(this);
+ _handler->requestCanceled(this, InvocationTimeoutException(__FILE__, __LINE__));
//
// Wait for the exception to propagate. It's possible the request handler ignores
- // the timeout if there was a failure shortly before requestTimedOut got called.
+ // the timeout if there was a failure shortly before requestCanceled got called.
// In this case, the exception should be set on the Outgoing.
//
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- while(!_exception.get())
+ while(_state == StateInProgress)
{
_monitor.wait();
}
@@ -223,11 +294,23 @@ IceInternal::Outgoing::invoke()
{
try
{
- int interval = _proxy->__handleException(ex, _handler, _mode, _sent, cnt);
- _observer.retried(); // Invocation is being retried.
- if(interval > 0)
+ IceUtil::Time interval;
+ interval = IceUtil::Time::milliSeconds(_proxy->__handleException(ex, _handler, _mode, _sent, cnt));
+ if(interval > IceUtil::Time())
+ {
+ if(_invocationTimeoutDeadline != IceUtil::Time())
+ {
+ IceUtil::Time deadline = _invocationTimeoutDeadline - IceUtil::Time::now();
+ if(deadline < interval)
+ {
+ interval = deadline;
+ }
+ }
+ IceUtil::ThreadControl::sleep(interval);
+ }
+ if(_invocationTimeoutDeadline == IceUtil::Time() || _invocationTimeoutDeadline > IceUtil::Time::now())
{
- IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(interval));
+ _observer.retried();
}
}
catch(const Ice::Exception& ex)
@@ -243,7 +326,7 @@ IceInternal::Outgoing::invoke()
}
void
-IceInternal::Outgoing::abort(const LocalException& ex)
+Outgoing::abort(const LocalException& ex)
{
assert(_state == StateUnsent);
@@ -261,67 +344,8 @@ IceInternal::Outgoing::abort(const LocalException& ex)
ex.ice_throw();
}
-bool
-IceInternal::Outgoing::send(const Ice::ConnectionIPtr& connection, bool compress, bool response)
-{
- return connection->sendRequest(this, compress, response);
-}
-
-void
-IceInternal::Outgoing::invokeCollocated(CollocatedRequestHandler* handler)
-{
- handler->invokeRequest(this);
-}
-
-void
-IceInternal::Outgoing::sent()
-{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- if(_proxy->__reference()->getMode() != Reference::ModeTwoway)
- {
- _childObserver.detach();
- _state = StateOK;
- }
- _sent = true;
- _monitor.notify();
-
- //
- // NOTE: At this point the stack allocated Outgoing object can be destroyed
- // since the notify() on the monitor will release the thread waiting on the
- // synchronous Ice call.
- //
-}
-
void
-IceInternal::Outgoing::finished(const Exception& ex)
-{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- //assert(_state <= StateInProgress);
- if(_state > StateInProgress)
- {
- //
- // Response was already received but message
- // didn't get removed first from the connection
- // send message queue so it's possible we can be
- // notified of failures. In this case, ignore the
- // failure and assume the outgoing has been sent.
- //
- assert(_state != StateFailed);
- _sent = true;
- _monitor.notify();
- return;
- }
-
- _childObserver.failed(ex.ice_name());
- _childObserver.detach();
-
- _state = StateFailed;
- _exception.reset(ex.ice_clone());
- _monitor.notify();
-}
-
-void
-IceInternal::Outgoing::finished(BasicStream& is)
+Outgoing::completed(BasicStream& is)
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
@@ -482,7 +506,7 @@ IceInternal::Outgoing::finished(BasicStream& is)
}
void
-IceInternal::Outgoing::throwUserException()
+Outgoing::throwUserException()
{
try
{
@@ -496,27 +520,22 @@ IceInternal::Outgoing::throwUserException()
}
}
-IceInternal::BatchOutgoing::BatchOutgoing(IceProxy::Ice::Object* proxy, const string& name) :
- _proxy(proxy),
- _connection(0),
- _sent(false),
- _os(proxy->__reference()->getInstance().get(), Ice::currentProtocolEncoding),
- _observer(proxy, name, 0)
+FlushBatch::FlushBatch(IceProxy::Ice::Object* proxy, const string& operation) :
+ OutgoingBase(proxy->__reference()->getInstance().get(), operation), _proxy(proxy), _connection(0)
{
checkSupportedProtocol(proxy->__reference()->getProtocol());
+
+ _observer.attach(proxy->__reference()->getInstance().get(), operation);
}
-IceInternal::BatchOutgoing::BatchOutgoing(ConnectionI* connection, Instance* instance, const string& name) :
- _proxy(0),
- _connection(connection),
- _sent(false),
- _os(instance, Ice::currentProtocolEncoding),
- _observer(instance, name)
+FlushBatch::FlushBatch(ConnectionI* connection, Instance* instance, const string& operation) :
+ OutgoingBase(instance, operation), _proxy(0), _connection(connection)
{
+ _observer.attach(instance, operation);
}
void
-IceInternal::BatchOutgoing::invoke()
+FlushBatch::invoke()
{
assert(_proxy || _connection);
@@ -577,7 +596,8 @@ IceInternal::BatchOutgoing::invoke()
if(timedOut)
{
- handler->requestTimedOut(this);
+ Ice::InvocationTimeoutException ex(__FILE__, __LINE__);
+ handler->requestCanceled(this, ex);
//
// Wait for the exception to propagate. It's possible the request handler ignores
@@ -614,19 +634,19 @@ IceInternal::BatchOutgoing::invoke()
}
bool
-IceInternal::BatchOutgoing::send(const Ice::ConnectionIPtr& connection, bool, bool)
+FlushBatch::send(const Ice::ConnectionIPtr& connection, bool, bool)
{
return connection->flushBatchRequests(this);
}
void
-IceInternal::BatchOutgoing::invokeCollocated(CollocatedRequestHandler* handler)
+FlushBatch::invokeCollocated(CollocatedRequestHandler* handler)
{
handler->invokeBatchRequests(this);
}
void
-IceInternal::BatchOutgoing::sent()
+FlushBatch::sent()
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
_childObserver.detach();
@@ -635,14 +655,14 @@ IceInternal::BatchOutgoing::sent()
_monitor.notify();
//
- // NOTE: At this point the stack allocated BatchOutgoing object
+ // NOTE: At this point the stack allocated FlushBatch object
// can be destroyed since the notify() on the monitor will release
// the thread waiting on the synchronous Ice call.
//
}
void
-IceInternal::BatchOutgoing::finished(const Ice::Exception& ex)
+FlushBatch::completed(const Ice::Exception& ex)
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
_childObserver.failed(ex.ice_name());
diff --git a/cpp/src/Ice/OutgoingAsync.cpp b/cpp/src/Ice/OutgoingAsync.cpp
index fb57965b60f..b348b1c8cc8 100644
--- a/cpp/src/Ice/OutgoingAsync.cpp
+++ b/cpp/src/Ice/OutgoingAsync.cpp
@@ -9,18 +9,11 @@
#include <IceUtil/DisableWarnings.h>
#include <Ice/OutgoingAsync.h>
-#include <Ice/Object.h>
#include <Ice/ConnectionI.h>
#include <Ice/CollocatedRequestHandler.h>
#include <Ice/Reference.h>
#include <Ice/Instance.h>
#include <Ice/LocalException.h>
-#include <Ice/Properties.h>
-#include <Ice/LoggerUtil.h>
-#include <Ice/LocatorInfo.h>
-#include <Ice/ProxyFactory.h>
-#include <Ice/RouterInfo.h>
-#include <Ice/Protocol.h>
#include <Ice/ReplyStatus.h>
#include <Ice/ImplicitContextI.h>
#include <Ice/ThreadPool.h>
@@ -30,431 +23,289 @@ using namespace std;
using namespace Ice;
using namespace IceInternal;
-IceUtil::Shared* Ice::upCast(AsyncResult* p) { return p; }
-
-IceUtil::Shared* IceInternal::upCast(OutgoingAsyncMessageCallback* p) { return p; }
+IceUtil::Shared* IceInternal::upCast(OutgoingAsyncBase* p) { return p; }
+IceUtil::Shared* IceInternal::upCast(ProxyOutgoingAsyncBase* p) { return p; }
IceUtil::Shared* IceInternal::upCast(OutgoingAsync* p) { return p; }
-IceUtil::Shared* IceInternal::upCast(BatchOutgoingAsync* p) { return p; }
-IceUtil::Shared* IceInternal::upCast(ProxyBatchOutgoingAsync* p) { return p; }
-IceUtil::Shared* IceInternal::upCast(ConnectionBatchOutgoingAsync* p) { return p; }
-IceUtil::Shared* IceInternal::upCast(CommunicatorBatchOutgoingAsync* p) { return p; }
-IceUtil::Shared* IceInternal::upCast(GetConnectionOutgoingAsync* p) { return p; }
-
-const unsigned char Ice::AsyncResult::OK = 0x1;
-const unsigned char Ice::AsyncResult::Done = 0x2;
-const unsigned char Ice::AsyncResult::Sent = 0x4;
-const unsigned char Ice::AsyncResult::EndCalled = 0x8;
-
-namespace
-{
-
-class AsynchronousException : public DispatchWorkItem
-{
-public:
-
- AsynchronousException(const Ice::ConnectionPtr& connection, const Ice::AsyncResultPtr& result,
- const Ice::Exception& ex) :
- DispatchWorkItem(connection), _result(result), _exception(ex.ice_clone())
- {
- }
-
- virtual void
- run()
- {
- _result->__invokeException(*_exception.get());
- }
-
-private:
-
- const Ice::AsyncResultPtr _result;
- const IceUtil::UniquePtr<Ice::Exception> _exception;
-};
-
-class AsynchronousSent : public DispatchWorkItem
-{
-public:
-
- AsynchronousSent(const Ice::ConnectionPtr& connection, const Ice::AsyncResultPtr& result) :
- DispatchWorkItem(connection), _result(result)
- {
- }
-
- virtual void
- run()
- {
- _result->__invokeSent();
- }
+IceUtil::Shared* IceInternal::upCast(CommunicatorFlushBatch* p) { return p; }
-private:
-
- const Ice::AsyncResultPtr _result;
-};
-
-};
-
-Ice::AsyncResult::AsyncResult(const CommunicatorPtr& communicator,
- const IceInternal::InstancePtr& instance,
- const string& op,
- const CallbackBasePtr& del,
- const LocalObjectPtr& cookie) :
- _communicator(communicator),
- _instance(instance),
- _operation(op),
- _callback(del),
- _cookie(cookie),
- _is(instance.get(), Ice::currentProtocolEncoding),
- _os(instance.get(), Ice::currentProtocolEncoding),
- _state(0),
- _sentSynchronously(false),
- _exception(0)
+bool
+OutgoingAsyncBase::sent()
{
- if(!_callback)
- {
- throw IceUtil::IllegalArgumentException(__FILE__, __LINE__);
- }
- const_cast<CallbackBasePtr&>(_callback) = _callback->verify(_cookie);
+ return sent(true);
}
-Ice::AsyncResult::~AsyncResult()
+bool
+OutgoingAsyncBase::completed(const Exception& ex)
{
+ return finished(ex);
}
-Int
-Ice::AsyncResult::getHash() const
+OutgoingAsyncBase::OutgoingAsyncBase(const CommunicatorPtr& communicator,
+ const InstancePtr& instance,
+ const string& operation,
+ const CallbackBasePtr& delegate,
+ const LocalObjectPtr& cookie) :
+ AsyncResult(communicator, instance, operation, delegate, cookie),
+ _os(instance.get(), Ice::currentProtocolEncoding)
{
- return static_cast<Int>(reinterpret_cast<Long>(this) >> 4);
}
bool
-Ice::AsyncResult::isCompleted() const
+OutgoingAsyncBase::sent(bool done)
{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- return _state & Done;
-}
-
-void
-Ice::AsyncResult::waitForCompleted()
-{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- while(!(_state & Done))
+ if(done)
{
- _monitor.wait();
+ _childObserver.detach();
}
+ return AsyncResult::sent(done);
}
bool
-Ice::AsyncResult::isSent() const
-{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- return _state & Sent;
-}
-
-void
-Ice::AsyncResult::waitForSent()
+OutgoingAsyncBase::finished(const Exception& ex)
{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- while(!(_state & Sent) && !_exception.get())
+ if(_childObserver)
{
- _monitor.wait();
+ _childObserver.failed(ex.ice_name());
+ _childObserver.detach();
}
+ return AsyncResult::finished(ex);
}
-void
-Ice::AsyncResult::throwLocalException() const
+Ice::ObjectPrx
+ProxyOutgoingAsyncBase::getProxy() const
{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- if(_exception.get())
- {
- _exception.get()->ice_throw();
- }
+ return _proxy;
}
bool
-Ice::AsyncResult::__wait()
+ProxyOutgoingAsyncBase::sent()
{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- if(_state & EndCalled)
- {
- throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "end_ method called more than once");
- }
- _state |= EndCalled;
- while(!(_state & Done))
- {
- _monitor.wait();
- }
- if(_exception.get())
- {
- _exception.get()->ice_throw();
- }
- return _state & OK;
+ return sent(!_proxy->ice_isTwoway()); // Done if it's not a two-way proxy (no response expected).
}
-void
-Ice::AsyncResult::__throwUserException()
+bool
+ProxyOutgoingAsyncBase::completed(const Exception& exc)
{
- try
- {
- _is.startReadEncaps();
- _is.throwException();
- }
- catch(const Ice::UserException&)
+ if(_childObserver)
{
- _is.endReadEncaps();
- throw;
+ _childObserver.failed(exc.ice_name());
+ _childObserver.detach();
}
-}
-void
-Ice::AsyncResult::__invokeSent()
-{
//
- // Note: no need to change the _state here, specializations are responsible for
- // changing the state.
+ // NOTE: at this point, synchronization isn't needed, no other threads should be
+ // calling on the callback.
//
-
- if(_callback)
+ try
{
- try
- {
- AsyncResultPtr self(this);
- _callback->sent(self);
- }
- catch(const std::exception& ex)
- {
- __warning(ex);
- }
- catch(...)
- {
- __warning();
- }
+ _instance->retryQueue()->add(this, handleException(exc));
+ return false;
}
-
- if(_observer)
+ catch(const Exception& ex)
{
- Ice::ObjectPrx proxy = getProxy();
- if(!proxy || !proxy->ice_isTwoway())
- {
- _observer.detach();
- }
+ return finished(ex); // No retries, we're done
}
}
void
-Ice::AsyncResult::__invokeSentAsync()
+ProxyOutgoingAsyncBase::retry()
{
- //
- // This is called when it's not safe to call the sent callback synchronously
- // from this thread. Instead the exception callback is called asynchronously from
- // the client thread pool.
- //
- try
- {
- _instance->clientThreadPool()->dispatch(new AsynchronousSent(_cachedConnection, this));
- }
- catch(const Ice::CommunicatorDestroyedException&)
- {
- }
+ invokeImpl(false);
}
void
-Ice::AsyncResult::__invokeException(const Ice::Exception& ex)
+ProxyOutgoingAsyncBase::abort(const Ice::Exception& ex)
{
+ assert(!_childObserver);
+
+ if(finished(ex))
{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- _state |= Done;
- _os.resize(0); // Clear buffer now, instead of waiting for AsyncResult deallocation
- _exception.reset(ex.ice_clone());
- _monitor.notifyAll();
+ invokeCompletedAsync();
+ }
+ else if(dynamic_cast<const Ice::CommunicatorDestroyedException*>(&ex))
+ {
+ //
+ // If it's a communicator destroyed exception, don't swallow
+ // it but instead notify the user thread. Even if no callback
+ // was provided.
+ //
+ ex.ice_throw();
}
-
- __invokeCompleted();
}
-void
-Ice::AsyncResult::__invokeExceptionAsync(const Ice::Exception& ex)
+ProxyOutgoingAsyncBase::ProxyOutgoingAsyncBase(const ObjectPrx& prx,
+ const string& operation,
+ const CallbackBasePtr& delegate,
+ const LocalObjectPtr& cookie) :
+ OutgoingAsyncBase(prx->ice_getCommunicator(), prx->__reference()->getInstance(), operation, delegate, cookie),
+ _proxy(prx),
+ _mode(Normal),
+ _cnt(0),
+ _sent(false)
{
- //
- // This is called when it's not safe to call the exception callback synchronously
- // from this thread. Instead the exception callback is called asynchronously from
- // the client thread pool.
- //
- // CommunicatorDestroyedException is the only exception that can propagate directly
- // from this method.
- //
- _instance->clientThreadPool()->dispatch(new AsynchronousException(_cachedConnection, this, ex));
}
void
-Ice::AsyncResult::__invokeCompleted()
+ProxyOutgoingAsyncBase::invokeImpl(bool userThread)
{
- //
- // Note: no need to change the _state here, specializations are responsible for
- // changing the state.
- //
-
- if(_callback)
+ try
{
- try
+ if(userThread)
{
- AsyncResultPtr self(this);
- _callback->completed(self);
+ int invocationTimeout = _proxy->__reference()->getInvocationTimeout();
+ if(invocationTimeout > 0)
+ {
+ _instance->timer()->schedule(this, IceUtil::Time::milliSeconds(invocationTimeout));
+ }
}
- catch(const std::exception& ex)
+ else
{
- __warning(ex);
+ checkCanceled(); // Cancellation exception aren't retriable
+ _observer.retried();
}
- catch(...)
+
+ while(true)
{
- __warning();
+ try
+ {
+ _sent = false;
+ _handler = _proxy->__getRequestHandler();
+ AsyncStatus status = _handler->sendAsyncRequest(this);
+ if(status & AsyncStatusSent)
+ {
+ if(userThread)
+ {
+ _sentSynchronously = true;
+ if(status & AsyncStatusInvokeSentCallback)
+ {
+ invokeSent(); // Call the sent callback from the user thread.
+ }
+ }
+ else
+ {
+ if(status & AsyncStatusInvokeSentCallback)
+ {
+ invokeSentAsync(); // Call the sent callback from a client thread pool thread.
+ }
+ }
+ }
+ return; // We're done!
+ }
+ catch(const RetryException& ex)
+ {
+ handleRetryException(ex);
+ }
+ catch(const Exception& ex)
+ {
+ if(_childObserver)
+ {
+ _childObserver.failed(ex.ice_name());
+ _childObserver.detach();
+ }
+ int interval = handleException(ex);
+ if(interval > 0)
+ {
+ _instance->retryQueue()->add(this, interval);
+ return;
+ }
+ else
+ {
+ checkCanceled(); // Cancellation exception aren't retriable
+ _observer.retried();
+ }
+ }
}
}
-
- _observer.detach();
-}
-
-void
-Ice::AsyncResult::runTimerTask() // Implementation of TimerTask::runTimerTask()
-{
- RequestHandlerPtr handler;
+ catch(const Exception& ex)
{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- swap(handler, _timeoutRequestHandler);
- }
-
- if(handler)
- {
- handler->asyncRequestTimedOut(OutgoingAsyncMessageCallbackPtr::dynamicCast(this));
+ //
+ // If called from the user thread we re-throw, the exception
+ // will be catch by the caller and abort() will be called.
+ //
+ if(userThread)
+ {
+ throw;
+ }
+ else if(finished(ex)) // No retries, we're done
+ {
+ invokeCompletedAsync();
+ }
}
}
-
-void
-Ice::AsyncResult::__check(const AsyncResultPtr& r, const IceProxy::Ice::Object* prx, const string& operation)
+bool
+ProxyOutgoingAsyncBase::sent(bool done)
{
- __check(r, operation);
- if(r->getProxy().get() != prx)
+ _sent = true;
+ if(done)
{
- throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Proxy for call to end_" + operation +
- " does not match proxy that was used to call corresponding begin_" +
- operation + " method");
+ if(_proxy->__reference()->getInvocationTimeout() > 0)
+ {
+ _instance->timer()->cancel(this);
+ }
}
+ return OutgoingAsyncBase::sent(done);
}
-void
-Ice::AsyncResult::__check(const AsyncResultPtr& r, const Ice::Communicator* com, const string& operation)
+bool
+ProxyOutgoingAsyncBase::finished(const Exception& ex)
{
- __check(r, operation);
- if(r->getCommunicator().get() != com)
+ if(_proxy->__reference()->getInvocationTimeout() > 0)
{
- throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Communicator for call to end_" + operation +
- " does not match communicator that was used to call corresponding " +
- "begin_" + operation + " method");
+ _instance->timer()->cancel(this);
}
+ return OutgoingAsyncBase::finished(ex);
}
-void
-Ice::AsyncResult::__check(const AsyncResultPtr& r, const Ice::Connection* con, const string& operation)
+bool
+ProxyOutgoingAsyncBase::finished(bool ok)
{
- __check(r, operation);
- if(r->getConnection().get() != con)
+ if(_proxy->__reference()->getInvocationTimeout() > 0)
{
- throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Connection for call to end_" + operation +
- " does not match connection that was used to call corresponding " +
- "begin_" + operation + " method");
+ _instance->timer()->cancel(this);
}
+ return AsyncResult::finished(ok);
}
void
-Ice::AsyncResult::__check(const AsyncResultPtr& r, const string& operation)
+ProxyOutgoingAsyncBase::handleRetryException(const RetryException& exc)
{
- if(!r)
- {
- throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "AsyncResult == null");
- }
- else if(&r->_operation != &operation)
- {
- throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "Incorrect operation for end_" + operation +
- " method: " + r->_operation);
- }
+ _proxy->__setRequestHandler(_handler, 0); // Clear request handler and always retry.
}
-
-void
-Ice::AsyncResult::__warning(const std::exception& exc) const
+int
+ProxyOutgoingAsyncBase::handleException(const Exception& exc)
{
- if(_instance->initializationData().properties->getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0)
- {
- Warning out(_instance->initializationData().logger);
- const Exception* ex = dynamic_cast<const Exception*>(&exc);
- if(ex)
- {
- out << "Ice::Exception raised by AMI callback:\n" << *ex;
- }
- else
- {
- out << "std::exception raised by AMI callback:\n" << exc.what();
- }
- }
+ return _proxy->__handleException(exc, _handler, _mode, _sent, _cnt);
}
void
-Ice::AsyncResult::__warning() const
+ProxyOutgoingAsyncBase::runTimerTask()
{
- if(_instance->initializationData().properties->getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0)
+ try
{
- Warning out(_instance->initializationData().logger);
- out << "unknown exception raised by AMI callback";
+ cancel(InvocationTimeoutException(__FILE__, __LINE__));
}
-}
-
-void
-IceInternal::OutgoingAsyncMessageCallback::__dispatchInvocationTimeout(const ThreadPoolPtr& threadPool,
- const Ice::ConnectionPtr& connection)
-{
- class InvocationTimeoutCall : public DispatchWorkItem
+ catch(const CommunicatorDestroyedException&)
{
- public:
-
- InvocationTimeoutCall(const OutgoingAsyncMessageCallbackPtr& outAsync, const Ice::ConnectionPtr& connection) :
- DispatchWorkItem(connection), _outAsync(outAsync)
- {
- }
-
- virtual void
- run()
- {
- InvocationTimeoutException ex(__FILE__, __LINE__);
- _outAsync->__finished(ex);
- }
-
- private:
-
- const OutgoingAsyncMessageCallbackPtr _outAsync;
- };
- threadPool->dispatch(new InvocationTimeoutCall(this, connection));
+ }
}
-IceInternal::OutgoingAsync::OutgoingAsync(const ObjectPrx& prx,
- const std::string& operation,
- const CallbackBasePtr& delegate,
- const Ice::LocalObjectPtr& cookie) :
- AsyncResult(prx->ice_getCommunicator(), prx->__reference()->getInstance(), operation, delegate, cookie),
- _proxy(prx),
+OutgoingAsync::OutgoingAsync(const ObjectPrx& prx,
+ const string& operation,
+ const CallbackBasePtr& delegate,
+ const LocalObjectPtr& cookie) :
+ ProxyOutgoingAsyncBase(prx, operation, delegate, cookie),
_encoding(getCompatibleEncoding(prx->__reference()->getEncoding()))
{
}
void
-IceInternal::OutgoingAsync::__prepare(const std::string& operation, OperationMode mode, const Context* context)
+OutgoingAsync::prepare(const string& operation, OperationMode mode, const Context* context)
{
- _handler = 0;
- _cnt = 0;
- _sent = false;
- _mode = mode;
- _sentSynchronously = false;
-
checkSupportedProtocol(getCompatibleProtocol(_proxy->__reference()->getProtocol()));
+ _mode = mode;
_observer.attach(_proxy.get(), operation, context);
switch(_proxy->__reference()->getMode())
@@ -482,7 +333,7 @@ IceInternal::OutgoingAsync::__prepare(const std::string& operation, OperationMod
{
_proxy->__setRequestHandler(_handler, 0); // Clear request handler and retry.
}
- catch(const Ice::LocalException& ex)
+ catch(const LocalException& ex)
{
_observer.failed(ex.ice_name());
_proxy->__setRequestHandler(_handler, 0); // Clear request handler
@@ -541,109 +392,63 @@ IceInternal::OutgoingAsync::__prepare(const std::string& operation, OperationMod
}
AsyncStatus
-IceInternal::OutgoingAsync::__send(const Ice::ConnectionIPtr& connection, bool compress, bool response)
+OutgoingAsync::send(const ConnectionIPtr& connection, bool compress, bool response)
{
_cachedConnection = connection;
return connection->sendAsyncRequest(this, compress, response);
}
AsyncStatus
-IceInternal::OutgoingAsync::__invokeCollocated(CollocatedRequestHandler* handler)
+OutgoingAsync::invokeCollocated(CollocatedRequestHandler* handler)
{
return handler->invokeAsyncRequest(this);
}
-bool
-IceInternal::OutgoingAsync::__sent()
+void
+OutgoingAsync::abort(const Exception& ex)
{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
-
- bool alreadySent = _state & Sent; // Expected in case of a retry.
- _state |= Sent;
- _sent = true;
-
- assert(!(_state & Done));
- if(!_proxy->ice_isTwoway())
+ const Reference::Mode mode = _proxy->__reference()->getMode();
+ if(mode == Reference::ModeBatchOneway || mode == Reference::ModeBatchDatagram)
{
- _childObserver.detach();
- if(!_callback || !_callback->hasSentCallback())
+ if(_handler)
{
- _observer.detach();
- }
- if(_timeoutRequestHandler)
- {
- _instance->timer()->cancel(this);
- _timeoutRequestHandler = 0;
+ //
+ // If we didn't finish a batch oneway or datagram request, we
+ // must notify the connection about that we give up ownership
+ // of the batch stream.
+ //
+ _handler->abortBatchRequest();
}
- _state |= Done | OK;
- //_os.resize(0); // Don't clear the buffer now, it's needed for collocation optimization.
}
- _monitor.notifyAll();
- return !alreadySent && _callback && _callback->hasSentCallback();
-}
-
-void
-IceInternal::OutgoingAsync::__invokeSent()
-{
- ::Ice::AsyncResult::__invokeSent();
+
+ ProxyOutgoingAsyncBase::abort(ex);
}
void
-IceInternal::OutgoingAsync::__finished(const Ice::Exception& exc)
+OutgoingAsync::invoke()
{
+ const Reference::Mode mode = _proxy->__reference()->getMode();
+ if(mode == Reference::ModeBatchOneway || mode == Reference::ModeBatchDatagram)
{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- assert(!(_state & Done));
- _childObserver.failed(exc.ice_name());
- _childObserver.detach();
- if(_timeoutRequestHandler)
+ if(_handler)
{
- _instance->timer()->cancel(this);
- _timeoutRequestHandler = 0;
+ _sentSynchronously = true;
+ _handler->finishBatchRequest(&_os);
+ finished(true);
}
+ return; // Don't call sent/completed callback for batch AMI requests
}
//
- // NOTE: at this point, synchronization isn't needed, no other threads should be
- // calling on the callback.
+ // NOTE: invokeImpl doesn't throw so this can be called from the
+ // try block with the catch block calling abort() in case of an
+ // exception.
//
- try
- {
- handleException(exc);
- }
- catch(const Ice::Exception& ex)
- {
- __invokeException(ex);
- }
-}
-
-void
-IceInternal::OutgoingAsync::__invokeExceptionAsync(const Ice::Exception& ex)
-{
- if((_state & Done) == 0 && _handler)
- {
- //
- // If we didn't finish a batch oneway or datagram request, we
- // must notify the connection about that we give up ownership
- // of the batch stream.
- //
- int mode = _proxy->__reference()->getMode();
- if(mode == Reference::ModeBatchOneway || mode == Reference::ModeBatchDatagram)
- {
- _handler->abortBatchRequest();
- }
- }
- AsyncResult::__invokeExceptionAsync(ex);
-}
-
-void
-IceInternal::OutgoingAsync::__processRetry()
-{
- __invoke(false);
+ invokeImpl(true); // userThread = true
}
bool
-IceInternal::OutgoingAsync::__finished()
+OutgoingAsync::completed()
{
//
// NOTE: this method is called from ConnectionI.parseMessage
@@ -652,25 +457,15 @@ IceInternal::OutgoingAsync::__finished()
//
assert(_proxy->ice_isTwoway()); // Can only be called for twoways.
- Ice::Byte replyStatus;
- try
+ if(_childObserver)
{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- assert(!_exception.get() && !(_state & Done));
- assert(!_is.b.empty());
-
- if(_childObserver)
- {
- _childObserver->reply(static_cast<Int>(_is.b.size() - headerSize - 4));
- }
+ _childObserver->reply(static_cast<Int>(_is.b.size() - headerSize - 4));
_childObserver.detach();
+ }
- if(_timeoutRequestHandler)
- {
- _instance->timer()->cancel(this);
- _timeoutRequestHandler = 0;
- }
-
+ Byte replyStatus;
+ try
+ {
_is.read(replyStatus);
switch(replyStatus)
@@ -789,373 +584,197 @@ IceInternal::OutgoingAsync::__finished()
}
}
- _state |= Done;
- _os.resize(0); // Clear buffer now, instead of waiting for AsyncResult deallocation
- if(replyStatus == replyOK)
- {
- _state |= OK;
- }
- _monitor.notifyAll();
-
- if(!_callback)
- {
- _observer.detach();
- return false;
- }
- return true;
+ return finished(replyStatus == replyOK);
}
- catch(const LocalException& exc)
+ catch(const Exception& ex)
{
- //
- // We don't call finished(exc) here because we don't want
- // to invoke the completion callback. The completion
- // callback is invoked by the connection is this method
- // returns true.
- //
- try
- {
- handleException(exc);
- return false; // Invocation will be retried.
- }
- catch(const Ice::Exception& ex)
- {
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- _state |= Done;
- _os.resize(0); // Clear buffer now, instead of waiting for AsyncResult deallocation
- _exception.reset(ex.ice_clone());
- _monitor.notifyAll();
-
- if(!_callback)
- {
- _observer.detach();
- return false;
- }
- return true;
- }
+ return completed(ex);
}
}
+ProxyFlushBatch::ProxyFlushBatch(const ObjectPrx& proxy,
+ const string& operation,
+ const CallbackBasePtr& delegate,
+ const LocalObjectPtr& cookie) :
+ ProxyOutgoingAsyncBase(proxy, operation, delegate, cookie)
+{
+ _observer.attach(proxy.get(), operation, 0);
+}
+
bool
-IceInternal::OutgoingAsync::__invoke(bool userThread)
+ProxyFlushBatch::sent()
{
- const Reference::Mode mode = _proxy->__reference()->getMode();
- if(mode == Reference::ModeBatchOneway || mode == Reference::ModeBatchDatagram)
- {
- _state |= Done | OK;
- _handler->finishBatchRequest(&_os);
- _observer.detach();
- return true;
- }
+ return ProxyOutgoingAsyncBase::sent(true); // Overriden because the flush is done even if using a two-way proxy.
+}
- while(true)
- {
- try
- {
- _sent = false;
- _handler = _proxy->__getRequestHandler();
- AsyncStatus status = _handler->sendAsyncRequest(this);
- if(status & AsyncStatusSent)
- {
- if(userThread)
- {
- _sentSynchronously = true;
- if(status & AsyncStatusInvokeSentCallback)
- {
- __invokeSent(); // Call the sent callback from the user thread.
- }
- }
- else
- {
- if(status & AsyncStatusInvokeSentCallback)
- {
- __invokeSentAsync(); // Call the sent callback from a client thread pool thread.
- }
- }
- }
+AsyncStatus
+ProxyFlushBatch::send(const ConnectionIPtr& connection, bool, bool)
+{
+ _cachedConnection = connection;
+ return connection->flushAsyncBatchRequests(this);
+}
- if(mode == Reference::ModeTwoway || !(status & AsyncStatusSent))
- {
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- if(!(_state & Done))
- {
- int invocationTimeout = _handler->getReference()->getInvocationTimeout();
- if(invocationTimeout > 0)
- {
- _instance->timer()->schedule(this, IceUtil::Time::milliSeconds(invocationTimeout));
- _timeoutRequestHandler = _handler;
- }
- }
- }
- }
- catch(const RetryException&)
- {
- _proxy->__setRequestHandler(_handler, 0); // Clear request handler and retry.
- continue;
- }
- catch(const Ice::Exception& ex)
- {
- handleException(ex);
- }
- break;
- }
- return _sentSynchronously;
+AsyncStatus
+ProxyFlushBatch::invokeCollocated(CollocatedRequestHandler* handler)
+{
+ return handler->invokeAsyncBatchRequests(this);
}
void
-IceInternal::OutgoingAsync::handleException(const Ice::Exception& exc)
+ProxyFlushBatch::invoke()
{
- try
- {
- int interval = _proxy->__handleException(exc, _handler, _mode, _sent, _cnt);
- _observer.retried(); // Invocation is being retried.
-
- //
- // Schedule the retry. Note that we always schedule the retry
- // on the retry queue even if the invocation can be retried
- // immediately. This is required because it might not be safe
- // to retry from this thread (this is for instance called by
- // finished(BasicStream) which is called with the connection
- // locked.
- //
- _instance->retryQueue()->add(this, interval);
- }
- catch(const Ice::Exception& ex)
- {
- _observer.failed(ex.ice_name());
- throw;
- }
+ checkSupportedProtocol(getCompatibleProtocol(_proxy->__reference()->getProtocol()));
+ invokeImpl(true); // userThread = true
}
-IceInternal::BatchOutgoingAsync::BatchOutgoingAsync(const CommunicatorPtr& communicator,
- const InstancePtr& instance,
- const std::string& operation,
- const CallbackBasePtr& delegate,
- const Ice::LocalObjectPtr& cookie) :
- AsyncResult(communicator, instance, operation, delegate, cookie)
+void
+ProxyFlushBatch::handleRetryException(const RetryException& ex)
{
+ _proxy->__setRequestHandler(_handler, 0); // Clear request handler
+ ex.get()->ice_throw(); // No retries, we want to notify the user of potentially lost batch requests
}
-AsyncStatus
-IceInternal::BatchOutgoingAsync::__send(const Ice::ConnectionIPtr& connection, bool, bool)
+int
+ProxyFlushBatch::handleException(const Exception& ex)
{
- _cachedConnection = connection;
- return connection->flushAsyncBatchRequests(this);
+ _proxy->__setRequestHandler(_handler, 0); // Clear request handler
+ ex.ice_throw(); // No retries, we want to notify the user of potentially lost batch requests
+ return 0;
}
-AsyncStatus
-IceInternal::BatchOutgoingAsync::__invokeCollocated(CollocatedRequestHandler* handler)
+ProxyGetConnection::ProxyGetConnection(const ObjectPrx& prx,
+ const string& operation,
+ const CallbackBasePtr& delegate,
+ const LocalObjectPtr& cookie) :
+ ProxyOutgoingAsyncBase(prx, operation, delegate, cookie)
{
- return handler->invokeAsyncBatchRequests(this);
+ _observer.attach(prx.get(), operation, 0);
}
-bool
-IceInternal::BatchOutgoingAsync::__sent()
+AsyncStatus
+ProxyGetConnection::send(const ConnectionIPtr& connection, bool, bool)
{
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- assert(!_exception.get());
- _state |= Done | OK | Sent;
- //_os.resize(0); // Don't clear the buffer now, it's needed for collocation optimization.
- _childObserver.detach();
- if(_timeoutRequestHandler)
- {
- _instance->timer()->cancel(this);
- _timeoutRequestHandler = 0;
- }
- _monitor.notifyAll();
- if(!_callback || !_callback->hasSentCallback())
+ _cachedConnection = connection;
+ if(finished(true))
{
- _observer.detach();
- return false;
+ invokeCompletedAsync();
}
- return true;
+ return AsyncStatusSent;
}
-void
-IceInternal::BatchOutgoingAsync::__invokeSent()
+AsyncStatus
+ProxyGetConnection::invokeCollocated(CollocatedRequestHandler*)
{
- ::Ice::AsyncResult::__invokeSent();
+ if(finished(true))
+ {
+ invokeCompletedAsync();
+ }
+ return AsyncStatusSent;
}
void
-IceInternal::BatchOutgoingAsync::__finished(const Ice::Exception& exc)
+ProxyGetConnection::invoke()
{
- {
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- _childObserver.failed(exc.ice_name());
- _childObserver.detach();
- if(_timeoutRequestHandler)
- {
- _instance->timer()->cancel(this);
- _timeoutRequestHandler = 0;
- }
- }
- __invokeException(exc);
+ invokeImpl(true); // userThread = true
}
-void
-IceInternal::BatchOutgoingAsync::__processRetry()
+ConnectionFlushBatch::ConnectionFlushBatch(const ConnectionIPtr& connection,
+ const CommunicatorPtr& communicator,
+ const InstancePtr& instance,
+ const string& operation,
+ const CallbackBasePtr& delegate,
+ const LocalObjectPtr& cookie) :
+ OutgoingAsyncBase(communicator, instance, operation, delegate, cookie), _connection(connection)
{
- assert(false); // Retries are never scheduled
+ _observer.attach(instance.get(), operation);
}
-IceInternal::ProxyBatchOutgoingAsync::ProxyBatchOutgoingAsync(const Ice::ObjectPrx& proxy,
- const std::string& operation,
- const CallbackBasePtr& delegate,
- const Ice::LocalObjectPtr& cookie) :
- BatchOutgoingAsync(proxy->ice_getCommunicator(), proxy->__reference()->getInstance(), operation, delegate, cookie),
- _proxy(proxy)
+ConnectionPtr
+ConnectionFlushBatch::getConnection() const
{
- _observer.attach(proxy.get(), operation, 0);
+ return _connection;
}
void
-IceInternal::ProxyBatchOutgoingAsync::__invoke()
+ConnectionFlushBatch::invoke()
{
- checkSupportedProtocol(_proxy->__reference()->getProtocol());
-
- RequestHandlerPtr handler;
try
{
- handler = _proxy->__getRequestHandler();
- AsyncStatus status = handler->sendAsyncRequest(this);
+ AsyncStatus status = _connection->flushAsyncBatchRequests(this);
if(status & AsyncStatusSent)
{
_sentSynchronously = true;
if(status & AsyncStatusInvokeSentCallback)
{
- __invokeSent();
- }
- }
- else
- {
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- if(!(_state & Done))
- {
- int invocationTimeout = handler->getReference()->getInvocationTimeout();
- if(invocationTimeout > 0)
- {
- _instance->timer()->schedule(this, IceUtil::Time::milliSeconds(invocationTimeout));
- _timeoutRequestHandler = handler;
- }
+ invokeSent();
}
}
}
- catch(const RetryException&)
- {
- //
- // Clear request handler but don't retry or throw. Retrying
- // isn't useful, there were no batch requests associated with
- // the proxy's request handler.
- //
- _proxy->__setRequestHandler(handler, 0);
- }
- catch(const Ice::Exception& ex)
+ catch(const Exception& ex)
{
- _observer.failed(ex.ice_name());
- _proxy->__setRequestHandler(handler, 0); // Clear request handler
- throw; // Throw to notify the user that batch requests were potentially lost.
- }
-}
-
-IceInternal::ConnectionBatchOutgoingAsync::ConnectionBatchOutgoingAsync(const ConnectionIPtr& con,
- const CommunicatorPtr& communicator,
- const InstancePtr& instance,
- const string& operation,
- const CallbackBasePtr& delegate,
- const Ice::LocalObjectPtr& cookie) :
- BatchOutgoingAsync(communicator, instance, operation, delegate, cookie),
- _connection(con)
-{
- _observer.attach(instance.get(), operation);
-}
-
-void
-IceInternal::ConnectionBatchOutgoingAsync::__invoke()
-{
- AsyncStatus status = _connection->flushAsyncBatchRequests(this);
- if(status & AsyncStatusSent)
- {
- _sentSynchronously = true;
- if(status & AsyncStatusInvokeSentCallback)
+ if(completed(ex))
{
- __invokeSent();
+ invokeCompletedAsync();
}
}
}
-Ice::ConnectionPtr
-IceInternal::ConnectionBatchOutgoingAsync::getConnection() const
+CommunicatorFlushBatch::CommunicatorFlushBatch(const CommunicatorPtr& communicator,
+ const InstancePtr& instance,
+ const string& operation,
+ const CallbackBasePtr& cb,
+ const LocalObjectPtr& cookie) :
+ AsyncResult(communicator, instance, operation, cb, cookie)
{
- return _connection;
-}
+ _observer.attach(instance.get(), operation);
-IceInternal::CommunicatorBatchOutgoingAsync::CommunicatorBatchOutgoingAsync(const CommunicatorPtr& communicator,
- const InstancePtr& instance,
- const string& operation,
- const CallbackBasePtr& delegate,
- const Ice::LocalObjectPtr& cookie) :
- AsyncResult(communicator, instance, operation, delegate, cookie)
-{
//
// _useCount is initialized to 1 to prevent premature callbacks.
// The caller must invoke ready() after all flush requests have
// been initiated.
//
_useCount = 1;
-
- //
- // Assume all connections are flushed synchronously.
- //
- _sentSynchronously = true;
-
- //
- // Attach observer
- //
- _observer.attach(instance.get(), operation);
}
void
-IceInternal::CommunicatorBatchOutgoingAsync::flushConnection(const ConnectionIPtr& con)
+CommunicatorFlushBatch::flushConnection(const ConnectionIPtr& con)
{
- class BatchOutgoingAsyncI : public BatchOutgoingAsync
+ class FlushBatch : public OutgoingAsyncBase
{
public:
-
- BatchOutgoingAsyncI(const CommunicatorBatchOutgoingAsyncPtr& outAsync,
- const InstancePtr& instance,
- InvocationObserver& observer) :
- BatchOutgoingAsync(outAsync->getCommunicator(), instance, outAsync->getOperation(), __dummyCallback, 0),
- _outAsync(outAsync), _observer(observer)
+
+ FlushBatch(const CommunicatorFlushBatchPtr& outAsync,
+ const InstancePtr& instance,
+ InvocationObserver& observer) :
+ OutgoingAsyncBase(outAsync->getCommunicator(), instance, outAsync->getOperation(), __dummyCallback, 0),
+ _outAsync(outAsync),
+ _observer(observer)
{
}
- virtual bool __sent()
+ virtual bool sent()
{
_childObserver.detach();
_outAsync->check(false);
return false;
}
-#ifdef __SUNPRO_CC
- using BatchOutgoingAsync::__sent;
-#endif
-
- virtual void __finished(const Ice::Exception& ex)
+ virtual bool completed(const Exception& ex)
{
_childObserver.failed(ex.ice_name());
_childObserver.detach();
_outAsync->check(false);
+ return false;
}
- virtual void __attachRemoteObserver(const Ice::ConnectionInfoPtr& connection, const Ice::EndpointPtr& endpt,
- Ice::Int requestId, Ice::Int sz)
+ private:
+
+ virtual InvocationObserver& getObserver()
{
- _childObserver.attach(_observer.getRemoteObserver(connection, endpt, requestId, sz));
+ return _observer;
}
- private:
-
- const CommunicatorBatchOutgoingAsyncPtr _outAsync;
+ const CommunicatorFlushBatchPtr _outAsync;
InvocationObserver& _observer;
};
@@ -1166,13 +785,9 @@ IceInternal::CommunicatorBatchOutgoingAsync::flushConnection(const ConnectionIPt
try
{
- AsyncStatus status = con->flushAsyncBatchRequests(new BatchOutgoingAsyncI(this, _instance, _observer));
- if(!(status & AsyncStatusSent))
- {
- _sentSynchronously = false;
- }
+ con->flushAsyncBatchRequests(new FlushBatch(this, _instance, _observer));
}
- catch(const Ice::LocalException&)
+ catch(const LocalException&)
{
check(false);
throw;
@@ -1180,19 +795,13 @@ IceInternal::CommunicatorBatchOutgoingAsync::flushConnection(const ConnectionIPt
}
void
-IceInternal::CommunicatorBatchOutgoingAsync::ready()
+CommunicatorFlushBatch::ready()
{
check(true);
}
void
-IceInternal::CommunicatorBatchOutgoingAsync::__processRetry()
-{
- assert(false); // Retries are never scheduled
-}
-
-void
-IceInternal::CommunicatorBatchOutgoingAsync::check(bool userThread)
+CommunicatorFlushBatch::check(bool userThread)
{
{
IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
@@ -1201,255 +810,18 @@ IceInternal::CommunicatorBatchOutgoingAsync::check(bool userThread)
{
return;
}
- _state |= Done | OK | Sent;
- _os.resize(0); // Clear buffer now, instead of waiting for AsyncResult deallocation
- _monitor.notifyAll();
}
- if(!_callback || !_callback->hasSentCallback())
+ if(sent(true))
{
- _observer.detach();
- }
- else
- {
- //
- // _sentSynchronously is immutable here.
- //
- if(!_sentSynchronously || !userThread)
+ if(userThread)
{
- __invokeSentAsync();
+ _sentSynchronously = true;
+ invokeSent();
}
else
{
- AsyncResult::__invokeSent();
- }
- }
-}
-
-IceInternal::GetConnectionOutgoingAsync::GetConnectionOutgoingAsync(const Ice::ObjectPrx& prx,
- const std::string& operation,
- const CallbackBasePtr& delegate,
- const Ice::LocalObjectPtr& cookie) :
- AsyncResult(prx->ice_getCommunicator(), prx->__reference()->getInstance(), operation, delegate, cookie),
- _proxy(prx),
- _cnt(0)
-{
- _observer.attach(prx.get(), operation, 0);
-}
-
-void
-IceInternal::GetConnectionOutgoingAsync::__invoke()
-{
- while(true)
- {
- try
- {
- _handler = _proxy->__getRequestHandler();
- _handler->sendAsyncRequest(this);
- }
- catch(const RetryException&)
- {
- _proxy->__setRequestHandler(_handler, 0);
- }
- catch(const Ice::Exception& ex)
- {
- handleException(ex);
+ invokeSentAsync();
}
- break;
- }
-}
-
-AsyncStatus
-IceInternal::GetConnectionOutgoingAsync::__send(const Ice::ConnectionIPtr&, bool, bool)
-{
- __sent();
- return AsyncStatusSent;
-}
-
-AsyncStatus
-IceInternal::GetConnectionOutgoingAsync::__invokeCollocated(CollocatedRequestHandler*)
-{
- __sent();
- return AsyncStatusSent;
-}
-
-bool
-IceInternal::GetConnectionOutgoingAsync::__sent()
-{
- {
- IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
- _state |= Done;
- _monitor.notifyAll();
- }
- __invokeCompleted();
- return false;
-}
-
-void
-IceInternal::GetConnectionOutgoingAsync::__invokeSent()
-{
- // No sent callback
-}
-
-void
-IceInternal::GetConnectionOutgoingAsync::__finished(const Ice::Exception& exc)
-{
- try
- {
- handleException(exc);
- }
- catch(const Ice::Exception& ex)
- {
- __invokeException(ex);
- }
-}
-
-void
-IceInternal::GetConnectionOutgoingAsync::__processRetry()
-{
- __invoke();
-}
-
-void
-IceInternal::GetConnectionOutgoingAsync::handleException(const Ice::Exception& exc)
-{
- try
- {
- _instance->retryQueue()->add(this, _proxy->__handleException(exc, _handler, Ice::Idempotent, false, _cnt));
- _observer.retried(); // Invocation is being retried.
- }
- catch(const Ice::Exception& ex)
- {
- _observer.failed(ex.ice_name());
- throw;
- }
-}
-
-namespace
-{
-
-//
-// Dummy class derived from CallbackBase
-// We use this class for the __dummyCallback extern pointer in OutgoingAsync. In turn,
-// this allows us to test whether the user supplied a null delegate instance to the
-// generated begin_ method without having to generate a separate test to throw IllegalArgumentException
-// in the inlined versions of the begin_ method. In other words, this reduces the amount of generated
-// object code.
-//
-class DummyCallback : public CallbackBase
-{
-public:
-
- DummyCallback()
- {
- }
-
- virtual void
- completed(const Ice::AsyncResultPtr&) const
- {
- assert(false);
- }
-
- virtual CallbackBasePtr
- verify(const Ice::LocalObjectPtr&)
- {
- //
- // Called by the AsyncResult constructor to verify the delegate. The dummy
- // delegate is passed when the user used a begin_ method without delegate.
- // By returning 0 here, we tell the AsyncResult that no delegates was
- // provided.
- //
- return 0;
- }
-
- virtual void
- sent(const AsyncResultPtr&) const
- {
- assert(false);
- }
-
- virtual bool
- hasSentCallback() const
- {
- assert(false);
- return false;
- }
-};
-
-}
-
-//
-// This gives a pointer value to compare against in the generated
-// begin_ method to decide whether the caller passed a null pointer
-// versus the generated inline version of the begin_ method having
-// passed a pointer to the dummy delegate.
-//
-CallbackBasePtr IceInternal::__dummyCallback = new DummyCallback;
-
-#ifdef ICE_CPP11
-
-Ice::CallbackPtr
-Ice::newCallback(const ::IceInternal::Function<void (const AsyncResultPtr&)>& completed,
- const ::IceInternal::Function<void (const AsyncResultPtr&)>& sent)
-{
- class Cpp11CB : public GenericCallbackBase
- {
- public:
-
- Cpp11CB(const ::std::function<void (const AsyncResultPtr&)>& completed,
- const ::std::function<void (const AsyncResultPtr&)>& sent) :
- _completed(completed),
- _sent(sent)
- {
- checkCallback(true, completed != nullptr);
- }
-
- virtual void
- completed(const AsyncResultPtr& result) const
- {
- _completed(result);
- }
-
- virtual CallbackBasePtr
- verify(const LocalObjectPtr&)
- {
- return this; // Nothing to do, the cookie is not type-safe.
- }
-
- virtual void
- sent(const AsyncResultPtr& result) const
- {
- if(_sent != nullptr)
- {
- _sent(result);
- }
- }
-
- virtual bool
- hasSentCallback() const
- {
- return _sent != nullptr;
- }
-
- private:
-
- ::std::function< void (const AsyncResultPtr&)> _completed;
- ::std::function< void (const AsyncResultPtr&)> _sent;
- };
-
- return new Cpp11CB(completed, sent);
-}
-#endif
-
-void
-IceInternal::CallbackBase::checkCallback(bool obj, bool cb)
-{
- if(!obj)
- {
- throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "callback object cannot be null");
- }
- if(!cb)
- {
- throw IceUtil::IllegalArgumentException(__FILE__, __LINE__, "callback cannot be null");
}
}
diff --git a/cpp/src/Ice/Proxy.cpp b/cpp/src/Ice/Proxy.cpp
index f455f5e6361..13bd0120a8f 100644
--- a/cpp/src/Ice/Proxy.cpp
+++ b/cpp/src/Ice/Proxy.cpp
@@ -217,15 +217,15 @@ IceProxy::Ice::Object::begin_ice_isA(const string& typeId,
OutgoingAsyncPtr __result = new OutgoingAsync(this, ice_isA_name, del, cookie);
try
{
- __result->__prepare(ice_isA_name, Nonmutating, ctx);
- IceInternal::BasicStream* __os = __result->__startWriteParams(DefaultFormat);
+ __result->prepare(ice_isA_name, Nonmutating, ctx);
+ IceInternal::BasicStream* __os = __result->startWriteParams(DefaultFormat);
__os->write(typeId);
- __result->__endWriteParams();
- __result->__invoke(true);
+ __result->endWriteParams();
+ __result->invoke();
}
catch(const Exception& __ex)
{
- __result->__invokeExceptionAsync(__ex);
+ __result->abort(__ex);
}
return __result;
}
@@ -233,12 +233,11 @@ IceProxy::Ice::Object::begin_ice_isA(const string& typeId,
#ifdef ICE_CPP11
Ice::AsyncResultPtr
-IceProxy::Ice::Object::__begin_ice_isA(
- const ::std::string& typeId,
- const ::Ice::Context* ctx,
- const ::IceInternal::Function<void (bool)>& response,
- const ::IceInternal::Function<void (const ::Ice::Exception&)>& exception,
- const ::IceInternal::Function<void (bool)>& sent)
+IceProxy::Ice::Object::__begin_ice_isA(const ::std::string& typeId,
+ const ::Ice::Context* ctx,
+ const ::IceInternal::Function<void (bool)>& response,
+ const ::IceInternal::Function<void (const ::Ice::Exception&)>& exception,
+ const ::IceInternal::Function<void (bool)>& sent)
{
class Cpp11CB : public ::IceInternal::Cpp11FnCallbackNC
{
@@ -281,11 +280,10 @@ IceProxy::Ice::Object::__begin_ice_isA(
}
Ice::AsyncResultPtr
-IceProxy::Ice::Object::__begin_ice_id(
- const ::Ice::Context* ctx,
- const ::IceInternal::Function<void (const ::std::string&)>& response,
- const ::IceInternal::Function<void (const ::Ice::Exception&)>& exception,
- const ::IceInternal::Function<void (bool)>& sent)
+IceProxy::Ice::Object::__begin_ice_id(const ::Ice::Context* ctx,
+ const ::IceInternal::Function<void (const ::std::string&)>& response,
+ const ::IceInternal::Function<void (const ::Ice::Exception&)>& exception,
+ const ::IceInternal::Function<void (bool)>& sent)
{
class Cpp11CB : public ::IceInternal::Cpp11FnCallbackNC
{
@@ -573,13 +571,13 @@ IceProxy::Ice::Object::begin_ice_ping(const Context* ctx,
OutgoingAsyncPtr __result = new OutgoingAsync(this, ice_ping_name, del, cookie);
try
{
- __result->__prepare(ice_ping_name, Nonmutating, ctx);
- __result->__writeEmptyParams();
- __result->__invoke(true);
+ __result->prepare(ice_ping_name, Nonmutating, ctx);
+ __result->writeEmptyParams();
+ __result->invoke();
}
catch(const Exception& __ex)
{
- __result->__invokeExceptionAsync(__ex);
+ __result->abort(__ex);
}
return __result;
}
@@ -647,13 +645,13 @@ IceProxy::Ice::Object::begin_ice_ids(const Context* ctx,
OutgoingAsyncPtr __result = new OutgoingAsync(this, ice_ids_name, del, cookie);
try
{
- __result->__prepare(ice_ids_name, Nonmutating, ctx);
- __result->__writeEmptyParams();
- __result->__invoke(true);
+ __result->prepare(ice_ids_name, Nonmutating, ctx);
+ __result->writeEmptyParams();
+ __result->invoke();
}
catch(const Exception& __ex)
{
- __result->__invokeExceptionAsync(__ex);
+ __result->abort(__ex);
}
return __result;
}
@@ -690,13 +688,13 @@ IceProxy::Ice::Object::begin_ice_id(const Context* ctx,
OutgoingAsyncPtr __result = new OutgoingAsync(this, ice_id_name, del, cookie);
try
{
- __result->__prepare(ice_id_name, Nonmutating, ctx);
- __result->__writeEmptyParams();
- __result->__invoke(true);
+ __result->prepare(ice_id_name, Nonmutating, ctx);
+ __result->writeEmptyParams();
+ __result->invoke();
}
catch(const Exception& __ex)
{
- __result->__invokeExceptionAsync(__ex);
+ __result->abort(__ex);
}
return __result;
}
@@ -818,13 +816,13 @@ IceProxy::Ice::Object::begin_ice_invoke(const string& operation,
OutgoingAsyncPtr __result = new OutgoingAsync(this, ice_invoke_name, del, cookie);
try
{
- __result->__prepare(operation, mode, ctx);
- __result->__writeParamEncaps(inEncaps.first, static_cast<Int>(inEncaps.second - inEncaps.first));
- __result->__invoke(true);
+ __result->prepare(operation, mode, ctx);
+ __result->writeParamEncaps(inEncaps.first, static_cast<Int>(inEncaps.second - inEncaps.first));
+ __result->invoke();
}
catch(const Exception& __ex)
{
- __result->__invokeExceptionAsync(__ex);
+ __result->abort(__ex);
}
return __result;
}
@@ -1389,17 +1387,16 @@ AsyncResultPtr
IceProxy::Ice::Object::begin_ice_getConnectionInternal(const ::IceInternal::CallbackBasePtr& del,
const ::Ice::LocalObjectPtr& cookie)
{
- ::IceInternal::GetConnectionOutgoingAsyncPtr __result =
- new ::IceInternal::GetConnectionOutgoingAsync(this, ice_getConnection_name, del, cookie);
+ ProxyGetConnectionPtr result = new ProxyGetConnection(this, ice_getConnection_name, del, cookie);
try
{
- __result->__invoke();
+ result->invoke();
}
- catch(const Exception& __ex)
+ catch(const Exception& ex)
{
- __result->__invokeExceptionAsync(__ex);
+ result->abort(ex);
}
- return __result;
+ return result;
}
ConnectionPtr
@@ -1435,32 +1432,31 @@ IceProxy::Ice::Object::ice_getCachedConnection() const
void
IceProxy::Ice::Object::ice_flushBatchRequests()
{
- BatchOutgoing __og(this, ice_flushBatchRequests_name);
- __og.invoke();
+ FlushBatch og(this, ice_flushBatchRequests_name);
+ og.invoke();
}
::Ice::AsyncResultPtr
IceProxy::Ice::Object::begin_ice_flushBatchRequestsInternal(const ::IceInternal::CallbackBasePtr& del,
const ::Ice::LocalObjectPtr& cookie)
{
- ::IceInternal::ProxyBatchOutgoingAsyncPtr __result =
- new ::IceInternal::ProxyBatchOutgoingAsync(this, ice_flushBatchRequests_name, del, cookie);
+ ProxyFlushBatchPtr result = new ProxyFlushBatch(this, ice_flushBatchRequests_name, del, cookie);
try
{
- __result->__invoke();
+ result->invoke();
}
- catch(const Exception& __ex)
+ catch(const Exception& ex)
{
- __result->__invokeExceptionAsync(__ex);
+ result->abort(ex);
}
- return __result;
+ return result;
}
void
-IceProxy::Ice::Object::end_ice_flushBatchRequests(const AsyncResultPtr& __result)
+IceProxy::Ice::Object::end_ice_flushBatchRequests(const AsyncResultPtr& result)
{
- AsyncResult::__check(__result, this, ice_flushBatchRequests_name);
- __result->__wait();
+ AsyncResult::__check(result, this, ice_flushBatchRequests_name);
+ result->__wait();
}
Int
diff --git a/cpp/src/Ice/ProxyFactory.cpp b/cpp/src/Ice/ProxyFactory.cpp
index 68ca8b02598..fb2aea3e337 100644
--- a/cpp/src/Ice/ProxyFactory.cpp
+++ b/cpp/src/Ice/ProxyFactory.cpp
@@ -223,7 +223,7 @@ IceInternal::ProxyFactory::checkRetryAfterException(const LocalException& ex, co
//
// Don't retry invocation timeouts.
//
- if(dynamic_cast<const InvocationTimeoutException*>(&ex))
+ if(dynamic_cast<const InvocationTimeoutException*>(&ex) || dynamic_cast<const InvocationCanceledException*>(&ex))
{
ex.ice_throw();
}
diff --git a/cpp/src/Ice/RequestHandler.cpp b/cpp/src/Ice/RequestHandler.cpp
index 2cbf7826213..07ec753912d 100644
--- a/cpp/src/Ice/RequestHandler.cpp
+++ b/cpp/src/Ice/RequestHandler.cpp
@@ -14,6 +14,7 @@ using namespace std;
using namespace IceInternal;
IceUtil::Shared* IceInternal::upCast(RequestHandler* p) { return p; }
+IceUtil::Shared* IceInternal::upCast(CancellationHandler* p) { return p; }
RetryException::RetryException(const Ice::LocalException& ex)
{
@@ -32,10 +33,6 @@ RetryException::get() const
return _ex.get();
}
-RequestHandler::~RequestHandler()
-{
-}
-
RequestHandler::RequestHandler(const ReferencePtr& reference) :
_reference(reference),
_response(reference->getMode() == Reference::ModeTwoway)
diff --git a/cpp/src/Ice/RequestHandler.h b/cpp/src/Ice/RequestHandler.h
index 73c3e818b56..68ff00d647d 100644
--- a/cpp/src/Ice/RequestHandler.h
+++ b/cpp/src/Ice/RequestHandler.h
@@ -31,7 +31,7 @@ namespace IceInternal
class BasicStream;
-class OutgoingMessageCallback;
+class OutgoingBase;
//
// An exception wrapper, which is used to notify that the request
@@ -51,11 +51,17 @@ private:
IceUtil::UniquePtr<Ice::LocalException> _ex;
};
-class RequestHandler : virtual public ::IceUtil::Shared
+class CancellationHandler : virtual public IceUtil::Shared
{
public:
- virtual ~RequestHandler();
+ virtual void requestCanceled(OutgoingBase*, const Ice::LocalException&) = 0;
+ virtual void asyncRequestCanceled(const OutgoingAsyncBasePtr&, const Ice::LocalException&) = 0;
+};
+
+class RequestHandler : public CancellationHandler
+{
+public:
virtual RequestHandlerPtr connect() = 0;
virtual RequestHandlerPtr update(const RequestHandlerPtr&, const RequestHandlerPtr&) = 0;
@@ -64,11 +70,8 @@ public:
virtual void finishBatchRequest(BasicStream*) = 0;
virtual void abortBatchRequest() = 0;
- virtual bool sendRequest(OutgoingMessageCallback*) = 0;
- virtual AsyncStatus sendAsyncRequest(const OutgoingAsyncMessageCallbackPtr&) = 0;
-
- virtual void requestTimedOut(OutgoingMessageCallback*) = 0;
- virtual void asyncRequestTimedOut(const OutgoingAsyncMessageCallbackPtr&) = 0;
+ virtual bool sendRequest(OutgoingBase*) = 0;
+ virtual AsyncStatus sendAsyncRequest(const OutgoingAsyncBasePtr&) = 0;
const ReferencePtr& getReference() const { return _reference; } // Inlined for performances.
diff --git a/cpp/src/Ice/RetryQueue.cpp b/cpp/src/Ice/RetryQueue.cpp
index adfb6bf9440..c70ed379edd 100644
--- a/cpp/src/Ice/RetryQueue.cpp
+++ b/cpp/src/Ice/RetryQueue.cpp
@@ -18,7 +18,7 @@ using namespace IceInternal;
IceUtil::Shared* IceInternal::upCast(RetryQueue* p) { return p; }
-IceInternal::RetryTask::RetryTask(const RetryQueuePtr& queue, const AsyncResultPtr& outAsync) :
+IceInternal::RetryTask::RetryTask(const RetryQueuePtr& queue, const ProxyOutgoingAsyncBasePtr& outAsync) :
_queue(queue), _outAsync(outAsync)
{
}
@@ -26,14 +26,7 @@ IceInternal::RetryTask::RetryTask(const RetryQueuePtr& queue, const AsyncResultP
void
IceInternal::RetryTask::runTimerTask()
{
- try
- {
- _outAsync->__processRetry();
- }
- catch(const Ice::LocalException& ex)
- {
- _outAsync->__invokeExceptionAsync(ex);
- }
+ _outAsync->retry(); // Retry again the invocation.
//
// NOTE: this must be called last, destroy() blocks until all task
@@ -44,10 +37,37 @@ IceInternal::RetryTask::runTimerTask()
_queue->remove(this);
}
+void
+IceInternal::RetryTask::requestCanceled(OutgoingBase*, const Ice::LocalException&)
+{
+ assert(false);
+}
+
+void
+IceInternal::RetryTask::asyncRequestCanceled(const OutgoingAsyncBasePtr& outAsync, const Ice::LocalException&)
+{
+ if(_queue->cancel(this))
+ {
+ //
+ // We just retry the outgoing async now rather than marking it
+ // as finished. The retry will check for the cancellation
+ // exception and terminate appropriately the request.
+ //
+ _outAsync->retry();
+ }
+}
+
void
IceInternal::RetryTask::destroy()
{
- _outAsync->__invokeExceptionAsync(CommunicatorDestroyedException(__FILE__, __LINE__));
+ try
+ {
+ _outAsync->abort(CommunicatorDestroyedException(__FILE__, __LINE__));
+ }
+ catch(const CommunicatorDestroyedException&)
+ {
+ // Abort shouldn't throw if there's no callback, ignore.
+ }
}
bool
@@ -61,7 +81,7 @@ IceInternal::RetryQueue::RetryQueue(const InstancePtr& instance) : _instance(ins
}
void
-IceInternal::RetryQueue::add(const AsyncResultPtr& out, int interval)
+IceInternal::RetryQueue::add(const ProxyOutgoingAsyncBasePtr& out, int interval)
{
Lock sync(*this);
if(!_instance)
@@ -78,6 +98,7 @@ IceInternal::RetryQueue::add(const AsyncResultPtr& out, int interval)
throw CommunicatorDestroyedException(__FILE__, __LINE__);
}
_requests.insert(task);
+ out->cancelable(task);
}
void
@@ -119,4 +140,17 @@ IceInternal::RetryQueue::remove(const RetryTaskPtr& task)
}
}
-
+bool
+IceInternal::RetryQueue::cancel(const RetryTaskPtr& task)
+{
+ Lock sync(*this);
+ if(_requests.erase(task) > 0)
+ {
+ if(!_instance && _requests.empty())
+ {
+ notify(); // If we are destroying the queue, destroy is probably waiting on the queue to be empty.
+ }
+ return _instance->timer()->cancel(task);
+ }
+ return false;
+}
diff --git a/cpp/src/Ice/RetryQueue.h b/cpp/src/Ice/RetryQueue.h
index 5a0b7cf52a2..71c9c946d8d 100644
--- a/cpp/src/Ice/RetryQueue.h
+++ b/cpp/src/Ice/RetryQueue.h
@@ -16,25 +16,31 @@
#include <Ice/RetryQueueF.h>
#include <Ice/OutgoingAsyncF.h>
#include <Ice/InstanceF.h>
+#include <Ice/RequestHandler.h> // For CancellationHandler
namespace IceInternal
{
-class RetryTask : public IceUtil::TimerTask
+class RetryTask : public IceUtil::TimerTask, public CancellationHandler
{
public:
- RetryTask(const RetryQueuePtr&, const Ice::AsyncResultPtr&);
+ RetryTask(const RetryQueuePtr&, const ProxyOutgoingAsyncBasePtr&);
virtual void runTimerTask();
+
+ virtual void requestCanceled(OutgoingBase*, const Ice::LocalException&);
+ virtual void asyncRequestCanceled(const OutgoingAsyncBasePtr&, const Ice::LocalException&);
+
void destroy();
bool operator<(const RetryTask&) const;
+
private:
const RetryQueuePtr _queue;
- const Ice::AsyncResultPtr _outAsync;
+ const ProxyOutgoingAsyncBasePtr _outAsync;
};
typedef IceUtil::Handle<RetryTask> RetryTaskPtr;
@@ -44,12 +50,13 @@ public:
RetryQueue(const InstancePtr&);
- void add(const Ice::AsyncResultPtr&, int);
+ void add(const ProxyOutgoingAsyncBasePtr&, int);
void destroy();
private:
void remove(const RetryTaskPtr&);
+ bool cancel(const RetryTaskPtr&);
friend class RetryTask;
InstancePtr _instance;
diff --git a/cpp/src/Ice/winrt/Makefile.mak b/cpp/src/Ice/winrt/Makefile.mak
index 7eda814e8f6..c05ba0bc7e0 100644
--- a/cpp/src/Ice/winrt/Makefile.mak
+++ b/cpp/src/Ice/winrt/Makefile.mak
@@ -7,13 +7,14 @@
#
# **********************************************************************
-top_srcdir = ..\..\..
+top_srcdir = ..\..\..
LIBNAME = $(SDK_LIBRARY_PATH)\ice.lib
TARGETS = $(LIBNAME)
SOURCE_DIR = ..
OBJS = $(ARCH)\$(CONFIG)\Acceptor.obj \
$(ARCH)\$(CONFIG)\ACM.obj \
+ $(ARCH)\$(CONFIG)\AsyncResult.obj \
$(ARCH)\$(CONFIG)\Base64.obj \
$(ARCH)\$(CONFIG)\Buffer.obj \
$(ARCH)\$(CONFIG)\BasicStream.obj \
diff --git a/cpp/src/IceDiscovery/LocatorI.h b/cpp/src/IceDiscovery/LocatorI.h
index 700f4305129..bb48d8cb509 100644
--- a/cpp/src/IceDiscovery/LocatorI.h
+++ b/cpp/src/IceDiscovery/LocatorI.h
@@ -13,6 +13,8 @@
#include <Ice/Locator.h>
#include <Ice/ProxyF.h>
+#include <set>
+
namespace IceDiscovery
{
diff --git a/cpp/src/IceDiscovery/LookupI.h b/cpp/src/IceDiscovery/LookupI.h
index 1a249b4e0da..58e1e7ca044 100644
--- a/cpp/src/IceDiscovery/LookupI.h
+++ b/cpp/src/IceDiscovery/LookupI.h
@@ -13,6 +13,7 @@
#include <IceDiscovery/IceDiscovery.h>
#include <IceDiscovery/LocatorI.h>
+#include <IceUtil/Timer.h>
#include <Ice/Properties.h>
namespace IceDiscovery
diff --git a/cpp/src/IceGrid/AdapterCache.h b/cpp/src/IceGrid/AdapterCache.h
index 8c37a623def..78258c2ff54 100644
--- a/cpp/src/IceGrid/AdapterCache.h
+++ b/cpp/src/IceGrid/AdapterCache.h
@@ -16,6 +16,8 @@
#include <IceGrid/Query.h>
#include <IceGrid/Internal.h>
+#include <set>
+
namespace IceGrid
{
diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp
index 5bf6c662656..57f3337c06f 100644
--- a/cpp/src/slice2cpp/Gen.cpp
+++ b/cpp/src/slice2cpp/Gen.cpp
@@ -373,8 +373,7 @@ Slice::Gen::generate(const UnitPtr& p)
{
H << "\n#include <Ice/Proxy.h>";
H << "\n#include <Ice/GCObject.h>";
- H << "\n#include <Ice/Outgoing.h>";
- H << "\n#include <Ice/OutgoingAsync.h>";
+ H << "\n#include <Ice/AsyncResult.h>";
H << "\n#include <Ice/Incoming.h>";
if(p->hasContentsWithMetaData("amd"))
{
@@ -382,11 +381,14 @@ Slice::Gen::generate(const UnitPtr& p)
}
C << "\n#include <Ice/LocalException.h>";
C << "\n#include <Ice/ObjectFactory.h>";
+ C << "\n#include <Ice/Outgoing.h>";
+ C << "\n#include <Ice/OutgoingAsync.h>";
}
else if(p->hasLocalClassDefsWithAsync())
{
H << "\n#include <Ice/Proxy.h>";
- H << "\n#include <Ice/OutgoingAsync.h>";
+ H << "\n#include <Ice/AsyncResult.h>";
+ C << "\n#include <Ice/OutgoingAsync.h>";
}
else if(p->hasNonLocalClassDecls())
{
@@ -2184,26 +2186,26 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p)
C << flatName << ", __del, __cookie);";
C << nl << "try";
C << sb;
- C << nl << "__result->__prepare(" << flatName << ", " << operationModeToString(p->sendMode()) << ", __ctx);";
+ C << nl << "__result->prepare(" << flatName << ", " << operationModeToString(p->sendMode()) << ", __ctx);";
if(inParams.empty())
{
- C << nl << "__result->__writeEmptyParams();";
+ C << nl << "__result->writeEmptyParams();";
}
else
{
- C << nl << "::IceInternal::BasicStream* __os = __result->__startWriteParams(" << opFormatTypeToString(p) <<");";
+ C << nl << "::IceInternal::BasicStream* __os = __result->startWriteParams(" << opFormatTypeToString(p) <<");";
writeMarshalCode(C, inParams, 0, TypeContextInParam);
if(p->sendsClasses(false))
{
C << nl << "__os->writePendingObjects();";
}
- C << nl << "__result->__endWriteParams();";
+ C << nl << "__result->endWriteParams();";
}
- C << nl << "__result->__invoke(true);";
+ C << nl << "__result->invoke();";
C << eb;
C << nl << "catch(const ::Ice::Exception& __ex)";
C << sb;
- C << nl << "__result->__invokeExceptionAsync(__ex);";
+ C << nl << "__result->abort(__ex);";
C << eb;
C << nl << "return __result;";
C << eb;
diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp
index b877d04ce69..8ba2d479750 100644
--- a/cpp/src/slice2cs/Gen.cpp
+++ b/cpp/src/slice2cs/Gen.cpp
@@ -5312,8 +5312,8 @@ Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p)
_out << sb;
if(op->returnsData())
{
- _out << nl << "IceInternal.OutgoingAsync outAsync__ = (IceInternal.OutgoingAsync)r__;";
- _out << nl << "IceInternal.OutgoingAsync.check(outAsync__, this, " << flatName << ");";
+ _out << nl << "IceInternal.OutgoingAsync outAsync__ = IceInternal.OutgoingAsync.check(r__, this, "
+ << flatName << ");";
_out << nl << "try";
_out << sb;
@@ -5480,11 +5480,11 @@ Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p)
_out << nl << "result__.writeEmptyParams();";
}
- _out << nl << "result__.invoke(true);";
+ _out << nl << "result__.invoke();";
_out << eb;
_out << nl << "catch(Ice.Exception ex__)";
_out << sb;
- _out << nl << "result__.invokeExceptionAsync(ex__);";
+ _out << nl << "result__.abort(ex__);";
_out << eb;
_out << nl << "return result__;";
_out << eb;
diff --git a/cpp/src/slice2java/Gen.cpp b/cpp/src/slice2java/Gen.cpp
index a288cfd8290..8eaccb5650e 100644
--- a/cpp/src/slice2java/Gen.cpp
+++ b/cpp/src/slice2java/Gen.cpp
@@ -4752,8 +4752,8 @@ Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p)
out << sb;
if(op->returnsData())
{
- out << nl << "IceInternal.OutgoingAsyncBase __result = (IceInternal.OutgoingAsyncBase)__iresult;";
- out << nl << "IceInternal.OutgoingAsyncBase.check(__result, this, __" << op->name() << "_name);";
+ out << nl << "IceInternal.OutgoingAsync __result = IceInternal.OutgoingAsync.check(__iresult, this, __"
+ << op->name() << "_name);";
out << nl << "try";
out << sb;
@@ -5737,11 +5737,11 @@ Slice::Gen::HelperVisitor::writeOperation(const ClassDefPtr& p, const string& pa
out << nl << "__result.writeEmptyParams();";
}
- out << nl << "__result.invoke(true);";
+ out << nl << "__result.invoke();";
out << eb;
out << nl << "catch(Ice.Exception __ex)";
out << sb;
- out << nl << "__result.invokeExceptionAsync(__ex);";
+ out << nl << "__result.abort(__ex);";
out << eb;
out << nl << "return __result;";
out << eb;
diff --git a/cpp/test/Ice/ami/AllTests.cpp b/cpp/test/Ice/ami/AllTests.cpp
index c164220c2ae..406461975b7 100644
--- a/cpp/test/Ice/ami/AllTests.cpp
+++ b/cpp/test/Ice/ami/AllTests.cpp
@@ -1983,6 +1983,14 @@ allTests(const Ice::CommunicatorPtr& communicator, bool collocated)
test(r->isSent());
test(r->isCompleted());
test(p->waitForBatch(2));
+
+ // Ensure it also works with a twoway proxy
+ cb = new FlushCallback();
+ r = p->ice_getConnection()->begin_flushBatchRequests(
+ Ice::newCallback(cb, &FlushCallback::completedAsync, &FlushCallback::sentAsync));
+ cb->check();
+ test(r->isSent());
+ test(r->isCompleted());
}
{
@@ -2657,6 +2665,73 @@ allTests(const Ice::CommunicatorPtr& communicator, bool collocated)
communicator->end_flushBatchRequests(r);
}
}
+
+ if(p->ice_getConnection())
+ {
+ testController->holdAdapter();
+
+ Ice::AsyncResultPtr r;
+ Ice::ByteSeq seq;
+ seq.resize(1024); // Make sure the request doesn't compress too well.
+ for(Ice::ByteSeq::iterator q = seq.begin(); q != seq.end(); ++q)
+ {
+ *q = static_cast<Ice::Byte>(IceUtilInternal::random(255));
+ }
+ while((r = p->begin_opWithPayload(seq))->sentSynchronously());
+
+ test(!r->isSent());
+
+ Ice::AsyncResultPtr r1 = p->begin_ice_ping();
+ Ice::AsyncResultPtr r2 = p->begin_ice_id();
+ r1->cancel();
+ r2->cancel();
+ try
+ {
+ p->end_ice_ping(r1);
+ test(false);
+ }
+ catch(const Ice::InvocationCanceledException&)
+ {
+ }
+ try
+ {
+ p->end_ice_id(r2);
+ test(false);
+ }
+ catch(const Ice::InvocationCanceledException&)
+ {
+ }
+
+ testController->resumeAdapter();
+ p->ice_ping();
+ test(!r1->isSent() && r1->isCompleted());
+ test(!r2->isSent() && r2->isCompleted());
+
+ testController->holdAdapter();
+ r1 = p->begin_op();
+ r2 = p->begin_ice_id();
+ r1->waitForSent();
+ r2->waitForSent();
+ r1->cancel();
+ r2->cancel();
+ try
+ {
+ p->end_op(r1);
+ test(false);
+ }
+ catch(const Ice::InvocationCanceledException&)
+ {
+ }
+ try
+ {
+ p->end_ice_id(r2);
+ test(false);
+ }
+ catch(const Ice::InvocationCanceledException&)
+ {
+ }
+ testController->resumeAdapter();
+ }
}
cout << "ok" << endl;
diff --git a/cpp/test/Ice/retry/AllTests.cpp b/cpp/test/Ice/retry/AllTests.cpp
index 8722e3aa32c..3df2727cfd3 100644
--- a/cpp/test/Ice/retry/AllTests.cpp
+++ b/cpp/test/Ice/retry/AllTests.cpp
@@ -112,7 +112,7 @@ allTests(const Ice::CommunicatorPtr& communicator)
retry1->op(false);
cout << "ok" << endl;
- int invocationCount = 3;
+ testInvocationCount(3);
cout << "calling operation to kill connection with second proxy... " << flush;
try
@@ -127,15 +127,15 @@ allTests(const Ice::CommunicatorPtr& communicator)
catch(const Ice::ConnectionLostException&)
{
}
- testInvocationCount(invocationCount + 1);
+ testInvocationCount(1);
testFailureCount(1);
testRetryCount(0);
cout << "ok" << endl;
cout << "calling regular operation with first proxy again... " << flush;
retry1->op(false);
- testInvocationCount(invocationCount + 2);
- testFailureCount(1);
+ testInvocationCount(1);
+ testFailureCount(0);
testRetryCount(0);
cout << "ok" << endl;
@@ -145,66 +145,66 @@ allTests(const Ice::CommunicatorPtr& communicator)
cout << "calling regular AMI operation with first proxy... " << flush;
retry1->begin_op(false, newCallback_Retry_op(cb1, &CallbackSuccess::response, &CallbackSuccess::exception));
cb1->check();
- testInvocationCount(invocationCount + 3);
- testFailureCount(1);
+ testInvocationCount(1);
+ testFailureCount(0);
testRetryCount(0);
cout << "ok" << endl;
cout << "calling AMI operation to kill connection with second proxy... " << flush;
retry2->begin_op(true, newCallback_Retry_op(cb2, &CallbackFail::response, &CallbackFail::exception));
cb2->check();
- testInvocationCount(invocationCount + 4);
- testFailureCount(2);
+ testInvocationCount(1);
+ testFailureCount(1);
testRetryCount(0);
cout << "ok" << endl;
cout << "calling regular AMI operation with first proxy again... " << flush;
retry1->begin_op(false, newCallback_Retry_op(cb1, &CallbackSuccess::response, &CallbackSuccess::exception));
cb1->check();
- testInvocationCount(invocationCount + 5);
- testFailureCount(2);
+ testInvocationCount(1);
+ testFailureCount(0);
testRetryCount(0);
cout << "ok" << endl;
cout << "testing idempotent operation... " << flush;
- test(retry1->opIdempotent(0) == 4);
- testInvocationCount(invocationCount + 6);
- testFailureCount(2);
+ test(retry1->opIdempotent(4) == 4);
+ testInvocationCount(1);
+ testFailureCount(0);
+ testRetryCount(4);
+ test(retry1->end_opIdempotent(retry1->begin_opIdempotent(4)) == 4);
+ testInvocationCount(1);
+ testFailureCount(0);
testRetryCount(4);
- test(retry1->end_opIdempotent(retry1->begin_opIdempotent(4)) == 8);
- testInvocationCount(invocationCount + 7);
- testFailureCount(2);
- testRetryCount(8);
cout << "ok" << endl;
cout << "testing non-idempotent operation... " << flush;
try
{
- retry1->opNotIdempotent(8);
+ retry1->opNotIdempotent();
test(false);
}
catch(const Ice::LocalException&)
{
}
- testInvocationCount(invocationCount + 8);
- testFailureCount(3);
- testRetryCount(8);
+ testInvocationCount(1);
+ testFailureCount(1);
+ testRetryCount(0);
try
{
- retry1->end_opNotIdempotent(retry1->begin_opNotIdempotent(9));
+ retry1->end_opNotIdempotent(retry1->begin_opNotIdempotent());
test(false);
}
catch(const Ice::LocalException&)
{
}
- testInvocationCount(invocationCount + 9);
- testFailureCount(4);
- testRetryCount(8);
+ testInvocationCount(1);
+ testFailureCount(1);
+ testRetryCount(0);
cout << "ok" << endl;
if(!retry1->ice_getConnection())
{
- invocationCount = invocationCount + 10;
+ testInvocationCount(-1);
cout << "testing system exception... " << flush;
try
{
@@ -214,9 +214,9 @@ allTests(const Ice::CommunicatorPtr& communicator)
catch(const SystemFailure&)
{
}
- test(invocationCount + 1);
- testFailureCount(5);
- testRetryCount(8);
+ testInvocationCount(1);
+ testFailureCount(1);
+ testRetryCount(0);
try
{
retry1->end_opSystemException(retry1->begin_opSystemException());
@@ -225,11 +225,38 @@ allTests(const Ice::CommunicatorPtr& communicator)
catch(const SystemFailure&)
{
}
- testInvocationCount(invocationCount + 2);
- testFailureCount(6);
- testRetryCount(8);
+ testInvocationCount(1);
+ testFailureCount(1);
+ testRetryCount(0);
cout << "ok" << endl;
}
+ cout << "testing invocation timeout and retries... " << flush;
+ try
+ {
+ retry1->ice_invocationTimeout(50)->opIdempotent(4); // No more than 2 retries before timeout kicks-in
+ test(false);
+ }
+ catch(const Ice::InvocationTimeoutException&)
+ {
+ testRetryCount(2);
+ retry1->opIdempotent(-1); // Reset the counter
+ testRetryCount(-1);
+ }
+ try
+ {
+ // No more than 2 retries before timeout kicks-in
+ RetryPrx prx = retry1->ice_invocationTimeout(50);
+ prx->end_opIdempotent(prx->begin_opIdempotent(4));
+ test(false);
+ }
+ catch(const Ice::InvocationTimeoutException&)
+ {
+ testRetryCount(2);
+ retry1->opIdempotent(-1);
+ testRetryCount(-1);
+ }
+ cout << "ok" << endl;
+
return retry1;
}
diff --git a/cpp/test/Ice/retry/Client.cpp b/cpp/test/Ice/retry/Client.cpp
index 5b877b2c1a9..53bed9b8c2f 100644
--- a/cpp/test/Ice/retry/Client.cpp
+++ b/cpp/test/Ice/retry/Client.cpp
@@ -38,7 +38,7 @@ main(int argc, char* argv[])
initData.properties = Ice::createProperties(argc, argv);
initData.observer = getObserver();
- initData.properties->setProperty("Ice.RetryIntervals", "0 10 20 30");
+ initData.properties->setProperty("Ice.RetryIntervals", "0 1 100 1");
//
// This test kills connections, so we don't want warnings.
diff --git a/cpp/test/Ice/retry/Collocated.cpp b/cpp/test/Ice/retry/Collocated.cpp
index 8bb1be3b5ca..46729831b47 100644
--- a/cpp/test/Ice/retry/Collocated.cpp
+++ b/cpp/test/Ice/retry/Collocated.cpp
@@ -45,7 +45,7 @@ main(int argc, char* argv[])
initData.properties = Ice::createProperties(argc, argv);
initData.observer = getObserver();
- initData.properties->setProperty("Ice.RetryIntervals", "0 10 20 30");
+ initData.properties->setProperty("Ice.RetryIntervals", "0 1 100 1");
//
// This test kills connections, so we don't want warnings.
diff --git a/cpp/test/Ice/retry/InstrumentationI.cpp b/cpp/test/Ice/retry/InstrumentationI.cpp
index a39a2804b38..f60ba5706c9 100644
--- a/cpp/test/Ice/retry/InstrumentationI.cpp
+++ b/cpp/test/Ice/retry/InstrumentationI.cpp
@@ -143,6 +143,12 @@ Ice::Instrumentation::CommunicatorObserverPtr communicatorObserver = new Communi
void
testEqual(int& value, int expected)
{
+ if(expected < 0)
+ {
+ value = 0;
+ return;
+ }
+
int retry = 0;
while(++retry < 100)
{
@@ -160,6 +166,7 @@ testEqual(int& value, int expected)
std::cerr << "value = " << value << ", expected = " << expected << std::endl;
test(false);
}
+ value = 0;
}
}
diff --git a/cpp/test/Ice/retry/Test.ice b/cpp/test/Ice/retry/Test.ice
index 61297d94557..cd8c2595796 100644
--- a/cpp/test/Ice/retry/Test.ice
+++ b/cpp/test/Ice/retry/Test.ice
@@ -17,10 +17,10 @@ interface Retry
void op(bool kill);
idempotent int opIdempotent(int c);
- void opNotIdempotent(int c);
+ void opNotIdempotent();
void opSystemException();
- void shutdown();
+ idempotent void shutdown();
};
};
diff --git a/cpp/test/Ice/retry/TestI.cpp b/cpp/test/Ice/retry/TestI.cpp
index b3545fa4c7a..9a0ed3fc81d 100644
--- a/cpp/test/Ice/retry/TestI.cpp
+++ b/cpp/test/Ice/retry/TestI.cpp
@@ -11,13 +11,6 @@
#include <TestI.h>
#include <SystemFailure.h>
-namespace
-{
-
-const int nRetry = 4; // See Ice.RetryIntervals configuration in Client.cpp/Collocated.cpp
-
-}
-
RetryI::RetryI() : _counter(0)
{
}
@@ -39,9 +32,15 @@ RetryI::op(bool kill, const Ice::Current& current)
}
int
-RetryI::opIdempotent(int counter, const Ice::Current& current)
+RetryI::opIdempotent(int nRetry, const Ice::Current& current)
{
- if(counter + nRetry > _counter)
+ if(nRetry < 0)
+ {
+ _counter = 0;
+ return 0;
+ }
+
+ if(nRetry > _counter)
{
++_counter;
if(current.con)
@@ -52,19 +51,16 @@ RetryI::opIdempotent(int counter, const Ice::Current& current)
{
throw Ice::ConnectionLostException(__FILE__, __LINE__);
}
+ return 0;
}
- return _counter;
+ int counter = _counter;
+ _counter = 0;
+ return counter;
}
void
-RetryI::opNotIdempotent(int counter, const Ice::Current& current)
+RetryI::opNotIdempotent(const Ice::Current& current)
{
- if(_counter != counter)
- {
- return;
- }
-
- ++_counter;
if(current.con)
{
current.con->close(true);
diff --git a/cpp/test/Ice/retry/TestI.h b/cpp/test/Ice/retry/TestI.h
index 24405acbf99..c049fadfbd6 100644
--- a/cpp/test/Ice/retry/TestI.h
+++ b/cpp/test/Ice/retry/TestI.h
@@ -20,7 +20,7 @@ public:
virtual void op(bool, const Ice::Current&);
virtual int opIdempotent(int, const Ice::Current&);
- virtual void opNotIdempotent(int, const Ice::Current&);
+ virtual void opNotIdempotent(const Ice::Current&);
virtual void opSystemException(const Ice::Current&);
virtual void shutdown(const Ice::Current&);
diff --git a/cs/src/Ice/AsyncResult.cs b/cs/src/Ice/AsyncResult.cs
new file mode 100644
index 00000000000..e8db66e4b0d
--- /dev/null
+++ b/cs/src/Ice/AsyncResult.cs
@@ -0,0 +1,701 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+namespace Ice
+{
+ ///
+ /// <summary>
+ /// Callback that requires the application to down-cast the proxy.
+ /// </summary>
+ ///
+ public delegate void AsyncCallback(AsyncResult r);
+
+ ///
+ /// <summary>
+ /// Callback for the successful completion of an operation
+ /// that returns no data.
+ /// </summary>
+ ///
+ public delegate void OnewayCallback();
+
+ ///
+ /// <summary>
+ /// Callback for the successful completion of an operation
+ /// that returns no data.
+ /// </summary>
+ ///
+ public delegate void SentCallback(bool sentSynchronously);
+
+ ///
+ /// <summary>
+ /// Called when an invocation raises an exception.
+ /// </summary>
+ ///
+ public delegate void ExceptionCallback(Ice.Exception ex);
+
+ ///
+ /// <summary>
+ /// <!-- TODO -->
+ /// </summary>
+ public interface AsyncResult : System.IAsyncResult
+ {
+ void cancel();
+
+ Ice.Communicator getCommunicator();
+
+ Ice.Connection getConnection();
+
+ ObjectPrx getProxy();
+
+ bool isCompleted_();
+ void waitForCompleted();
+
+ bool isSent();
+ void waitForSent();
+
+ void throwLocalException();
+
+ bool sentSynchronously();
+
+ string getOperation();
+
+ AsyncResult whenSent(Ice.AsyncCallback cb);
+ AsyncResult whenSent(Ice.SentCallback cb);
+
+ AsyncResult whenCompleted(Ice.ExceptionCallback excb);
+ }
+
+ public interface AsyncResult<T> : AsyncResult
+ {
+ AsyncResult<T> whenCompleted(T cb, Ice.ExceptionCallback excb);
+
+ new AsyncResult<T> whenCompleted(Ice.ExceptionCallback excb);
+ new AsyncResult<T> whenSent(Ice.SentCallback cb);
+ }
+}
+
+namespace IceInternal
+{
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Threading;
+
+ public delegate void ProxyTwowayCallback<T>(Ice.AsyncResult result, T cb, Ice.ExceptionCallback excb);
+ public delegate void ProxyOnewayCallback<T>(T cb);
+
+ public class AsyncResultI : Ice.AsyncResult
+ {
+ public virtual void cancel()
+ {
+ cancel(new Ice.InvocationCanceledException());
+ }
+
+ public Ice.Communicator getCommunicator()
+ {
+ return _communicator;
+ }
+
+ public virtual Ice.Connection getConnection()
+ {
+ return null;
+ }
+
+ public virtual Ice.ObjectPrx getProxy()
+ {
+ return null;
+ }
+
+ public bool isCompleted_()
+ {
+ lock(this)
+ {
+ return (state_ & StateDone) != 0;
+ }
+ }
+
+ public void waitForCompleted()
+ {
+ lock(this)
+ {
+ while((state_ & StateDone) == 0)
+ {
+ System.Threading.Monitor.Wait(this);
+ }
+ }
+ }
+
+ public bool isSent()
+ {
+ lock(this)
+ {
+ return (state_ & StateSent) != 0;
+ }
+ }
+
+ public void waitForSent()
+ {
+ lock(this)
+ {
+ while((state_ & StateSent) == 0 && _exception == null)
+ {
+ System.Threading.Monitor.Wait(this);
+ }
+ }
+ }
+
+ public void throwLocalException()
+ {
+ lock(this)
+ {
+ if(_exception != null)
+ {
+ throw _exception;
+ }
+ }
+ }
+
+ public bool sentSynchronously()
+ {
+ return sentSynchronously_; // No lock needed
+ }
+
+ //
+ // Implementation of System.IAsyncResult properties
+ //
+
+ public bool IsCompleted
+ {
+ get
+ {
+ return isCompleted_();
+ }
+ }
+
+ public bool CompletedSynchronously
+ {
+ get
+ {
+ if(getProxy() != null && getProxy().ice_isTwoway())
+ {
+ return false;
+ }
+ return sentSynchronously_;
+ }
+ }
+
+ public object AsyncState
+ {
+ get
+ {
+ return _cookie; // No lock needed, cookie is immutable.
+ }
+ }
+
+ public WaitHandle AsyncWaitHandle
+ {
+ get
+ {
+ lock(this)
+ {
+ if(_waitHandle == null)
+ {
+#if SILVERLIGHT
+ _waitHandle = new ManualResetEvent(false);
+#else
+ _waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
+#endif
+ }
+ if((state_ & StateDone) != 0)
+ {
+ _waitHandle.Set();
+ }
+ return _waitHandle;
+ }
+ }
+ }
+
+ public Ice.AsyncResult whenSent(Ice.AsyncCallback cb)
+ {
+ lock(this)
+ {
+ if(cb == null)
+ {
+ throw new System.ArgumentException("callback is null");
+ }
+ if(_sentCallback != null)
+ {
+ throw new System.ArgumentException("sent callback already set");
+ }
+ _sentCallback = cb;
+ if((state_ & StateSent) == 0)
+ {
+ return this;
+ }
+ }
+
+ if(sentSynchronously_)
+ {
+ try
+ {
+ _sentCallback(this);
+ }
+ catch(System.Exception ex)
+ {
+ warning(ex);
+ }
+ }
+ else
+ {
+ instance_.clientThreadPool().dispatch(() =>
+ {
+ try
+ {
+ _sentCallback(this);
+ }
+ catch(System.Exception ex)
+ {
+ warning(ex);
+ }
+ }, cachedConnection_);
+ }
+ return this;
+ }
+
+ public Ice.AsyncResult whenSent(Ice.SentCallback cb)
+ {
+ lock(this)
+ {
+ if(cb == null)
+ {
+ throw new System.ArgumentException("callback is null");
+ }
+ if(_sentCallback != null)
+ {
+ throw new System.ArgumentException("sent callback already set");
+ }
+ _sentCallback = (Ice.AsyncResult result) =>
+ {
+ cb(result.sentSynchronously());
+ };
+ if((state_ & StateSent) == 0)
+ {
+ return this;
+ }
+ }
+
+ if(sentSynchronously_)
+ {
+ try
+ {
+ cb(true);
+ }
+ catch(System.Exception ex)
+ {
+ warning(ex);
+ }
+ }
+ else
+ {
+ instance_.clientThreadPool().dispatch(() =>
+ {
+ try
+ {
+ cb(false);
+ }
+ catch(System.Exception ex)
+ {
+ warning(ex);
+ }
+ }, cachedConnection_);
+ }
+ return this;
+ }
+
+ public Ice.AsyncResult whenCompletedWithAsyncCallback(Ice.AsyncCallback cb)
+ {
+ setCompletedCallback(cb);
+ return this;
+ }
+
+ public Ice.AsyncResult whenCompleted(Ice.ExceptionCallback cb)
+ {
+ if(cb == null)
+ {
+ throw new System.ArgumentException("callback is null");
+ }
+ lock(this)
+ {
+ if(exceptionCallback_ != null)
+ {
+ throw new System.ArgumentException("callback already set");
+ }
+ exceptionCallback_ = cb;
+ }
+ setCompletedCallback(getCompletedCallback());
+ return this;
+ }
+
+ public string getOperation()
+ {
+ return _operation;
+ }
+
+ public void invokeSent(Ice.AsyncCallback cb)
+ {
+ Debug.Assert(cb != null);
+ try
+ {
+ cb(this);
+ }
+ catch(System.Exception ex)
+ {
+ warning(ex);
+ }
+
+ if(observer_ != null)
+ {
+ Ice.ObjectPrx proxy = getProxy();
+ if(proxy == null || !proxy.ice_isTwoway())
+ {
+ observer_.detach();
+ observer_ = null;
+ }
+ }
+ }
+
+ public void invokeCompleted(Ice.AsyncCallback cb)
+ {
+ Debug.Assert(cb != null);
+ try
+ {
+ cb(this);
+ }
+ catch(System.Exception ex)
+ {
+ warning(ex);
+ }
+
+ if(observer_ != null)
+ {
+ observer_.detach();
+ observer_ = null;
+ }
+ }
+
+ public void invokeCompletedAsync(Ice.AsyncCallback cb)
+ {
+ //
+ // This is called when it's not safe to call the exception callback synchronously
+ // from this thread. Instead the exception callback is called asynchronously from
+ // the client thread pool.
+ //
+ Debug.Assert(cb != null);
+
+ // CommunicatorDestroyedException is the only exception that can propagate directly.
+ instance_.clientThreadPool().dispatch(() =>
+ {
+ invokeCompleted(cb);
+ }, cachedConnection_);
+ }
+
+ public void cancelable(CancellationHandler handler)
+ {
+ lock(this)
+ {
+ if(_cancellationException == null)
+ {
+ _cancellationHandler = handler;
+ return;
+ }
+ }
+ handler.asyncRequestCanceled((OutgoingAsyncBase)this, _cancellationException);
+ }
+
+ public bool wait()
+ {
+ lock(this)
+ {
+ if((state_ & StateEndCalled) != 0)
+ {
+ throw new System.ArgumentException("end_ method called more than once");
+ }
+ state_ |= StateEndCalled;
+ while((state_ & StateDone) == 0)
+ {
+ System.Threading.Monitor.Wait(this);
+ }
+ if(_exception != null)
+ {
+ throw _exception;
+ }
+ return (state_ & StateOK) != 0;
+ }
+ }
+
+ public virtual void cacheMessageBuffers()
+ {
+ }
+
+ protected AsyncResultI(Ice.Communicator communicator, Instance instance, string op, object cookie)
+ {
+ instance_ = instance;
+ sentSynchronously_ = false;
+ state_ = 0;
+
+ _communicator = communicator;
+ _operation = op;
+ _exception = null;
+ _cookie = cookie;
+ }
+
+ protected Ice.AsyncCallback sent(bool done)
+ {
+ lock(this)
+ {
+ Debug.Assert(_exception == null);
+
+ bool alreadySent = (state_ & StateSent) != 0;
+ state_ |= StateSent;
+ if(done)
+ {
+ state_ |= StateDone | StateOK;
+ _cancellationHandler = null;
+ if(observer_ != null && _sentCallback == null)
+ {
+ observer_.detach();
+ observer_ = null;
+ }
+
+ //
+ // For oneway requests after the data has been sent
+ // the buffers can be reused unless this is a
+ // collocated invocation. For collocated invocations
+ // the buffer won't be reused because it has already
+ // been marked as cached in invokeCollocated.
+ //
+ cacheMessageBuffers();
+ }
+ if(_waitHandle != null)
+ {
+ _waitHandle.Set();
+ }
+ System.Threading.Monitor.PulseAll(this);
+ return !alreadySent ? _sentCallback : null;
+ }
+ }
+
+ protected Ice.AsyncCallback finished(bool ok)
+ {
+ lock(this)
+ {
+ state_ |= StateDone;
+ if(ok)
+ {
+ state_ |= StateOK;
+ }
+ _cancellationHandler = null;
+ if(_completedCallback == null)
+ {
+ if(observer_ != null)
+ {
+ observer_.detach();
+ observer_ = null;
+ }
+ }
+ if(_waitHandle != null)
+ {
+ _waitHandle.Set();
+ }
+ System.Threading.Monitor.PulseAll(this);
+ return _completedCallback;
+ }
+ }
+
+ protected Ice.AsyncCallback finished(Ice.Exception ex)
+ {
+ lock(this)
+ {
+ state_ |= StateDone;
+ _exception = ex;
+ _cancellationHandler = null;
+ if(observer_ != null)
+ {
+ observer_.failed(ex.ice_name());
+ }
+ if(_completedCallback == null)
+ {
+ if(observer_ != null)
+ {
+ observer_.detach();
+ observer_ = null;
+ }
+ }
+ if(_waitHandle != null)
+ {
+ _waitHandle.Set();
+ }
+ System.Threading.Monitor.PulseAll(this);
+ return _completedCallback;
+ }
+ }
+
+ protected void invokeSentAsync(Ice.AsyncCallback cb)
+ {
+ //
+ // This is called when it's not safe to call the exception callback synchronously
+ // from this thread. Instead the exception callback is called asynchronously from
+ // the client thread pool.
+ //
+ Debug.Assert(cb != null);
+ try
+ {
+ instance_.clientThreadPool().dispatch(() =>
+ {
+ invokeSent(cb);
+ }, cachedConnection_);
+ }
+ catch(Ice.CommunicatorDestroyedException)
+ {
+ }
+ }
+
+ protected void setCompletedCallback(Ice.AsyncCallback cb)
+ {
+ lock(this)
+ {
+ if(cb == null)
+ {
+ throw new System.ArgumentException("callback is null");
+ }
+ if(_completedCallback != null)
+ {
+ throw new System.ArgumentException("callback already set");
+ }
+ _completedCallback = cb;
+ if((state_ & StateDone) == 0)
+ {
+ return;
+ }
+ else if((getProxy() == null || !getProxy().ice_isTwoway()) && _exception == null)
+ {
+ return;
+ }
+ }
+
+ instance_.clientThreadPool().dispatch(() =>
+ {
+ try
+ {
+ cb(this);
+ }
+ catch(System.Exception ex)
+ {
+ warning(ex);
+ }
+ }, cachedConnection_);
+ }
+
+ protected virtual Ice.AsyncCallback getCompletedCallback()
+ {
+ return (Ice.AsyncResult result) =>
+ {
+ Debug.Assert(exceptionCallback_ != null);
+ try
+ {
+ ((AsyncResultI)result).wait();
+ }
+ catch(Ice.Exception ex)
+ {
+ exceptionCallback_(ex);
+ return;
+ }
+ };
+ }
+
+ protected void cancel(Ice.LocalException ex)
+ {
+ lock(this)
+ {
+ _cancellationException = ex;
+ if(_cancellationHandler == null)
+ {
+ return;
+ }
+ }
+ _cancellationHandler.asyncRequestCanceled((OutgoingAsyncBase)this, ex);
+ }
+
+ protected void checkCanceled()
+ {
+ lock(this)
+ {
+ if(_cancellationException != null)
+ {
+ throw _cancellationException;
+ }
+ }
+ }
+
+ protected virtual Ice.Instrumentation.InvocationObserver getObserver()
+ {
+ return observer_;
+ }
+
+ protected static T check<T>(Ice.AsyncResult r, string operation)
+ {
+ if(r == null)
+ {
+ throw new System.ArgumentException("AsyncResult == null");
+ }
+ if(r.getOperation() != operation)
+ {
+ throw new System.ArgumentException("Incorrect operation for end_" + operation + " method: " +
+ r.getOperation());
+ }
+ if(!(r is T))
+ {
+ throw new System.ArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ return (T)r;
+ }
+
+ protected void warning(System.Exception ex)
+ {
+ if(instance_.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0)
+ {
+ instance_.initializationData().logger.warning("exception raised by AMI callback:\n" + ex);
+ }
+ }
+
+ protected IceInternal.Instance instance_;
+ protected Ice.Instrumentation.InvocationObserver observer_;
+ protected Ice.Connection cachedConnection_;
+ protected bool sentSynchronously_;
+
+ private readonly Ice.Communicator _communicator;
+ private readonly string _operation;
+ private readonly object _cookie;
+ private Ice.Exception _exception;
+ private EventWaitHandle _waitHandle;
+
+ private CancellationHandler _cancellationHandler;
+ private Ice.LocalException _cancellationException;
+
+ private Ice.AsyncCallback _completedCallback;
+ private Ice.AsyncCallback _sentCallback;
+ protected Ice.ExceptionCallback exceptionCallback_;
+
+ protected const int StateOK = 0x1;
+ protected const int StateDone = 0x2;
+ protected const int StateSent = 0x4;
+ protected const int StateEndCalled = 0x8;
+ protected const int StateCachedBuffers = 0x10;
+ protected int state_;
+ }
+}
diff --git a/cs/src/Ice/CollocatedRequestHandler.cs b/cs/src/Ice/CollocatedRequestHandler.cs
index a53801b98fc..632934a7d33 100644
--- a/cs/src/Ice/CollocatedRequestHandler.cs
+++ b/cs/src/Ice/CollocatedRequestHandler.cs
@@ -165,12 +165,12 @@ namespace IceInternal
}
}
- public bool sendAsyncRequest(OutgoingAsyncMessageCallback outAsync, out Ice.AsyncCallback sentCallback)
+ public bool sendAsyncRequest(OutgoingAsyncBase outAsync, out Ice.AsyncCallback sentCallback)
{
return outAsync.invokeCollocated(this, out sentCallback);
}
- public void asyncRequestCanceled(OutgoingAsyncMessageCallback outAsync, Ice.LocalException ex)
+ public void asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex)
{
lock(this)
{
@@ -182,8 +182,12 @@ namespace IceInternal
_asyncRequests.Remove(requestId);
}
_sendAsyncRequests.Remove(outAsync);
- outAsync.dispatchInvocationCancel(ex, _reference.getInstance().clientThreadPool(), null);
- return; // We're done
+ Ice.AsyncCallback cb = outAsync.completed(ex);
+ if(cb != null)
+ {
+ outAsync.invokeCompletedAsync(cb);
+ }
+ return;
}
if(outAsync is OutgoingAsync)
{
@@ -194,8 +198,12 @@ namespace IceInternal
if(e.Value == o)
{
_asyncRequests.Remove(e.Key);
- outAsync.dispatchInvocationCancel(ex, _reference.getInstance().clientThreadPool(), null);
- return; // We're done
+ Ice.AsyncCallback cb = outAsync.completed(ex);
+ if(cb != null)
+ {
+ outAsync.invokeCompletedAsync(cb);
+ }
+ return;
}
}
}
@@ -204,7 +212,8 @@ namespace IceInternal
public void sendResponse(int requestId, BasicStream os, byte status)
{
- OutgoingAsync outAsync = null;
+ Ice.AsyncCallback cb = null;
+ OutgoingAsync outAsync;
lock(this)
{
Debug.Assert(_response);
@@ -219,18 +228,15 @@ namespace IceInternal
if(_asyncRequests.TryGetValue(requestId, out outAsync))
{
- os.swap(outAsync.istr__);
_asyncRequests.Remove(requestId);
+ outAsync.getIs().swap(os);
+ cb = outAsync.completed();
}
}
- if(outAsync != null)
+ if(cb != null)
{
- Ice.AsyncCallback cb = outAsync.finished();
- if(cb != null)
- {
- outAsync.invokeCompleted(cb);
- }
+ outAsync.invokeCompleted(cb);
}
_adapter.decDirectCount();
}
@@ -252,21 +258,7 @@ namespace IceInternal
public void
invokeException(int requestId, Ice.LocalException ex, int invokeNum)
{
- if(requestId > 0)
- {
- OutgoingAsync outAsync = null;
- lock(this)
- {
- if(_asyncRequests.TryGetValue(requestId, out outAsync))
- {
- _asyncRequests.Remove(requestId);
- }
- }
- if(outAsync != null)
- {
- outAsync.finished(ex);
- }
- }
+ handleException(requestId, ex);
_adapter.decDirectCount();
}
@@ -288,7 +280,7 @@ namespace IceInternal
return null;
}
- public void invokeAsyncRequest(OutgoingAsync outAsync, bool synchronous, out Ice.AsyncCallback sentCallback)
+ public bool invokeAsyncRequest(OutgoingAsync outAsync, bool synchronous, out Ice.AsyncCallback sentCallback)
{
int requestId = 0;
if(_reference.getInvocationTimeout() > 0 || _response)
@@ -304,6 +296,7 @@ namespace IceInternal
{
_sendAsyncRequests.Add(outAsync, requestId);
}
+ outAsync.cancelable(this);
}
}
@@ -321,7 +314,7 @@ namespace IceInternal
{
if(sentAsync(outAsync))
{
- invokeAll(outAsync.ostr__, requestId, 1, false);
+ invokeAll(outAsync.getOs(), requestId, 1, false);
}
}, null);
}
@@ -331,7 +324,7 @@ namespace IceInternal
{
if(sentAsync(outAsync))
{
- invokeAll(outAsync.ostr__, requestId, 1, false);
+ invokeAll(outAsync.getOs(), requestId, 1, false);
}
}, null);
}
@@ -339,7 +332,7 @@ namespace IceInternal
{
if(sentAsync(outAsync))
{
- invokeAll(outAsync.ostr__, requestId, 1, false);
+ invokeAll(outAsync.getOs(), requestId, 1, false);
}
}
sentCallback = null;
@@ -350,14 +343,15 @@ namespace IceInternal
{
if(sentAsync(outAsync))
{
- invokeAll(outAsync.ostr__, requestId, 1, false);
+ invokeAll(outAsync.getOs(), requestId, 1, false);
}
}, null);
sentCallback = null;
}
+ return false;
}
- public bool invokeAsyncBatchRequests(BatchOutgoingAsync outAsync, out Ice.AsyncCallback sentCallback)
+ public bool invokeAsyncBatchRequests(OutgoingAsyncBase outAsync, out Ice.AsyncCallback sentCallback)
{
int invokeNum;
lock(this)
@@ -373,10 +367,11 @@ namespace IceInternal
if(_reference.getInvocationTimeout() > 0)
{
_sendAsyncRequests.Add(outAsync, 0);
+ outAsync.cancelable(this);
}
Debug.Assert(!_batchStream.isEmpty());
- _batchStream.swap(outAsync.ostr__);
+ _batchStream.swap(outAsync.getOs());
//
// Reset the batch stream.
@@ -397,7 +392,7 @@ namespace IceInternal
{
if(sentAsync(outAsync))
{
- invokeAll(outAsync.ostr__, 0, invokeNum, true);
+ invokeAll(outAsync.getOs(), 0, invokeNum, true);
}
}, null);
sentCallback = null;
@@ -411,7 +406,7 @@ namespace IceInternal
}
- private bool sentAsync(OutgoingAsyncMessageCallback outAsync)
+ private bool sentAsync(OutgoingAsyncBase outAsync)
{
if(_reference.getInvocationTimeout() > 0)
{
@@ -492,18 +487,20 @@ namespace IceInternal
return; // Ignore exception for oneway messages.
}
- OutgoingAsync outAsync = null;
+ OutgoingAsync outAsync;
+ Ice.AsyncCallback cb = null;
lock(this)
{
if(_asyncRequests.TryGetValue(requestId, out outAsync))
{
_asyncRequests.Remove(requestId);
+ cb = outAsync.completed(ex);
}
}
- if(outAsync != null)
+ if(cb != null)
{
- outAsync.finished(ex);
+ outAsync.invokeCompleted(cb);
}
}
@@ -517,8 +514,7 @@ namespace IceInternal
private int _requestId;
- private Dictionary<OutgoingAsyncMessageCallback, int> _sendAsyncRequests =
- new Dictionary<OutgoingAsyncMessageCallback, int>();
+ private Dictionary<OutgoingAsyncBase, int> _sendAsyncRequests = new Dictionary<OutgoingAsyncBase, int>();
private Dictionary<int, OutgoingAsync> _asyncRequests = new Dictionary<int, OutgoingAsync>();
private BasicStream _batchStream;
diff --git a/cs/src/Ice/CommunicatorI.cs b/cs/src/Ice/CommunicatorI.cs
index 418285cbc64..8b86b1c2179 100644
--- a/cs/src/Ice/CommunicatorI.cs
+++ b/cs/src/Ice/CommunicatorI.cs
@@ -177,8 +177,8 @@ namespace Ice
// This callback object receives the results of all invocations
// of Connection.begin_flushBatchRequests.
//
- IceInternal.CommunicatorBatchOutgoingAsync result =
- new IceInternal.CommunicatorBatchOutgoingAsync(this, instance_, __flushBatchRequests_name, cookie);
+ IceInternal.CommunicatorFlushBatch result =
+ new IceInternal.CommunicatorFlushBatch(this, instance_, __flushBatchRequests_name, cookie);
if(cb != null)
{
@@ -200,8 +200,8 @@ namespace Ice
public void end_flushBatchRequests(AsyncResult result)
{
- IceInternal.OutgoingAsyncBase outAsync = (IceInternal.OutgoingAsyncBase)result;
- IceInternal.OutgoingAsyncBase.check(outAsync, this, __flushBatchRequests_name);
+ IceInternal.CommunicatorFlushBatch outAsync =
+ IceInternal.CommunicatorFlushBatch.check(result, this, __flushBatchRequests_name);
outAsync.wait();
}
diff --git a/cs/src/Ice/ConnectRequestHandler.cs b/cs/src/Ice/ConnectRequestHandler.cs
index 7676ee84d55..eed058479e7 100644
--- a/cs/src/Ice/ConnectRequestHandler.cs
+++ b/cs/src/Ice/ConnectRequestHandler.cs
@@ -26,12 +26,12 @@ namespace IceInternal
this.os.swap(os);
}
- internal Request(OutgoingAsyncMessageCallback outAsync)
+ internal Request(OutgoingAsyncBase outAsync)
{
this.outAsync = outAsync;
}
- internal OutgoingAsyncMessageCallback outAsync = null;
+ internal OutgoingAsyncBase outAsync = null;
internal BasicStream os = null;
internal Ice.AsyncCallback sentCallback = null;
}
@@ -143,7 +143,7 @@ namespace IceInternal
_connection.abortBatchRequest();
}
- public bool sendAsyncRequest(OutgoingAsyncMessageCallback outAsync, out Ice.AsyncCallback sentCallback)
+ public bool sendAsyncRequest(OutgoingAsyncBase outAsync, out Ice.AsyncCallback sentCallback)
{
lock(this)
{
@@ -152,6 +152,7 @@ namespace IceInternal
if(!initialized())
{
_requests.AddLast(new Request(outAsync));
+ outAsync.cancelable(this);
sentCallback = null;
return false;
}
@@ -164,7 +165,7 @@ namespace IceInternal
return outAsync.send(_connection, _compress, _response, out sentCallback);
}
- public void asyncRequestCanceled(OutgoingAsyncMessageCallback outAsync, Ice.LocalException ex)
+ public void asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex)
{
lock(this)
{
@@ -182,8 +183,12 @@ namespace IceInternal
if(request.outAsync == outAsync)
{
_requests.Remove(p);
- outAsync.dispatchInvocationCancel(ex, _reference.getInstance().clientThreadPool(), null);
- return; // We're done
+ Ice.AsyncCallback cb = outAsync.completed(ex);
+ if(cb != null)
+ {
+ outAsync.invokeCompletedAsync(cb);
+ }
+ return;
}
p = p.Next;
}
@@ -476,7 +481,11 @@ namespace IceInternal
{
if(request.outAsync != null)
{
- request.outAsync.finished(_exception);
+ Ice.AsyncCallback cb = request.outAsync.completed(_exception);
+ if(cb != null)
+ {
+ request.outAsync.invokeCompleted(cb);
+ }
}
}
_requests.Clear();
diff --git a/cs/src/Ice/ConnectionFactory.cs b/cs/src/Ice/ConnectionFactory.cs
index 47f4ec450aa..88cbb58d094 100644
--- a/cs/src/Ice/ConnectionFactory.cs
+++ b/cs/src/Ice/ConnectionFactory.cs
@@ -434,7 +434,7 @@ namespace IceInternal
}
}
- public void flushAsyncBatchRequests(CommunicatorBatchOutgoingAsync outAsync)
+ public void flushAsyncBatchRequests(CommunicatorFlushBatch outAsync)
{
ICollection<Ice.ConnectionI> c = new List<Ice.ConnectionI>();
@@ -1418,7 +1418,7 @@ namespace IceInternal
}
}
- public void flushAsyncBatchRequests(CommunicatorBatchOutgoingAsync outAsync)
+ public void flushAsyncBatchRequests(CommunicatorFlushBatch outAsync)
{
//
// connections() is synchronized, no need to synchronize here.
diff --git a/cs/src/Ice/ConnectionI.cs b/cs/src/Ice/ConnectionI.cs
index 88f92f334bd..6b7ce6d7510 100644
--- a/cs/src/Ice/ConnectionI.cs
+++ b/cs/src/Ice/ConnectionI.cs
@@ -17,7 +17,8 @@ namespace Ice
using System.Threading;
using Ice.Instrumentation;
- public sealed class ConnectionI : IceInternal.EventHandler, IceInternal.ResponseHandler, Connection
+ public sealed class ConnectionI :
+ IceInternal.EventHandler, IceInternal.ResponseHandler, IceInternal.CancellationHandler, Connection
{
public interface StartCallback
{
@@ -384,7 +385,7 @@ namespace Ice
public bool sendAsyncRequest(IceInternal.OutgoingAsync og, bool compress, bool response,
out Ice.AsyncCallback sentCallback)
{
- IceInternal.BasicStream os = og.ostr__;
+ IceInternal.BasicStream os = og.getOs();
lock(this)
{
@@ -427,8 +428,7 @@ namespace Ice
os.writeInt(requestId);
}
- og.attachRemoteObserver(initConnectionInfo(), _endpoint, requestId,
- os.size() - IceInternal.Protocol.headerSize - 4);
+ og.attachRemoteObserver(initConnectionInfo(), _endpoint, requestId);
bool sent;
try
@@ -444,6 +444,11 @@ namespace Ice
throw _exception;
}
+ if(response || !sent)
+ {
+ og.cancelable(this); // Notify the request that it's cancelable
+ }
+
if(response)
{
//
@@ -672,8 +677,8 @@ namespace Ice
public void end_flushBatchRequests(AsyncResult r)
{
- IceInternal.OutgoingAsyncBase outAsync = (IceInternal.OutgoingAsyncBase)r;
- IceInternal.OutgoingAsyncBase.check(outAsync, this, __flushBatchRequests_name);
+ IceInternal.ConnectionFlushBatch outAsync =
+ IceInternal.ConnectionFlushBatch.check(r, this, __flushBatchRequests_name);
outAsync.wait();
}
@@ -681,28 +686,17 @@ namespace Ice
private AsyncResult begin_flushBatchRequestsInternal(AsyncCallback cb, object cookie)
{
- IceInternal.ConnectionBatchOutgoingAsync result =
- new IceInternal.ConnectionBatchOutgoingAsync(this, _communicator, _instance, __flushBatchRequests_name,
- cookie);
-
+ IceInternal.ConnectionFlushBatch result =
+ new IceInternal.ConnectionFlushBatch(this, _communicator, _instance, __flushBatchRequests_name, cookie);
if(cb != null)
{
result.whenCompletedWithAsyncCallback(cb);
}
-
- try
- {
- result.invoke();
- }
- catch(LocalException ex)
- {
- result.invokeExceptionAsync(ex);
- }
-
+ result.invoke();
return result;
}
- public bool flushAsyncBatchRequests(IceInternal.BatchOutgoingAsync outAsync, out Ice.AsyncCallback sentCallback)
+ public bool flushAsyncBatchRequests(IceInternal.OutgoingAsyncBase outAsync, out Ice.AsyncCallback sentCallback)
{
lock(this)
{
@@ -728,10 +722,9 @@ namespace Ice
_batchStream.pos(IceInternal.Protocol.headerSize);
_batchStream.writeInt(_batchRequestNum);
- outAsync.attachRemoteObserver(initConnectionInfo(), _endpoint, 0,
- _batchStream.size() - IceInternal.Protocol.headerSize - 4);
+ _batchStream.swap(outAsync.getOs());
- _batchStream.swap(outAsync.ostr__);
+ outAsync.attachRemoteObserver(initConnectionInfo(), _endpoint, 0);
//
// Send the batch stream.
@@ -739,7 +732,7 @@ namespace Ice
bool sent;
try
{
- OutgoingMessage message = new OutgoingMessage(outAsync, outAsync.ostr__, _batchRequestCompress, 0);
+ OutgoingMessage message = new OutgoingMessage(outAsync, outAsync.getOs(), _batchRequestCompress, 0);
sent = sendMessage(message);
sentCallback = message.sentCallback;
}
@@ -749,6 +742,11 @@ namespace Ice
Debug.Assert(_exception != null);
throw _exception;
}
+
+ if(!sent)
+ {
+ outAsync.cancelable(this); // Notify the request that it's cancelable.
+ }
//
// Reset the batch stream.
@@ -779,7 +777,7 @@ namespace Ice
{
_logger.error("connection callback exception:\n" + ex + '\n' + _desc);
}
- } , null);
+ } , this);
}
}
else
@@ -828,10 +826,19 @@ namespace Ice
}
}
- public void asyncRequestCanceled(IceInternal.OutgoingAsyncMessageCallback outAsync, Ice.LocalException ex)
+ public void asyncRequestCanceled(IceInternal.OutgoingAsyncBase outAsync, Ice.LocalException ex)
{
+ //
+ // NOTE: This isn't called from a thread pool thread.
+ //
+
lock(this)
{
+ if(_state >= StateClosed)
+ {
+ return; // The request has already been or will be shortly notified of the failure.
+ }
+
LinkedListNode<OutgoingMessage> p;
for(p = _sendStreams.First; p != null; p = p.Next)
{
@@ -847,13 +854,17 @@ namespace Ice
// If the request is being sent, don't remove it from the send streams,
// it will be removed once the sending is finished.
//
- o.timedOut();
+ o.canceled();
if(o != _sendStreams.First.Value)
{
_sendStreams.Remove(p);
}
- outAsync.dispatchInvocationCancel(ex, _threadPool, this);
- return; // We're done.
+ Ice.AsyncCallback cb = outAsync.completed(ex);
+ if(cb != null)
+ {
+ outAsync.invokeCompletedAsync(cb);
+ }
+ return;
}
}
@@ -865,8 +876,12 @@ namespace Ice
if(kvp.Value == o)
{
_asyncRequests.Remove(kvp.Key);
- outAsync.dispatchInvocationCancel(ex, _threadPool, this);
- return; // We're done.
+ Ice.AsyncCallback cb = outAsync.completed(ex);
+ if(cb != null)
+ {
+ outAsync.invokeCompletedAsync(cb);
+ }
+ return;
}
}
}
@@ -1422,7 +1437,7 @@ namespace Ice
if(m.receivedReply)
{
IceInternal.OutgoingAsync outAsync = (IceInternal.OutgoingAsync)m.outAsync;
- Ice.AsyncCallback cb = outAsync.finished();
+ Ice.AsyncCallback cb = outAsync.completed();
if(cb != null)
{
outAsync.invokeCompleted(cb);
@@ -1596,7 +1611,7 @@ namespace Ice
if(message.receivedReply)
{
IceInternal.OutgoingAsync outAsync = (IceInternal.OutgoingAsync)message.outAsync;
- Ice.AsyncCallback cb = outAsync.finished();
+ Ice.AsyncCallback cb = outAsync.completed();
if(cb != null)
{
outAsync.invokeCompleted(cb);
@@ -1608,7 +1623,7 @@ namespace Ice
foreach(OutgoingMessage m in _sendStreams)
{
- m.finished(_exception);
+ m.completed(_exception);
if(m.requestId > 0) // Make sure finished isn't called twice.
{
_asyncRequests.Remove(m.requestId);
@@ -1619,7 +1634,11 @@ namespace Ice
foreach(IceInternal.OutgoingAsync o in _asyncRequests.Values)
{
- o.finished(_exception);
+ Ice.AsyncCallback cb = o.completed(_exception);
+ if(cb != null)
+ {
+ o.invokeCompleted(cb);
+ }
}
_asyncRequests.Clear();
@@ -2670,7 +2689,7 @@ namespace Ice
{
_asyncRequests.Remove(info.requestId);
- outAsync.istr__.swap(info.stream);
+ outAsync.getIs().swap(info.stream);
//
// If we just received the reply for a request which isn't acknowledge as
@@ -2684,7 +2703,7 @@ namespace Ice
}
else
{
- info.completedCallback = outAsync.finished();
+ info.completedCallback = outAsync.completed();
if(info.completedCallback != null)
{
info.outAsync = outAsync;
@@ -3044,7 +3063,7 @@ namespace Ice
this.requestId = 0;
}
- internal OutgoingMessage(IceInternal.OutgoingAsyncMessageCallback outAsync, IceInternal.BasicStream stream,
+ internal OutgoingMessage(IceInternal.OutgoingAsyncBase outAsync, IceInternal.BasicStream stream,
bool compress, int requestId)
{
this.stream = stream;
@@ -3054,7 +3073,7 @@ namespace Ice
this.isSent = false;
}
- internal void timedOut()
+ internal void canceled()
{
Debug.Assert(outAsync != null);
outAsync = null;
@@ -3081,16 +3100,20 @@ namespace Ice
return sentCallback != null || receivedReply;
}
- internal void finished(LocalException ex)
+ internal void completed(LocalException ex)
{
if(outAsync != null)
{
- outAsync.finished(ex);
+ Ice.AsyncCallback cb = outAsync.completed(ex);
+ if(cb != null)
+ {
+ outAsync.invokeCompleted(cb);
+ }
}
}
internal IceInternal.BasicStream stream;
- internal IceInternal.OutgoingAsyncMessageCallback outAsync;
+ internal IceInternal.OutgoingAsyncBase outAsync;
internal bool receivedReply;
internal bool compress;
internal int requestId;
diff --git a/cs/src/Ice/ConnectionRequestHandler.cs b/cs/src/Ice/ConnectionRequestHandler.cs
index 1d7a2b32ff0..a0f1edec56f 100644
--- a/cs/src/Ice/ConnectionRequestHandler.cs
+++ b/cs/src/Ice/ConnectionRequestHandler.cs
@@ -61,13 +61,13 @@ namespace IceInternal
{
_connection.abortBatchRequest();
}
-
- public bool sendAsyncRequest(OutgoingAsyncMessageCallback outAsync, out Ice.AsyncCallback sentCallback)
+
+ public bool sendAsyncRequest(OutgoingAsyncBase outAsync, out Ice.AsyncCallback sentCallback)
{
return outAsync.send(_connection, _compress, _response, out sentCallback);
}
- public void asyncRequestCanceled(OutgoingAsyncMessageCallback outAsync, Ice.LocalException ex)
+ public void asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex)
{
_connection.asyncRequestCanceled(outAsync, ex);
}
diff --git a/cs/src/Ice/Makefile b/cs/src/Ice/Makefile
index dc7b66116ce..dbdd6671d1c 100644
--- a/cs/src/Ice/Makefile
+++ b/cs/src/Ice/Makefile
@@ -22,6 +22,7 @@ SRCS = Acceptor.cs \
AssemblyInfo.cs \
AssemblyUtil.cs \
AsyncIOThread.cs \
+ AsyncResult.cs \
Base64.cs \
BasicStream.cs \
Buffer.cs \
diff --git a/cs/src/Ice/Makefile.mak b/cs/src/Ice/Makefile.mak
index f900f2902ec..454302543aa 100644
--- a/cs/src/Ice/Makefile.mak
+++ b/cs/src/Ice/Makefile.mak
@@ -22,6 +22,7 @@ SRCS = Acceptor.cs \
AssemblyInfo.cs \
AssemblyUtil.cs \
AsyncIOThread.cs \
+ AsyncResult.cs \
Base64.cs \
BasicStream.cs \
Buffer.cs \
diff --git a/cs/src/Ice/ObjectAdapterFactory.cs b/cs/src/Ice/ObjectAdapterFactory.cs
index 3dd791b1030..0b9cdb2a914 100644
--- a/cs/src/Ice/ObjectAdapterFactory.cs
+++ b/cs/src/Ice/ObjectAdapterFactory.cs
@@ -212,7 +212,7 @@ namespace IceInternal
}
}
- public void flushAsyncBatchRequests(CommunicatorBatchOutgoingAsync outAsync)
+ public void flushAsyncBatchRequests(CommunicatorFlushBatch outAsync)
{
List<Ice.ObjectAdapterI> adapters;
lock(this)
diff --git a/cs/src/Ice/ObjectAdapterI.cs b/cs/src/Ice/ObjectAdapterI.cs
index eaf5b98260e..7756016527d 100644
--- a/cs/src/Ice/ObjectAdapterI.cs
+++ b/cs/src/Ice/ObjectAdapterI.cs
@@ -705,7 +705,7 @@ namespace Ice
}
}
- public void flushAsyncBatchRequests(IceInternal.CommunicatorBatchOutgoingAsync outAsync)
+ public void flushAsyncBatchRequests(IceInternal.CommunicatorFlushBatch outAsync)
{
List<IceInternal.IncomingConnectionFactory> f;
lock(this)
diff --git a/cs/src/Ice/OutgoingAsync.cs b/cs/src/Ice/OutgoingAsync.cs
index 001573244be..910d4fae161 100644
--- a/cs/src/Ice/OutgoingAsync.cs
+++ b/cs/src/Ice/OutgoingAsync.cs
@@ -7,81 +7,6 @@
//
// **********************************************************************
-namespace Ice
-{
- using System.Threading;
- using System.Collections.Generic;
- using System.Diagnostics;
-
- ///
- /// <summary>
- /// Callback that requires the application to down-cast the proxy.
- /// </summary>
- ///
- public delegate void AsyncCallback(AsyncResult r);
-
- ///
- /// <summary>
- /// Callback for the successful completion of an operation
- /// that returns no data.
- /// </summary>
- ///
- public delegate void OnewayCallback();
-
- ///
- /// <summary>
- /// Callback for the successful completion of an operation
- /// that returns no data.
- /// </summary>
- ///
- public delegate void SentCallback(bool sentSynchronously);
-
- ///
- /// <summary>
- /// Called when an invocation raises an exception.
- /// </summary>
- ///
- public delegate void ExceptionCallback(Ice.Exception ex);
-
- ///
- /// <summary>
- /// <!-- TODO -->
- /// </summary>
- public interface AsyncResult : System.IAsyncResult
- {
- Ice.Communicator getCommunicator();
-
- Ice.Connection getConnection();
-
- ObjectPrx getProxy();
-
- bool isCompleted_();
- void waitForCompleted();
-
- bool isSent();
- void waitForSent();
-
- void throwLocalException();
-
- bool sentSynchronously();
-
- string getOperation();
-
- AsyncResult whenSent(Ice.AsyncCallback cb);
- AsyncResult whenSent(Ice.SentCallback cb);
-
- AsyncResult whenCompleted(Ice.ExceptionCallback excb);
- }
-
- public interface AsyncResult<T> : AsyncResult
- {
- AsyncResult<T> whenCompleted(T cb, Ice.ExceptionCallback excb);
-
- new AsyncResult<T> whenCompleted(Ice.ExceptionCallback excb);
- new AsyncResult<T> whenSent(Ice.SentCallback cb);
- }
-}
-
namespace IceInternal
{
using System;
@@ -89,732 +14,385 @@ namespace IceInternal
using System.Diagnostics;
using System.Threading;
- public delegate void ProxyTwowayCallback<T>(Ice.AsyncResult result, T cb, Ice.ExceptionCallback excb);
- public delegate void ProxyOnewayCallback<T>(T cb);
-
- //
- // This interface is used by the connection to handle OutgoingAsync
- // and BatchOutgoingAsync messages.
- //
- public interface OutgoingAsyncMessageCallback
- {
- //
- // Called by the request handler to send the request over the connection.
- //
- bool send(Ice.ConnectionI connection, bool compress, bool response, out Ice.AsyncCallback sentCallback);
-
- //
- // Called by the collocated request handler to invoke the request.
- //
- bool invokeCollocated(CollocatedRequestHandler handler, out Ice.AsyncCallback sentCallback);
-
- //
- // Called by the connection when the message is confirmed sent. The connection is locked
- // when this is called so this method can call the sent callback. Instead, this method
- // returns true if there's a sent callback and false otherwise. If true is returned, the
- // connection will call the __sent() method bellow (which in turn should call the sent
- // callback).
- //
- Ice.AsyncCallback sent();
-
- //
- // Called by the connection to call the user sent callback.
- //
- void invokeSent(Ice.AsyncCallback cb);
-
- //
- // Called by the connection when the request failed.
- //
- void finished(Ice.Exception ex);
-
- //
- // Helper to dispatch invocation timeout.
- //
- void dispatchInvocationCancel(Ice.LocalException ex, ThreadPool threadPool, Ice.Connection connection);
- }
-
- abstract public class OutgoingAsyncBase : Ice.AsyncResult
+ public class OutgoingAsyncBase : AsyncResultI
{
- public virtual Ice.Communicator getCommunicator()
- {
- return communicator_;
- }
-
- public virtual Ice.Connection getConnection()
+ public virtual bool send(Ice.ConnectionI connection, bool compress, bool response, out Ice.AsyncCallback cb)
{
- return null;
+ Debug.Assert(false); // This should be overriden if this object is used with a request handler
+ cb = null;
+ return false;
}
- public virtual Ice.ObjectPrx getProxy()
+ public virtual bool invokeCollocated(CollocatedRequestHandler handler, out Ice.AsyncCallback cb)
{
- return null;
- }
-
- public bool isCompleted_()
- {
- lock(monitor_)
- {
- return (state_ & StateDone) != 0;
- }
+ Debug.Assert(false); // This should be overriden if this object is used with a request handler
+ cb = null;
+ return false;
}
- public void waitForCompleted()
+ public virtual Ice.AsyncCallback sent()
{
- lock(monitor_)
- {
- while((state_ & StateDone) == 0)
- {
- System.Threading.Monitor.Wait(monitor_);
- }
- }
+ return sent(true);
}
- public bool isSent()
+ public virtual Ice.AsyncCallback completed(Ice.Exception ex)
{
- lock(monitor_)
- {
- return (state_ & StateSent) != 0;
- }
+ return finished(ex);
}
- public void waitForSent()
+ public void attachRemoteObserver(Ice.ConnectionInfo info, Ice.Endpoint endpt, int requestId)
{
- lock(monitor_)
+ if(observer_ != null)
{
- while((state_ & StateSent) == 0 && exception_ == null)
+ int size = os_.size() - Protocol.headerSize - 4;
+ childObserver_ = getObserver().getRemoteObserver(info, endpt, requestId, size);
+ if(childObserver_ != null)
{
- System.Threading.Monitor.Wait(monitor_);
+ childObserver_.attach();
}
}
}
- public void throwLocalException()
+ public void attachCollocatedObserver(Ice.ObjectAdapter adapter, int requestId)
{
- lock(monitor_)
+ if(observer_ != null)
{
- if(exception_ != null)
+ int size = os_.size() - Protocol.headerSize - 4;
+ childObserver_ = getObserver().getCollocatedObserver(adapter, requestId, size);
+ if(childObserver_ != null)
{
- throw exception_;
+ childObserver_.attach();
}
}
}
- public bool sentSynchronously()
+ public IceInternal.BasicStream getOs()
{
- return sentSynchronously_; // No lock needed, immutable once invoke() is called
- }
-
- //
- // Implementation of System.IAsyncResult properties
- //
-
- public bool IsCompleted
- {
- get
- {
- return isCompleted_();
- }
+ return os_;
}
- public bool CompletedSynchronously
+ protected OutgoingAsyncBase(Ice.Communicator com, Instance instance, string op, object cookie) :
+ base(com, instance, op, cookie)
{
- get
- {
- if(getProxy() != null && getProxy().ice_isTwoway())
- {
- return false;
- }
- return sentSynchronously_;
- }
+ os_ = new BasicStream(instance, Ice.Util.currentProtocolEncoding);
}
- public object AsyncState
+ protected OutgoingAsyncBase(Ice.Communicator com, Instance instance, string op, object cookie, BasicStream os) :
+ base(com, instance, op, cookie)
{
- get
- {
- return _cookie; // No lock needed, cookie is immutable.
- }
+ os_ = os;
}
- public WaitHandle AsyncWaitHandle
+ protected new Ice.AsyncCallback sent(bool done)
{
- get
+ if(done)
{
- lock(monitor_)
+ if(childObserver_ != null)
{
- if(waitHandle_ == null)
- {
-#if SILVERLIGHT
- waitHandle_ = new ManualResetEvent(false);
-#else
- waitHandle_ = new EventWaitHandle(false, EventResetMode.ManualReset);
-#endif
- }
- if((state_ & StateDone) != 0)
- {
- waitHandle_.Set();
- }
- return waitHandle_;
+ childObserver_.detach();
+ childObserver_ = null;
}
}
+ return base.sent(done);
}
- public Ice.AsyncResult whenSent(Ice.AsyncCallback cb)
+ protected new Ice.AsyncCallback finished(Ice.Exception ex)
{
- lock(monitor_)
+ if(childObserver_ != null)
{
- if(cb == null)
- {
- throw new System.ArgumentException("callback is null");
- }
- if(sentCallback_ != null)
- {
- throw new System.ArgumentException("sent callback already set");
- }
- sentCallback_ = cb;
- if((state_ & StateSent) == 0)
- {
- return this;
- }
+ childObserver_.failed(ex.ice_name());
+ childObserver_.detach();
+ childObserver_ = null;
}
-
- if(sentSynchronously_)
- {
- try
- {
- sentCallback_(this);
- }
- catch(System.Exception ex)
- {
- warning(ex);
- }
- }
- else
- {
- instance_.clientThreadPool().dispatch(() =>
- {
- try
- {
- sentCallback_(this);
- }
- catch(System.Exception ex)
- {
- warning(ex);
- }
- }, cachedConnection_);
- }
- return this;
+ return base.finished(ex);
}
- public Ice.AsyncResult whenSent(Ice.SentCallback cb)
- {
- lock(monitor_)
- {
- if(cb == null)
- {
- throw new System.ArgumentException("callback is null");
- }
- if(sentCallback_ != null)
- {
- throw new System.ArgumentException("sent callback already set");
- }
- sentCallback_ = (Ice.AsyncResult result) =>
- {
- cb(result.sentSynchronously());
- };
- if((state_ & StateSent) == 0)
- {
- return this;
- }
- }
-
- if(sentSynchronously_)
- {
- try
- {
- cb(true);
- }
- catch(System.Exception ex)
- {
- warning(ex);
- }
- }
- else
- {
- instance_.clientThreadPool().dispatch(() =>
- {
- try
- {
- cb(false);
- }
- catch(System.Exception ex)
- {
- warning(ex);
- }
- }, cachedConnection_);
- }
- return this;
- }
-
- public Ice.AsyncResult whenCompletedWithAsyncCallback(Ice.AsyncCallback cb)
- {
- setCompletedCallback(cb);
- return this;
- }
-
- public Ice.AsyncResult whenCompleted(Ice.ExceptionCallback cb)
- {
- if(cb == null)
- {
- throw new System.ArgumentException("callback is null");
- }
- lock(monitor_)
- {
- if(exceptionCallback_ != null)
- {
- throw new System.ArgumentException("callback already set");
- }
- exceptionCallback_ = cb;
- }
- setCompletedCallback(getCompletedCallback());
- return this;
- }
+ protected BasicStream os_;
+ protected Ice.Instrumentation.ChildInvocationObserver childObserver_;
+ }
- public string getOperation()
+ //
+ // Base class for proxy based invocations. This class handles the
+ // retry for proxy invocations. It also ensures the child observer is
+ // correct notified of failures and make sure the retry task is
+ // correctly canceled when the invocation completes.
+ //
+ public class ProxyOutgoingAsyncBase : OutgoingAsyncBase, TimerTask
+ {
+ public static ProxyOutgoingAsyncBase check(Ice.AsyncResult r, Ice.ObjectPrx prx, string operation)
{
- return operation_;
+ return ProxyOutgoingAsyncBase.check<ProxyOutgoingAsyncBase>(r, prx, operation);
}
- public IceInternal.BasicStream ostr__
+ public override Ice.ObjectPrx getProxy()
{
- get
- {
- return os_;
- }
+ return proxy_;
}
- public bool wait()
+ public override Ice.AsyncCallback sent()
{
- lock(monitor_)
- {
- if((state_ & StateEndCalled) != 0)
- {
- throw new System.ArgumentException("end_ method called more than once");
- }
- state_ |= StateEndCalled;
- while((state_ & StateDone) == 0)
- {
- System.Threading.Monitor.Wait(monitor_);
- }
- if(exception_ != null)
- {
- throw exception_;
- }
- return (state_ & StateOK) != 0;
- }
+ return sent(!proxy_.ice_isTwoway());
}
- public void throwUserException()
+ public override Ice.AsyncCallback completed(Ice.Exception exc)
{
- try
- {
- is_.startReadEncaps();
- is_.throwException(null);
- }
- catch(Ice.UserException)
+ if(childObserver_ != null)
{
- is_.endReadEncaps();
- throw;
+ childObserver_.failed(exc.ice_name());
+ childObserver_.detach();
+ childObserver_ = null;
}
- }
- virtual public void invokeExceptionAsync(Ice.Exception ex)
- {
//
- // This is called when it's not safe to call the exception callback synchronously
- // from this thread. Instead the exception callback is called asynchronously from
- // the client thread pool.
+ // NOTE: at this point, synchronization isn't needed, no other threads should be
+ // calling on the callback.
//
try
{
- instance_.clientThreadPool().dispatch(() =>
- {
- invokeException(ex);
- }, cachedConnection_);
+ instance_.retryQueue().add(this, handleException(exc));
+ return null;
}
- catch(Ice.CommunicatorDestroyedException)
+ catch(Ice.Exception ex)
{
- throw; // CommunicatorDestroyedException is the only exception that can propagate directly.
+ return finished(ex); // No retries, we're done
}
}
- virtual public void attachRemoteObserver(Ice.ConnectionInfo info, Ice.Endpoint endpt, int requestId, int sz)
+ public void retry()
{
- if(observer_ != null)
- {
- childObserver_ = observer_.getRemoteObserver(info, endpt, requestId, sz);
- if(childObserver_ != null)
- {
- childObserver_.attach();
- }
- }
+ invokeImpl(false);
}
- virtual public void attachCollocatedObserver(Ice.ObjectAdapter adapter, int requestId)
+ public virtual void abort(Ice.Exception ex)
{
- if(observer_ != null)
+ Debug.Assert(childObserver_ == null);
+ Ice.AsyncCallback cb = finished(ex);
+ if(cb != null)
{
- childObserver_ = observer_.getCollocatedObserver(adapter,
- requestId,
- os_.size() - IceInternal.Protocol.headerSize - 4);
- if(childObserver_ != null)
- {
- childObserver_.attach();
- }
+ invokeCompletedAsync(cb);
}
- }
-
- public void invokeSentAsync(Ice.AsyncCallback callback)
- {
- //
- // This is called when it's not safe to call the exception callback synchronously
- // from this thread. Instead the exception callback is called asynchronously from
- // the client thread pool.
- //
- if(callback != null)
+ else if(ex is Ice.CommunicatorDestroyedException)
{
- try
- {
- instance_.clientThreadPool().dispatch(() =>
- {
- invokeSent(callback);
- }, cachedConnection_);
- }
- catch(Ice.CommunicatorDestroyedException)
- {
- }
+ //
+ // If it's a communicator destroyed exception, don't swallow
+ // it but instead notify the user thread. Even if no callback
+ // was provided.
+ //
+ throw ex;
}
}
- abstract internal void processRetry();
-
- public static void check(OutgoingAsyncBase r, Ice.ObjectPrx prx, string operation)
+ public void runTimerTask()
{
- check(r, operation);
- if(r.getProxy() != prx)
- {
- throw new System.ArgumentException("Proxy for call to end_" + operation +
- " does not match proxy that was used to call corresponding begin_" +
- operation + " method");
- }
+ cancel(new Ice.InvocationTimeoutException());
}
- public static void check(OutgoingAsyncBase r, Ice.Connection con, string operation)
+ protected ProxyOutgoingAsyncBase(Ice.ObjectPrxHelperBase prx, string op, object cookie) :
+ base(prx.ice_getCommunicator(), prx.reference__().getInstance(), op, cookie)
{
- check(r, operation);
- if(r.getConnection() != con)
- {
- throw new System.ArgumentException("Connection for call to end_" + operation +
- " does not match connection that was used to call " +
- "corresponding begin_" + operation + " method");
- }
+ proxy_ = prx;
+ mode_ = Ice.OperationMode.Normal;
+ _cnt = 0;
+ _sent = false;
}
- public static void check(OutgoingAsyncBase r, Ice.Communicator com, string operation)
+ protected ProxyOutgoingAsyncBase(Ice.ObjectPrxHelperBase prx, string op, object cookie, BasicStream os) :
+ base(prx.ice_getCommunicator(), prx.reference__().getInstance(), op, cookie, os)
{
- check(r, operation);
- if(r.getCommunicator() != com)
- {
- throw new System.ArgumentException("Communicator for call to end_" + operation +
- " does not match communicator that was used to call " +
- "corresponding begin_" + operation + " method");
- }
+ proxy_ = prx;
+ mode_ = Ice.OperationMode.Normal;
+ _cnt = 0;
+ _sent = false;
}
- protected static void check(OutgoingAsyncBase r, string operation)
+ protected static T check<T>(Ice.AsyncResult r, Ice.ObjectPrx prx, string operation)
{
- if(r == null)
- {
- throw new System.ArgumentException("AsyncResult == null");
- }
- if(r.getOperation() != operation)
+ if(r != null && r.getProxy() != prx)
{
- throw new System.ArgumentException("Incorrect operation for end_" + operation + " method: " +
- r.getOperation());
+ throw new System.ArgumentException("Proxy for call to end_" + operation +
+ " does not match proxy that was used to call corresponding begin_" +
+ operation + " method");
}
+ return check<T>(r, operation);
}
- protected OutgoingAsyncBase(Ice.Communicator communicator, Instance instance, string op, object cookie)
- {
- communicator_ = communicator;
- instance_ = instance;
- operation_ = op;
- // Lazy initialized when response is received.
- //is_ = new IceInternal.BasicStream(instance);
- os_ = new IceInternal.BasicStream(instance, Ice.Util.currentProtocolEncoding);
- state_ = 0;
- sentSynchronously_ = false;
- exception_ = null;
- _cookie = cookie;
- }
-
- protected OutgoingAsyncBase(Ice.Communicator communicator, Instance instance, string op, object cookie,
- BasicStream iss, BasicStream os)
- {
- communicator_ = communicator;
- instance_ = instance;
- operation_ = op;
- is_ = iss;
- os_ = os;
- state_ = 0;
- sentSynchronously_ = false;
- exception_ = null;
- _cookie = cookie;
- }
-
- protected void setCompletedCallback(Ice.AsyncCallback cb)
+ protected void invokeImpl(bool userThread)
{
- lock(monitor_)
+ try
{
- if(cb == null)
- {
- throw new System.ArgumentException("callback is null");
- }
- if(completedCallback_ != null)
+ if(userThread)
{
- throw new System.ArgumentException("callback already set");
- }
- completedCallback_ = cb;
- if((state_ & StateDone) == 0)
- {
- return;
+ int invocationTimeout = proxy_.reference__().getInvocationTimeout();
+ if(invocationTimeout > 0)
+ {
+ instance_.timer().schedule(this, invocationTimeout);
+ }
}
- else if((getProxy() == null || getProxy().ice_isOneway()) && exception_ == null)
+ else // If not called from the user thread, it's called from the retry queue
{
- return;
+ checkCanceled(); // Cancellation exception aren't retriable
+ if(observer_ != null)
+ {
+ observer_.retried();
+ }
}
- }
- instance_.clientThreadPool().dispatch(() =>
+ while(true)
{
try
{
- cb(this);
+ _sent = false;
+ handler_ = proxy_.getRequestHandler__();
+ Ice.AsyncCallback sentCallback;
+ if(handler_.sendAsyncRequest(this, out sentCallback))
+ {
+ if(userThread)
+ {
+ sentSynchronously_ = true;
+ if(sentCallback != null)
+ {
+ invokeSent(sentCallback); // Call from the user thread.
+ }
+ }
+ else
+ {
+ if(sentCallback != null)
+ {
+ invokeSentAsync(sentCallback); // Call from a client thread pool thread.
+ }
+ }
+ }
+ return; // We're done!
}
- catch(System.Exception ex)
+ catch(RetryException ex)
{
- warning(ex);
+ handleRetryException(ex);
+ }
+ catch(Ice.Exception ex)
+ {
+ if(childObserver_ != null)
+ {
+ childObserver_.failed(ex.ice_name());
+ childObserver_.detach();
+ childObserver_ = null;
+ }
+ int interval = handleException(ex);
+ if(interval > 0)
+ {
+ instance_.retryQueue().add(this, interval);
+ return;
+ }
+ else if(observer_ != null)
+ {
+ checkCanceled();
+ observer_.retried();
+ }
}
- }, cachedConnection_);
-
- }
-
- protected void invokeSent(Ice.AsyncCallback cb)
- {
- //
- // Note: no need to change the state_ here, specializations are responsible for
- // changing the state.
- //
-
- if(cb != null)
- {
- try
- {
- cb(this);
- }
- catch(System.Exception ex)
- {
- warning(ex);
- }
- }
-
- if(observer_ != null)
- {
- Ice.ObjectPrx proxy = getProxy();
- if(proxy == null || !proxy.ice_isTwoway())
- {
- observer_.detach();
- observer_ = null;
}
}
- }
-
- protected void invokeCompleted(Ice.AsyncCallback cb)
- {
- //
- // Note: no need to change the state_ here, specializations are responsible for
- // changing the state.
- //
-
- if(cb != null)
+ catch(Ice.Exception ex)
{
- try
+ //
+ // If called from the user thread we re-throw, the exception
+ // will be catch by the caller and abort() will be called.
+ //
+ if(userThread)
{
- cb(this);
+ throw ex;
}
- catch(System.Exception ex)
+ Ice.AsyncCallback cb = finished(ex); // No retries, we're done
+ if(cb != null)
{
- warning(ex);
+ invokeCompletedAsync(cb);
}
}
-
- if(observer_ != null)
- {
- observer_.detach();
- observer_ = null;
- }
}
- protected void invokeException(Ice.Exception ex)
+ protected new Ice.AsyncCallback sent(bool done)
{
- Ice.AsyncCallback cb;
- lock(monitor_)
- {
- state_ |= StateDone;
- os_.resize(0, false); // Clear buffer now, instead of waiting for AsyncResult deallocation
- exception_ = ex;
- System.Threading.Monitor.PulseAll(monitor_);
- if(waitHandle_ != null)
- {
- waitHandle_.Set();
- }
- cb = completedCallback_;
- }
-
- if(cb != null)
+ _sent = true;
+ if(done)
{
- try
- {
- cb(this);
- }
- catch(System.Exception exc)
+ if(proxy_.reference__().getInvocationTimeout() > 0)
{
- warning(exc);
+ instance_.timer().cancel(this);
}
}
-
- if(observer_ != null)
- {
- observer_.detach();
- observer_ = null;
- }
+ return base.sent(done);
}
- protected virtual Ice.AsyncCallback getCompletedCallback()
+ protected new Ice.AsyncCallback finished(Ice.Exception ex)
{
- return (Ice.AsyncResult result) => {
- Debug.Assert(exceptionCallback_ != null);
- try
- {
- ((OutgoingAsyncBase)result).wait();
- }
- catch(Ice.Exception ex)
- {
- exceptionCallback_(ex);
- return;
- }
- };
- }
-
- protected void runTimerTask__()
- {
- IceInternal.RequestHandler handler;
- lock(monitor_)
- {
-
- handler = timeoutRequestHandler_;
- timeoutRequestHandler_ = null;
- }
-
- if(handler != null)
+ if(proxy_.reference__().getInvocationTimeout() > 0)
{
- handler.asyncRequestCanceled((OutgoingAsyncMessageCallback)this, new Ice.InvocationTimeoutException());
+ instance_.timer().cancel(this);
}
+ return base.finished(ex);
}
- protected void warning(System.Exception ex)
+ protected new Ice.AsyncCallback finished(bool ok)
{
- if(instance_.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0)
+ if(proxy_.reference__().getInvocationTimeout() > 0)
{
- instance_.initializationData().logger.warning("exception raised by AMI callback:\n" + ex);
+ instance_.timer().cancel(this);
}
+ return base.finished(ok);
}
- protected Ice.Communicator communicator_;
- protected IceInternal.Instance instance_;
- protected string operation_;
- protected Ice.Connection cachedConnection_;
-
- protected readonly object monitor_ = new object();
- protected IceInternal.BasicStream is_;
- protected IceInternal.BasicStream os_;
-
- protected IceInternal.RequestHandler timeoutRequestHandler_;
-
- protected const int StateOK = 0x1;
- protected const int StateDone = 0x2;
- protected const int StateSent = 0x4;
- protected const int StateEndCalled = 0x8;
- protected const int StateCachedBuffers = 0x10;
-
- protected int state_;
- protected bool sentSynchronously_;
-
- //
- // If true this AMI request is being used for a generated synchronous invocation.
- //
- protected bool synchronous_;
-
- protected Ice.Exception exception_;
- protected EventWaitHandle waitHandle_;
+ protected virtual void handleRetryException(RetryException exc)
+ {
+ proxy_.setRequestHandler__(handler_, null); // Clear request handler and always retry.
+ }
- protected Ice.Instrumentation.InvocationObserver observer_;
- protected Ice.Instrumentation.ChildInvocationObserver childObserver_;
+ protected virtual int handleException(Ice.Exception exc)
+ {
+ return proxy_.handleException__(exc, handler_, mode_, _sent, ref _cnt);
+ }
- protected Ice.AsyncCallback completedCallback_;
- protected Ice.AsyncCallback sentCallback_;
- protected Ice.ExceptionCallback exceptionCallback_;
+ protected Ice.ObjectPrxHelperBase proxy_;
+ protected RequestHandler handler_;
+ protected Ice.OperationMode mode_;
- private object _cookie;
+ private int _cnt;
+ private bool _sent;
}
- abstract public class OutgoingAsync : OutgoingAsyncBase, OutgoingAsyncMessageCallback, TimerTask
+ public class OutgoingAsync : ProxyOutgoingAsyncBase
{
- public OutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, object cookie) :
- base(prx.ice_getCommunicator(), prx.reference__().getInstance(), operation, cookie)
+ public new static OutgoingAsync check(Ice.AsyncResult r, Ice.ObjectPrx prx, string operation)
+ {
+ return ProxyOutgoingAsyncBase.check<OutgoingAsync>(r, prx, operation);
+ }
+
+ public OutgoingAsync(Ice.ObjectPrx prx, string operation, object cookie) :
+ base((Ice.ObjectPrxHelperBase)prx, operation, cookie)
{
- _proxy = prx;
- _encoding = Protocol.getCompatibleEncoding(_proxy.reference__().getEncoding());
+ _encoding = Protocol.getCompatibleEncoding(proxy_.reference__().getEncoding());
+ _is = null;
}
- public OutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, object cookie, BasicStream iss,
- BasicStream os) :
- base(prx.ice_getCommunicator(), prx.reference__().getInstance(), operation, cookie, iss, os)
+ public OutgoingAsync(Ice.ObjectPrx prx, string operation, object cookie, BasicStream istr, BasicStream ostr) :
+ base((Ice.ObjectPrxHelperBase)prx, operation, cookie, ostr)
{
- _proxy = prx;
- _encoding = Protocol.getCompatibleEncoding(_proxy.reference__().getEncoding());
+ _encoding = Protocol.getCompatibleEncoding(proxy_.reference__().getEncoding());
+ _is = istr;
}
- public void prepare(string operation, Ice.OperationMode mode, Dictionary<string, string> context,
- bool explicitContext, bool synchronous)
+ public void prepare(string operation, Ice.OperationMode mode, Dictionary<string, string> ctx,
+ bool explicitCtx, bool synchronous)
{
- handler_ = null;
- _sent = false;
- cnt_ = 0;
- _mode = mode;
- sentSynchronously_ = false;
- synchronous_ = synchronous;
+ Protocol.checkSupportedProtocol(Protocol.getCompatibleProtocol(proxy_.reference__().getProtocol()));
- Protocol.checkSupportedProtocol(Protocol.getCompatibleProtocol(_proxy.reference__().getProtocol()));
+ mode_ = mode;
+ _synchronous = synchronous;
- if(explicitContext && context == null)
+ if(explicitCtx && ctx == null)
{
- context = emptyContext_;
+ ctx = _emptyContext;
}
+ observer_ = ObserverHelper.get(proxy_, operation, ctx);
- observer_ = ObserverHelper.get(_proxy, operation, context);
-
- switch(_proxy.reference__().getMode())
+ switch(proxy_.reference__().getMode())
{
case Reference.Mode.ModeTwoway:
case Reference.Mode.ModeOneway:
@@ -831,14 +409,14 @@ namespace IceInternal
{
try
{
- handler_ = _proxy.getRequestHandler__();
+ handler_ = proxy_.getRequestHandler__();
handler_.prepareBatchRequest(os_);
break;
}
catch(RetryException)
{
// Clear request handler and retry.
- _proxy.setRequestHandler__(handler_, null);
+ proxy_.setRequestHandler__(handler_, null);
}
catch(Ice.LocalException ex)
{
@@ -847,7 +425,7 @@ namespace IceInternal
observer_.failed(ex.ice_name());
}
// Clear request handler
- _proxy.setRequestHandler__(handler_, null);
+ proxy_.setRequestHandler__(handler_, null);
handler_ = null;
throw ex;
}
@@ -856,7 +434,7 @@ namespace IceInternal
}
}
- Reference rf = _proxy.reference__();
+ Reference rf = proxy_.reference__();
rf.getIdentity().write__(os_);
@@ -878,12 +456,12 @@ namespace IceInternal
os_.writeByte((byte)mode);
- if(context != null)
+ if(ctx != null)
{
//
// Explicit context
//
- Ice.ContextHelper.write(os_, context);
+ Ice.ContextHelper.write(os_, ctx);
}
else
{
@@ -904,422 +482,215 @@ namespace IceInternal
}
}
- public override Ice.ObjectPrx getProxy()
- {
- return _proxy;
- }
-
- public virtual bool send(Ice.ConnectionI connection, bool compress, bool response, out Ice.AsyncCallback sentCB)
+ public override bool send(Ice.ConnectionI con, bool compress, bool response, out Ice.AsyncCallback sentCB)
{
- // Store away the connection for passing to the dispatcher.
- cachedConnection_ = connection;
- return connection.sendAsyncRequest(this, compress, response, out sentCB);
+ cachedConnection_ = con;
+ return con.sendAsyncRequest(this, compress, response, out sentCB);
}
- public virtual bool invokeCollocated(CollocatedRequestHandler handler, out Ice.AsyncCallback sentCallback)
+ public override bool invokeCollocated(CollocatedRequestHandler handler, out Ice.AsyncCallback sentCB)
{
- // The BasicStream cannot be cached if the proxy is
- // not a twoway or there is an invocation timeout set.
- if(!_proxy.ice_isTwoway() || _proxy.reference__().getInvocationTimeout() > 0)
+ // The BasicStream cannot be cached if the proxy is not a twoway or there is an invocation timeout set.
+ if(!proxy_.ice_isTwoway() || proxy_.reference__().getInvocationTimeout() > 0)
{
// Disable caching by marking the streams as cached!
state_ |= StateCachedBuffers;
}
- handler.invokeAsyncRequest(this, synchronous_, out sentCallback);
- return false;
+ return handler.invokeAsyncRequest(this, _synchronous, out sentCB);
}
- public virtual Ice.AsyncCallback sent()
+ public override void abort(Ice.Exception ex)
{
- lock(monitor_)
+ Reference.Mode mode = proxy_.reference__().getMode();
+ if(mode == Reference.Mode.ModeBatchOneway || mode == Reference.Mode.ModeBatchDatagram)
{
- bool alreadySent = (state_ & StateSent) != 0;
- state_ |= StateSent;
- _sent = true;
-
- Debug.Assert((state_ & StateDone) == 0);
- if(!_proxy.ice_isTwoway())
+ if(handler_ != null)
{
- if(childObserver_ != null)
- {
- childObserver_.detach();
- childObserver_ = null;
- }
- if(observer_ != null && sentCallback_ == null)
- {
- observer_.detach();
- observer_ = null;
- }
- if(timeoutRequestHandler_ != null)
- {
- instance_.timer().cancel(this);
- timeoutRequestHandler_ = null;
- }
- state_ |= StateDone | StateOK;
- //_os.resize(0, false); // Don't clear the buffer now, it's needed for the collocation optimization
- if(waitHandle_ != null)
- {
- waitHandle_.Set();
- }
+ //
+ // If we didn't finish a batch oneway or datagram request, we
+ // must notify the connection about that we give up ownership
+ // of the batch stream.
+ //
+ handler_.abortBatchRequest();
}
- System.Threading.Monitor.PulseAll(monitor_);
-
- return alreadySent ? null : sentCallback_; // Don't call the sent call is already sent.
}
- }
-
- public virtual new void invokeSent(Ice.AsyncCallback cb)
- {
- base.invokeSent(cb);
- }
- public virtual new void invokeCompleted(Ice.AsyncCallback cb)
- {
- base.invokeCompleted(cb);
+ base.abort(ex);
}
- public virtual void finished(Ice.Exception exc)
+ public void invoke()
{
- lock(monitor_)
+ Reference.Mode mode = proxy_.reference__().getMode();
+ if(mode == Reference.Mode.ModeBatchOneway || mode == Reference.Mode.ModeBatchDatagram)
{
- Debug.Assert((state_ & StateDone) == 0);
- if(childObserver_ != null)
- {
- childObserver_.failed(exc.ice_name());
- childObserver_.detach();
- childObserver_ = null;
- }
- if(timeoutRequestHandler_ != null)
+ if(handler_ != null)
{
- instance_.timer().cancel(this);
- timeoutRequestHandler_ = null;
+ sentSynchronously_ = true;
+ handler_.finishBatchRequest(os_);
+ finished(true);
}
+ return; // Don't call sent/completed callback for batch AMI requests
}
//
- // NOTE: at this point, synchronization isn't needed, no other threads should be
- // calling on the callback.
+ // NOTE: invokeImpl doesn't throw so this can be called from the
+ // try block with the catch block calling abort() in case of an
+ // exception.
//
- try
- {
- handleException(exc);
- }
- catch(Ice.Exception ex)
- {
- invokeException(ex);
- }
+ invokeImpl(true); // userThread = true
}
- internal override void processRetry()
+ public Ice.AsyncCallback completed()
{
- invoke(false);
- }
+ Debug.Assert(_is != null); // _is has been initialized prior to this call
- public void
- dispatchInvocationCancel(Ice.LocalException ex, ThreadPool threadPool, Ice.Connection connection)
- {
- OutgoingAsync self = this;
- threadPool.dispatch(() =>
- {
- self.finished(ex);
- }, connection);
- }
+ //
+ // NOTE: this method is called from ConnectionI.parseMessage
+ // with the connection locked. Therefore, it must not invoke
+ // any user callbacks.
+ //
- public Ice.AsyncCallback finished()
- {
- Debug.Assert(_proxy.ice_isTwoway()); // Can only be called for twoways.
+ Debug.Assert(proxy_.ice_isTwoway()); // Can only be called for twoways.
+
+ if(childObserver_ != null)
+ {
+ childObserver_.reply(_is.size() - Protocol.headerSize - 4);
+ childObserver_.detach();
+ childObserver_ = null;
+ }
byte replyStatus;
try
{
- lock(monitor_)
- {
- Debug.Assert(exception_ == null && (state_ & StateDone) == 0);
- Debug.Assert(is_ != null);
+ replyStatus = _is.readByte();
- if(childObserver_ != null)
- {
- childObserver_.reply(is_.size() - Protocol.headerSize - 4);
- childObserver_.detach();
- childObserver_ = null;
- }
+ switch(replyStatus)
+ {
+ case ReplyStatus.replyOK:
+ {
+ break;
+ }
- if(timeoutRequestHandler_ != null)
+ case ReplyStatus.replyUserException:
+ {
+ if(observer_ != null)
{
- instance_.timer().cancel(this);
- timeoutRequestHandler_ = null;
+ observer_.userException();
}
+ break;
+ }
- replyStatus = is_.readByte();
+ case ReplyStatus.replyObjectNotExist:
+ case ReplyStatus.replyFacetNotExist:
+ case ReplyStatus.replyOperationNotExist:
+ {
+ Ice.Identity id = new Ice.Identity();
+ id.read__(_is);
- switch(replyStatus)
+ //
+ // For compatibility with the old FacetPath.
+ //
+ string[] facetPath = _is.readStringSeq();
+ string facet;
+ if(facetPath.Length > 0)
{
- case ReplyStatus.replyOK:
- {
- break;
- }
-
- case ReplyStatus.replyUserException:
- {
- if(observer_ != null)
- {
- observer_.userException();
- }
- break;
- }
-
- case ReplyStatus.replyObjectNotExist:
- case ReplyStatus.replyFacetNotExist:
- case ReplyStatus.replyOperationNotExist:
+ if(facetPath.Length > 1)
{
- Ice.Identity id = new Ice.Identity();
- id.read__(is_);
-
- //
- // For compatibility with the old FacetPath.
- //
- string[] facetPath = is_.readStringSeq();
- string facet;
- if(facetPath.Length > 0)
- {
- if(facetPath.Length > 1)
- {
- throw new Ice.MarshalException();
- }
- facet = facetPath[0];
- }
- else
- {
- facet = "";
- }
-
- string operation = is_.readString();
-
- Ice.RequestFailedException ex = null;
- switch(replyStatus)
- {
- case ReplyStatus.replyObjectNotExist:
- {
- ex = new Ice.ObjectNotExistException();
- break;
- }
-
- case ReplyStatus.replyFacetNotExist:
- {
- ex = new Ice.FacetNotExistException();
- break;
- }
-
- case ReplyStatus.replyOperationNotExist:
- {
- ex = new Ice.OperationNotExistException();
- break;
- }
-
- default:
- {
- Debug.Assert(false);
- break;
- }
- }
-
- ex.id = id;
- ex.facet = facet;;
- ex.operation = operation;
- throw ex;
+ throw new Ice.MarshalException();
}
+ facet = facetPath[0];
+ }
+ else
+ {
+ facet = "";
+ }
- case ReplyStatus.replyUnknownException:
- case ReplyStatus.replyUnknownLocalException:
- case ReplyStatus.replyUnknownUserException:
- {
- string unknown = is_.readString();
+ string operation = _is.readString();
- Ice.UnknownException ex = null;
- switch(replyStatus)
- {
- case ReplyStatus.replyUnknownException:
- {
- ex = new Ice.UnknownException();
- break;
- }
- case ReplyStatus.replyUnknownLocalException:
- {
- ex = new Ice.UnknownLocalException();
- break;
- }
- case ReplyStatus.replyUnknownUserException:
- {
- ex = new Ice.UnknownUserException();
- break;
- }
- default:
- {
- Debug.Assert(false);
- break;
- }
- }
- ex.unknown = unknown;
- throw ex;
- }
-
- default:
- {
- throw new Ice.UnknownReplyStatusException();
- }
+ Ice.RequestFailedException ex = null;
+ switch(replyStatus)
+ {
+ case ReplyStatus.replyObjectNotExist:
+ {
+ ex = new Ice.ObjectNotExistException();
+ break;
}
- state_ |= StateDone;
- //os_.resize(0, false); // Clear buffer now, instead of waiting for AsyncResult deallocation
- if(waitHandle_ != null)
+ case ReplyStatus.replyFacetNotExist:
{
- waitHandle_.Set();
+ ex = new Ice.FacetNotExistException();
+ break;
}
- if(replyStatus == ReplyStatus.replyOK)
+
+ case ReplyStatus.replyOperationNotExist:
{
- state_ |= StateOK;
+ ex = new Ice.OperationNotExistException();
+ break;
}
- System.Threading.Monitor.PulseAll(monitor_);
- if(completedCallback_ == null)
+ default:
{
- if(observer_ != null)
- {
- observer_.detach();
- observer_ = null;
- }
- return null;
+ Debug.Assert(false);
+ break;
}
- return completedCallback_;
- }
- }
- catch(Ice.LocalException exc)
- {
- //
- // We don't call finished(exc) here because we don't want
- // to invoke the completion callback. The completion
- // callback is invoked by the connection is this method
- // returns true.
- //
- try
- {
- handleException(exc);
- return null;
+ }
+
+ ex.id = id;
+ ex.facet = facet;
+ ex.operation = operation;
+ throw ex;
}
- catch(Ice.LocalException ex)
+
+ case ReplyStatus.replyUnknownException:
+ case ReplyStatus.replyUnknownLocalException:
+ case ReplyStatus.replyUnknownUserException:
{
- lock(monitor_)
- {
- state_ |= StateDone;
- exception_ = ex;
- if(waitHandle_ != null)
- {
- waitHandle_.Set();
- }
- System.Threading.Monitor.PulseAll(monitor_);
+ string unknown = _is.readString();
- if(completedCallback_ == null)
- {
- if(observer_ != null)
- {
- observer_.detach();
- observer_ = null;
- }
- return null;
- }
- return completedCallback_;
+ Ice.UnknownException ex = null;
+ switch(replyStatus)
+ {
+ case ReplyStatus.replyUnknownException:
+ {
+ ex = new Ice.UnknownException();
+ break;
}
- }
- }
- }
- public bool invoke(bool userThread)
- {
- Reference.Mode mode = _proxy.reference__().getMode();
- if(mode == Reference.Mode.ModeBatchOneway || mode == Reference.Mode.ModeBatchDatagram)
- {
- state_ |= StateDone | StateOK;
- handler_.finishBatchRequest(os_);
- if(observer_ != null)
- {
- observer_.detach();
- observer_ = null;
- }
- return true;
- }
+ case ReplyStatus.replyUnknownLocalException:
+ {
+ ex = new Ice.UnknownLocalException();
+ break;
+ }
- while(true)
- {
- try
- {
- _sent = false;
- handler_ = _proxy.getRequestHandler__();
- Ice.AsyncCallback sentCallback;
- bool sent = handler_.sendAsyncRequest(this, out sentCallback);
- if(sent)
+ case ReplyStatus.replyUnknownUserException:
{
- if(userThread) // Only set sentSynchronously_ If called synchronously by the user thread.
- {
- sentSynchronously_ = true;
- invokeSent(sentCallback);
- }
- else
- {
- invokeSentAsync(sentCallback);
- }
+ ex = new Ice.UnknownUserException();
+ break;
}
- if(_proxy.ice_isTwoway() || !sent)
+ default:
{
- lock(monitor_)
- {
- if((state_ & StateDone) == 0)
- {
- int invocationTimeout = handler_.getReference().getInvocationTimeout();
- if(invocationTimeout > 0)
- {
- instance_.timer().schedule(this, invocationTimeout);
- timeoutRequestHandler_ = handler_;
- }
- }
- }
+ Debug.Assert(false);
+ break;
+ }
}
- }
- catch(RetryException)
- {
- _proxy.setRequestHandler__(handler_, null); // Clear request handler and retry.
- continue;
+ ex.unknown = unknown;
+ throw ex;
}
- catch(Ice.Exception ex)
+
+ default:
{
- handleException(ex);
+ throw new Ice.UnknownReplyStatusException();
+ }
}
- break;
- }
- return sentSynchronously_;
- }
-
- public IceInternal.BasicStream startReadParams()
- {
- is_.startReadEncaps();
- return is_;
- }
-
- public void endReadParams()
- {
- is_.endReadEncaps();
- }
-
- public void readEmptyParams()
- {
- is_.skipEmptyEncaps();
- }
- public byte[] readParamEncaps()
- {
- Ice.EncodingVersion encoding;
- return is_.readEncaps(out encoding);
+ return finished(replyStatus == ReplyStatus.replyOK);
+ }
+ catch(Ice.Exception ex)
+ {
+ return completed(ex);
+ }
}
public BasicStream startWriteParams(Ice.FormatType format)
@@ -1350,326 +721,353 @@ namespace IceInternal
}
}
- public IceInternal.BasicStream istr__
+ public IceInternal.BasicStream startReadParams()
{
- get
+ _is.startReadEncaps();
+ return _is;
+ }
+
+ public void endReadParams()
+ {
+ _is.endReadEncaps();
+ }
+
+ public void readEmptyParams()
+ {
+ _is.skipEmptyEncaps();
+ }
+
+ public byte[] readParamEncaps()
+ {
+ Ice.EncodingVersion encoding;
+ return _is.readEncaps(out encoding);
+ }
+
+ public BasicStream getIs()
+ {
+ // _is can already be initialized if the invocation is retried
+ if(_is == null)
{
- if(is_ == null) // _is can already be initialized if the invocation is retried
- {
- is_ = new IceInternal.BasicStream(instance_, Ice.Util.currentProtocolEncoding);
- }
- return is_;
+ _is = new IceInternal.BasicStream(instance_, Ice.Util.currentProtocolEncoding);
}
+ return _is;
}
- public void
- runTimerTask()
+ public void throwUserException()
{
- runTimerTask__();
+ try
+ {
+ _is.startReadEncaps();
+ _is.throwException(null);
+ }
+ catch(Ice.UserException ex)
+ {
+ _is.endReadEncaps();
+ throw ex;
+ }
}
- public void
- cacheMessageBuffers()
+ public override void cacheMessageBuffers()
{
- if(_proxy.reference__().getInstance().cacheMessageBuffers() > 0)
+ if(proxy_.reference__().getInstance().cacheMessageBuffers() > 0)
{
lock(this)
{
- if((state_ & StateCachedBuffers) > 0) {
+ if((state_ & StateCachedBuffers) > 0)
+ {
return;
}
state_ |= StateCachedBuffers;
}
- if(is_ != null)
+ if(_is != null)
{
- is_.reset();
+ _is.reset();
}
os_.reset();
- _proxy.cacheMessageBuffers(is_, os_);
+ proxy_.cacheMessageBuffers(_is, os_);
+
+ _is = null;
+ os_ = null;
}
}
- override public void invokeExceptionAsync(Ice.Exception ex)
+ private Ice.EncodingVersion _encoding;
+ private BasicStream _is;
+
+ //
+ // If true this AMI request is being used for a generated synchronous invocation.
+ //
+ private bool _synchronous;
+
+ private static Dictionary<string, string> _emptyContext = new Dictionary<string, string>();
+ }
+
+ public class CommunicatorFlushBatch : IceInternal.AsyncResultI
+ {
+ public static CommunicatorFlushBatch check(Ice.AsyncResult r, Ice.Communicator com, string operation)
{
- if((state_ & StateDone) == 0 && handler_ != null)
+ if(r != null && r.getCommunicator() != com)
{
- //
- // If we didn't finish a batch oneway or datagram request, we
- // must notify the connection about that we give up ownership
- // of the batch stream.
- //
- Reference.Mode mode = _proxy.reference__().getMode();
- if(mode == Reference.Mode.ModeBatchOneway || mode == Reference.Mode.ModeBatchDatagram)
- {
- handler_.abortBatchRequest();
- }
+ throw new System.ArgumentException("Communicator for call to end_" + operation +
+ " does not match communicator that was used to call " +
+ "corresponding begin_" + operation + " method");
}
- base.invokeExceptionAsync(ex);
+ return AsyncResultI.check<CommunicatorFlushBatch>(r, operation);
}
+
+ public CommunicatorFlushBatch(Ice.Communicator communicator, Instance instance, string op, object cookie) :
+ base(communicator, instance, op, cookie)
+ {
- private void handleException(Ice.Exception exc)
+ observer_ = ObserverHelper.get(instance, op);
+
+ //
+ // _useCount is initialized to 1 to prevent premature callbacks.
+ // The caller must invoke ready() after all flush requests have
+ // been initiated.
+ //
+ _useCount = 1;
+ }
+
+ public void flushConnection(Ice.ConnectionI con)
{
+ lock(this)
+ {
+ ++_useCount;
+ }
+
try
{
- int interval = _proxy.handleException__(exc, handler_, _mode, _sent, ref cnt_);
- if(observer_ != null)
+ Ice.AsyncCallback sentCB;
+ con.flushAsyncBatchRequests(new FlushBatch(this), out sentCB);
+ Debug.Assert(sentCB == null);
+ }
+ catch(Ice.LocalException ex)
+ {
+ doCheck(false);
+ throw ex;
+ }
+ }
+
+ public void ready()
+ {
+ doCheck(true);
+ }
+
+ private void doCheck(bool userThread)
+ {
+ lock(this)
+ {
+ Debug.Assert(_useCount > 0);
+ if(--_useCount > 0)
{
- observer_.retried(); // Invocation is being retried.
+ return;
}
+ }
- //
- // Schedule the retry. Note that we always schedule the retry
- // on the retry queue even if the invocation can be retried
- // immediately. This is required because it might not be safe
- // to retry from this thread (this is for instance called by
- // finished(BasicStream) which is called with the connection
- // locked.
- //
- instance_.retryQueue().add(this, interval);
+ Ice.AsyncCallback sentCB = sent(true);
+ if(userThread)
+ {
+ sentSynchronously_ = true;
+ if(sentCB != null)
+ {
+ invokeSent(sentCB);
+ }
}
- catch(Ice.Exception ex)
+ else
{
- if(observer_ != null)
+ if(sentCB != null)
{
- observer_.failed(ex.ice_name());
+ invokeSentAsync(sentCB);
}
- throw ex;
}
}
- private class TaskI : TimerTask
+ class FlushBatch : OutgoingAsyncBase
{
- internal TaskI(OutgoingAsync @out)
+ public FlushBatch(CommunicatorFlushBatch outAsync) :
+ base(outAsync.getCommunicator(), outAsync.instance_, outAsync.getOperation(), null)
{
- _out = @out;
+ _outAsync = outAsync;
}
- public void runTimerTask()
+ public override Ice.AsyncCallback sent()
{
- _out.runTimerTask__();
+ if(childObserver_ != null)
+ {
+ childObserver_.detach();
+ childObserver_ = null;
+ }
+ _outAsync.doCheck(false);
+ return null;
+ }
+
+ public override Ice.AsyncCallback completed(Ice.Exception ex)
+ {
+ if(childObserver_ != null)
+ {
+ childObserver_.failed(ex.ice_name());
+ childObserver_.detach();
+ childObserver_ = null;
+ }
+ _outAsync.doCheck(false);
+ return null;
+ }
+
+ protected override Ice.Instrumentation.InvocationObserver getObserver()
+ {
+ return _outAsync.getObserver();
}
- private OutgoingAsync _out;
- }
-
- private readonly Ice.ObjectPrxHelperBase _proxy;
- private readonly Ice.EncodingVersion _encoding;
-
- private RequestHandler handler_;
- private int cnt_;
- private Ice.OperationMode _mode;
- private bool _sent;
-
- private static Dictionary<string, string> emptyContext_ = new Dictionary<string, string>();
+ private CommunicatorFlushBatch _outAsync;
+ };
+ private int _useCount;
}
- abstract public class OutgoingAsync<T> : OutgoingAsync, Ice.AsyncResult<T>
+
+ public class ConnectionFlushBatch : OutgoingAsyncBase
{
- public OutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, object cookie) :
- base(prx, operation, cookie)
+ public static ConnectionFlushBatch check(Ice.AsyncResult r, Ice.Connection con, string operation)
{
+ if(r != null && r.getConnection() != con)
+ {
+ throw new System.ArgumentException("Connection for call to end_" + operation +
+ " does not match connection that was used to call " +
+ "corresponding begin_" + operation + " method");
+ }
+ return AsyncResultI.check<ConnectionFlushBatch>(r, operation);
}
- public OutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, object cookie, BasicStream iss,
- BasicStream os) :
- base(prx, operation, cookie, iss, os)
+ public ConnectionFlushBatch(Ice.ConnectionI con, Ice.Communicator communicator, Instance instance, string op,
+ object cookie) :
+ base(communicator, instance, op, cookie)
{
+ _connection = con;
}
- new public Ice.AsyncResult<T> whenCompleted(Ice.ExceptionCallback excb)
+ public override Ice.Connection getConnection()
{
- base.whenCompleted(excb);
- return this;
+ return _connection;
}
- virtual public Ice.AsyncResult<T> whenCompleted(T cb, Ice.ExceptionCallback excb)
+ public void invoke()
{
- if(cb == null && excb == null)
+ try
{
- throw new System.ArgumentException("callback is null");
+ Ice.AsyncCallback sentCB;
+ if(_connection.flushAsyncBatchRequests(this, out sentCB))
+ {
+ sentSynchronously_ = true;
+ if(sentCB != null)
+ {
+ invokeSent(sentCB);
+ }
+ }
}
- lock(monitor_)
+ catch(Ice.Exception ex)
{
- if(responseCallback_ != null || exceptionCallback_ != null)
+ Ice.AsyncCallback cb = completed(ex);
+ if(cb != null)
{
- throw new System.ArgumentException("callback already set");
+ invokeCompletedAsync(cb);
}
- responseCallback_ = cb;
- exceptionCallback_ = excb;
}
- setCompletedCallback(getCompletedCallback());
- return this;
- }
-
- new public Ice.AsyncResult<T> whenSent(Ice.SentCallback cb)
- {
- base.whenSent(cb);
- return this;
}
- protected T responseCallback_;
+ private Ice.ConnectionI _connection;
}
- public class TwowayOutgoingAsync<T> : OutgoingAsync<T>
+ public class ProxyFlushBatch : ProxyOutgoingAsyncBase
{
- public TwowayOutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, ProxyTwowayCallback<T> cb,
- object cookie) :
- base(prx, operation, cookie)
- {
- Debug.Assert(cb != null);
- _completed = cb;
- }
-
- public TwowayOutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, ProxyTwowayCallback<T> cb,
- object cookie, BasicStream iss, BasicStream os) :
- base(prx, operation, cookie, iss, os)
+ public new static ProxyFlushBatch check(Ice.AsyncResult r, Ice.ObjectPrx prx, string operation)
{
- Debug.Assert(cb != null);
- _completed = cb;
+ return ProxyOutgoingAsyncBase.check<ProxyFlushBatch>(r, prx, operation);
}
- override protected Ice.AsyncCallback getCompletedCallback()
- {
- return (Ice.AsyncResult result) => { _completed(this, responseCallback_, exceptionCallback_); };
- }
-
- private ProxyTwowayCallback<T> _completed;
- }
-
- public class OnewayOutgoingAsync<T> : OutgoingAsync<T>
- {
- public OnewayOutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, ProxyOnewayCallback<T> cb,
- object cookie) :
+ public ProxyFlushBatch(Ice.ObjectPrxHelperBase prx, string operation, object cookie) :
base(prx, operation, cookie)
{
- Debug.Assert(cb != null);
- _completed = cb;
+ observer_ = ObserverHelper.get(prx, operation);
}
- public OnewayOutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, ProxyOnewayCallback<T> cb,
- object cookie, BasicStream iss, BasicStream os) :
- base(prx, operation, cookie, iss, os)
+ public override Ice.AsyncCallback sent()
{
- Debug.Assert(cb != null);
- _completed = cb;
+ return sent(true); // Overriden because the flush is done even if using a two-way proxy.
}
- override protected Ice.AsyncCallback getCompletedCallback()
+ public override bool send(Ice.ConnectionI con, bool compress, bool response, out Ice.AsyncCallback sentCB)
{
- return (Ice.AsyncResult result) => {
- try
- {
- IceInternal.OutgoingAsync outAsync__ = (IceInternal.OutgoingAsync)result;
- ((Ice.ObjectPrxHelperBase)(outAsync__.getProxy())).end__(outAsync__, outAsync__.getOperation());
- }
- catch(Ice.Exception ex__)
- {
- if(exceptionCallback_ != null)
- {
- exceptionCallback_(ex__);
- }
- return;
- }
- _completed(responseCallback_);
- };
+ cachedConnection_ = con;
+ return con.flushAsyncBatchRequests(this, out sentCB);
}
- private ProxyOnewayCallback<T> _completed;
- }
-
- public class GetConnectionOutgoingAsync : OutgoingAsyncBase, OutgoingAsyncMessageCallback,
- Ice.AsyncResult<Ice.Callback_Object_ice_getConnection>
- {
- public GetConnectionOutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation,
- ProxyTwowayCallback<Ice.Callback_Object_ice_getConnection> cb,
- object cookie) :
- base(prx.ice_getCommunicator(), prx.reference__().getInstance(), operation, cookie)
+ public override bool invokeCollocated(CollocatedRequestHandler handler, out Ice.AsyncCallback sentCB)
{
- _proxy = prx;
- _completed = cb;
- _cnt = 0;
- observer_ = ObserverHelper.get(prx, operation);
+ return handler.invokeAsyncBatchRequests(this, out sentCB);
}
public void invoke()
{
- while(true)
- {
- try
- {
- _handler = _proxy.getRequestHandler__();
- Ice.AsyncCallback sentCallback;
- _handler.sendAsyncRequest(this, out sentCallback);
- }
- catch(RetryException)
- {
- _proxy.setRequestHandler__(_handler, null);
- }
- catch(Ice.Exception ex)
- {
- handleException(ex);
- }
- break;
- }
+ Protocol.checkSupportedProtocol(Protocol.getCompatibleProtocol(proxy_.reference__().getProtocol()));
+ invokeImpl(true); // userThread = true
}
- public bool send(Ice.ConnectionI connection, bool compress, bool response, out Ice.AsyncCallback sentCallback)
+ protected override void handleRetryException(RetryException exc)
{
- sent();
- sentCallback = null;
- return false;
+ proxy_.setRequestHandler__(handler_, null); // Clear request handler
+ throw exc.get(); // No retries, we want to notify the user of potentially lost batch requests
}
- public bool invokeCollocated(CollocatedRequestHandler handler, out Ice.AsyncCallback sentCallback)
+ protected override int handleException(Ice.Exception exc)
{
- sent();
- sentCallback = null;
- return false;
+ proxy_.setRequestHandler__(handler_, null); // Clear request handler
+ throw exc; // No retries, we want to notify the user of potentially lost batch requests
}
+ }
- public Ice.AsyncCallback sent()
+ public class ProxyGetConnection : ProxyOutgoingAsyncBase, Ice.AsyncResult<Ice.Callback_Object_ice_getConnection>
+ {
+ public new static ProxyGetConnection check(Ice.AsyncResult r, Ice.ObjectPrx prx, string operation)
{
- lock(monitor_)
- {
- state_ |= StateDone;
- System.Threading.Monitor.PulseAll(monitor_);
- }
- invokeCompleted(completedCallback_);
- return null;
+ return ProxyOutgoingAsyncBase.check<ProxyGetConnection>(r, prx, operation);
}
- new public void invokeSent(Ice.AsyncCallback cb)
+ public ProxyGetConnection(Ice.ObjectPrxHelperBase prx, string operation,
+ ProxyTwowayCallback<Ice.Callback_Object_ice_getConnection> cb, object cookie) :
+ base(prx, operation, cookie)
{
- // No sent callback
+ observer_ = ObserverHelper.get(prx, operation);
+ _completed = cb;
}
- public void finished(Ice.Exception exc)
+ public override bool send(Ice.ConnectionI con, bool compress, bool response, out Ice.AsyncCallback sentCB)
{
- try
- {
- handleException(exc);
- }
- catch(Ice.Exception ex)
+ sentCB = null;
+ cachedConnection_ = con;
+ Ice.AsyncCallback cb = finished(true);
+ if(cb != null)
{
- invokeExceptionAsync(ex);
+ invokeCompletedAsync(cb);
}
+ return true;
}
- internal override void processRetry()
+ public override bool invokeCollocated(CollocatedRequestHandler handler, out Ice.AsyncCallback sentCB)
{
- invoke();
+ sentCB = null;
+ Ice.AsyncCallback cb = finished(true);
+ if(cb != null)
+ {
+ invokeCompletedAsync(cb);
+ }
+ return true;
}
- public void
- dispatchInvocationCancel(Ice.LocalException ex, ThreadPool threadPool, Ice.Connection connection)
+ public void invoke()
{
- GetConnectionOutgoingAsync self = this;
- threadPool.dispatch(() =>
- {
- self.finished(ex);
- }, connection);
+ invokeImpl(true); // userThread = true
}
new public Ice.AsyncResult<Ice.Callback_Object_ice_getConnection> whenCompleted(Ice.ExceptionCallback excb)
@@ -1685,7 +1083,7 @@ namespace IceInternal
{
throw new System.ArgumentException("callback is null");
}
- lock(monitor_)
+ lock(this)
{
if(_responseCallback != null || exceptionCallback_ != null)
{
@@ -1704,391 +1102,127 @@ namespace IceInternal
return this;
}
- public override Ice.ObjectPrx getProxy()
- {
- return _proxy;
- }
-
protected override Ice.AsyncCallback getCompletedCallback()
{
return (Ice.AsyncResult result) => { _completed(this, _responseCallback, exceptionCallback_); };
}
- private void handleException(Ice.Exception exc)
- {
- try
- {
- instance_.retryQueue().add(this, _proxy.handleException__(exc, _handler, Ice.OperationMode.Idempotent,
- false, ref _cnt));
- if(observer_ != null)
- {
- observer_.retried(); // Invocation is being retried
- }
- }
- catch(Ice.Exception ex)
- {
- if(observer_ != null)
- {
- observer_.failed(ex.ice_name());
- }
- throw ex;
- }
- }
-
- private readonly Ice.ObjectPrxHelperBase _proxy;
private ProxyTwowayCallback<Ice.Callback_Object_ice_getConnection> _completed;
- private int _cnt;
-
private Ice.Callback_Object_ice_getConnection _responseCallback = null;
- private RequestHandler _handler = null;
}
- public class BatchOutgoingAsync : OutgoingAsyncBase, OutgoingAsyncMessageCallback, TimerTask
+ public abstract class OutgoingAsync<T> : OutgoingAsync, Ice.AsyncResult<T>
{
- public BatchOutgoingAsync(Ice.Communicator communicator, Instance instance, string operation, object cookie) :
- base(communicator, instance, operation, cookie)
+ public OutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, object cookie) :
+ base(prx, operation, cookie)
{
}
- public bool send(Ice.ConnectionI connection, bool compress, bool response, out Ice.AsyncCallback sentCallback)
+ public OutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, object cookie, BasicStream iss,
+ BasicStream os) :
+ base(prx, operation, cookie, iss, os)
{
- // Store away the connection for passing to the dispatcher.
- cachedConnection_ = connection;
- return connection.flushAsyncBatchRequests(this, out sentCallback);
}
- public bool invokeCollocated(CollocatedRequestHandler handler, out Ice.AsyncCallback sentCallback)
+ new public Ice.AsyncResult<T> whenCompleted(Ice.ExceptionCallback excb)
{
- return handler.invokeAsyncBatchRequests(this, out sentCallback);
+ base.whenCompleted(excb);
+ return this;
}
- virtual public Ice.AsyncCallback sent()
+ virtual public Ice.AsyncResult<T> whenCompleted(T cb, Ice.ExceptionCallback excb)
{
- lock(monitor_)
+ if(cb == null && excb == null)
{
- Debug.Assert((state_ & (StateDone | StateOK | StateSent)) == 0);
- state_ |= (StateDone | StateOK | StateSent);
- //_os.resize(0, false); // Don't clear the buffer now, it's needed for the collocation optimization
- if(childObserver_ != null)
- {
- childObserver_.detach();
- childObserver_ = null;
- }
- if(timeoutRequestHandler_ != null)
- {
- instance_.timer().cancel(this);
- timeoutRequestHandler_ = null;
- }
- System.Threading.Monitor.PulseAll(monitor_);
- if(waitHandle_ != null)
- {
- waitHandle_.Set();
- }
-
- if(sentCallback_ == null)
- {
- if(observer_ != null)
- {
- observer_.detach();
- observer_ = null;
- }
- }
- return sentCallback_;
+ throw new System.ArgumentException("callback is null");
}
- }
-
- public new void invokeSent(Ice.AsyncCallback cb)
- {
- base.invokeSent(cb);
- }
-
- virtual public void finished(Ice.Exception exc)
- {
lock(this)
{
- if(childObserver_ != null)
- {
- childObserver_.failed(exc.ice_name());
- childObserver_.detach();
- childObserver_ = null;
- }
- if(timeoutRequestHandler_ != null)
- {
- instance_.timer().cancel(this);
- timeoutRequestHandler_ = null;
- }
- }
- invokeException(exc);
- }
-
- internal override void processRetry()
- {
- Debug.Assert(false); // Retries are never scheduled.
- }
-
- public void
- dispatchInvocationCancel(Ice.LocalException ex, ThreadPool threadPool, Ice.Connection connection)
- {
- BatchOutgoingAsync self = this;
- threadPool.dispatch(() =>
- {
- self.finished(ex);
- }, connection);
- }
-
- public void
- runTimerTask()
- {
- runTimerTask__();
- }
- }
-
- public class ProxyBatchOutgoingAsync : BatchOutgoingAsync
- {
- public ProxyBatchOutgoingAsync(Ice.ObjectPrxHelperBase proxy, string operation, object cookie) :
- base(proxy.ice_getCommunicator(), proxy.reference__().getInstance(), operation, cookie)
- {
- _proxy = proxy;
- observer_ = ObserverHelper.get(proxy, operation);
- }
-
- public void invoke()
- {
- Protocol.checkSupportedProtocol(_proxy.reference__().getProtocol());
-
- RequestHandler handler = null;
- try
- {
- handler = _proxy.getRequestHandler__();
- Ice.AsyncCallback sentCallback;
- if(handler.sendAsyncRequest(this, out sentCallback))
- {
- sentSynchronously_ = true;
- if(sentCallback != null)
- {
- invokeSent(sentCallback);
- }
- }
- else
- {
- lock(monitor_)
- {
- if((state_ & StateDone) == 0)
- {
- int invocationTimeout = handler.getReference().getInvocationTimeout();
- if(invocationTimeout > 0)
- {
- instance_.timer().schedule(this, invocationTimeout);
- timeoutRequestHandler_ = handler;
- }
- }
- }
- }
- }
- catch(RetryException)
- {
- //
- // Clear request handler but don't retry or throw. Retrying
- // isn't useful, there were no batch requests associated with
- // the proxy's request handler.
- //
- _proxy.setRequestHandler__(handler, null);
- }
- catch(Ice.Exception ex)
- {
- if(observer_ != null)
+ if(responseCallback_ != null || exceptionCallback_ != null)
{
- observer_.failed(ex.ice_name());
+ throw new System.ArgumentException("callback already set");
}
- _proxy.setRequestHandler__(handler, null); // Clear request handler
- throw ex; // Throw to notify the user lthat batch requests were potentially lost.
+ responseCallback_ = cb;
+ exceptionCallback_ = excb;
}
+ setCompletedCallback(getCompletedCallback());
+ return this;
}
- public override Ice.ObjectPrx getProxy()
+ new public Ice.AsyncResult<T> whenSent(Ice.SentCallback cb)
{
- return _proxy;
+ base.whenSent(cb);
+ return this;
}
- private readonly Ice.ObjectPrxHelperBase _proxy;
+ protected T responseCallback_;
}
- public class ConnectionBatchOutgoingAsync : BatchOutgoingAsync
+ public class TwowayOutgoingAsync<T> : OutgoingAsync<T>
{
- public ConnectionBatchOutgoingAsync(Ice.ConnectionI con, Ice.Communicator communicator, Instance instance,
- string operation, object cookie) :
- base(communicator, instance, operation, cookie)
+ public TwowayOutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, ProxyTwowayCallback<T> cb,
+ object cookie) :
+ base(prx, operation, cookie)
{
- _connection = con;
+ Debug.Assert(cb != null);
+ _completed = cb;
}
- public void invoke()
+ public TwowayOutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, ProxyTwowayCallback<T> cb,
+ object cookie, BasicStream iss, BasicStream os) :
+ base(prx, operation, cookie, iss, os)
{
- Ice.AsyncCallback sentCallback;
- if(_connection.flushAsyncBatchRequests(this, out sentCallback))
- {
- sentSynchronously_ = true;
- invokeSent(sentCallback);
- }
+ Debug.Assert(cb != null);
+ _completed = cb;
}
- public override Ice.Connection getConnection()
+ override protected Ice.AsyncCallback getCompletedCallback()
{
- return _connection;
+ return (Ice.AsyncResult result) => { _completed(this, responseCallback_, exceptionCallback_); };
}
- private Ice.ConnectionI _connection;
+ private ProxyTwowayCallback<T> _completed;
}
- public class CommunicatorBatchOutgoingAsync : OutgoingAsyncBase
+ public class OnewayOutgoingAsync<T> : OutgoingAsync<T>
{
- public CommunicatorBatchOutgoingAsync(Ice.Communicator communicator, Instance instance, String operation,
- object cookie) :
- base(communicator, instance, operation, cookie)
- {
- //
- // _useCount is initialized to 1 to prevent premature callbacks.
- // The caller must invoke ready() after all flush requests have
- // been initiated.
- //
- _useCount = 1;
-
- //
- // Assume all connections are flushed synchronously.
- //
- sentSynchronously_ = true;
-
- //
- // Attach observer
- //
- observer_ = ObserverHelper.get(instance, operation);
- }
-
- public void flushConnection(Ice.ConnectionI con)
- {
- lock(monitor_)
- {
- ++_useCount;
- }
-
-
- try
- {
- Ice.AsyncCallback sentCallback;
- if(!con.flushAsyncBatchRequests(new BatchOutgoingAsyncI(this), out sentCallback))
- {
- sentSynchronously_ = false;
- }
- Debug.Assert(sentCallback == null);
- }
- catch(Ice.LocalException)
- {
- check(false);
- throw;
- }
- }
-
- public void ready()
- {
- check(true);
- }
-
- internal override void processRetry()
+ public OnewayOutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, ProxyOnewayCallback<T> cb,
+ object cookie) :
+ base(prx, operation, cookie)
{
- Debug.Assert(false); // Retries are never scheduled.
+ Debug.Assert(cb != null);
+ _completed = cb;
}
- private void check(bool userThread)
+ public OnewayOutgoingAsync(Ice.ObjectPrxHelperBase prx, string operation, ProxyOnewayCallback<T> cb,
+ object cookie, BasicStream iss, BasicStream os) :
+ base(prx, operation, cookie, iss, os)
{
- Ice.AsyncCallback sentCallback = null;
- lock(monitor_)
- {
- Debug.Assert(_useCount > 0);
- if(--_useCount > 0)
- {
- return;
- }
-
- state_ |= (StateDone | StateOK | StateSent);
- os_.resize(0, false); // Clear buffer now, instead of waiting for AsyncResult deallocation
- sentCallback = sentCallback_;
- System.Threading.Monitor.PulseAll(monitor_);
- if(waitHandle_ != null)
- {
- waitHandle_.Set();
- }
- }
-
- //
- // sentSynchronously_ is immutable here.
- //
- if(sentCallback == null)
- {
- if(observer_ != null)
- {
- observer_.detach();
- observer_ = null;
- }
- }
- else
- {
- if(!sentSynchronously_ || !userThread)
- {
- invokeSentAsync(sentCallback);
- }
- else
- {
- invokeSent(sentCallback);
- }
- }
+ Debug.Assert(cb != null);
+ _completed = cb;
}
- class BatchOutgoingAsyncI : BatchOutgoingAsync
+ override protected Ice.AsyncCallback getCompletedCallback()
{
- public BatchOutgoingAsyncI(CommunicatorBatchOutgoingAsync outAsync) :
- base(outAsync.communicator_, outAsync.instance_, outAsync.operation_, null)
- {
- _outAsync = outAsync;
- }
-
- override public Ice.AsyncCallback sent()
- {
- if(childObserver_ != null)
- {
- childObserver_.detach();
- childObserver_ = null;
- }
- _outAsync.check(false);
- return null;
- }
-
- override public void finished(Ice.Exception ex)
- {
- if(childObserver_ != null)
+ return (Ice.AsyncResult result) =>
+ {
+ try
{
- childObserver_.failed(ex.ice_name());
- childObserver_.detach();
- childObserver_ = null;
+ IceInternal.OutgoingAsync outAsync__ = (IceInternal.OutgoingAsync)result;
+ ((Ice.ObjectPrxHelperBase)(outAsync__.getProxy())).end__(outAsync__, outAsync__.getOperation());
}
- _outAsync.check(false);
- }
-
- override public void attachRemoteObserver(Ice.ConnectionInfo info, Ice.Endpoint endpt,
- int requestId, int sz)
- {
- if(_outAsync.observer_ != null)
+ catch(Ice.Exception ex__)
{
- childObserver_ = _outAsync.observer_.getRemoteObserver(info, endpt, requestId, sz);
- if(childObserver_ != null)
+ if(exceptionCallback_ != null)
{
- childObserver_.attach();
+ exceptionCallback_(ex__);
}
+ return;
}
- }
-
- private CommunicatorBatchOutgoingAsync _outAsync;
- };
+ _completed(responseCallback_);
+ };
+ }
- private int _useCount;
+ private ProxyOnewayCallback<T> _completed;
}
}
diff --git a/cs/src/Ice/Proxy.cs b/cs/src/Ice/Proxy.cs
index fea163fbf6d..c0650815d2b 100644
--- a/cs/src/Ice/Proxy.cs
+++ b/cs/src/Ice/Proxy.cs
@@ -789,8 +789,7 @@ namespace Ice
public bool end_ice_isA(AsyncResult r__)
{
- IceInternal.OutgoingAsync outAsync__ = (IceInternal.OutgoingAsync)r__;
- IceInternal.OutgoingAsync.check(outAsync__, this, __ice_isA_name);
+ IceInternal.OutgoingAsync outAsync__ = IceInternal.OutgoingAsync.check(r__, this, __ice_isA_name);
try
{
if(!outAsync__.wait())
@@ -841,11 +840,11 @@ namespace Ice
IceInternal.BasicStream os__ = result__.startWriteParams(FormatType.DefaultFormat);
os__.writeString(id);
result__.endWriteParams();
- result__.invoke(true);
+ result__.invoke();
}
catch(Ice.Exception ex__)
{
- result__.invokeExceptionAsync(ex__);
+ result__.abort(ex__);
}
return result__;
}
@@ -1014,11 +1013,11 @@ namespace Ice
{
result__.prepare(__ice_ping_name, OperationMode.Nonmutating, context__, explicitCtx__, synchronous__);
result__.writeEmptyParams();
- result__.invoke(true);
+ result__.invoke();
}
catch(Ice.Exception ex__)
{
- result__.invokeExceptionAsync(ex__);
+ result__.abort(ex__);
}
return result__;
}
@@ -1083,8 +1082,7 @@ namespace Ice
public string[] end_ice_ids(AsyncResult r__)
{
- IceInternal.OutgoingAsync outAsync__ = (IceInternal.OutgoingAsync)r__;
- IceInternal.OutgoingAsync.check(outAsync__, this, __ice_ids_name);
+ IceInternal.OutgoingAsync outAsync__ = IceInternal.OutgoingAsync.check(r__, this, __ice_ids_name);
try
{
if(!outAsync__.wait())
@@ -1132,11 +1130,11 @@ namespace Ice
{
result__.prepare(__ice_ids_name, OperationMode.Nonmutating, context__, explicitCtx__, synchronous__);
result__.writeEmptyParams();
- result__.invoke(true);
+ result__.invoke();
}
catch(Ice.Exception ex__)
{
- result__.invokeExceptionAsync(ex__);
+ result__.abort(ex__);
}
return result__;
}
@@ -1211,8 +1209,7 @@ namespace Ice
public string end_ice_id(AsyncResult r__)
{
- IceInternal.OutgoingAsync outAsync__ = (IceInternal.OutgoingAsync)r__;
- IceInternal.OutgoingAsync.check(outAsync__, this, __ice_id_name);
+ IceInternal.OutgoingAsync outAsync__ = IceInternal.OutgoingAsync.check(r__, this, __ice_id_name);
try
{
if(!outAsync__.wait())
@@ -1260,11 +1257,11 @@ namespace Ice
{
result__.prepare(__ice_id_name, OperationMode.Nonmutating, context__, explicitCtx__, synchronous__);
result__.writeEmptyParams();
- result__.invoke(true);
+ result__.invoke();
}
catch(Ice.Exception ex__)
{
- result__.invokeExceptionAsync(ex__);
+ result__.abort(ex__);
}
return result__;
}
@@ -1365,8 +1362,7 @@ namespace Ice
public bool end_ice_invoke(out byte[] outEncaps, AsyncResult r__)
{
- IceInternal.OutgoingAsync outAsync__ = (IceInternal.OutgoingAsync)r__;
- IceInternal.OutgoingAsync.check(outAsync__, this, __ice_invoke_name);
+ IceInternal.OutgoingAsync outAsync__ = IceInternal.OutgoingAsync.check(r__, this, __ice_invoke_name);
try
{
bool ok = outAsync__.wait();
@@ -1410,11 +1406,11 @@ namespace Ice
{
result__.prepare(operation, mode, context__, explicitCtx__, synchronous__);
result__.writeParamEncaps(inEncaps);
- result__.invoke(true);
+ result__.invoke();
}
catch(Ice.Exception ex__)
{
- result__.invokeExceptionAsync(ex__);
+ result__.abort(ex__);
}
return result__;
}
@@ -2126,60 +2122,63 @@ namespace Ice
internal const string __ice_getConnection_name = "ice_getConnection";
- public AsyncResult begin_ice_getConnection(Ice.AsyncCallback cb__, object cookie__)
+ public AsyncResult begin_ice_getConnection(Ice.AsyncCallback cb, object cookie)
{
- return begin_ice_getConnectionInternal(cb__, cookie__);
+ return begin_ice_getConnectionInternal(cb, cookie);
}
- public Connection end_ice_getConnection(Ice.AsyncResult r__)
+ public Connection end_ice_getConnection(Ice.AsyncResult r)
{
- IceInternal.GetConnectionOutgoingAsync outAsync__ = (IceInternal.GetConnectionOutgoingAsync)r__;
- IceInternal.GetConnectionOutgoingAsync.check(outAsync__, this, __ice_getConnection_name);
- outAsync__.wait();
+ IceInternal.ProxyGetConnection outAsync =
+ IceInternal.ProxyGetConnection.check(r, this, __ice_getConnection_name);
+ outAsync.wait();
return ice_getCachedConnection();
}
- private AsyncResult<Callback_Object_ice_getConnection> begin_ice_getConnectionInternal(Ice.AsyncCallback cb__,
- object cookie__)
+ private AsyncResult<Callback_Object_ice_getConnection> begin_ice_getConnectionInternal(Ice.AsyncCallback cb,
+ object cookie)
{
- IceInternal.GetConnectionOutgoingAsync result__ =
- new IceInternal.GetConnectionOutgoingAsync(this, __ice_getConnection_name,
- ice_getConnection_completed__, cookie__);
- if(cb__ != null)
+ IceInternal.ProxyGetConnection result = new IceInternal.ProxyGetConnection(this,
+ __ice_getConnection_name,
+ ice_getConnection_completed__,
+ cookie);
+ if(cb != null)
{
- result__.whenCompletedWithAsyncCallback(cb__);
+ result.whenCompletedWithAsyncCallback(cb);
}
try
{
- result__.invoke();
+ result.invoke();
}
- catch(Ice.Exception ex__)
+ catch(Ice.Exception ex)
{
- result__.invokeExceptionAsync(ex__);
+ result.abort(ex);
}
- return result__;
+ return result;
}
- private void ice_getConnection_completed__(AsyncResult r__,
- Callback_Object_ice_getConnection cb__,
- Ice.ExceptionCallback excb__)
+
+
+ private void ice_getConnection_completed__(AsyncResult r,
+ Callback_Object_ice_getConnection cb,
+ Ice.ExceptionCallback excb)
{
- Connection ret__;
+ Connection ret;
try
{
- ret__ = end_ice_getConnection(r__);
+ ret = end_ice_getConnection(r);
}
- catch(Ice.Exception ex__)
+ catch(Ice.Exception ex)
{
- if(excb__ != null)
+ if(excb != null)
{
- excb__(ex__);
+ excb(ex);
}
return;
}
- if(cb__ != null)
+ if(cb != null)
{
- cb__(ret__);
+ cb(ret);
}
}
@@ -2227,30 +2226,31 @@ namespace Ice
return begin_ice_flushBatchRequests(null, null);
}
- public AsyncResult begin_ice_flushBatchRequests(Ice.AsyncCallback cb__, object cookie__)
+ public AsyncResult begin_ice_flushBatchRequests(Ice.AsyncCallback cb, object cookie)
{
- IceInternal.ProxyBatchOutgoingAsync result__ =
- new IceInternal.ProxyBatchOutgoingAsync(this, __ice_flushBatchRequests_name, cookie__);
- if(cb__ != null)
+ IceInternal.ProxyFlushBatch result = new IceInternal.ProxyFlushBatch(this,
+ __ice_flushBatchRequests_name,
+ cookie);
+ if(cb != null)
{
- result__.whenCompletedWithAsyncCallback(cb__);
+ result.whenCompletedWithAsyncCallback(cb);
}
try
{
- result__.invoke();
+ result.invoke();
}
- catch(Ice.Exception ex__)
+ catch(Ice.Exception ex)
{
- result__.invokeExceptionAsync(ex__);
+ result.abort(ex);
}
- return result__;
+ return result;
}
- public void end_ice_flushBatchRequests(Ice.AsyncResult r__)
+ public void end_ice_flushBatchRequests(Ice.AsyncResult r)
{
- IceInternal.BatchOutgoingAsync outAsync__ = (IceInternal.BatchOutgoingAsync)r__;
- IceInternal.BatchOutgoingAsync.check(outAsync__, this, __ice_flushBatchRequests_name);
- outAsync__.wait();
+ IceInternal.ProxyFlushBatch outAsync =
+ IceInternal.ProxyFlushBatch.check(r, this, __ice_flushBatchRequests_name);
+ outAsync.wait();
}
/// <summary>
@@ -2389,15 +2389,15 @@ namespace Ice
}
}
- public void end__(AsyncResult result, string operation)
+ public void end__(AsyncResult r, string operation)
{
- IceInternal.OutgoingAsync outAsync = (IceInternal.OutgoingAsync)result;
- IceInternal.OutgoingAsync.check(outAsync, this, operation);
+ IceInternal.ProxyOutgoingAsyncBase result = IceInternal.ProxyOutgoingAsyncBase.check(r, this, operation);
try
{
- bool ok = outAsync.wait();
+ bool ok = result.wait();
if(_reference.getMode() == IceInternal.Reference.Mode.ModeTwoway)
{
+ IceInternal.OutgoingAsync outAsync = (IceInternal.OutgoingAsync)result;
if(!ok)
{
try
@@ -2414,9 +2414,9 @@ namespace Ice
}
finally
{
- if(outAsync != null)
+ if(result != null)
{
- outAsync.cacheMessageBuffers();
+ result.cacheMessageBuffers();
}
}
}
diff --git a/cs/src/Ice/ProxyFactory.cs b/cs/src/Ice/ProxyFactory.cs
index 5f9995016f7..1ae060faeea 100644
--- a/cs/src/Ice/ProxyFactory.cs
+++ b/cs/src/Ice/ProxyFactory.cs
@@ -202,7 +202,7 @@ namespace IceInternal
//
// Don't retry invocation timeouts.
//
- if(ex is Ice.InvocationTimeoutException)
+ if(ex is Ice.InvocationTimeoutException || ex is Ice.InvocationCanceledException)
{
throw ex;
}
diff --git a/cs/src/Ice/RequestHandler.cs b/cs/src/Ice/RequestHandler.cs
index 6cd82e4666a..6cef5d16d4b 100644
--- a/cs/src/Ice/RequestHandler.cs
+++ b/cs/src/Ice/RequestHandler.cs
@@ -12,7 +12,12 @@ using Ice.Instrumentation;
namespace IceInternal
{
- public interface RequestHandler
+ public interface CancellationHandler
+ {
+ void asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex);
+ }
+
+ public interface RequestHandler : CancellationHandler
{
RequestHandler connect();
RequestHandler update(RequestHandler previousHandler, RequestHandler newHandler);
@@ -21,9 +26,7 @@ namespace IceInternal
void finishBatchRequest(BasicStream @out);
void abortBatchRequest();
- bool sendAsyncRequest(OutgoingAsyncMessageCallback @out, out Ice.AsyncCallback cb);
-
- void asyncRequestCanceled(OutgoingAsyncMessageCallback outAsync, Ice.LocalException ex);
+ bool sendAsyncRequest(OutgoingAsyncBase @out, out Ice.AsyncCallback cb);
Reference getReference();
diff --git a/cs/src/Ice/RetryQueue.cs b/cs/src/Ice/RetryQueue.cs
index cf549beb95d..4379ecdc0fd 100644
--- a/cs/src/Ice/RetryQueue.cs
+++ b/cs/src/Ice/RetryQueue.cs
@@ -12,9 +12,9 @@ namespace IceInternal
using System.Collections.Generic;
using System.Diagnostics;
- public class RetryTask : TimerTask
+ public class RetryTask : TimerTask, CancellationHandler
{
- public RetryTask(RetryQueue retryQueue, OutgoingAsyncBase outAsync)
+ public RetryTask(RetryQueue retryQueue, ProxyOutgoingAsyncBase outAsync)
{
_retryQueue = retryQueue;
_outAsync = outAsync;
@@ -22,14 +22,7 @@ namespace IceInternal
public void runTimerTask()
{
- try
- {
- _outAsync.processRetry();
- }
- catch(Ice.LocalException ex)
- {
- _outAsync.invokeExceptionAsync(ex);
- }
+ _outAsync.retry();
//
// NOTE: this must be called last, destroy() blocks until all task
@@ -40,13 +33,34 @@ namespace IceInternal
_retryQueue.remove(this);
}
+ public void asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex)
+ {
+ Debug.Assert(_outAsync == outAsync);
+ if(_retryQueue.cancel(this))
+ {
+ //
+ // We just retry the outgoing async now rather than marking it
+ // as finished. The retry will check for the cancellation
+ // exception and terminate appropriately the request.
+ //
+ _outAsync.retry();
+ }
+ }
+
public void destroy()
{
- _outAsync.invokeExceptionAsync(new Ice.CommunicatorDestroyedException());
+ try
+ {
+ _outAsync.abort(new Ice.CommunicatorDestroyedException());
+ }
+ catch(Ice.CommunicatorDestroyedException)
+ {
+ // Abort can throw if there's no callback, just ignore in this case
+ }
}
private RetryQueue _retryQueue;
- private OutgoingAsyncBase _outAsync;
+ private ProxyOutgoingAsyncBase _outAsync;
}
public class RetryQueue
@@ -56,7 +70,7 @@ namespace IceInternal
_instance = instance;
}
- public void add(OutgoingAsyncBase outAsync, int interval)
+ public void add(ProxyOutgoingAsyncBase outAsync, int interval)
{
lock(this)
{
@@ -67,11 +81,11 @@ namespace IceInternal
RetryTask task = new RetryTask(this, outAsync);
_instance.timer().schedule(task, interval);
_requests.Add(task, null);
+ outAsync.cancelable(task);
}
}
- public void
- destroy()
+ public void destroy()
{
lock(this)
{
@@ -96,8 +110,7 @@ namespace IceInternal
}
}
- public void
- remove(RetryTask task)
+ public void remove(RetryTask task)
{
lock(this)
{
@@ -111,6 +124,23 @@ namespace IceInternal
}
}
+ public bool cancel(RetryTask task)
+ {
+ lock(this)
+ {
+ if(_requests.Remove(task))
+ {
+ if(_instance == null && _requests.Count == 0)
+ {
+ // If we are destroying the queue, destroy is probably waiting on the queue to be empty.
+ System.Threading.Monitor.Pulse(this);
+ }
+ return _instance.timer().cancel(task);
+ }
+ return false;
+ }
+ }
+
private Instance _instance;
private Dictionary<RetryTask, object> _requests = new Dictionary<RetryTask, object>();
}
diff --git a/cs/test/Ice/ami/AllTests.cs b/cs/test/Ice/ami/AllTests.cs
index 14099e70e6d..f449f3eaddf 100644
--- a/cs/test/Ice/ami/AllTests.cs
+++ b/cs/test/Ice/ami/AllTests.cs
@@ -1701,6 +1701,21 @@ public class AllTests : TestCommon.TestApp
test(r.isSent());
test(r.IsCompleted);
test(p.waitForBatch(2));
+
+ FlushCallback cb2 = new FlushCallback(cookie);
+ Ice.AsyncResult r2 = b1.begin_ice_flushBatchRequests(
+ (Ice.AsyncResult result) =>
+ {
+ cb2.completedAsync(result);
+ }, cookie);
+ r2.whenSent(
+ (Ice.AsyncResult result) =>
+ {
+ cb2.sentAsync(result);
+ });
+ cb2.check();
+ test(r2.isSent());
+ test(r2.IsCompleted);
}
if(p.ice_getConnection() != null)
@@ -2597,6 +2612,86 @@ public class AllTests : TestCommon.TestApp
communicator.end_flushBatchRequests(r);
}
}
+
+ if(p.ice_getConnection() != null)
+ {
+ Ice.AsyncResult r1 = null;
+ Ice.AsyncResult r2 = null;
+ testController.holdAdapter();
+ try
+ {
+ Ice.AsyncResult r = null;
+ byte[] seq = new byte[10024];
+ (new System.Random()).NextBytes(seq);
+ for(int i = 0; i < 200; ++i) // 2MB
+ {
+ r = p.begin_opWithPayload(seq);
+ }
+
+ test(!r.isSent());
+
+ r1 = p.begin_ice_ping();
+ r2 = p.begin_ice_id();
+ r1.cancel();
+ r2.cancel();
+ try
+ {
+ p.end_ice_ping(r1);
+ test(false);
+ }
+ catch(Ice.InvocationCanceledException)
+ {
+ }
+ try
+ {
+ p.end_ice_id(r2);
+ test(false);
+ }
+ catch(Ice.InvocationCanceledException)
+ {
+ }
+
+ }
+ finally
+ {
+ testController.resumeAdapter();
+ p.ice_ping();
+ test(!r1.isSent() && r1.isCompleted_());
+ test(!r2.isSent() && r2.isCompleted_());
+ }
+
+
+ testController.holdAdapter();
+ try
+ {
+ r1 = p.begin_op();
+ r2 = p.begin_ice_id();
+ r1.waitForSent();
+ r2.waitForSent();
+ r1.cancel();
+ r2.cancel();
+ try
+ {
+ p.end_op(r1);
+ test(false);
+ }
+ catch(Ice.InvocationCanceledException)
+ {
+ }
+ try
+ {
+ p.end_ice_id(r2);
+ test(false);
+ }
+ catch(Ice.InvocationCanceledException)
+ {
+ }
+ }
+ finally
+ {
+ testController.resumeAdapter();
+ }
+ }
}
WriteLine("ok");
diff --git a/cs/test/Ice/retry/AllTests.cs b/cs/test/Ice/retry/AllTests.cs
index f3383ccc7d1..32c91dd55f8 100644
--- a/cs/test/Ice/retry/AllTests.cs
+++ b/cs/test/Ice/retry/AllTests.cs
@@ -96,7 +96,7 @@ public class AllTests : TestCommon.TestApp
retry1.op(false);
WriteLine("ok");
- int invocationCount = 3;
+ Instrumentation.testInvocationCount(3);
Write("calling operation to kill connection with second proxy... ");
Flush();
@@ -112,7 +112,7 @@ public class AllTests : TestCommon.TestApp
catch(Ice.ConnectionLostException)
{
}
- Instrumentation.testInvocationCount(invocationCount + 1);
+ Instrumentation.testInvocationCount(1);
Instrumentation.testFailureCount(1);
Instrumentation.testRetryCount(0);
WriteLine("ok");
@@ -120,8 +120,8 @@ public class AllTests : TestCommon.TestApp
Write("calling regular operation with first proxy again... ");
Flush();
retry1.op(false);
- Instrumentation.testInvocationCount(invocationCount + 2);
- Instrumentation.testFailureCount(1);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(0);
Instrumentation.testRetryCount(0);
WriteLine("ok");
@@ -138,8 +138,8 @@ public class AllTests : TestCommon.TestApp
test(false);
});
cb.check();
- Instrumentation.testInvocationCount(invocationCount + 3);
- Instrumentation.testFailureCount(1);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(0);
Instrumentation.testRetryCount(0);
WriteLine("ok");
@@ -155,8 +155,8 @@ public class AllTests : TestCommon.TestApp
cb.called();
});
cb.check();
- Instrumentation.testInvocationCount(invocationCount + 4);
- Instrumentation.testFailureCount(2);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(1);
Instrumentation.testRetryCount(0);
WriteLine("ok");
@@ -171,50 +171,51 @@ public class AllTests : TestCommon.TestApp
test(false);
});
cb.check();
- Instrumentation.testInvocationCount(invocationCount + 5);
- Instrumentation.testFailureCount(2);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(0);
Instrumentation.testRetryCount(0);
WriteLine("ok");
Write("testing idempotent operation... ");
- test(retry1.opIdempotent(0) == 4);
- Instrumentation.testInvocationCount(invocationCount + 6);
- Instrumentation.testFailureCount(2);
+ test(retry1.opIdempotent(4) == 4);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(0);
+ Instrumentation.testRetryCount(4);
+ test(retry1.end_opIdempotent(retry1.begin_opIdempotent(4)) == 4);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(0);
Instrumentation.testRetryCount(4);
- test(retry1.end_opIdempotent(retry1.begin_opIdempotent(4)) == 8);
- Instrumentation.testInvocationCount(invocationCount + 7);
- Instrumentation.testFailureCount(2);
- Instrumentation.testRetryCount(8);
WriteLine("ok");
Write("testing non-idempotent operation... ");
try
{
- retry1.opNotIdempotent(8);
+ retry1.opNotIdempotent();
test(false);
}
catch(Ice.LocalException)
{
}
- Instrumentation.testInvocationCount(invocationCount + 8);
- Instrumentation.testFailureCount(3);
- Instrumentation.testRetryCount(8);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(1);
+ Instrumentation.testRetryCount(0);
try
{
- retry1.end_opNotIdempotent(retry1.begin_opNotIdempotent(9));
+ retry1.end_opNotIdempotent(retry1.begin_opNotIdempotent());
test(false);
}
catch(Ice.LocalException)
{
}
- Instrumentation.testInvocationCount(invocationCount + 9);
- Instrumentation.testFailureCount(4);
- Instrumentation.testRetryCount(8);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(1);
+ Instrumentation.testRetryCount(0);
WriteLine("ok");
if(retry1.ice_getConnection() == null)
{
- invocationCount = invocationCount + 10;
+ Instrumentation.testInvocationCount(1);
+
Write("testing system exception... ");
try
{
@@ -224,9 +225,9 @@ public class AllTests : TestCommon.TestApp
catch(SystemFailure)
{
}
- Instrumentation.testInvocationCount(invocationCount + 1);
- Instrumentation.testFailureCount(5);
- Instrumentation.testRetryCount(8);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(1);
+ Instrumentation.testRetryCount(0);
try
{
retry1.end_opSystemException(retry1.begin_opSystemException());
@@ -235,12 +236,41 @@ public class AllTests : TestCommon.TestApp
catch(SystemFailure)
{
}
- Instrumentation.testInvocationCount(invocationCount + 2);
- Instrumentation.testFailureCount(6);
- Instrumentation.testRetryCount(8);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(1);
+ Instrumentation.testRetryCount(0);
WriteLine("ok");
}
+ Write("testing invocation timeout and retries... ");
+ Flush();
+ try
+ {
+ // No more than 2 retries before timeout kicks-in
+ ((Test.RetryPrx)retry1.ice_invocationTimeout(50)).opIdempotent(4);
+ test(false);
+ }
+ catch(Ice.InvocationTimeoutException)
+ {
+ Instrumentation.testRetryCount(2);
+ retry1.opIdempotent(-1); // Reset the counter
+ Instrumentation.testRetryCount(-1);
+ }
+ try
+ {
+ // No more than 2 retries before timeout kicks-in
+ Test.RetryPrx prx = (Test.RetryPrx)retry1.ice_invocationTimeout(50);
+ prx.end_opIdempotent(prx.begin_opIdempotent(4));
+ test(false);
+ }
+ catch(Ice.InvocationTimeoutException)
+ {
+ Instrumentation.testRetryCount(2);
+ retry1.opIdempotent(-1); // Reset the counter
+ Instrumentation.testRetryCount(-1);
+ }
+ WriteLine("ok");
+
#if SILVERLIGHT
retry1.shutdown();
#else
diff --git a/cs/test/Ice/retry/Client.cs b/cs/test/Ice/retry/Client.cs
index 6edf7610149..3623ddddc8f 100644
--- a/cs/test/Ice/retry/Client.cs
+++ b/cs/test/Ice/retry/Client.cs
@@ -37,7 +37,7 @@ public class Client
initData.properties = Ice.Util.createProperties(ref args);
initData.observer = Instrumentation.getObserver();
- initData.properties.setProperty("Ice.RetryIntervals", "0 10 20 30");
+ initData.properties.setProperty("Ice.RetryIntervals", "0 1 100 1");
//
// This test kills connections, so we don't want warnings.
diff --git a/cs/test/Ice/retry/Collocated.cs b/cs/test/Ice/retry/Collocated.cs
index 191d4c0e6d7..a4e93bcc1d1 100644
--- a/cs/test/Ice/retry/Collocated.cs
+++ b/cs/test/Ice/retry/Collocated.cs
@@ -41,7 +41,7 @@ public class Collocated
initData.properties = Ice.Util.createProperties(ref args);
initData.observer = Instrumentation.getObserver();
- initData.properties.setProperty("Ice.RetryIntervals", "0 10 20 30");
+ initData.properties.setProperty("Ice.RetryIntervals", "0 1 100 1");
//
// This test kills connections, so we don't want warnings.
diff --git a/cs/test/Ice/retry/Instrumentation.cs b/cs/test/Ice/retry/Instrumentation.cs
index 169dc8e95fb..01a93ad3534 100644
--- a/cs/test/Ice/retry/Instrumentation.cs
+++ b/cs/test/Ice/retry/Instrumentation.cs
@@ -129,8 +129,14 @@ public class Instrumentation
static private void
testEqual(ref int value, int expected)
{
+ if(expected < 0)
+ {
+ value = 0;
+ return;
+ }
+
int retry = 0;
- while(retry < 100)
+ while(++retry < 100)
{
lock(mutex)
{
@@ -147,6 +153,7 @@ public class Instrumentation
System.Diagnostics.Debug.Assert(false);
throw new System.Exception();
}
+ value = 0;
}
static public void
diff --git a/cs/test/Ice/retry/RetryI.cs b/cs/test/Ice/retry/RetryI.cs
index 93d8987b997..024b4890b6b 100644
--- a/cs/test/Ice/retry/RetryI.cs
+++ b/cs/test/Ice/retry/RetryI.cs
@@ -30,9 +30,9 @@ public sealed class RetryI : Test.RetryDisp_
}
}
- public override int opIdempotent(int counter, Ice.Current current)
+ public override int opIdempotent(int nRetry, Ice.Current current)
{
- if(counter + nRetry > _counter)
+ if(nRetry > _counter)
{
++_counter;
if(current.con != null)
@@ -43,18 +43,15 @@ public sealed class RetryI : Test.RetryDisp_
{
throw new Ice.ConnectionLostException();
}
+ return 0;
}
- return _counter;
+ int counter = _counter;
+ _counter = 0;
+ return counter;
}
- public override void opNotIdempotent(int counter, Ice.Current current)
+ public override void opNotIdempotent(Ice.Current current)
{
- if(_counter != counter)
- {
- return;
- }
-
- ++_counter;
if(current.con != null)
{
current.con.close(true);
@@ -76,5 +73,4 @@ public sealed class RetryI : Test.RetryDisp_
}
private int _counter;
- static readonly int nRetry = 4;
}
diff --git a/cs/test/Ice/retry/Test.ice b/cs/test/Ice/retry/Test.ice
index 61297d94557..cd8c2595796 100644
--- a/cs/test/Ice/retry/Test.ice
+++ b/cs/test/Ice/retry/Test.ice
@@ -17,10 +17,10 @@ interface Retry
void op(bool kill);
idempotent int opIdempotent(int c);
- void opNotIdempotent(int c);
+ void opNotIdempotent();
void opSystemException();
- void shutdown();
+ idempotent void shutdown();
};
};
diff --git a/java/src/Ice/AsyncResult.java b/java/src/Ice/AsyncResult.java
index df247ac9358..477dec5f5ac 100644
--- a/java/src/Ice/AsyncResult.java
+++ b/java/src/Ice/AsyncResult.java
@@ -16,6 +16,13 @@ package Ice;
**/
public interface AsyncResult
{
+ /**
+ * If not completed, cancels the request. This is a local
+ * operation, it won't cancel the request on the server side. The
+ * request won't be sent if it was waiting to be sent or the
+ * response will be ignored if it received after the callback.
+ **/
+ public void cancel();
/**
* Returns the communicator that sent the invocation.
diff --git a/java/src/Ice/CommunicatorI.java b/java/src/Ice/CommunicatorI.java
index 76d46baab6a..fab8cf98605 100644
--- a/java/src/Ice/CommunicatorI.java
+++ b/java/src/Ice/CommunicatorI.java
@@ -263,8 +263,10 @@ public final class CommunicatorI implements Communicator
// This callback object receives the results of all invocations
// of Connection.begin_flushBatchRequests.
//
- IceInternal.CommunicatorBatchOutgoingAsync result =
- new IceInternal.CommunicatorBatchOutgoingAsync(this, _instance, __flushBatchRequests_name, cb);
+ IceInternal.CommunicatorFlushBatch result = new IceInternal.CommunicatorFlushBatch(this,
+ _instance,
+ __flushBatchRequests_name,
+ cb);
connectionFactory.flushAsyncBatchRequests(result);
adapterFactory.flushAsyncBatchRequests(result);
@@ -282,8 +284,8 @@ public final class CommunicatorI implements Communicator
public void
end_flushBatchRequests(AsyncResult r)
{
- IceInternal.OutgoingAsyncBase ri = (IceInternal.OutgoingAsyncBase)r;
- IceInternal.OutgoingAsyncBase.check(ri, this, __flushBatchRequests_name);
+ IceInternal.CommunicatorFlushBatch ri =
+ IceInternal.CommunicatorFlushBatch.check(r, this, __flushBatchRequests_name);
ri.__wait();
}
diff --git a/java/src/Ice/ConnectionI.java b/java/src/Ice/ConnectionI.java
index 73880042340..9ee6ac10121 100644
--- a/java/src/Ice/ConnectionI.java
+++ b/java/src/Ice/ConnectionI.java
@@ -9,7 +9,8 @@
package Ice;
-public final class ConnectionI extends IceInternal.EventHandler implements Connection, IceInternal.ResponseHandler
+public final class ConnectionI extends IceInternal.EventHandler
+ implements Connection, IceInternal.ResponseHandler, IceInternal.CancellationHandler
{
public interface StartCallback
{
@@ -373,8 +374,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
os.writeInt(requestId);
}
- out.attachRemoteObserver(initConnectionInfo(), _endpoint, requestId, os.size() -
- IceInternal.Protocol.headerSize - 4);
+ out.attachRemoteObserver(initConnectionInfo(), _endpoint, requestId);
int status;
try
@@ -388,6 +388,11 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
throw (Ice.LocalException) _exception.fillInStackTrace();
}
+ if(response || (status & IceInternal.AsyncStatus.Queued) > 0)
+ {
+ out.cancelable(this); // Notify the request that it's cancelable
+ }
+
if(response)
{
//
@@ -640,29 +645,21 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
private Ice.AsyncResult begin_flushBatchRequestsInternal(IceInternal.CallbackBase cb)
{
- IceInternal.ConnectionBatchOutgoingAsync result = new IceInternal.ConnectionBatchOutgoingAsync(this,
- _communicator, _instance, __flushBatchRequests_name, cb);
- try
- {
- result.__invoke();
- }
- catch(LocalException __ex)
- {
- result.invokeExceptionAsync(__ex);
- }
-
+ IceInternal.ConnectionFlushBatch result =
+ new IceInternal.ConnectionFlushBatch(this, _communicator, _instance, __flushBatchRequests_name, cb);
+ result.invoke();
return result;
}
@Override
public void end_flushBatchRequests(AsyncResult ir)
{
- IceInternal.OutgoingAsyncBase r = (IceInternal.OutgoingAsyncBase) ir;
- IceInternal.OutgoingAsyncBase.check(r, this, __flushBatchRequests_name);
+ IceInternal.ConnectionFlushBatch r =
+ IceInternal.ConnectionFlushBatch.check(ir, this, __flushBatchRequests_name);
r.__wait();
}
- synchronized public int flushAsyncBatchRequests(IceInternal.BatchOutgoingAsync outAsync)
+ synchronized public int flushAsyncBatchRequests(IceInternal.OutgoingAsyncBase outAsync)
{
waitBatchStreamInUse();
@@ -687,11 +684,10 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
_batchStream.pos(IceInternal.Protocol.headerSize);
_batchStream.writeInt(_batchRequestNum);
- outAsync.attachRemoteObserver(initConnectionInfo(), _endpoint, 0, _batchStream.size() -
- IceInternal.Protocol.headerSize - 4);
-
_batchStream.swap(outAsync.getOs());
+ outAsync.attachRemoteObserver(initConnectionInfo(), _endpoint, 0);
+
//
// Send the batch stream.
//
@@ -708,6 +704,11 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
throw (Ice.LocalException) _exception.fillInStackTrace();
}
+ if((status & IceInternal.AsyncStatus.Queued) > 0)
+ {
+ outAsync.cancelable(this); // Notify the request that it's cancelable.
+ }
+
//
// Reset the batch stream.
//
@@ -728,12 +729,8 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
{
if(callback != null)
{
- class CallbackWorkItem extends IceInternal.DispatchWorkItem
+ _threadPool.dispatch(new IceInternal.DispatchWorkItem(this)
{
- public CallbackWorkItem()
- {
- }
-
@Override
public void run()
{
@@ -746,8 +743,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
_logger.error("connection callback exception:\n" + ex + '\n' + _desc);
}
}
- };
- _threadPool.dispatch(new CallbackWorkItem());
+ });
}
}
else
@@ -793,9 +789,14 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
return _monitor != null ? _monitor.getACM() : new ACM(0, ACMClose.CloseOff, ACMHeartbeat.HeartbeatOff);
}
- synchronized public boolean asyncRequestCanceled(IceInternal.OutgoingAsyncMessageCallback outAsync,
- Ice.LocalException ex)
+ @Override
+ synchronized public void asyncRequestCanceled(IceInternal.OutgoingAsyncBase outAsync, Ice.LocalException ex)
{
+ if(_state >= StateClosed)
+ {
+ return; // The request has already been or will be shortly notified of the failure.
+ }
+
java.util.Iterator<OutgoingMessage> it = _sendStreams.iterator();
while(it.hasNext())
{
@@ -815,13 +816,16 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
// it's fine if the OutgoingAsync output stream is released (and
// as long as canceled requests cannot be retried).
//
- o.timedOut();
+ o.canceled();
if(o != _sendStreams.getFirst())
{
it.remove();
}
- outAsync.dispatchInvocationCancel(ex, _threadPool, this);
- return true; // We're done
+ if(outAsync.completed(ex))
+ {
+ outAsync.invokeCompletedAsync();
+ }
+ return;
}
}
@@ -834,12 +838,13 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
if(it2.next() == o)
{
it2.remove();
- outAsync.dispatchInvocationCancel(ex, _threadPool, this);
- return true; // We're done.
+ if(outAsync.completed(ex))
+ {
+ outAsync.invokeCompletedAsync();
+ }
}
}
}
- return false;
}
@Override
@@ -1469,7 +1474,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
for(OutgoingMessage p : _sendStreams)
{
- p.finished(_exception);
+ p.completed(_exception);
if(p.requestId > 0) // Make sure finished isn't called twice.
{
_asyncRequests.remove(p.requestId);
@@ -1480,7 +1485,10 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
for(IceInternal.OutgoingAsync p : _asyncRequests.values())
{
- p.finished(_exception);
+ if(p.completed(_exception))
+ {
+ p.invokeCompleted();
+ }
}
_asyncRequests.clear();
@@ -2580,7 +2588,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
IceInternal.TraceUtil.traceRecv(info.stream, _logger, _traceLevels);
info.requestId = info.stream.readInt();
IceInternal.OutgoingAsync outAsync = _asyncRequests.remove(info.requestId);
- if(outAsync != null && outAsync.finished(info.stream))
+ if(outAsync != null && outAsync.completed(info.stream))
{
info.outAsync = outAsync;
++info.messageDispatchCount;
@@ -2999,7 +3007,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
this.requestId = 0;
}
- OutgoingMessage(IceInternal.OutgoingAsyncMessageCallback out, IceInternal.BasicStream stream, boolean compress,
+ OutgoingMessage(IceInternal.OutgoingAsyncBase out, IceInternal.BasicStream stream, boolean compress,
int requestId)
{
this.stream = stream;
@@ -3008,7 +3016,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
this.requestId = requestId;
}
- public void timedOut()
+ public void canceled()
{
assert (outAsync != null);
outAsync = null;
@@ -3035,16 +3043,16 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
return false;
}
- public void finished(Ice.LocalException ex)
+ public void completed(Ice.LocalException ex)
{
- if(outAsync != null)
+ if(outAsync != null && outAsync.completed(ex))
{
- outAsync.finished(ex);
+ outAsync.invokeCompleted();
}
}
public IceInternal.BasicStream stream;
- public IceInternal.OutgoingAsyncMessageCallback outAsync;
+ public IceInternal.OutgoingAsyncBase outAsync;
public boolean compress;
public int requestId;
boolean adopt;
diff --git a/java/src/Ice/ObjectAdapterI.java b/java/src/Ice/ObjectAdapterI.java
index 7538fc16ced..48ad2739082 100644
--- a/java/src/Ice/ObjectAdapterI.java
+++ b/java/src/Ice/ObjectAdapterI.java
@@ -13,8 +13,6 @@ import java.util.Map;
public final class ObjectAdapterI implements ObjectAdapter
{
-
-
@Override
public String
getName()
@@ -751,7 +749,7 @@ public final class ObjectAdapterI implements ObjectAdapter
}
public void
- flushAsyncBatchRequests(IceInternal.CommunicatorBatchOutgoingAsync outAsync)
+ flushAsyncBatchRequests(IceInternal.CommunicatorFlushBatch outAsync)
{
java.util.List<IceInternal.IncomingConnectionFactory> f;
synchronized(this)
diff --git a/java/src/Ice/ObjectPrxHelperBase.java b/java/src/Ice/ObjectPrxHelperBase.java
index 17b426c69cb..3f7bb25d9ad 100644
--- a/java/src/Ice/ObjectPrxHelperBase.java
+++ b/java/src/Ice/ObjectPrxHelperBase.java
@@ -286,11 +286,11 @@ public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
IceInternal.BasicStream __os = __result.startWriteParams(Ice.FormatType.DefaultFormat);
__os.writeString(__id);
__result.endWriteParams();
- __result.invoke(true);
+ __result.invoke();
}
catch(Exception __ex)
{
- __result.invokeExceptionAsync(__ex);
+ __result.abort(__ex);
}
return __result;
}
@@ -305,8 +305,7 @@ public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
public final boolean
end_ice_isA(AsyncResult __iresult)
{
- IceInternal.OutgoingAsyncBase __result = (IceInternal.OutgoingAsyncBase)__iresult;
- IceInternal.OutgoingAsyncBase.check(__result, this, __ice_isA_name);
+ IceInternal.OutgoingAsync __result = IceInternal.OutgoingAsync.check(__iresult, this, __ice_isA_name);
try
{
if(!__result.__wait())
@@ -544,11 +543,11 @@ public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
{
__result.prepare(__ice_ping_name, OperationMode.Nonmutating, __context, __explicitCtx, __synchronous);
__result.writeEmptyParams();
- __result.invoke(true);
+ __result.invoke();
}
catch(Exception __ex)
{
- __result.invokeExceptionAsync(__ex);
+ __result.abort(__ex);
}
return __result;
}
@@ -777,11 +776,11 @@ public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
{
__result.prepare(__ice_ids_name, OperationMode.Nonmutating, __context, __explicitCtx, __synchronous);
__result.writeEmptyParams();
- __result.invoke(true);
+ __result.invoke();
}
catch(Exception __ex)
{
- __result.invokeExceptionAsync(__ex);
+ __result.abort(__ex);
}
return __result;
}
@@ -797,8 +796,7 @@ public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
public final String[]
end_ice_ids(AsyncResult __iresult)
{
- IceInternal.OutgoingAsyncBase __result = (IceInternal.OutgoingAsyncBase) __iresult;
- IceInternal.OutgoingAsyncBase.check(__result, this, __ice_ids_name);
+ IceInternal.OutgoingAsync __result = IceInternal.OutgoingAsync.check(__iresult, this, __ice_ids_name);
try
{
if(!__result.__wait())
@@ -1054,11 +1052,11 @@ public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
{
__result.prepare(__ice_id_name, OperationMode.Nonmutating, __context, __explicitCtx, __synchronous);
__result.writeEmptyParams();
- __result.invoke(true);
+ __result.invoke();
}
catch(Exception __ex)
{
- __result.invokeExceptionAsync(__ex);
+ __result.abort(__ex);
}
return __result;
}
@@ -1073,8 +1071,7 @@ public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
public final String
end_ice_id(AsyncResult __iresult)
{
- IceInternal.OutgoingAsyncBase __result = (IceInternal.OutgoingAsyncBase) __iresult;
- IceInternal.OutgoingAsyncBase.check(__result, this, __ice_id_name);
+ IceInternal.OutgoingAsync __result = IceInternal.OutgoingAsync.check(__iresult, this, __ice_id_name);
try
{
if(!__result.__wait())
@@ -1444,11 +1441,11 @@ public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
{
__result.prepare(operation, mode, __context, __explicitCtx, __synchronous);
__result.writeParamEncaps(inParams);
- __result.invoke(true);
+ __result.invoke();
}
catch(Exception __ex)
{
- __result.invokeExceptionAsync(__ex);
+ __result.abort(__ex);
}
return __result;
}
@@ -1468,8 +1465,7 @@ public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
public final boolean
end_ice_invoke(ByteSeqHolder outParams, AsyncResult __iresult)
{
- IceInternal.OutgoingAsyncBase __result = (IceInternal.OutgoingAsyncBase) __iresult;
- IceInternal.OutgoingAsyncBase.check(__result, this, __ice_invoke_name);
+ IceInternal.OutgoingAsync __result = IceInternal.OutgoingAsync.check(__iresult, this, __ice_invoke_name);
try
{
boolean ok = __result.__wait();
@@ -2427,49 +2423,47 @@ public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
private static final String __ice_getConnection_name = "ice_getConnection";
private AsyncResult
- begin_ice_getConnectionInternal(IceInternal.CallbackBase __cb)
+ begin_ice_getConnectionInternal(IceInternal.CallbackBase cb)
{
- IceInternal.GetConnectionOutgoingAsync __result =
- new IceInternal.GetConnectionOutgoingAsync(this, __ice_getConnection_name, __cb);
+ IceInternal.ProxyGetConnection result = new IceInternal.ProxyGetConnection(this, __ice_getConnection_name, cb);
try
{
- __result.__invoke();
+ result.invoke();
}
- catch(Exception __ex)
+ catch(Exception ex)
{
- __result.invokeExceptionAsync(__ex);
+ result.abort(ex);
}
- return __result;
+ return result;
}
@Override
public Ice.Connection
- end_ice_getConnection(AsyncResult __iresult)
+ end_ice_getConnection(AsyncResult r)
{
- IceInternal.OutgoingAsyncBase __result = (IceInternal.OutgoingAsyncBase)__iresult;
- IceInternal.OutgoingAsyncBase.check(__result, this, __ice_getConnection_name);
- __result.__wait();
+ IceInternal.ProxyGetConnection result = IceInternal.ProxyGetConnection.check(r, this, __ice_getConnection_name);
+ result.__wait();
return ice_getCachedConnection();
}
- static public final void __ice_getConnection_completed(TwowayCallbackArg1<Ice.Connection> __cb, AsyncResult __result)
+ static public final void __ice_getConnection_completed(TwowayCallbackArg1<Ice.Connection> cb, AsyncResult result)
{
- Ice.Connection __ret = null;
+ Ice.Connection ret = null;
try
{
- __ret = __result.getProxy().end_ice_getConnection(__result);
+ ret = result.getProxy().end_ice_getConnection(result);
}
- catch(LocalException __ex)
+ catch(LocalException ex)
{
- __cb.exception(__ex);
+ cb.exception(ex);
return;
}
- catch(SystemException __ex)
+ catch(SystemException ex)
{
- __cb.exception(__ex);
+ cb.exception(ex);
return;
}
- __cb.response(__ret);
+ cb.response(ret);
}
/**
@@ -2578,28 +2572,26 @@ public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
private static final String __ice_flushBatchRequests_name = "ice_flushBatchRequests";
private AsyncResult
- begin_ice_flushBatchRequestsInternal(IceInternal.CallbackBase __cb)
+ begin_ice_flushBatchRequestsInternal(IceInternal.CallbackBase cb)
{
- IceInternal.ProxyBatchOutgoingAsync __result =
- new IceInternal.ProxyBatchOutgoingAsync(this, __ice_flushBatchRequests_name, __cb);
+ IceInternal.ProxyFlushBatch result = new IceInternal.ProxyFlushBatch(this, __ice_flushBatchRequests_name, cb);
try
{
- __result.__invoke();
+ result.invoke();
}
- catch(Exception __ex)
+ catch(Exception ex)
{
- __result.invokeExceptionAsync(__ex);
+ result.abort(ex);
}
- return __result;
+ return result;
}
@Override
public void
- end_ice_flushBatchRequests(AsyncResult __iresult)
+ end_ice_flushBatchRequests(AsyncResult r)
{
- IceInternal.OutgoingAsyncBase __result = (IceInternal.OutgoingAsyncBase)__iresult;
- IceInternal.OutgoingAsyncBase.check(__result, this, __ice_flushBatchRequests_name);
- __result.__wait();
+ IceInternal.ProxyFlushBatch result = IceInternal.ProxyFlushBatch.check(r, this, __ice_flushBatchRequests_name);
+ result.__wait();
}
/**
@@ -2721,34 +2713,34 @@ public class ObjectPrxHelperBase implements ObjectPrx, java.io.Serializable
}
public final void
- __end(AsyncResult __iresult, String operation)
+ __end(AsyncResult r, String operation)
{
- IceInternal.OutgoingAsyncBase __result = (IceInternal.OutgoingAsyncBase)__iresult;
- IceInternal.OutgoingAsyncBase.check(__result, this, operation);
+ IceInternal.ProxyOutgoingAsyncBase result = IceInternal.ProxyOutgoingAsyncBase.check(r, this, operation);
try
{
- boolean ok = __result.__wait();
+ boolean ok = result.__wait();
if(_reference.getMode() == IceInternal.Reference.ModeTwoway)
{
+ IceInternal.OutgoingAsync outAsync = (IceInternal.OutgoingAsync)result;
if(!ok)
{
try
{
- __result.throwUserException();
+ outAsync.throwUserException();
}
- catch(UserException __ex)
+ catch(UserException ex)
{
- throw new UnknownUserException(__ex.ice_name(), __ex);
+ throw new UnknownUserException(ex.ice_name(), ex);
}
}
- __result.readEmptyParams();
+ outAsync.readEmptyParams();
}
}
finally
{
- if(__result != null)
+ if(result != null)
{
- __result.cacheMessageBuffers();
+ result.cacheMessageBuffers();
}
}
}
diff --git a/java/src/IceInternal/AsyncResultI.java b/java/src/IceInternal/AsyncResultI.java
new file mode 100644
index 00000000000..9d7445584fe
--- /dev/null
+++ b/java/src/IceInternal/AsyncResultI.java
@@ -0,0 +1,475 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import Ice.AsyncResult;
+import Ice.Communicator;
+import Ice.CommunicatorDestroyedException;
+import Ice.Connection;
+
+public class AsyncResultI implements AsyncResult
+{
+ @Override
+ public void cancel()
+ {
+ cancel(new Ice.InvocationCanceledException());
+ }
+
+ @Override
+ public Communicator getCommunicator()
+ {
+ return _communicator;
+ }
+
+ @Override
+ public Connection getConnection()
+ {
+ return null;
+ }
+
+ @Override
+ public Ice.ObjectPrx getProxy()
+ {
+ return null;
+ }
+
+ @Override
+ public final boolean isCompleted()
+ {
+ synchronized(this)
+ {
+ return (_state & StateDone) > 0;
+ }
+ }
+
+ @Override
+ public final void waitForCompleted()
+ {
+ synchronized(this)
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ while((_state & StateDone) == 0)
+ {
+ try
+ {
+ this.wait();
+ }
+ catch(InterruptedException ex)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+ }
+ }
+
+ @Override
+ public final boolean isSent()
+ {
+ synchronized(this)
+ {
+ return (_state & StateSent) > 0;
+ }
+ }
+
+ @Override
+ public final void waitForSent()
+ {
+ synchronized(this)
+ {
+ if(Thread.interrupted())
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ while((_state & StateSent) == 0 && _exception == null)
+ {
+ try
+ {
+ this.wait();
+ }
+ catch(InterruptedException ex)
+ {
+ throw new Ice.OperationInterruptedException();
+ }
+ }
+ }
+ }
+
+ @Override
+ public final void throwLocalException()
+ {
+ synchronized(this)
+ {
+ if(_exception != null)
+ {
+ throw _exception;
+ }
+ }
+ }
+
+ @Override
+ public final boolean sentSynchronously()
+ {
+ return _sentSynchronously; // No lock needed, immutable
+ }
+
+ @Override
+ public final String getOperation()
+ {
+ return _operation;
+ }
+
+ public final void invokeSent()
+ {
+ assert(_callback != null);
+
+ if(_instance.useApplicationClassLoader())
+ {
+ Thread.currentThread().setContextClassLoader(_callback.getClass().getClassLoader());
+ }
+
+ try
+ {
+ _callback.__sent(this);
+ }
+ catch(RuntimeException ex)
+ {
+ warning(ex);
+ }
+ catch(AssertionError exc)
+ {
+ error(exc);
+ }
+ catch(OutOfMemoryError exc)
+ {
+ error(exc);
+ }
+ finally
+ {
+ if(_instance.useApplicationClassLoader())
+ {
+ Thread.currentThread().setContextClassLoader(null);
+ }
+ }
+
+ if(_observer != null)
+ {
+ Ice.ObjectPrx proxy = getProxy();
+ if(proxy == null || !proxy.ice_isTwoway())
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ }
+ }
+
+ public final void invokeCompleted()
+ {
+ assert(_callback != null);
+
+ if(_instance.useApplicationClassLoader())
+ {
+ Thread.currentThread().setContextClassLoader(_callback.getClass().getClassLoader());
+ }
+
+ try
+ {
+ _callback.__completed(this);
+ }
+ catch(RuntimeException ex)
+ {
+ warning(ex);
+ }
+ catch(AssertionError exc)
+ {
+ error(exc);
+ }
+ catch(OutOfMemoryError exc)
+ {
+ error(exc);
+ }
+ finally
+ {
+ if(_instance.useApplicationClassLoader())
+ {
+ Thread.currentThread().setContextClassLoader(null);
+ }
+ }
+
+ if(_observer != null)
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ }
+
+ public final void invokeCompletedAsync()
+ {
+ //
+ // CommunicatorDestroyedCompleted is the only exception that can propagate directly
+ // from this method.
+ //
+ _instance.clientThreadPool().dispatch(new DispatchWorkItem(_cachedConnection)
+ {
+ @Override
+ public void run()
+ {
+ invokeCompleted();
+ }
+ });
+ }
+
+ public void cancelable(final CancellationHandler handler)
+ {
+ synchronized(this)
+ {
+ if(_cancellationException == null)
+ {
+ _cancellationHandler = handler;
+ return;
+ }
+ }
+ handler.asyncRequestCanceled((OutgoingAsyncBase)this, _cancellationException);
+ }
+
+ public final boolean __wait()
+ {
+ try
+ {
+ synchronized(this)
+ {
+ if((_state & StateEndCalled) > 0)
+ {
+ throw new IllegalArgumentException("end_ method called more than once");
+ }
+
+ _state |= StateEndCalled;
+ if(Thread.interrupted())
+ {
+ throw new InterruptedException();
+ }
+ while((_state & StateDone) == 0)
+ {
+ this.wait();
+ }
+
+ if(_exception != null)
+ {
+ throw (Ice.Exception)_exception.fillInStackTrace();
+ }
+
+ return (_state & StateOK) > 0;
+ }
+ }
+ catch(InterruptedException ex)
+ {
+ Ice.OperationInterruptedException exc = new Ice.OperationInterruptedException();
+ cancel(exc); // Must be called outside the synchronization
+ throw exc;
+ }
+ }
+
+ public void cacheMessageBuffers()
+ {
+ }
+
+ protected AsyncResultI(Communicator communicator, Instance instance, String op, CallbackBase del)
+ {
+ _communicator = communicator;
+ _instance = instance;
+ _operation = op;
+ _state = 0;
+ _sentSynchronously = false;
+ _exception = null;
+ _callback = del;
+ }
+
+ protected boolean sent(boolean done)
+ {
+ synchronized(this)
+ {
+ assert(_exception == null);
+
+ boolean alreadySent = (_state & StateSent) != 0;
+ _state |= StateSent;
+ if(done)
+ {
+ _state |= StateDone | StateOK;
+ _cancellationHandler = null;
+ if(_observer != null && (_callback == null || !_callback.__hasSentCallback()))
+ {
+ _observer.detach();
+ _observer = null;
+ }
+
+ //
+ // For oneway requests after the data has been sent
+ // the buffers can be reused unless this is a
+ // collocated invocation. For collocated invocations
+ // the buffer won't be reused because it has already
+ // been marked as cached in invokeCollocated.
+ //
+ cacheMessageBuffers();
+ }
+ this.notifyAll();
+ return !alreadySent && _callback != null && _callback.__hasSentCallback();
+ }
+ }
+
+ protected boolean finished(boolean ok)
+ {
+ synchronized(this)
+ {
+ _state |= StateDone;
+ if(ok)
+ {
+ _state |= StateOK;
+ }
+ _cancellationHandler = null;
+ if(_callback == null)
+ {
+ if(_observer != null)
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ }
+ this.notifyAll();
+ return _callback != null;
+ }
+ }
+
+ protected boolean finished(Ice.Exception ex)
+ {
+ synchronized(this)
+ {
+ _state |= StateDone;
+ _exception = ex;
+ _cancellationHandler = null;
+ if(_observer != null)
+ {
+ _observer.failed(ex.ice_name());
+ }
+ if(_callback == null)
+ {
+ if(_observer != null)
+ {
+ _observer.detach();
+ _observer = null;
+ }
+ }
+ this.notifyAll();
+ return _callback != null;
+ }
+ }
+
+ protected final void invokeSentAsync()
+ {
+ //
+ // This is called when it's not safe to call the sent callback
+ // synchronously from this thread. Instead the exception callback
+ // is called asynchronously from the client thread pool.
+ //
+ try
+ {
+ _instance.clientThreadPool().dispatch(new DispatchWorkItem(_cachedConnection)
+ {
+ @Override
+ public void run()
+ {
+ invokeSent();
+ }
+ });
+ }
+ catch(CommunicatorDestroyedException exc)
+ {
+ }
+ }
+
+ protected void cancel(Ice.LocalException ex)
+ {
+ synchronized(this)
+ {
+ _cancellationException = ex;
+ if(_cancellationHandler == null)
+ {
+ return;
+ }
+ }
+ _cancellationHandler.asyncRequestCanceled((OutgoingAsyncBase)this, ex);
+ }
+
+ protected void checkCanceled()
+ {
+ synchronized(this)
+ {
+ if(_cancellationException != null)
+ {
+ throw _cancellationException;
+ }
+ }
+ }
+
+ protected Ice.Instrumentation.InvocationObserver getObserver()
+ {
+ return _observer;
+ }
+
+ protected static void check(AsyncResult r, String operation)
+ {
+ if(r == null)
+ {
+ throw new IllegalArgumentException("AsyncResult == null");
+ }
+ else if(r.getOperation() != operation) // Do NOT use equals() here - we are comparing reference equality
+ {
+ throw new IllegalArgumentException("Incorrect operation for end_" + operation + " method: " +
+ r.getOperation());
+ }
+ }
+
+ private final void warning(RuntimeException ex)
+ {
+ if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0)
+ {
+ String s = "exception raised by AMI callback:\n" + Ex.toString(ex);
+ _instance.initializationData().logger.warning(s);
+ }
+ }
+
+ private final void error(Error error)
+ {
+ String s = "error raised by AMI callback:\n" + Ex.toString(error);
+ _instance.initializationData().logger.error(s);
+ }
+
+ protected final Instance _instance;
+ protected Ice.Instrumentation.InvocationObserver _observer;
+ protected Connection _cachedConnection;
+ protected boolean _sentSynchronously;
+
+ private final Communicator _communicator;
+ private final String _operation;
+ private final CallbackBase _callback;
+
+ private Ice.Exception _exception;
+
+ private CancellationHandler _cancellationHandler;
+ private Ice.LocalException _cancellationException;
+
+ protected static final byte StateOK = 0x1;
+ protected static final byte StateDone = 0x2;
+ protected static final byte StateSent = 0x4;
+ protected static final byte StateEndCalled = 0x8;
+ protected static final byte StateCachedBuffers = 0x10;
+ protected byte _state;
+}
diff --git a/java/src/IceInternal/BatchOutgoingAsync.java b/java/src/IceInternal/BatchOutgoingAsync.java
deleted file mode 100644
index ff8ba712185..00000000000
--- a/java/src/IceInternal/BatchOutgoingAsync.java
+++ /dev/null
@@ -1,117 +0,0 @@
-// **********************************************************************
-//
-// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
-//
-// This copy of Ice is licensed to you under the terms described in the
-// ICE_LICENSE file included in this distribution.
-//
-// **********************************************************************
-
-package IceInternal;
-
-abstract public class BatchOutgoingAsync extends OutgoingAsyncBase implements OutgoingAsyncMessageCallback
-{
- BatchOutgoingAsync(Ice.Communicator communicator, Instance instance, String operation, CallbackBase callback)
- {
- super(communicator, instance, operation, callback);
- }
-
- @Override
- public int
- send(Ice.ConnectionI connection, boolean compress, boolean response)
- {
- _cachedConnection = connection;
- return connection.flushAsyncBatchRequests(this);
- }
-
- @Override
- public int
- invokeCollocated(CollocatedRequestHandler handler)
- {
- return handler.invokeAsyncBatchRequests(this);
- }
-
- @Override
- public boolean
- sent()
- {
- synchronized(_monitor)
- {
- _state |= StateDone | StateOK | StateSent;
- //_os.resize(0, false); // Don't clear the buffer now, it's needed for the collocation optimization
- if(_childObserver != null)
- {
- _childObserver.detach();
- _childObserver = null;
- }
- if(_timeoutRequestHandler != null)
- {
- _future.cancel(false);
- _future = null;
- _timeoutRequestHandler = null;
- }
- _monitor.notifyAll();
-
- if(_callback == null || !_callback.__hasSentCallback())
- {
- if(_observer != null)
- {
- _observer.detach();
- _observer = null;
- }
- return false;
- }
- return true;
- }
- }
-
- @Override
- public void
- invokeSent()
- {
- invokeSentInternal();
- }
-
- @Override
- public void
- finished(Ice.Exception exc)
- {
- synchronized(_monitor)
- {
- if(_childObserver != null)
- {
- _childObserver.failed(exc.ice_name());
- _childObserver.detach();
- _childObserver = null;
- }
- if(_timeoutRequestHandler != null)
- {
- _future.cancel(false);
- _future = null;
- _timeoutRequestHandler = null;
- }
- }
- invokeException(exc);
- }
-
- @Override
- public void
- processRetry()
- {
- assert(false); // Retries are never scheduled
- }
-
- @Override
- public void
- dispatchInvocationCancel(final Ice.LocalException ex, ThreadPool threadPool, Ice.Connection connection)
- {
- threadPool.dispatch(new DispatchWorkItem(connection)
- {
- @Override
- public void run()
- {
- BatchOutgoingAsync.this.finished(ex);
- }
- });
- }
-}
diff --git a/java/src/IceInternal/CancellationHandler.java b/java/src/IceInternal/CancellationHandler.java
new file mode 100644
index 00000000000..0182f403cb4
--- /dev/null
+++ b/java/src/IceInternal/CancellationHandler.java
@@ -0,0 +1,15 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public interface CancellationHandler
+{
+ void asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex);
+}
diff --git a/java/src/IceInternal/CollocatedRequestHandler.java b/java/src/IceInternal/CollocatedRequestHandler.java
index 8de4a93ebc4..48d7bfa5b7d 100644
--- a/java/src/IceInternal/CollocatedRequestHandler.java
+++ b/java/src/IceInternal/CollocatedRequestHandler.java
@@ -13,8 +13,7 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
{
private class InvokeAllAsync extends DispatchWorkItem
{
- private InvokeAllAsync(OutgoingAsyncMessageCallback outAsync, BasicStream os, int requestId, int invokeNum,
- boolean batch)
+ private InvokeAllAsync(OutgoingAsyncBase outAsync, BasicStream os, int requestId, int invokeNum, boolean batch)
{
_outAsync = outAsync;
_os = os;
@@ -32,7 +31,7 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
}
}
- private final OutgoingAsyncMessageCallback _outAsync;
+ private final OutgoingAsyncBase _outAsync;
private BasicStream _os;
private final int _requestId;
private final int _invokeNum;
@@ -186,14 +185,14 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
@Override
public int
- sendAsyncRequest(OutgoingAsyncMessageCallback outAsync)
+ sendAsyncRequest(OutgoingAsyncBase outAsync)
{
return outAsync.invokeCollocated(this);
}
@Override
- synchronized public boolean
- asyncRequestCanceled(OutgoingAsyncMessageCallback outAsync, Ice.LocalException ex)
+ synchronized public void
+ asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex)
{
Integer requestId = _sendAsyncRequests.get(outAsync);
if(requestId != null)
@@ -203,8 +202,11 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
_asyncRequests.remove(requestId);
}
_sendAsyncRequests.remove(outAsync);
- outAsync.dispatchInvocationCancel(ex, _reference.getInstance().clientThreadPool(), null);
- return true; // We're done
+ if(outAsync.completed(ex))
+ {
+ outAsync.invokeCompletedAsync();
+ }
+ return;
}
if(outAsync instanceof OutgoingAsync)
@@ -216,12 +218,14 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
if(e.getValue() == o)
{
_asyncRequests.remove(e.getKey());
- outAsync.dispatchInvocationCancel(ex, _reference.getInstance().clientThreadPool(), null);
- return true; // We're done
+ if(outAsync.completed(ex))
+ {
+ outAsync.invokeCompletedAsync();
+ }
+ return;
}
}
}
- return false;
}
@Override
@@ -242,9 +246,13 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
}
outAsync = _asyncRequests.remove(requestId);
+ if(outAsync != null && !outAsync.completed(os))
+ {
+ outAsync = null;
+ }
}
- if(outAsync != null && outAsync.finished(os))
+ if(outAsync != null)
{
outAsync.invokeCompleted();
}
@@ -271,18 +279,7 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
public void
invokeException(int requestId, Ice.LocalException ex, int invokeNum)
{
- if(requestId > 0)
- {
- OutgoingAsync outAsync = null;
- synchronized(this)
- {
- outAsync = _asyncRequests.remove(requestId);
- }
- if(outAsync != null)
- {
- outAsync.finished(ex);
- }
- }
+ handleException(requestId, ex);
_adapter.decDirectCount();
}
@@ -307,7 +304,7 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
return null;
}
- void invokeAsyncRequest(OutgoingAsync outAsync, boolean synchronous)
+ int invokeAsyncRequest(OutgoingAsync outAsync, boolean synchronous)
{
int requestId = 0;
if((_reference.getInstance().queueRequests() || _reference.getInvocationTimeout() > 0) || _response)
@@ -323,6 +320,7 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
{
_sendAsyncRequests.put(outAsync, requestId);
}
+ outAsync.cancelable(this);
}
}
@@ -355,9 +353,10 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
{
_adapter.getThreadPool().dispatch(new InvokeAllAsync(outAsync, outAsync.getOs(), requestId, 1, false));
}
+ return AsyncStatus.Queued;
}
- int invokeAsyncBatchRequests(BatchOutgoingAsync outAsync)
+ int invokeAsyncBatchRequests(OutgoingAsyncBase outAsync)
{
int invokeNum;
synchronized(this)
@@ -370,6 +369,7 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
if(_reference.getInstance().queueRequests() || _reference.getInvocationTimeout() > 0)
{
_sendAsyncRequests.put(outAsync, 0);
+ outAsync.cancelable(this);
}
assert(!_batchStream.isEmpty());
@@ -404,7 +404,7 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
}
private boolean
- sentAsync(final OutgoingAsyncMessageCallback outAsync)
+ sentAsync(final OutgoingAsyncBase outAsync)
{
if(_reference.getInstance().queueRequests() || _reference.getInvocationTimeout() > 0)
{
@@ -511,10 +511,15 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
synchronized(this)
{
outAsync = _asyncRequests.remove(requestId);
+ if(outAsync != null && !outAsync.completed(ex))
+ {
+ outAsync = null;
+ }
}
+
if(outAsync != null)
{
- outAsync.finished(ex);
+ outAsync.invokeCompleted();
}
}
@@ -567,8 +572,8 @@ public class CollocatedRequestHandler implements RequestHandler, ResponseHandler
// A map of outstanding requests that can be canceled. A request
// can be canceled if it has an invocation timeout, or we support
// interrupts.
- private java.util.Map<OutgoingAsyncMessageCallback, Integer> _sendAsyncRequests =
- new java.util.HashMap<OutgoingAsyncMessageCallback, Integer>();
+ private java.util.Map<OutgoingAsyncBase, Integer> _sendAsyncRequests =
+ new java.util.HashMap<OutgoingAsyncBase, Integer>();
private java.util.Map<Integer, OutgoingAsync> _asyncRequests = new java.util.HashMap<Integer, OutgoingAsync>();
diff --git a/java/src/IceInternal/CommunicatorBatchOutgoingAsync.java b/java/src/IceInternal/CommunicatorFlushBatch.java
index ab1854cbce1..19e55ecc91c 100644
--- a/java/src/IceInternal/CommunicatorBatchOutgoingAsync.java
+++ b/java/src/IceInternal/CommunicatorFlushBatch.java
@@ -16,12 +16,29 @@ import java.util.concurrent.RejectedExecutionException;
import Ice.CommunicatorDestroyedException;
-public class CommunicatorBatchOutgoingAsync extends OutgoingAsyncBase
+public class CommunicatorFlushBatch extends IceInternal.AsyncResultI
{
- public CommunicatorBatchOutgoingAsync(Ice.Communicator communicator, Instance instance, String operation,
- CallbackBase callback)
+ public static CommunicatorFlushBatch check(Ice.AsyncResult r, Ice.Communicator com, String operation)
{
- super(communicator, instance, operation, callback);
+ check(r, operation);
+ if(!(r instanceof CommunicatorFlushBatch))
+ {
+ throw new IllegalArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ if(r.getCommunicator() != com)
+ {
+ throw new IllegalArgumentException("Communicator for call to end_" + operation +
+ " does not match communicator that was used to call corresponding " +
+ "begin_" + operation + " method");
+ }
+ return (CommunicatorFlushBatch)r;
+ }
+
+ public CommunicatorFlushBatch(Ice.Communicator communicator, Instance instance, String op, CallbackBase callback)
+ {
+ super(communicator, instance, op, callback);
+
+ _observer = ObserverHelper.get(instance, op);
//
// _useCount is initialized to 1 to prevent premature callbacks.
@@ -29,34 +46,22 @@ public class CommunicatorBatchOutgoingAsync extends OutgoingAsyncBase
// been initiated.
//
_useCount = 1;
-
- //
- // Assume all connections are flushed synchronously.
- //
- _sentSynchronously = true;
-
- //
- // Attach observer
- //
- _observer = ObserverHelper.get(instance, operation);
}
public void flushConnection(final Ice.ConnectionI con)
{
- class BatchOutgoingAsyncI extends BatchOutgoingAsync
+ class FlushBatch extends OutgoingAsyncBase
{
- public
- BatchOutgoingAsyncI()
+ public FlushBatch()
{
- super(CommunicatorBatchOutgoingAsync.this._communicator,
- CommunicatorBatchOutgoingAsync.this._instance,
- CommunicatorBatchOutgoingAsync.this._operation,
+ super(CommunicatorFlushBatch.this.getCommunicator(),
+ CommunicatorFlushBatch.this._instance,
+ CommunicatorFlushBatch.this.getOperation(),
null);
}
@Override
- public boolean
- sent()
+ public boolean sent()
{
if(_childObserver != null)
{
@@ -69,8 +74,7 @@ public class CommunicatorBatchOutgoingAsync extends OutgoingAsyncBase
// TODO: MJN: This is missing a test.
@Override
- public void
- finished(Ice.Exception ex)
+ public boolean completed(Ice.Exception ex)
{
if(_childObserver != null)
{
@@ -79,37 +83,23 @@ public class CommunicatorBatchOutgoingAsync extends OutgoingAsyncBase
_childObserver = null;
}
doCheck(false);
+ return false;
}
- @Override
- public void
- attachRemoteObserver(Ice.ConnectionInfo info, Ice.Endpoint endpt, int requestId, int size)
- {
- if(CommunicatorBatchOutgoingAsync.this._observer != null)
- {
- _childObserver = CommunicatorBatchOutgoingAsync.this._observer.getRemoteObserver(info, endpt,
- requestId, size);
- if(_childObserver != null)
- {
- _childObserver.attach();
- }
- }
- }
-
- @Override
- protected void cancelRequest()
+ @Override
+ protected Ice.Instrumentation.InvocationObserver getObserver()
{
+ return CommunicatorFlushBatch.this._observer;
}
}
- synchronized(_monitor)
+ synchronized(this)
{
++_useCount;
}
try
{
- int status;
if(_instance.queueRequests())
{
Future<Integer> future = _instance.getQueueExecutor().submit(new Callable<Integer>()
@@ -117,7 +107,7 @@ public class CommunicatorBatchOutgoingAsync extends OutgoingAsyncBase
@Override
public Integer call() throws RetryException
{
- return con.flushAsyncBatchRequests(new BatchOutgoingAsyncI());
+ return con.flushAsyncBatchRequests(new FlushBatch());
}
});
@@ -126,7 +116,7 @@ public class CommunicatorBatchOutgoingAsync extends OutgoingAsyncBase
{
try
{
- status = future.get();
+ future.get();
if(interrupted)
{
Thread.currentThread().interrupt();
@@ -160,11 +150,7 @@ public class CommunicatorBatchOutgoingAsync extends OutgoingAsyncBase
}
else
{
- status = con.flushAsyncBatchRequests(new BatchOutgoingAsyncI());
- }
- if((status & AsyncStatus.Sent) > 0)
- {
- _sentSynchronously = false;
+ con.flushAsyncBatchRequests(new FlushBatch());
}
}
catch(Ice.LocalException ex)
@@ -181,53 +167,28 @@ public class CommunicatorBatchOutgoingAsync extends OutgoingAsyncBase
private void doCheck(boolean userThread)
{
- synchronized(_monitor)
+ synchronized(this)
{
assert(_useCount > 0);
if(--_useCount > 0)
{
return;
}
- _state |= StateDone | StateOK | StateSent;
- _os.resize(0, false); // Clear buffer now, instead of waiting for AsyncResult deallocation
- _monitor.notifyAll();
}
- if(_callback == null || !_callback.__hasSentCallback())
- {
- if(_observer != null)
- {
- _observer.detach();
- _observer = null;
- }
- }
- else
+ if(sent(true))
{
- //
- // sentSynchronously_ is immutable here.
- //
- if(!_sentSynchronously || !userThread)
+ if(userThread)
{
- invokeSentAsync();
+ _sentSynchronously = true;
+ invokeSent();
}
else
{
- invokeSentInternal();
+ invokeSentAsync();
}
}
}
- @Override
- public void
- processRetry()
- {
- assert(false); // Retries are never scheduled
- }
-
- @Override
- protected void cancelRequest()
- {
- }
-
private int _useCount;
}
diff --git a/java/src/IceInternal/ConnectRequestHandler.java b/java/src/IceInternal/ConnectRequestHandler.java
index 91957af1a0c..e4c1e6b1727 100644
--- a/java/src/IceInternal/ConnectRequestHandler.java
+++ b/java/src/IceInternal/ConnectRequestHandler.java
@@ -22,12 +22,12 @@ public class ConnectRequestHandler
this.os.swap(os);
}
- Request(OutgoingAsyncMessageCallback out)
+ Request(OutgoingAsyncBase out)
{
this.outAsync = out;
}
- OutgoingAsyncMessageCallback outAsync = null;
+ OutgoingAsyncBase outAsync = null;
BasicStream os = null;
}
@@ -149,7 +149,7 @@ public class ConnectRequestHandler
@Override
public int
- sendAsyncRequest(OutgoingAsyncMessageCallback out)
+ sendAsyncRequest(OutgoingAsyncBase out)
throws RetryException
{
synchronized(this)
@@ -159,6 +159,7 @@ public class ConnectRequestHandler
if(!initialized())
{
_requests.add(new Request(out));
+ out.cancelable(this);
return AsyncStatus.Queued;
}
}
@@ -171,14 +172,14 @@ public class ConnectRequestHandler
}
@Override
- public boolean
- asyncRequestCanceled(OutgoingAsyncMessageCallback outAsync, Ice.LocalException ex)
+ public void
+ asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex)
{
synchronized(this)
{
if(_exception != null)
{
- return false; // The request has been notified of a failure already.
+ return; // The request has been notified of a failure already.
}
if(!initialized())
@@ -190,14 +191,17 @@ public class ConnectRequestHandler
if(request.outAsync == outAsync)
{
it.remove();
- outAsync.dispatchInvocationCancel(ex, _reference.getInstance().clientThreadPool(), null);
- return true; // We're done
+ 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.
}
}
- return _connection.asyncRequestCanceled(outAsync, ex);
+ _connection.asyncRequestCanceled(outAsync, ex);
}
@Override
@@ -394,8 +398,7 @@ public class ConnectRequestHandler
_flushing = true;
}
- final java.util.List<OutgoingAsyncMessageCallback> sentCallbacks =
- new java.util.ArrayList<OutgoingAsyncMessageCallback>();
+ final java.util.List<OutgoingAsyncBase> sentCallbacks = new java.util.ArrayList<OutgoingAsyncBase>();
try
{
java.util.Iterator<Request> p = _requests.iterator(); // _requests is immutable when _flushing = true
@@ -476,7 +479,7 @@ public class ConnectRequestHandler
@Override
public void run()
{
- for(OutgoingAsyncMessageCallback callback : sentCallbacks)
+ for(OutgoingAsyncBase callback : sentCallbacks)
{
callback.invokeSent();
}
@@ -546,7 +549,10 @@ public class ConnectRequestHandler
{
if(request.outAsync != null)
{
- request.outAsync.finished(_exception);
+ if(request.outAsync.completed(_exception))
+ {
+ request.outAsync.invokeCompleted();
+ }
}
}
_requests.clear();
diff --git a/java/src/IceInternal/ConnectionBatchOutgoingAsync.java b/java/src/IceInternal/ConnectionBatchOutgoingAsync.java
deleted file mode 100644
index 5a1f0a30886..00000000000
--- a/java/src/IceInternal/ConnectionBatchOutgoingAsync.java
+++ /dev/null
@@ -1,107 +0,0 @@
-// **********************************************************************
-//
-// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
-//
-// This copy of Ice is licensed to you under the terms described in the
-// ICE_LICENSE file included in this distribution.
-//
-// **********************************************************************
-
-package IceInternal;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.RejectedExecutionException;
-
-import Ice.CommunicatorDestroyedException;
-
-public class ConnectionBatchOutgoingAsync extends BatchOutgoingAsync
-{
- public ConnectionBatchOutgoingAsync(Ice.ConnectionI con, Ice.Communicator communicator, Instance instance,
- String operation, CallbackBase callback)
- {
- super(communicator, instance, operation, callback);
- _connection = con;
- }
-
- public void __invoke()
- {
- int status;
- if(_instance.queueRequests())
- {
- Future<Integer> future = _instance.getQueueExecutor().submit(new Callable<Integer>()
- {
- @Override
- public Integer call() throws RetryException
- {
- return _connection.flushAsyncBatchRequests(ConnectionBatchOutgoingAsync.this);
- }
- });
-
- boolean interrupted = false;
- while(true)
- {
- try
- {
- status = future.get();
- if(interrupted)
- {
- Thread.currentThread().interrupt();
- }
- break;
- }
- catch(InterruptedException ex)
- {
- interrupted = true;
- }
- catch(RejectedExecutionException e)
- {
- throw new CommunicatorDestroyedException();
- }
- catch(ExecutionException e)
- {
- try
- {
- throw e.getCause();
- }
- catch(RuntimeException ex)
- {
- throw ex;
- }
- catch(Throwable ex)
- {
- assert(false);
- }
- }
- }
- }
- else
- {
- status = _connection.flushAsyncBatchRequests(this);
- }
-
- if((status & AsyncStatus.Sent) > 0)
- {
- _sentSynchronously = true;
- if((status & AsyncStatus.InvokeSentCallback) > 0)
- {
- invokeSent();
- }
- }
- }
-
- @Override
- public Ice.Connection getConnection()
- {
- return _connection;
- }
-
- @Override
- protected void cancelRequest()
- {
- _connection.asyncRequestCanceled(this, new Ice.OperationInterruptedException());
- }
-
- private Ice.ConnectionI _connection;
-}
diff --git a/java/src/IceInternal/ConnectionFlushBatch.java b/java/src/IceInternal/ConnectionFlushBatch.java
new file mode 100644
index 00000000000..4b3da0bcb5e
--- /dev/null
+++ b/java/src/IceInternal/ConnectionFlushBatch.java
@@ -0,0 +1,128 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+
+import Ice.CommunicatorDestroyedException;
+
+public class ConnectionFlushBatch extends OutgoingAsyncBase
+{
+ public static ConnectionFlushBatch check(Ice.AsyncResult r, Ice.Connection con, String operation)
+ {
+ check(r, operation);
+ if(!(r instanceof ConnectionFlushBatch))
+ {
+ throw new IllegalArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ if(r.getConnection() != con)
+ {
+ throw new IllegalArgumentException("Connection for call to end_" + operation +
+ " does not match connection that was used to call corresponding " +
+ "begin_" + operation + " method");
+ }
+ return (ConnectionFlushBatch)r;
+ }
+
+ public ConnectionFlushBatch(Ice.ConnectionI con, Ice.Communicator communicator, Instance instance,
+ String operation, CallbackBase callback)
+ {
+ super(communicator, instance, operation, callback);
+ _connection = con;
+ }
+
+ @Override
+ public Ice.Connection getConnection()
+ {
+ return _connection;
+ }
+
+ public void invoke()
+ {
+ try
+ {
+ int status;
+ if(_instance.queueRequests())
+ {
+ Future<Integer> future = _instance.getQueueExecutor().submit(
+ new Callable<Integer>()
+ {
+ @Override
+ public Integer call() throws RetryException
+ {
+ return _connection.flushAsyncBatchRequests(ConnectionFlushBatch.this);
+ }
+ });
+
+ boolean interrupted = false;
+ while(true)
+ {
+ try
+ {
+ status = future.get();
+ if(interrupted)
+ {
+ Thread.currentThread().interrupt();
+ }
+ break;
+ }
+ catch(InterruptedException ex)
+ {
+ interrupted = true;
+ }
+ catch(RejectedExecutionException e)
+ {
+ throw new CommunicatorDestroyedException();
+ }
+ catch(ExecutionException e)
+ {
+ try
+ {
+ throw e.getCause();
+ }
+ catch(RuntimeException ex)
+ {
+ throw ex;
+ }
+ catch(Throwable ex)
+ {
+ assert(false);
+ }
+ }
+ }
+ }
+ else
+ {
+ status = _connection.flushAsyncBatchRequests(this);
+ }
+
+ if((status & AsyncStatus.Sent) > 0)
+ {
+ _sentSynchronously = true;
+ if((status & AsyncStatus.InvokeSentCallback) > 0)
+ {
+ invokeSent();
+ }
+ }
+ }
+ catch(Ice.Exception ex)
+ {
+ if(completed(ex))
+ {
+ invokeCompletedAsync();
+ }
+ }
+ }
+
+ private Ice.ConnectionI _connection;
+}
diff --git a/java/src/IceInternal/ConnectionRequestHandler.java b/java/src/IceInternal/ConnectionRequestHandler.java
index f7ca7bb5b29..924b633e670 100644
--- a/java/src/IceInternal/ConnectionRequestHandler.java
+++ b/java/src/IceInternal/ConnectionRequestHandler.java
@@ -69,17 +69,17 @@ public class ConnectionRequestHandler implements RequestHandler
}
@Override
- public int sendAsyncRequest(OutgoingAsyncMessageCallback out)
+ public int sendAsyncRequest(OutgoingAsyncBase out)
throws RetryException
{
return out.send(_connection, _compress, _response);
}
@Override
- public boolean
- asyncRequestCanceled(OutgoingAsyncMessageCallback outgoingAsync, Ice.LocalException ex)
+ public void
+ asyncRequestCanceled(OutgoingAsyncBase outgoingAsync, Ice.LocalException ex)
{
- return _connection.asyncRequestCanceled(outgoingAsync, ex);
+ _connection.asyncRequestCanceled(outgoingAsync, ex);
}
@Override
@@ -103,8 +103,8 @@ public class ConnectionRequestHandler implements RequestHandler
return _connection;
}
- public ConnectionRequestHandler(Reference ref, Ice.ConnectionI connection,
- boolean compress) {
+ public ConnectionRequestHandler(Reference ref, Ice.ConnectionI connection, boolean compress)
+ {
_reference = ref;
_response = _reference.getMode() == Reference.ModeTwoway;
_connection = connection;
diff --git a/java/src/IceInternal/GetConnectionOutgoingAsync.java b/java/src/IceInternal/GetConnectionOutgoingAsync.java
deleted file mode 100644
index 55653630ca2..00000000000
--- a/java/src/IceInternal/GetConnectionOutgoingAsync.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// **********************************************************************
-//
-// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
-//
-// This copy of Ice is licensed to you under the terms described in the
-// ICE_LICENSE file included in this distribution.
-//
-// **********************************************************************
-
-package IceInternal;
-
-public class GetConnectionOutgoingAsync extends OutgoingAsyncBase implements OutgoingAsyncMessageCallback
-{
- public GetConnectionOutgoingAsync(Ice.ObjectPrxHelperBase prx, String operation, CallbackBase cb)
- {
- super(prx.ice_getCommunicator(), ((Ice.ObjectPrxHelperBase) prx).__reference().getInstance(), operation, cb);
- _proxy = (Ice.ObjectPrxHelperBase) prx;
- _cnt = 0;
- _observer = ObserverHelper.get(prx, operation);
- }
-
- public void __invoke()
- {
- while(true)
- {
- try
- {
- _handler = _proxy.__getRequestHandler();
- _handler.sendAsyncRequest(this);
- }
- catch(RetryException ex)
- {
- _proxy.__setRequestHandler(_handler, null);
- }
- catch(Ice.Exception ex)
- {
- handleException(ex);
- }
- break;
- }
- }
-
- @Override
- public Ice.ObjectPrx getProxy()
- {
- return _proxy;
- }
-
- @Override
- public int send(Ice.ConnectionI conection, boolean compress, boolean response)
- throws RetryException
- {
- sent();
- return 0;
- }
-
- @Override
- public int invokeCollocated(CollocatedRequestHandler handler)
- {
- sent();
- return 0;
- }
-
- @Override
- public boolean sent()
- {
- synchronized(_monitor)
- {
- _state |= StateDone;
- _monitor.notifyAll();
- }
- invokeCompleted();
- return false;
- }
-
- @Override
- public void invokeSent()
- {
- // No sent callback
- }
-
- @Override
- public void finished(Ice.Exception exc)
- {
- try
- {
- handleException(exc);
- }
- catch(Ice.Exception ex)
- {
- invokeExceptionAsync(ex);
- }
- }
-
- @Override
- void processRetry()
- {
- __invoke();
- }
-
- @Override
- public void dispatchInvocationCancel(final Ice.LocalException ex, ThreadPool threadPool, Ice.Connection connection)
- {
- threadPool.dispatch(new DispatchWorkItem(connection)
- {
- @Override
- public void run()
- {
- GetConnectionOutgoingAsync.this.finished(ex);
- }
- });
- }
-
- @Override
- protected void cancelRequest()
- {
- if(_handler != null)
- {
- _handler.asyncRequestCanceled(this, new Ice.OperationInterruptedException());
- }
- }
-
- private void handleException(Ice.Exception exc)
- {
- try
- {
- Ice.Holder<Integer> interval = new Ice.Holder<Integer>();
- _cnt = _proxy.__handleException(exc, _handler, Ice.OperationMode.Idempotent, false, interval, _cnt);
- if(_observer != null)
- {
- _observer.retried(); // Invocation is being retried
- }
- _instance.retryQueue().add(this, interval.value);
- }
- catch(Ice.Exception ex)
- {
- if(_observer != null)
- {
- _observer.failed(ex.ice_name());
- }
- throw ex;
- }
- }
-
- private Ice.ObjectPrxHelperBase _proxy;
- private RequestHandler _handler = null;
- private int _cnt;
-}
diff --git a/java/src/IceInternal/IncomingConnectionFactory.java b/java/src/IceInternal/IncomingConnectionFactory.java
index 89dcf9b44ed..31306a14ca6 100644
--- a/java/src/IceInternal/IncomingConnectionFactory.java
+++ b/java/src/IceInternal/IncomingConnectionFactory.java
@@ -170,7 +170,7 @@ public final class IncomingConnectionFactory extends EventHandler implements Ice
}
public void
- flushAsyncBatchRequests(CommunicatorBatchOutgoingAsync outAsync)
+ flushAsyncBatchRequests(CommunicatorFlushBatch outAsync)
{
for(Ice.ConnectionI c : connections()) // connections() is synchronized, no need to synchronize here.
{
diff --git a/java/src/IceInternal/ObjectAdapterFactory.java b/java/src/IceInternal/ObjectAdapterFactory.java
index 63c3e592669..a723537cd7e 100644
--- a/java/src/IceInternal/ObjectAdapterFactory.java
+++ b/java/src/IceInternal/ObjectAdapterFactory.java
@@ -218,7 +218,7 @@ public final class ObjectAdapterFactory
}
public void
- flushAsyncBatchRequests(CommunicatorBatchOutgoingAsync outAsync)
+ flushAsyncBatchRequests(CommunicatorFlushBatch outAsync)
{
java.util.List<Ice.ObjectAdapterI> adapters;
synchronized(this)
diff --git a/java/src/IceInternal/OutgoingAsync.java b/java/src/IceInternal/OutgoingAsync.java
index ef4d3d7c959..e42c817b42c 100644
--- a/java/src/IceInternal/OutgoingAsync.java
+++ b/java/src/IceInternal/OutgoingAsync.java
@@ -9,41 +9,47 @@
package IceInternal;
-public class OutgoingAsync extends OutgoingAsyncBase implements OutgoingAsyncMessageCallback
+public class OutgoingAsync extends ProxyOutgoingAsyncBase
{
+ public static OutgoingAsync check(Ice.AsyncResult r, Ice.ObjectPrx prx, String operation)
+ {
+ ProxyOutgoingAsyncBase.checkImpl(r, prx, operation);
+ try
+ {
+ return (OutgoingAsync)r;
+ }
+ catch(ClassCastException ex)
+ {
+ throw new IllegalArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ }
+
public OutgoingAsync(Ice.ObjectPrx prx, String operation, CallbackBase cb)
{
- super(prx.ice_getCommunicator(), ((Ice.ObjectPrxHelperBase) prx).__reference().getInstance(), operation, cb);
- _proxy = (Ice.ObjectPrxHelperBase) prx;
+ super((Ice.ObjectPrxHelperBase)prx, operation, cb);
_encoding = Protocol.getCompatibleEncoding(_proxy.__reference().getEncoding());
+ _is = null;
}
- public OutgoingAsync(Ice.ObjectPrx prx, String operation, CallbackBase cb, IceInternal.BasicStream is,
- IceInternal.BasicStream os)
+ public OutgoingAsync(Ice.ObjectPrx prx, String operation, CallbackBase cb, BasicStream is, BasicStream os)
{
- super(prx.ice_getCommunicator(), ((Ice.ObjectPrxHelperBase) prx).__reference().getInstance(), operation, cb,
- is, os);
- _proxy = (Ice.ObjectPrxHelperBase) prx;
+ super((Ice.ObjectPrxHelperBase)prx, operation, cb, os);
_encoding = Protocol.getCompatibleEncoding(_proxy.__reference().getEncoding());
+ _is = is;
}
public void prepare(String operation, Ice.OperationMode mode, java.util.Map<String, String> ctx,
boolean explicitCtx, boolean synchronous)
{
- _handler = null;
- _cnt = 0;
- _sent = false;
+ Protocol.checkSupportedProtocol(Protocol.getCompatibleProtocol(_proxy.__reference().getProtocol()));
+
_mode = mode;
- _sentSynchronously = false;
_synchronous = synchronous;
- Protocol.checkSupportedProtocol(Protocol.getCompatibleProtocol(_proxy.__reference().getProtocol()));
-
if(explicitCtx && ctx == null)
{
ctx = _emptyContext;
}
-
_observer = ObserverHelper.get(_proxy, operation, ctx);
switch(_proxy.__reference().getMode())
@@ -137,12 +143,6 @@ public class OutgoingAsync extends OutgoingAsyncBase implements OutgoingAsyncMes
}
@Override
- public Ice.ObjectPrx getProxy()
- {
- return _proxy;
- }
-
- @Override
public int send(Ice.ConnectionI connection, boolean compress, boolean response) throws RetryException
{
_cachedConnection = connection;
@@ -158,117 +158,52 @@ public class OutgoingAsync extends OutgoingAsyncBase implements OutgoingAsyncMes
// Disable caching by marking the streams as cached!
_state |= StateCachedBuffers;
}
- handler.invokeAsyncRequest(this, _synchronous);
- return AsyncStatus.Queued;
+ return handler.invokeAsyncRequest(this, _synchronous);
}
@Override
- public boolean sent()
+ public void abort(Ice.Exception ex)
{
- synchronized(_monitor)
+ int mode = _proxy.__reference().getMode();
+ if(mode == Reference.ModeBatchOneway || mode == Reference.ModeBatchDatagram)
{
- boolean alreadySent = (_state & StateSent) != 0;
- _state |= StateSent;
- _sent = true;
-
- assert ((_state & StateDone) == 0);
-
- if(!_proxy.ice_isTwoway())
+ if(_handler != null)
{
- if(_childObserver != null)
- {
- _childObserver.detach();
- _childObserver = null;
- }
- if(_observer != null && (_callback == null || !_callback.__hasSentCallback()))
- {
- _observer.detach();
- _observer = null;
- }
- if(_timeoutRequestHandler != null)
- {
- _future.cancel(false);
- _future = null;
- _timeoutRequestHandler = null;
- }
- _state |= StateDone | StateOK;
- // _os.resize(0, false); // Don't clear the buffer now, it's
- // needed for the collocation optimization
-
- // For oneway requests after the data has been sent the buffers
- // can be reused unless this is a collocated invocation. For
- // collocated invocations the buffer won't be reused as the
- // because it has already been marked as cached in
- // invokeCollocated.
- cacheMessageBuffers();
+ //
+ // If we didn't finish a batch oneway or datagram request, we
+ // must notify the connection about that we give up ownership
+ // of the batch stream.
+ //
+ _handler.abortBatchRequest();
}
- _monitor.notifyAll();
-
- // Don't call the sent call is already sent.
- return !alreadySent && _callback != null && _callback.__hasSentCallback();
}
- }
- @Override
- public void invokeSent()
- {
- invokeSentInternal();
+ super.abort(ex);
}
- @Override
- public void finished(Ice.Exception exc)
+ public void invoke()
{
- synchronized(_monitor)
+ int mode = _proxy.__reference().getMode();
+ if(mode == Reference.ModeBatchOneway || mode == Reference.ModeBatchDatagram)
{
- assert ((_state & StateDone) == 0);
- if(_childObserver != null)
- {
- _childObserver.failed(exc.ice_name());
- _childObserver.detach();
- _childObserver = null;
- }
- if(_timeoutRequestHandler != null)
+ if(_handler != null)
{
- _future.cancel(false);
- _future = null;
- _timeoutRequestHandler = null;
+ _sentSynchronously = true;
+ _handler.finishBatchRequest(_os);
+ finished(true);
}
+ return; // Don't call sent/completed callback for batch AMI requests
}
//
- // NOTE: at this point, synchronization isn't needed, no other threads
- // should be calling on the callback.
+ // NOTE: invokeImpl doesn't throw so this can be called from the
+ // try block with the catch block calling abort() in case of an
+ // exception.
//
- try
- {
- handleException(exc);
- }
- catch(Ice.Exception ex)
- {
- invokeException(ex);
- }
- }
-
- @Override
- void processRetry()
- {
- invoke(false);
- }
-
- @Override
- public void dispatchInvocationCancel(final Ice.LocalException ex, ThreadPool threadPool, Ice.Connection connection)
- {
- threadPool.dispatch(new DispatchWorkItem(connection)
- {
- @Override
- public void run()
- {
- OutgoingAsync.this.finished(ex);
- }
- });
+ invokeImpl(true); // userThread = true
}
- public final boolean finished(BasicStream is)
+ public final boolean completed(BasicStream is)
{
//
// NOTE: this method is called from ConnectionI.parseMessage
@@ -276,291 +211,153 @@ public class OutgoingAsync extends OutgoingAsyncBase implements OutgoingAsyncMes
// any user callbacks.
//
- assert (_proxy.ice_isTwoway()); // Can only be called for twoways.
-
+ assert(_proxy.ice_isTwoway()); // Can only be called for twoways.
+
+ if(_childObserver != null)
+ {
+ _childObserver.reply(is.size() - Protocol.headerSize - 4);
+ _childObserver.detach();
+ _childObserver = null;
+ }
+
byte replyStatus;
try
{
- synchronized(_monitor)
+ // _is can already be initialized if the invocation is retried
+ if(_is == null)
+ {
+ _is = new IceInternal.BasicStream(_instance, IceInternal.Protocol.currentProtocolEncoding);
+ }
+ _is.swap(is);
+ replyStatus = _is.readByte();
+
+ switch(replyStatus)
+ {
+ case ReplyStatus.replyOK:
+ {
+ break;
+ }
+
+ case ReplyStatus.replyUserException:
{
- assert (_exception == null && (_state & StateDone) == 0);
- if(_childObserver != null)
+ if(_observer != null)
{
- _childObserver.reply(is.size() - Protocol.headerSize - 4);
- _childObserver.detach();
- _childObserver = null;
+ _observer.userException();
}
-
- if(_timeoutRequestHandler != null)
+ break;
+ }
+
+ case ReplyStatus.replyObjectNotExist:
+ case ReplyStatus.replyFacetNotExist:
+ case ReplyStatus.replyOperationNotExist:
+ {
+ Ice.Identity id = new Ice.Identity();
+ id.__read(_is);
+
+ //
+ // For compatibility with the old FacetPath.
+ //
+ String[] facetPath = _is.readStringSeq();
+ String facet;
+ if(facetPath.length > 0)
{
- _future.cancel(false);
- _future = null;
- _timeoutRequestHandler = null;
+ if(facetPath.length > 1)
+ {
+ throw new Ice.MarshalException();
+ }
+ facet = facetPath[0];
}
-
- // _is can already be initialized if the invocation is retried
- if(_is == null)
+ else
{
- _is = new IceInternal.BasicStream(_instance, IceInternal.Protocol.currentProtocolEncoding);
+ facet = "";
}
- _is.swap(is);
- replyStatus = _is.readByte();
-
+
+ String operation = _is.readString();
+
+ Ice.RequestFailedException ex = null;
switch(replyStatus)
{
- case ReplyStatus.replyOK:
- {
- break;
- }
-
- case ReplyStatus.replyUserException:
- {
- if(_observer != null)
- {
- _observer.userException();
- }
- break;
- }
-
- case ReplyStatus.replyObjectNotExist:
- case ReplyStatus.replyFacetNotExist:
- case ReplyStatus.replyOperationNotExist:
- {
- Ice.Identity id = new Ice.Identity();
- id.__read(_is);
-
- //
- // For compatibility with the old FacetPath.
- //
- String[] facetPath = _is.readStringSeq();
- String facet;
- if(facetPath.length > 0)
- {
- if(facetPath.length > 1)
- {
- throw new Ice.MarshalException();
- }
- facet = facetPath[0];
- }
- else
- {
- facet = "";
- }
-
- String operation = _is.readString();
-
- Ice.RequestFailedException ex = null;
- switch(replyStatus)
- {
- case ReplyStatus.replyObjectNotExist:
- {
- ex = new Ice.ObjectNotExistException();
- break;
- }
-
- case ReplyStatus.replyFacetNotExist:
- {
- ex = new Ice.FacetNotExistException();
- break;
- }
-
- case ReplyStatus.replyOperationNotExist:
- {
- ex = new Ice.OperationNotExistException();
- break;
- }
-
- default:
- {
- assert (false);
- break;
- }
- }
-
- ex.id = id;
- ex.facet = facet;
- ex.operation = operation;
- throw ex;
- }
-
- case ReplyStatus.replyUnknownException:
- case ReplyStatus.replyUnknownLocalException:
- case ReplyStatus.replyUnknownUserException:
- {
- String unknown = _is.readString();
-
- Ice.UnknownException ex = null;
- switch(replyStatus)
- {
- case ReplyStatus.replyUnknownException:
- {
- ex = new Ice.UnknownException();
- break;
- }
-
- case ReplyStatus.replyUnknownLocalException:
- {
- ex = new Ice.UnknownLocalException();
- break;
- }
-
- case ReplyStatus.replyUnknownUserException:
- {
- ex = new Ice.UnknownUserException();
- break;
- }
-
- default:
- {
- assert (false);
- break;
- }
- }
-
- ex.unknown = unknown;
- throw ex;
- }
+ case ReplyStatus.replyObjectNotExist:
+ {
+ ex = new Ice.ObjectNotExistException();
+ break;
+ }
- default:
- {
- throw new Ice.UnknownReplyStatusException();
- }
+ case ReplyStatus.replyFacetNotExist:
+ {
+ ex = new Ice.FacetNotExistException();
+ break;
}
- if(replyStatus == ReplyStatus.replyOK)
+ case ReplyStatus.replyOperationNotExist:
{
- _state |= StateOK;
+ ex = new Ice.OperationNotExistException();
+ break;
}
- _state |= StateDone;
- _monitor.notifyAll();
- if(_callback == null)
+ default:
{
- if(_observer != null)
- {
- _observer.detach();
- _observer = null;
- }
- return false;
+ assert(false);
+ break;
}
- return true;
- }
- }
- catch(Ice.Exception exc)
- {
- //
- // We don't call finished(exc) here because we don't want
- // to invoke the completion callback. The completion
- // callback is invoked by the connection is this method
- // returns true.
- //
- try
- {
- handleException(exc);
- return false;
+ }
+
+ ex.id = id;
+ ex.facet = facet;
+ ex.operation = operation;
+ throw ex;
}
- catch(Ice.LocalException ex)
+
+ case ReplyStatus.replyUnknownException:
+ case ReplyStatus.replyUnknownLocalException:
+ case ReplyStatus.replyUnknownUserException:
{
- synchronized(_monitor)
- {
- _state |= StateDone;
- _exception = ex;
- _monitor.notifyAll();
+ String unknown = _is.readString();
- if(_callback == null)
- {
- if(_observer != null)
- {
- _observer.detach();
- _observer = null;
- }
- return false;
- }
- return true;
+ Ice.UnknownException ex = null;
+ switch(replyStatus)
+ {
+ case ReplyStatus.replyUnknownException:
+ {
+ ex = new Ice.UnknownException();
+ break;
}
- }
- }
- }
- public final boolean invoke(boolean userThread)
- {
- int mode = _proxy.__reference().getMode();
- if(mode == Reference.ModeBatchOneway || mode == Reference.ModeBatchDatagram)
- {
- _state |= StateDone | StateOK;
- _handler.finishBatchRequest(_os);
- if(_observer != null)
- {
- _observer.detach();
- _observer = null;
- }
- return true;
- }
+ case ReplyStatus.replyUnknownLocalException:
+ {
+ ex = new Ice.UnknownLocalException();
+ break;
+ }
- while(true)
- {
- try
- {
- _sent = false;
- _handler = _proxy.__getRequestHandler();
- int status = _handler.sendAsyncRequest(this);
- if((status & AsyncStatus.Sent) > 0)
+ case ReplyStatus.replyUnknownUserException:
{
- if(userThread)
- {
- _sentSynchronously = true;
- if((status & AsyncStatus.InvokeSentCallback) > 0)
- {
- invokeSent(); // Call from the user thread.
- }
- }
- else
- {
- if((status & AsyncStatus.InvokeSentCallback) > 0)
- {
- // Call from a client thread pool thread.
- invokeSentAsync();
- }
- }
+ ex = new Ice.UnknownUserException();
+ break;
}
- if(mode == IceInternal.Reference.ModeTwoway || (status & AsyncStatus.Sent) == 0)
+ default:
{
- synchronized(_monitor)
- {
- if((_state & StateDone) == 0)
- {
- int invocationTimeout = _handler.getReference().getInvocationTimeout();
- if(invocationTimeout > 0)
- {
- _future = _instance.timer().schedule(new Runnable()
- {
- @Override
- public void run()
- {
- timeout();
- }
- }, invocationTimeout, java.util.concurrent.TimeUnit.MILLISECONDS);
- _timeoutRequestHandler = _handler;
- }
- }
- }
+ assert(false);
+ break;
+ }
}
+
+ ex.unknown = unknown;
+ throw ex;
}
- catch(RetryException ex)
+
+ default:
{
- // Clear request handler and retry.
- _proxy.__setRequestHandler(_handler, null);
- continue;
+ throw new Ice.UnknownReplyStatusException();
}
- catch(Ice.Exception ex)
- {
- // This will throw if the invocation can't be retried.
- handleException(ex);
}
- break;
+
+ return finished(replyStatus == ReplyStatus.replyOK);
+ }
+ catch(Ice.Exception ex)
+ {
+ return completed(ex);
}
- return _sentSynchronously;
}
public BasicStream startWriteParams(Ice.FormatType format)
@@ -591,12 +388,48 @@ public class OutgoingAsync extends OutgoingAsyncBase implements OutgoingAsyncMes
}
}
+ public IceInternal.BasicStream startReadParams()
+ {
+ _is.startReadEncaps();
+ return _is;
+ }
+
+ public void endReadParams()
+ {
+ _is.endReadEncaps();
+ }
+
+ public void readEmptyParams()
+ {
+ _is.skipEmptyEncaps(null);
+ }
+
+ public byte[] readParamEncaps()
+ {
+ return _is.readEncaps(null);
+ }
+
+ public final void throwUserException()
+ throws Ice.UserException
+ {
+ try
+ {
+ _is.startReadEncaps();
+ _is.throwException(null);
+ }
+ catch(Ice.UserException ex)
+ {
+ _is.endReadEncaps();
+ throw ex;
+ }
+ }
+
@Override
public void cacheMessageBuffers()
{
if(_proxy.__reference().getInstance().cacheMessageBuffers() > 0)
{
- synchronized(_monitor)
+ synchronized(this)
{
if((_state & StateCachedBuffers) > 0)
{
@@ -612,76 +445,14 @@ public class OutgoingAsync extends OutgoingAsyncBase implements OutgoingAsyncMes
_os.reset();
_proxy.cacheMessageBuffers(_is, _os);
- }
- }
- @Override
- public void invokeExceptionAsync(final Ice.Exception ex)
- {
- if((_state & StateDone) == 0 && _handler != null)
- {
- //
- // If we didn't finish a batch oneway or datagram request, we
- // must notify the connection about that we give up ownership
- // of the batch stream.
- //
- int mode = _proxy.__reference().getMode();
- if(mode == Reference.ModeBatchOneway || mode == Reference.ModeBatchDatagram)
- {
- _handler.abortBatchRequest();
- }
- }
-
- super.invokeExceptionAsync(ex);
- }
-
- @Override
- protected void cancelRequest()
- {
- if(_handler != null)
- {
- _handler.asyncRequestCanceled(this, new Ice.OperationInterruptedException());
+ _is = null;
+ _os = null;
}
}
- private void handleException(Ice.Exception exc)
- {
- try
- {
- Ice.Holder<Integer> interval = new Ice.Holder<Integer>();
- _cnt = _proxy.__handleException(exc, _handler, _mode, _sent, interval, _cnt);
- if(_observer != null)
- {
- _observer.retried(); // Invocation is being retried.
- }
-
- //
- // Schedule the retry. Note that we always schedule the retry
- // on the retry queue even if the invocation can be retried
- // immediately. This is required because it might not be safe
- // to retry from this thread (this is for instance called by
- // finished(BasicStream) which is called with the connection
- // locked.
- //
- _instance.retryQueue().add(this, interval.value);
- }
- catch(Ice.Exception ex)
- {
- if(_observer != null)
- {
- _observer.failed(ex.ice_name());
- }
- throw ex;
- }
- }
-
- final private Ice.ObjectPrxHelperBase _proxy;
final private Ice.EncodingVersion _encoding;
-
- private RequestHandler _handler;
- private int _cnt;
- private Ice.OperationMode _mode;
- private boolean _sent;
+ private BasicStream _is;
//
// If true this AMI request is being used for a generated synchronous invocation.
diff --git a/java/src/IceInternal/OutgoingAsyncBase.java b/java/src/IceInternal/OutgoingAsyncBase.java
index 2e6aa221f4d..f04b09ea941 100644
--- a/java/src/IceInternal/OutgoingAsyncBase.java
+++ b/java/src/IceInternal/OutgoingAsyncBase.java
@@ -9,385 +9,41 @@
package IceInternal;
-import Ice.AsyncResult;
-import Ice.Communicator;
-import Ice.CommunicatorDestroyedException;
-import Ice.Connection;
-import Ice.ObjectPrx;
-import Ice.UserException;
-
-/**
- * An AsyncResult object is the return value of an asynchronous invocation.
- * With this object, an application can obtain several attributes of the
- * invocation and discover its outcome.
- **/
-public abstract class OutgoingAsyncBase implements Ice.AsyncResult
+//
+// Base class for handling asynchronous invocations. This class is
+// responsible for the handling of the output stream and the child
+// invocation observer.
+//
+public abstract class OutgoingAsyncBase extends IceInternal.AsyncResultI
{
- protected OutgoingAsyncBase(Communicator communicator, IceInternal.Instance instance, String op,
- IceInternal.CallbackBase del)
+ public int send(Ice.ConnectionI connection, boolean compress, boolean response) throws RetryException
{
- _communicator = communicator;
- _instance = instance;
- _operation = op;
- _os = new IceInternal.BasicStream(instance, IceInternal.Protocol.currentProtocolEncoding);
- _state = 0;
- _sentSynchronously = false;
- _exception = null;
- _callback = del;
- }
-
- protected OutgoingAsyncBase(Communicator communicator, Instance instance, String op, CallbackBase del,
- BasicStream is, BasicStream os)
- {
- _communicator = communicator;
- _instance = instance;
- _operation = op;
- _os = os;
- _is = is;
- _state = 0;
- _sentSynchronously = false;
- _exception = null;
- _callback = del;
- }
-
- /**
- * Returns the communicator that sent the invocation.
- *
- * @return The communicator.
- **/
- @Override
- public Communicator getCommunicator()
- {
- return _communicator;
- }
-
- /**
- * Returns the connection that was used for the invocation.
- *
- * @return The connection.
- **/
- @Override
- public Connection getConnection()
- {
- return null;
- }
-
- /**
- * Returns the proxy that was used to call the <code>begin_</code> method.
- *
- * @return The proxy.
- **/
- @Override
- public ObjectPrx getProxy()
- {
- return null;
- }
-
- /**
- * Indicates whether the result of an invocation is available.
- *
- * @return True if the result is available, which means a call to the <code>end_</code>
- * method will not block. The method returns false if the result is not yet available.
- **/
- @Override
- public final boolean isCompleted()
- {
- synchronized(_monitor)
- {
- return (_state & StateDone) > 0;
- }
+ assert(false); // This should be overriden if this object is used with a request handler
+ return AsyncStatus.Queued;
}
- /**
- * Blocks the caller until the result of the invocation is available.
- **/
- @Override
- public final void waitForCompleted()
+ public int invokeCollocated(CollocatedRequestHandler handler)
{
- synchronized(_monitor)
- {
- if(Thread.interrupted())
- {
- throw new Ice.OperationInterruptedException();
- }
- while((_state & StateDone) == 0)
- {
- try
- {
- _monitor.wait();
- }
- catch(InterruptedException ex)
- {
- throw new Ice.OperationInterruptedException();
- }
- }
- }
+ assert(false); // This should be overriden if this object is used with a request handler
+ return AsyncStatus.Queued;
}
- /**
- * When you call the <code>begin_</code> method, the Ice run time attempts to
- * write the corresponding request to the client-side transport. If the
- * transport cannot accept the request, the Ice run time queues the request
- * for later transmission. This method returns true if, at the time it is called,
- * the request has been written to the local transport (whether it was initially
- * queued or not). Otherwise, if the request is still queued, this method returns
- * false.
- *
- * @return True if the request has been sent, or false if the request is queued.
- **/
- @Override
- public final boolean isSent()
+ public boolean sent()
{
- synchronized(_monitor)
- {
- return (_state & StateSent) > 0;
- }
+ return sent(true);
}
- /**
- * Blocks the caller until the request has been written to the client-side transport.
- **/
- @Override
- public final void waitForSent()
+ public boolean completed(Ice.Exception ex)
{
- synchronized(_monitor)
- {
- if(Thread.interrupted())
- {
- throw new Ice.OperationInterruptedException();
- }
- while((_state & StateSent) == 0 && _exception == null)
- {
- try
- {
- _monitor.wait();
- }
- catch(InterruptedException ex)
- {
- throw new Ice.OperationInterruptedException();
- }
- }
- }
+ return finished(ex);
}
- /**
- * If the invocation failed with a local exception, throws the local exception.
- **/
- @Override
- public final void throwLocalException()
+ public final void attachRemoteObserver(Ice.ConnectionInfo info, Ice.Endpoint endpt, int requestId)
{
- synchronized(_monitor)
- {
- if(_exception != null)
- {
- throw _exception;
- }
- }
- }
-
- /**
- * This method returns true if a request was written to the client-side
- * transport without first being queued. If the request was initially
- * queued, this method returns false (independent of whether the request
- * is still in the queue or has since been written to the client-side transport).
- *
- * @return True if the request was sent without being queued, or false
- * otherwise.
- **/
- @Override
- public final boolean sentSynchronously()
- {
- return _sentSynchronously; // No lock needed, immutable once __send() is called
- }
-
- /**
- * Returns the name of the operation.
- *
- * @return The operation name.
- **/
- @Override
- public final String getOperation()
- {
- return _operation;
- }
-
- public final IceInternal.BasicStream getOs()
- {
- return _os;
- }
-
- public IceInternal.BasicStream
- startReadParams()
- {
- _is.startReadEncaps();
- return _is;
- }
-
- public void
- endReadParams()
- {
- _is.endReadEncaps();
- }
-
- public void
- readEmptyParams()
- {
- _is.skipEmptyEncaps(null);
- }
-
- public byte[]
- readParamEncaps()
- {
- return _is.readEncaps(null);
- }
-
- public final boolean __wait()
- {
- try
- {
- synchronized(_monitor)
- {
- if((_state & StateEndCalled) > 0)
- {
- throw new java.lang.IllegalArgumentException("end_ method called more than once");
- }
-
- _state |= StateEndCalled;
- if(Thread.interrupted())
- {
- throw new InterruptedException();
- }
- while((_state & StateDone) == 0)
- {
- _monitor.wait();
- }
-
- if(_exception != null)
- {
- throw (Ice.Exception)_exception.fillInStackTrace();
- }
-
- return (_state & StateOK) > 0;
- }
- }
- catch(InterruptedException ex)
- {
- // This must be called outside of the monitor as the
- // invocation will potentially want to lock the
- // connection (which in turn may want to lock the outgoing
- // to notify that the message has been sent).
- cancelRequest();
- throw new Ice.OperationInterruptedException();
- }
- }
-
- public final void throwUserException()
- throws UserException
- {
- try
- {
- _is.startReadEncaps();
- _is.throwException(null);
- }
- catch(UserException ex)
- {
- _is.endReadEncaps();
- throw ex;
- }
- }
-
- public void invokeExceptionAsync(final Ice.Exception ex)
- {
- //
- // This is called when it's not safe to call the exception callback synchronously
- // from this thread. Instead the exception callback is called asynchronously from
- // the client thread pool.
- //
- try
- {
- _instance.clientThreadPool().dispatch(new IceInternal.DispatchWorkItem(_cachedConnection)
- {
- @Override
- public void
- run()
- {
- invokeException(ex);
- }
- });
- }
- catch(CommunicatorDestroyedException exc)
- {
- throw exc; // CommunicatorDestroyedException is the only exception that can propagate directly.
- }
- }
-
- public final void invokeException(Ice.Exception ex)
- {
- synchronized(_monitor)
- {
- _state |= StateDone;
- //_os.resize(0, false); // Clear buffer now, instead of waiting for AsyncResult deallocation
- _exception = ex;
- _monitor.notifyAll();
- }
-
- invokeCompleted();
- }
-
- protected final void invokeSentInternal()
- {
- //
- // Note: no need to change the _state here, specializations are responsible for
- // changing the state.
- //
-
- if(_callback != null)
- {
- if(_instance.useApplicationClassLoader())
- {
- Thread.currentThread().setContextClassLoader(_callback.getClass().getClassLoader());
- }
-
- try
- {
- _callback.__sent(this);
- }
- catch(RuntimeException ex)
- {
- warning(ex);
- }
- catch(AssertionError exc)
- {
- error(exc);
- }
- catch(OutOfMemoryError exc)
- {
- error(exc);
- }
- finally
- {
- if(_instance.useApplicationClassLoader())
- {
- Thread.currentThread().setContextClassLoader(null);
- }
- }
- }
-
if(_observer != null)
{
- Ice.ObjectPrx proxy = getProxy();
- if(proxy == null || !proxy.ice_isTwoway())
- {
- _observer.detach();
- }
- }
- }
-
- public void attachRemoteObserver(Ice.ConnectionInfo info, Ice.Endpoint endpt, int requestId, int size)
- {
- if(_observer != null)
- {
- _childObserver = _observer.getRemoteObserver(info, endpt, requestId, size);
+ final int size = _os.size() - IceInternal.Protocol.headerSize - 4;
+ _childObserver = getObserver().getRemoteObserver(info, endpt, requestId, size);
if(_childObserver != null)
{
_childObserver.attach();
@@ -395,13 +51,12 @@ public abstract class OutgoingAsyncBase implements Ice.AsyncResult
}
}
- void attachCollocatedObserver(Ice.ObjectAdapter adapter, int requestId)
+ public final void attachCollocatedObserver(Ice.ObjectAdapter adapter, int requestId)
{
if(_observer != null)
{
- _childObserver = _observer.getCollocatedObserver(adapter,
- requestId,
- _os.size() - IceInternal.Protocol.headerSize - 4);
+ final int size = _os.size() - IceInternal.Protocol.headerSize - 4;
+ _childObserver = getObserver().getCollocatedObserver(adapter, requestId, size);
if(_childObserver != null)
{
_childObserver.attach();
@@ -409,185 +64,49 @@ public abstract class OutgoingAsyncBase implements Ice.AsyncResult
}
}
- abstract void processRetry();
-
- final protected void invokeSentAsync()
- {
- //
- // This is called when it's not safe to call the sent callback synchronously
- // from this thread. Instead the exception callback is called asynchronously from
- // the client thread pool.
- //
- try
- {
- _instance.clientThreadPool().dispatch(new IceInternal.DispatchWorkItem(_cachedConnection)
- {
- @Override
- public void run()
- {
- invokeSentInternal();
- }
- });
- }
- catch(CommunicatorDestroyedException exc)
- {
- }
- }
-
- public static void check(AsyncResult r, ObjectPrx prx, String operation)
- {
- check(r, operation);
- if(r.getProxy() != prx)
- {
- throw new IllegalArgumentException("Proxy for call to end_" + operation +
- " does not match proxy that was used to call corresponding begin_" +
- operation + " method");
- }
- }
-
- public static void check(AsyncResult r, Connection con, String operation)
+ public final IceInternal.BasicStream getOs()
{
- check(r, operation);
- if(r.getConnection() != con)
- {
- throw new IllegalArgumentException("Connection for call to end_" + operation +
- " does not match connection that was used to call corresponding begin_" +
- operation + " method");
- }
+ return _os;
}
- public static void check(AsyncResult r, Communicator com, String operation)
+ protected OutgoingAsyncBase(Ice.Communicator com, Instance instance, String op, CallbackBase del)
{
- check(r, operation);
- if(r.getCommunicator() != com)
- {
- throw new IllegalArgumentException("Communicator for call to end_" + operation +
- " does not match communicator that was used to call corresponding " +
- "begin_" + operation + " method");
- }
+ super(com, instance, op, del);
+ _os = new BasicStream(instance, Protocol.currentProtocolEncoding);
}
- public void cacheMessageBuffers()
+ protected OutgoingAsyncBase(Ice.Communicator com, Instance instance, String op, CallbackBase del, BasicStream os)
{
+ super(com, instance, op, del);
+ _os = os;
}
- public final void invokeCompleted()
+ @Override
+ protected boolean sent(boolean done)
{
- //
- // Note: no need to change the _state here, specializations are responsible for
- // changing the state.
- //
-
- if(_callback != null)
+ if(done)
{
- if(_instance.useApplicationClassLoader())
- {
- Thread.currentThread().setContextClassLoader(_callback.getClass().getClassLoader());
- }
-
- try
- {
- _callback.__completed(this);
- }
- catch(RuntimeException ex)
- {
- warning(ex);
- }
- catch(AssertionError exc)
- {
- error(exc);
- }
- catch(OutOfMemoryError exc)
- {
- error(exc);
- }
- finally
+ if(_childObserver != null)
{
- if(_instance.useApplicationClassLoader())
- {
- Thread.currentThread().setContextClassLoader(null);
- }
+ _childObserver.detach();
+ _childObserver = null;
}
}
-
- if(_observer != null)
- {
- _observer.detach();
- _observer = null;
- }
+ return super.sent(done);
}
- protected void
- timeout()
- {
- IceInternal.RequestHandler handler;
- synchronized(_monitor)
- {
- handler = _timeoutRequestHandler;
- _timeoutRequestHandler = null;
- }
-
- if(handler != null)
- {
- handler.asyncRequestCanceled((IceInternal.OutgoingAsyncMessageCallback)this,
- new Ice.InvocationTimeoutException());
- }
- }
-
- private static void check(AsyncResult r, String operation)
- {
- if(r == null)
- {
- throw new IllegalArgumentException("AsyncResult == null");
- }
- else if(r.getOperation() != operation) // Do NOT use equals() here - we are comparing reference equality
- {
- throw new IllegalArgumentException("Incorrect operation for end_" + operation + " method: " +
- r.getOperation());
- }
- }
-
- private final void warning(RuntimeException ex)
+ @Override
+ protected boolean finished(Ice.Exception ex)
{
- if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0)
+ if(_childObserver != null)
{
- String s = "exception raised by AMI callback:\n" + IceInternal.Ex.toString(ex);
- _instance.initializationData().logger.warning(s);
+ _childObserver.failed(ex.ice_name());
+ _childObserver.detach();
+ _childObserver = null;
}
+ return super.finished(ex);
}
- private final void error(Error error)
- {
- String s = "error raised by AMI callback:\n" + IceInternal.Ex.toString(error);
- _instance.initializationData().logger.error(s);
- }
-
- abstract protected void cancelRequest();
-
- protected Communicator _communicator;
- protected IceInternal.Instance _instance;
- protected String _operation;
- protected Ice.Connection _cachedConnection;
-
- protected java.lang.Object _monitor = new java.lang.Object();
- protected IceInternal.BasicStream _is;
- protected IceInternal.BasicStream _os;
-
- protected IceInternal.RequestHandler _timeoutRequestHandler;
- protected java.util.concurrent.Future<?> _future;
-
- protected static final byte StateOK = 0x1;
- protected static final byte StateDone = 0x2;
- protected static final byte StateSent = 0x4;
- protected static final byte StateEndCalled = 0x8;
- protected static final byte StateCachedBuffers = 0x10;
-
- protected byte _state;
- protected boolean _sentSynchronously;
- protected Ice.Exception _exception;
-
- protected Ice.Instrumentation.InvocationObserver _observer;
+ protected BasicStream _os;
protected Ice.Instrumentation.ChildInvocationObserver _childObserver;
-
- protected IceInternal.CallbackBase _callback;
}
diff --git a/java/src/IceInternal/OutgoingAsyncMessageCallback.java b/java/src/IceInternal/OutgoingAsyncMessageCallback.java
deleted file mode 100644
index 7b1f5972434..00000000000
--- a/java/src/IceInternal/OutgoingAsyncMessageCallback.java
+++ /dev/null
@@ -1,53 +0,0 @@
-// **********************************************************************
-//
-// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
-//
-// This copy of Ice is licensed to you under the terms described in the
-// ICE_LICENSE file included in this distribution.
-//
-// **********************************************************************
-
-package IceInternal;
-
-//
-// This interface is used by the connection to handle OutgoingAsync
-// and BatchOutgoingAsync messages.
-//
-public interface OutgoingAsyncMessageCallback
-{
- //
- // Called by the request handler to send the request over the connection.
- //
- int send(Ice.ConnectionI conection, boolean compress, boolean response)
- throws RetryException;
-
- //
- // Called by the collocated request handler to invoke the request.
- //
- int invokeCollocated(CollocatedRequestHandler handler);
-
- //
- // Called by the connection when the message is confirmed sent. The
- // connection is locked when this is called so this method can't call the
- // sent callback. Instead, this method returns true if there's a sent
- // callback and false otherwise. If true is returned, the connection will
- // call the __invokeSent() method bellow (which in turn should call the sent
- // callback).
- //
- boolean sent();
-
- //
- // Called by the connection to call the user sent callback.
- //
- void invokeSent();
-
- //
- // Called by the connection when the request failed.
- //
- void finished(Ice.Exception ex);
-
- //
- // Helper to dispatch the cancellation exception.
- //
- void dispatchInvocationCancel(Ice.LocalException ex, ThreadPool threadPool, Ice.Connection connection);
-}
diff --git a/java/src/IceInternal/OutgoingConnectionFactory.java b/java/src/IceInternal/OutgoingConnectionFactory.java
index 534888ec89e..116038ad537 100644
--- a/java/src/IceInternal/OutgoingConnectionFactory.java
+++ b/java/src/IceInternal/OutgoingConnectionFactory.java
@@ -265,7 +265,7 @@ public final class OutgoingConnectionFactory
}
public void
- flushAsyncBatchRequests(CommunicatorBatchOutgoingAsync outAsync)
+ flushAsyncBatchRequests(CommunicatorFlushBatch outAsync)
{
java.util.List<Ice.ConnectionI> c = new java.util.LinkedList<Ice.ConnectionI>();
diff --git a/java/src/IceInternal/ProxyBatchOutgoingAsync.java b/java/src/IceInternal/ProxyBatchOutgoingAsync.java
deleted file mode 100644
index 4a575142da7..00000000000
--- a/java/src/IceInternal/ProxyBatchOutgoingAsync.java
+++ /dev/null
@@ -1,97 +0,0 @@
-// **********************************************************************
-//
-// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
-//
-// This copy of Ice is licensed to you under the terms described in the
-// ICE_LICENSE file included in this distribution.
-//
-// **********************************************************************
-
-package IceInternal;
-
-public class ProxyBatchOutgoingAsync extends BatchOutgoingAsync
-{
- public ProxyBatchOutgoingAsync(Ice.ObjectPrxHelperBase prx, String operation, CallbackBase callback)
- {
- super(prx.ice_getCommunicator(), prx.__reference().getInstance(), operation, callback);
- _proxy = prx;
- _observer = ObserverHelper.get(prx, operation);
- }
-
- public void __invoke()
- {
- Protocol.checkSupportedProtocol(_proxy.__reference().getProtocol());
-
- try
- {
- _handler = _proxy.__getRequestHandler();
- int status = _handler.sendAsyncRequest(this);
- if((status & AsyncStatus.Sent) > 0)
- {
- _sentSynchronously = true;
- if((status & AsyncStatus.InvokeSentCallback) > 0)
- {
- invokeSent();
- }
- }
- else
- {
- synchronized(_monitor)
- {
- if((_state & StateDone) == 0)
- {
- int invocationTimeout = _handler.getReference().getInvocationTimeout();
- if(invocationTimeout > 0)
- {
- _future = _instance.timer().schedule(new Runnable()
- {
- @Override
- public void run()
- {
- timeout();
- }
- }, invocationTimeout, java.util.concurrent.TimeUnit.MILLISECONDS);
- _timeoutRequestHandler = _handler;
- }
- }
- }
- }
- }
- catch(RetryException ex)
- {
- //
- // Clear request handler but don't retry or throw. Retrying
- // isn't useful, there were no batch requests associated with
- // the proxy's request handler.
- //
- _proxy.__setRequestHandler(_handler, null);
- }
- catch(Ice.Exception ex)
- {
- if(_observer != null)
- {
- _observer.failed(ex.ice_name());
- }
- _proxy.__setRequestHandler(_handler, null); // Clear request handler
- throw ex; // Throw to notify the user lthat batch requests were potentially lost.
- }
- }
-
- @Override
- public Ice.ObjectPrx getProxy()
- {
- return _proxy;
- }
-
- @Override
- protected void cancelRequest()
- {
- if(_handler != null)
- {
- _handler.asyncRequestCanceled(this, new Ice.OperationInterruptedException());
- }
- }
-
- final private Ice.ObjectPrxHelperBase _proxy;
- private RequestHandler _handler = null;
-}
diff --git a/java/src/IceInternal/ProxyFactory.java b/java/src/IceInternal/ProxyFactory.java
index fb664c89b9b..a5165c37374 100644
--- a/java/src/IceInternal/ProxyFactory.java
+++ b/java/src/IceInternal/ProxyFactory.java
@@ -217,7 +217,7 @@ public final class ProxyFactory
//
// Don't retry invocation timeouts.
//
- if(ex instanceof Ice.InvocationTimeoutException)
+ if(ex instanceof Ice.InvocationTimeoutException || ex instanceof Ice.InvocationCanceledException)
{
throw ex;
}
diff --git a/java/src/IceInternal/ProxyFlushBatch.java b/java/src/IceInternal/ProxyFlushBatch.java
new file mode 100644
index 00000000000..d3708dc67e3
--- /dev/null
+++ b/java/src/IceInternal/ProxyFlushBatch.java
@@ -0,0 +1,71 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class ProxyFlushBatch extends ProxyOutgoingAsyncBase
+{
+ public static ProxyFlushBatch check(Ice.AsyncResult r, Ice.ObjectPrx prx, String operation)
+ {
+ ProxyOutgoingAsyncBase.checkImpl(r, prx, operation);
+ try
+ {
+ return (ProxyFlushBatch)r;
+ }
+ catch(ClassCastException ex)
+ {
+ throw new IllegalArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ }
+
+ public ProxyFlushBatch(Ice.ObjectPrxHelperBase prx, String operation, CallbackBase callback)
+ {
+ super(prx, operation, callback);
+ _observer = ObserverHelper.get(prx, operation);
+ }
+
+ @Override
+ public boolean sent()
+ {
+ return sent(true); // Overriden because the flush is done even if using a two-way proxy.
+ }
+
+ @Override
+ public int send(Ice.ConnectionI connection, boolean compress, boolean response)
+ {
+ _cachedConnection = connection;
+ return connection.flushAsyncBatchRequests(this);
+ }
+
+ @Override
+ public int invokeCollocated(CollocatedRequestHandler handler)
+ {
+ return handler.invokeAsyncBatchRequests(this);
+ }
+
+ public void invoke()
+ {
+ Protocol.checkSupportedProtocol(Protocol.getCompatibleProtocol(_proxy.__reference().getProtocol()));
+ invokeImpl(true); // userThread = true
+ }
+
+ @Override
+ protected void handleRetryException(RetryException exc)
+ {
+ _proxy.__setRequestHandler(_handler, null); // Clear request handler
+ throw exc.get(); // No retries, we want to notify the user of potentially lost batch requests
+ }
+
+ @Override
+ protected int handleException(Ice.Exception exc)
+ {
+ _proxy.__setRequestHandler(_handler, null); // Clear request handler
+ throw exc; // No retries, we want to notify the user of potentially lost batch requests
+ }
+}
diff --git a/java/src/IceInternal/ProxyGetConnection.java b/java/src/IceInternal/ProxyGetConnection.java
new file mode 100644
index 00000000000..9f5388218db
--- /dev/null
+++ b/java/src/IceInternal/ProxyGetConnection.java
@@ -0,0 +1,59 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+public class ProxyGetConnection extends ProxyOutgoingAsyncBase
+{
+ public static ProxyGetConnection check(Ice.AsyncResult r, Ice.ObjectPrx prx, String operation)
+ {
+ ProxyOutgoingAsyncBase.checkImpl(r, prx, operation);
+ try
+ {
+ return (ProxyGetConnection)r;
+ }
+ catch(ClassCastException ex)
+ {
+ throw new IllegalArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ }
+
+ public ProxyGetConnection(Ice.ObjectPrxHelperBase prx, String operation, CallbackBase cb)
+ {
+ super(prx, operation, cb);
+ _observer = ObserverHelper.get(prx, operation);
+ }
+
+ @Override
+ public int send(Ice.ConnectionI connection, boolean compress, boolean response)
+ throws RetryException
+ {
+ _cachedConnection = connection;
+ if(finished(true))
+ {
+ invokeCompletedAsync();
+ }
+ return AsyncStatus.Sent;
+ }
+
+ @Override
+ public int invokeCollocated(CollocatedRequestHandler handler)
+ {
+ if(finished(true))
+ {
+ invokeCompletedAsync();
+ }
+ return AsyncStatus.Sent;
+ }
+
+ public void invoke()
+ {
+ invokeImpl(true); // userThread = true
+ }
+}
diff --git a/java/src/IceInternal/ProxyOutgoingAsyncBase.java b/java/src/IceInternal/ProxyOutgoingAsyncBase.java
new file mode 100644
index 00000000000..eca0de9fcf6
--- /dev/null
+++ b/java/src/IceInternal/ProxyOutgoingAsyncBase.java
@@ -0,0 +1,278 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceInternal;
+
+//
+// Base class for proxy based invocations. This class handles the
+// retry for proxy invocations. It also ensures the child observer is
+// correct notified of failures and make sure the retry task is
+// correctly canceled when the invocation completes.
+//
+public abstract class ProxyOutgoingAsyncBase extends OutgoingAsyncBase
+{
+ public static ProxyOutgoingAsyncBase check(Ice.AsyncResult r, Ice.ObjectPrx prx, String operation)
+ {
+ ProxyOutgoingAsyncBase.checkImpl(r, prx, operation);
+ try
+ {
+ return (ProxyOutgoingAsyncBase)r;
+ }
+ catch(ClassCastException ex)
+ {
+ throw new IllegalArgumentException("Incorrect AsyncResult object for end_" + operation + " method");
+ }
+ }
+
+ @Override
+ public Ice.ObjectPrx getProxy()
+ {
+ return _proxy;
+ }
+
+ @Override
+ public boolean sent()
+ {
+ return sent(!_proxy.ice_isTwoway());
+ }
+
+ @Override
+ public boolean completed(Ice.Exception exc)
+ {
+ if(_childObserver != null)
+ {
+ _childObserver.failed(exc.ice_name());
+ _childObserver.detach();
+ _childObserver = null;
+ }
+
+ //
+ // NOTE: at this point, synchronization isn't needed, no other threads should be
+ // calling on the callback.
+ //
+ try
+ {
+ _instance.retryQueue().add(this, handleException(exc));
+ return false;
+ }
+ catch(Ice.Exception ex)
+ {
+ return finished(ex); // No retries, we're done
+ }
+ }
+
+ public void retry()
+ {
+ invokeImpl(false);
+ }
+
+ public void abort(Ice.Exception ex)
+ {
+ assert(_childObserver == null);
+ if(finished(ex))
+ {
+ invokeCompletedAsync();
+ }
+ else if(ex instanceof Ice.CommunicatorDestroyedException)
+ {
+ //
+ // If it's a communicator destroyed exception, don't swallow
+ // it but instead notify the user thread. Even if no callback
+ // was provided.
+ //
+ throw ex;
+ }
+ }
+
+ protected ProxyOutgoingAsyncBase(Ice.ObjectPrxHelperBase prx, String op, CallbackBase delegate)
+ {
+ super(prx.ice_getCommunicator(), prx.__reference().getInstance(), op, delegate);
+ _proxy = prx;
+ _mode = Ice.OperationMode.Normal;
+ _cnt = 0;
+ _sent = false;
+ }
+
+ protected ProxyOutgoingAsyncBase(Ice.ObjectPrxHelperBase prx, String op, CallbackBase delegate, BasicStream os)
+ {
+ super(prx.ice_getCommunicator(), prx.__reference().getInstance(), op, delegate, os);
+ _proxy = prx;
+ _mode = Ice.OperationMode.Normal;
+ _cnt = 0;
+ _sent = false;
+ }
+
+ protected static Ice.AsyncResult checkImpl(Ice.AsyncResult r, Ice.ObjectPrx p, String operation)
+ {
+ check(r, operation);
+ if(r.getProxy() != p)
+ {
+ throw new IllegalArgumentException("Proxy for call to end_" + operation +
+ " does not match proxy that was used to call corresponding " +
+ "begin_" + operation + " method");
+ }
+ return r;
+ }
+
+ protected void invokeImpl(boolean userThread)
+ {
+ try
+ {
+ if(userThread)
+ {
+ int invocationTimeout = _proxy.__reference().getInvocationTimeout();
+ if(invocationTimeout > 0)
+ {
+ _future = _instance.timer().schedule(
+ new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ cancel(new Ice.InvocationTimeoutException());
+ }
+ }, invocationTimeout, java.util.concurrent.TimeUnit.MILLISECONDS);
+ }
+ }
+ else // If not called from the user thread, it's called from the retry queue
+ {
+ checkCanceled(); // Cancellation exception aren't retriable
+ if(_observer != null)
+ {
+ _observer.retried();
+ }
+ }
+
+ while(true)
+ {
+ try
+ {
+ _sent = false;
+ _handler = _proxy.__getRequestHandler();
+ int status = _handler.sendAsyncRequest(this);
+ if((status & AsyncStatus.Sent) > 0)
+ {
+ if(userThread)
+ {
+ _sentSynchronously = true;
+ if((status & AsyncStatus.InvokeSentCallback) > 0)
+ {
+ invokeSent(); // Call the sent callback from the user thread.
+ }
+ }
+ else
+ {
+ if((status & AsyncStatus.InvokeSentCallback) > 0)
+ {
+ invokeSentAsync(); // Call the sent callback from a client thread pool thread.
+ }
+ }
+ }
+ return; // We're done!
+ }
+ catch(RetryException ex)
+ {
+ handleRetryException(ex);
+ }
+ catch(Ice.Exception ex)
+ {
+ if(_childObserver != null)
+ {
+ _childObserver.failed(ex.ice_name());
+ _childObserver.detach();
+ _childObserver = null;
+ }
+ final int interval = handleException(ex);
+ if(interval > 0)
+ {
+ _instance.retryQueue().add(this, interval);
+ return;
+ }
+ else if(_observer != null)
+ {
+ checkCanceled();
+ _observer.retried();
+ }
+ }
+ }
+ }
+ catch(Ice.Exception ex)
+ {
+ //
+ // If called from the user thread we re-throw, the exception
+ // will be catch by the caller and abort() will be called.
+ //
+ if(userThread)
+ {
+ throw ex;
+ }
+ else if(finished(ex)) // No retries, we're done
+ {
+ invokeCompletedAsync();
+ }
+ }
+ }
+
+ @Override
+ protected boolean sent(boolean done)
+ {
+ _sent = true;
+ if(done)
+ {
+ if(_future != null)
+ {
+ _future.cancel(false);
+ _future = null;
+ }
+ }
+ return super.sent(done);
+ }
+
+ @Override
+ protected boolean finished(Ice.Exception ex)
+ {
+ if(_future != null)
+ {
+ _future.cancel(false);
+ _future = null;
+ }
+ return super.finished(ex);
+ }
+
+ @Override
+ protected boolean finished(boolean ok)
+ {
+ if(_future != null)
+ {
+ _future.cancel(false);
+ _future = null;
+ }
+ return super.finished(ok);
+ }
+
+ protected void handleRetryException(RetryException exc)
+ {
+ _proxy.__setRequestHandler(_handler, null); // Clear request handler and always retry.
+ }
+
+ protected int handleException(Ice.Exception exc)
+ {
+ Ice.Holder<Integer> interval = new Ice.Holder<Integer>();
+ _cnt = _proxy.__handleException(exc, _handler, _mode, _sent, interval, _cnt);
+ return interval.value;
+ }
+
+ final protected Ice.ObjectPrxHelperBase _proxy;
+ protected RequestHandler _handler;
+ protected Ice.OperationMode _mode;
+
+ private java.util.concurrent.Future<?> _future;
+ private int _cnt;
+ private boolean _sent;
+}
diff --git a/java/src/IceInternal/QueueRequestHandler.java b/java/src/IceInternal/QueueRequestHandler.java
index 5f40ea37403..fdb7a672e2a 100644
--- a/java/src/IceInternal/QueueRequestHandler.java
+++ b/java/src/IceInternal/QueueRequestHandler.java
@@ -124,7 +124,7 @@ public class QueueRequestHandler implements RequestHandler
@Override
public int
- sendAsyncRequest(final OutgoingAsyncMessageCallback out) throws RetryException
+ sendAsyncRequest(final OutgoingAsyncBase out) throws RetryException
{
try
{
@@ -148,15 +148,16 @@ public class QueueRequestHandler implements RequestHandler
}
@Override
- public boolean
- asyncRequestCanceled(final OutgoingAsyncMessageCallback outAsync, final Ice.LocalException ex)
+ public void
+ asyncRequestCanceled(final OutgoingAsyncBase outAsync, final Ice.LocalException ex)
{
- return performCallable(new Callable<Boolean>()
+ performCallable(new Callable<Void>()
{
@Override
- public Boolean call()
+ public Void call()
{
- return _delegate.asyncRequestCanceled(outAsync, ex);
+ _delegate.asyncRequestCanceled(outAsync, ex);
+ return null;
}
});
}
diff --git a/java/src/IceInternal/RequestHandler.java b/java/src/IceInternal/RequestHandler.java
index 1e0e4a7909a..f87b215919f 100644
--- a/java/src/IceInternal/RequestHandler.java
+++ b/java/src/IceInternal/RequestHandler.java
@@ -9,7 +9,7 @@
package IceInternal;
-public interface RequestHandler
+public interface RequestHandler extends CancellationHandler
{
RequestHandler connect();
RequestHandler update(RequestHandler previousHandler, RequestHandler newHandler);
@@ -19,11 +19,9 @@ public interface RequestHandler
void finishBatchRequest(BasicStream out);
void abortBatchRequest();
- int sendAsyncRequest(OutgoingAsyncMessageCallback out)
+ int sendAsyncRequest(OutgoingAsyncBase out)
throws RetryException;
- boolean asyncRequestCanceled(OutgoingAsyncMessageCallback outAsync, Ice.LocalException ex);
-
Reference getReference();
Ice.ConnectionI getConnection();
diff --git a/java/src/IceInternal/RetryQueue.java b/java/src/IceInternal/RetryQueue.java
index 2c322d1cb72..82831529545 100644
--- a/java/src/IceInternal/RetryQueue.java
+++ b/java/src/IceInternal/RetryQueue.java
@@ -16,8 +16,7 @@ public class RetryQueue
_instance = instance;
}
- synchronized public void
- add(OutgoingAsyncBase outAsync, int interval)
+ synchronized public void add(ProxyOutgoingAsyncBase outAsync, int interval)
{
if(_instance == null)
{
@@ -26,10 +25,10 @@ public class RetryQueue
RetryTask task = new RetryTask(this, outAsync);
task.setFuture(_instance.timer().schedule(task, interval, java.util.concurrent.TimeUnit.MILLISECONDS));
_requests.add(task);
+ outAsync.cancelable(task);
}
- synchronized public void
- destroy()
+ synchronized public void destroy()
{
java.util.HashSet<RetryTask> keep = new java.util.HashSet<RetryTask>();
for(RetryTask task : _requests)
@@ -65,14 +64,14 @@ public class RetryQueue
}
}
- synchronized void
- remove(RetryTask task)
+ synchronized boolean remove(RetryTask task)
{
- _requests.remove(task);
+ boolean removed = _requests.remove(task);
if(_instance == null && _requests.isEmpty())
{
notify();
}
+ return removed;
}
private Instance _instance;
diff --git a/java/src/IceInternal/RetryTask.java b/java/src/IceInternal/RetryTask.java
index 64a54bd45b5..974dc998a79 100644
--- a/java/src/IceInternal/RetryTask.java
+++ b/java/src/IceInternal/RetryTask.java
@@ -9,26 +9,18 @@
package IceInternal;
-class RetryTask implements Runnable
+class RetryTask implements Runnable, CancellationHandler
{
- RetryTask(RetryQueue queue, OutgoingAsyncBase outAsync)
+ RetryTask(RetryQueue queue, ProxyOutgoingAsyncBase outAsync)
{
_queue = queue;
_outAsync = outAsync;
}
@Override
- public void
- run()
+ public void run()
{
- try
- {
- _outAsync.processRetry();
- }
- catch(Ice.LocalException ex)
- {
- _outAsync.invokeExceptionAsync(ex);
- }
+ _outAsync.retry();
//
// NOTE: this must be called last, destroy() blocks until all task
@@ -39,12 +31,32 @@ class RetryTask implements Runnable
_queue.remove(this);
}
- public boolean
- destroy()
+ @Override
+ public void asyncRequestCanceled(OutgoingAsyncBase outAsync, Ice.LocalException ex)
+ {
+ if(_queue.remove(this) && _future.cancel(false))
+ {
+ //
+ // We just retry the outgoing async now rather than marking it
+ // as finished. The retry will check for the cancellation
+ // exception and terminate appropriately the request.
+ //
+ _outAsync.retry();
+ }
+ }
+
+ public boolean destroy()
{
if(_future.cancel(false))
{
- _outAsync.invokeExceptionAsync(new Ice.CommunicatorDestroyedException());
+ try
+ {
+ _outAsync.abort(new Ice.CommunicatorDestroyedException());
+ }
+ catch(Ice.CommunicatorDestroyedException ex)
+ {
+ // Abort can throw if there's no callback, just ignore in this case
+ }
return true;
}
return false;
@@ -56,6 +68,6 @@ class RetryTask implements Runnable
}
private final RetryQueue _queue;
- private final OutgoingAsyncBase _outAsync;
+ private final ProxyOutgoingAsyncBase _outAsync;
private java.util.concurrent.Future<?> _future;
}
diff --git a/java/test/Ice/ami/AMI.java b/java/test/Ice/ami/AMI.java
index aa3f9c9b328..ab1591c3c10 100644
--- a/java/test/Ice/ami/AMI.java
+++ b/java/test/Ice/ami/AMI.java
@@ -1722,6 +1722,26 @@ public class AMI
test(r.isSent());
test(r.isCompleted());
test(p.waitForBatch(2));
+
+ final FlushCallback cb2 = new FlushCallback();
+ Ice.AsyncResult r2 = b1.begin_ice_flushBatchRequests(
+ new Ice.Callback()
+ {
+ @Override
+ public void completed(Ice.AsyncResult result)
+ {
+ cb2.completedAsync(result);
+ }
+
+ @Override
+ public void sent(Ice.AsyncResult result)
+ {
+ cb2.sentAsync(result);
+ }
+ });
+ cb2.check();
+ test(r2.isSent());
+ test(r2.isCompleted());
}
if(p.ice_getConnection() != null)
@@ -2400,6 +2420,82 @@ public class AMI
communicator.end_flushBatchRequests(r);
}
}
+
+ if(p.ice_getConnection() != null)
+ {
+ Ice.AsyncResult r1 = null;
+ Ice.AsyncResult r2 = null;
+
+ testController.holdAdapter();
+ try
+ {
+ Ice.AsyncResult r;
+ byte[] seq = new byte[10024];
+ new java.util.Random().nextBytes(seq); // Make sure the request doesn't compress too well.
+ while((r = p.begin_opWithPayload(seq)).sentSynchronously());
+
+ test(!r.isSent());
+
+ r1 = p.begin_ice_ping();
+ r2 = p.begin_ice_id();
+ r1.cancel();
+ r2.cancel();
+ try
+ {
+ p.end_ice_ping(r1);
+ test(false);
+ }
+ catch(Ice.InvocationCanceledException ex)
+ {
+ }
+ try
+ {
+ p.end_ice_id(r2);
+ test(false);
+ }
+ catch(Ice.InvocationCanceledException ex)
+ {
+ }
+ }
+ finally
+ {
+ testController.resumeAdapter();
+ p.ice_ping();
+ test(!r1.isSent() && r1.isCompleted());
+ test(!r2.isSent() && r2.isCompleted());
+ }
+
+ testController.holdAdapter();
+ try
+ {
+ r1 = p.begin_op();
+ r2 = p.begin_ice_id();
+ r1.waitForSent();
+ r2.waitForSent();
+ r1.cancel();
+ r2.cancel();
+ try
+ {
+ p.end_op(r1);
+ test(false);
+ }
+ catch(Ice.InvocationCanceledException ex)
+ {
+ }
+ try
+ {
+ p.end_ice_id(r2);
+ test(false);
+ }
+ catch(Ice.InvocationCanceledException ex)
+ {
+ }
+ }
+ finally
+ {
+ testController.resumeAdapter();
+ }
+ }
}
out.println("ok");
diff --git a/java/test/Ice/ami/lambda/AMI.java b/java/test/Ice/ami/lambda/AMI.java
index 0e013b97435..65bd185a849 100644
--- a/java/test/Ice/ami/lambda/AMI.java
+++ b/java/test/Ice/ami/lambda/AMI.java
@@ -881,6 +881,15 @@ public class AMI
test(r.isSent());
test(r.isCompleted());
test(p.waitForBatch(2));
+
+ final FlushCallback cb2 = new FlushCallback();
+ Ice.AsyncResult r2 = b1.ice_getConnection().begin_flushBatchRequests(
+ null,
+ (Ice.Exception ex) -> cb2.exception(ex),
+ (boolean sentSynchronously) -> cb2.sent(sentSynchronously));
+ cb2.check();
+ test(r2.isSent());
+ test(r2.isCompleted());
}
{
diff --git a/java/test/Ice/retry/AllTests.java b/java/test/Ice/retry/AllTests.java
index 42f40727eef..cdcdc586961 100644
--- a/java/test/Ice/retry/AllTests.java
+++ b/java/test/Ice/retry/AllTests.java
@@ -139,7 +139,7 @@ public class AllTests
retry1.op(false);
out.println("ok");
- int invocationCount = 3;
+ Instrumentation.testInvocationCount(3);
out.print("calling operation to kill connection with second proxy... ");
out.flush();
@@ -155,7 +155,7 @@ public class AllTests
catch(Ice.ConnectionLostException ex)
{
}
- Instrumentation.testInvocationCount(invocationCount + 1);
+ Instrumentation.testInvocationCount(1);
Instrumentation.testFailureCount(1);
Instrumentation.testRetryCount(0);
out.println("ok");
@@ -163,8 +163,8 @@ public class AllTests
out.print("calling regular operation with first proxy again... ");
out.flush();
retry1.op(false);
- Instrumentation.testInvocationCount(invocationCount + 2);
- Instrumentation.testFailureCount(1);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(0);
Instrumentation.testRetryCount(0);
out.println("ok");
@@ -174,66 +174,67 @@ public class AllTests
out.print("calling regular AMI operation with first proxy... ");
retry1.begin_op(false, cb1);
cb1.check();
- Instrumentation.testInvocationCount(invocationCount + 3);
- Instrumentation.testFailureCount(1);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(0);
Instrumentation.testRetryCount(0);
out.println("ok");
out.print("calling AMI operation to kill connection with second proxy... ");
retry2.begin_op(true, cb2);
cb2.check();
- Instrumentation.testInvocationCount(invocationCount + 4);
- Instrumentation.testFailureCount(2);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(1);
Instrumentation.testRetryCount(0);
out.println("ok");
out.print("calling regular AMI operation with first proxy again... ");
retry1.begin_op(false, cb1);
cb1.check();
- Instrumentation.testInvocationCount(invocationCount + 5);
- Instrumentation.testFailureCount(2);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(0);
Instrumentation.testRetryCount(0);
out.println("ok");
out.print("testing idempotent operation... ");
- test(retry1.opIdempotent(0) == 4);
- Instrumentation.testInvocationCount(invocationCount + 6);
- Instrumentation.testFailureCount(2);
+ test(retry1.opIdempotent(4) == 4);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(0);
+ Instrumentation.testRetryCount(4);
+ test(retry1.end_opIdempotent(retry1.begin_opIdempotent(4)) == 4);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(0);
Instrumentation.testRetryCount(4);
- test(retry1.end_opIdempotent(retry1.begin_opIdempotent(4)) == 8);
- Instrumentation.testInvocationCount(invocationCount + 7);
- Instrumentation.testFailureCount(2);
- Instrumentation.testRetryCount(8);
out.println("ok");
out.print("testing non-idempotent operation... ");
try
{
- retry1.opNotIdempotent(8);
+ retry1.opNotIdempotent();
test(false);
}
catch(Ice.LocalException ex)
{
}
- Instrumentation.testInvocationCount(invocationCount + 8);
- Instrumentation.testFailureCount(3);
- Instrumentation.testRetryCount(8);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(1);
+ Instrumentation.testRetryCount(0);
try
{
- retry1.end_opNotIdempotent(retry1.begin_opNotIdempotent(9));
+ retry1.end_opNotIdempotent(retry1.begin_opNotIdempotent());
test(false);
}
catch(Ice.LocalException ex)
{
}
- Instrumentation.testInvocationCount(invocationCount + 9);
- Instrumentation.testFailureCount(4);
- Instrumentation.testRetryCount(8);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(1);
+ Instrumentation.testRetryCount(0);
out.println("ok");
if(retry1.ice_getConnection() == null)
{
- invocationCount = invocationCount + 10;
+ Instrumentation.testInvocationCount(1);
+
out.print("testing system exception... ");
try
{
@@ -243,9 +244,9 @@ public class AllTests
catch(SystemFailure ex)
{
}
- Instrumentation.testInvocationCount(invocationCount + 1);
- Instrumentation.testFailureCount(5);
- Instrumentation.testRetryCount(8);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(1);
+ Instrumentation.testRetryCount(0);
try
{
retry1.end_opSystemException(retry1.begin_opSystemException());
@@ -254,12 +255,41 @@ public class AllTests
catch(SystemFailure ex)
{
}
- Instrumentation.testInvocationCount(invocationCount + 2);
- Instrumentation.testFailureCount(6);
- Instrumentation.testRetryCount(8);
+ Instrumentation.testInvocationCount(1);
+ Instrumentation.testFailureCount(1);
+ Instrumentation.testRetryCount(0);
out.println("ok");
}
+ out.print("testing invocation timeout and retries... ");
+ out.flush();
+ try
+ {
+ // No more than 2 retries before timeout kicks-in
+ ((RetryPrx)retry1.ice_invocationTimeout(50)).opIdempotent(4);
+ test(false);
+ }
+ catch(Ice.InvocationTimeoutException ex)
+ {
+ Instrumentation.testRetryCount(2);
+ retry1.opIdempotent(-1); // Reset the counter
+ Instrumentation.testRetryCount(-1);
+ }
+ try
+ {
+ // No more than 2 retries before timeout kicks-in
+ RetryPrx prx = (RetryPrx)retry1.ice_invocationTimeout(50);
+ prx.end_opIdempotent(prx.begin_opIdempotent(4));
+ test(false);
+ }
+ catch(Ice.InvocationTimeoutException ex)
+ {
+ Instrumentation.testRetryCount(2);
+ retry1.opIdempotent(-1); // Reset the counter
+ Instrumentation.testRetryCount(-1);
+ }
+ out.println("ok");
+
return retry1;
}
}
diff --git a/java/test/Ice/retry/Client.java b/java/test/Ice/retry/Client.java
index aaec9406b13..190fda805dd 100644
--- a/java/test/Ice/retry/Client.java
+++ b/java/test/Ice/retry/Client.java
@@ -31,7 +31,7 @@ public class Client extends test.Util.Application
initData.properties.setProperty("Ice.Package.Test", "test.Ice.retry");
- initData.properties.setProperty("Ice.RetryIntervals", "0 10 20 30");
+ initData.properties.setProperty("Ice.RetryIntervals", "0 1 100 1");
//
// We don't want connection warnings because of the timeout
diff --git a/java/test/Ice/retry/Collocated.java b/java/test/Ice/retry/Collocated.java
index 63868d1d64a..a193c18eaf4 100644
--- a/java/test/Ice/retry/Collocated.java
+++ b/java/test/Ice/retry/Collocated.java
@@ -35,7 +35,7 @@ public class Collocated extends test.Util.Application
initData.properties.setProperty("Ice.Package.Test", "test.Ice.retry");
- initData.properties.setProperty("Ice.RetryIntervals", "0 10 20 30");
+ initData.properties.setProperty("Ice.RetryIntervals", "0 1 100 1");
//
// We don't want connection warnings because of the timeout
diff --git a/java/test/Ice/retry/Instrumentation.java b/java/test/Ice/retry/Instrumentation.java
index 4c825ba7231..609a8225ef2 100644
--- a/java/test/Ice/retry/Instrumentation.java
+++ b/java/test/Ice/retry/Instrumentation.java
@@ -149,8 +149,14 @@ public class Instrumentation
static private void
testEqual(Ice.IntHolder value, int expected)
{
+ if(expected < 0)
+ {
+ value.value = 0;
+ return;
+ }
+
int retry = 0;
- while(retry < 100)
+ while(++retry < 100)
{
synchronized(Instrumentation.class)
{
@@ -172,6 +178,7 @@ public class Instrumentation
System.err.println("value = " + value.value + ", expected = " + expected);
test(false);
}
+ value.value = 0;
}
static public void
diff --git a/java/test/Ice/retry/RetryI.java b/java/test/Ice/retry/RetryI.java
index 31a0b104f55..f2afcc881dd 100644
--- a/java/test/Ice/retry/RetryI.java
+++ b/java/test/Ice/retry/RetryI.java
@@ -36,9 +36,15 @@ public final class RetryI extends _RetryDisp
@Override
public int
- opIdempotent(int counter, Ice.Current current)
+ opIdempotent(int nRetry, Ice.Current current)
{
- if(counter + nRetry > _counter)
+ if(nRetry < 0)
+ {
+ _counter = 0;
+ return 0;
+ }
+
+ if(nRetry > _counter)
{
++_counter;
if(current.con != null)
@@ -49,20 +55,18 @@ public final class RetryI extends _RetryDisp
{
throw new Ice.ConnectionLostException();
}
+ return 0;
}
- return _counter;
+
+ int counter = _counter;
+ _counter = 0;
+ return counter;
}
@Override
public void
- opNotIdempotent(int counter, Ice.Current current)
+ opNotIdempotent(Ice.Current current)
{
- if(_counter != counter)
- {
- return;
- }
-
- ++_counter;
if(current.con != null)
{
current.con.close(true);
@@ -88,5 +92,4 @@ public final class RetryI extends _RetryDisp
}
private int _counter;
- static final int nRetry = 4;
}
diff --git a/java/test/Ice/retry/Test.ice b/java/test/Ice/retry/Test.ice
index aeffa8e72fc..0e1be095f41 100644
--- a/java/test/Ice/retry/Test.ice
+++ b/java/test/Ice/retry/Test.ice
@@ -18,10 +18,10 @@ interface Retry
void op(bool kill);
idempotent int opIdempotent(int c);
- void opNotIdempotent(int c);
+ void opNotIdempotent();
void opSystemException();
- void shutdown();
+ idempotent void shutdown();
};
};
diff --git a/js/test/Ice/retry/Test.ice b/js/test/Ice/retry/Test.ice
index 61297d94557..bd73167b511 100644
--- a/js/test/Ice/retry/Test.ice
+++ b/js/test/Ice/retry/Test.ice
@@ -20,7 +20,7 @@ interface Retry
void opNotIdempotent(int c);
void opSystemException();
- void shutdown();
+ idempotent void shutdown();
};
};
diff --git a/py/modules/IcePy/Operation.cpp b/py/modules/IcePy/Operation.cpp
index ac5221029fd..740a8ff8902 100644
--- a/py/modules/IcePy/Operation.cpp
+++ b/py/modules/IcePy/Operation.cpp
@@ -24,7 +24,7 @@
#include <Ice/LocalException.h>
#include <Ice/Logger.h>
#include <Ice/ObjectAdapter.h>
-#include <Ice/OutgoingAsync.h>
+#include <Ice/AsyncResult.h>
#include <Ice/Properties.h>
#include <Ice/Proxy.h>
#include <Slice/PythonUtil.h>
@@ -814,6 +814,25 @@ asyncResultGetCommunicator(AsyncResultObject* self)
extern "C"
#endif
static PyObject*
+asyncResultCancel(AsyncResultObject* self)
+{
+ try
+ {
+ (*self->result)->cancel();
+ }
+ catch(...)
+ {
+ assert(false);
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#ifdef WIN32
+extern "C"
+#endif
+static PyObject*
asyncResultGetConnection(AsyncResultObject* self)
{
if(self->connection)
@@ -1255,6 +1274,8 @@ static PyMethodDef AMDCallbackMethods[] =
static PyMethodDef AsyncResultMethods[] =
{
+ { STRCAST("cancel"), reinterpret_cast<PyCFunction>(asyncResultCancel), METH_NOARGS,
+ PyDoc_STR(STRCAST("cancels the invocation")) },
{ STRCAST("getCommunicator"), reinterpret_cast<PyCFunction>(asyncResultGetCommunicator), METH_NOARGS,
PyDoc_STR(STRCAST("returns the communicator for the invocation")) },
{ STRCAST("getConnection"), reinterpret_cast<PyCFunction>(asyncResultGetConnection), METH_NOARGS,
diff --git a/py/modules/IcePy/Operation.h b/py/modules/IcePy/Operation.h
index e9691c63f8f..6dc478eebb4 100644
--- a/py/modules/IcePy/Operation.h
+++ b/py/modules/IcePy/Operation.h
@@ -13,7 +13,7 @@
#include <Config.h>
#include <Ice/Current.h>
#include <Ice/Object.h>
-#include <Ice/OutgoingAsyncF.h>
+#include <Ice/AsyncResultF.h>
#include <Ice/CommunicatorF.h>
namespace IcePy
diff --git a/py/modules/IcePy/Types.h b/py/modules/IcePy/Types.h
index 2acd5f54320..7a96cf1fafd 100644
--- a/py/modules/IcePy/Types.h
+++ b/py/modules/IcePy/Types.h
@@ -15,6 +15,8 @@
#include <Ice/Stream.h>
#include <IceUtil/OutputUtil.h>
+#include <set>
+
namespace IcePy
{
diff --git a/py/test/Ice/ami/AllTests.py b/py/test/Ice/ami/AllTests.py
index ed5e6603f6a..5ddefdd8c4a 100644
--- a/py/test/Ice/ami/AllTests.py
+++ b/py/test/Ice/ami/AllTests.py
@@ -977,6 +977,66 @@ def allTests(communicator, collocated):
test(r.getCommunicator() == communicator)
test(r.getProxy() == None) # Expected
communicator.end_flushBatchRequests(r)
+
+ if(p.ice_getConnection()):
+ r1 = None;
+ r2 = None;
+
+ if sys.version_info[0] == 2:
+ b = [chr(random.randint(0, 255)) for x in range(0, 1024)] # Make sure the request doesn't compress too well.
+ seq = ''.join(b)
+ else:
+ b = [random.randint(0, 255) for x in range(0, 1024)] # Make sure the request doesn't compress too well.
+ seq = bytes(b)
+
+ testController.holdAdapter()
+ while(True):
+ r = p.begin_opWithPayload(seq)
+ if not r.sentSynchronously():
+ break
+
+ test(not r.isSent())
+
+ r1 = p.begin_ice_ping()
+ r2 = p.begin_ice_id()
+ r1.cancel()
+ r2.cancel()
+ try:
+ p.end_ice_ping(r1)
+ test(false)
+ except(Ice.InvocationCanceledException):
+ pass
+
+ try:
+ p.end_ice_id(r2)
+ test(false)
+ except(Ice.InvocationCanceledException):
+ pass
+
+ testController.resumeAdapter()
+ p.ice_ping()
+ test(not r1.isSent() and r1.isCompleted())
+ test(not r2.isSent() and r2.isCompleted())
+
+ testController.holdAdapter()
+
+ r1 = p.begin_op()
+ r2 = p.begin_ice_id()
+ r1.waitForSent()
+ r2.waitForSent()
+ r1.cancel()
+ r2.cancel()
+ try:
+ p.end_op(r1)
+ test(false)
+ except:
+ pass
+ try:
+ p.end_ice_id(r2)
+ test(false)
+ except:
+ pass
+ testController.resumeAdapter()
print("ok")
diff --git a/slice/Ice/LocalException.ice b/slice/Ice/LocalException.ice
index 249a92cc0c2..6665d71d6ad 100644
--- a/slice/Ice/LocalException.ice
+++ b/slice/Ice/LocalException.ice
@@ -641,6 +641,18 @@ local exception InvocationTimeoutException extends TimeoutException
/**
*
+ * This exception indicates that an asynchronous invocation failed
+ * because it was canceled explicitly by the user using the
+ * <tt>Ice::AsyncResult::cancel</tt> method.
+ *
+ **/
+["cpp:ice_print"]
+local exception InvocationCanceledException
+{
+};
+
+/**
+ *
* A generic exception base for all kinds of protocol error
* conditions.
*