/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.cache.client.internal.pooling; import org.apache.geode.CancelCriterion; import org.apache.geode.cache.client.AllConnectionsInUseException; import org.apache.geode.cache.client.NoAvailableServersException; import org.apache.geode.cache.client.internal.*; import org.apache.geode.distributed.DistributedMember; import org.apache.geode.distributed.DistributedSystem; import org.apache.geode.distributed.internal.ServerLocation; import org.apache.geode.distributed.internal.membership.InternalDistributedMember; import org.apache.geode.internal.cache.PoolStats; import org.apache.geode.internal.cache.tier.sockets.ServerQueueStatus; import org.apache.geode.internal.logging.InternalLogWriter; import org.apache.geode.internal.logging.LocalLogWriter; import org.apache.geode.test.dunit.ThreadUtils; import org.apache.geode.test.dunit.Wait; import org.apache.geode.test.dunit.WaitCriterion; import org.apache.geode.test.junit.categories.ClientServerTest; import org.apache.geode.test.junit.categories.IntegrationTest; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.util.Collections; import java.util.Properties; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS; import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT; import static org.junit.Assert.fail; @Category({IntegrationTest.class, ClientServerTest.class}) public class ConnectionManagerJUnitTest { private static final long TIMEOUT = 30 * 1000; // This is added for some windows machines which think the connection expired // before the idle timeout due to precision issues. private static final long ALLOWABLE_ERROR_IN_EXPIRATION = 20; // milliseconds ConnectionManager manager; private InternalLogWriter logger; protected DummyFactory factory; private DistributedSystem ds; private ScheduledExecutorService background; protected EndpointManager endpointManager; private CancelCriterion cancelCriterion; private PoolStats poolStats; @Before public void setUp() { this.logger = new LocalLogWriter(InternalLogWriter.FINEST_LEVEL, System.out); factory = new DummyFactory(); Properties properties = new Properties(); properties.put(MCAST_PORT, "0"); properties.put(LOCATORS, ""); ds = DistributedSystem.connect(properties); background = Executors.newSingleThreadScheduledExecutor(); poolStats = new PoolStats(ds, "connectionManagerJUnitTest"); endpointManager = new EndpointManagerImpl("pool", ds, ds.getCancelCriterion(), poolStats); cancelCriterion = new CancelCriterion() { public String cancelInProgress() { return null; } public RuntimeException generateCancelledException(Throwable e) { return null; } }; } @After public void tearDown() throws InterruptedException { ds.disconnect(); if (manager != null) { manager.close(false); } background.shutdownNow(); } @Test public void testGet() throws InterruptedException, AllConnectionsInUseException, NoAvailableServersException { manager = new ConnectionManagerImpl("pool", factory, endpointManager, 3, 0, -1, -1, logger, 60 * 1000, cancelCriterion, poolStats); manager.start(background); Connection conn[] = new Connection[4]; conn[0] = manager.borrowConnection(0); Assert.assertEquals(1, factory.creates); manager.returnConnection(conn[0]); conn[0] = manager.borrowConnection(0); Assert.assertEquals(1, factory.creates); conn[1] = manager.borrowConnection(0); manager.returnConnection(conn[0]); manager.returnConnection(conn[1]); Assert.assertEquals(2, factory.creates); conn[0] = manager.borrowConnection(0); conn[1] = manager.borrowConnection(0); conn[2] = manager.borrowConnection(0); Assert.assertEquals(3, factory.creates); try { conn[4] = manager.borrowConnection(10); fail("Should have received an all connections in use exception"); } catch (AllConnectionsInUseException e) { // expected exception } } @Test public void testPrefill() throws InterruptedException { manager = new ConnectionManagerImpl("pool", factory, endpointManager, 10, 2, -1, -1, logger, 60 * 1000, cancelCriterion, poolStats); manager.start(background); final String descrip = manager.toString(); WaitCriterion ev = new WaitCriterion() { public boolean done() { return factory.creates == 2 && factory.destroys == 0; } public String description() { return "waiting for manager " + descrip; } }; Wait.waitForCriterion(ev, 200, 200, true); } @Test public void testInvalidateConnection() throws InterruptedException, AllConnectionsInUseException, NoAvailableServersException { manager = new ConnectionManagerImpl("pool", factory, endpointManager, 10, 0, 0L, -1, logger, 60 * 1000, cancelCriterion, poolStats); manager.start(background); Connection conn = manager.borrowConnection(0); Assert.assertEquals(1, factory.creates); Assert.assertEquals(0, factory.destroys); conn.destroy(); manager.returnConnection(conn); Assert.assertEquals(1, factory.creates); Assert.assertEquals(1, factory.destroys); conn = manager.borrowConnection(0); Assert.assertEquals(2, factory.creates); Assert.assertEquals(1, factory.destroys); } @Test public void testInvalidateServer() throws InterruptedException, AllConnectionsInUseException, NoAvailableServersException { manager = new ConnectionManagerImpl("pool", factory, endpointManager, 10, 0, -1, -1, logger, 60 * 1000, cancelCriterion, poolStats); manager.start(background); ServerLocation server1 = new ServerLocation("localhost", 1); ServerLocation server2 = new ServerLocation("localhost", 2); factory.nextServer = server1; Connection conn1 = manager.borrowConnection(0); Connection conn2 = manager.borrowConnection(0); Connection conn3 = manager.borrowConnection(0); factory.nextServer = server2; Connection conn4 = manager.borrowConnection(0); Assert.assertEquals(4, factory.creates); Assert.assertEquals(0, factory.destroys); manager.returnConnection(conn2); endpointManager.serverCrashed(conn2.getEndpoint()); Assert.assertEquals(3, factory.destroys); conn1.destroy(); manager.returnConnection(conn1); Assert.assertEquals(3, factory.destroys); manager.returnConnection(conn3); manager.returnConnection(conn4); Assert.assertEquals(3, factory.destroys); manager.borrowConnection(0); Assert.assertEquals(4, factory.creates); Assert.assertEquals(3, factory.destroys); } // public void testGetConnectionToSpecificServer() throws AllConnectionsInUseException, // NoAvailableServersException, InterruptedException { // DummySource source = new DummySource(); // manager = new ConnectionManager(source, factory, 10, -1, 10, logger, logger); // manager.start(); // // source.nextServer = new ServerLocation("localhost", 10); // Connection conn1 = manager.borrowConnection(10); // manager.returnConnection(conn1); // // try { // Connection conn2 = manager.borrowConnection(new ServerLocation("locahost", 20), 10); // Assert.fail("Should have received no servers available, because we asked for a server we can't // get"); // } catch(NoAvailableServersException expected) { // // } // // } @Test public void testIdleExpiration() throws InterruptedException, AllConnectionsInUseException, NoAvailableServersException { final long nanoToMillis = 1000000; final long idleTimeout = 300; manager = new ConnectionManagerImpl("pool", factory, endpointManager, 5, 2, idleTimeout, -1, logger, 60 * 1000, cancelCriterion, poolStats); manager.start(background); { long start = System.currentTimeMillis(); synchronized (factory) { long remaining = TIMEOUT; while (factory.creates < 2 && remaining > 0) { factory.wait(remaining); remaining = TIMEOUT - (System.currentTimeMillis() - start); } } Assert.assertEquals(2, factory.creates); Assert.assertEquals(0, factory.destroys); Assert.assertEquals(0, factory.closes); Assert.assertEquals(0, poolStats.getIdleExpire()); // no need to wait; dangerous because it gives connections a chance to expire // //wait for prefill task to finish. // Thread.sleep(100); } Connection conn1 = manager.borrowConnection(500); Connection conn2 = manager.borrowConnection(500); Connection conn3 = manager.borrowConnection(500); Connection conn4 = manager.borrowConnection(500); Connection conn5 = manager.borrowConnection(500); // wait to make sure checked out connections aren't timed out Thread.sleep(idleTimeout * 2); Assert.assertEquals(5, factory.creates); Assert.assertEquals(0, factory.destroys); Assert.assertEquals(0, factory.closes); Assert.assertEquals(0, poolStats.getIdleExpire()); long startInNanos = System.nanoTime(); { // make sure a thread local connection that has been passivated can idle-expire manager.passivate(conn1, true); synchronized (factory) { long waitTime = TIMEOUT * nanoToMillis + startInNanos; while (factory.destroys < 1 && (waitTime - System.nanoTime()) > 0) { factory.wait(idleTimeout); } } long elapsed = (System.nanoTime() - startInNanos) / nanoToMillis; Assert.assertTrue("Elapsed " + elapsed + " is less than idle timeout " + idleTimeout, elapsed >= idleTimeout && elapsed <= idleTimeout + 100); Assert.assertEquals(5, factory.creates); Assert.assertEquals(1, factory.destroys); Assert.assertEquals(1, factory.closes); Assert.assertEquals(1, poolStats.getIdleExpire()); } startInNanos = System.nanoTime(); // now return all other connections to pool and verify that just 2 expire manager.returnConnection(conn2); manager.returnConnection(conn3); manager.returnConnection(conn4); manager.returnConnection(conn5); { synchronized (factory) { long waitTime = TIMEOUT * nanoToMillis + startInNanos; while (factory.destroys < 3 && (waitTime - System.nanoTime()) > 0) { factory.wait(idleTimeout); } } long elapsed = (System.nanoTime() - startInNanos) / nanoToMillis; Assert.assertTrue("Elapsed " + elapsed + " is less than idle timeout " + idleTimeout, elapsed >= idleTimeout && elapsed <= idleTimeout + 100); Assert.assertEquals(5, factory.creates); Assert.assertEquals(3, factory.destroys); Assert.assertEquals(3, factory.closes); Assert.assertEquals(3, poolStats.getIdleExpire()); } // wait to make sure min-connections don't time out Thread.sleep(idleTimeout * 2); Assert.assertEquals(5, factory.creates); Assert.assertEquals(3, factory.destroys); Assert.assertEquals(3, factory.closes); Assert.assertEquals(3, poolStats.getIdleExpire()); } @Test public void testBug41516() throws InterruptedException, AllConnectionsInUseException, NoAvailableServersException { final long idleTimeout = 300; manager = new ConnectionManagerImpl("pool", factory, endpointManager, 2, 1, idleTimeout, -1, logger, 60 * 1000, cancelCriterion, poolStats); manager.start(background); Connection conn1 = manager.borrowConnection(500); Connection conn2 = manager.borrowConnection(500); // Return some connections, let them idle expire manager.returnConnection(conn1); manager.returnConnection(conn2); { long start = System.currentTimeMillis(); synchronized (factory) { long remaining = TIMEOUT; while (factory.destroys < 1 && remaining > 0) { factory.wait(remaining); remaining = TIMEOUT - (System.currentTimeMillis() - start); } } long elapsed = System.currentTimeMillis() - start; Assert.assertTrue("Elapsed " + elapsed + " is less than idle timeout " + idleTimeout, elapsed + ALLOWABLE_ERROR_IN_EXPIRATION >= idleTimeout); Assert.assertEquals(1, factory.destroys); Assert.assertEquals(1, factory.closes); Assert.assertEquals(1, poolStats.getIdleExpire()); } // Ok, now get some connections that fill our queue Connection ping1 = manager.borrowConnection(new ServerLocation("localhost", 5), 500, false); Connection ping2 = manager.borrowConnection(new ServerLocation("localhost", 5), 500, false); manager.returnConnection(ping1); manager.returnConnection(ping2); Connection conn3 = manager.borrowConnection(500); Connection conn4 = manager.borrowConnection(500); long start = System.currentTimeMillis(); try { Connection conn5 = manager.borrowConnection(500); fail("Didn't get an exception"); } catch (AllConnectionsInUseException e) { // expected } long elapsed = System.currentTimeMillis() - start; Assert.assertTrue("Elapsed = " + elapsed, elapsed >= 500); } @Test public void testLifetimeExpiration() throws InterruptedException, AllConnectionsInUseException, NoAvailableServersException, Throwable { int lifetimeTimeout = 500; manager = new ConnectionManagerImpl("pool", factory, endpointManager, 2, 2, -1, lifetimeTimeout, logger, 60 * 1000, cancelCriterion, poolStats); manager.start(background); { long start = System.currentTimeMillis(); synchronized (factory) { long remaining = TIMEOUT; while (factory.creates < 2 && remaining > 0) { factory.wait(remaining); remaining = TIMEOUT - (System.currentTimeMillis() - start); } } Assert.assertEquals(2, factory.creates); Assert.assertEquals(0, factory.destroys); Assert.assertEquals(0, factory.finds); } // need to start a thread that keeps the connections busy // so that their last access time keeps changing AtomicReference exception = new AtomicReference(); int updaterCount = 2; UpdaterThread[] updaters = new UpdaterThread[updaterCount]; for (int i = 0; i < updaterCount; i++) { updaters[i] = new UpdaterThread(null, exception, i, (lifetimeTimeout / 10) * 2, true); } for (int i = 0; i < updaterCount; i++) { updaters[i].start(); } { long start = System.currentTimeMillis(); synchronized (factory) { long remaining = TIMEOUT; while (factory.finds < 2 && remaining > 0) { factory.wait(remaining); remaining = TIMEOUT - (System.currentTimeMillis() - start); } } long end = System.currentTimeMillis(); Assert.assertEquals(2, factory.finds); // server shouldn't have changed so no increase in creates or destroys Assert.assertEquals(2, factory.creates); Assert.assertEquals(0, factory.destroys); Assert.assertEquals(0, factory.closes); Assert.assertTrue("took too long to expire lifetime; expected=" + lifetimeTimeout + " but took=" + (end - start), (end - start) < lifetimeTimeout * 2); } for (int i = 0; i < updaterCount; i++) { ThreadUtils.join(updaters[i], 30 * 1000); } if (exception.get() != null) { throw (Throwable) exception.get(); } for (int i = 0; i < updaterCount; i++) { Assert.assertFalse("Updater [" + i + "] is still running", updaters[i].isAlive()); } // //wait for prefill task to finish. // Thread.sleep(100); // Connection conn1 = manager.borrowConnection(0); // Connection conn2 = manager.borrowConnection(0); // Connection conn3 = manager.borrowConnection(0); // Connection conn4 = manager.borrowConnection(0); // Connection conn5 = manager.borrowConnection(0); // //wait to make sure checked out connections aren't timed out // Thread.sleep(idleTimeout + 100); // Assert.assertIndexDetailsEquals(5,factory.creates); // Assert.assertIndexDetailsEquals(0,factory.destroys); // manager.returnConnection(conn1); // manager.returnConnection(conn2); // manager.returnConnection(conn3); // manager.returnConnection(conn4); // manager.returnConnection(conn5); // long start = System.currentTimeMillis(); // synchronized(factory) { // while(factory.destroys < 3 && remaining > 0) { // factory.wait(remaining); // remaining = TIMEOUT - (System.currentTimeMillis() - start); // } // } // long elapsed = System.currentTimeMillis() - start; // Assert.assertTrue(elapsed > idleTimeout); // Assert.assertIndexDetailsEquals(5,factory.creates); // Assert.assertIndexDetailsEquals(3,factory.destroys); } @Test public void testExclusiveConnectionAccess() throws Throwable { manager = new ConnectionManagerImpl("pool", factory, endpointManager, 1, 0, -1, -1, logger, 60 * 1000, cancelCriterion, poolStats); manager.start(background); AtomicReference exception = new AtomicReference(); AtomicBoolean haveConnection = new AtomicBoolean(); int updaterCount = 10; UpdaterThread[] updaters = new UpdaterThread[updaterCount]; for (int i = 0; i < updaterCount; i++) { updaters[i] = new UpdaterThread(haveConnection, exception, i); } for (int i = 0; i < updaterCount; i++) { updaters[i].start(); } for (int i = 0; i < updaterCount; i++) { ThreadUtils.join(updaters[i], 30 * 1000); } if (exception.get() != null) { throw (Throwable) exception.get(); } for (int i = 0; i < updaterCount; i++) { Assert.assertFalse("Updater [" + i + "] is still running", updaters[i].isAlive()); } } @Test public void testClose() throws AllConnectionsInUseException, NoAvailableServersException, InterruptedException { manager = new ConnectionManagerImpl("pool", factory, endpointManager, 10, 0, -1, -1, logger, 60 * 1000, cancelCriterion, poolStats); manager.start(background); Connection conn1 = manager.borrowConnection(0); manager.borrowConnection(0); manager.returnConnection(conn1); Assert.assertEquals(2, factory.creates); Assert.assertEquals(0, factory.destroys); manager.close(false); Assert.assertEquals(2, factory.closes); Assert.assertEquals(2, factory.destroys); } @Test public void testExchangeConnection() throws Exception { manager = new ConnectionManagerImpl("pool", factory, endpointManager, 2, 0, -1, -1, logger, 60 * 1000, cancelCriterion, poolStats); manager.start(background); Connection conn1 = manager.borrowConnection(10); Connection conn2 = manager.borrowConnection(10); try { manager.borrowConnection(10); fail("Exepected no servers available"); } catch (AllConnectionsInUseException e) { // expected } Assert.assertEquals(2, factory.creates); Assert.assertEquals(0, factory.destroys); Assert.assertEquals(2, manager.getConnectionCount()); Connection conn3 = manager.exchangeConnection(conn1, Collections.EMPTY_SET, 10); Assert.assertEquals(3, factory.creates); Assert.assertEquals(1, factory.destroys); Assert.assertEquals(2, manager.getConnectionCount()); manager.returnConnection(conn2); Assert.assertEquals(3, factory.creates); Assert.assertEquals(1, factory.destroys); Assert.assertEquals(2, manager.getConnectionCount()); Connection conn4 = manager.exchangeConnection(conn3, Collections.singleton(conn3.getServer()), 10); Assert.assertEquals(4, factory.creates); Assert.assertEquals(2, factory.destroys); Assert.assertEquals(2, manager.getConnectionCount()); manager.returnConnection(conn4); } @Test public void testBlocking() throws Throwable { manager = new ConnectionManagerImpl("pool", factory, endpointManager, 1, 0, -1, -1, logger, 60 * 1000, cancelCriterion, poolStats); manager.start(background); final Connection conn1 = manager.borrowConnection(10); long startTime = System.currentTimeMillis(); try { manager.borrowConnection(100); fail("Should have received no servers available"); } catch (AllConnectionsInUseException expected) { } long elapsed = System.currentTimeMillis() - startTime; Assert.assertTrue("Should have blocked for 100 millis for a connection", elapsed >= 100); Thread returnThread = new Thread() { public void run() { try { Thread.sleep(50); } catch (InterruptedException e) { fail("interrupted"); } manager.returnConnection(conn1); } }; returnThread.start(); startTime = System.currentTimeMillis(); Connection conn2 = manager.borrowConnection(1000); elapsed = System.currentTimeMillis() - startTime; Assert.assertTrue("Should have blocked for less than 1 second", elapsed < 1000); manager.returnConnection(conn2); final Connection conn3 = manager.borrowConnection(10); Thread invalidateThread = new Thread() { public void run() { try { Thread.sleep(50); } catch (InterruptedException e) { fail("interrupted"); } conn3.destroy(); manager.returnConnection(conn3); } }; invalidateThread.start(); startTime = System.currentTimeMillis(); conn2 = manager.borrowConnection(1000); elapsed = System.currentTimeMillis() - startTime; Assert.assertTrue("Should have blocked for less than 1 second", elapsed < 1000); manager.returnConnection(conn2); final Connection conn4 = manager.borrowConnection(10); Thread invalidateThread2 = new Thread() { public void run() { try { Thread.sleep(50); } catch (InterruptedException e) { fail("interrupted"); } endpointManager.serverCrashed(conn4.getEndpoint()); manager.returnConnection(conn4); } }; invalidateThread2.start(); startTime = System.currentTimeMillis(); conn2 = manager.borrowConnection(1000); elapsed = System.currentTimeMillis() - startTime; Assert.assertTrue("Should have blocked for less than 1 second", elapsed < 1000); manager.returnConnection(conn2); } @Test public void testExplicitServer() throws Exception { manager = new ConnectionManagerImpl("pool", factory, endpointManager, 1, 0, -1, -1, logger, 60 * 1000, cancelCriterion, poolStats); manager.start(background); Connection conn1 = manager.borrowConnection(0); try { manager.borrowConnection(10); fail("Should have received an error"); } catch (AllConnectionsInUseException expected) { // do nothing } Connection conn3 = manager.borrowConnection(new ServerLocation("localhost", -2), 10, false); Assert.assertEquals(2, factory.creates); Assert.assertEquals(0, factory.destroys); Assert.assertEquals(0, factory.closes); manager.returnConnection(conn3); Assert.assertEquals(2, factory.creates); Assert.assertEquals(1, factory.destroys); Assert.assertEquals(1, factory.closes); manager.returnConnection(conn1); Assert.assertEquals(2, factory.creates); Assert.assertEquals(1, factory.destroys); Assert.assertEquals(1, factory.closes); } private class UpdaterThread extends Thread { private AtomicReference exception; private final AtomicBoolean haveConnection; private int id; private final int iterations; /** * If true then obtain the connection as if it is a thread local one */ private final boolean threadLocal; public UpdaterThread(AtomicBoolean haveConnection, AtomicReference exception, int id) { this(haveConnection, exception, id, 10, false); } public UpdaterThread(AtomicBoolean haveConnection, AtomicReference exception, int id, int iterations, boolean threadLocal) { this.haveConnection = haveConnection; this.exception = exception; this.id = id; this.iterations = iterations; this.threadLocal = threadLocal; } private Connection borrow(int i) { long startTime = System.currentTimeMillis(); Connection conn = manager.borrowConnection(2000); if (haveConnection != null) { Assert.assertTrue("Updater[" + id + "] loop[" + i + "] Someone else has the connection!", haveConnection.compareAndSet(false, true)); } long elapsed = System.currentTimeMillis() - startTime; if (elapsed >= 2000) { Assert.assertTrue("Elapsed time (" + elapsed + ") >= 2000", false); } return conn; } public void run() { int i = 0; Connection conn = null; try { if (threadLocal) { conn = borrow(-1); } for (i = 0; i < iterations; i++) { if (!threadLocal) { conn = borrow(i); } else { if (i != 0) { manager.activate(conn); } } try { Thread.sleep(10); if (haveConnection != null) { Assert.assertTrue( "Updater[" + id + "] loop[" + i + "] Someone else changed the connection flag", haveConnection.compareAndSet(true, false)); } } finally { if (!threadLocal) { manager.returnConnection(conn); } else { manager.passivate(conn, true); } } } } catch (Throwable t) { this.exception.compareAndSet(null, new Exception("ERROR Updater[" + id + "] loop[" + i + "]", t)); } finally { if (threadLocal && conn != null) { manager.returnConnection(conn); } } } } public class DummyFactory implements ConnectionFactory { public ServerLocation nextServer = new ServerLocation("localhost", -1); protected volatile int creates; protected volatile int destroys; protected volatile int closes; protected volatile int finds; public ServerBlackList getBlackList() { return new ServerBlackList(1); } public ServerLocation findBestServer(ServerLocation currentServer, Set excludedServers) { synchronized (this) { finds++; this.notifyAll(); } if (excludedServers != null) { if (excludedServers.contains(nextServer)) { return null; } } return nextServer; } public Connection createClientToServerConnection(Set excluded) { return createClientToServerConnection(nextServer, true); } /* * (non-Javadoc) * * @see * org.apache.geode.cache.client.internal.ConnectionFactory#createClientToServerConnection(org. * apache.geode.distributed.internal.ServerLocation) */ public Connection createClientToServerConnection(final ServerLocation location, boolean forQueue) { synchronized (this) { creates++; this.notifyAll(); } DistributedMember fakeMember = null; fakeMember = new InternalDistributedMember("localhost", 555); final DistributedMember member = fakeMember; return new Connection() { private Endpoint endpoint = endpointManager.referenceEndpoint(location, member); public void destroy() { synchronized (DummyFactory.this) { destroys++; DummyFactory.this.notifyAll(); } } public ServerLocation getServer() { return location; } public ByteBuffer getCommBuffer() { return null; } public Socket getSocket() { return null; } public ConnectionStats getStats() { return null; } public void close(boolean keepAlive) throws Exception { synchronized (DummyFactory.this) { closes++; DummyFactory.this.notifyAll(); } } public Endpoint getEndpoint() { return endpoint; } public ServerQueueStatus getQueueStatus() { return null; } public Object execute(Op op) throws Exception { return op.attempt(this); } public boolean isDestroyed() { return false; } public void emergencyClose() {} public short getWanSiteVersion() { return -1; } public int getDistributedSystemId() { return -1; } public void setWanSiteVersion(short wanSiteVersion) {} public InputStream getInputStream() { return null; } public OutputStream getOutputStream() { return null; } public void setConnectionID(long id) {} public long getConnectionID() { return 0; } }; } public ClientUpdater createServerToClientConnection(Endpoint endpoint, QueueManager manager, boolean isPrimary, ClientUpdater failedUpdater) { return null; } } }