示例#1
0
def recvAndSet(sock, i):
    global mesSlot, recvConds, ballot, myVal, procNo, acceptNum, acceptVal, states
    global activeFailed, linkSuc
    global queue
    global acceptBallot
    global acceptSlot, acceptCond
    global promiseSlot, promiseCond
    global myBlock, tempBlock
    global leader
    global balance
    global decideCond
    while True:
        le = safeRec(sock, 2)
        le = unpack(">H", le)[0]
        mes = safeRec(sock, le)
        newone = paxos_pb2.Prepare()
        newone.ParseFromString(mes)
        # getting Prepare, set the ballot number if greater and return promise
        if newone.type == 1:
            if (newone.ballot.num > ballot.num or
                (newone.ballot.num == ballot.num and newone.ballot.pid >=
                 procNo)) and newone.ballot.depth >= len(ballot.blockChain):
                ballot.num = newone.ballot.num
                leader = False
                if newone.ballot.depth > ballot.depth:

                    sendForRecovery(ballot.depth, newone.ballot.depth)
                    ballot.depth = newone.ballot.depth

                returned = paxos_pb2.Promise()
                returned.type = 3
                returned.ballot.CopyFrom(newone.ballot)
                returned.acceptNum.CopyFrom(acceptNum)
                returned.acceptVal.CopyFrom(acceptVal)
                threading.Thread(target=waitSend, args=(
                    sock,
                    returned,
                )).start()

        elif newone.type == 3:
            if len(promiseSlot) <= 2:
                newone = paxos_pb2.Promise()
                newone.ParseFromString(mes)
                promiseSlot.append((i, newone))
                if len(promiseSlot) == 2:
                    promiseCond.acquire()
                    promiseCond.notifyAll()
                    promiseCond.clear()
                    promiseCond.release()

                    # promiseSlot to be cleared

        elif newone.type == 4:
            newone = paxos_pb2.Accept()
            newone.ParseFromString(mes)
            if (newone.myVal.num > ballot.num or
                (newone.myVal.num == ballot.num and newone.myVal.pid >
                 ballot.pid)) and newone.myVal.depth >= len(states.blockChain):
                leader = False
                insi = newone.myVal.trans
                states.queue.append((i, insi))
                then = paxos_pb2.Accepted()
                then.type = 5
                acceptNum = newone.ballot
                acceptVal = newone.myVal
                then.ballot.CopyFrom(newone.ballot)
                then.acceptVal.CopyFrom(newone.myVal)

                threading.Thread(target=waitSend, args=(
                    sock,
                    then,
                )).start()

            continue

        elif newone.type == 5:
            if len(acceptSlot) < 2:

                newone = paxos_pb2.Accepted()
                newone.ParseFromString(mes)
                if newone.ballot == acceptBallot:
                    acceptSlot.append(newone)

            elif len(acceptSlot) == 2:
                acceptCond.acquire()
                acceptCond.notifyAll()
                acceptSlot.clear()
                acceptCond.release()

            # acceptSlot to be cleared

        elif newone.type == 6:
            newone = paxos_pb2.Decide()
            newone.ParseFromString(mes)
            if newone.val not in states.blockChain:
                states.blockChain.append(newone.val)
                for ite in newone.val.trans:
                    if ite.rcvr == procNo:
                        states.balance += ite.amt

            ballot.depth = len(states.blockChain)
            #             clearQueue(i)
            tempBlock = paxos_pb2.Block()
            decideCond.acquire()
            decideCond.notifyAll()
            decideCond.release()

        elif newone.type == 7:
            newone = paxos_pb2.Recover()
            newone.ParseFromString(mes)
            if newone.depth < ballot.depth:
                then = paxos_pb2.RepRecover()
                then.type = 8
                then.depth = newone.depth
                then.block.CopyFrom(states.blockChain[depth])
                waitSend(sock, then)

        elif newone.type == 8:
            newone = paxos_pb2.RepRecover()
            newone.ParseFromString(mes)
            addToBlockChain(newone)
            continue
