factor out ofutils.timed_wait and simplify Controller.poll
diff --git a/src/python/oftest/controller.py b/src/python/oftest/controller.py
index 764662f..e2641b7 100644
--- a/src/python/oftest/controller.py
+++ b/src/python/oftest/controller.py
@@ -457,14 +457,15 @@
return
self.handlers[msg_type] = handler
- def poll(self, exp_msg=None, timeout=None):
+ def poll(self, exp_msg=None, timeout=-1):
"""
Wait for the next OF message received from the switch.
@param exp_msg If set, return only when this type of message
is received (unless timeout occurs).
- @param timeout If None, do not block. Otherwise, sleep in
- intervals of 1 second until message is received.
+
+ @param timeout Maximum number of seconds to wait for the message.
+ Pass -1 for the default timeout.
@retval A pair (msg, pkt) where msg is a message object and pkt
the string representing the packet as received from the socket.
@@ -472,14 +473,15 @@
The data members in the message are in host endian order.
If an error occurs, (None, None) is returned
-
- The current queue is searched for a message of the desired type
- before sleeping on message in events.
"""
- self.logger.debug("Poll for " + ofp_type_map[exp_msg])
+ # TODO make this configurable
+ if timeout == -1:
+ timeout = 1
- # Looks for the packet in the queue
+ self.logger.debug("Poll for %s, timeout %fs" % (ofp_type_map[exp_msg], timeout))
+
+ # Take the packet from the queue
def grab():
if len(self.packets) > 0:
if not exp_msg:
@@ -496,31 +498,17 @@
return (msg, pkt)
# Not found
self.logger.debug("Packet not in queue")
- return (None, None)
+ return None
- # Non-blocking case
- if timeout is None or timeout <= 0:
- return grab()
-
- msg = pkt = None
- self.logger.debug("Entering timeout (%fs)" % timeout)
- end_time = time.time() + timeout
with self.packets_cv:
- while True:
- if time.time() > end_time:
- self.logger.debug("Poll time out")
- return (None, None)
+ ret = timed_wait(self.packets_cv, grab)
- (msg, pkt) = grab()
- if msg != None:
- self.logger.debug("Got msg " + str(msg))
- return (msg, pkt)
-
- # Go to sleep
- remaining_time = end_time - time.time()
- self.packets_cv.wait(remaining_time)
-
- return (msg, pkt)
+ if ret != None:
+ (msg, pkt) = ret
+ self.logger.debug("Got message %s" % str(msg))
+ return (msg, pkt)
+ else:
+ return (None, None)
def transact(self, msg, timeout=-1, zero_xid=False):
"""
diff --git a/src/python/oftest/ofutils.py b/src/python/oftest/ofutils.py
index 5daba2f..9e59c5d 100644
--- a/src/python/oftest/ofutils.py
+++ b/src/python/oftest/ofutils.py
@@ -4,6 +4,26 @@
"""
import random
+import time
def gen_xid():
return random.randrange(1,0xffffffff)
+
+"""
+Wait on a condition variable until the given function returns non-None or a timeout expires.
+The condition variable must already be acquired.
+There is deliberately no support for an infinite timeout.
+TODO: get the default timeout from configuration
+"""
+def timed_wait(cv, fn, timeout=10):
+ end_time = time.time() + timeout
+ while True:
+ if time.time() > end_time:
+ return None
+
+ val = fn()
+ if val != None:
+ return val
+
+ remaining_time = end_time - time.time()
+ cv.wait(remaining_time)