blob: 9e2a7ed236c75d7f00c9a4e3b36d0d6a5bb72d73 [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/**
Ray Milkey269ffb92014-04-03 14:43:30 -07002 * Copyright 2011, Big Switch Networks, Inc.
3 * Originally created by David Erickson, Stanford University
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 * not use this file except in compliance with the License. You may obtain
7 * a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations
15 * under the License.
16 **/
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080017
18package net.floodlightcontroller.core.internal;
19
20import java.util.concurrent.CountDownLatch;
21import java.util.concurrent.ExecutionException;
22import java.util.concurrent.Future;
23import java.util.concurrent.TimeUnit;
24import java.util.concurrent.TimeoutException;
25
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080026import net.floodlightcontroller.core.IOFSwitch;
27import net.floodlightcontroller.threadpool.IThreadPoolService;
28
Jonathan Harta99ec672014-04-03 11:30:34 -070029import org.openflow.protocol.OFMessage;
30import org.openflow.protocol.OFType;
31
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080032/**
33 * A Future object used to retrieve asynchronous OFMessage replies. Unregisters
34 * and cancels itself by default after 60 seconds. This class is meant to be
35 * sub-classed and proper behavior added to the handleReply method, and
36 * termination of the Future to be handled in the isFinished method.
37 *
38 * @author David Erickson (daviderickson@cs.stanford.edu)
39 */
40public abstract class OFMessageFuture<V> implements Future<V> {
41
42 protected IThreadPoolService threadPool;
43 protected volatile boolean canceled;
44 protected CountDownLatch latch;
45 protected OFType responseType;
46 protected volatile V result;
47 protected IOFSwitch sw;
48 protected Runnable timeoutTimer;
49 protected int transactionId;
50 protected static final long DEFAULT_TIMEOUT = 60;
51 protected static final TimeUnit DEFAULT_TIMEOUT_UNIT = TimeUnit.SECONDS;
52
53 public OFMessageFuture(IThreadPoolService tp,
Ray Milkey269ffb92014-04-03 14:43:30 -070054 IOFSwitch sw, OFType responseType, int transactionId) {
55 this(tp, sw, responseType, transactionId,
56 DEFAULT_TIMEOUT, DEFAULT_TIMEOUT_UNIT);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080057 }
58
59 public OFMessageFuture(IThreadPoolService tp,
Ray Milkey269ffb92014-04-03 14:43:30 -070060 IOFSwitch sw, OFType responseType, int transactionId, long timeout, TimeUnit unit) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080061 this.threadPool = tp;
62 this.canceled = false;
63 this.latch = new CountDownLatch(1);
64 this.responseType = responseType;
65 this.sw = sw;
66 this.transactionId = transactionId;
67
68 final OFMessageFuture<V> future = this;
69 timeoutTimer = new Runnable() {
70 @Override
71 public void run() {
72 if (timeoutTimer == this)
73 future.cancel(true);
74 }
75 };
76 threadPool.getScheduledExecutor().schedule(timeoutTimer, timeout, unit);
77 }
78
79 protected void unRegister() {
80 this.timeoutTimer = null;
81 }
82
Ray Milkey269ffb92014-04-03 14:43:30 -070083
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080084 public void deliverFuture(IOFSwitch sw, OFMessage msg) {
85 if (transactionId == msg.getXid()) {
86 handleReply(sw, msg);
87 if (isFinished()) {
88 unRegister();
89 this.latch.countDown();
90 }
91 }
92 }
93
94 /**
95 * Used to handle the specific expected message this Future was reigstered
96 * for, the specified msg parameter is guaranteed to match the type and
97 * transaction id specified.
Ray Milkey269ffb92014-04-03 14:43:30 -070098 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080099 * @param sw
100 * @param msg
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800101 */
102 protected abstract void handleReply(IOFSwitch sw, OFMessage msg);
103
104 /**
105 * Called directly after handleReply, subclasses implement this method to
106 * indicate when the future can deregister itself from receiving future
107 * messages, and when it is safe to return the results to any waiting
108 * threads.
Ray Milkey269ffb92014-04-03 14:43:30 -0700109 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800110 * @return when this Future has completed its work
111 */
112 protected abstract boolean isFinished();
113
114 /* (non-Javadoc)
115 * @see java.util.concurrent.Future#cancel(boolean)
116 */
117 @Override
118 public boolean cancel(boolean mayInterruptIfRunning) {
119 if (isDone()) {
120 return false;
121 } else {
122 unRegister();
123 canceled = true;
124 this.latch.countDown();
125 return !isDone();
126 }
127 }
128
129 /* (non-Javadoc)
130 * @see java.util.concurrent.Future#isCancelled()
131 */
132 @Override
133 public boolean isCancelled() {
134 return canceled;
135 }
136
137 /* (non-Javadoc)
138 * @see java.util.concurrent.Future#isDone()
139 */
140 @Override
141 public boolean isDone() {
142 return this.latch.getCount() == 0;
143 }
144
145 /* (non-Javadoc)
146 * @see java.util.concurrent.Future#get()
147 */
148 @Override
149 public V get() throws InterruptedException, ExecutionException {
150 this.latch.await();
151 return result;
152 }
153
154 /* (non-Javadoc)
155 * @see java.util.concurrent.Future#get(long, java.util.concurrent.TimeUnit)
156 */
157 @Override
158 public V get(long timeout, TimeUnit unit) throws InterruptedException,
159 ExecutionException, TimeoutException {
160 this.latch.await(timeout, unit);
161 return result;
162 }
163
164 public int getTransactionId() {
165 return transactionId;
166 }
167
168 public void setTransactionId(int transactionId) {
169 this.transactionId = transactionId;
170 }
171}