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 <yamah...@valinux.co.jp>
---
change v1 -> v2:
- replace select.poll with select.select for simplicity instead of
  monkey patching
---
 python/ovs/poller.py |   71 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/python/ovs/poller.py b/python/ovs/poller.py
index e459c58..e4294e3 100644
--- a/python/ovs/poller.py
+++ b/python/ovs/poller.py
@@ -13,13 +13,80 @@
 # 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 that does monkey patch to select module 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 python is used so that
+# performance isn't so important.
+# If eventlet/gevent isn't used, we can use select.poll by replacing
+# SelectPoll with select.poll class
+# SelectPoll = select.poll
+class _SelectSelect(object):
+    """ select.poll emulation by using select.select.
+    Only register and poll are needed at the moment.
+    """
+    def __init__(self):
+        super(_SelectSelect, self).__init__()
+        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)
+
+    @staticmethod
+    def _events_update(events_dict, fd, event):
+        """Emulate 'collections.defaultdict(int)[fd] |= event' with dict"""
+        events = events_dict.setdefault(fd, 0)
+        events_dict[fd] = events | event
+
+    def poll(self, timeout):
+        if timeout == -1:
+            # epoll uses -1 for indifinite 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:
+            self._events_update(events_dict, fd, select.POLLIN)
+        for fd in wlist:
+            self._events_update(events_dict, fd, select.POLLOUT)
+        for fd in xlist:
+            self._events_update(events_dict, fd, select.POLLERR |
+                                select.POLLHUP | select.POLLNVAL)
+        return [(fd, events) for (fd, events) in events_dict.items()]
+
+
+SelectPoll = _SelectSelect
+# SelectPoll = select.poll
+
+
 class Poller(object):
     """High-level wrapper around the "poll" system call.
 
@@ -122,5 +189,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
-- 
1.7.1.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to