def handleUDP(data):
    global ACTIVE
    global BLOCK_FLAG
    global log
    global state
    global quiet_lock
    global num_client
    global num_blocked

    sock = data
    tdata = threading.local()

    while True:
        try:
            tdata.data, tdata.addr = sock.recvfrom(buffSize)
        except socket.timeout:
            exit(0)

        tdata.t, tdata.s, tdata.c = messager.decodeMsg(
            tdata.data.decode('utf-8'))
        if tdata.t == messager.MSG_CHECKPOINT:
            with __lock:
                if tdata.s == 1:
                    tdata.data = messager.encodeMsg(messager.MSG_CHECKPOINT, 2,
                                                    state)
                    sock.sendto(bytes(tdata.data, 'utf-8'),
                                (tdata.c[0], tdata.c[1]))
                elif tdata.s == 2:
                    print("after checkpoint state is : ", tdata.c)
                else:
                    tdata.cid, tdata.sid, tdata.seq, tdata.ts, tdata.state = messager.decodeUpdateState(
                        tdata.c)
                    print("checkpoint state is : ", tdata.state)
                    state = tdata.state
                    for i in range(len(log)):
                        if log[i][0] == tdata.cid and log[i][2] == tdata.seq:
                            break
                    log = log[i:]
                    print("obtain useful log:")
                    for i in log:
                        print(i)
                    for i in log:
                        state = i[4]
                        logging.info(
                            "client: %i ,server: %i, seq: %i, time: %s,state: %s",
                            i[0], i[1], i[2], i[3], i[4])
                    log = []
                    quiet_lock = False
        if tdata.t == messager.MSG_LFD_SERVER_INIT:
            print('recv lfd init')
            sudp.sendto(tdata.data, tdata.addr)
        # Heartbeating
        if tdata.t == messager.MSG_PING:
            if sid == messager.decodeHeartbeat(tdata.c):
                tdata.data = messager.encodeMsg(messager.MSG_BEATING, tdata.s,
                                                tdata.c)
                sock.sendto(bytes(tdata.data, 'utf-8'), tdata.addr)
            # Should Never happen, but just in case
            else:
                tdata.data = messager.encodeMsg(messager.MSG_ERROR, tdata.s,
                                                tdata.c)
                sock.sendto(bytes(tdata.data, 'utf-8'), tdata.addr)

        elif tdata.t == messager.MSG_ACTIVE:
            with __lock:
                ACTIVE = True
            logging.info("Become active")

        elif tdata.t == messager.MSG_QUIET:
            with __lock:
                quiet_lock = True

            logging.info("Become quiet")

        elif tdata.t == messager.MSG_CHECK_REMIND:
            with __lock:
                tosid = int(tdata.c)

                print("sid:", tosid)
                if tosid == 1:
                    sendToCheck = 10087
                if tosid == 2:
                    sendToCheck = 10088
                if tosid == 3:
                    sendToCheck = 10089
                BLOCK_FLAG = True
                check_state = state
                print("checkpointing")
                print("send checkpoint. state:", check_state)

            #logging.info("%d %d", num_blocked, num_client)
            while num_blocked < num_client:
                continue
            #logging.info("%d %d", num_blocked, num_client)

            with __lock:
                tdata.c = messager.encodeUpdateState(log[0][0], log[0][1],
                                                     log[0][2], log[0][3],
                                                     check_state)
                msg = messager.encodeMsg(messager.MSG_CHECKPOINT, 0, tdata.c)
                sock.sendto(msg.encode('utf-8'), ("localhost", sendToCheck))
                BLOCK_FLAG = False
                log = []
                num_client = 0
