Skip to content

Commit dfcd905

Browse files
committed
FIX: Concurrency problem in locator allNodes.
1 parent 715f73a commit dfcd905

2 files changed

Lines changed: 12 additions & 7 deletions

File tree

src/main/java/net/spy/memcached/ArcusKetamaNodeLocator.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
public class ArcusKetamaNodeLocator extends SpyObject implements NodeLocator {
4242

4343
private final TreeMap<Long, SortedSet<MemcachedNode>> ketamaNodes;
44-
private final Collection<MemcachedNode> allNodes;
44+
private Collection<MemcachedNode> allNodes;
4545

4646
/* ENABLE_MIGRATION if */
4747
private TreeMap<Long, SortedSet<MemcachedNode>> ketamaAlterNodes;
@@ -206,15 +206,16 @@ public void update(Collection<MemcachedNode> toAttach,
206206
Collection<MemcachedNode> toDelete) {
207207
lock.lock();
208208
try {
209+
ArrayList<MemcachedNode> newAllNodes = new ArrayList<>(allNodes);
209210
// Add memcached nodes.
210211
for (MemcachedNode node : toAttach) {
211-
allNodes.add(node);
212+
newAllNodes.add(node);
212213
insertHash(node);
213214
}
214215

215216
// Remove memcached nodes.
216217
for (MemcachedNode node : toDelete) {
217-
allNodes.remove(node);
218+
newAllNodes.remove(node);
218219
removeHash(node);
219220
try {
220221
node.closeChannel();
@@ -223,6 +224,7 @@ public void update(Collection<MemcachedNode> toAttach,
223224
"Failed to closeChannel the node : " + node);
224225
}
225226
}
227+
allNodes = newAllNodes;
226228
} finally {
227229
/* ENABLE_MIGRATION if */
228230
if (migrationInProgress && alterNodes.isEmpty()) {

src/main/java/net/spy/memcached/ArcusReplKetamaNodeLocator.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.util.SortedSet;
3333
import java.util.TreeMap;
3434
import java.util.TreeSet;
35+
import java.util.concurrent.CopyOnWriteArrayList;
3536
import java.util.concurrent.locks.Lock;
3637
import java.util.concurrent.locks.ReentrantLock;
3738

@@ -42,7 +43,7 @@ public class ArcusReplKetamaNodeLocator extends SpyObject implements NodeLocator
4243

4344
private final TreeMap<Long, SortedSet<MemcachedReplicaGroup>> ketamaGroups;
4445
private final HashMap<String, MemcachedReplicaGroup> allGroups;
45-
private final Collection<MemcachedNode> allNodes;
46+
private Collection<MemcachedNode> allNodes;
4647

4748
/* ENABLE_MIGRATION if */
4849
private TreeMap<Long, SortedSet<MemcachedReplicaGroup>> ketamaAlterGroups;
@@ -65,7 +66,7 @@ public class ArcusReplKetamaNodeLocator extends SpyObject implements NodeLocator
6566

6667
public ArcusReplKetamaNodeLocator(List<MemcachedNode> nodes) {
6768
super();
68-
allNodes = nodes;
69+
allNodes = new CopyOnWriteArrayList<>(nodes);
6970
ketamaGroups = new TreeMap<>();
7071
allGroups = new HashMap<>();
7172

@@ -251,9 +252,10 @@ public void update(Collection<MemcachedNode> toAttach,
251252
*/
252253
lock.lock();
253254
try {
255+
ArrayList<MemcachedNode> newAllNodes = new ArrayList<>(allNodes);
254256
// Remove memcached nodes.
255257
for (MemcachedNode node : toDelete) {
256-
allNodes.remove(node);
258+
newAllNodes.remove(node);
257259
removeNodeFromGroup(node);
258260
try {
259261
node.closeChannel();
@@ -269,7 +271,7 @@ public void update(Collection<MemcachedNode> toAttach,
269271

270272
// Add memcached nodes.
271273
for (MemcachedNode node : toAttach) {
272-
allNodes.add(node);
274+
newAllNodes.add(node);
273275
insertNodeIntoGroup(node);
274276
}
275277

@@ -280,6 +282,7 @@ public void update(Collection<MemcachedNode> toAttach,
280282
removeHash(group);
281283
}
282284
toDeleteGroups.clear();
285+
allNodes = newAllNodes;
283286
} finally {
284287
/* ENABLE_MIGRATION if */
285288
if (migrationInProgress && alterNodes.isEmpty()) {

0 commit comments

Comments
 (0)