2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.protocol.bgp.rib.impl.protocol;
10 import com.google.common.base.Preconditions;
11 import io.netty.bootstrap.Bootstrap;
12 import io.netty.channel.ChannelFuture;
13 import io.netty.channel.ChannelFutureListener;
14 import io.netty.channel.ChannelOption;
15 import io.netty.util.concurrent.DefaultPromise;
16 import io.netty.util.concurrent.EventExecutor;
17 import io.netty.util.concurrent.Future;
18 import io.netty.util.concurrent.FutureListener;
19 import io.netty.util.concurrent.Promise;
20 import java.net.InetSocketAddress;
21 import javax.annotation.concurrent.GuardedBy;
22 import org.opendaylight.protocol.bgp.rib.spi.BGPSession;
23 import org.opendaylight.protocol.framework.ReconnectStrategy;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
27 public class BGPProtocolSessionPromise<S extends BGPSession> extends DefaultPromise<S> {
28 private static final Logger LOG = LoggerFactory.getLogger(BGPProtocolSessionPromise.class);
29 private final ReconnectStrategy strategy;
30 private final Bootstrap b;
32 private InetSocketAddress address;
34 private Future<?> pending;
36 public BGPProtocolSessionPromise(EventExecutor executor, InetSocketAddress address, ReconnectStrategy strategy, Bootstrap b) {
38 this.strategy = Preconditions.checkNotNull(strategy);
39 this.address = Preconditions.checkNotNull(address);
40 this.b = Preconditions.checkNotNull(b);
43 public synchronized void connect() {
44 final BGPProtocolSessionPromise lock = this;
47 int e = this.strategy.getConnectTimeout();
48 LOG.debug("Promise {} attempting connect for {}ms", lock, Integer.valueOf(e));
49 if (this.address.isUnresolved()) {
50 this.address = new InetSocketAddress(this.address.getHostName(), this.address.getPort());
53 this.b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, e);
54 final ChannelFuture connectFuture = this.b.connect(this.address);
55 connectFuture.addListener(new BGPProtocolSessionPromise.BootstrapConnectListener(lock));
56 this.pending = connectFuture;
57 } catch (Exception e) {
58 LOG.info("Failed to connect to {}", this.address, e);
65 public synchronized boolean cancel(final boolean mayInterruptIfRunning) {
66 if (super.cancel(mayInterruptIfRunning)) {
67 this.pending.cancel(mayInterruptIfRunning);
75 public synchronized Promise<S> setSuccess(final S result) {
76 LOG.debug("Promise {} completed", this);
77 this.strategy.reconnectSuccessful();
78 return super.setSuccess(result);
81 private class BootstrapConnectListener implements ChannelFutureListener {
82 private final Object lock;
84 public BootstrapConnectListener(final Object lock) {
89 public void operationComplete(final ChannelFuture cf) throws Exception {
90 synchronized (this.lock) {
91 BGPProtocolSessionPromise.LOG.debug("Promise {} connection resolved", this.lock);
92 Preconditions.checkState(BGPProtocolSessionPromise.this.pending.equals(cf));
93 if (BGPProtocolSessionPromise.this.isCancelled()) {
95 BGPProtocolSessionPromise.LOG.debug("Closing channel for cancelled promise {}", this.lock);
99 } else if (cf.isSuccess()) {
100 BGPProtocolSessionPromise.LOG.debug("Promise {} connection successful", this.lock);
102 BGPProtocolSessionPromise.LOG.debug("Attempt to connect to {} failed", BGPProtocolSessionPromise.this.address, cf.cause());
103 final Future rf = BGPProtocolSessionPromise.this.strategy.scheduleReconnect(cf.cause());
104 rf.addListener(new BGPProtocolSessionPromise.BootstrapConnectListener.ReconnectingStrategyListener());
105 BGPProtocolSessionPromise.this.pending = rf;
110 private final class ReconnectingStrategyListener implements FutureListener<Void> {
111 private ReconnectingStrategyListener() {
115 public void operationComplete(final Future<Void> sf) {
116 synchronized (BootstrapConnectListener.this.lock) {
117 Preconditions.checkState(BGPProtocolSessionPromise.this.pending.equals(sf));
118 if (!BGPProtocolSessionPromise.this.isCancelled()) {
119 if (sf.isSuccess()) {
120 BGPProtocolSessionPromise.this.connect();
122 BGPProtocolSessionPromise.this.setFailure(sf.cause());