diff options
author | Harald Musum <musum@verizonmedia.com> | 2022-02-24 14:26:42 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-24 14:26:42 +0100 |
commit | b4f06ca78224a2df262b93f7a0440443f329f337 (patch) | |
tree | 2d226e59cf068eaf2230623ec462ede3de489135 /jrt | |
parent | 4ed0d2b6f00c82bc3ba8a3290576a7bedfdd1895 (diff) |
Revert "GC unused SessionHandler"
Diffstat (limited to 'jrt')
-rw-r--r-- | jrt/src/com/yahoo/jrt/Connection.java | 30 | ||||
-rw-r--r-- | jrt/src/com/yahoo/jrt/SessionHandler.java | 66 | ||||
-rw-r--r-- | jrt/src/com/yahoo/jrt/Supervisor.java | 79 | ||||
-rw-r--r-- | jrt/tests/com/yahoo/jrt/ConnectTest.java | 18 | ||||
-rw-r--r-- | jrt/tests/com/yahoo/jrt/SessionTest.java | 466 | ||||
-rw-r--r-- | jrt/tests/com/yahoo/jrt/Test.java | 28 |
6 files changed, 674 insertions, 13 deletions
diff --git a/jrt/src/com/yahoo/jrt/Connection.java b/jrt/src/com/yahoo/jrt/Connection.java index 00aceb7e352..c4f906f5e35 100644 --- a/jrt/src/com/yahoo/jrt/Connection.java +++ b/jrt/src/com/yahoo/jrt/Connection.java @@ -40,6 +40,7 @@ class Connection extends Target { private final boolean tcpNoDelay; private final Map<Integer, ReplyHandler> replyMap = new HashMap<>(); private final Map<TargetWatcher, TargetWatcher> watchers = new IdentityHashMap<>(); + private int activeReqs = 0; private int writeWork = 0; private boolean pendingHandshakeWork = false; private final TransportThread parent; @@ -59,9 +60,11 @@ class Connection extends Target { } boolean live = (state == CONNECTED); boolean down = (state == CLOSED); + boolean fini; boolean pendingWrite; synchronized (this) { this.state = state; + fini = down && (activeReqs == 0); pendingWrite = (writeWork > 0); } if (live) { @@ -71,6 +74,7 @@ class Connection extends Target { } else { disableWrite(); } + owner.sessionLive(this); } if (down) { for (ReplyHandler rh : replyMap.values()) { @@ -79,6 +83,10 @@ class Connection extends Target { for (TargetWatcher watcher : watchers.values()) { watcher.notifyTargetInvalid(this); } + owner.sessionDown(this); + } + if (fini) { + owner.sessionFini(this); } } @@ -94,6 +102,7 @@ class Connection extends Target { maxOutputSize = owner.getMaxOutputBufferSize(); dropEmptyBuffers = owner.getDropEmptyBuffers(); server = true; + owner.sessionInit(this); } public Connection(TransportThread parent, Supervisor owner, Spec spec, Object context, boolean tcpNoDelay) { @@ -106,6 +115,7 @@ class Connection extends Target { maxOutputSize = owner.getMaxOutputBufferSize(); dropEmptyBuffers = owner.getDropEmptyBuffers(); server = false; + owner.sessionInit(this); } public TransportThread transportThread() { @@ -115,7 +125,8 @@ class Connection extends Target { public int allocateKey() { long v = requestId.getAndIncrement(); v = v*2 + (server ? 1 : 0); - return (int)(v & 0x7fffffff); + int i = (int)(v & 0x7fffffff); + return i; } public synchronized boolean cancelReply(ReplyHandler handler) { @@ -267,7 +278,7 @@ class Connection extends Target { try { packet = info.decodePacket(rb); } catch (RuntimeException e) { - log.log(Level.WARNING, "got garbage; closing connection: " + this); + log.log(Level.WARNING, "got garbage; closing connection: " + toString()); throw new IOException("jrt: decode error", e); } ReplyHandler handler; @@ -385,10 +396,6 @@ class Connection extends Target { return (state == CLOSED); } - public synchronized boolean isConnected() { - return (state == CONNECTED); - } - public boolean hasSocket() { return ((socket != null) && (socket.channel() != null)); } @@ -410,16 +417,25 @@ class Connection extends Target { } public TieBreaker startRequest() { + synchronized (this) { + activeReqs++; + } return new TieBreaker(); } public boolean completeRequest(TieBreaker done) { + boolean signalFini = false; synchronized (this) { if (!done.first()) { return false; } + if (--activeReqs == 0 && state == CLOSED) { + signalFini = true; + } + } + if (signalFini) { + owner.sessionFini(this); } - return true; } diff --git a/jrt/src/com/yahoo/jrt/SessionHandler.java b/jrt/src/com/yahoo/jrt/SessionHandler.java new file mode 100644 index 00000000000..82355d73a93 --- /dev/null +++ b/jrt/src/com/yahoo/jrt/SessionHandler.java @@ -0,0 +1,66 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jrt; + + +/** + * Interface used to handle the lifetime of a {@link Target}. The word + * session is used to denote all the RPC activity across a single + * {@link Target} during its lifetime. This interface gives the + * application information about when different {@link Target} objects + * enter different stages in their lifetime. Combined with the ability + * to bind application specific data to a {@link Target} with the + * {@link Target#setContext} method, this enables method invocations + * in the same session to share state information. Usage of this + * interface is optional. It is typically useful for server + * applications needing state to be shared between RPC method + * invocation on a session. Each {@link Supervisor} can only have a + * single session handler. Use the {@link Supervisor#setSessionHandler + * Supervisor.setSessionHandler} method to set the session + * handler. The different callbacks may be called from several + * different threads, but for a single target there will be no + * overlapping of session callbacks, and the order will always be the + * same; init, live (not always called), down, fini. + **/ +public interface SessionHandler { + + /** + * Invoked when a new {@link Target} is created. This is a nice + * place to initialize and attach application context to the + * {@link Target}. + * + * @param target the target + **/ + public void handleSessionInit(Target target); + + /** + * Invoked when a connection is established with the peer. Note + * that if a connection could not be established with the peer, + * this method is never invoked. + * + * @param target the target + **/ + public void handleSessionLive(Target target); + + /** + * Invoked when the target becomes invalid. This is typically + * caused by the network connection with the peer going down. Note + * that this method is invoked also when a connection with the + * peer could not be established at all. + * + * @param target the target + **/ + public void handleSessionDown(Target target); + + /** + * Invoked when the target is invalid and no more RPC invocations + * are active on our side of this target (invoked from the other + * side; we being the server). If you need to perform cleanup + * related to the application data associated with the target, you + * should wait until this method is invoked, to avoid cleaning up + * the {@link Target} application context under the feet of active + * invocations. + * + * @param target the target + **/ + public void handleSessionFini(Target target); +} diff --git a/jrt/src/com/yahoo/jrt/Supervisor.java b/jrt/src/com/yahoo/jrt/Supervisor.java index 48dd2d8bd3d..e8dc6219768 100644 --- a/jrt/src/com/yahoo/jrt/Supervisor.java +++ b/jrt/src/com/yahoo/jrt/Supervisor.java @@ -15,7 +15,10 @@ import java.util.concurrent.atomic.AtomicReference; **/ public class Supervisor { + private static final int SMALL_INPUT_BUFFER_SIZE = 20 * 1024; // Large enough too hold the typical application buffersize of 17k. + private static final int SMALL_OUTPUT_BUFFER_SIZE = 8 *1024; // Suitable small buffer usage with many connections and little traffic. private final Transport transport; + private SessionHandler sessionHandler = null; private final Object methodMapLock = new Object(); private final AtomicReference<HashMap<String, Method>> methodMap = new AtomicReference<>(new HashMap<>()); private int maxInputBufferSize = 64*1024; @@ -95,6 +98,15 @@ public class Supervisor { } /** + * Set the session handler for this Supervisor + * + * @param handler the session handler + **/ + public void setSessionHandler(SessionHandler handler) { + sessionHandler = handler; + } + + /** * Add a method to the set of methods held by this Supervisor * * @param method the method to add @@ -161,6 +173,73 @@ public class Supervisor { } /** + * Convenience method for connecting to a peer, invoking a method + * and disconnecting. + * + * @param spec the address to connect to + * @param req the invocation request + * @param timeout request timeout in seconds + **/ + public void invokeBatch(Spec spec, Request req, double timeout) { + Target target = connect(spec); + try { + target.invokeSync(req, timeout); + } finally { + target.close(); + } + } + + /** + * This method is invoked when a new target is created + * + * @param target the target + **/ + void sessionInit(Target target) { + SessionHandler handler = sessionHandler; + if (handler != null) { + handler.handleSessionInit(target); + } + } + + /** + * This method is invoked when a target establishes a connection + * with its peer + * + * @param target the target + **/ + void sessionLive(Target target) { + SessionHandler handler = sessionHandler; + if (handler != null) { + handler.handleSessionLive(target); + } + } + + /** + * This method is invoked when a target becomes invalid + * + * @param target the target + **/ + void sessionDown(Target target) { + SessionHandler handler = sessionHandler; + if (handler != null) { + handler.handleSessionDown(target); + } + } + + /** + * This method is invoked when a target is invalid and no more + * invocations are active + * + * @param target the target + **/ + void sessionFini(Target target) { + SessionHandler handler = sessionHandler; + if (handler != null) { + handler.handleSessionFini(target); + } + } + + /** * This method is invoked each time we write a packet. This method * is empty and only used for testing through sub-classing. * diff --git a/jrt/tests/com/yahoo/jrt/ConnectTest.java b/jrt/tests/com/yahoo/jrt/ConnectTest.java index 6ad7198f310..31bb713595c 100644 --- a/jrt/tests/com/yahoo/jrt/ConnectTest.java +++ b/jrt/tests/com/yahoo/jrt/ConnectTest.java @@ -1,7 +1,6 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.jrt; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class ConnectTest { @@ -12,25 +11,32 @@ public class ConnectTest { Test.Orb client = new Test.Orb(new Transport()); Acceptor acceptor = server.listen(new Spec(0)); - Connection target = (Connection) client.connect(new Spec("localhost", acceptor.port())); + assertTrue(server.checkLifeCounts(0, 0)); + assertTrue(client.checkLifeCounts(0, 0)); + + Target target = client.connect(new Spec("localhost", acceptor.port())); for (int i = 0; i < 100; i++) { - if (target.isConnected()) { + if (client.initCount == 1 && server.initCount == 1) { break; } try { Thread.sleep(100); } catch (InterruptedException e) {} } - assertTrue(target.isConnected()); + + assertTrue(server.checkLifeCounts(1, 0)); + assertTrue(client.checkLifeCounts(1, 0)); target.close(); for (int i = 0; i < 100; i++) { - if (!target.isClosed()) { + if (client.finiCount == 1 && server.finiCount == 1) { break; } try { Thread.sleep(100); } catch (InterruptedException e) {} } - assertFalse(target.isClosed()); + + assertTrue(server.checkLifeCounts(1, 1)); + assertTrue(client.checkLifeCounts(1, 1)); acceptor.shutdown().join(); client.transport().shutdown().join(); diff --git a/jrt/tests/com/yahoo/jrt/SessionTest.java b/jrt/tests/com/yahoo/jrt/SessionTest.java new file mode 100644 index 00000000000..61db0438959 --- /dev/null +++ b/jrt/tests/com/yahoo/jrt/SessionTest.java @@ -0,0 +1,466 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.jrt; + + +import org.junit.After; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import static com.yahoo.jrt.CryptoUtils.createTestTlsContext; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +@RunWith(Parameterized.class) +public class SessionTest implements SessionHandler { + + @Parameter public CryptoEngine crypto; + @Parameters(name = "{0}") public static Object[] engines() { + return new Object[] { new NullCryptoEngine(), new XorCryptoEngine(), new TlsCryptoEngine(createTestTlsContext()) }; + } + + private static class Session { + private static volatile int cnt = 0; + private static boolean error = false; + + private int value = 0; + private boolean gotInit = false; + private boolean gotLive = false; + private boolean gotDown = false; + private boolean gotFini = false; + + private static synchronized void add() { + cnt++; + } + + private static synchronized void sub() { + cnt--; + } + + public Session() { + add(); + } + + public void init() { + if (gotInit || gotLive || gotDown || gotFini) { + setError(); + } + gotInit = true; + } + + public void live() { + if (!gotInit || gotLive || gotDown || gotFini) { + setError(); + } + gotLive = true; + } + + public void touch() { + if (!gotInit || gotFini) { + setError(); + } + } + + public int value() { + if (!gotInit || gotFini) { + setError(); + } + return value; + } + + public void value(int value) { + if (!gotInit || gotFini) { + setError(); + } + this.value = value; + } + + public void down() { + if (!gotInit || gotDown || gotFini) { + setError(); + } + gotDown = true; + } + + public void fini() { + if (!gotInit || !gotDown || gotFini) { + setError(); + } + gotFini = true; + sub(); + } + + public static int cnt() { + return cnt; + } + + public static void setError() { + error = true; + Throwable e = new RuntimeException("ERROR TRACE"); + e.printStackTrace(); + } + + public static boolean getError() { + return error; + } + + public static void reset() { + error = false; + cnt = 0; + } + } + + Test.Orb server; + Acceptor acceptor; + Test.Orb client; + Target target; + Test.Receptor receptor; + + @Before + public void setUp() throws ListenFailedException { + Session.reset(); + server = new Test.Orb(new Transport("server", crypto, 1)); + server.setSessionHandler(this); + client = new Test.Orb(new Transport("client", crypto, 1)); + client.setSessionHandler(this); + acceptor = server.listen(new Spec(0)); + target = client.connect(new Spec("localhost", acceptor.port()), new Session()); + + server.addMethod(new Method("set", "i", "", this::rpc_set)); + server.addMethod(new Method("get", "", "i", this::rpc_get)); + server.addMethod(new Method("call_detach", "", "", this::rpc_call_detach)); + client.addMethod(new Method("detach", "", "", this::rpc_detach)); + receptor = new Test.Receptor(); + } + + @After + public void tearDown() { + target.close(); + acceptor.shutdown().join(); + client.transport().shutdown().join(); + server.transport().shutdown().join(); + } + + public void handleSessionInit(Target t) { + Object ctx = t.getContext(); + if (t.isClient()) { + if (ctx == null) { + Session.setError(); + } + } + if (t.isServer()) { + if (ctx != null) { + Session.setError(); + } + t.setContext(new Session()); + } + Session s = (Session) t.getContext(); + if (s == null) { + Session.setError(); + } else { + s.init(); + } + } + + public void handleSessionLive(Target t) { + Session s = (Session) t.getContext(); + if (s == null) { + Session.setError(); + } else { + s.live(); + } + } + + public void handleSessionDown(Target t) { + Session s = (Session) t.getContext(); + if (s == null) { + Session.setError(); + } else { + s.down(); + } + } + + public void handleSessionFini(Target t) { + Session s = (Session) t.getContext(); + if (s == null) { + Session.setError(); + } else { + s.fini(); + } + } + + private void rpc_set(Request req) { + Session s = (Session) req.target().getContext(); + s.value(req.parameters().get(0).asInt32()); + } + + private void rpc_get(Request req) { + Session s = (Session) req.target().getContext(); + req.returnValues().add(new Int32Value(s.value())); + } + + private void rpc_call_detach(Request req) { + Session s = (Session) req.target().getContext(); + s.touch(); + req.target().invokeVoid(new Request("detach")); + } + + private void rpc_detach(Request req) { + Session s = (Session) req.target().getContext(); + if (s == null) { + Session.setError(); + } else { + s.touch(); + } + req.detach(); + receptor.put(req); + } + + public void waitState(int sessionCount, + int serverInitCount, + int serverLiveCount, + int serverDownCount, + int serverFiniCount, + int clientInitCount, + int clientLiveCount, + int clientDownCount, + int clientFiniCount) { + server.transport().sync().sync(); + client.transport().sync().sync(); + for (int i = 0; i < 12000; i++) { + if ((sessionCount == Session.cnt() || sessionCount < 0) && + (serverInitCount == server.initCount || serverInitCount < 0) && + (serverLiveCount == server.liveCount || serverLiveCount < 0) && + (serverDownCount == server.downCount || serverDownCount < 0) && + (serverFiniCount == server.finiCount || serverFiniCount < 0) && + (clientInitCount == client.initCount || clientInitCount < 0) && + (clientLiveCount == client.liveCount || clientLiveCount < 0) && + (clientDownCount == client.downCount || clientDownCount < 0) && + (clientFiniCount == client.finiCount || clientFiniCount < 0)) { + break; + } + try { Thread.sleep(10); } catch (InterruptedException e) {} + } + server.transport().sync().sync(); + client.transport().sync().sync(); + } + + @org.junit.Test + public void testConnDownLast() { + waitState(2, 1, 1, 0, 0, 1, 1, 0, 0); + assertEquals(2, Session.cnt()); + assertEquals(1, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(0, server.downCount); + assertEquals(0, server.finiCount); + assertEquals(1, client.initCount); + assertEquals(1, client.liveCount); + assertEquals(0, client.downCount); + assertEquals(0, client.finiCount); + + Request req = new Request("get"); + target.invokeSync(req, 5.0); + assertEquals(0, req.returnValues().get(0).asInt32()); + + req = new Request("set"); + req.parameters().add(new Int32Value(42)); + target.invokeSync(req, 5.0); + assertTrue(!req.isError()); + + req = new Request("get"); + target.invokeSync(req, 5.0); + assertEquals(42, req.returnValues().get(0).asInt32()); + + assertEquals(2, Session.cnt()); + assertEquals(1, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(0, server.downCount); + assertEquals(0, server.finiCount); + assertEquals(1, client.initCount); + assertEquals(1, client.liveCount); + assertEquals(0, client.downCount); + assertEquals(0, client.finiCount); + + target.close(); + waitState(0, 1, 1, 1, 1, 1, 1, 1, 1); + assertEquals(0, Session.cnt()); + assertEquals(1, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(1, server.downCount); + assertEquals(1, server.finiCount); + assertEquals(1, client.initCount); + assertEquals(1, client.liveCount); + assertEquals(1, client.downCount); + assertEquals(1, client.finiCount); + assertFalse(Session.getError()); + } + + @org.junit.Test + public void testReqDoneLast() { + waitState(2, 1, 1, 0, 0, 1, 1, 0, 0); + assertEquals(2, Session.cnt()); + assertEquals(1, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(0, server.downCount); + assertEquals(0, server.finiCount); + assertEquals(1, client.initCount); + assertEquals(1, client.liveCount); + assertEquals(0, client.downCount); + assertEquals(0, client.finiCount); + + Request req = new Request("get"); + target.invokeSync(req, 5.0); + assertEquals(0, req.returnValues().get(0).asInt32()); + + req = new Request("set"); + req.parameters().add(new Int32Value(42)); + target.invokeSync(req, 5.0); + assertTrue(!req.isError()); + + req = new Request("get"); + target.invokeSync(req, 5.0); + assertEquals(42, req.returnValues().get(0).asInt32()); + + assertEquals(2, Session.cnt()); + assertEquals(1, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(0, server.downCount); + assertEquals(0, server.finiCount); + assertEquals(1, client.initCount); + assertEquals(1, client.liveCount); + assertEquals(0, client.downCount); + assertEquals(0, client.finiCount); + + req = new Request("call_detach"); + target.invokeSync(req, 5.0); + assertTrue(!req.isError()); + Request detached = (Request) receptor.get(); + + target.close(); + waitState(1, 1, 1, 1, 1, 1, 1, 1, 0); + assertEquals(1, Session.cnt()); + assertEquals(1, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(1, server.downCount); + assertEquals(1, server.finiCount); + assertEquals(1, client.initCount); + assertEquals(1, client.liveCount); + assertEquals(1, client.downCount); + assertEquals(0, client.finiCount); + + detached.returnRequest(); + waitState(0, 1, 1, 1, 1, 1, 1, 1, 1); + assertEquals(0, Session.cnt()); + assertEquals(1, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(1, server.downCount); + assertEquals(1, server.finiCount); + assertEquals(1, client.initCount); + assertEquals(1, client.liveCount); + assertEquals(1, client.downCount); + assertEquals(1, client.finiCount); + assertFalse(Session.getError()); + } + + @org.junit.Test + public void testNeverLive() { + waitState(2, 1, 1, 0, 0, 1, 1, 0, 0); + assertEquals(2, Session.cnt()); + assertEquals(1, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(0, server.downCount); + assertEquals(0, server.finiCount); + assertEquals(1, client.initCount); + assertEquals(1, client.liveCount); + assertEquals(0, client.downCount); + assertEquals(0, client.finiCount); + + target.close(); + waitState(0, 1, 1, 1, 1, 1, 1, 1, 1); + assertEquals(0, Session.cnt()); + assertEquals(1, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(1, server.downCount); + assertEquals(1, server.finiCount); + assertEquals(1, client.initCount); + assertEquals(1, client.liveCount); + assertEquals(1, client.downCount); + assertEquals(1, client.finiCount); + + Target bogus = client.connect(new Spec("bogus"), + new Session()); + waitState(0, 1, 1, 1, 1, 2, 1, 2, 2); + assertEquals(0, Session.cnt()); + assertEquals(1, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(1, server.downCount); + assertEquals(1, server.finiCount); + assertEquals(2, client.initCount); + assertEquals(1, client.liveCount); // <--- NB + assertEquals(2, client.downCount); + assertEquals(2, client.finiCount); + assertFalse(Session.getError()); + } + + @org.junit.Test + public void testTransportDown() { + waitState(2, 1, 1, 0, 0, 1, 1, 0, 0); + assertEquals(2, Session.cnt()); + assertEquals(1, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(0, server.downCount); + assertEquals(0, server.finiCount); + assertEquals(1, client.initCount); + assertEquals(1, client.liveCount); + assertEquals(0, client.downCount); + assertEquals(0, client.finiCount); + + server.transport().shutdown().join(); + + waitState(0, 1, 1, 1, 1, 1, 1, 1, 1); + assertEquals(0, Session.cnt()); + assertEquals(1, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(1, server.downCount); + assertEquals(1, server.finiCount); + assertEquals(1, client.initCount); + assertEquals(1, client.liveCount); + assertEquals(1, client.downCount); + assertEquals(1, client.finiCount); + + target = client.connect(new Spec("localhost", acceptor.port()), + new Session()); + + waitState(0, 2, 1, 2, 2, 2, -1, 2, 2); + assertEquals(0, Session.cnt()); + assertEquals(2, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(2, server.downCount); + assertEquals(2, server.finiCount); + assertEquals(2, client.initCount); + int oldClientLive = client.liveCount; + assertEquals(2, client.downCount); + assertEquals(2, client.finiCount); + + client.transport().shutdown().join(); + + target = client.connect(new Spec("localhost", acceptor.port()), + new Session()); + + waitState(0, 2, 1, 2, 2, 3, oldClientLive, 3, 3); + assertEquals(0, Session.cnt()); + assertEquals(2, server.initCount); + assertEquals(1, server.liveCount); + assertEquals(2, server.downCount); + assertEquals(2, server.finiCount); + assertEquals(3, client.initCount); + assertEquals(oldClientLive, client.liveCount); + assertEquals(3, client.downCount); + assertEquals(3, client.finiCount); + assertFalse(Session.getError()); + } + +} diff --git a/jrt/tests/com/yahoo/jrt/Test.java b/jrt/tests/com/yahoo/jrt/Test.java index ed2566a7ec2..59edd31ecea 100644 --- a/jrt/tests/com/yahoo/jrt/Test.java +++ b/jrt/tests/com/yahoo/jrt/Test.java @@ -13,6 +13,8 @@ public class Test { * testing. **/ public static class Orb extends Supervisor { + public volatile int initCount = 0; + public volatile int liveCount = 0; public volatile int readRequestCount = 0; public volatile int readReplyCount = 0; public volatile int readErrorCount = 0; @@ -21,6 +23,8 @@ public class Test { public volatile int writeReplyCount = 0; public volatile int writeErrorCount = 0; public volatile long writeBytes = 0; + public volatile int downCount = 0; + public volatile int finiCount = 0; public Orb(Transport t) { super(t); @@ -38,6 +42,30 @@ public class Test { error == writeErrorCount); } + public boolean checkLifeCounts(int init, int fini) { + return (init == initCount && fini == finiCount); + } + + public void sessionInit(Target target) { + initCount++; + super.sessionInit(target); + } + + public void sessionLive(Target target) { + liveCount++; + super.sessionLive(target); + } + + public void sessionDown(Target target) { + downCount++; + super.sessionDown(target); + } + + public void sessionFini(Target target) { + finiCount++; + super.sessionFini(target); + } + public void readPacket(PacketInfo info) { if (info.packetCode() == Packet.PCODE_REQUEST) { readRequestCount++; |