Skip to content

Commit e8732a5

Browse files
committed
<fix>[core]: synchronize nodeHash and nodes to prevent race condition in dual-MN hash ring
Resolves: ZSTAC-77711 Change-Id: I000273d162bd7f129256904c14c75d4d6e60cb18
1 parent 1d41921 commit e8732a5

1 file changed

Lines changed: 53 additions & 31 deletions

File tree

core/src/main/java/org/zstack/core/cloudbus/ResourceDestinationMakerImpl.java

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,47 +22,58 @@
2222
public class ResourceDestinationMakerImpl implements ManagementNodeChangeListener, ResourceDestinationMaker {
2323
private final ConsistentHash<String> nodeHash = new ConsistentHash<>(new ApacheHash(), 500, new ArrayList<String>()) ;
2424
private final Map<String, NodeInfo> nodes = new HashMap<>();
25+
private final Object lock = new Object();
2526

2627
@Autowired
2728
private DatabaseFacade dbf;
2829

2930
@Override
3031
public void nodeJoin(ManagementNodeInventory inv) {
31-
nodeHash.add(inv.getUuid());
32-
nodes.put(inv.getUuid(), new NodeInfo(inv));
32+
synchronized (lock) {
33+
nodeHash.add(inv.getUuid());
34+
nodes.put(inv.getUuid(), new NodeInfo(inv));
35+
}
3336
}
3437

3538
@Override
3639
public void nodeLeft(ManagementNodeInventory inv) {
37-
String nodeId = inv.getUuid();
38-
nodeHash.remove(nodeId);
39-
nodes.remove(nodeId);
40+
synchronized (lock) {
41+
String nodeId = inv.getUuid();
42+
nodeHash.remove(nodeId);
43+
nodes.remove(nodeId);
44+
}
4045
}
4146

4247
@Override
4348
public void iAmDead(ManagementNodeInventory inv) {
44-
String nodeId = inv.getUuid();
45-
nodeHash.remove(nodeId);
46-
nodes.remove(nodeId);
49+
synchronized (lock) {
50+
String nodeId = inv.getUuid();
51+
nodeHash.remove(nodeId);
52+
nodes.remove(nodeId);
53+
}
4754
}
4855

4956
@Override
5057
public void iJoin(ManagementNodeInventory inv) {
51-
List<ManagementNodeVO> lst = Q.New(ManagementNodeVO.class).list();
52-
lst.forEach((ManagementNodeVO node) -> {
53-
nodeHash.add(node.getUuid());
54-
nodes.put(node.getUuid(), new NodeInfo(node));
55-
});
58+
synchronized (lock) {
59+
List<ManagementNodeVO> lst = Q.New(ManagementNodeVO.class).list();
60+
lst.forEach((ManagementNodeVO node) -> {
61+
nodeHash.add(node.getUuid());
62+
nodes.put(node.getUuid(), new NodeInfo(node));
63+
});
64+
}
5665
}
5766

5867
@Override
5968
public String makeDestination(String resourceUuid) {
60-
String nodeUuid = nodeHash.get(resourceUuid);
61-
if (nodeUuid == null) {
62-
throw new CloudRuntimeException("Cannot find any available management node to send message");
63-
}
69+
synchronized (lock) {
70+
String nodeUuid = nodeHash.get(resourceUuid);
71+
if (nodeUuid == null) {
72+
throw new CloudRuntimeException("Cannot find any available management node to send message");
73+
}
6474

65-
return nodeUuid;
75+
return nodeUuid;
76+
}
6677
}
6778

6879
@Override
@@ -73,37 +84,48 @@ public boolean isManagedByUs(String resourceUuid) {
7384

7485
@Override
7586
public Collection<String> getManagementNodesInHashRing() {
76-
return nodeHash.getNodes();
87+
synchronized (lock) {
88+
return new ArrayList<>(nodeHash.getNodes());
89+
}
7790
}
7891

7992
@Override
8093
public NodeInfo getNodeInfo(String nodeUuid) {
81-
NodeInfo info = nodes.get(nodeUuid);
82-
if (info == null) {
83-
ManagementNodeVO vo = dbf.findByUuid(nodeUuid, ManagementNodeVO.class);
84-
if (vo == null) {
85-
throw new ManagementNodeNotFoundException(nodeUuid);
94+
synchronized (lock) {
95+
NodeInfo info = nodes.get(nodeUuid);
96+
if (info == null) {
97+
ManagementNodeVO vo = dbf.findByUuid(nodeUuid, ManagementNodeVO.class);
98+
if (vo == null) {
99+
throw new ManagementNodeNotFoundException(nodeUuid);
100+
}
101+
102+
nodeHash.add(nodeUuid);
103+
info = new NodeInfo(vo);
104+
nodes.put(nodeUuid, info);
86105
}
87106

88-
nodeHash.add(nodeUuid);
89-
info = nodes.put(nodeUuid, new NodeInfo(vo));
107+
return info;
90108
}
91-
92-
return info;
93109
}
94110

95111
@Override
96112
public Collection<NodeInfo> getAllNodeInfo() {
97-
return nodes.values();
113+
synchronized (lock) {
114+
return new ArrayList<>(nodes.values());
115+
}
98116
}
99117

100118
@Override
101119
public int getManagementNodeCount() {
102-
return nodes.values().size();
120+
synchronized (lock) {
121+
return nodes.size();
122+
}
103123
}
104124

105125

106126
public boolean isNodeInCircle(String nodeId) {
107-
return nodeHash.hasNode(nodeId);
127+
synchronized (lock) {
128+
return nodeHash.hasNode(nodeId);
129+
}
108130
}
109131
}

0 commit comments

Comments
 (0)