Esempio n. 1
0
    def __init__(self, selfNodeAddr, otherNodesAddrs, conf=None):
        """
        Main SyncObj class, you should inherit your own class from it.

        :param selfNodeAddr: address of the current node server, 'host:port'
        :type selfNodeAddr: str
        :param otherNodesAddrs: addresses of partner nodes, ['host1:port1', 'host2:port2', ...]
        :type otherNodesAddrs: list of str
        :param conf: configuration object
        :type conf: SyncObjConf
        """

        if conf is None:
            self.__conf = SyncObjConf()
        else:
            self.__conf = conf

        self.__conf.validate()

        if self.__conf.password is not None:
            if not HAS_CRYPTO:
                raise ImportError("Please install 'cryptography' module")
            self.__encryptor = getEncryptor(self.__conf.password)
        else:
            self.__encryptor = None

        self.__selfNodeAddr = selfNodeAddr
        self.__otherNodesAddrs = otherNodesAddrs
        self.__unknownConnections = {}  # descr => _Connection
        self.__raftState = _RAFT_STATE.FOLLOWER
        self.__raftCurrentTerm = 0
        self.__votedFor = None
        self.__votesCount = 0
        self.__raftLeader = None
        self.__raftElectionDeadline = time.time() + self.__generateRaftTimeout(
        )
        self.__raftLog = createJournal(self.__conf.journalFile)
        if len(self.__raftLog) == 0:
            self.__raftLog.add(_bchr(_COMMAND_TYPE.NO_OP), 1,
                               self.__raftCurrentTerm)
        self.__raftCommitIndex = 1
        self.__raftLastApplied = 1
        self.__raftNextIndex = {}
        self.__raftMatchIndex = {}
        self.__lastSerializedTime = time.time()
        self.__lastSerializedEntry = None
        self.__forceLogCompaction = False
        self.__leaderCommitIndex = None
        self.__onReadyCalled = False
        self.__changeClusterIDx = None
        self.__noopIDx = None
        self.__destroying = False
        self.__recvTransmission = ''

        self.__startTime = time.time()
        globalDnsResolver().setTimeouts(self.__conf.dnsCacheTime,
                                        self.__conf.dnsFailCacheTime)
        self.__serializer = Serializer(self.__conf.fullDumpFile,
                                       self.__conf.logCompactionBatchSize,
                                       self.__conf.useFork,
                                       self.__conf.serializer,
                                       self.__conf.deserializer,
                                       self.__conf.serializeChecker)
        self.__isInitialized = False
        self.__lastInitTryTime = 0
        self._poller = createPoller(self.__conf.pollerType)

        if selfNodeAddr is not None:
            bindAddr = self.__conf.bindAddress or selfNodeAddr
            host, port = bindAddr.split(':')
            self.__server = TcpServer(
                self._poller,
                host,
                port,
                onNewConnection=self.__onNewConnection,
                sendBufferSize=self.__conf.sendBufferSize,
                recvBufferSize=self.__conf.recvBufferSize,
                connectionTimeout=self.__conf.connectionTimeout)

        self._methodToID = {}
        self._idToMethod = {}
        methods = sorted([m for m in dir(self) if callable(getattr(self, m))])
        for i, method in enumerate(methods):
            self._methodToID[method] = i
            self._idToMethod[i] = getattr(self, method)

        self.__thread = None
        self.__mainThread = None
        self.__initialised = None
        self.__commandsQueue = FastQueue(self.__conf.commandsQueueSize)
        if not self.__conf.appendEntriesUseBatch:
            self.__pipeNotifier = PipeNotifier(self._poller)

        self.__nodes = []
        self.__readonlyNodes = []
        self.__readonlyNodesCounter = 0
        self.__lastReadonlyCheck = 0
        self.__newAppendEntriesTime = 0

        self.__commandsWaitingCommit = collections.defaultdict(
            list)  # logID => [(termID, callback), ...]
        self.__commandsLocalCounter = 0
        self.__commandsWaitingReply = {}  # commandLocalCounter => callback

        self.__properies = set()
        for key in self.__dict__:
            self.__properies.add(key)

        if self.__conf.autoTick:
            self.__mainThread = threading.current_thread()
            self.__initialised = threading.Event()
            self.__thread = threading.Thread(target=SyncObj._autoTickThread,
                                             args=(weakref.proxy(self), ))
            self.__thread.start()
            while not self.__initialised.is_set():
                pass
        else:
            self.__initInTickThread()