def handle(self, socket, address): """ If not a leader, a node will simply return a single item list pointing to the leader. Otherwise, it will add the host of the connected client to the cluster roster, broadcast to all nodes the new roster, and wait for keepalives. If no keepalive within timeout or the client drops, it drops it from the roster and broadcasts to all remaining nodes. """ self.logger.debug('New connection from %s:%s' % address) if not self.manager.is_leader: socket.send(json.dumps({'leader': self.manager.client.leader_address[0], 'port': self.manager.client.leader_address[1]})) socket.close() self.logger.debug("Redirected to %s:%s" % self.manager.client.leader_address) else: socket.send(self._cluster_message()) sockfile = socket.makefile() name = sockfile.readline() if not name: return if name == '\n': name = address[0] else: name = name.strip() self._update(add={'host': name, 'socket': socket}) # TODO: Use TCP keepalives timeout = self._client_timeout(socket) for line in util.line_protocol(sockfile, strip=False): timeout.kill() timeout = self._client_timeout(socket) socket.send('\n') self.logger.debug("Keepalive from %s:%s" % address) self.logger.debug("Client disconnected from %s:%s" % address) self._update(remove=name)
def handle(self, socket): self.set_ready() self.logger.debug("Connected to leader") client_address = self.client_hostname or socket.getsockname()[0] socket.send('%s\n' % client_address) # TODO: Use TCP keepalives keepalive = self._server_keepalive(socket) try: for line in util.line_protocol(socket, strip=False): if line == '\n': # Keepalive ack from leader keepalive.kill() keepalive = self._server_keepalive(socket) else: cluster = json.loads(line) if 'leader' in cluster: # Means you have the wrong leader, redirect host = cluster['leader'] port = cluster.get('port', self.leader_address[1]) self.leader_address = (host, port) self.logger.info("Redirected to %s:%s..." % self.leader_address) raise NewLeader() elif client_address in cluster['cluster']: # Only report cluster once I'm a member self.manager.cluster = set(cluster['cluster']) self.manager.trigger_callback() self._leader_election() except NewLeader: self.manager.trigger_callback() if self.leader_address[0] == client_address: self.manager.is_leader = True self.stop() else: return
def test_does_connect(): class SimpleServer(gevent.server.StreamServer): def handle(self, socket, address): socket.sendall("hello and goodbye!") socket.shutdown(0) server = SimpleServer(('127.0.0.1', 0)) server.start() client = util.connect_and_retry(('127.0.0.1', server.server_port)) lines = [line for line in util.line_protocol(client)] assert len(lines) == 1, "Didn't receive the line" server.stop()
def test_eventual_connect(): class SimpleServer(gevent.server.StreamServer): def handle(self, socket, address): socket.sendall("hello and goodbye!") socket.shutdown(0) server = SimpleServer(('127.0.0.1', 16667)) gevent.spawn_later(0.5, server.start) client = util.connect_and_retry(('127.0.0.1', 16667), max_delay=1) lines = [line for line in util.line_protocol(client)] assert len(lines) == 1, "Didn't receive the line" server.stop()