One of the The Architect's developers laid the egg that is this round-robin connection pooling code. He discovered this when he noticed that his connection was getting incorrect responses under load.
public class RoundRobinConnectionContainer { private static final Logger LOG = Logger.getLogger( RoundRobinConnectionContainer.class ); private int useNext = 0; private List<BehaviorEngineConnection> connections = Collections.synchronizedList(new ArrayList<BehaviorEngineConnection>()); // Find the index of the next connection to try public int getNextIndex() { if (useNext > this.connections.size() - 1) { useNext = 0; } return( this.useNext++ ); } public void addConnection(BehaviorEngineConnection connection) { connections.add(connection); } public BehaviorEngineConnection getConnectedConnection() { int size = this.connections.size(); while (size-- > 0) { BehaviorEngineConnection conn = connections.get(getNextIndex()); if (conn.isConnected()) { return conn; } LOG.error("No connected connection available!"); return null; } } }
Hmmm, let's see. The function getNextIndex() is public, potentially leading to all sorts of indexing fun, depending upon when and how it's called elsewhere. Most importantly, a connected connection is returned from getConnectedConnection(). Depending upon the size of your pool, the number of times it's called, and for how long the connection is used by the caller, the same connection can get returned to multiple callers. Debugging fun!