Exemple #1
0
    def __init__(self, nodetype, addr=options.addr, port=options.port, givenbootstraplist=options.bootstrap, debugoption=options.debug, objectfilename=options.objectfilename, objectname=options.objectname, instantiateobj=False, configpath=options.configpath, logger=options.logger):
        """Node State
        - addr: hostname for Node, detected automatically
        - port: port for Node, can be taken from the commandline (-p [port]) or
        detected automatically by binding.
        - connectionpool: ConnectionPool that keeps all Connections Node knows about
        - type: type of the corresponding Node: NODE_ACCEPTOR | NODE_REPLICA | NODE_NAMESERVER
        - alive: liveness of Node
        - outstandingmessages: collection of sent but not-yet-acked messages
        - socket: server socket for Node
        - me: Peer object that represents Node
        - id: id for Node (addr:port)
        - groups: other Peers in the system that Node knows about. Node.groups is indexed by the
        corresponding node_name (NODE_ACCEPTOR | NODE_REPLICA | NODE_NAMESERVER), which returns a Group
        """
        self.addr = addr if addr else findOwnIP()
        self.port = port
        self.connectionpool = ConnectionPool()
        self.type = nodetype
        if instantiateobj:
            if objectfilename == '':
                parser.print_help()
                self._graceexit(1)
            self.objectfilename = objectfilename
            self.objectname = objectname
        ## messaging layer information
        self.receivedmessages_semaphore = Semaphore(0)
        self.receivedmessages = []
        # msgs not acked yet
        # {msgid: msginfo}
        self.outstandingmessages_lock =RLock()
        self.outstandingmessages = {}
        # last msg timestamp for all peers
        # {peer: timestamp}
        self.lastmessages_lock =RLock()
        self.lastmessages = {}
        # number of retries for all peers
        # {peer: retries}
        self.retries_lock =RLock()
        self.retries = {}
        
        self.lock = Lock()
        self.done = False
        self.donecond = Condition()

        # create server socket and bind to a port
        self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        self.socket.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,1)
        self.socket.setblocking(0)
        if self.port:
            try:
                self.socket.bind((self.addr,self.port))
            except socket.error:
                print "Cannot bind to port %d" % self.port
                self._graceexit(1)
        else:
            for i in range(50):
                self.port = random.randint(14000,15000)
                try:
                    self.socket.bind((self.addr,self.port))
                    break
                except socket.error:
                    pass
        self.socket.listen(10)
        self.alive = True
        
        # initialize empty groups
        self.me = Peer(self.addr,self.port,self.type)
        self.id = self.me.getid()
        self.configpath = configpath
        try:
            LOGGERNODE = load_configdict(self.configpath)['LOGGERNODE']
        except:
            if logger:
                LOGGERNODE=logger
            else:
                LOGGERNODE = None
        self.logger = NetworkLogger("%s-%s" % (node_names[self.type],self.id), LOGGERNODE)
        self.logger.write("State", "Connected.")
        self.groups = {NODE_ACCEPTOR:Group(self.me), NODE_REPLICA: Group(self.me), NODE_NAMESERVER:Group(self.me)}
        # connect to the bootstrap node
        if givenbootstraplist:
            self.bootstraplist = []
            self.discoverbootstrap(givenbootstraplist)
            self.connecttobootstrap()
        if self.type == NODE_REPLICA or self.type == NODE_NAMESERVER:
            self.stateuptodate = False
