diff options
author | Dwayne Boone <dwayne@zeroc.com> | 2006-03-14 12:47:12 +0000 |
---|---|---|
committer | Dwayne Boone <dwayne@zeroc.com> | 2006-03-14 12:47:12 +0000 |
commit | 4ec329c60555de5562c72df0e2fc583d591bf84d (patch) | |
tree | 86eb4af9aac33fc6277bed19d8936c4ffdbcd2d5 | |
parent | Fixed http://www.zeroc.com/vbulletin/showthread.php?p=9533#post9533 (diff) | |
download | ice-4ec329c60555de5562c72df0e2fc583d591bf84d.tar.bz2 ice-4ec329c60555de5562c72df0e2fc583d591bf84d.tar.xz ice-4ec329c60555de5562c72df0e2fc583d591bf84d.zip |
Ported fix for bug 574.
31 files changed, 1014 insertions, 156 deletions
diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index 753070d6296..87d9abb29ed 100755 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -3349,15 +3349,15 @@ Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p) _out << nl << "return;"; } _out << eb; - _out << nl << "catch(IceInternal.NonRepeatable ex__)"; + _out << nl << "catch(IceInternal.LocalExceptionWrapper ex__)"; _out << sb; if(op->mode() == Operation::Idempotent || op->mode() == Operation::Nonmutating) { - _out << nl << "cnt__ = handleException__(ex__.get(), cnt__);"; + _out << nl << "cnt__ = handleExceptionWrapperRelaxed__(ex__, cnt__);"; } else { - _out << nl << "rethrowException__(ex__.get());"; + _out << nl << "handleExceptionWrapper__(ex__);"; } _out << eb; _out << nl << "catch(Ice.LocalException ex__)"; @@ -4020,7 +4020,7 @@ Slice::Gen::DelegateMVisitor::visitClassDefStart(const ClassDefPtr& p) _out << eb; _out << nl << "catch(Ice.LocalException ex__)"; _out << sb; - _out << nl << "throw new IceInternal.NonRepeatable(ex__);"; + _out << nl << "throw new IceInternal.LocalExceptionWrapper(ex__, false);"; _out << eb; _out << eb; _out << nl << "finally"; @@ -4125,7 +4125,7 @@ Slice::Gen::DelegateDVisitor::visitClassDefStart(const ClassDefPtr& p) _out << eb; _out << nl << "catch(Ice.LocalException ex__)"; _out << sb; - _out << nl << "throw new IceInternal.NonRepeatable(ex__);"; + _out << nl << "throw new IceInternal.LocalExceptionWrapper(ex__, false);"; _out << eb; _out << nl << "finally"; _out << sb; diff --git a/cpp/src/slice2java/Gen.cpp b/cpp/src/slice2java/Gen.cpp index 648dd82c3b8..bbee749c47f 100644 --- a/cpp/src/slice2java/Gen.cpp +++ b/cpp/src/slice2java/Gen.cpp @@ -242,7 +242,7 @@ Slice::JavaVisitor::writeDelegateThrowsClause(const string& package, const Excep out.inc(); out << nl << "throws "; out.useCurrentPosAsIndent(); - out << "IceInternal.NonRepeatable"; + out << "IceInternal.LocalExceptionWrapper"; ExceptionList::const_iterator r; for(r = throws.begin(); r != throws.end(); ++r) @@ -3090,15 +3090,15 @@ Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p) out << nl << "return;"; } out << eb; - out << nl << "catch(IceInternal.NonRepeatable __ex)"; + out << nl << "catch(IceInternal.LocalExceptionWrapper __ex)"; out << sb; if(op->mode() == Operation::Idempotent || op->mode() == Operation::Nonmutating) { - out << nl << "__cnt = __handleException(__ex.get(), __cnt);"; + out << nl << "__cnt = __handleExceptionWrapperRelaxed(__ex, __cnt);"; } else { - out << nl << "__rethrowException(__ex.get());"; + out << nl << "__handleExceptionWrapper(__ex);"; } out << eb; out << nl << "catch(Ice.LocalException __ex)"; @@ -3893,7 +3893,7 @@ Slice::Gen::DelegateMVisitor::visitClassDefStart(const ClassDefPtr& p) out << eb; out << nl << "catch(Ice.LocalException __ex)"; out << sb; - out << nl << "throw new IceInternal.NonRepeatable(__ex);"; + out << nl << "throw new IceInternal.LocalExceptionWrapper(__ex, false);"; out << eb; out << eb; out << nl << "finally"; @@ -4003,7 +4003,7 @@ Slice::Gen::DelegateDVisitor::visitClassDefStart(const ClassDefPtr& p) out << eb; out << nl << "catch(Ice.LocalException __ex)"; out << sb; - out << nl << "throw new IceInternal.NonRepeatable(__ex);"; + out << nl << "throw new IceInternal.LocalExceptionWrapper(__ex, false);"; out << eb; out << eb; out << nl << "finally"; diff --git a/cpp/src/slice2vb/Gen.cpp b/cpp/src/slice2vb/Gen.cpp index e9007cb2130..280cb8ab97d 100755 --- a/cpp/src/slice2vb/Gen.cpp +++ b/cpp/src/slice2vb/Gen.cpp @@ -3691,15 +3691,15 @@ Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p) _out << nl << "Return"; } _out.dec(); - _out << nl << "Catch ex__ As IceInternal.NonRepeatable"; + _out << nl << "Catch ex__ As IceInternal.LocalExceptionWrapper"; _out.inc(); if(op->mode() == Operation::Idempotent || op->mode() == Operation::Nonmutating) { - _out << nl << "cnt__ = handleException__(ex__.get(), cnt__)"; + _out << nl << "cnt__ = handleExceptionWrapperRelaxed__(ex__, cnt__)"; } else { - _out << nl << "rethrowException__(ex__.get())"; + _out << nl << "handleExceptionWrapper__(ex__)"; } _out.dec(); _out << nl << "Catch ex__ As Ice.LocalException"; @@ -4464,7 +4464,7 @@ Slice::Gen::DelegateMVisitor::visitClassDefStart(const ClassDefPtr& p) _out.dec(); _out << nl << "Catch ex__ As Ice.LocalException"; _out.inc(); - _out << nl << "throw New IceInternal.NonRepeatable(ex__)"; + _out << nl << "throw New IceInternal.LocalExceptionWrapper(ex__, false)"; _out.dec(); _out << nl << "End Try"; _out.dec(); @@ -4583,7 +4583,7 @@ Slice::Gen::DelegateDVisitor::visitClassDefStart(const ClassDefPtr& p) _out.dec(); _out << nl << "Catch ex__ As Ice.LocalException"; _out.inc(); - _out << nl << "Throw New IceInternal.NonRepeatable(ex__)"; + _out << nl << "Throw New IceInternal.LocalExceptionWrapper(ex__, false)"; _out.dec(); _out << nl << "Finally"; _out.inc(); diff --git a/java/CHANGES b/java/CHANGES index a5256e0142a..79795af92bb 100644 --- a/java/CHANGES +++ b/java/CHANGES @@ -1,6 +1,15 @@ Changes since version 3.0.1 --------------------------- +- Performance improvements if an AMI callback object is reused with + the same proxy. + +- If several proxies share the same connection, and an operation call + on one of the proxies causes a failure and the shared connection to + be closed, then subsequent calls on the other proxies will try to + establish a new connection instead of throwing an exception, even if + retries are disabled. + - Fixed bug in identityToString() and proxyToString() that could cause incorrect string values to be returned for identities containing characters outside the ASCII range. diff --git a/java/allTests.py b/java/allTests.py index 9f580b6c661..a2dec50ccd7 100755 --- a/java/allTests.py +++ b/java/allTests.py @@ -68,6 +68,7 @@ tests = [ \ "Ice/checksum", \ "Ice/package", \ "Ice/stream", \ + "Ice/retry", \ "Freeze/dbmap", \ "Freeze/complex", \ "Freeze/evictor", \ diff --git a/java/src/Ice/ConnectionI.java b/java/src/Ice/ConnectionI.java index c65d91082df..1446568273f 100644 --- a/java/src/Ice/ConnectionI.java +++ b/java/src/Ice/ConnectionI.java @@ -319,6 +319,16 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne } public synchronized void + throwException() + { + if(_exception != null) + { + assert(_state >= StateClosing); + throw _exception; + } + } + + public synchronized void waitUntilHolding() { while(_state < StateHolding || _dispatchCount > 0) @@ -495,6 +505,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne public void sendRequest(IceInternal.BasicStream os, IceInternal.Outgoing out, boolean compress) + throws IceInternal.LocalExceptionWrapper { int requestId = 0; IceInternal.BasicStream stream = null; @@ -505,7 +516,12 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne if(_exception != null) { - throw _exception; + // + // If the connection is closed before we even have a chance + // to send our request, we always try to send the request + // again. + // + throw new IceInternal.LocalExceptionWrapper(_exception, true); } assert(_state > StateNotValidated); @@ -605,6 +621,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne public void sendAsyncRequest(IceInternal.BasicStream os, IceInternal.OutgoingAsync out, boolean compress) + throws IceInternal.LocalExceptionWrapper { int requestId = 0; IceInternal.BasicStream stream = null; @@ -615,7 +632,12 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne if(_exception != null) { - throw _exception; + // + // If the connection is closed before we even have a chance + // to send our request, we always try to send the request + // again. + // + throw new IceInternal.LocalExceptionWrapper(_exception, true); } assert(_state > StateNotValidated); @@ -2383,7 +2405,7 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne public IceInternal.Outgoing getOutgoing(IceInternal.Reference reference, String operation, OperationMode mode, java.util.Map context, boolean compress) - throws IceInternal.NonRepeatable + throws IceInternal.LocalExceptionWrapper { IceInternal.Outgoing out = null; diff --git a/java/src/Ice/ObjectPrxHelperBase.java b/java/src/Ice/ObjectPrxHelperBase.java index 125e227438e..98fd2b40044 100644 --- a/java/src/Ice/ObjectPrxHelperBase.java +++ b/java/src/Ice/ObjectPrxHelperBase.java @@ -56,9 +56,9 @@ public class ObjectPrxHelperBase implements ObjectPrx _ObjectDel __del = __getDelegate(); return __del.ice_isA(__id, __context); } - catch(IceInternal.NonRepeatable __ex) + catch(IceInternal.LocalExceptionWrapper __ex) { - __cnt = __handleException(__ex.get(), __cnt); + __cnt = __handleExceptionWrapperRelaxed(__ex, __cnt); } catch(LocalException __ex) { @@ -86,9 +86,9 @@ public class ObjectPrxHelperBase implements ObjectPrx __del.ice_ping(__context); return; } - catch(IceInternal.NonRepeatable __ex) + catch(IceInternal.LocalExceptionWrapper __ex) { - __cnt = __handleException(__ex.get(), __cnt); + __cnt = __handleExceptionWrapperRelaxed(__ex, __cnt); } catch(LocalException __ex) { @@ -115,9 +115,9 @@ public class ObjectPrxHelperBase implements ObjectPrx _ObjectDel __del = __getDelegate(); return __del.ice_ids(__context); } - catch(IceInternal.NonRepeatable __ex) + catch(IceInternal.LocalExceptionWrapper __ex) { - __cnt = __handleException(__ex.get(), __cnt); + __cnt = __handleExceptionWrapperRelaxed(__ex, __cnt); } catch(LocalException __ex) { @@ -144,9 +144,9 @@ public class ObjectPrxHelperBase implements ObjectPrx _ObjectDel __del = __getDelegate(); return __del.ice_id(__context); } - catch(IceInternal.NonRepeatable __ex) + catch(IceInternal.LocalExceptionWrapper __ex) { - __cnt = __handleException(__ex.get(), __cnt); + __cnt = __handleExceptionWrapperRelaxed(__ex, __cnt); } catch(LocalException __ex) { @@ -173,15 +173,15 @@ public class ObjectPrxHelperBase implements ObjectPrx _ObjectDel __del = __getDelegate(); return __del.ice_invoke(operation, mode, inParams, outParams, context); } - catch(IceInternal.NonRepeatable __ex) + catch(IceInternal.LocalExceptionWrapper __ex) { if(mode == OperationMode.Nonmutating || mode == OperationMode.Idempotent) { - __cnt = __handleException(__ex.get(), __cnt); + __cnt = __handleExceptionWrapperRelaxed(__ex, __cnt); } else { - __rethrowException(__ex.get()); + __handleExceptionWrapper(__ex); } } catch(LocalException __ex) @@ -723,11 +723,35 @@ public class ObjectPrxHelperBase implements ObjectPrx } } - public final synchronized void - __rethrowException(LocalException ex) + public final void + __handleExceptionWrapper(IceInternal.LocalExceptionWrapper ex) { - _delegate = null; - throw ex; + synchronized(this) + { + _delegate = null; + } + + if(!ex.retry()) + { + throw ex.get(); + } + } + + public final int + __handleExceptionWrapperRelaxed(IceInternal.LocalExceptionWrapper ex, int cnt) + { + if(!ex.retry()) + { + return __handleException(ex.get(), cnt); + } + else + { + synchronized(this) + { + _delegate = null; + } + return cnt; + } } public final void diff --git a/java/src/Ice/_ObjectDel.java b/java/src/Ice/_ObjectDel.java index 5adb5143e23..f4c208f7fb1 100644 --- a/java/src/Ice/_ObjectDel.java +++ b/java/src/Ice/_ObjectDel.java @@ -12,20 +12,20 @@ package Ice; public interface _ObjectDel { boolean ice_isA(String id, java.util.Map context) - throws IceInternal.NonRepeatable; + throws IceInternal.LocalExceptionWrapper; void ice_ping(java.util.Map context) - throws IceInternal.NonRepeatable; + throws IceInternal.LocalExceptionWrapper; String[] ice_ids(java.util.Map context) - throws IceInternal.NonRepeatable; + throws IceInternal.LocalExceptionWrapper; String ice_id(java.util.Map context) - throws IceInternal.NonRepeatable; + throws IceInternal.LocalExceptionWrapper; boolean ice_invoke(String operation, Ice.OperationMode mode, byte[] inParams, ByteSeqHolder outParams, java.util.Map context) - throws IceInternal.NonRepeatable; + throws IceInternal.LocalExceptionWrapper; Connection ice_connection(); } diff --git a/java/src/Ice/_ObjectDelD.java b/java/src/Ice/_ObjectDelD.java index 20fd114beb1..40058a4b9f8 100644 --- a/java/src/Ice/_ObjectDelD.java +++ b/java/src/Ice/_ObjectDelD.java @@ -13,7 +13,7 @@ public class _ObjectDelD implements _ObjectDel { public boolean ice_isA(String __id, java.util.Map __context) - throws IceInternal.NonRepeatable + throws IceInternal.LocalExceptionWrapper { Current __current = new Current(); __initCurrent(__current, "ice_isA", OperationMode.Nonmutating, __context); @@ -33,7 +33,7 @@ public class _ObjectDelD implements _ObjectDel public void ice_ping(java.util.Map __context) - throws IceInternal.NonRepeatable + throws IceInternal.LocalExceptionWrapper { Current __current = new Current(); __initCurrent(__current, "ice_ping", OperationMode.Nonmutating, __context); @@ -54,7 +54,7 @@ public class _ObjectDelD implements _ObjectDel public String[] ice_ids(java.util.Map __context) - throws IceInternal.NonRepeatable + throws IceInternal.LocalExceptionWrapper { Current __current = new Current(); __initCurrent(__current, "ice_ids", OperationMode.Nonmutating, __context); @@ -74,7 +74,7 @@ public class _ObjectDelD implements _ObjectDel public String ice_id(java.util.Map __context) - throws IceInternal.NonRepeatable + throws IceInternal.LocalExceptionWrapper { Current __current = new Current(); __initCurrent(__current, "ice_id", OperationMode.Nonmutating, __context); @@ -95,7 +95,7 @@ public class _ObjectDelD implements _ObjectDel public boolean ice_invoke(String operation, Ice.OperationMode mode, byte[] inParams, ByteSeqHolder outParams, java.util.Map context) - throws IceInternal.NonRepeatable + throws IceInternal.LocalExceptionWrapper { throw new CollocationOptimizationException(); } diff --git a/java/src/Ice/_ObjectDelM.java b/java/src/Ice/_ObjectDelM.java index c6301ce909d..6a5501e170c 100644 --- a/java/src/Ice/_ObjectDelM.java +++ b/java/src/Ice/_ObjectDelM.java @@ -13,7 +13,7 @@ public class _ObjectDelM implements _ObjectDel { public boolean ice_isA(String __id, java.util.Map __context) - throws IceInternal.NonRepeatable + throws IceInternal.LocalExceptionWrapper { IceInternal.Outgoing __og = __connection.getOutgoing(__reference, "ice_isA", OperationMode.Nonmutating, __context, __compress); @@ -47,7 +47,7 @@ public class _ObjectDelM implements _ObjectDel } catch(LocalException __ex) { - throw new IceInternal.NonRepeatable(__ex); + throw new IceInternal.LocalExceptionWrapper(__ex, false); } } finally @@ -58,7 +58,7 @@ public class _ObjectDelM implements _ObjectDel public void ice_ping(java.util.Map __context) - throws IceInternal.NonRepeatable + throws IceInternal.LocalExceptionWrapper { IceInternal.Outgoing __og = __connection.getOutgoing(__reference, "ice_ping", OperationMode.Nonmutating, __context, __compress); @@ -82,7 +82,7 @@ public class _ObjectDelM implements _ObjectDel } catch(LocalException __ex) { - throw new IceInternal.NonRepeatable(__ex); + throw new IceInternal.LocalExceptionWrapper(__ex, false); } } finally @@ -93,7 +93,7 @@ public class _ObjectDelM implements _ObjectDel public String[] ice_ids(java.util.Map __context) - throws IceInternal.NonRepeatable + throws IceInternal.LocalExceptionWrapper { IceInternal.Outgoing __og = __connection.getOutgoing(__reference, "ice_ids", OperationMode.Nonmutating, __context, __compress); @@ -118,7 +118,7 @@ public class _ObjectDelM implements _ObjectDel } catch(LocalException __ex) { - throw new IceInternal.NonRepeatable(__ex); + throw new IceInternal.LocalExceptionWrapper(__ex, false); } } finally @@ -129,7 +129,7 @@ public class _ObjectDelM implements _ObjectDel public String ice_id(java.util.Map __context) - throws IceInternal.NonRepeatable + throws IceInternal.LocalExceptionWrapper { IceInternal.Outgoing __og = __connection.getOutgoing(__reference, "ice_id", OperationMode.Nonmutating, __context, __compress); @@ -154,7 +154,7 @@ public class _ObjectDelM implements _ObjectDel } catch(LocalException __ex) { - throw new IceInternal.NonRepeatable(__ex); + throw new IceInternal.LocalExceptionWrapper(__ex, false); } } finally @@ -165,7 +165,7 @@ public class _ObjectDelM implements _ObjectDel public boolean ice_invoke(String operation, OperationMode mode, byte[] inParams, ByteSeqHolder outParams, java.util.Map __context) - throws IceInternal.NonRepeatable + throws IceInternal.LocalExceptionWrapper { IceInternal.Outgoing __og = __connection.getOutgoing(__reference, operation, mode, __context, __compress); try @@ -196,7 +196,7 @@ public class _ObjectDelM implements _ObjectDel } catch(LocalException __ex) { - throw new IceInternal.NonRepeatable(__ex); + throw new IceInternal.LocalExceptionWrapper(__ex, false); } } return ok; diff --git a/java/src/IceInternal/FixedReference.java b/java/src/IceInternal/FixedReference.java index 445fd725ca3..b3d77f7a5b2 100644 --- a/java/src/IceInternal/FixedReference.java +++ b/java/src/IceInternal/FixedReference.java @@ -174,6 +174,7 @@ public class FixedReference extends Reference Ice.ConnectionI connection = filteredConns[0]; assert(connection != null); + connection.throwException(); // Throw in case our connection is already destroyed. compress.value = connection.endpoint().compress(); return connection; diff --git a/java/src/IceInternal/LocalExceptionWrapper.java b/java/src/IceInternal/LocalExceptionWrapper.java new file mode 100644 index 00000000000..2d60f8d219a --- /dev/null +++ b/java/src/IceInternal/LocalExceptionWrapper.java @@ -0,0 +1,49 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2006 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 LocalExceptionWrapper extends Exception +{ + public + LocalExceptionWrapper(Ice.LocalException ex, boolean retry) + { + _ex = ex; + _retry = retry; + } + + public + LocalExceptionWrapper(IceInternal.LocalExceptionWrapper ex) + { + _ex = ex.get(); + _retry = ex._retry; + } + + public Ice.LocalException + get() + { + return _ex; + } + + // + // If true, always repeat the request. Don't take retry settings + // or "at-most-once" guarantees into account. + // + // If false, only repeat the request if the retry settings allow + // to do so, and if "at-most-once" does not need to be guaranteed. + // + public boolean + retry() + { + return _retry; + } + + private Ice.LocalException _ex; + private boolean _retry; +} diff --git a/java/src/IceInternal/Outgoing.java b/java/src/IceInternal/Outgoing.java index 6640129de61..c32f6055829 100644 --- a/java/src/IceInternal/Outgoing.java +++ b/java/src/IceInternal/Outgoing.java @@ -14,7 +14,7 @@ public final class Outgoing public Outgoing(Ice.ConnectionI connection, Reference ref, String operation, Ice.OperationMode mode, java.util.Map context, boolean compress) - throws NonRepeatable + throws LocalExceptionWrapper { _connection = connection; _reference = ref; @@ -31,7 +31,7 @@ public final class Outgoing // public void reset(Reference ref, String operation, Ice.OperationMode mode, java.util.Map context, boolean compress) - throws NonRepeatable + throws LocalExceptionWrapper { _reference = ref; _state = StateUnsent; @@ -51,7 +51,7 @@ public final class Outgoing // Returns true if ok, false if user exception. public boolean invoke() - throws NonRepeatable + throws LocalExceptionWrapper { assert(_state == StateUnsent); @@ -165,11 +165,11 @@ public final class Outgoing } // - // Throw the exception wrapped in a NonRepeatable, to + // Throw the exception wrapped in a LocalExceptionWrapper, to // indicate that the request cannot be resent without // potentially violating the "at-most-once" principle. // - throw new NonRepeatable(_exception); + throw new LocalExceptionWrapper(_exception, false); } if(_state == StateUserException) @@ -216,7 +216,7 @@ public final class Outgoing public void abort(Ice.LocalException ex) - throws NonRepeatable + throws LocalExceptionWrapper { assert(_state == StateUnsent); @@ -236,7 +236,7 @@ public final class Outgoing // be aborted, but all other requests in the batch as // well. // - throw new NonRepeatable(ex); + throw new LocalExceptionWrapper(ex, false); } throw ex; @@ -413,7 +413,7 @@ public final class Outgoing private void writeHeader(String operation, Ice.OperationMode mode, java.util.Map context) - throws NonRepeatable + throws LocalExceptionWrapper { switch(_reference.getMode()) { diff --git a/java/src/IceInternal/OutgoingAsync.java b/java/src/IceInternal/OutgoingAsync.java index 15a1c158e16..f83b5cbc9ea 100644 --- a/java/src/IceInternal/OutgoingAsync.java +++ b/java/src/IceInternal/OutgoingAsync.java @@ -173,7 +173,7 @@ public abstract class OutgoingAsync { synchronized(_monitor) { - if(_reference != null) + if(__os != null) // Don't retry if cleanup() was already called. { boolean doRetry = false; @@ -264,7 +264,7 @@ public abstract class OutgoingAsync // // We must first wait for other requests to finish. // - while(_reference != null) + while(__os != null) { try { @@ -279,10 +279,19 @@ public abstract class OutgoingAsync // Can't call async via a oneway proxy. // ((Ice.ObjectPrxHelperBase)prx).__checkTwowayOnly(operation); + + Reference ref = ((Ice.ObjectPrxHelperBase)prx).__reference(); + + // + // Optimization: Don't update the connection if it is not + // necessary. + // + if(_connection == null || _reference == null || !_reference.equals(ref)) + { + _connection = ref.getConnection(_compress); + } - _reference = ((Ice.ObjectPrxHelperBase)prx).__reference(); - assert(_connection == null); - _connection = _reference.getConnection(_compress); + _reference = ref; _cnt = 0; _mode = mode; assert(__is == null); @@ -394,6 +403,13 @@ public abstract class OutgoingAsync // return; } + catch(LocalExceptionWrapper ex) + { + if(!ex.retry()) + { + throw ex.get(); + } + } catch(Ice.LocalException ex) { ProxyFactory proxyFactory = _reference.getInstance().proxyFactory(); @@ -422,7 +438,7 @@ public abstract class OutgoingAsync private final void warning(java.lang.Exception ex) { - if(_reference != null) // Don't print anything if cleanup() was already called. + if(__os != null) // Don't print anything if cleanup() was already called. { if(_reference.getInstance().properties().getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0) { @@ -441,8 +457,6 @@ public abstract class OutgoingAsync private final void cleanup() { - _reference = null; - _connection = null; __is = null; __os = null; diff --git a/java/src/IceInternal/ProxyFactory.java b/java/src/IceInternal/ProxyFactory.java index c3a8132395a..1a2e1731090 100644 --- a/java/src/IceInternal/ProxyFactory.java +++ b/java/src/IceInternal/ProxyFactory.java @@ -105,86 +105,77 @@ public final class ProxyFactory throw ex; } - // - // There is no point in retrying an operation that resulted in a - // MarshalException. This must have been raised locally (because if - // it happened in a server it would result in an UnknownLocalException - // instead), which means there was a problem in this process that will - // not change if we try again. - // - // The most likely cause for a MarshalException is exceeding the - // maximum message size, which is represented by the the subclass - // MemoryLimitException. For example, a client can attempt to send a - // message that exceeds the maximum memory size, or accumulate enough - // batch requests without flushing that the maximum size is reached. - // - // This latter case is especially problematic, because if we were to - // retry a batch request after a MarshalException, we would in fact - // silently discard the accumulated requests and allow new batch - // requests to accumulate. If the subsequent batched requests do not - // exceed the maximum message size, it appears to the client that all - // of the batched requests were accepted, when in reality only the - // last few are actually sent. - // - if(ex instanceof Ice.MarshalException) - { - throw ex; - } + // + // There is no point in retrying an operation that resulted in a + // MarshalException. This must have been raised locally (because + // if it happened in a server it would result in an + // UnknownLocalException instead), which means there was a problem + // in this process that will not change if we try again. + // + // The most likely cause for a MarshalException is exceeding the + // maximum message size, which is represented by the the subclass + // MemoryLimitException. For example, a client can attempt to send + // a message that exceeds the maximum memory size, or accumulate + // enough batch requests without flushing that the maximum size is + // reached. + // + // This latter case is especially problematic, because if we were + // to retry a batch request after a MarshalException, we would in + // fact silently discard the accumulated requests and allow new + // batch requests to accumulate. If the subsequent batched + // requests do not exceed the maximum message size, it appears to + // the client that all of the batched requests were accepted, when + // in reality only the last few are actually sent. + // + if(ex instanceof Ice.MarshalException) + { + throw ex; + } - ++cnt; + ++cnt; + assert(cnt > 0); TraceLevels traceLevels = _instance.traceLevels(); Ice.Logger logger = _instance.logger(); - // - // Instance components may be null if Communicator has been destroyed. - // - if(traceLevels != null && logger != null) + if(cnt > _retryIntervals.length) { - if(cnt > _retryIntervals.length) - { - if(traceLevels.retry >= 1) - { - String s = "cannot retry operation call because retry limit has been exceeded\n" + ex.toString(); - logger.trace(traceLevels.retryCat, s); - } - throw ex; - } - if(traceLevels.retry >= 1) { - String s = "re-trying operation call"; - if(cnt > 0 && _retryIntervals[cnt - 1] > 0) - { - s += " in " + _retryIntervals[cnt - 1] + "ms"; - } - s += " because of exception\n" + ex; + String s = "cannot retry operation call because retry limit has been exceeded\n" + ex.toString(); logger.trace(traceLevels.retryCat, s); } + throw ex; + } + + int interval = _retryIntervals[cnt - 1]; - if(cnt > 0) + if(traceLevels.retry >= 1) + { + String s = "re-trying operation call"; + if(interval > 0) { - // - // Sleep before retrying. - // - try - { - Thread.currentThread().sleep(_retryIntervals[cnt - 1]); - } - catch(InterruptedException ex1) - { - } + s += " in " + interval + "ms"; } - - return cnt; + s += " because of exception\n" + ex; + logger.trace(traceLevels.retryCat, s); } - else + + if(cnt > 0) { // - // Impossible to retry after Communicator has been destroyed. + // Sleep before retrying. // - throw ex; + try + { + Thread.currentThread().sleep(interval); + } + catch(InterruptedException ex1) + { + } } + + return cnt; } // diff --git a/java/src/IceInternal/RoutableReference.java b/java/src/IceInternal/RoutableReference.java index e17e6b873d7..b2085dc0859 100644 --- a/java/src/IceInternal/RoutableReference.java +++ b/java/src/IceInternal/RoutableReference.java @@ -237,15 +237,21 @@ public abstract class RoutableReference extends Reference // switch(getEndpointSelection().value()) { - case Ice.EndpointSelectionType._Random: - java.util.Collections.shuffle(endpoints); - break; - case Ice.EndpointSelectionType._Ordered: - // Nothing to do. - break; - default: - assert(false); - break; + case Ice.EndpointSelectionType._Random: + { + java.util.Collections.shuffle(endpoints); + break; + } + case Ice.EndpointSelectionType._Ordered: + { + // Nothing to do. + break; + } + default: + { + assert(false); + break; + } } // diff --git a/java/test/Ice/build.xml b/java/test/Ice/build.xml index e4a2a76728e..57719374a06 100644 --- a/java/test/Ice/build.xml +++ b/java/test/Ice/build.xml @@ -29,11 +29,13 @@ <ant dir="translator"/> <ant dir="checksum"/> <ant dir="package"/> - <ant dir="stream"/> + <ant dir="stream"/> + <ant dir="retry"/> </target> <target name="clean"> <ant dir="adapterDeactivation" target="clean"/> + <ant dir="binding" target="clean"/> <ant dir="exceptions" target="clean"/> <ant dir="exceptionsAMD" target="clean"/> <ant dir="facets" target="clean"/> @@ -50,6 +52,7 @@ <ant dir="checksum" target="clean"/> <ant dir="package" target="clean"/> <ant dir="stream" target="clean"/> + <ant dir="retry" target="clean"/> </target> </project> diff --git a/java/test/Ice/retry/AllTests.java b/java/test/Ice/retry/AllTests.java new file mode 100644 index 00000000000..f9b764ae2ac --- /dev/null +++ b/java/test/Ice/retry/AllTests.java @@ -0,0 +1,174 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +// +// This copy of Ice-E is licensed to you under the terms described in the +// ICEE_LICENSE file included in this distribution. +// +// ********************************************************************** + +public class AllTests +{ + private static void + test(boolean b) + { + if(!b) + { + throw new RuntimeException(); + } + } + + private static class Callback + { + Callback() + { + _called = false; + } + + public synchronized boolean + check() + { + while(!_called) + { + try + { + wait(5000); + } + catch(InterruptedException ex) + { + continue; + } + + if(!_called) + { + return false; // Must be timeout. + } + } + + _called = false; + return true; + } + + public synchronized void + called() + { + assert(!_called); + _called = true; + notify(); + } + + private boolean _called; + } + + private static class AMIRegular extends Test.AMI_Retry_op + { + public void + ice_response() + { + callback.called(); + } + + public void + ice_exception(Ice.LocalException ex) + { + test(false); + } + + public boolean + check() + { + return callback.check(); + } + + private Callback callback = new Callback(); + } + + private static class AMIException extends Test.AMI_Retry_op + { + public void + ice_response() + { + test(false); + } + + public void + ice_exception(Ice.LocalException ex) + { + test(ex instanceof Ice.ConnectionLostException); + callback.called(); + } + + public boolean + check() + { + return callback.check(); + } + + private Callback callback = new Callback(); + } + + public static Test.RetryPrx + allTests(Ice.Communicator communicator, java.io.PrintStream out) + { + out.print("testing stringToProxy... "); + out.flush(); + String ref = "retry:default -p 12010 -t 10000"; + Ice.ObjectPrx base1 = communicator.stringToProxy(ref); + test(base1 != null); + Ice.ObjectPrx base2 = communicator.stringToProxy(ref); + test(base2 != null); + out.println("ok"); + + out.print("testing checked cast... "); + out.flush(); + Test.RetryPrx retry1 = Test.RetryPrxHelper.checkedCast(base1); + test(retry1 != null); + test(retry1.equals(base1)); + Test.RetryPrx retry2 = Test.RetryPrxHelper.checkedCast(base2); + test(retry2 != null); + test(retry2.equals(base2)); + out.println("ok"); + + out.print("calling regular operation with first proxy... "); + out.flush(); + retry1.op(false); + out.println("ok"); + + out.print("calling operation to kill connection with second proxy... "); + out.flush(); + try + { + retry2.op(true); + test(false); + } + catch(Ice.ConnectionLostException ex) + { + out.println("ok"); + } + + out.print("calling regular operation with first proxy again... "); + out.flush(); + retry1.op(false); + out.println("ok"); + + AMIRegular cb1 = new AMIRegular(); + AMIException cb2 = new AMIException(); + + out.print("calling regular AMI operation with first proxy... "); + retry1.op_async(cb1, false); + test(cb1.check()); + out.println("ok"); + + out.print("calling AMI operation to kill connection with second proxy... "); + retry2.op_async(cb2, true); + test(cb2.check()); + out.println("ok"); + + out.print("calling regular AMI operation with first proxy again... "); + retry1.op_async(cb1, false); + test(cb1.check()); + out.println("ok"); + + return retry1; + } +} diff --git a/java/test/Ice/retry/Client.java b/java/test/Ice/retry/Client.java new file mode 100644 index 00000000000..49b9f330b9a --- /dev/null +++ b/java/test/Ice/retry/Client.java @@ -0,0 +1,67 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +// +// This copy of Ice-E is licensed to you under the terms described in the +// ICEE_LICENSE file included in this distribution. +// +// ********************************************************************** + +public class Client +{ + public static int + run(String[] args, Ice.Communicator communicator, java.io.PrintStream out) + { + Test.RetryPrx retry = AllTests.allTests(communicator, out); + retry.shutdown(); + return 0; + } + + public static void + main(String[] args) + { + int status = 0; + Ice.Communicator communicator = null; + + try + { + Ice.StringSeqHolder argsH = new Ice.StringSeqHolder(args); + Ice.Properties properties = Ice.Util.getDefaultProperties(argsH); + + // + // For this test, we want to disable retries. + // + properties.setProperty("Ice.RetryIntervals", "-1"); + + communicator = Ice.Util.initialize(argsH); + + // + // We don't want connection warnings because of the timeout test. + // + properties.setProperty("Ice.Warn.Connections", "0"); + + status = run(argsH.value, communicator, System.out); + } + catch(Ice.LocalException ex) + { + ex.printStackTrace(); + status = 1; + } + + if(communicator != null) + { + try + { + communicator.destroy(); + } + catch(Ice.LocalException ex) + { + ex.printStackTrace(); + status = 1; + } + } + + System.gc(); + System.exit(status); + } +} diff --git a/java/test/Ice/retry/RetryI.java b/java/test/Ice/retry/RetryI.java new file mode 100644 index 00000000000..69e9fbdf461 --- /dev/null +++ b/java/test/Ice/retry/RetryI.java @@ -0,0 +1,33 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2006 ZeroC, Inc. All rights reserved. +// +// This copy of Ice-E is licensed to you under the terms described in the +// ICEE_LICENSE file included in this distribution. +// +// ********************************************************************** + +import Test.*; + +public final class RetryI extends _RetryDisp +{ + public + RetryI() + { + } + + public void + op(boolean kill, Ice.Current current) + { + if(kill) + { + current.con.close(true); + } + } + + public void + shutdown(Ice.Current current) + { + current.adapter.getCommunicator().shutdown(); + } +} diff --git a/java/test/Ice/retry/Server.java b/java/test/Ice/retry/Server.java new file mode 100644 index 00000000000..e8404acabf8 --- /dev/null +++ b/java/test/Ice/retry/Server.java @@ -0,0 +1,66 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +// +// This copy of Ice-E is licensed to you under the terms described in the +// ICEE_LICENSE file included in this distribution. +// +// ********************************************************************** + +public class Server +{ + public static int + run(String[] args, Ice.Communicator communicator, java.io.PrintStream out) + { + // + // When running as a MIDlet the properties for the server may be + // overridden by configuration. If it isn't then we assume + // defaults. + // + if(communicator.getProperties().getProperty("TestAdapter.Endpoints").length() == 0) + { + communicator.getProperties().setProperty("TestAdapter.Endpoints", "default -p 12010 -t 10000"); + } + + Ice.ObjectAdapter adapter = communicator.createObjectAdapter("TestAdapter"); + adapter.add(new RetryI(), Ice.Util.stringToIdentity("retry")); + adapter.activate(); + + communicator.waitForShutdown(); + return 0; + } + + public static void + main(String[] args) + { + int status = 0; + Ice.Communicator communicator = null; + + try + { + communicator = Ice.Util.initialize(args); + status = run(args, communicator, System.out); + } + catch(Ice.LocalException ex) + { + ex.printStackTrace(); + status = 1; + } + + if(communicator != null) + { + try + { + communicator.destroy(); + } + catch(Ice.LocalException ex) + { + ex.printStackTrace(); + status = 1; + } + } + + System.gc(); + System.exit(status); + } +} diff --git a/java/src/IceInternal/NonRepeatable.java b/java/test/Ice/retry/Test.ice index c82a8077ebb..688b0fcb5da 100644 --- a/java/src/IceInternal/NonRepeatable.java +++ b/java/test/Ice/retry/Test.ice @@ -7,21 +7,18 @@ // // ********************************************************************** -package IceInternal; +#ifndef TEST_ICE +#define TEST_ICE -public class NonRepeatable extends Exception +module Test { - public - NonRepeatable(Ice.LocalException ex) - { - _ex = ex; - } - public Ice.LocalException - get() - { - return _ex; - } +interface Retry +{ + ["ami"] void op(bool kill); + void shutdown(); +}; + +}; - private Ice.LocalException _ex; -} +#endif diff --git a/java/test/Ice/retry/build.xml b/java/test/Ice/retry/build.xml new file mode 100644 index 00000000000..37cf2231693 --- /dev/null +++ b/java/test/Ice/retry/build.xml @@ -0,0 +1,58 @@ +<!-- + ********************************************************************** + + Copyright (c) 2003-2005 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. + + ********************************************************************** +--> + +<!DOCTYPE project [ +<!ENTITY common SYSTEM "file:../../../config/common.xml"> +]> + +<project name="test_Ice_retry" default="all" basedir="."> + + <!-- set global properties for this build --> + <property name="top.dir" value="../../.."/> + + <!-- Include common definitions --> + &common; + + <property name="class.dir" value="classes"/> + <property name="generated.dir" value="generated"/> + + <target name="init" depends="config-init"> + <!-- Create the time stamp --> + <tstamp/> + </target> + + <target name="generate" depends="init"> + <!-- Create the output directory for generated code --> + <mkdir dir="${generated.dir}"/> + <slice2java outputdir="${generated.dir}"> + <fileset dir="." includes="Test.ice"/> + <includepath> + <pathelement path="${slice.dir}" /> + </includepath> + </slice2java> + </target> + + <target name="compile" depends="generate"> + <mkdir dir="${class.dir}"/> + <javac srcdir="${generated.dir}" destdir="${class.dir}" + source="1.4" classpath="${lib.dir}" debug="${debug}"/> + <javac srcdir="." destdir="${class.dir}" source="1.4" + classpath="${lib.dir}" excludes="generated/**" debug="${debug}"/> + </target> + + <target name="all" depends="compile"/> + + <target name="clean"> + <delete dir="${generated.dir}"/> + <delete dir="${class.dir}"/> + </target> + +</project> diff --git a/java/test/Ice/retry/run.py b/java/test/Ice/retry/run.py new file mode 100755 index 00000000000..3266f26b780 --- /dev/null +++ b/java/test/Ice/retry/run.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +# +# This copy of Ice-E is licensed to you under the terms described in the +# ICEE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import os, sys + +for toplevel in [".", "..", "../..", "../../..", "../../../.."]: + toplevel = os.path.normpath(toplevel) + if os.path.exists(os.path.join(toplevel, "config", "TestUtil.py")): + break +else: + raise "can't find toplevel directory!" + +sys.path.append(os.path.join(toplevel, "config")) +import TestUtil + +name = os.path.join("Ice", "retry") +testdir = os.path.join(toplevel, "test", name) + +classpath = os.getenv("CLASSPATH", "") +os.environ["CLASSPATH"] = os.path.join(testdir, "classes") + TestUtil.sep + classpath +TestUtil.clientServerTest() +sys.exit(0) diff --git a/py/allTests.py b/py/allTests.py index 17ecf59a03b..01f71dfe1d2 100755 --- a/py/allTests.py +++ b/py/allTests.py @@ -61,6 +61,7 @@ tests = [ \ "Ice/slicing/exceptions", \ "Ice/slicing/objects", \ "Ice/checksum", \ + "Ice/retry", \ ] def usage(): diff --git a/py/test/Ice/retry/AllTests.py b/py/test/Ice/retry/AllTests.py new file mode 100644 index 00000000000..504c186af67 --- /dev/null +++ b/py/test/Ice/retry/AllTests.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2005 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. +# +# ********************************************************************** + +import Ice, Test, threading + +def test(b): + if not b: + raise RuntimeError('test assertion failed') + +class CallbackBase: + def __init__(self): + self._called = False + self._cond = threading.Condition() + + def check(self): + self._cond.acquire() + try: + while not self._called: + self._cond.wait(5.0) + if self._called: + self._called = False + return True + else: + return False + finally: + self._cond.release() + + def called(self): + self._cond.acquire() + self._called = True + self._cond.notify() + self._cond.release() + +class AMIRegular(CallbackBase): + def __init__(self): + CallbackBase.__init__(self) + + def ice_response(self): + self.called() + + def ice_exception(self, ex): + test(False) + +class AMIException(CallbackBase): + def __init__(self): + CallbackBase.__init__(self) + + def ice_response(self): + test(False) + + def ice_exception(self, ex): + test(isinstance(ex, Ice.ConnectionLostException)) + self.called() + +def allTests(communicator): + print "testing stringToProxy...", + ref = "retry:default -p 12010 -t 10000" + base1 = communicator.stringToProxy(ref) + test(base1) + base2 = communicator.stringToProxy(ref) + test(base2) + print "ok" + + print "testing checked cast...", + retry1 = Test.RetryPrx.checkedCast(base1) + test(retry1) + test(retry1 == base1) + retry2 = Test.RetryPrx.checkedCast(base2) + test(retry2) + test(retry2 == base2) + print "ok" + + print "calling regular operation with first proxy...", + retry1.op(False) + print "ok" + + print "calling operation to kill connection with second proxy...", + try: + retry2.op(True) + test(False) + except Ice.ConnectionLostException: + print "ok" + + print "calling regular operation with first proxy again...", + retry1.op(False) + print "ok" + + cb1 = AMIRegular() + cb2 = AMIException() + + print "calling regular AMI operation with first proxy...", + retry1.op_async(cb1, False) + test(cb1.check()) + print "ok" + + print "calling AMI operation to kill connection with second proxy...", + retry2.op_async(cb2, True) + test(cb2.check()) + print "ok" + + print "calling regular AMI operation with first proxy again...", + retry1.op_async(cb1, False) + test(cb1.check()) + print "ok" + + return retry1 + return retry1 diff --git a/py/test/Ice/retry/Client.py b/py/test/Ice/retry/Client.py new file mode 100644 index 00000000000..614676fb090 --- /dev/null +++ b/py/test/Ice/retry/Client.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2005 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. +# +# ********************************************************************** + +import os, sys, traceback + +for toplevel in [".", "..", "../..", "../../..", "../../../.."]: + toplevel = os.path.normpath(toplevel) + if os.path.exists(os.path.join(toplevel, "python", "Ice.py")): + break +else: + raise "can't find toplevel directory!" + +sys.path.insert(0, os.path.join(toplevel, "python")) +sys.path.insert(0, os.path.join(toplevel, "lib")) + +# +# Find Slice directory. +# +slice_dir = os.getenv('ICEPY_HOME', '') +if len(slice_dir) == 0 or not os.path.exists(os.path.join(slice_dir, "slice")): + slice_dir = os.getenv('ICE_HOME', '') +if len(slice_dir) == 0 or not os.path.exists(os.path.join(slice_dir, "slice")): + print sys.argv[0] + ': Slice directory not found. Define ICEPY_HOME or ICE_HOME.' + sys.exit(1) + +import Ice +Ice.loadSlice('-I' + slice_dir + '/slice Test.ice') +import AllTests + +def test(b): + if not b: + raise RuntimeError('test assertion failed') + +def run(args, communicator): + retry = AllTests.allTests(communicator) + retry.shutdown() + return True + +try: + # + # In this test, we need at least two threads in the + # client side thread pool for nested AMI. + # + properties = Ice.getDefaultProperties(sys.argv) + properties.setProperty('Ice.RetryIntervals', '-1') + + communicator = Ice.initialize(sys.argv) + properties.setProperty('Ice.Warn.Connections', '0') + status = run(sys.argv, communicator) +except: + traceback.print_exc() + status = False + +if communicator: + try: + communicator.destroy() + except: + traceback.print_exc() + status = False + +sys.exit(not status) diff --git a/py/test/Ice/retry/Server.py b/py/test/Ice/retry/Server.py new file mode 100644 index 00000000000..887e7e9cef6 --- /dev/null +++ b/py/test/Ice/retry/Server.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2005 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. +# +# ********************************************************************** + +import os, sys, traceback + +for toplevel in [".", "..", "../..", "../../..", "../../../.."]: + toplevel = os.path.normpath(toplevel) + if os.path.exists(os.path.join(toplevel, "python", "Ice.py")): + break +else: + raise "can't find toplevel directory!" + +sys.path.insert(0, os.path.join(toplevel, "python")) +sys.path.insert(0, os.path.join(toplevel, "lib")) + +import Ice + +# +# Find Slice directory. +# +slice_dir = os.getenv('ICEPY_HOME', '') +if len(slice_dir) == 0 or not os.path.exists(os.path.join(slice_dir, "slice")): + slice_dir = os.getenv('ICE_HOME', '') +if len(slice_dir) == 0 or not os.path.exists(os.path.join(slice_dir, "slice")): + print sys.argv[0] + ': Slice directory not found. Define ICEPY_HOME or ICE_HOME.' + sys.exit(1) + +Ice.loadSlice('-I' + slice_dir + '/slice Test.ice') +import Test, TestI + +def run(args, communicator): + communicator.getProperties().setProperty("TestAdapter.Endpoints", "default -p 12010 -t 10000:udp") + adapter = communicator.createObjectAdapter("TestAdapter") + id = Ice.stringToIdentity("retry") + adapter.add(TestI.RetryI(), id) + adapter.activate() + communicator.waitForShutdown() + return True + +try: + communicator = Ice.initialize(sys.argv) + status = run(sys.argv, communicator) +except: + traceback.print_exc() + status = False + +if communicator: + try: + communicator.destroy() + except: + traceback.print_exc() + status = False + +sys.exit(not status) diff --git a/py/test/Ice/retry/Test.ice b/py/test/Ice/retry/Test.ice new file mode 100644 index 00000000000..688b0fcb5da --- /dev/null +++ b/py/test/Ice/retry/Test.ice @@ -0,0 +1,24 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 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 TEST_ICE +#define TEST_ICE + +module Test +{ + +interface Retry +{ + ["ami"] void op(bool kill); + void shutdown(); +}; + +}; + +#endif diff --git a/py/test/Ice/retry/TestI.py b/py/test/Ice/retry/TestI.py new file mode 100644 index 00000000000..9101583ef83 --- /dev/null +++ b/py/test/Ice/retry/TestI.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2005 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. +# +# ********************************************************************** + +import Ice, Test + +class RetryI(Test.Retry): + + def op(self, kill, current=None): + if kill: + current.con.close(True) + + def shutdown(self, current=None): + current.adapter.getCommunicator().shutdown() diff --git a/py/test/Ice/retry/run.py b/py/test/Ice/retry/run.py new file mode 100755 index 00000000000..9c43edcfe72 --- /dev/null +++ b/py/test/Ice/retry/run.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2005 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. +# +# ********************************************************************** + +import os, sys + +for toplevel in [".", "..", "../..", "../../..", "../../../.."]: + toplevel = os.path.normpath(toplevel) + if os.path.exists(os.path.join(toplevel, "config", "TestUtil.py")): + break +else: + raise "can't find toplevel directory!" + +sys.path.append(os.path.join(toplevel, "config")) +import TestUtil + +name = os.path.join("Ice", "retry") + +TestUtil.clientServerTest(name) +sys.exit(0) |