Further simplified the store & connection manager relationship.
Showing
16 changed files
with
277 additions
and
345 deletions
1 | -package org.onlab.onos.ccc; | ||
2 | - | ||
3 | -import com.fasterxml.jackson.core.JsonEncoding; | ||
4 | -import com.fasterxml.jackson.core.JsonFactory; | ||
5 | -import com.fasterxml.jackson.databind.JsonNode; | ||
6 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
7 | -import com.fasterxml.jackson.databind.node.ArrayNode; | ||
8 | -import com.fasterxml.jackson.databind.node.ObjectNode; | ||
9 | -import org.onlab.onos.cluster.DefaultControllerNode; | ||
10 | -import org.onlab.onos.cluster.NodeId; | ||
11 | -import org.onlab.packet.IpPrefix; | ||
12 | - | ||
13 | -import java.io.File; | ||
14 | -import java.io.IOException; | ||
15 | -import java.util.HashSet; | ||
16 | -import java.util.Iterator; | ||
17 | -import java.util.Set; | ||
18 | - | ||
19 | -/** | ||
20 | - * Allows for reading and writing cluster definition as a JSON file. | ||
21 | - */ | ||
22 | -public class ClusterDefinitionStore { | ||
23 | - | ||
24 | - private final File file; | ||
25 | - | ||
26 | - /** | ||
27 | - * Creates a reader/writer of the cluster definition file. | ||
28 | - * | ||
29 | - * @param filePath location of the definition file | ||
30 | - */ | ||
31 | - public ClusterDefinitionStore(String filePath) { | ||
32 | - file = new File(filePath); | ||
33 | - } | ||
34 | - | ||
35 | - /** | ||
36 | - * Returns set of the controller nodes, including self. | ||
37 | - * | ||
38 | - * @return set of controller nodes | ||
39 | - */ | ||
40 | - public Set<DefaultControllerNode> read() throws IOException { | ||
41 | - Set<DefaultControllerNode> nodes = new HashSet<>(); | ||
42 | - ObjectMapper mapper = new ObjectMapper(); | ||
43 | - ObjectNode clusterNodeDef = (ObjectNode) mapper.readTree(file); | ||
44 | - Iterator<JsonNode> it = ((ArrayNode) clusterNodeDef.get("nodes")).elements(); | ||
45 | - while (it.hasNext()) { | ||
46 | - ObjectNode nodeDef = (ObjectNode) it.next(); | ||
47 | - nodes.add(new DefaultControllerNode(new NodeId(nodeDef.get("id").asText()), | ||
48 | - IpPrefix.valueOf(nodeDef.get("ip").asText()), | ||
49 | - nodeDef.get("tcpPort").asInt(9876))); | ||
50 | - } | ||
51 | - return nodes; | ||
52 | - } | ||
53 | - | ||
54 | - /** | ||
55 | - * Writes the given set of the controller nodes. | ||
56 | - * | ||
57 | - * @param nodes set of controller nodes | ||
58 | - */ | ||
59 | - public void write(Set<DefaultControllerNode> nodes) throws IOException { | ||
60 | - ObjectMapper mapper = new ObjectMapper(); | ||
61 | - ObjectNode clusterNodeDef = mapper.createObjectNode(); | ||
62 | - ArrayNode nodeDefs = mapper.createArrayNode(); | ||
63 | - clusterNodeDef.set("nodes", nodeDefs); | ||
64 | - for (DefaultControllerNode node : nodes) { | ||
65 | - ObjectNode nodeDef = mapper.createObjectNode(); | ||
66 | - nodeDef.put("id", node.id().toString()) | ||
67 | - .put("ip", node.ip().toString()) | ||
68 | - .put("tcpPort", node.tcpPort()); | ||
69 | - nodeDefs.add(nodeDef); | ||
70 | - } | ||
71 | - mapper.writeTree(new JsonFactory().createGenerator(file, JsonEncoding.UTF8), | ||
72 | - clusterNodeDef); | ||
73 | - } | ||
74 | - | ||
75 | -} |
1 | +package org.onlab.onos.store.cluster.impl; | ||
2 | + | ||
3 | +import org.onlab.onos.cluster.DefaultControllerNode; | ||
4 | + | ||
5 | +/** | ||
6 | + * Service for administering communications manager. | ||
7 | + */ | ||
8 | +public interface ClusterCommunicationAdminService { | ||
9 | + | ||
10 | + /** | ||
11 | + * Adds the node to the list of monitored nodes. | ||
12 | + * | ||
13 | + * @param node node to be added | ||
14 | + */ | ||
15 | + void addNode(DefaultControllerNode node); | ||
16 | + | ||
17 | + /** | ||
18 | + * Removes the node from the list of monitored nodes. | ||
19 | + * | ||
20 | + * @param node node to be removed | ||
21 | + */ | ||
22 | + void removeNode(DefaultControllerNode node); | ||
23 | + | ||
24 | + /** | ||
25 | + * Starts-up the communications engine. | ||
26 | + * | ||
27 | + * @param localNode local controller node | ||
28 | + * @param delegate nodes delegate | ||
29 | + */ | ||
30 | + void startUp(DefaultControllerNode localNode, ClusterNodesDelegate delegate); | ||
31 | + | ||
32 | +} |
1 | package org.onlab.onos.store.cluster.impl; | 1 | package org.onlab.onos.store.cluster.impl; |
2 | 2 | ||
3 | +import com.google.common.collect.HashMultimap; | ||
4 | +import com.google.common.collect.ImmutableSet; | ||
5 | +import com.google.common.collect.Multimap; | ||
6 | +import org.apache.felix.scr.annotations.Activate; | ||
7 | +import org.apache.felix.scr.annotations.Component; | ||
8 | +import org.apache.felix.scr.annotations.Deactivate; | ||
9 | +import org.apache.felix.scr.annotations.Reference; | ||
10 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
11 | +import org.apache.felix.scr.annotations.Service; | ||
3 | import org.onlab.onos.cluster.DefaultControllerNode; | 12 | import org.onlab.onos.cluster.DefaultControllerNode; |
4 | import org.onlab.onos.cluster.NodeId; | 13 | import org.onlab.onos.cluster.NodeId; |
14 | +import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; | ||
5 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; | 15 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; |
6 | import org.onlab.onos.store.cluster.messaging.ClusterMessageStream; | 16 | import org.onlab.onos.store.cluster.messaging.ClusterMessageStream; |
7 | import org.onlab.onos.store.cluster.messaging.HelloMessage; | 17 | import org.onlab.onos.store.cluster.messaging.HelloMessage; |
18 | +import org.onlab.onos.store.cluster.messaging.MessageSubject; | ||
19 | +import org.onlab.onos.store.cluster.messaging.MessageSubscriber; | ||
8 | import org.onlab.onos.store.cluster.messaging.SerializationService; | 20 | import org.onlab.onos.store.cluster.messaging.SerializationService; |
21 | +import org.onlab.packet.IpPrefix; | ||
9 | import org.slf4j.Logger; | 22 | import org.slf4j.Logger; |
10 | import org.slf4j.LoggerFactory; | 23 | import org.slf4j.LoggerFactory; |
11 | 24 | ||
... | @@ -28,9 +41,12 @@ import static java.net.InetAddress.getByAddress; | ... | @@ -28,9 +41,12 @@ import static java.net.InetAddress.getByAddress; |
28 | import static org.onlab.util.Tools.namedThreads; | 41 | import static org.onlab.util.Tools.namedThreads; |
29 | 42 | ||
30 | /** | 43 | /** |
31 | - * Manages connections to other controller cluster nodes. | 44 | + * Implements the cluster communication services to use by other stores. |
32 | */ | 45 | */ |
33 | -public class ConnectionManager implements MessageSender { | 46 | +@Component(immediate = true) |
47 | +@Service | ||
48 | +public class ClusterCommunicationManager | ||
49 | + implements ClusterCommunicationService, ClusterCommunicationAdminService { | ||
34 | 50 | ||
35 | private final Logger log = LoggerFactory.getLogger(getClass()); | 51 | private final Logger log = LoggerFactory.getLogger(getClass()); |
36 | 52 | ||
... | @@ -43,10 +59,11 @@ public class ConnectionManager implements MessageSender { | ... | @@ -43,10 +59,11 @@ public class ConnectionManager implements MessageSender { |
43 | private ClusterConnectionListener connectionListener; | 59 | private ClusterConnectionListener connectionListener; |
44 | private List<ClusterIOWorker> workers = new ArrayList<>(WORKERS); | 60 | private List<ClusterIOWorker> workers = new ArrayList<>(WORKERS); |
45 | 61 | ||
46 | - private final DefaultControllerNode localNode; | 62 | + private DefaultControllerNode localNode; |
47 | - private final ClusterNodesDelegate nodesDelegate; | 63 | + private ClusterNodesDelegate nodesDelegate; |
48 | - private final CommunicationsDelegate commsDelegate; | 64 | + |
49 | - private final SerializationService serializationService; | 65 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
66 | + protected SerializationService serializationService; | ||
50 | 67 | ||
51 | // Nodes to be monitored to make sure they have a connection. | 68 | // Nodes to be monitored to make sure they have a connection. |
52 | private final Set<DefaultControllerNode> nodes = new HashSet<>(); | 69 | private final Set<DefaultControllerNode> nodes = new HashSet<>(); |
... | @@ -54,6 +71,9 @@ public class ConnectionManager implements MessageSender { | ... | @@ -54,6 +71,9 @@ public class ConnectionManager implements MessageSender { |
54 | // Means to track message streams to other nodes. | 71 | // Means to track message streams to other nodes. |
55 | private final Map<NodeId, ClusterMessageStream> streams = new ConcurrentHashMap<>(); | 72 | private final Map<NodeId, ClusterMessageStream> streams = new ConcurrentHashMap<>(); |
56 | 73 | ||
74 | + // TODO: use something different that won't require synchronization | ||
75 | + private Multimap<MessageSubject, MessageSubscriber> subscribers = HashMultimap.create(); | ||
76 | + | ||
57 | // Executor pools for listening and managing connections to other nodes. | 77 | // Executor pools for listening and managing connections to other nodes. |
58 | private final ExecutorService listenExecutor = | 78 | private final ExecutorService listenExecutor = |
59 | Executors.newSingleThreadExecutor(namedThreads("onos-comm-listen")); | 79 | Executors.newSingleThreadExecutor(namedThreads("onos-comm-listen")); |
... | @@ -65,59 +85,110 @@ public class ConnectionManager implements MessageSender { | ... | @@ -65,59 +85,110 @@ public class ConnectionManager implements MessageSender { |
65 | private final Timer timer = new Timer("onos-comm-initiator"); | 85 | private final Timer timer = new Timer("onos-comm-initiator"); |
66 | private final TimerTask connectionCustodian = new ConnectionCustodian(); | 86 | private final TimerTask connectionCustodian = new ConnectionCustodian(); |
67 | 87 | ||
68 | - private final WorkerFinder workerFinder = new LeastUtilitiedWorkerFinder(); | 88 | + @Activate |
89 | + public void activate() { | ||
90 | + log.info("Activated but waiting for delegate"); | ||
91 | + } | ||
69 | 92 | ||
93 | + @Deactivate | ||
94 | + public void deactivate() { | ||
95 | + connectionCustodian.cancel(); | ||
96 | + if (connectionListener != null) { | ||
97 | + connectionListener.shutdown(); | ||
98 | + for (ClusterIOWorker worker : workers) { | ||
99 | + worker.shutdown(); | ||
100 | + } | ||
101 | + } | ||
102 | + log.info("Stopped"); | ||
103 | + } | ||
70 | 104 | ||
71 | - /** | 105 | + @Override |
72 | - * Creates a new connection manager. | 106 | + public boolean send(ClusterMessage message, NodeId toNodeId) { |
73 | - */ | 107 | + ClusterMessageStream stream = streams.get(toNodeId); |
74 | - ConnectionManager(DefaultControllerNode localNode, | 108 | + if (stream != null) { |
75 | - ClusterNodesDelegate nodesDelegate, | 109 | + try { |
76 | - CommunicationsDelegate commsDelegate, | 110 | + stream.write(message); |
77 | - SerializationService serializationService) { | 111 | + return true; |
112 | + } catch (IOException e) { | ||
113 | + log.warn("Unable to send message {} to node {}", | ||
114 | + message.subject(), toNodeId); | ||
115 | + } | ||
116 | + } | ||
117 | + return false; | ||
118 | + } | ||
119 | + | ||
120 | + @Override | ||
121 | + public synchronized void addSubscriber(MessageSubject subject, | ||
122 | + MessageSubscriber subscriber) { | ||
123 | + subscribers.put(subject, subscriber); | ||
124 | + } | ||
125 | + | ||
126 | + @Override | ||
127 | + public synchronized void removeSubscriber(MessageSubject subject, | ||
128 | + MessageSubscriber subscriber) { | ||
129 | + subscribers.remove(subject, subscriber); | ||
130 | + } | ||
131 | + | ||
132 | + @Override | ||
133 | + public Set<MessageSubscriber> getSubscribers(MessageSubject subject) { | ||
134 | + return ImmutableSet.copyOf(subscribers.get(subject)); | ||
135 | + } | ||
136 | + | ||
137 | + @Override | ||
138 | + public void addNode(DefaultControllerNode node) { | ||
139 | + nodes.add(node); | ||
140 | + } | ||
141 | + | ||
142 | + @Override | ||
143 | + public void removeNode(DefaultControllerNode node) { | ||
144 | + nodes.remove(node); | ||
145 | + ClusterMessageStream stream = streams.remove(node.id()); | ||
146 | + if (stream != null) { | ||
147 | + stream.close(); | ||
148 | + } | ||
149 | + } | ||
150 | + | ||
151 | + @Override | ||
152 | + public void startUp(DefaultControllerNode localNode, | ||
153 | + ClusterNodesDelegate delegate) { | ||
78 | this.localNode = localNode; | 154 | this.localNode = localNode; |
79 | - this.nodesDelegate = nodesDelegate; | 155 | + this.nodesDelegate = delegate; |
80 | - this.commsDelegate = commsDelegate; | ||
81 | - this.serializationService = serializationService; | ||
82 | 156 | ||
83 | - commsDelegate.setSender(this); | ||
84 | startCommunications(); | 157 | startCommunications(); |
85 | startListening(); | 158 | startListening(); |
86 | - startInitiating(); | 159 | + startInitiatingConnections(); |
87 | log.info("Started"); | 160 | log.info("Started"); |
88 | } | 161 | } |
89 | 162 | ||
90 | /** | 163 | /** |
91 | - * Shuts down the connection manager. | 164 | + * Dispatches the specified message to all subscribers to its subject. |
92 | - */ | ||
93 | - void shutdown() { | ||
94 | - connectionListener.shutdown(); | ||
95 | - for (ClusterIOWorker worker : workers) { | ||
96 | - worker.shutdown(); | ||
97 | - } | ||
98 | - log.info("Stopped"); | ||
99 | - } | ||
100 | - | ||
101 | - /** | ||
102 | - * Adds the node to the list of monitored nodes. | ||
103 | * | 165 | * |
104 | - * @param node node to be added | 166 | + * @param message message to dispatch |
167 | + * @param fromNodeId node from which the message was received | ||
105 | */ | 168 | */ |
106 | - void addNode(DefaultControllerNode node) { | 169 | + void dispatch(ClusterMessage message, NodeId fromNodeId) { |
107 | - nodes.add(node); | 170 | + Set<MessageSubscriber> set = getSubscribers(message.subject()); |
171 | + if (set != null) { | ||
172 | + for (MessageSubscriber subscriber : set) { | ||
173 | + subscriber.receive(message, fromNodeId); | ||
174 | + } | ||
175 | + } | ||
108 | } | 176 | } |
109 | 177 | ||
110 | /** | 178 | /** |
111 | - * Removes the node from the list of monitored nodes. | 179 | + * Removes the stream associated with the specified node. |
112 | * | 180 | * |
113 | - * @param node node to be removed | 181 | + * @param nodeId newly detected cluster node id |
182 | + * @param ip node IP listen address | ||
183 | + * @param tcpPort node TCP listen port | ||
184 | + * @return controller node bound to the stream | ||
114 | */ | 185 | */ |
115 | - void removeNode(DefaultControllerNode node) { | 186 | + DefaultControllerNode addNodeStream(NodeId nodeId, IpPrefix ip, int tcpPort, |
116 | - nodes.remove(node); | 187 | + ClusterMessageStream stream) { |
117 | - ClusterMessageStream stream = streams.remove(node.id()); | 188 | + DefaultControllerNode node = nodesDelegate.nodeDetected(nodeId, ip, tcpPort); |
118 | - if (stream != null) { | 189 | + stream.setNode(node); |
119 | - stream.close(); | 190 | + streams.put(node.id(), stream); |
120 | - } | 191 | + return node; |
121 | } | 192 | } |
122 | 193 | ||
123 | /** | 194 | /** |
... | @@ -126,23 +197,30 @@ public class ConnectionManager implements MessageSender { | ... | @@ -126,23 +197,30 @@ public class ConnectionManager implements MessageSender { |
126 | * @param node node whose stream to remove | 197 | * @param node node whose stream to remove |
127 | */ | 198 | */ |
128 | void removeNodeStream(DefaultControllerNode node) { | 199 | void removeNodeStream(DefaultControllerNode node) { |
129 | - nodesDelegate.nodeVanished(node); | 200 | + nodesDelegate.nodeVanished(node.id()); |
130 | streams.remove(node.id()); | 201 | streams.remove(node.id()); |
131 | } | 202 | } |
132 | 203 | ||
133 | - @Override | 204 | + /** |
134 | - public boolean send(NodeId nodeId, ClusterMessage message) { | 205 | + * Finds the least utilized IO worker. |
135 | - ClusterMessageStream stream = streams.get(nodeId); | 206 | + * |
136 | - if (stream != null) { | 207 | + * @return IO worker |
137 | - try { | 208 | + */ |
138 | - stream.write(message); | 209 | + ClusterIOWorker findWorker() { |
139 | - return true; | 210 | + ClusterIOWorker leastUtilized = null; |
140 | - } catch (IOException e) { | 211 | + int minCount = Integer.MAX_VALUE; |
141 | - log.warn("Unable to send a message about {} to node {}", | 212 | + for (ClusterIOWorker worker : workers) { |
142 | - message.subject(), nodeId); | 213 | + int count = worker.streamCount(); |
214 | + if (count == 0) { | ||
215 | + return worker; | ||
216 | + } | ||
217 | + | ||
218 | + if (count < minCount) { | ||
219 | + leastUtilized = worker; | ||
220 | + minCount = count; | ||
143 | } | 221 | } |
144 | } | 222 | } |
145 | - return false; | 223 | + return leastUtilized; |
146 | } | 224 | } |
147 | 225 | ||
148 | /** | 226 | /** |
... | @@ -154,8 +232,7 @@ public class ConnectionManager implements MessageSender { | ... | @@ -154,8 +232,7 @@ public class ConnectionManager implements MessageSender { |
154 | for (int i = 0; i < WORKERS; i++) { | 232 | for (int i = 0; i < WORKERS; i++) { |
155 | try { | 233 | try { |
156 | ClusterIOWorker worker = | 234 | ClusterIOWorker worker = |
157 | - new ClusterIOWorker(this, commsDelegate, | 235 | + new ClusterIOWorker(this, serializationService, hello); |
158 | - serializationService, hello); | ||
159 | workers.add(worker); | 236 | workers.add(worker); |
160 | commExecutors.execute(worker); | 237 | commExecutors.execute(worker); |
161 | } catch (IOException e) { | 238 | } catch (IOException e) { |
... | @@ -177,8 +254,7 @@ public class ConnectionManager implements MessageSender { | ... | @@ -177,8 +254,7 @@ public class ConnectionManager implements MessageSender { |
177 | private void startListening() { | 254 | private void startListening() { |
178 | try { | 255 | try { |
179 | connectionListener = | 256 | connectionListener = |
180 | - new ClusterConnectionListener(localNode.ip(), localNode.tcpPort(), | 257 | + new ClusterConnectionListener(this, localNode.ip(), localNode.tcpPort()); |
181 | - workerFinder); | ||
182 | listenExecutor.execute(connectionListener); | 258 | listenExecutor.execute(connectionListener); |
183 | if (!connectionListener.awaitStart(START_TIMEOUT)) { | 259 | if (!connectionListener.awaitStart(START_TIMEOUT)) { |
184 | log.warn("Listener did not start on-time; moving on..."); | 260 | log.warn("Listener did not start on-time; moving on..."); |
... | @@ -189,28 +265,27 @@ public class ConnectionManager implements MessageSender { | ... | @@ -189,28 +265,27 @@ public class ConnectionManager implements MessageSender { |
189 | } | 265 | } |
190 | 266 | ||
191 | /** | 267 | /** |
268 | + * Attempts to connect to any nodes that do not have an associated connection. | ||
269 | + */ | ||
270 | + private void startInitiatingConnections() { | ||
271 | + timer.schedule(connectionCustodian, CONNECTION_CUSTODIAN_DELAY, | ||
272 | + CONNECTION_CUSTODIAN_FREQUENCY); | ||
273 | + } | ||
274 | + | ||
275 | + /** | ||
192 | * Initiates open connection request and registers the pending socket | 276 | * Initiates open connection request and registers the pending socket |
193 | - * channel with the given IO loop. | 277 | + * channel with the given IO worker. |
194 | * | 278 | * |
195 | - * @param loop loop with which the channel should be registered | 279 | + * @param worker loop with which the channel should be registered |
196 | * @throws java.io.IOException if the socket could not be open or connected | 280 | * @throws java.io.IOException if the socket could not be open or connected |
197 | */ | 281 | */ |
198 | private void initiateConnection(DefaultControllerNode node, | 282 | private void initiateConnection(DefaultControllerNode node, |
199 | - ClusterIOWorker loop) throws IOException { | 283 | + ClusterIOWorker worker) throws IOException { |
200 | SocketAddress sa = new InetSocketAddress(getByAddress(node.ip().toOctets()), node.tcpPort()); | 284 | SocketAddress sa = new InetSocketAddress(getByAddress(node.ip().toOctets()), node.tcpPort()); |
201 | SocketChannel ch = SocketChannel.open(); | 285 | SocketChannel ch = SocketChannel.open(); |
202 | ch.configureBlocking(false); | 286 | ch.configureBlocking(false); |
203 | ch.connect(sa); | 287 | ch.connect(sa); |
204 | - loop.connectStream(ch); | 288 | + worker.connectStream(ch); |
205 | - } | ||
206 | - | ||
207 | - | ||
208 | - /** | ||
209 | - * Attempts to connect to any nodes that do not have an associated connection. | ||
210 | - */ | ||
211 | - private void startInitiating() { | ||
212 | - timer.schedule(connectionCustodian, CONNECTION_CUSTODIAN_DELAY, | ||
213 | - CONNECTION_CUSTODIAN_FREQUENCY); | ||
214 | } | 289 | } |
215 | 290 | ||
216 | // Sweeps through all controller nodes and attempts to open connection to | 291 | // Sweeps through all controller nodes and attempts to open connection to |
... | @@ -219,9 +294,9 @@ public class ConnectionManager implements MessageSender { | ... | @@ -219,9 +294,9 @@ public class ConnectionManager implements MessageSender { |
219 | @Override | 294 | @Override |
220 | public void run() { | 295 | public void run() { |
221 | for (DefaultControllerNode node : nodes) { | 296 | for (DefaultControllerNode node : nodes) { |
222 | - if (node != localNode && !streams.containsKey(node.id())) { | 297 | + if (!node.id().equals(localNode.id()) && !streams.containsKey(node.id())) { |
223 | try { | 298 | try { |
224 | - initiateConnection(node, workerFinder.findWorker()); | 299 | + initiateConnection(node, findWorker()); |
225 | } catch (IOException e) { | 300 | } catch (IOException e) { |
226 | log.debug("Unable to connect", e); | 301 | log.debug("Unable to connect", e); |
227 | } | 302 | } |
... | @@ -230,26 +305,4 @@ public class ConnectionManager implements MessageSender { | ... | @@ -230,26 +305,4 @@ public class ConnectionManager implements MessageSender { |
230 | } | 305 | } |
231 | } | 306 | } |
232 | 307 | ||
233 | - // Finds the least utilitied IO loop. | ||
234 | - private class LeastUtilitiedWorkerFinder implements WorkerFinder { | ||
235 | - | ||
236 | - @Override | ||
237 | - public ClusterIOWorker findWorker() { | ||
238 | - ClusterIOWorker leastUtilized = null; | ||
239 | - int minCount = Integer.MAX_VALUE; | ||
240 | - for (ClusterIOWorker worker : workers) { | ||
241 | - int count = worker.streamCount(); | ||
242 | - if (count == 0) { | ||
243 | - return worker; | ||
244 | - } | ||
245 | - | ||
246 | - if (count < minCount) { | ||
247 | - leastUtilized = worker; | ||
248 | - minCount = count; | ||
249 | - } | ||
250 | - } | ||
251 | - return leastUtilized; | ||
252 | - } | ||
253 | - } | ||
254 | - | ||
255 | } | 308 | } | ... | ... |
... | @@ -23,12 +23,12 @@ public class ClusterConnectionListener extends AcceptorLoop { | ... | @@ -23,12 +23,12 @@ public class ClusterConnectionListener extends AcceptorLoop { |
23 | private static final int SO_SEND_BUFFER_SIZE = COMM_BUFFER_SIZE; | 23 | private static final int SO_SEND_BUFFER_SIZE = COMM_BUFFER_SIZE; |
24 | private static final int SO_RCV_BUFFER_SIZE = COMM_BUFFER_SIZE; | 24 | private static final int SO_RCV_BUFFER_SIZE = COMM_BUFFER_SIZE; |
25 | 25 | ||
26 | - private final WorkerFinder workerFinder; | 26 | + private final ClusterCommunicationManager manager; |
27 | 27 | ||
28 | - ClusterConnectionListener(IpPrefix ip, int tcpPort, | 28 | + ClusterConnectionListener(ClusterCommunicationManager manager, |
29 | - WorkerFinder workerFinder) throws IOException { | 29 | + IpPrefix ip, int tcpPort) throws IOException { |
30 | super(SELECT_TIMEOUT, new InetSocketAddress(getByAddress(ip.toOctets()), tcpPort)); | 30 | super(SELECT_TIMEOUT, new InetSocketAddress(getByAddress(ip.toOctets()), tcpPort)); |
31 | - this.workerFinder = workerFinder; | 31 | + this.manager = manager; |
32 | } | 32 | } |
33 | 33 | ||
34 | @Override | 34 | @Override |
... | @@ -41,7 +41,7 @@ public class ClusterConnectionListener extends AcceptorLoop { | ... | @@ -41,7 +41,7 @@ public class ClusterConnectionListener extends AcceptorLoop { |
41 | so.setReceiveBufferSize(SO_RCV_BUFFER_SIZE); | 41 | so.setReceiveBufferSize(SO_RCV_BUFFER_SIZE); |
42 | so.setSendBufferSize(SO_SEND_BUFFER_SIZE); | 42 | so.setSendBufferSize(SO_SEND_BUFFER_SIZE); |
43 | 43 | ||
44 | - workerFinder.findWorker().acceptStream(sc); | 44 | + manager.findWorker().acceptStream(sc); |
45 | } | 45 | } |
46 | 46 | ||
47 | } | 47 | } | ... | ... |
... | @@ -3,8 +3,10 @@ package org.onlab.onos.store.cluster.impl; | ... | @@ -3,8 +3,10 @@ package org.onlab.onos.store.cluster.impl; |
3 | import org.onlab.nio.IOLoop; | 3 | import org.onlab.nio.IOLoop; |
4 | import org.onlab.nio.MessageStream; | 4 | import org.onlab.nio.MessageStream; |
5 | import org.onlab.onos.cluster.DefaultControllerNode; | 5 | import org.onlab.onos.cluster.DefaultControllerNode; |
6 | +import org.onlab.onos.cluster.NodeId; | ||
6 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; | 7 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; |
7 | import org.onlab.onos.store.cluster.messaging.ClusterMessageStream; | 8 | import org.onlab.onos.store.cluster.messaging.ClusterMessageStream; |
9 | +import org.onlab.onos.store.cluster.messaging.HelloMessage; | ||
8 | import org.onlab.onos.store.cluster.messaging.SerializationService; | 10 | import org.onlab.onos.store.cluster.messaging.SerializationService; |
9 | import org.slf4j.Logger; | 11 | import org.slf4j.Logger; |
10 | import org.slf4j.LoggerFactory; | 12 | import org.slf4j.LoggerFactory; |
... | @@ -29,27 +31,23 @@ public class ClusterIOWorker extends | ... | @@ -29,27 +31,23 @@ public class ClusterIOWorker extends |
29 | 31 | ||
30 | private static final long SELECT_TIMEOUT = 50; | 32 | private static final long SELECT_TIMEOUT = 50; |
31 | 33 | ||
32 | - private final ConnectionManager connectionManager; | 34 | + private final ClusterCommunicationManager manager; |
33 | - private final CommunicationsDelegate commsDelegate; | ||
34 | private final SerializationService serializationService; | 35 | private final SerializationService serializationService; |
35 | private final ClusterMessage helloMessage; | 36 | private final ClusterMessage helloMessage; |
36 | 37 | ||
37 | /** | 38 | /** |
38 | * Creates a new cluster IO worker. | 39 | * Creates a new cluster IO worker. |
39 | * | 40 | * |
40 | - * @param connectionManager parent connection manager | 41 | + * @param manager parent comms manager |
41 | - * @param commsDelegate communications delegate for dispatching | ||
42 | * @param serializationService serialization service for encode/decode | 42 | * @param serializationService serialization service for encode/decode |
43 | * @param helloMessage hello message for greeting peers | 43 | * @param helloMessage hello message for greeting peers |
44 | * @throws IOException if errors occur during IO loop ignition | 44 | * @throws IOException if errors occur during IO loop ignition |
45 | */ | 45 | */ |
46 | - ClusterIOWorker(ConnectionManager connectionManager, | 46 | + ClusterIOWorker(ClusterCommunicationManager manager, |
47 | - CommunicationsDelegate commsDelegate, | ||
48 | SerializationService serializationService, | 47 | SerializationService serializationService, |
49 | ClusterMessage helloMessage) throws IOException { | 48 | ClusterMessage helloMessage) throws IOException { |
50 | super(SELECT_TIMEOUT); | 49 | super(SELECT_TIMEOUT); |
51 | - this.connectionManager = connectionManager; | 50 | + this.manager = manager; |
52 | - this.commsDelegate = commsDelegate; | ||
53 | this.serializationService = serializationService; | 51 | this.serializationService = serializationService; |
54 | this.helloMessage = helloMessage; | 52 | this.helloMessage = helloMessage; |
55 | } | 53 | } |
... | @@ -61,11 +59,27 @@ public class ClusterIOWorker extends | ... | @@ -61,11 +59,27 @@ public class ClusterIOWorker extends |
61 | 59 | ||
62 | @Override | 60 | @Override |
63 | protected void processMessages(List<ClusterMessage> messages, MessageStream<ClusterMessage> stream) { | 61 | protected void processMessages(List<ClusterMessage> messages, MessageStream<ClusterMessage> stream) { |
62 | + NodeId nodeId = getNodeId(messages, (ClusterMessageStream) stream); | ||
64 | for (ClusterMessage message : messages) { | 63 | for (ClusterMessage message : messages) { |
65 | - commsDelegate.dispatch(message); | 64 | + manager.dispatch(message, nodeId); |
66 | } | 65 | } |
67 | } | 66 | } |
68 | 67 | ||
68 | + // Retrieves the node from the stream. If one is not bound, it attempts | ||
69 | + // to bind it using the knowledge that the first message must be a hello. | ||
70 | + private NodeId getNodeId(List<ClusterMessage> messages, ClusterMessageStream stream) { | ||
71 | + DefaultControllerNode node = stream.node(); | ||
72 | + if (node == null && !messages.isEmpty()) { | ||
73 | + ClusterMessage firstMessage = messages.get(0); | ||
74 | + if (firstMessage instanceof HelloMessage) { | ||
75 | + HelloMessage hello = (HelloMessage) firstMessage; | ||
76 | + node = manager.addNodeStream(hello.nodeId(), hello.ipAddress(), | ||
77 | + hello.tcpPort(), stream); | ||
78 | + } | ||
79 | + } | ||
80 | + return node != null ? node.id() : null; | ||
81 | + } | ||
82 | + | ||
69 | @Override | 83 | @Override |
70 | public ClusterMessageStream acceptStream(SocketChannel channel) { | 84 | public ClusterMessageStream acceptStream(SocketChannel channel) { |
71 | ClusterMessageStream stream = super.acceptStream(channel); | 85 | ClusterMessageStream stream = super.acceptStream(channel); |
... | @@ -99,7 +113,7 @@ public class ClusterIOWorker extends | ... | @@ -99,7 +113,7 @@ public class ClusterIOWorker extends |
99 | DefaultControllerNode node = ((ClusterMessageStream) stream).node(); | 113 | DefaultControllerNode node = ((ClusterMessageStream) stream).node(); |
100 | if (node != null) { | 114 | if (node != null) { |
101 | log.info("Closed connection to node {}", node.id()); | 115 | log.info("Closed connection to node {}", node.id()); |
102 | - connectionManager.removeNodeStream(node); | 116 | + manager.removeNodeStream(node); |
103 | } | 117 | } |
104 | super.removeStream(stream); | 118 | super.removeStream(stream); |
105 | } | 119 | } | ... | ... |
1 | package org.onlab.onos.store.cluster.impl; | 1 | package org.onlab.onos.store.cluster.impl; |
2 | 2 | ||
3 | import org.onlab.onos.cluster.DefaultControllerNode; | 3 | import org.onlab.onos.cluster.DefaultControllerNode; |
4 | +import org.onlab.onos.cluster.NodeId; | ||
5 | +import org.onlab.packet.IpPrefix; | ||
4 | 6 | ||
5 | /** | 7 | /** |
6 | * Simple back interface through which connection manager can interact with | 8 | * Simple back interface through which connection manager can interact with |
... | @@ -9,17 +11,20 @@ import org.onlab.onos.cluster.DefaultControllerNode; | ... | @@ -9,17 +11,20 @@ import org.onlab.onos.cluster.DefaultControllerNode; |
9 | public interface ClusterNodesDelegate { | 11 | public interface ClusterNodesDelegate { |
10 | 12 | ||
11 | /** | 13 | /** |
12 | - * Notifies about a new cluster node being detected. | 14 | + * Notifies about cluster node coming online. |
13 | * | 15 | * |
14 | - * @param node newly detected cluster node | 16 | + * @param nodeId newly detected cluster node id |
17 | + * @param ip node IP listen address | ||
18 | + * @param tcpPort node TCP listen port | ||
19 | + * @return the controller node | ||
15 | */ | 20 | */ |
16 | - void nodeDetected(DefaultControllerNode node); | 21 | + DefaultControllerNode nodeDetected(NodeId nodeId, IpPrefix ip, int tcpPort); |
17 | 22 | ||
18 | /** | 23 | /** |
19 | * Notifies about cluster node going offline. | 24 | * Notifies about cluster node going offline. |
20 | * | 25 | * |
21 | - * @param node cluster node that vanished | 26 | + * @param nodeId identifier of the cluster node that vanished |
22 | */ | 27 | */ |
23 | - void nodeVanished(DefaultControllerNode node); | 28 | + void nodeVanished(NodeId nodeId); |
24 | 29 | ||
25 | } | 30 | } | ... | ... |
core/store/dist/src/main/java/org/onlab/onos/store/cluster/impl/CommunicationsDelegate.java
deleted
100644 → 0
1 | -package org.onlab.onos.store.cluster.impl; | ||
2 | - | ||
3 | -import org.onlab.onos.store.cluster.messaging.ClusterMessage; | ||
4 | - | ||
5 | -/** | ||
6 | - * Simple back interface for interacting with the communications service. | ||
7 | - */ | ||
8 | -public interface CommunicationsDelegate { | ||
9 | - | ||
10 | - /** | ||
11 | - * Dispatches the specified message to all registered subscribers. | ||
12 | - * | ||
13 | - * @param message message to be dispatched | ||
14 | - */ | ||
15 | - void dispatch(ClusterMessage message); | ||
16 | - | ||
17 | - /** | ||
18 | - * Sets the sender. | ||
19 | - * | ||
20 | - * @param messageSender message sender | ||
21 | - */ | ||
22 | - void setSender(MessageSender messageSender); | ||
23 | - | ||
24 | -} |
... | @@ -14,7 +14,6 @@ import org.onlab.onos.cluster.ControllerNode; | ... | @@ -14,7 +14,6 @@ import org.onlab.onos.cluster.ControllerNode; |
14 | import org.onlab.onos.cluster.DefaultControllerNode; | 14 | import org.onlab.onos.cluster.DefaultControllerNode; |
15 | import org.onlab.onos.cluster.NodeId; | 15 | import org.onlab.onos.cluster.NodeId; |
16 | import org.onlab.onos.store.AbstractStore; | 16 | import org.onlab.onos.store.AbstractStore; |
17 | -import org.onlab.onos.store.cluster.messaging.SerializationService; | ||
18 | import org.onlab.packet.IpPrefix; | 17 | import org.onlab.packet.IpPrefix; |
19 | import org.slf4j.Logger; | 18 | import org.slf4j.Logger; |
20 | import org.slf4j.LoggerFactory; | 19 | import org.slf4j.LoggerFactory; |
... | @@ -43,20 +42,20 @@ public class DistributedClusterStore | ... | @@ -43,20 +42,20 @@ public class DistributedClusterStore |
43 | private final Map<NodeId, State> states = new ConcurrentHashMap<>(); | 42 | private final Map<NodeId, State> states = new ConcurrentHashMap<>(); |
44 | 43 | ||
45 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 44 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
46 | - private CommunicationsDelegate commsDelegate; | 45 | + private ClusterCommunicationAdminService communicationAdminService; |
47 | - | ||
48 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
49 | - private SerializationService serializationService; | ||
50 | 46 | ||
51 | private final ClusterNodesDelegate nodesDelegate = new InnerNodesDelegate(); | 47 | private final ClusterNodesDelegate nodesDelegate = new InnerNodesDelegate(); |
52 | - private ConnectionManager connectionManager; | ||
53 | 48 | ||
54 | @Activate | 49 | @Activate |
55 | public void activate() { | 50 | public void activate() { |
56 | loadClusterDefinition(); | 51 | loadClusterDefinition(); |
57 | establishSelfIdentity(); | 52 | establishSelfIdentity(); |
58 | - connectionManager = new ConnectionManager(localNode, nodesDelegate, | 53 | + |
59 | - commsDelegate, serializationService); | 54 | + // Start-up the comm service and prime it with the loaded nodes. |
55 | + communicationAdminService.startUp(localNode, nodesDelegate); | ||
56 | + for (DefaultControllerNode node : nodes.values()) { | ||
57 | + communicationAdminService.addNode(node); | ||
58 | + } | ||
60 | log.info("Started"); | 59 | log.info("Started"); |
61 | } | 60 | } |
62 | 61 | ||
... | @@ -92,8 +91,8 @@ public class DistributedClusterStore | ... | @@ -92,8 +91,8 @@ public class DistributedClusterStore |
92 | if (localNode == null) { | 91 | if (localNode == null) { |
93 | localNode = new DefaultControllerNode(new NodeId(ip.toString()), ip); | 92 | localNode = new DefaultControllerNode(new NodeId(ip.toString()), ip); |
94 | nodes.put(localNode.id(), localNode); | 93 | nodes.put(localNode.id(), localNode); |
95 | - states.put(localNode.id(), State.ACTIVE); | ||
96 | } | 94 | } |
95 | + states.put(localNode.id(), State.ACTIVE); | ||
97 | } | 96 | } |
98 | 97 | ||
99 | @Override | 98 | @Override |
... | @@ -122,7 +121,7 @@ public class DistributedClusterStore | ... | @@ -122,7 +121,7 @@ public class DistributedClusterStore |
122 | public ControllerNode addNode(NodeId nodeId, IpPrefix ip, int tcpPort) { | 121 | public ControllerNode addNode(NodeId nodeId, IpPrefix ip, int tcpPort) { |
123 | DefaultControllerNode node = new DefaultControllerNode(nodeId, ip, tcpPort); | 122 | DefaultControllerNode node = new DefaultControllerNode(nodeId, ip, tcpPort); |
124 | nodes.put(nodeId, node); | 123 | nodes.put(nodeId, node); |
125 | - connectionManager.addNode(node); | 124 | + communicationAdminService.addNode(node); |
126 | return node; | 125 | return node; |
127 | } | 126 | } |
128 | 127 | ||
... | @@ -130,21 +129,25 @@ public class DistributedClusterStore | ... | @@ -130,21 +129,25 @@ public class DistributedClusterStore |
130 | public void removeNode(NodeId nodeId) { | 129 | public void removeNode(NodeId nodeId) { |
131 | DefaultControllerNode node = nodes.remove(nodeId); | 130 | DefaultControllerNode node = nodes.remove(nodeId); |
132 | if (node != null) { | 131 | if (node != null) { |
133 | - connectionManager.removeNode(node); | 132 | + communicationAdminService.removeNode(node); |
134 | } | 133 | } |
135 | } | 134 | } |
136 | 135 | ||
137 | // Entity to handle back calls from the connection manager. | 136 | // Entity to handle back calls from the connection manager. |
138 | private class InnerNodesDelegate implements ClusterNodesDelegate { | 137 | private class InnerNodesDelegate implements ClusterNodesDelegate { |
139 | @Override | 138 | @Override |
140 | - public void nodeDetected(DefaultControllerNode node) { | 139 | + public DefaultControllerNode nodeDetected(NodeId nodeId, IpPrefix ip, int tcpPort) { |
141 | - nodes.put(node.id(), node); | 140 | + DefaultControllerNode node = nodes.get(nodeId); |
142 | - states.put(node.id(), State.ACTIVE); | 141 | + if (node == null) { |
142 | + node = (DefaultControllerNode) addNode(nodeId, ip, tcpPort); | ||
143 | + } | ||
144 | + states.put(nodeId, State.ACTIVE); | ||
145 | + return node; | ||
143 | } | 146 | } |
144 | - | ||
145 | @Override | 147 | @Override |
146 | - public void nodeVanished(DefaultControllerNode node) { | 148 | + public void nodeVanished(NodeId nodeId) { |
147 | - states.put(node.id(), State.INACTIVE); | 149 | + states.put(nodeId, State.INACTIVE); |
148 | } | 150 | } |
149 | } | 151 | } |
152 | + | ||
150 | } | 153 | } | ... | ... |
core/store/dist/src/main/java/org/onlab/onos/store/cluster/impl/MessageSender.java
deleted
100644 → 0
1 | -package org.onlab.onos.store.cluster.impl; | ||
2 | - | ||
3 | -import org.onlab.onos.cluster.NodeId; | ||
4 | -import org.onlab.onos.store.cluster.messaging.ClusterMessage; | ||
5 | - | ||
6 | -/** | ||
7 | - * Created by tom on 9/29/14. | ||
8 | - */ | ||
9 | -public interface MessageSender { | ||
10 | - | ||
11 | - /** | ||
12 | - * Sends the specified message to the given cluster node. | ||
13 | - * | ||
14 | - * @param nodeId node identifier | ||
15 | - * @param message mesage to send | ||
16 | - * @return true if the message was sent sucessfully; false if there is | ||
17 | - * no stream or if there was an error | ||
18 | - */ | ||
19 | - boolean send(NodeId nodeId, ClusterMessage message); | ||
20 | - | ||
21 | -} |
... | @@ -29,9 +29,9 @@ public class HelloMessage extends ClusterMessage { | ... | @@ -29,9 +29,9 @@ public class HelloMessage extends ClusterMessage { |
29 | */ | 29 | */ |
30 | public HelloMessage(NodeId nodeId, IpPrefix ipAddress, int tcpPort) { | 30 | public HelloMessage(NodeId nodeId, IpPrefix ipAddress, int tcpPort) { |
31 | super(MessageSubject.HELLO); | 31 | super(MessageSubject.HELLO); |
32 | - nodeId = nodeId; | 32 | + this.nodeId = nodeId; |
33 | - ipAddress = ipAddress; | 33 | + this.ipAddress = ipAddress; |
34 | - tcpPort = tcpPort; | 34 | + this.tcpPort = tcpPort; |
35 | } | 35 | } |
36 | 36 | ||
37 | /** | 37 | /** |
... | @@ -60,4 +60,5 @@ public class HelloMessage extends ClusterMessage { | ... | @@ -60,4 +60,5 @@ public class HelloMessage extends ClusterMessage { |
60 | public int tcpPort() { | 60 | public int tcpPort() { |
61 | return tcpPort; | 61 | return tcpPort; |
62 | } | 62 | } |
63 | + | ||
63 | } | 64 | } | ... | ... |
1 | package org.onlab.onos.store.cluster.messaging; | 1 | package org.onlab.onos.store.cluster.messaging; |
2 | 2 | ||
3 | +import org.onlab.onos.cluster.NodeId; | ||
4 | + | ||
3 | /** | 5 | /** |
4 | * Represents a message consumer. | 6 | * Represents a message consumer. |
5 | */ | 7 | */ |
... | @@ -8,8 +10,9 @@ public interface MessageSubscriber { | ... | @@ -8,8 +10,9 @@ public interface MessageSubscriber { |
8 | /** | 10 | /** |
9 | * Receives the specified cluster message. | 11 | * Receives the specified cluster message. |
10 | * | 12 | * |
11 | - * @param message message to be received | 13 | + * @param message message to be received |
14 | + * @param fromNodeId node from which the message was received | ||
12 | */ | 15 | */ |
13 | - void receive(ClusterMessage message); | 16 | + void receive(ClusterMessage message, NodeId fromNodeId); |
14 | 17 | ||
15 | } | 18 | } | ... | ... |
... | @@ -3,12 +3,12 @@ package org.onlab.onos.store.cluster.messaging; | ... | @@ -3,12 +3,12 @@ package org.onlab.onos.store.cluster.messaging; |
3 | import java.nio.ByteBuffer; | 3 | import java.nio.ByteBuffer; |
4 | 4 | ||
5 | /** | 5 | /** |
6 | - * Service for serializing/deserializing intra-cluster messages. | 6 | + * Service for encoding & decoding intra-cluster messages. |
7 | */ | 7 | */ |
8 | public interface SerializationService { | 8 | public interface SerializationService { |
9 | 9 | ||
10 | /** | 10 | /** |
11 | - * Decodes the specified byte buffer to obtain a message within. | 11 | + * Decodes the specified byte buffer to obtain the message within. |
12 | * | 12 | * |
13 | * @param buffer byte buffer with message(s) | 13 | * @param buffer byte buffer with message(s) |
14 | * @return parsed message | 14 | * @return parsed message | ... | ... |
1 | -package org.onlab.onos.store.cluster.messaging.impl; | ||
2 | - | ||
3 | -import com.google.common.collect.HashMultimap; | ||
4 | -import com.google.common.collect.ImmutableSet; | ||
5 | -import com.google.common.collect.Multimap; | ||
6 | -import org.apache.felix.scr.annotations.Component; | ||
7 | -import org.apache.felix.scr.annotations.Service; | ||
8 | -import org.onlab.onos.cluster.NodeId; | ||
9 | -import org.onlab.onos.store.cluster.impl.CommunicationsDelegate; | ||
10 | -import org.onlab.onos.store.cluster.impl.MessageSender; | ||
11 | -import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; | ||
12 | -import org.onlab.onos.store.cluster.messaging.ClusterMessage; | ||
13 | -import org.onlab.onos.store.cluster.messaging.MessageSubject; | ||
14 | -import org.onlab.onos.store.cluster.messaging.MessageSubscriber; | ||
15 | - | ||
16 | -import java.util.Set; | ||
17 | - | ||
18 | -/** | ||
19 | - * Implements the cluster communication services to use by other stores. | ||
20 | - */ | ||
21 | -@Component(immediate = true) | ||
22 | -@Service | ||
23 | -public class ClusterCommunicationManager | ||
24 | - implements ClusterCommunicationService, CommunicationsDelegate { | ||
25 | - | ||
26 | - // TODO: use something different that won't require synchronization | ||
27 | - private Multimap<MessageSubject, MessageSubscriber> subscribers = HashMultimap.create(); | ||
28 | - private MessageSender messageSender; | ||
29 | - | ||
30 | - @Override | ||
31 | - public boolean send(ClusterMessage message, NodeId toNodeId) { | ||
32 | - return messageSender.send(toNodeId, message); | ||
33 | - } | ||
34 | - | ||
35 | - @Override | ||
36 | - public synchronized void addSubscriber(MessageSubject subject, MessageSubscriber subscriber) { | ||
37 | - subscribers.put(subject, subscriber); | ||
38 | - } | ||
39 | - | ||
40 | - @Override | ||
41 | - public synchronized void removeSubscriber(MessageSubject subject, MessageSubscriber subscriber) { | ||
42 | - subscribers.remove(subject, subscriber); | ||
43 | - } | ||
44 | - | ||
45 | - @Override | ||
46 | - public Set<MessageSubscriber> getSubscribers(MessageSubject subject) { | ||
47 | - return ImmutableSet.copyOf(subscribers.get(subject)); | ||
48 | - } | ||
49 | - | ||
50 | - @Override | ||
51 | - public void dispatch(ClusterMessage message) { | ||
52 | - Set<MessageSubscriber> set = getSubscribers(message.subject()); | ||
53 | - if (set != null) { | ||
54 | - for (MessageSubscriber subscriber : set) { | ||
55 | - subscriber.receive(message); | ||
56 | - } | ||
57 | - } | ||
58 | - } | ||
59 | - | ||
60 | - @Override | ||
61 | - public void setSender(MessageSender messageSender) { | ||
62 | - this.messageSender = messageSender; | ||
63 | - } | ||
64 | -} |
1 | package org.onlab.onos.store.cluster.messaging.impl; | 1 | package org.onlab.onos.store.cluster.messaging.impl; |
2 | 2 | ||
3 | +import org.apache.felix.scr.annotations.Component; | ||
4 | +import org.apache.felix.scr.annotations.Service; | ||
5 | +import org.onlab.onos.cluster.NodeId; | ||
3 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; | 6 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; |
7 | +import org.onlab.onos.store.cluster.messaging.HelloMessage; | ||
4 | import org.onlab.onos.store.cluster.messaging.MessageSubject; | 8 | import org.onlab.onos.store.cluster.messaging.MessageSubject; |
5 | import org.onlab.onos.store.cluster.messaging.SerializationService; | 9 | import org.onlab.onos.store.cluster.messaging.SerializationService; |
10 | +import org.onlab.packet.IpPrefix; | ||
11 | +import org.slf4j.Logger; | ||
12 | +import org.slf4j.LoggerFactory; | ||
6 | 13 | ||
7 | import java.nio.ByteBuffer; | 14 | import java.nio.ByteBuffer; |
8 | 15 | ||
... | @@ -11,8 +18,12 @@ import static com.google.common.base.Preconditions.checkState; | ... | @@ -11,8 +18,12 @@ import static com.google.common.base.Preconditions.checkState; |
11 | /** | 18 | /** |
12 | * Factory for parsing messages sent between cluster members. | 19 | * Factory for parsing messages sent between cluster members. |
13 | */ | 20 | */ |
21 | +@Component(immediate = true) | ||
22 | +@Service | ||
14 | public class MessageSerializer implements SerializationService { | 23 | public class MessageSerializer implements SerializationService { |
15 | 24 | ||
25 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
26 | + | ||
16 | private static final int METADATA_LENGTH = 16; // 8 + 4 + 4 | 27 | private static final int METADATA_LENGTH = 16; // 8 + 4 + 4 |
17 | private static final int LENGTH_OFFSET = 12; | 28 | private static final int LENGTH_OFFSET = 12; |
18 | 29 | ||
... | @@ -46,11 +57,12 @@ public class MessageSerializer implements SerializationService { | ... | @@ -46,11 +57,12 @@ public class MessageSerializer implements SerializationService { |
46 | buffer.get(data); | 57 | buffer.get(data); |
47 | 58 | ||
48 | // TODO: add deserialization hook here; for now this hack | 59 | // TODO: add deserialization hook here; for now this hack |
49 | - return null; // actually deserialize | 60 | + String[] fields = new String(data).split(":"); |
61 | + return new HelloMessage(new NodeId(fields[0]), IpPrefix.valueOf(fields[1]), Integer.parseInt(fields[2])); | ||
50 | 62 | ||
51 | } catch (Exception e) { | 63 | } catch (Exception e) { |
52 | // TODO: recover from exceptions by forwarding stream to next marker | 64 | // TODO: recover from exceptions by forwarding stream to next marker |
53 | - e.printStackTrace(); | 65 | + log.warn("Unable to decode message due to: " + e); |
54 | } | 66 | } |
55 | return null; | 67 | return null; |
56 | } | 68 | } |
... | @@ -58,11 +70,18 @@ public class MessageSerializer implements SerializationService { | ... | @@ -58,11 +70,18 @@ public class MessageSerializer implements SerializationService { |
58 | @Override | 70 | @Override |
59 | public void encode(ClusterMessage message, ByteBuffer buffer) { | 71 | public void encode(ClusterMessage message, ByteBuffer buffer) { |
60 | try { | 72 | try { |
61 | - int i = 0; | 73 | + HelloMessage helloMessage = (HelloMessage) message; |
62 | - // Type based lookup for proper encoder | 74 | + buffer.putLong(MARKER); |
75 | + buffer.putInt(message.subject().ordinal()); | ||
76 | + | ||
77 | + String str = helloMessage.nodeId() + ":" + helloMessage.ipAddress() + ":" + helloMessage.tcpPort(); | ||
78 | + byte[] data = str.getBytes(); | ||
79 | + buffer.putInt(data.length + METADATA_LENGTH); | ||
80 | + buffer.put(data); | ||
81 | + | ||
63 | } catch (Exception e) { | 82 | } catch (Exception e) { |
64 | // TODO: recover from exceptions by forwarding stream to next marker | 83 | // TODO: recover from exceptions by forwarding stream to next marker |
65 | - e.printStackTrace(); | 84 | + log.warn("Unable to encode message due to: " + e); |
66 | } | 85 | } |
67 | } | 86 | } |
68 | 87 | ... | ... |
... | @@ -2,9 +2,9 @@ | ... | @@ -2,9 +2,9 @@ |
2 | 2 | ||
3 | export ONOS_NIC=192.168.56.* | 3 | export ONOS_NIC=192.168.56.* |
4 | 4 | ||
5 | -export OC1="192.168.56.101" | 5 | +export OC1="192.168.56.11" |
6 | -export OC2="192.168.56.102" | 6 | +export OC2="192.168.56.12" |
7 | 7 | ||
8 | -export OCN="192.168.56.105" | 8 | +export OCN="192.168.56.7" |
9 | 9 | ||
10 | 10 | ... | ... |
-
Please register or login to post a comment