Skip to content

Commit fca57b0

Browse files
committed
HostConnectionPool: share excessive connections between ConnectionTasks
Previously each ConnectionTask was keeping its own excessive connections (connections that are not to the shard it wants). This patch changes the behaviour so that all ConnectionTasks share excessive connections. This way we not only better limit number of excessive connections but also will quicker find the right connection for each task (some other task may open a connection for it). Signed-off-by: Piotr Jastrzebski <haaawk@gmail.com>
1 parent ca3dec8 commit fca57b0

1 file changed

Lines changed: 70 additions & 19 deletions

File tree

driver-core/src/main/java/com/datastax/driver/core/HostConnectionPool.java

Lines changed: 70 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@
3838
import java.nio.ByteBuffer;
3939
import java.util.ArrayList;
4040
import java.util.Collection;
41+
import java.util.HashMap;
4142
import java.util.List;
43+
import java.util.Map;
4244
import java.util.Queue;
4345
import java.util.Random;
4446
import java.util.Set;
@@ -97,7 +99,60 @@ private enum Phase {
9799

98100
protected final AtomicReference<Phase> phase = new AtomicReference<Phase>(Phase.INITIALIZING);
99101

102+
public static class ConnectionTasksSharedState {
103+
private final Object lock = new Object();
104+
private int tasksInFlight = 0;
105+
private Map<Integer, Connection> connectionsToClose = new HashMap<Integer, Connection>();
106+
107+
public Connection registerTask(int shardId) {
108+
Connection c = null;
109+
synchronized (lock) {
110+
c = connectionsToClose.remove(shardId);
111+
if (c == null) {
112+
++tasksInFlight;
113+
}
114+
}
115+
return c;
116+
}
117+
118+
public void unregisterTask() {
119+
Map<Integer, Connection> toClose = null;
120+
synchronized (lock) {
121+
--tasksInFlight;
122+
if (tasksInFlight == 0) {
123+
toClose = connectionsToClose;
124+
connectionsToClose = new HashMap<Integer, Connection>();
125+
}
126+
}
127+
if (toClose != null) {
128+
for (Connection c : toClose.values()) {
129+
c.closeAsync();
130+
}
131+
}
132+
}
133+
134+
public Connection addConnectionToClose(int shardId, Connection c) {
135+
Connection res = null;
136+
boolean close = false;
137+
synchronized (lock) {
138+
res = connectionsToClose.remove(shardId);
139+
close = connectionsToClose.get(c.shardId()) != null;
140+
if (!close) {
141+
connectionsToClose.put(c.shardId(), c);
142+
}
143+
}
144+
if (close) {
145+
c.closeAsync();
146+
}
147+
return res;
148+
}
149+
}
150+
151+
private final ConnectionTasksSharedState connectionTasksSharedState =
152+
new ConnectionTasksSharedState();
153+
100154
private class ConnectionTask implements Runnable {
155+
101156
private final int shardId;
102157

103158
public ConnectionTask(int shardId) {
@@ -106,7 +161,7 @@ public ConnectionTask(int shardId) {
106161

107162
@Override
108163
public void run() {
109-
addConnectionIfUnderMaximum(shardId);
164+
addConnectionIfUnderMaximum(shardId, connectionTasksSharedState);
110165
scheduledForCreation[shardId].decrementAndGet();
111166
}
112167
}
@@ -585,7 +640,7 @@ private void doTrashConnection(Connection connection) {
585640
trash[connection.shardId()].add(connection);
586641
}
587642

588-
private boolean addConnectionIfUnderMaximum(int shardId) {
643+
private boolean addConnectionIfUnderMaximum(int shardId, ConnectionTasksSharedState sharedState) {
589644

590645
// First, make sure we don't cross the allowed limit of open connections
591646
for (; ; ) {
@@ -609,23 +664,19 @@ private boolean addConnectionIfUnderMaximum(int shardId) {
609664
return false;
610665
}
611666
logger.debug("Creating new connection on busy pool to {}", host);
612-
List<Connection> toClose = new ArrayList<Connection>();
613-
try {
614-
while (true) {
615-
newConnection = manager.connectionFactory().open(this);
616-
if (newConnection.shardId() == shardId) {
617-
newConnection.setKeyspace(manager.poolsState.keyspace);
618-
break;
619-
}
620-
if (toClose.size() < connections.length) {
621-
toClose.add(newConnection);
622-
} else {
623-
newConnection.closeAsync();
624-
}
625-
}
626-
} finally {
627-
for (Connection c : toClose) {
628-
c.closeAsync();
667+
newConnection = sharedState.registerTask(shardId);
668+
if (newConnection == null) {
669+
try {
670+
do {
671+
newConnection = manager.connectionFactory().open(this);
672+
if (newConnection.shardId() == shardId) {
673+
newConnection.setKeyspace(manager.poolsState.keyspace);
674+
} else {
675+
newConnection = sharedState.addConnectionToClose(shardId, newConnection);
676+
}
677+
} while (newConnection == null);
678+
} finally {
679+
sharedState.unregisterTask();
629680
}
630681
}
631682
}

0 commit comments

Comments
 (0)