diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | cpp/include/Ice/OutgoingAsync.h | 2 | ||||
-rw-r--r-- | cpp/src/Ice/OutgoingAsync.cpp | 10 | ||||
-rw-r--r-- | cpp/test/Ice/ami/AllTests.cpp | 13 | ||||
-rw-r--r-- | cs/src/Ice/OutgoingAsync.cs | 11 | ||||
-rw-r--r-- | java/src/Ice/AsyncResult.java | 14 | ||||
-rw-r--r-- | java/test/Ice/ami/AllTests.java | 12 | ||||
-rw-r--r-- | py/modules/IcePy/Operation.cpp | 27 | ||||
-rw-r--r-- | py/modules/IcePy/Proxy.cpp | 3 | ||||
-rw-r--r-- | py/test/Ice/ami/AllTests.py | 11 |
10 files changed, 105 insertions, 2 deletions
@@ -27,6 +27,10 @@ Changes since version 3.4.1 General Changes =============== +- Added throwLocalException method to the Ice AsyncResult class. If + the request fails with a local exception, this method throws the + local exception. + - Fixed a bug that caused a crash if a timeout occurs while sending an AMI request and if automatic retry is enabled (the default). diff --git a/cpp/include/Ice/OutgoingAsync.h b/cpp/include/Ice/OutgoingAsync.h index 5f65f54a58e..ab062cd7bc2 100644 --- a/cpp/include/Ice/OutgoingAsync.h +++ b/cpp/include/Ice/OutgoingAsync.h @@ -65,6 +65,8 @@ public: bool isSent() const; void waitForSent(); + void throwLocalException() const; + bool sentSynchronously() const { return _sentSynchronously; // No lock needed, immutable once __send() is called diff --git a/cpp/src/Ice/OutgoingAsync.cpp b/cpp/src/Ice/OutgoingAsync.cpp index 4698877694b..a598b5b1c31 100644 --- a/cpp/src/Ice/OutgoingAsync.cpp +++ b/cpp/src/Ice/OutgoingAsync.cpp @@ -168,6 +168,16 @@ Ice::AsyncResult::waitForSent() } } +void +Ice::AsyncResult::throwLocalException() const +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor); + if(_exception.get()) + { + _exception.get()->ice_throw(); + } +} + bool Ice::AsyncResult::__wait() { diff --git a/cpp/test/Ice/ami/AllTests.cpp b/cpp/test/Ice/ami/AllTests.cpp index d5c15332dd3..2b39222dc9a 100644 --- a/cpp/test/Ice/ami/AllTests.cpp +++ b/cpp/test/Ice/ami/AllTests.cpp @@ -1975,6 +1975,19 @@ allTests(const Ice::CommunicatorPtr& communicator) cout << "testing AsyncResult operations... " << flush; { + Test::TestIntfPrx indirect = Test::TestIntfPrx::uncheckedCast(p->ice_adapterId("dummy")); + Ice::AsyncResultPtr r; + r = indirect->begin_op(); + try + { + r->waitForCompleted(); + r->throwLocalException(); + test(false); + } + catch(const Ice::NoEndpointException&) + { + } + testController->holdAdapter(); Ice::AsyncResultPtr r1; Ice::AsyncResultPtr r2; diff --git a/cs/src/Ice/OutgoingAsync.cs b/cs/src/Ice/OutgoingAsync.cs index 4cbd4e17e12..bc78961ac4f 100644 --- a/cs/src/Ice/OutgoingAsync.cs +++ b/cs/src/Ice/OutgoingAsync.cs @@ -173,6 +173,17 @@ namespace IceInternal } } + public void throwLocalException() + { + lock(monitor_) + { + if(exception_ != null) + { + throw exception_; + } + } + } + public bool sentSynchronously() { return sentSynchronously_; // No lock needed, immutable once send__() is called diff --git a/java/src/Ice/AsyncResult.java b/java/src/Ice/AsyncResult.java index 2bf8cddd24a..0ccf2f61aea 100644 --- a/java/src/Ice/AsyncResult.java +++ b/java/src/Ice/AsyncResult.java @@ -131,6 +131,20 @@ public class AsyncResult } /** + * If the invocation failed with a local exception, throws the local exception. + **/ + public final void throwLocalException() + { + 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 diff --git a/java/test/Ice/ami/AllTests.java b/java/test/Ice/ami/AllTests.java index a34331cbc25..2c1b21e98e0 100644 --- a/java/test/Ice/ami/AllTests.java +++ b/java/test/Ice/ami/AllTests.java @@ -2086,6 +2086,18 @@ public class AllTests out.print("testing AsyncResult operations... "); out.flush(); { + TestIntfPrx indirect = TestIntfPrxHelper.uncheckedCast(p.ice_adapterId("dummy")); + Ice.AsyncResult r = indirect.begin_op(); + try + { + r.waitForCompleted(); + r.throwLocalException(); + test(false); + } + catch(Ice.NoEndpointException ex) + { + } + testController.holdAdapter(); Ice.AsyncResult r1; Ice.AsyncResult r2; diff --git a/py/modules/IcePy/Operation.cpp b/py/modules/IcePy/Operation.cpp index 8c7b4bf33c9..71a081e6e7c 100644 --- a/py/modules/IcePy/Operation.cpp +++ b/py/modules/IcePy/Operation.cpp @@ -887,6 +887,31 @@ asyncResultWaitForSent(AsyncResultObject* self) extern "C" #endif static PyObject* +asyncResultThrowLocalException(AsyncResultObject* self) +{ + try + { + assert(self->result); + (*self->result)->throwLocalException(); + } + catch(const Ice::LocalException& ex) + { + setPythonException(ex); + return 0; + } + catch(...) + { + assert(false); + } + + Py_INCREF(Py_None); + return Py_None; +} + +#ifdef WIN32 +extern "C" +#endif +static PyObject* asyncResultSentSynchronously(AsyncResultObject* self) { bool b = false; @@ -1121,6 +1146,8 @@ static PyMethodDef AsyncResultMethods[] = PyDoc_STR(STRCAST("returns true if the request is sent")) }, { STRCAST("waitForSent"), reinterpret_cast<PyCFunction>(asyncResultWaitForSent), METH_NOARGS, PyDoc_STR(STRCAST("blocks until the request is sent")) }, + { STRCAST("throwLocalException"), reinterpret_cast<PyCFunction>(asyncResultThrowLocalException), METH_NOARGS, + PyDoc_STR(STRCAST("throw location exception if the request failed with a local exception")) }, { STRCAST("sentSynchronously"), reinterpret_cast<PyCFunction>(asyncResultSentSynchronously), METH_NOARGS, PyDoc_STR(STRCAST("returns true if the request was sent synchronously")) }, { STRCAST("getOperation"), reinterpret_cast<PyCFunction>(asyncResultGetOperation), METH_NOARGS, diff --git a/py/modules/IcePy/Proxy.cpp b/py/modules/IcePy/Proxy.cpp index 35c9724e882..c0cdca329ba 100644 --- a/py/modules/IcePy/Proxy.cpp +++ b/py/modules/IcePy/Proxy.cpp @@ -1556,12 +1556,11 @@ extern "C" static PyObject* proxyIceFlushBatchRequests(ProxyObject* self) { - AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. - assert(self->proxy); try { + AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations. (*self->proxy)->ice_flushBatchRequests(); } catch(const Ice::Exception& ex) diff --git a/py/test/Ice/ami/AllTests.py b/py/test/Ice/ami/AllTests.py index 270a4202958..607bc16ba9f 100644 --- a/py/test/Ice/ami/AllTests.py +++ b/py/test/Ice/ami/AllTests.py @@ -428,6 +428,7 @@ def allTests(communicator): r = indirect.begin_op() try: indirect.end_op(r) + test(False) except Ice.NoEndpointException: pass @@ -827,6 +828,16 @@ def allTests(communicator): print "ok" print "testing AsyncResult operations...", + + indirect = Test.TestIntfPrx.uncheckedCast(p.ice_adapterId("dummy")) + r = indirect.begin_op() + try: + r.waitForCompleted() + r.throwLocalException() + test(False) + except Ice.NoEndpointException: + pass + testController.holdAdapter() r1 = None r2 = None |