mirror of
https://github.com/openvswitch/ovs
synced 2025-10-13 14:07:02 +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.
|
# limitations under the License.
|
||||||
|
|
||||||
import errno
|
import errno
|
||||||
import select
|
|
||||||
import ovs.timeval
|
import ovs.timeval
|
||||||
import ovs.vlog
|
import ovs.vlog
|
||||||
|
import select
|
||||||
|
import socket
|
||||||
|
|
||||||
vlog = ovs.vlog.Vlog("poller")
|
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):
|
class Poller(object):
|
||||||
"""High-level wrapper around the "poll" system call.
|
"""High-level wrapper around the "poll" system call.
|
||||||
|
|
||||||
@@ -122,5 +181,5 @@ class Poller(object):
|
|||||||
vlog.dbg("%s on fd %d" % (s, fd))
|
vlog.dbg("%s on fd %d" % (s, fd))
|
||||||
|
|
||||||
def __reset(self):
|
def __reset(self):
|
||||||
self.poll = select.poll()
|
self.poll = _SelectPoll()
|
||||||
self.timeout = -1
|
self.timeout = -1
|
||||||
|
Reference in New Issue
Block a user