def sendall (self, data, flags=0): # *NOTE: gross, copied code from ssl.py becase it's not factored well enough to be used as-is if self._sslobj: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to sendall() on %s" % self.__class__) amount = len(data) count = 0 while (count < amount): v = self.send(data[count:]) count += v if v == 0: trampoline(self, write=True, timeout_exc=timeout_exc('timed out')) return amount else: while True: try: return socket.sendall(self, data, flags) except orig_socket.error as e: if self.act_non_blocking: raise if get_errno(e) == errno.EWOULDBLOCK: trampoline(self, write=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) if get_errno(e) in SOCKET_CLOSED: return '' raise
def recv(self, buflen=1024, flags=0): # *NOTE: gross, copied code from ssl.py becase it's not factored well enough to be used as-is if self._sslobj: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to recv() on %s" % self.__class__) read = self.read(buflen) return read else: while True: try: return socket.recv(self, buflen, flags) except orig_socket.error as e: if self.act_non_blocking: raise if get_errno(e) == errno.EWOULDBLOCK: try: trampoline( self, read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) except IOClosed: return b'' if get_errno(e) in SOCKET_CLOSED: return b'' raise
def sendall(self, data, flags=0): # *NOTE: gross, copied code from ssl.py becase it's not factored well enough to be used as-is if self._sslobj: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to sendall() on %s" % self.__class__) amount = len(data) count = 0 data_to_send = data while (count < amount): v = self.send(data_to_send) count += v if v == 0: trampoline(self, write=True, timeout_exc=timeout_exc('timed out')) else: data_to_send = data[count:] return amount else: while True: try: return socket.sendall(self, data, flags) except orig_socket.error as e: if self.act_non_blocking: raise erno = get_errno(e) if erno in greenio.SOCKET_BLOCKING: trampoline(self, write=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) elif erno in greenio.SOCKET_CLOSED: return '' raise
def main(): # pragma: no cover get_env('INFRABOX_VERSION') get_env('INFRABOX_DATABASE_DB') get_env('INFRABOX_DATABASE_USER') get_env('INFRABOX_DATABASE_PASSWORD') get_env('INFRABOX_DATABASE_HOST') get_env('INFRABOX_DATABASE_PORT') cluster_name = get_env('INFRABOX_CLUSTER_NAME') conn = connect_db() conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) logger.info("Connected to database") elect_leader(conn, 'github-review', cluster_name) curs = conn.cursor() curs.execute("LISTEN job_update;") logger.info("Waiting for job updates") pool = eventlet.GreenPool() while True: trampoline(conn, read=True) conn.poll() while conn.notifies: notify = conn.notifies.pop(0) event = json.loads(notify.payload) if not is_leader(conn, 'github-review', cluster_name, exit=False): logger.info("skip job: %s because I'm not leader", event.get('job_id')) continue pool.spawn_n(handle, event)
def subscribe(self, q: eventlet.Queue) -> NoReturn: """Green thread process waiting for NOTIFYs on the channel and feeding them to the queue. Args: q: event queue through which to pipe NOTIFY events to the main thread. """ # Subscribe to notification channel self.database.listen_on_channel(self.channel, self.key) # Infinite listening loop while True: # self.database.pool._used[self.key] is the connection object # corresponding to [key] in the conneciton pool # spawns a green thread and return control once there is a # notification to read trampoline(self.database.pool._used[self.key], read=True) # once there is a notification --> poll self.database.pool._used[self.key].poll() while self.database.pool._used[self.key].notifies: # extract notify: notify = self.database.pool._used[self.key].notifies.pop() # block until slot available in queue to insert Notify: q.put(notify)
def _socket_connect(self, addr): real_connect = socket.connect if self.act_non_blocking: return real_connect(self, addr) else: # *NOTE: gross, copied code from greenio because it's not factored # well enough to reuse if self.gettimeout() is None: while True: try: return real_connect(self, addr) except orig_socket.error as exc: if get_errno(exc) in CONNECT_ERR: trampoline(self, write=True) elif get_errno(exc) in CONNECT_SUCCESS: return else: raise else: end = time.time() + self.gettimeout() while True: try: real_connect(self, addr) except orig_socket.error as exc: if get_errno(exc) in CONNECT_ERR: trampoline( self, write=True, timeout=end - time.time(), timeout_exc=timeout_exc('timed out')) elif get_errno(exc) in CONNECT_SUCCESS: return else: raise if time.time() >= end: raise timeout_exc('timed out')
def recv(self, buflen=1024, flags=0): # *NOTE: gross, copied code from ssl.py becase it's not factored well enough to be used as-is if self._sslobj: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to recv() on %s" % self.__class__) read = self.read(buflen) return read else: while True: try: return socket.recv(self, buflen, flags) except orig_socket.error as e: if self.act_non_blocking: raise if get_errno(e) == errno.EWOULDBLOCK: try: trampoline(self, read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) except IOClosed: return b'' if get_errno(e) in SOCKET_CLOSED: return b'' raise
def _socket_connect(self, addr): real_connect = socket.connect if self.act_non_blocking: return real_connect(self, addr) else: # *NOTE: gross, copied code from greenio because it's not factored # well enough to reuse if self.gettimeout() is None: while True: try: return real_connect(self, addr) except orig_socket.error as exc: if get_errno(exc) in CONNECT_ERR: trampoline(self, write=True) elif get_errno(exc) in CONNECT_SUCCESS: return else: raise else: end = time.time() + self.gettimeout() while True: try: real_connect(self, addr) except orig_socket.error as exc: if get_errno(exc) in CONNECT_ERR: trampoline(self, write=True, timeout=end-time.time(), timeout_exc=timeout_exc('timed out')) elif get_errno(exc) in CONNECT_SUCCESS: return else: raise if time.time() >= end: raise timeout_exc('timed out')
def accept(self): """Accepts a new connection from a remote client, and returns a tuple containing that new connection wrapped with a server-side SSL channel, and the address of the remote client.""" # RDW grr duplication of code from greenio if self.act_non_blocking: newsock, addr = socket.accept(self) else: while True: try: newsock, addr = socket.accept(self) break except orig_socket.error as e: if get_errno(e) not in greenio.SOCKET_BLOCKING: raise trampoline(self, read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) new_ssl = type(self)( newsock, server_side=True, do_handshake_on_connect=False, suppress_ragged_eofs=self.suppress_ragged_eofs, _context=self._context, ) return (new_ssl, addr)
def sendall (self, data, flags=0): # *NOTE: gross, copied code from ssl.py becase it's not factored well enough to be used as-is if self._sslobj: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to sendall() on %s" % self.__class__) amount = len(data) count = 0 while (count < amount): v = self.send(data[count:]) count += v return amount else: while True: try: return socket.sendall(self, buflen, flags) except orig_socket.error, e: if self.act_non_blocking: raise if get_errno(e) == errno.EWOULDBLOCK: trampoline(self, write=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) if get_errno(e) in SOCKET_CLOSED: return '' raise
def connectionwatcher(sock, proc_weakref, *exc_args): logger = logging.getLogger("drivel.utils.connwatch.connectionwatcher") enums = [errno.EPIPE, errno.ECONNRESET] def kill(): p = proc_weakref() if p: greenthread.kill(p, *exc_args) while True: hubs.trampoline(sock, read=True) try: if hasattr(sock, "read"): data = sock.read() else: data = sock.recv(4096) if not data: kill() return else: logging.error("got unexpected data %r from sock %d" % (data, sock.fileno())) except socket.error, e: if e[0] in enums: kill() return logging.error("unexpected socket.error %d: %s" % (e[0], errno.errorcode[e[0]])) except IOError, e: if e.errno in enums: kill() return logging.error("unexpected IOError %d: %s" % (e.errno, errno.errorcode[e.errno]))
def send(self, data, flags=0): if self._sslobj: return self._call_trampolining( super(GreenSSLSocket, self).send, data, flags) else: trampoline(self, write=True, timeout_exc=timeout_exc('timed out')) return socket.send(self, data, flags)
def accept(self): """Accepts a new connection from a remote client, and returns a tuple containing that new connection wrapped with a server-side SSL channel, and the address of the remote client.""" # RDW grr duplication of code from greenio if self.act_non_blocking: newsock, addr = socket.accept(self) else: while True: try: newsock, addr = socket.accept(self) set_nonblocking(newsock) break except orig_socket.error as e: if get_errno(e) not in greenio.SOCKET_BLOCKING: raise trampoline(self, read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) new_ssl = type(self)( newsock, keyfile=self.keyfile, certfile=self.certfile, server_side=True, cert_reqs=self.cert_reqs, ssl_version=self.ssl_version, ca_certs=self.ca_certs, do_handshake_on_connect=False, suppress_ragged_eofs=self.suppress_ragged_eofs) return (new_ssl, addr)
def recvfrom(self, addr, buflen=1024, flags=0): if not self.act_non_blocking: trampoline(self, read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) return super(GreenSSLSocket, self).recvfrom(addr, buflen, flags)
def accept(self): """Accepts a new connection from a remote client, and returns a tuple containing that new connection wrapped with a server-side SSL channel, and the address of the remote client.""" # RDW grr duplication of code from greenio if self.act_non_blocking: newsock, addr = socket.accept(self) else: while True: try: newsock, addr = socket.accept(self) set_nonblocking(newsock) break except orig_socket.error as e: if get_errno(e) != errno.EWOULDBLOCK: raise trampoline(self, read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) new_ssl = type(self)(newsock, keyfile=self.keyfile, certfile=self.certfile, server_side=True, cert_reqs=self.cert_reqs, ssl_version=self.ssl_version, ca_certs=self.ca_certs, do_handshake_on_connect=self.do_handshake_on_connect, suppress_ragged_eofs=self.suppress_ragged_eofs) return (new_ssl, addr)
def recv_into(self, *args): if not self.act_non_blocking: trampoline(self.fd, read=True, timeout=self.gettimeout(), timeout_exc=socket.timeout("timed out")) return self.fd.recv_into(*args)
def recvfrom_into(self, buffer, nbytes=None, flags=0): if not self.act_non_blocking: trampoline(self, read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out')) return super(GreenSSLSocket, self).recvfrom_into(buffer, nbytes, flags)
def sendto(self, data, addr, flags=0): # *NOTE: gross, copied code from ssl.py becase it's not factored well enough to be used as-is if self._sslobj: raise ValueError("sendto not allowed on instances of %s" % self.__class__) else: trampoline(self, write=True, timeout_exc=timeout_exc("timed out")) return socket.sendto(self, data, addr, flags)
def recv(self, buflen): trampoline(self, read=True, timeout=self._timeout) while True: try: return os.read(self._fileno, buflen) except OSError, e: if get_errno(e) != errno.EAGAIN: raise IOError(*e.args)
def readfd(fd): while True: try: return os.read(fd, 1) except OSError as e: if e.errno != errno.EAGAIN: raise hubs.trampoline(fd, read=True)
def send(self, data): while True: try: os.write(self._fileno, data) except OSError as e: if get_errno(e) not in SOCKET_BLOCKING: raise IOError(*e.args) trampoline(self, write=True)
def sendto(self, data, addr, flags=0): # *NOTE: gross, copied code from ssl.py becase it's not factored well enough to be used as-is if self._sslobj: raise ValueError("sendto not allowed on instances of %s" % self.__class__) else: trampoline(self, write=True, timeout_exc=timeout_exc('timed out')) return socket.sendto(self, data, addr, flags)
def recv(self, buflen): while True: try: data = os.read(self._fileno, buflen) return data except OSError as e: if get_errno(e) not in SOCKET_BLOCKING: raise IOError(*e.args) trampoline(self, read=True)
def write(self, data): while True: try: return _original_os.write(self._fileno, data) except OSError as e: if get_errno(e) not in SOCKET_BLOCKING: raise IOError(*e.args) else: trampoline(self, write=True)
def recv(self, buflen): while True: try: data = os.read(self._fileno, buflen) return data except OSError, e: if get_errno(e) != errno.EAGAIN: raise IOError(*e.args) trampoline(self, read=True)
def _eventlet_sendfile(fdout, fdin, offset, nbytes): while True: try: return o_sendfile(fdout, fdin, offset, nbytes) except OSError as e: if e.args[0] == errno.EAGAIN: trampoline(fdout, write=True) else: raise
def go(): desc = eventlet.connect(('127.0.0.1', bound_port)) try: hubs.trampoline(desc, read=True, timeout=0.1) except eventlet.TimeoutError: assert False, "Timed out" server.close() desc.close() done[0] = True
def connect_ex(self, address): if self.act_non_blocking: return self.fd.connect_ex(address) fd = self.fd if self.gettimeout() is None: while not socket_connect(fd, address): try: trampoline(fd, write=True) except socket.error, ex: return get_errno(ex)
def _send_message(self, msg, flags=0): flags |= __zmq__.NOBLOCK while True: try: super(Socket, self)._send_message(msg, flags) return except __zmq__.ZMQError, e: if e.errno != EAGAIN: raise trampoline(self, write=True)
def _send_copy(self, data, flags=0, copy=True): flags |= __zmq__.NOBLOCK while True: try: super(Socket, self)._send_copy(data, flags) return except __zmq__.ZMQError, e: if e.errno != EAGAIN: raise trampoline(self, write=True)
def _recv_copy(self, flags=0): flags |= __zmq__.NOBLOCK while True: try: m = super(Socket, self)._recv_copy(flags) if m: return m except __zmq__.ZMQError, e: if e.errno != EAGAIN: raise trampoline(self, read=True)
def accept(self): if self.act_non_blocking: return self.fd.accept() fd = self.fd while True: res = socket_accept(fd) if res is not None: client, addr = res set_nonblocking(client) return type(self)(client), addr trampoline(fd, read=True, timeout=self.gettimeout(), timeout_exc=socket.timeout("timed out"))
def inner(pubsub): cnn = psycopg2.connect(self.dsn, self.database, self.user, self.password, self.host, self.port) cnn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) cur = cnn.cursor() cur.execute("LISTEN %s;" % channel) while 1: trampoline(cnn, read=True) cnn.poll() while cnn.notifies: n = cnn.notifies.pop() f(n, pubsub)
def eventlet_wait_callback(conn, timeout=-1): """A wait callback useful to allow eventlet to work with Psycopg.""" while 1: state = conn.poll() if state == extensions.POLL_OK: break elif state == extensions.POLL_READ: trampoline(conn.fileno(), read=True) elif state == extensions.POLL_WRITE: trampoline(conn.fileno(), write=True) else: raise psycopg2.OperationalError("Bad result from poll: %r" % state)
def _recv_message(self, flags=0, track=False): flags |= __zmq__.NOBLOCK while True: try: m = super(Socket, self)._recv_message(flags, track) if m is not None: return m except __zmq__.ZMQError, e: if e.errno != EAGAIN: raise trampoline(self, read=True)
def __listen(socketio): conn = connect_db() conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) cur = conn.cursor() cur.execute("LISTEN job_update") while True: trampoline(conn, read=True) conn.poll() while conn.notifies: n = conn.notifies.pop() socketio.start_background_task(__handle_event, json.loads(n.payload), socketio)
def pg_listen(queue, channel): """Open a postgres connection and add notifications to the queue. """ connection = psycopg2.connect(dsn) connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) cursor = connection.cursor() cursor.execute("LISTEN {};".format(channel)) while 1: trampoline(connection, read=True) connection.poll() while connection.notifies: item = connection.notifies.pop() queue.put(item)
def eventlet_wait_callback(conn, timeout=-1): """A wait callback useful to allow eventlet to work with Psycopg.""" while 1: state = conn.poll() if state == extensions.POLL_OK: break elif state == extensions.POLL_READ: trampoline(conn.fileno(), read=True) elif state == extensions.POLL_WRITE: trampoline(conn.fileno(), write=True) else: raise psycopg2.OperationalError( "Bad result from poll: %r" % state)
def write(self, data): view = memoryview(data) datalen = len(data) offset = 0 while offset < datalen: try: written = _original_os.write(self._fileno, view[offset:]) except OSError as e: if get_errno(e) not in SOCKET_BLOCKING: raise IOError(*e.args) trampoline(self, write=True) else: offset += written return offset
def _call_trampolining(self, func, *a, **kw): if self.act_non_blocking: return func(*a, **kw) else: while True: try: return func(*a, **kw) except SSLError as exc: if get_errno(exc) == SSL_ERROR_WANT_READ: trampoline(self, read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc("timed out")) elif get_errno(exc) == SSL_ERROR_WANT_WRITE: trampoline(self, write=True, timeout=self.gettimeout(), timeout_exc=timeout_exc("timed out")) else: raise
def dblisten(q): """ Open a db connection and add notifications to *q*. """ cnn = psycopg2.connect(dsn) cnn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) cur = cnn.cursor() cur.execute("LISTEN data;") while 1: trampoline(cnn, read=True) cnn.poll() while cnn.notifies: n = cnn.notifies.pop() q.put(n)
def read(fd, n): """read(fd, buffersize) -> string Read a file descriptor.""" while True: try: return __original_read__(fd, n) except (OSError, IOError) as e: if get_errno(e) != errno.EAGAIN: raise except socket.error as e: if get_errno(e) == errno.EPIPE: return '' raise hubs.trampoline(fd, read=True)
def recv(self, buflen, flags=0): fd = self.fd if self.act_non_blocking: return fd.recv(buflen, flags) while True: try: return fd.recv(buflen, flags) except socket.error, e: if get_errno(e) in SOCKET_BLOCKING: pass elif get_errno(e) in SOCKET_CLOSED: return "" else: raise trampoline(fd, read=True, timeout=self.gettimeout(), timeout_exc=socket.timeout("timed out"))
def write(fd, st): """write(fd, string) -> byteswritten Write a string to a file descriptor. """ while True: try: return __original_write__(fd, st) except (OSError, IOError) as e: if get_errno(e) != errno.EAGAIN: raise except socket.error as e: if get_errno(e) != errno.EPIPE: raise hubs.trampoline(fd, write=True)
def wait_cb(conn): """A wait callback useful to allow eventlet to work with Psycopg.""" while 1: if panic: raise Exception('whatever') state = conn.poll() if state == extensions.POLL_OK: break elif state == extensions.POLL_READ: trampoline(conn.fileno(), read=True) elif state == extensions.POLL_WRITE: trampoline(conn.fileno(), write=True) else: raise psycopg2.OperationalError( "Bad result from poll: %r" % state)