def handleTCP(data):
    global state
    global log
    global num_client
    global num_blocked
    sock = data[0]
    tdata = threading.local()
    tdata.cid = 0

    recovered = False

    with __lock:
        num_client += 1

    while True:
        tdata.data = sock.recv(buffSize)

        if not tdata.data:
            # logging.info("CID: %i exit (0 is UNKNOWN)", tdata.cid)
            with __lock:
                num_client -= 1
            sock.close()
            return

        tdata.t, tdata.s, tdata.c = messager.decodeMsg(
            tdata.data.decode('utf-8'))
        # Update state, may be better to have a dedicate function
        if tdata.t == messager.MSG_UPDATESTATE:

            # cid, seq, state
            tdata.cid, tdata.sid, tdata.seq, tdata.ts, tdata.state = messager.decodeUpdateState(
                tdata.c)
            item = [tdata.cid, tdata.sid, tdata.seq, tdata.ts, tdata.state]

            with __lock:
                if ACTIVE == False:
                    logging.error("NOT ACTIVE")
                    log.append([
                        tdata.cid, tdata.sid, tdata.seq, tdata.ts, tdata.state
                    ])
                    print("log:")
                    for i in log:
                        print(i)
                    tdata.c = "SERVER NOT ACTIVE"
                    tdata.data = messager.encodeMsg(messager.MSG_ERROR,
                                                    len(tdata.c), tdata.c)
                    sock.send(bytes(tdata.data, 'utf-8'))

                    #with __lock:
                    #num_client -= 1
                    #sock.close()
                    continue

            with __lock:
                # Send
                if quiet_lock:
                    logging.info("NOT ACTIVE")
                    log.append([
                        tdata.cid, tdata.sid, tdata.seq, tdata.ts, tdata.state
                    ])
                    print("log:")
                    for i in log:
                        print(i)
                    tdata.data = messager.encodeMsg(messager.MSG_UPDATESTATE,
                                                    0, tdata.c)
                    sock.send(bytes(tdata.data, 'utf-8'))
                    continue

            __lock.acquire()  # Racing Condition
            state = tdata.state
            logging.info("client: %i ,server: %i, seq: %i, time: %s,state: %s",
                         tdata.cid, tdata.sid, tdata.seq, tdata.ts, state)

            if BLOCK_FLAG:
                num_blocked += 1
                log.append(
                    [tdata.cid, tdata.sid, tdata.seq, tdata.ts, tdata.state])
                recovered = True
            __lock.release()

            while BLOCK_FLAG:  # Busy wait for very short period
                continue

            with __lock:
                tdata.data = messager.encodeMsg(messager.MSG_UPDATESTATE, 0,
                                                tdata.c)
                sock.send(tdata.data.encode('utf-8'))
                if recovered:
                    time.sleep(0.2)
                    recovered = False
예제 #3
0
def stateUpdate(stcp):
    global seq
    global recovering
    global resend
    # Currently for easy debug -- Later will be feeded by script
    if recovering:
        state = resend
        print("send recover", state)
    else:
        state = messager.inputState()

    # send msg
    for i in stcp:
        # check connection
        if i[2]:
            timestamp = str(datetime.now())
            update_str = messager.encodeUpdateState(cid, i[0], seq, timestamp,
                                                    state)
            if recovering:
                msg = messager.encodeMsg(messager.MSG_RECOVERY,
                                         len(update_str) + 1, update_str)
            else:
                msg = messager.encodeMsg(messager.MSG_UPDATESTATE,
                                         len(update_str) + 1, update_str)
            i[1].send(bytes(msg, 'utf-8'))
            if not recovering:
                print("msg send to server id:", i[0], state)
        else:
            # reconnect
            try:
                i[1] = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                i[1].connect(server_address[i[0] - 1])
                i[2] = True
                timestamp = str(datetime.now())
                update_str = messager.encodeUpdateState(
                    cid, i[0], seq, timestamp, state)
                if recovering:
                    msg = messager.encodeMsg(messager.MSG_RECOVERY,
                                             len(update_str) + 1, update_str)
                else:
                    msg = messager.encodeMsg(messager.MSG_UPDATESTATE,
                                             len(update_str) + 1, update_str)
                i[1].send(bytes(msg, 'utf-8'))
                if not recovering:
                    print("msg send to server id:", i[0], state)
            except socket.error:
                continue

    # duplicate detector
    recovering = True
    for i in range(len(stcp)):
        if stcp[i][2]:
            try:
                data = stcp[i][1].recv(buffSize)
                # error
                if not data:
                    stcp[i][1].close()
                    stcp[i][2] = False
                    if stcp[i][3] == 'p':
                        recovering = True
                    stcp[i][3] = 'b'
                    continue

                i_type, i_len, i_c = messager.decodeMsg(data.decode('utf-8'))
                if i_type == messager.MSG_UPDATESTATE:
                    i_cid, i_sid, i_seq, i_timestamp, i_state = messager.decodeUpdateState(
                        i_c)
                    # only implementaiton on reply
                    if i_state == "backup is sleeping":
                        continue
                    if i_seq >= seq:
                        print(messager.decodeUpdateState(i_c))
                        stcp[i][3] = 'p'
                        recovering = False
                        seq += 1
                    else:
                        print("duplicate reply detected:")
                        print(messager.decodeUpdateState(i_c))
            # error
            except socket.error:
                stcp[i][1].close()
                stcp[i][2] = False
                if stcp[i][3] == 'p':
                    recovering = True
                stcp[i][3] = 'b'
                continue
    if recovering:
        resend = state
        time.sleep(1)
    return
