Get rid of JSR305 annotations
[bgpcep.git] / pcep / impl / src / main / java / org / opendaylight / protocol / pcep / impl / PCEPProtocolSessionPromise.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.protocol.pcep.impl;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.base.Preconditions;
13 import io.netty.bootstrap.Bootstrap;
14 import io.netty.channel.ChannelFuture;
15 import io.netty.channel.ChannelFutureListener;
16 import io.netty.channel.ChannelOption;
17 import io.netty.channel.EventLoop;
18 import io.netty.util.concurrent.DefaultPromise;
19 import io.netty.util.concurrent.EventExecutor;
20 import io.netty.util.concurrent.Future;
21 import io.netty.util.concurrent.Promise;
22 import java.net.InetSocketAddress;
23 import java.util.concurrent.TimeUnit;
24 import org.checkerframework.checker.lock.qual.GuardedBy;
25 import org.opendaylight.protocol.pcep.PCEPSession;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 // This class is thread-safe
30 public final class PCEPProtocolSessionPromise<S extends PCEPSession> extends DefaultPromise<S> {
31     private static final Logger LOG = LoggerFactory.getLogger(PCEPProtocolSessionPromise.class);
32     private InetSocketAddress address;
33     private final int retryTimer;
34     private final int connectTimeout;
35     private final Bootstrap b;
36     @GuardedBy("this")
37     private Future<?> pending;
38
39     PCEPProtocolSessionPromise(final EventExecutor executor, final InetSocketAddress address,
40             final int retryTimer, final int connectTimeout, final Bootstrap b) {
41         super(executor);
42         this.address = requireNonNull(address);
43         this.retryTimer = retryTimer;
44         this.connectTimeout = connectTimeout;
45         this.b = requireNonNull(b);
46     }
47
48     synchronized void connect() {
49         final PCEPProtocolSessionPromise<?> lock = this;
50
51         try {
52             LOG.debug("Promise {} attempting connect for {}ms", lock, this.connectTimeout);
53             if (this.address.isUnresolved()) {
54                 this.address = new InetSocketAddress(this.address.getHostName(), this.address.getPort());
55             }
56
57             this.b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, this.connectTimeout);
58             this.b.remoteAddress(this.address);
59             final ChannelFuture connectFuture = this.b.connect();
60             connectFuture.addListener(new BootstrapConnectListener());
61             this.pending = connectFuture;
62         } catch (Exception e) {
63             LOG.info("Failed to connect to {}", this.address, e);
64             this.setFailure(e);
65         }
66     }
67
68     @Override
69     public synchronized boolean cancel(final boolean mayInterruptIfRunning) {
70         if (super.cancel(mayInterruptIfRunning)) {
71             this.pending.cancel(mayInterruptIfRunning);
72             return true;
73         }
74
75         return false;
76     }
77
78     @Override
79     public synchronized Promise<S> setSuccess(final S result) {
80         LOG.debug("Promise {} completed", this);
81         return super.setSuccess(result);
82     }
83
84     private class BootstrapConnectListener implements ChannelFutureListener {
85         @Override
86         public void operationComplete(final ChannelFuture cf) {
87             synchronized (PCEPProtocolSessionPromise.this) {
88                 PCEPProtocolSessionPromise.LOG.debug("Promise {} connection resolved",
89                         PCEPProtocolSessionPromise.this);
90                 Preconditions.checkState(PCEPProtocolSessionPromise.this.pending.equals(cf));
91                 if (PCEPProtocolSessionPromise.this.isCancelled()) {
92                     if (cf.isSuccess()) {
93                         PCEPProtocolSessionPromise.LOG.debug("Closing channel for cancelled promise {}",
94                                 PCEPProtocolSessionPromise.this);
95                         cf.channel().close();
96                     }
97                 } else if (cf.isSuccess()) {
98                     PCEPProtocolSessionPromise.LOG.debug("Promise {} connection successful",
99                             PCEPProtocolSessionPromise.this);
100                 } else {
101                     PCEPProtocolSessionPromise.LOG.debug("Attempt to connect to {} failed",
102                             PCEPProtocolSessionPromise.this.address, cf.cause());
103
104                     if (PCEPProtocolSessionPromise.this.retryTimer == 0) {
105                         PCEPProtocolSessionPromise.LOG
106                                 .debug("Retry timer value is 0. Reconnection will not be attempted");
107                         PCEPProtocolSessionPromise.this.setFailure(cf.cause());
108                         return;
109                     }
110
111                     final EventLoop loop = cf.channel().eventLoop();
112                     loop.schedule(() -> {
113                         synchronized (PCEPProtocolSessionPromise.this) {
114                             PCEPProtocolSessionPromise.LOG.debug("Attempting to connect to {}",
115                                     PCEPProtocolSessionPromise.this.address);
116                             final Future<Void> reconnectFuture = PCEPProtocolSessionPromise.this.b.connect();
117                             reconnectFuture.addListener(BootstrapConnectListener.this);
118                             PCEPProtocolSessionPromise.this.pending = reconnectFuture;
119                         }
120                     }, PCEPProtocolSessionPromise.this.retryTimer, TimeUnit.SECONDS);
121                     PCEPProtocolSessionPromise.LOG.debug("Next reconnection attempt in {}s",
122                             PCEPProtocolSessionPromise.this.retryTimer);
123                 }
124             }
125         }
126     }
127 }