Exemple #2
0
class Node():
    """Node encloses the basic Node behaviour and state that
    are extended by Leaders, Acceptors or Replicas.
    """ 
    def __init__(self, nodetype, addr=options.addr, port=options.port, givenbootstraplist=options.bootstrap, debugoption=options.debug, objectfilename=options.objectfilename, objectname=options.objectname, instantiateobj=False, configpath=options.configpath, logger=options.logger):
        """Node State
        - addr: hostname for Node, detected automatically
        - port: port for Node, can be taken from the commandline (-p [port]) or
        detected automatically by binding.
        - connectionpool: ConnectionPool that keeps all Connections Node knows about
        - type: type of the corresponding Node: NODE_ACCEPTOR | NODE_REPLICA | NODE_NAMESERVER
        - alive: liveness of Node
        - outstandingmessages: collection of sent but not-yet-acked messages
        - socket: server socket for Node
        - me: Peer object that represents Node
        - id: id for Node (addr:port)
        - groups: other Peers in the system that Node knows about. Node.groups is indexed by the
        corresponding node_name (NODE_ACCEPTOR | NODE_REPLICA | NODE_NAMESERVER), which returns a Group
        """
        self.addr = addr if addr else findOwnIP()
        self.port = port
        self.connectionpool = ConnectionPool()
        self.type = nodetype
        if instantiateobj:
            if objectfilename == '':
                parser.print_help()
                self._graceexit(1)
            self.objectfilename = objectfilename
            self.objectname = objectname
        ## messaging layer information
        self.receivedmessages_semaphore = Semaphore(0)
        self.receivedmessages = []
        # msgs not acked yet
        # {msgid: msginfo}
        self.outstandingmessages_lock =RLock()
        self.outstandingmessages = {}
        # last msg timestamp for all peers
        # {peer: timestamp}
        self.lastmessages_lock =RLock()
        self.lastmessages = {}
        # number of retries for all peers
        # {peer: retries}
        self.retries_lock =RLock()
        self.retries = {}
        
        self.lock = Lock()
        self.done = False
        self.donecond = Condition()

        # create server socket and bind to a port
        self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        self.socket.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,1)
        self.socket.setblocking(0)
        if self.port:
            try:
                self.socket.bind((self.addr,self.port))
            except socket.error:
                print "Cannot bind to port %d" % self.port
                self._graceexit(1)
        else:
            for i in range(50):
                self.port = random.randint(14000,15000)
                try:
                    self.socket.bind((self.addr,self.port))
                    break
                except socket.error:
                    pass
        self.socket.listen(10)
        self.alive = True
        
        # initialize empty groups
        self.me = Peer(self.addr,self.port,self.type)
        self.id = self.me.getid()
        self.configpath = configpath
        try:
            LOGGERNODE = load_configdict(self.configpath)['LOGGERNODE']
        except:
            if logger:
                LOGGERNODE=logger
            else:
                LOGGERNODE = None
        self.logger = NetworkLogger("%s-%s" % (node_names[self.type],self.id), LOGGERNODE)
        self.logger.write("State", "Connected.")
        self.groups = {NODE_ACCEPTOR:Group(self.me), NODE_REPLICA: Group(self.me), NODE_NAMESERVER:Group(self.me)}
        # connect to the bootstrap node
        if givenbootstraplist:
            self.bootstraplist = []
            self.discoverbootstrap(givenbootstraplist)
            self.connecttobootstrap()
        if self.type == NODE_REPLICA or self.type == NODE_NAMESERVER:
            self.stateuptodate = False

    def createinfofile(self):
        try:
            infofile = open(self.objectfilename[:-3]+"-descriptor", 'a')
            infofile.write("%s:%d" %(self.addr,self.port))
            infofile.close()
        except IOError as e:
            self.logger.write("File Error", "Info file cannot be created.")
            self._graceexit(1)

    def _getipportpairs(self, bootaddr, bootport):
        for node in socket.getaddrinfo(bootaddr, bootport):
            yield Peer(node[4][0],bootport,NODE_REPLICA)

    def discoverbootstrap(self, givenbootstraplist):
        bootstrapstrlist = givenbootstraplist.split(",")
        for bootstrap in bootstrapstrlist:
            #ipaddr:port pair given as bootstrap
            if bootstrap.find(":") >= 0:
                bootaddr,bootport = bootstrap.split(":")
                for peer in self._getipportpairs(bootaddr, int(bootport)):
                    self.bootstraplist.append(peer)
            #dnsname given as bootstrap
            else:
                answers = []
                try:
                    answers = dns.resolver.query('_concoord._tcp.'+bootstrap, 'SRV')
                except (dns.resolver.NXDOMAIN, dns.exception.Timeout):
                    self.logger.write("DNS Error", "Cannot resolve %s" % bootstrap)
                for rdata in answers:
                    for peer in self._getipportpairs(str(rdata.target), rdata.port):
                        self.bootstraplist.append(peer)

    def connecttobootstrap(self):
        tries = 0
        keeptrying = True
        while tries < BOOTSTRAPCONNECTTIMEOUT and keeptrying:
            for bootpeer in self.bootstraplist:
                try:
                    self.logger.write("State", "trying to connect to bootstrap: %s" % bootpeer)
                    helomessage = HandshakeMessage(MSG_HELO, self.me)
                    success = self.send(helomessage, peer=bootpeer)
                    if success < 0:
                        tries += 1
                        continue
                    self.groups[NODE_REPLICA].add(bootpeer)
                    self.logger.write("State", "connected to bootstrap: %s:%d" % (bootpeer.addr,bootpeer.port))
                    keeptrying = False
                    break
                except socket.error, e:
                    self.logger.write("Connection Error", "cannot connect to bootstrap: %s" % str(e))
                    print e
                    tries += 1
                    continue
            time.sleep(1)