def handleTCP(data, udp):
    global state
    global Checkpoint_turn
    global Log
    sock = data[0]
    tdata = threading.local()
    tdata.cid = 0
    checkpoint_count = 0

    while True:
        tdata.data = sock.recv(buffSize)

        if not tdata.data:
            logging.info("CID: %i exit (0 is UNKNOWN)", tdata.cid)
            sock.close()
            return

        tdata.t, tdata.s, tdata.c = messager.decodeMsg(
            tdata.data.decode('utf-8'))

        # Update state, may be better to have a dedicate function
        if tdata.t == messager.MSG_UPDATESTATE:

            # Client side do not have a way to handle this at this point
            if ACTIVE == False:
                logging.error("NOT ACTIVE")
                tdata.c = "SERVER NOT ACTIVE"
                tdata.data = messager.encodeMsg(messager.MSG_ERROR,
                                                len(tdata.c), tdata.c)
                # sock.send(bytes(tdata.data, 'utf-8'))
                sock.close()
                exit(0)

            # cid, seq, state
            tdata.cid, tdata.sid, tdata.seq, tdata.ts, tdata.state = messager.decodeUpdateState(
                tdata.c)

            __lock.acquire()  # Racing Condition

            # state = tdata.state
            # logging.info("client: %i ,server: %i, seq: %i, state: %s", tdata.cid, tdata.sid,tdata.seq, state)
            # sock.send(tdata.c.encode('utf-8'))
            # Checkpoint_turn = True
            ##checkpoint_count += 1

            if primaryFlag == True:
                state = tdata.state
                logging.info(
                    "client: %i ,server: %i, seq: %i, time: %s, state: %s",
                    tdata.cid, tdata.sid, tdata.seq, tdata.ts, state)
                tdata.data = messager.encodeMsg(messager.MSG_UPDATESTATE, 0,
                                                tdata.c)
                sock.send(tdata.data.encode('utf-8'))
                Checkpoint_turn += 1
            else:
                logging.info("backup is sleeping")
                tdata.c = messager.encodeUpdateState(tdata.cid, tdata.sid,
                                                     tdata.seq, tdata.ts,
                                                     "backup is sleeping")
                tdata.data = messager.encodeMsg(messager.MSG_UPDATESTATE, 0,
                                                tdata.c)
                sock.send(tdata.data.encode('utf-8'))
                Log.append([
                    tdata.cid, tdata.sid, tdata.seq, tdata.ts, tdata.state, 0
                ])
                print("log:")
                for i in Log:
                    print(i[:5])

            __lock.release()

        # recovery request
        elif tdata.t == messager.MSG_RECOVERY:
            #print("recovering")
            # cid, seq, state
            tdata.cid, tdata.sid, tdata.seq, tdata.ts, tdata.state = messager.decodeUpdateState(
                tdata.c)

            if primaryFlag == True:
                while True:
                    #process log
                    flag = False
                    for i in range(len(Log)):
                        if Log[i][0] == tdata.cid and Log[i][2] == tdata.seq:
                            #current first
                            if i == 0 or Log[i - 1][5] == 0 or Log[i -
                                                                   1][5] == 2:
                                flag = True
                                break
                            else:
                                break
                    if flag:
                        break
                    time.sleep(0.2)
                with __lock:
                    #process log
                    for i in range(len(Log)):
                        if Log[i][0] == tdata.cid and Log[i][2] == tdata.seq:
                            state = Log[i][4]
                            Log[i][5] = 2
                            logging.info(
                                "client: %i ,server: %i, seq: %i, time: %s, state: %s",
                                Log[i][0], Log[i][1], Log[i][2], Log[i][3],
                                state)
                            tdata.c = messager.encodeUpdateState(
                                Log[i][0], Log[i][1], Log[i][2], Log[i][3],
                                state)
                            tdata.data = messager.encodeMsg(
                                messager.MSG_UPDATESTATE, 0, tdata.c)
                            sock.send(tdata.data.encode('utf-8'))
                            Checkpoint_turn += 1
                            #prune log
                            if i == (len(Log) - 1):
                                Log = []
                                print("Recovery done. Current state:", state)
                            break
                        elif Log[i][5] == 0:
                            state = Log[i][4]
                            Log[i][5] = 2

            else:
                with __lock:
                    tdata.c = messager.encodeUpdateState(
                        tdata.cid, tdata.sid, tdata.seq, tdata.ts,
                        "backup is sleeping")
                    tdata.data = messager.encodeMsg(messager.MSG_UPDATESTATE,
                                                    0, tdata.c)
                    sock.send(tdata.data.encode('utf-8'))
                    #mark as unreplied
                    for i in range(len(Log)):
                        if Log[i][0] == tdata.cid and Log[i][2] == tdata.seq:
                            Log[i][5] = 1

            # send checkpoint out if it is the primary and meets the frequency
        if primaryFlag and (Checkpoint_turn >= checkpoint_frequency):
            with __lock:
                checkpoint = messager.encodeMsg(messager.MSG_CHECKPOINT,
                                                len(state) + 1, state)
                sendCheck(udp, checkpoint)
                Checkpoint_turn = 0
