Esempio n. 1
0
 def got_forward_message(self, contact, obj):
   self.forward(
     key=obj.key,
     message=obj.message,
     raw_key=obj.raw_key,
     requester=Contact.from_tuple(obj.requester, self)
     )
Esempio n. 2
0
  def got_leave_message(self, contact, obj):
    # special case: only one node in the system
    if contact == self.contacts.me():
      # don't bother doing anything, just call the callback
      self.callback_manager.call(obj.request_id, contact)
      return

    for key in obj.data:
      self.data[key] = self.value_from_wire(obj.data[key])
    self.contacts.set_successor(Contact.from_tuple(obj.successor, self))
    self.contacts.get_successor().send(LeaveUpdateSuccessor(leaving=contact.to_tuple()))
    self.contacts.remove(contact)
    contact.send(LeaveResponse(request_id=obj.request_id))
Esempio n. 3
0
    def got_leave_message(self, contact, obj):
        # special case: only one node in the system
        if contact == self.contacts.me():
            # don't bother doing anything, just call the callback
            self.callback_manager.call(obj.request_id, contact)
            return

        for key in obj.data:
            self.data[key] = self.value_from_wire(obj.data[key])
        self.contacts.set_successor(Contact.from_tuple(obj.successor, self))
        self.contacts.get_successor().send(
            LeaveUpdateSuccessor(leaving=contact.to_tuple()))
        self.contacts.remove(contact)
        contact.send(LeaveResponse(request_id=obj.request_id))
Esempio n. 4
0
 def get_requester(self, contact, obj):
   if hasattr(obj, 'requester'):
     return Contact.from_tuple(obj.requester, self)
   return contact
Esempio n. 5
0
 def stabilize_got_successor_predecessor(self, contact, obj):
   x = Contact.from_tuple(obj.predecessor, self)
   if keyspace_compare(self.id, self.contacts.get_successor().id, x.id):
     self.contacts.set_successor(x)
   self.contacts.get_successor().send(StabilizeNotify())
Esempio n. 6
0
 def got_leave_update_successor(self, contact, obj):
   self.contacts.remove(Contact.from_tuple(obj.leaving, self))
   self.contacts.set_predecessor(contact)
Esempio n. 7
0
class DHTNode(MessageHandlerNode):
    """
   Chord node

   Messages sent recursively
   Maintains an in-memory dict of node data
   Shuffles data when nodes join and leave
   Provides some consistency through vector version numbers
  """
    def __init__(self,
                 ring_id=1,
                 id=None,
                 ip='127.0.0.1',
                 port=8080,
                 user_id=None):
        MessageHandlerNode.__init__(self, ip, port)
        self.set_timeout(0.25)
        self.id = id if id != None else random_key()
        sys.stdout.write('me: %s\n' % key_to_int(self.id))
        self.ring_id = ring_id
        self.user_id = user_id
        self.contacts = MultiRingChordContacts(
            Contact(ring_id=ring_id,
                    id=self.id,
                    ip=self.ip,
                    port=self.port,
                    network_protocol=self))
        self.messages_received = 0
        self.message_limit = None

        # self.data[string_to_key('physical_key')] = {
        #   'data': value,
        #   'version': VectorVersion(),
        #   'requires': VectorVersionList()
        #   }
        self.data = {}
        self.callback_manager = CallbackManager()
        self.next_finger_to_fix = 1

    def about_to_receive(self):
        pass

    def received_obj(self, ip, port, obj):
        if not isinstance(obj, DHTNodeMessage):
            return
        contact = Contact(ring_id=obj.ring_id,
                          id=obj.id,
                          ip=ip,
                          port=port,
                          network_protocol=self)
        if hasattr(obj, 'join') and obj.join:
            # this node is trying to join
            # don't include it in any finger tables for now
            pass
        else:
            self.add_contact(contact)
        sys.stdout.write('received %s from %s\n' %
                         (message_to_string(obj), contact))
        self.received_msg(contact, obj)

    def received_msg(self, contact, obj):
        self.messages_received += 1
        if self.message_limit and (self.messages_received >=
                                   self.message_limit):
            sys.stdout.write('reached message limit\n')
            sys.exit(1)
        # figure out which function handles this message type
        handler = DHTNode.get_message_handler(obj)
        if handler:
            # invoke handler
            handler(self, contact, obj)

    def add_contact(self, contact):
        self.contacts.add(contact)

    def remove_contact(self, contact_id):
        del self.contacts[contact_id]

    def owns_key(self, key):
        return keyspace_compare(self.id, self.contacts.get_successor().id, key)

# JOIN

    def join(self, ip, port):
        dummy_contact = Contact(ring_id=None,
                                id=None,
                                ip=ip,
                                port=port,
                                network_protocol=self)
        request_id = self.callback_manager.register(
            self.join_response_callback)
        dummy_contact.send(JoinMessage(request_id=request_id, join=True))
        return request_id

    @handlesrequest(JoinMessage)
    def got_join_message(self, contact, obj):
        if not self.owns_key(contact.id):
            self.forward(key=contact.id,
                         raw_key=True,
                         message=obj,
                         requester=contact)
            return

        old_successor = self.contacts.get_successor()

        critical_data = {}
        for key in self.data:
            if keyspace_compare(contact.id, old_successor.id,
                                string_to_key(key)):
                critical_data[key] = self.value_to_wire(self.data[key])

        # data shuffle: potentially large message
        contact.send(
            JoinResponse(request_id=obj.request_id,
                         successor=old_successor.to_tuple(),
                         data=critical_data))
        self.contacts.set_successor(contact)

    @handlesrequest(JoinResponse)
    def got_join_response(self, contact, obj):
        for key in obj.data:
            self.data[key] = self.value_from_wire(obj.data[key])
        self.callback_manager.call(obj.request_id, (contact, obj))
        self.stabilize()

    def join_response_callback(self, request_id, (contact, obj)):
        self.contacts.set_successor(Contact.from_tuple(obj.successor, self))
        self.contacts.set_predecessor(contact)
        sys.stdout.write('joined!\n')
        sys.stdout.write('  predecessor: %s\n' %
                         key_to_int(self.contacts.get_predecessor().id))
        sys.stdout.write('  me: %s\n' % key_to_int(self.id))
        sys.stdout.write('  successor: %s\n' %
                         key_to_int(self.contacts.get_successor().id))
Esempio n. 8
0
 def get_requester(self, contact, obj):
     if hasattr(obj, 'requester'):
         return Contact.from_tuple(obj.requester, self)
     return contact
Esempio n. 9
0
 def got_forward_message(self, contact, obj):
     self.forward(key=obj.key,
                  message=obj.message,
                  raw_key=obj.raw_key,
                  requester=Contact.from_tuple(obj.requester, self))
Esempio n. 10
0
 def stabilize_got_successor_predecessor(self, contact, obj):
     x = Contact.from_tuple(obj.predecessor, self)
     if keyspace_compare(self.id, self.contacts.get_successor().id, x.id):
         self.contacts.set_successor(x)
     self.contacts.get_successor().send(StabilizeNotify())
Esempio n. 11
0
 def got_leave_update_successor(self, contact, obj):
     self.contacts.remove(Contact.from_tuple(obj.leaving, self))
     self.contacts.set_predecessor(contact)