示例#2
0
文件: Serv.py 项目: SihuaMa12/CS171
def recvAndSet(sock, i):
    global recvConds, ballot, myVal, procNo, acceptNum, acceptVal, states
    global activeFailed, linkSuc
    global acceptBallot
    global acceptSlot, acceptCond
    global promiseSlot, promiseCond
    global myBlock, tempBlock
    global decideCond
    global acceptingPromise
    global acceptingAcced
    global promiseSlotLock
    global blockChainLock
    global acceptSlotLock
    while True:
        le = safeRec(sock, 2)
        if le == b'':
            socks[i] = -1
            linkSuc[i - 1] = False
            return
        le = unpack(">H", le)[0]
        mes = safeRec(sock, le)
        newone = paxos_pb2.Prepare()
        newone.ParseFromString(mes)
        # getting Prepare, set the ballot number if greater and return promise
        if activeFailed[i - 1] == True:
            continue

        if newone.type == 1:
            print("Prepared")
            # print(newone.ballot)
            # print(ballot)
            if newone.ballot.depth > len(states.blockChain):
                ask = paxos_pb2.Recover()
                ask.type = 7
                threading.Thread(target=waitSend, args=(
                    sock,
                    ask,
                )).start()
            if newone.ballot.depth > ballot.depth or (
                    newone.ballot.depth == ballot.depth and newone.ballot.num >
                    ballot.num) or (newone.ballot.depth == ballot.depth
                                    and newone.ballot.num == ballot.num
                                    and newone.ballot.pid >= ballot.pid):
                ballot.CopyFrom(newone.ballot)
                #if newone.ballot.depth > ballot.depth:

                #   sendForRecovery(ballot.depth, newone.ballot.depth)
                #  ballot.depth = newone.ballot.depth

                returned = paxos_pb2.Promise()
                returned.type = 3
                returned.ballot.CopyFrom(newone.ballot)
                returned.acceptNum.CopyFrom(acceptNum)
                returned.acceptVal.CopyFrom(acceptVal)
                print("Sending")
                threading.Thread(target=waitSend, args=(
                    sock,
                    returned,
                )).start()

        elif newone.type == 3:
            print("Promised")
            newone = paxos_pb2.Promise()
            newone.ParseFromString(mes)
            promiseSlotLock.acquire()
            if newone.ballot == ballot and acceptingPromise:
                print("Still in phase")
                print("Length: ", len(promiseSlot))
                if len(promiseSlot) < 2:
                    # print("Going on")
                    promiseSlot.append((i, newone))
                    if len(promiseSlot) == 2:
                        # print("Here")
                        promiseCond.acquire()
                        promiseCond.notifyAll()
                        acceptingPromise = False
                        # promiseSlot.clear()
                        promiseCond.release()

            promiseSlotLock.release()
            # else:
            #     print("Debug: promiseSlot not equal 2 ", promiseSlot)
            # else:
            #     print("Debug: promiseSlot ", promiseSlot)
            # else:
            #     print("Promised, newone.ballot ", newone.ballot)
            #     print("Promised, ballot ", ballot)
            #         # promiseSlot to be cleared, not here

        elif newone.type == 4:
            print("Got accept from " + str(i))
            newone = paxos_pb2.Accept()
            newone.ParseFromString(mes)
            if newone.ballot.depth > len(states.blockChain):
                ask = paxos_pb2.Recover()
                ask.type = 7
                threading.Thread(target=waitSend, args=(
                    sock,
                    ask,
                )).start()
            if newone.ballot.depth > ballot.depth or (
                    newone.ballot.depth == ballot.depth and newone.ballot.num >
                    ballot.num) or (newone.ballot.depth == ballot.depth
                                    and newone.ballot.num == ballot.num
                                    and newone.ballot.pid >= ballot.pid):
                print("Sending back accepted")
                then = paxos_pb2.Accepted()
                then.type = 5
                acceptNum.CopyFrom(newone.ballot)
                acceptVal.CopyFrom(newone.myVal)
                then.ballot.CopyFrom(newone.ballot)
                then.acceptVal.CopyFrom(newone.myVal)

                threading.Thread(target=waitSend, args=(
                    sock,
                    then,
                )).start()
            else:
                print("Did not accept")
                print("newone.ballot ", newone.ballot)
                print("local ballot: ", ballot)

        elif newone.type == 5:
            print("Accepted from " + str(i))
            newone = paxos_pb2.Accepted()
            newone.ParseFromString(mes)
            acceptSlotLock.acquire()
            if len(acceptSlot) < 2 and acceptingAcced:

                if newone.ballot == acceptBallot:
                    acceptSlot.append(newone)

                if len(acceptSlot) == 2:
                    acceptCond.acquire()
                    acceptCond.notifyAll()
                    acceptingAcced = False
                    acceptSlot.clear()
                    acceptCond.release()

            acceptSlotLock.release()
            # acceptSlot to be cleared

        elif newone.type == 6:
            newone = paxos_pb2.Decide()
            newone.ParseFromString(mes)
            if newone.ballot.depth > len(states.blockChain):
                ask = paxos_pb2.Recover()
                ask.type = 7
                threading.Thread(target=waitSend, args=(
                    sock,
                    ask,
                )).start()
            if newone.val not in states.blockChain:
                blockChainLock.acquire()
                states.blockChain.append(newone.val)
                blockChainLock.release()
                for ite in newone.val.trans:
                    if ite.rcvr == procNo:
                        states.balance += ite.amt

            ballot.depth = len(states.blockChain)

            if newone.val == myBlock:
                print("cleaning myBLock")
                myBlock = paxos_pb2.Block()
            if newone.val == tempBlock:
                print("cleaning tempBlock and acceptVal")
                tempBlock = paxos_pb2.Block()

            if newone.val == acceptVal:
                print("cleaning acceptVal")
                acceptVal = paxos_pb2.Block()
            else:
                print("Error: ")
                print(newone.val)
                print(acceptVal)

            decideCond.acquire()
            decideCond.notifyAll()
            decideCond.release()

        elif newone.type == 7:

            zaWarudo = states.blockChain.copy()
            returned = paxos_pb2.RepRecover()
            returned.type = 8
            returned.insi.extend(zaWarudo)
            threading.Thread(target=waitSend, args=(
                sock,
                returned,
            )).start()
            # newone = paxos_pb2.Recover()
            # newone.ParseFromString(mes)
            # if newone.depth < ballot.depth:
            #     then = paxos_pb2.RepRecover()
            #     then.type = 8
            #     then.depth = newone.depth
            #     then.block.CopyFrom(states.blockChain[depth])
            #     waitSend(sock, then)

        elif newone.type == 8:
            thend = paxos_pb2.RepRecover()
            thend.ParseFromString(mes)
            # print("Type 8: ", thend)
            threading.Thread(target=recovery, args=(thend, )).start()