summaryrefslogtreecommitdiff
path: root/redis/selector.py
diff options
context:
space:
mode:
Diffstat (limited to 'redis/selector.py')
-rw-r--r--redis/selector.py196
1 files changed, 0 insertions, 196 deletions
diff --git a/redis/selector.py b/redis/selector.py
deleted file mode 100644
index bce84a5..0000000
--- a/redis/selector.py
+++ /dev/null
@@ -1,196 +0,0 @@
-import errno
-import select
-from redis.exceptions import RedisError
-
-
-_DEFAULT_SELECTOR = None
-
-
-class BaseSelector(object):
- """
- Base class for all Selectors
- """
- def __init__(self, sock):
- self.sock = sock
-
- def can_read(self, timeout=0):
- """
- Return True if data is ready to be read from the socket,
- otherwise False.
-
- This doesn't guarentee that the socket is still connected, just that
- there is data to read.
-
- Automatically retries EINTR errors based on PEP 475.
- """
- while True:
- try:
- return self.check_can_read(timeout)
- except (select.error, IOError) as ex:
- if self.errno_from_exception(ex) == errno.EINTR:
- continue
- return False
-
- def is_ready_for_command(self, timeout=0):
- """
- Return True if the socket is ready to send a command,
- otherwise False.
-
- Automatically retries EINTR errors based on PEP 475.
- """
- while True:
- try:
- return self.check_is_ready_for_command(timeout)
- except (select.error, IOError) as ex:
- if self.errno_from_exception(ex) == errno.EINTR:
- continue
- return False
-
- def check_can_read(self, timeout):
- """
- Perform the can_read check. Subclasses should implement this.
- """
- raise NotImplementedError
-
- def check_is_ready_for_command(self, timeout):
- """
- Perform the is_ready_for_command check. Subclasses should
- implement this.
- """
- raise NotImplementedError
-
- def close(self):
- """
- Close the selector.
- """
- self.sock = None
-
- def errno_from_exception(self, ex):
- """
- Get the error number from an exception
- """
- if hasattr(ex, 'errno'):
- return ex.errno
- elif ex.args:
- return ex.args[0]
- else:
- return None
-
-
-if hasattr(select, 'select'):
- class SelectSelector(BaseSelector):
- """
- A select-based selector that should work on most platforms.
-
- This is the worst poll strategy and should only be used if no other
- option is available.
- """
- def check_can_read(self, timeout):
- """
- Return True if data is ready to be read from the socket,
- otherwise False.
-
- This doesn't guarentee that the socket is still connected, just
- that there is data to read.
- """
- return bool(select.select([self.sock], [], [], timeout)[0])
-
- def check_is_ready_for_command(self, timeout):
- """
- Return True if the socket is ready to send a command,
- otherwise False.
- """
- r, w, e = select.select([self.sock], [self.sock], [self.sock],
- timeout)
- return bool(w and not r and not e)
-
-
-if hasattr(select, 'poll'):
- class PollSelector(BaseSelector):
- """
- A poll-based selector that should work on (almost?) all versions
- of Unix
- """
- READ_MASK = select.POLLIN | select.POLLPRI
- ERROR_MASK = select.POLLERR | select.POLLHUP
- WRITE_MASK = select.POLLOUT
-
- _READ_POLLER_MASK = READ_MASK | ERROR_MASK
- _READY_POLLER_MASK = READ_MASK | ERROR_MASK | WRITE_MASK
-
- def __init__(self, sock):
- super(PollSelector, self).__init__(sock)
- self.read_poller = select.poll()
- self.read_poller.register(sock, self._READ_POLLER_MASK)
- self.ready_poller = select.poll()
- self.ready_poller.register(sock, self._READY_POLLER_MASK)
-
- def close(self):
- """
- Close the selector.
- """
- for poller in (self.read_poller, self.ready_poller):
- try:
- poller.unregister(self.sock)
- except (KeyError, ValueError):
- # KeyError is raised if somehow the socket was not
- # registered
- # ValueError is raised if the socket's file descriptor is
- # negative.
- # In either case, we can't do anything better than to
- # remove the reference to the poller.
- pass
- self.read_poller = None
- self.ready_poller = None
- self.sock = None
-
- def check_can_read(self, timeout=0):
- """
- Return True if data is ready to be read from the socket,
- otherwise False.
-
- This doesn't guarentee that the socket is still connected, just
- that there is data to read.
- """
- timeout = int(timeout * 1000)
- events = self.read_poller.poll(timeout)
- return bool(events and events[0][1] & self.READ_MASK)
-
- def check_is_ready_for_command(self, timeout=0):
- """
- Return True if the socket is ready to send a command,
- otherwise False
- """
- timeout = timeout * 1000
- events = self.ready_poller.poll(timeout)
- return bool(events and events[0][1] == self.WRITE_MASK)
-
-
-def has_selector(selector):
- "Determine if the current platform has the selector available"
- try:
- if selector == 'poll':
- # the select module offers the poll selector even if the platform
- # doesn't support it. Attempt to poll for nothing to make sure
- # poll is available
- p = select.poll()
- p.poll(0)
- else:
- # the other selectors will fail when instantiated
- getattr(select, selector)().close()
- return True
- except (OSError, AttributeError):
- return False
-
-
-def DefaultSelector(sock):
- "Return the best selector for the platform"
- global _DEFAULT_SELECTOR
- if _DEFAULT_SELECTOR is None:
- if has_selector('poll'):
- _DEFAULT_SELECTOR = PollSelector
- elif hasattr(select, 'select'):
- _DEFAULT_SELECTOR = SelectSelector
- else:
- raise RedisError('Platform does not support any selectors')
- return _DEFAULT_SELECTOR(sock)