示例#1
0
    def stabilize(self):
        try:
            s = self.send(self.state.successor, 'get_predecessor')
            resp = s.recv(1024).decode('utf-8')
            if resp != 'None':
                x_ip, x_port = resp.split(':')
                x = Address(x_ip, x_port)
                s.close()
                if in_range(x.__hash__(), self.state.id,
                            self.state.successor.__hash__()):
                    self.state.lock.acquire()
                    self.state.finger[0] = x.__hash__()
                    self.state.successor = x
                    self.state.addr_dict[str(x.__hash__())] = x
                    self.state.lock.release()
            # else:
        except:
            self.state.lock.acquire()
            del self.state.addr_dict[str(self.state.successor.__hash__())]
            self.state.successor = self.state.local_address
            self.state.finger[0] = self.state.id
            self.state.lock.release()

        self.send(self.state.successor,
                  'notify {} {}'.format(self.state.ip,
                                        self.state.port)).close()
示例#2
0
 def fix_finger(self):
   self.state.lock.acquire()
   self.state.i = self.state.i + 1
   if self.state.i > M:
     self.state.i = 1
   s = self.send(self.state.local_address, 'find_successor {}'.format((self.state.id + pow(2, self.state.i-1)) % 2**M))
   n_ip, n_port = s.recv(1024).decode('utf-8').split(':')
   n = Address(n_ip, n_port)
   s.close()
   self.state.addr_dict[str(n.__hash__())] = n
   self.state.finger[self.state.i-1] = n.__hash__()
   # debug(self, "Finger:", self.state.finger)
   self.state.lock.release()
示例#3
0
 def notify(self, ip, port):
   n_ = Address(ip, port)
   if self.state.predecessor == None or\
      in_range(n_.__hash__(), self.state.predecessor.__hash__(), self.state.id):
     self.state.lock.acquire()      
     self.state.predecessor = n_
     self.state.lock.release()   
示例#4
0
class State:
    def __init__(self, port=8000):
        self.in_ring = False  # becomes True when this node has created or joined a ring
        self.ip = socket.gethostbyname(socket.gethostname())
        self.port = port
        self.local_address = Address(self.ip, self.port)
        self.id = self.local_address.__hash__()
        self.predecessor = None
        self.successor = None
        self.finger = [None] * M  # contains finger nodes' Chord ids
        self.addr_dict = {
        }  # key: a Chord id; value: corresponding Address (IP/port)
        self.i = 1
        self.lock = Lock()
示例#5
0
    def __init__(self, address):
        # ip addresses
        self._address = address
        self._base_address = address[0]

        # all slots, a ring
        nodes = [None for x in range(NUM_SLOTS)]
        self._nodes = nodes

        # create an initial nodes and add it to the Chord ring
        addr = Address(self._base_address)
        index = addr.__hash__()

        # avoid collision of hashing
        while self._nodes[index] is not None:
            index = (index + 1) % NUM_SLOTS
        self._nodes[index] = Node(addr, self)

        for x in range(1, len(address)):
            self.addNode(address[x], self._base_address)
