blob: 0d8d29f05629048b790d0e4d3dc6b9b51de23a74 [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
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070026
27import org.projectfloodlight.openflow.protocol.OFMessage;
28import org.projectfloodlight.openflow.protocol.OFType;
29
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080030import net.floodlightcontroller.core.IOFSwitch;
31import net.floodlightcontroller.threadpool.IThreadPoolService;
32
Jonathan Harta99ec672014-04-03 11:30:34 -070033
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080034/**
35 * A Future object used to retrieve asynchronous OFMessage replies. Unregisters
36 * and cancels itself by default after 60 seconds. This class is meant to be
37 * sub-classed and proper behavior added to the handleReply method, and
38 * termination of the Future to be handled in the isFinished method.
39 *
40 * @author David Erickson (daviderickson@cs.stanford.edu)
41 */
42public abstract class OFMessageFuture<V> implements Future<V> {
43
44 protected IThreadPoolService threadPool;
45 protected volatile boolean canceled;
46 protected CountDownLatch latch;
47 protected OFType responseType;
48 protected volatile V result;
49 protected IOFSwitch sw;
50 protected Runnable timeoutTimer;
51 protected int transactionId;
52 protected static final long DEFAULT_TIMEOUT = 60;
53 protected static final TimeUnit DEFAULT_TIMEOUT_UNIT = TimeUnit.SECONDS;
54
55 public OFMessageFuture(IThreadPoolService tp,
Ray Milkey269ffb92014-04-03 14:43:30 -070056 IOFSwitch sw, OFType responseType, int transactionId) {
57 this(tp, sw, responseType, transactionId,
58 DEFAULT_TIMEOUT, DEFAULT_TIMEOUT_UNIT);
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080059 }
60
61 public OFMessageFuture(IThreadPoolService tp,
Ray Milkey269ffb92014-04-03 14:43:30 -070062 IOFSwitch sw, OFType responseType, int transactionId, long timeout, TimeUnit unit) {
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080063 this.threadPool = tp;
64 this.canceled = false;
65 this.latch = new CountDownLatch(1);
66 this.responseType = responseType;
67 this.sw = sw;
68 this.transactionId = transactionId;
69
70 final OFMessageFuture<V> future = this;
71 timeoutTimer = new Runnable() {
72 @Override
73 public void run() {
74 if (timeoutTimer == this)
75 future.cancel(true);
76 }
77 };
78 threadPool.getScheduledExecutor().schedule(timeoutTimer, timeout, unit);
79 }
80
81 protected void unRegister() {
82 this.timeoutTimer = null;
83 }
84
Ray Milkey269ffb92014-04-03 14:43:30 -070085
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -080086 public void deliverFuture(IOFSwitch sw, OFMessage msg) {
87 if (transactionId == msg.getXid()) {
88 handleReply(sw, msg);
89 if (isFinished()) {
90 unRegister();
91 this.latch.countDown();
92 }
93 }
94 }
95
96 /**
97 * Used to handle the specific expected message this Future was reigstered
98 * for, the specified msg parameter is guaranteed to match the type and
99 * transaction id specified.
Ray Milkey269ffb92014-04-03 14:43:30 -0700100 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800101 * @param sw
102 * @param msg
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800103 */
104 protected abstract void handleReply(IOFSwitch sw, OFMessage msg);
105
106 /**
107 * Called directly after handleReply, subclasses implement this method to
108 * indicate when the future can deregister itself from receiving future
109 * messages, and when it is safe to return the results to any waiting
110 * threads.
Ray Milkey269ffb92014-04-03 14:43:30 -0700111 *
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -0800112 * @return when this Future has completed its work
113 */
114 protected abstract boolean isFinished();
115
116 /* (non-Javadoc)
117 * @see java.util.concurrent.Future#cancel(boolean)
118 */
119 @Override
120 public boolean cancel(boolean mayInterruptIfRunning) {
121 if (isDone()) {
122 return false;
123 } else {
124 unRegister();
125 canceled = true;
126 this.latch.countDown();
127 return !isDone();
128 }
129 }
130
131 /* (non-Javadoc)
132 * @see java.util.concurrent.Future#isCancelled()
133 */
134 @Override
135 public boolean isCancelled() {
136 return canceled;
137 }
138
139 /* (non-Javadoc)
140 * @see java.util.concurrent.Future#isDone()
141 */
142 @Override
143 public boolean isDone() {
144 return this.latch.getCount() == 0;
145 }
146
147 /* (non-Javadoc)
148 * @see java.util.concurrent.Future#get()
149 */
150 @Override
151 public V get() throws InterruptedException, ExecutionException {
152 this.latch.await();
153 return result;
154 }
155
156 /* (non-Javadoc)
157 * @see java.util.concurrent.Future#get(long, java.util.concurrent.TimeUnit)
158 */
159 @Override
160 public V get(long timeout, TimeUnit unit) throws InterruptedException,
161 ExecutionException, TimeoutException {
162 this.latch.await(timeout, unit);
163 return result;
164 }
165
166 public int getTransactionId() {
167 return transactionId;
168 }
169
170 public void setTransactionId(int transactionId) {
171 this.transactionId = transactionId;
172 }
173}