mirror of
https://github.com/openvswitch/ovs
synced 2025-09-05 00:35:33 +00:00
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>
This commit is contained in:
committed by
Ben Pfaff
parent
78a3fff6c3
commit
ed815d9bd2
@@ -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
|
||||
|
Reference in New Issue
Block a user