blob: f81a2f587ca4cf9146cf8fd19e191ad6d96cee27 [file] [log] [blame]
Dan Talaycoea8ad802010-02-22 20:30:18 -08001
2"""
3Utilities for the OpenFlow test framework
4"""
5
6import random
Rich Laneb64ce3d2012-07-26 15:37:57 -07007import time
Rich Lane4dfd5e12012-12-22 19:48:01 -08008import os
Rich Lane7e1d5c52012-12-24 14:08:32 -08009import fcntl
Rich Lane2e37ec22012-12-26 09:47:39 -080010import logging
Dan Talaycoea8ad802010-02-22 20:30:18 -080011
Rich Lanee55abf72012-07-26 20:11:42 -070012default_timeout = None # set by oft
Rich Lane48f6aed2014-03-23 15:51:02 -070013default_negative_timeout = None # set by oft
Rich Lanee55abf72012-07-26 20:11:42 -070014
Dan Talaycoea8ad802010-02-22 20:30:18 -080015def gen_xid():
16 return random.randrange(1,0xffffffff)
Rich Laneb64ce3d2012-07-26 15:37:57 -070017
18"""
19Wait on a condition variable until the given function returns non-None or a timeout expires.
20The condition variable must already be acquired.
Rich Lane8806bc42012-07-26 19:18:37 -070021The timeout value -1 means use the default timeout.
Rich Laneb64ce3d2012-07-26 15:37:57 -070022There is deliberately no support for an infinite timeout.
Rich Laneb64ce3d2012-07-26 15:37:57 -070023"""
Rich Lane8806bc42012-07-26 19:18:37 -070024def timed_wait(cv, fn, timeout=-1):
25 if timeout == -1:
Rich Lanee55abf72012-07-26 20:11:42 -070026 timeout = default_timeout
Rich Lane8806bc42012-07-26 19:18:37 -070027
Rich Laneb64ce3d2012-07-26 15:37:57 -070028 end_time = time.time() + timeout
29 while True:
Rich Laneb64ce3d2012-07-26 15:37:57 -070030 val = fn()
31 if val != None:
32 return val
33
34 remaining_time = end_time - time.time()
35 cv.wait(remaining_time)
Rich Lane8806bc42012-07-26 19:18:37 -070036
37 if time.time() > end_time:
38 return None
Rich Lane4dfd5e12012-12-22 19:48:01 -080039
40class EventDescriptor():
41 """
42 Similar to a condition variable, but can be passed to select().
43 Only supports one waiter.
44 """
45
46 def __init__(self):
47 self.pipe_rd, self.pipe_wr = os.pipe()
Rich Lane7e1d5c52012-12-24 14:08:32 -080048 fcntl.fcntl(self.pipe_wr, fcntl.F_SETFL, os.O_NONBLOCK)
Rich Lane4dfd5e12012-12-22 19:48:01 -080049
50 def __del__(self):
51 os.close(self.pipe_rd)
52 os.close(self.pipe_wr)
53
54 def notify(self):
Rich Lane7e1d5c52012-12-24 14:08:32 -080055 try:
56 os.write(self.pipe_wr, "x")
57 except OSError as e:
Rich Lane2e37ec22012-12-26 09:47:39 -080058 logging.warn("Failed to notify EventDescriptor: %s", e)
Rich Lane4dfd5e12012-12-22 19:48:01 -080059
60 def wait(self):
61 os.read(self.pipe_rd, 1)
62
63 def fileno(self):
64 return self.pipe_rd