예제 #1
0
 def _add_peer(self, host):
     client = gevent.socket.create_connection((host, self.port), source_address=(self.interface, 0))
     self.connections[host] = client
     for line in util.line_protocol(client):
         ack, task_id = line.split(':', 1)
         if ack == 'scheduled' and task_id in self.scheduled_acks:
             self.scheduled_acks[task_id].put(True)
     print "disconnected from peer %s" % host
     self._remove_peer(host)
예제 #2
0
 def _run(self):
     while True:
         try:
             self.socket = gevent.socket.create_connection((self.interface, 6002), source_address=(self.interface, 0))
         
             for line in util.line_protocol(self.socket):
                 event, payload = line.split(':', 1)
                 self.callback(event, payload)
         except IOError:
             pass
                 
         print "disconnected from dispatcher, retrying..."
예제 #3
0
 def connect(self):
     """ 
     Connects to the currently known leader. It maintains a connection expecting
     JSON lists of hosts in the cluster. It should receive a list on connection,
     however, if a list of one, this is a redirect to the leader (you hit a node
     in the cluster that's not the leader). We also maintain a keepalive. If we
     disconnect, it does a leader elect and reconnects.
     """
     while True:
         logger.info("Connecting to leader %s on port %s" % (self.leader, self.port))
         try:
             client = util.connect_and_retry((self.leader, self.port), 
                     source_address=(self.interface, 0), max_retries=5)
         except IOError:
             raise ClusterError("Unable to connect to leader: %s" % self.leader)
         logger.info("Connected to leader")
         # Use TCP keepalives
         keepalive = gevent.spawn_later(5, lambda: client.send('\n'))
         try:
             for line in util.line_protocol(client, strip=False):
                 if line == '\n':
                     # Keepalive ack from leader
                     keepalive.kill()
                     keepalive = gevent.spawn_later(5, lambda: client.send('\n'))
                 else:
                     new_cluster = json.loads(line)
                     if len(new_cluster) == 1:
                         # Cluster of one means you have the wrong leader
                         self.leader = new_cluster[0]
                         logger.info("Redirected to %s..." % self.leader)
                         raise NewLeader()
                     else:
                         self.cluster = set(new_cluster)
                         if self.callback:
                             self.callback(self.cluster.copy())
             self.cluster.remove(self.leader)
             candidates = list(self.cluster)
             candidates.sort()
             self.leader = candidates[0]
             logger.info("New leader %s..." % self.leader)
             # TODO: if i end up thinking i'm the leader when i'm not
             # then i will not rejoin the cluster
             raise NewLeader()
         except NewLeader:
             if self.callback:
                 self.callback(self.cluster.copy())
             if not self.is_leader():
                 gevent.sleep(1) # TODO: back off loop, not a sleep
             else:
                 break
예제 #4
0
 def _backend_server(self, socket, address):
     for line in util.line_protocol(socket):
         action, payload = line.split(':', 1)
         
         if action == 'schedule':
             task = Task.unserialize(payload)
             task.schedule(self.dispatcher)
             self.scheduled[task.id] = task
             socket.send('scheduled:%s\n' % task.id)
             print "scheduled: %s" % task.id
         
         elif action == 'cancel':
             task_id = payload
             print "canceled: %s" % task_id
             self.scheduled.pop(task_id).cancel()
         
         elif action == 'reschedule':
             task_id, eta = payload.split(':', 1)
             eta = int(eta)
             print "rescheduled: %s for %s" % (task_id, eta)
             self.scheduled[task_id].reschedule(self.dispatcher, eta)
예제 #5
0
 def _connection_handler(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. 
     """
     #print 'New connection from %s:%s' % address
     if not self.is_leader():
         socket.send(json.dumps([self.leader]))
         socket.close()
     else:
         self._update(add={'host': address[0], 'socket': socket})
         timeout = gevent.spawn_later(10, lambda: self._shutdown(socket))            
         for line in util.line_protocol(socket, strip=False):
             timeout.kill()
             timeout = gevent.spawn_later(10, lambda: self._shutdown(socket))
             socket.send('\n')
             #print "keepalive from %s:%s" % address
         #print "client disconnected"
         self._update(remove=address[0])
예제 #6
0
 def _connection_handler(self, socket, address):
     print "pair connected"
     self.scheduler = socket
     for line in util.line_protocol(socket):
         self.queue.put(line)
     print "pair dropped"