예제 #5
0
def stateUpdate(stcp):
    global seq
    # Currently for easy debug -- Later will be feeded by script
    state = messager.inputState()

    # send msg
    for i in stcp:
        # check connection
        if i[2]:
            timestamp = str(datetime.now())
            update_str = messager.encodeUpdateState(cid, i[0], seq, timestamp,
                                                    state)
            msg = messager.encodeMsg(messager.MSG_UPDATESTATE,
                                     len(update_str) + 1, update_str)
            i[1].send(bytes(msg, 'utf-8'))
            print("msg send to server id:", i[0], "msg:", state)
        else:
            # reconnect
            try:
                i[1] = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                i[1].connect(server_address[i[0] - 1])
                i[2] = True
                timestamp = str(datetime.now())
                update_str = messager.encodeUpdateState(
                    cid, i[0], seq, timestamp, state)
                msg = messager.encodeMsg(messager.MSG_UPDATESTATE,
                                         len(update_str) + 1, update_str)
                i[1].send(bytes(msg, 'utf-8'))
                print("msg send to server id:", i[0], "msg:", state)
            except socket.error:
                print("not add ", server_address[i[0] - 1])
                continue

    # duplicate detector
    for i in range(len(stcp)):
        if stcp[i][2]:
            try:
                data = stcp[i][1].recv(buffSize)
                # error
                if not data:
                    stcp[i][1].close()
                    stcp[i][2] = False
                    continue

                i_type, i_len, i_c = messager.decodeMsg(data.decode('utf-8'))
                if i_type == messager.MSG_UPDATESTATE:
                    i_cid, i_sid, i_seq, i_timestamp, i_state = messager.decodeUpdateState(
                        i_c)
                    # only implementaiton on reply
                    if i_state == "backup is sleeping":
                        continue
                    if i_seq >= seq:
                        print("Reply:", messager.decodeUpdateState(i_c))
                        seq += 1
                    else:
                        print("Duplicate reply detected:")
                        print(messager.decodeUpdateState(i_c))

                elif i_type == messager.MSG_ERROR:
                    if i_c == "SERVER NOT ACTIVE":
                        continue

                    elif i_c == "SERVER QUIESCENCE":
                        print("quiet")
                        continue
            # error
            except socket.error:
                stcp[i][1].close()
                stcp[i][2] = False
                continue

    return