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