Committed by
Gerrit Code Review
Makes establishing connections between onos nodes asynchronous, prevents threads…
… blocking when nodes are inaccessible. Change-Id: I46ce54505e8c4c34b56009412ddb1d645c83aaa3
Showing
1 changed file
with
85 additions
and
22 deletions
... | @@ -96,8 +96,8 @@ public class NettyMessaging implements MessagingService { | ... | @@ -96,8 +96,8 @@ public class NettyMessaging implements MessagingService { |
96 | }) | 96 | }) |
97 | .build(); | 97 | .build(); |
98 | 98 | ||
99 | - private final GenericKeyedObjectPool<Endpoint, Channel> channels | 99 | + private final GenericKeyedObjectPool<Endpoint, Connection> channels |
100 | - = new GenericKeyedObjectPool<Endpoint, Channel>(new OnosCommunicationChannelFactory()); | 100 | + = new GenericKeyedObjectPool<Endpoint, Connection>(new OnosCommunicationChannelFactory()); |
101 | 101 | ||
102 | private EventLoopGroup serverGroup; | 102 | private EventLoopGroup serverGroup; |
103 | private EventLoopGroup clientGroup; | 103 | private EventLoopGroup clientGroup; |
... | @@ -179,18 +179,13 @@ public class NettyMessaging implements MessagingService { | ... | @@ -179,18 +179,13 @@ public class NettyMessaging implements MessagingService { |
179 | 179 | ||
180 | CompletableFuture<Void> future = new CompletableFuture<>(); | 180 | CompletableFuture<Void> future = new CompletableFuture<>(); |
181 | try { | 181 | try { |
182 | - Channel channel = null; | 182 | + Connection connection = null; |
183 | try { | 183 | try { |
184 | - channel = channels.borrowObject(ep); | 184 | + connection = channels.borrowObject(ep); |
185 | - channel.writeAndFlush(message).addListener(channelFuture -> { | 185 | + connection.send(message, future); |
186 | - if (!channelFuture.isSuccess()) { | 186 | + |
187 | - future.completeExceptionally(channelFuture.cause()); | ||
188 | - } else { | ||
189 | - future.complete(null); | ||
190 | - } | ||
191 | - }); | ||
192 | } finally { | 187 | } finally { |
193 | - channels.returnObject(ep, channel); | 188 | + channels.returnObject(ep, connection); |
194 | } | 189 | } |
195 | } catch (Exception e) { | 190 | } catch (Exception e) { |
196 | future.completeExceptionally(e); | 191 | future.completeExceptionally(e); |
... | @@ -292,21 +287,22 @@ public class NettyMessaging implements MessagingService { | ... | @@ -292,21 +287,22 @@ public class NettyMessaging implements MessagingService { |
292 | } | 287 | } |
293 | 288 | ||
294 | private class OnosCommunicationChannelFactory | 289 | private class OnosCommunicationChannelFactory |
295 | - implements KeyedPoolableObjectFactory<Endpoint, Channel> { | 290 | + implements KeyedPoolableObjectFactory<Endpoint, Connection> { |
296 | 291 | ||
297 | @Override | 292 | @Override |
298 | - public void activateObject(Endpoint endpoint, Channel channel) | 293 | + public void activateObject(Endpoint endpoint, Connection connection) |
299 | throws Exception { | 294 | throws Exception { |
300 | } | 295 | } |
301 | 296 | ||
302 | @Override | 297 | @Override |
303 | - public void destroyObject(Endpoint ep, Channel channel) throws Exception { | 298 | + public void destroyObject(Endpoint ep, Connection connection) throws Exception { |
304 | log.debug("Closing connection to {}", ep); | 299 | log.debug("Closing connection to {}", ep); |
305 | - channel.close(); | 300 | + //Is this the right way to destroy? |
301 | + connection.destroy(); | ||
306 | } | 302 | } |
307 | 303 | ||
308 | @Override | 304 | @Override |
309 | - public Channel makeObject(Endpoint ep) throws Exception { | 305 | + public Connection makeObject(Endpoint ep) throws Exception { |
310 | Bootstrap bootstrap = new Bootstrap(); | 306 | Bootstrap bootstrap = new Bootstrap(); |
311 | bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); | 307 | bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); |
312 | bootstrap.option(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, 10 * 64 * 1024); | 308 | bootstrap.option(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, 10 * 64 * 1024); |
... | @@ -324,19 +320,28 @@ public class NettyMessaging implements MessagingService { | ... | @@ -324,19 +320,28 @@ public class NettyMessaging implements MessagingService { |
324 | bootstrap.handler(new OnosCommunicationChannelInitializer()); | 320 | bootstrap.handler(new OnosCommunicationChannelInitializer()); |
325 | } | 321 | } |
326 | // Start the client. | 322 | // Start the client. |
327 | - ChannelFuture f = bootstrap.connect(ep.host().toString(), ep.port()).sync(); | 323 | + CompletableFuture<Channel> retFuture = new CompletableFuture<>(); |
324 | + ChannelFuture f = bootstrap.connect(ep.host().toString(), ep.port()); | ||
325 | + | ||
326 | + f.addListener(future -> { | ||
327 | + if (future.isSuccess()) { | ||
328 | + retFuture.complete(f.channel()); | ||
329 | + } else { | ||
330 | + retFuture.completeExceptionally(future.cause()); | ||
331 | + } | ||
332 | + }); | ||
328 | log.debug("Established a new connection to {}", ep); | 333 | log.debug("Established a new connection to {}", ep); |
329 | - return f.channel(); | 334 | + return new Connection(retFuture); |
330 | } | 335 | } |
331 | 336 | ||
332 | @Override | 337 | @Override |
333 | - public void passivateObject(Endpoint ep, Channel channel) | 338 | + public void passivateObject(Endpoint ep, Connection connection) |
334 | throws Exception { | 339 | throws Exception { |
335 | } | 340 | } |
336 | 341 | ||
337 | @Override | 342 | @Override |
338 | - public boolean validateObject(Endpoint ep, Channel channel) { | 343 | + public boolean validateObject(Endpoint ep, Connection connection) { |
339 | - return channel.isOpen(); | 344 | + return connection.validate(); |
340 | } | 345 | } |
341 | } | 346 | } |
342 | 347 | ||
... | @@ -486,4 +491,62 @@ public class NettyMessaging implements MessagingService { | ... | @@ -486,4 +491,62 @@ public class NettyMessaging implements MessagingService { |
486 | executor.execute(() -> future.completeExceptionally(error)); | 491 | executor.execute(() -> future.completeExceptionally(error)); |
487 | } | 492 | } |
488 | } | 493 | } |
494 | + private final class Connection { | ||
495 | + private final CompletableFuture<Channel> internalFuture; | ||
496 | + | ||
497 | + public Connection(CompletableFuture<Channel> internalFuture) { | ||
498 | + this.internalFuture = internalFuture; | ||
499 | + } | ||
500 | + | ||
501 | + /** | ||
502 | + * Sends a message out on its channel and associated the message with a | ||
503 | + * completable future used for signaling. | ||
504 | + * @param message the message to be sent | ||
505 | + * @param future a future that is completed normally or exceptionally if | ||
506 | + * message sending succeeds or fails respectively | ||
507 | + */ | ||
508 | + public void send(Object message, CompletableFuture<Void> future) { | ||
509 | + internalFuture.whenComplete((channel, throwable) -> { | ||
510 | + if (throwable == null) { | ||
511 | + channel.writeAndFlush(message).addListener(channelFuture -> { | ||
512 | + if (!channelFuture.isSuccess()) { | ||
513 | + future.completeExceptionally(channelFuture.cause()); | ||
514 | + } else { | ||
515 | + future.complete(null); | ||
516 | + } | ||
517 | + }); | ||
518 | + } else { | ||
519 | + future.completeExceptionally(throwable); | ||
520 | + } | ||
521 | + | ||
522 | + }); | ||
523 | + } | ||
524 | + | ||
525 | + /** | ||
526 | + * Destroys a channel by closing its channel (if it exists) and | ||
527 | + * cancelling its future. | ||
528 | + */ | ||
529 | + public void destroy() { | ||
530 | + Channel channel = internalFuture.getNow(null); | ||
531 | + if (channel != null) { | ||
532 | + channel.close(); | ||
533 | + } | ||
534 | + internalFuture.cancel(false); | ||
535 | + } | ||
536 | + | ||
537 | + /** | ||
538 | + * Determines whether the connection is valid meaning it is either | ||
539 | + * complete with and active channel | ||
540 | + * or it has not yet completed. | ||
541 | + * @return true if the channel has an active connection or has not | ||
542 | + * yet completed | ||
543 | + */ | ||
544 | + public boolean validate() { | ||
545 | + if (internalFuture.isCompletedExceptionally()) { | ||
546 | + return false; | ||
547 | + } | ||
548 | + Channel channel = internalFuture.getNow(null); | ||
549 | + return channel == null || channel.isActive(); | ||
550 | + } | ||
551 | + } | ||
489 | } | 552 | } | ... | ... |
-
Please register or login to post a comment