aboutsummaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorIsaku Yamahata <yamahata@valinux.co.jp>2012-09-05 19:38:26 +0900
committerBen Pfaff <blp@nicira.com>2012-09-05 09:10:44 -0700
commited815d9bd28422a490fe370d7804d24bcd676806 (patch)
tree72645159cd1b85c176cbb085467c71636934f484 /python
parent78a3fff6c3b2f7943bcfd7301c666934834d2a0e (diff)
python/ovs/poller: use select.select instead of select.poll.
eventlet/gevent doesn't work well with select.poll because select.poll blocks python interpreter as a whole instead of switching from the current thread which is about to block to other runnable thread. So ovsdb python binding can't be used with eventlet/gevent. Emulate select.poll with select.select because using python means that performance isn't so important. Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> Signed-off-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'python')
-rw-r--r--python/ovs/poller.py63
1 files changed, 61 insertions, 2 deletions
diff --git a/python/ovs/poller.py b/python/ovs/poller.py
index e459c582..5c89f231 100644
--- a/python/ovs/poller.py
+++ b/python/ovs/poller.py
@@ -13,13 +13,72 @@
# limitations under the License.
import errno
-import select
import ovs.timeval
import ovs.vlog
+import select
+import socket
vlog = ovs.vlog.Vlog("poller")
+# eventlet/gevent doesn't support select.poll. If select.poll is used,
+# python interpreter is blocked as a whole instead of switching from the
+# current thread that is about to block to other runnable thread.
+# So emulate select.poll by select.select because using python means that
+# performance isn't so important.
+class _SelectSelect(object):
+ """ select.poll emulation by using select.select.
+ Only register and poll are needed at the moment.
+ """
+ def __init__(self):
+ self.rlist = []
+ self.wlist = []
+ self.xlist = []
+
+ def register(self, fd, events):
+ if isinstance(fd, socket.socket):
+ fd = fd.fileno()
+ assert isinstance(fd, int)
+ if events & select.POLLIN:
+ self.rlist.append(fd)
+ events &= ~select.POLLIN
+ if events & select.POLLOUT:
+ self.wlist.append(fd)
+ events &= ~select.POLLOUT
+ if events:
+ self.xlist.append(fd)
+
+ def poll(self, timeout):
+ if timeout == -1:
+ # epoll uses -1 for infinite timeout, select uses None.
+ timeout = None
+ else:
+ timeout = float(timeout) / 1000
+
+ rlist, wlist, xlist = select.select(self.rlist, self.wlist, self.xlist,
+ timeout)
+ # collections.defaultdict is introduced by python 2.5 and
+ # XenServer uses python 2.4. We don't use it for XenServer.
+ # events_dict = collections.defaultdict(int)
+ # events_dict[fd] |= event
+ events_dict = {}
+ for fd in rlist:
+ events_dict[fd] = events_dict.get(fd, 0) | select.POLLIN
+ for fd in wlist:
+ events_dict[fd] = events_dict.get(fd, 0) | select.POLLOUT
+ for fd in xlist:
+ events_dict[fd] = events_dict.get(fd, 0) | (select.POLLERR |
+ select.POLLHUP |
+ select.POLLNVAL)
+ return events_dict.items()
+
+
+_SelectPoll = _SelectSelect
+# If eventlet/gevent isn't used, we can use select.poll by replacing
+# _SelectPoll with select.poll class
+# _SelectPoll = select.poll
+
+
class Poller(object):
"""High-level wrapper around the "poll" system call.
@@ -122,5 +181,5 @@ class Poller(object):
vlog.dbg("%s on fd %d" % (s, fd))
def __reset(self):
- self.poll = select.poll()
+ self.poll = _SelectPoll()
self.timeout = -1