示例#6
0
class Local(object):
    def __init__(self, local_address, remote_address=None):
        self.address_ = Address(quick_lazy_ip(), local_address.port)
        self.local_addr = local_address
        print("self id = %s" % self.id())
        self.shutdown_ = False
        # list of successors
        self.successors_ = []
        # join the DHT
        self.join(remote_address)
        # we don't have deamons until we start
        self.daemons_ = {}
        # initially no commands
        self.command_ = []

    # is this id within our range?
    def is_ours(self, id):
        assert id >= 0 and id < SIZE
        return inrange(id, self.predecessor_.id(1), self.id(1))

    def shutdown(self):
        self.shutdown_ = Trues
        self.socket_.shutdown(socket.SHUT_RDWR)
        self.socket_.close()

    # logging function
    def log(self, info):
        f = open("./chord.log", "a+")
        f.write(str(self.id()) + " : " + info + "\n")
        f.close()
        #print str(self.id()) + " : " +  info

    def start(self):
        # start the daemons
        self.daemons_['run'] = Daemon(self, 'run')
        self.daemons_['fix_fingers'] = Daemon(self, 'fix_fingers')
        self.daemons_['stabilize'] = Daemon(self, 'stabilize')
        self.daemons_['update_successors'] = Daemon(self, 'update_successors')
        for key in self.daemons_:
            self.daemons_[key].start()

        self.log("started")

    def ping(self):
        return True

    def join(self, remote_address=None):
        # initially just set successor
        print "joining"
        self.finger_ = [None for x in range(LOGSIZE)]

        self.predecessor_ = None

        if remote_address:
            print "poking", remote_address
            remote = Remote(remote_address)
            print "fingering"
            self.finger_[0] = remote.find_successor(self.id())
        else:
            self.finger_[0] = self
        print "joined"
        self.log("joined")

    @repeat_and_sleep(STABILIZE_INT)
    @retry_on_socket_error(STABILIZE_RET)
    def stabilize(self):
        self.log("stabilize")
        suc = self.successor()
        # We may have found that x is our new successor iff
        # - x = pred(suc(n))
        # - x exists
        # - x is in range (n, suc(n))
        # - [n+1, suc(n)) is non-empty
        # fix finger_[0] if successor failed
        if suc.id() != self.finger_[0].id():
            self.finger_[0] = suc
        x = suc.predecessor()
        if x != None and \
           inrange(x.id(), self.id(1), suc.id()) and \
           self.id(1) != suc.id() and \
           x.ping():
            self.finger_[0] = x
        # We notify our new successor about us
        self.successor().notify(self)
        # Keep calling us
        return True

    def notify(self, remote):
        # Someone thinks they are our predecessor, they are iff
        # - we don't have a predecessor
        # OR
        # - the new node r is in the range (pred(n), n)
        # OR
        # - our previous predecessor is dead
        self.log("notify")
        if self.predecessor() == None or \
           inrange(remote.id(), self.predecessor().id(1), self.id()) or \
           not self.predecessor().ping():
            self.predecessor_ = remote

    @repeat_and_sleep(FIX_FINGERS_INT)
    def fix_fingers(self):
        # Randomly select an entry in finger_ table and update its value
        self.log("fix_fingers")
        i = random.randrange(LOGSIZE - 1) + 1
        self.finger_[i] = self.find_successor(self.id(1 << i))
        # Keep calling us
        return True

    @repeat_and_sleep(UPDATE_SUCCESSORS_INT)
    @retry_on_socket_error(UPDATE_SUCCESSORS_RET)
    def update_successors(self):
        self.log("update successor")
        suc = self.successor()
        # if we are not alone in the ring, calculate
        if suc.id() != self.id():
            successors = [suc]
            suc_list = suc.get_successors()
            if suc_list and len(suc_list):
                successors += suc_list
            # if everything worked, we update
            self.successors_ = successors
        return True

    def get_successors(self):
        self.log("get_successors")
        return [(node.address_.ip, node.address_.port)
                for node in self.successors_[:N_SUCCESSORS - 1]]

    def id(self, offset=0):
        return (self.address_.__hash__() + offset) % SIZE

    def successor(self):
        # We make sure to return an existing successor, there `might`
        # be redundance between finger_[0] and successors_[0], but
        # it doesn't harm
        for remote in [self.finger_[0]] + self.successors_:
            #print remote.address_
            if remote.ping():
                self.finger_[0] = remote
                return remote
        print("No successor available, aborting")
        self.shutdown_ = True
        sys.exit(-1)

    def predecessor(self):
        return self.predecessor_

    #@retry_on_socket_error(FIND_SUCCESSOR_RET)
    def find_successor(self, id):
        # The successor of a key can be us iff
        # - we have a pred(n)
        # - id is in (pred(n), n]
        self.log("find_successor")
        if self.predecessor() and \
           inrange(id, self.predecessor().id(1), self.id(1)):
            return self
        node = self.find_predecessor(id)
        return node.successor()

    #@retry_on_socket_error(FIND_PREDECESSOR_RET)
    def find_predecessor(self, id):
        self.log("find_predecessor")
        node = self
        # If we are alone in the ring, we are the pred(id)
        if node.successor().id() == node.id():
            return node
        while not inrange(id, node.id(1), node.successor().id(1)):
            node = node.closest_preceding_finger(id)
        return node

    def closest_preceding_finger(self, id):
        # first fingers in decreasing distance, then successors in
        # increasing distance.
        self.log("closest_preceding_finger")
        for remote in reversed(self.successors_ + self.finger_):
            if remote != None and inrange(remote.id(), self.id(1),
                                          id) and remote.ping():
                return remote
        return self

    def run(self):
        # should have a threadpool here :/
        # listen to incomming connections
        self.socket_ = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket_.bind((self.local_addr.ip, int(self.local_addr.port)))
        self.socket_.listen(10)

        while 1:
            self.log("run loop")
            try:
                conn, addr = self.socket_.accept()
            except socket.error:
                self.shutdown_ = True
                break

            request = read_from_socket(conn)
            command = request.split(' ')[0]

            # we take the command out
            request = request[len(command) + 1:]

            # defaul : "" = not respond anything
            result = json.dumps("")
            if command == 'get_successor':
                successor = self.successor()
                result = json.dumps(
                    (successor.address_.ip, successor.address_.port))
            if command == 'get_predecessor':
                # we can only reply if we have a predecessor
                if self.predecessor_ != None:
                    predecessor = self.predecessor_
                    result = json.dumps(
                        (predecessor.address_.ip, predecessor.address_.port))
            if command == 'find_successor':
                successor = self.find_successor(int(request))
                result = json.dumps(
                    (successor.address_.ip, successor.address_.port))
            if command == 'closest_preceding_finger':
                closest = self.closest_preceding_finger(int(request))
                result = json.dumps(
                    (closest.address_.ip, closest.address_.port))
            if command == 'notify':
                npredecessor = Address(
                    request.split(' ')[0], int(request.split(' ')[1]))
                self.notify(Remote(npredecessor))
            if command == 'get_successors':
                result = json.dumps(self.get_successors())

            # or it could be a user specified operation
            for t in self.command_:
                if command == t[0]:
                    result = t[1](request)

            send_to_socket(conn, result)
            conn.close()

            if command == 'shutdown':
                self.socket_.close()
                self.shutdown_ = True
                self.log("shutdown started")
                break
        self.log("execution terminated")

    def register_command(self, cmd, callback):
        self.command_.append((cmd, callback))

    def unregister_command(self, cmd):
        pass
示例#7
0
class Local(object):
	def __init__(self, local_address, remote_address = None):
		self.address_ = Address(quick_lazy_ip(),local_address.port)
		self.local_addr =  local_address
		print("self id = %s" % self.id())
		self.shutdown_ = False
		# list of successors
		self.successors_ = []
		# join the DHT
		self.join(remote_address)
		# we don't have deamons until we start
		self.daemons_ = {}
		# initially no commands
		self.command_ = []

	
	# is this id within our range?
	def is_ours(self, id):
		assert id >= 0 and id < SIZE
		return inrange(id, self.predecessor_.id(1), self.id(1))

	def shutdown(self):
		self.shutdown_ = Trues
		self.socket_.shutdown(socket.SHUT_RDWR)
		self.socket_.close()

	# logging function
	def log(self, info):
	    f = open("./chord.log", "a+")
	    f.write(str(self.id()) + " : " +  info + "\n")
	    f.close()
	    #print str(self.id()) + " : " +  info

	def start(self):
		# start the daemons
		self.daemons_['run'] = Daemon(self, 'run')
		self.daemons_['fix_fingers'] = Daemon(self, 'fix_fingers')
		self.daemons_['stabilize'] = Daemon(self, 'stabilize')
		self.daemons_['update_successors'] = Daemon(self, 'update_successors')
		for key in self.daemons_:
			self.daemons_[key].start()

		self.log("started")

	def ping(self):
		return True

	def join(self, remote_address = None):
		# initially just set successor
		print "joining"
		self.finger_ = [None for x in range(LOGSIZE)]

		self.predecessor_ = None

		if remote_address:
			print "poking", remote_address
			remote = Remote(remote_address)
			print "fingering"
			self.finger_[0] = remote.find_successor(self.id())
		else:
			self.finger_[0] = self
		print "joined"
		self.log("joined")

	@repeat_and_sleep(STABILIZE_INT)
	@retry_on_socket_error(STABILIZE_RET)
	def stabilize(self):
		self.log("stabilize")
		suc = self.successor()
		# We may have found that x is our new successor iff
		# - x = pred(suc(n))
		# - x exists
		# - x is in range (n, suc(n))
		# - [n+1, suc(n)) is non-empty
		# fix finger_[0] if successor failed
		if suc.id() != self.finger_[0].id():
			self.finger_[0] = suc
		x = suc.predecessor()
		if x != None and \
		   inrange(x.id(), self.id(1), suc.id()) and \
		   self.id(1) != suc.id() and \
		   x.ping():
			self.finger_[0] = x
		# We notify our new successor about us
		self.successor().notify(self)
		# Keep calling us
		return True

	def notify(self, remote):
		# Someone thinks they are our predecessor, they are iff
		# - we don't have a predecessor
		# OR
		# - the new node r is in the range (pred(n), n)
		# OR
		# - our previous predecessor is dead
		self.log("notify")
		if self.predecessor() == None or \
		   inrange(remote.id(), self.predecessor().id(1), self.id()) or \
		   not self.predecessor().ping():
			self.predecessor_ = remote

	@repeat_and_sleep(FIX_FINGERS_INT)
	def fix_fingers(self):
		# Randomly select an entry in finger_ table and update its value
		self.log("fix_fingers")
		i = random.randrange(LOGSIZE - 1) + 1
		self.finger_[i] = self.find_successor(self.id(1<<i))
		# Keep calling us
		return True

	@repeat_and_sleep(UPDATE_SUCCESSORS_INT)
	@retry_on_socket_error(UPDATE_SUCCESSORS_RET)
	def update_successors(self):
		self.log("update successor")
		suc = self.successor()
		# if we are not alone in the ring, calculate
		if suc.id() != self.id():
			successors = [suc]
			suc_list = suc.get_successors()
			if suc_list and len(suc_list):
				successors += suc_list
			# if everything worked, we update
			self.successors_ = successors
		return True

	def get_successors(self):
		self.log("get_successors")
		return [(node.address_.ip, node.address_.port) for node in self.successors_[:N_SUCCESSORS-1]]

	def id(self, offset = 0):
		return (self.address_.__hash__() + offset) % SIZE

	def successor(self):
		# We make sure to return an existing successor, there `might`
		# be redundance between finger_[0] and successors_[0], but
		# it doesn't harm
		for remote in [self.finger_[0]] + self.successors_:
			#print remote.address_
			if remote.ping():
				self.finger_[0] = remote
				return remote
		print("No successor available, aborting")
		self.shutdown_ = True
		sys.exit(-1)

	def predecessor(self):
		return self.predecessor_

	#@retry_on_socket_error(FIND_SUCCESSOR_RET)
	def find_successor(self, id):
		# The successor of a key can be us iff
		# - we have a pred(n)
		# - id is in (pred(n), n]
		self.log("find_successor")
		if self.predecessor() and \
		   inrange(id, self.predecessor().id(1), self.id(1)):
			return self
		node = self.find_predecessor(id)
		return node.successor()

	#@retry_on_socket_error(FIND_PREDECESSOR_RET)
	def find_predecessor(self, id):
		self.log("find_predecessor")
		node = self
		# If we are alone in the ring, we are the pred(id)
		if node.successor().id() == node.id():
			return node
		while not inrange(id, node.id(1), node.successor().id(1)):
			node = node.closest_preceding_finger(id)
		return node

	def closest_preceding_finger(self, id):
		# first fingers in decreasing distance, then successors in
		# increasing distance.
		self.log("closest_preceding_finger")
		for remote in reversed(self.successors_ + self.finger_):
			if remote != None and inrange(remote.id(), self.id(1), id) and remote.ping():
				return remote
		return self

	def run(self):
		# should have a threadpool here :/
		# listen to incomming connections
		self.socket_ = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.socket_.bind((self.local_addr.ip, int(self.local_addr.port)))
		self.socket_.listen(10)

		while 1:
			self.log("run loop")
			try:
				conn, addr = self.socket_.accept()
			except socket.error:
				self.shutdown_ = True
				break

			request = read_from_socket(conn)
			command = request.split(' ')[0]

			# we take the command out
			request = request[len(command) + 1:]

			# defaul : "" = not respond anything
			result = json.dumps("")
			if command == 'get_successor':
				successor = self.successor()
				result = json.dumps((successor.address_.ip, successor.address_.port))
			if command == 'get_predecessor':
				# we can only reply if we have a predecessor
				if self.predecessor_ != None:
					predecessor = self.predecessor_
					result = json.dumps((predecessor.address_.ip, predecessor.address_.port))
			if command == 'find_successor':
				successor = self.find_successor(int(request))
				result = json.dumps((successor.address_.ip, successor.address_.port))
			if command == 'closest_preceding_finger':
				closest = self.closest_preceding_finger(int(request))
				result = json.dumps((closest.address_.ip, closest.address_.port))
			if command == 'notify':
				npredecessor = Address(request.split(' ')[0], int(request.split(' ')[1]))
				self.notify(Remote(npredecessor))
			if command == 'get_successors':
				result = json.dumps(self.get_successors())

			# or it could be a user specified operation
			for t in self.command_:
				if command == t[0]:
					result = t[1](request)

			send_to_socket(conn, result)
			conn.close()

			if command == 'shutdown':
				self.socket_.close()
				self.shutdown_ = True
				self.log("shutdown started")
				break
		self.log("execution terminated")

	def register_command(self, cmd, callback):
		self.command_.append((cmd, callback))

	def unregister_command(self, cmd):
		pass