def next(self, input): action = map(DriverAction.DriverAction, [input["action"]])[0] if action == DriverAction.recvLocReq: # TODO: response the current location # check if the rsn is my RSN, route matched? global ROUTE_NO, DIRECTION, RSN_ADDR, LOCAL_ADDR, BUS_ID, WATCHDOG LOGGER.info("received RSN location request: %s" % input) # pet the watch dog WATCHDOG.petWatchdog() loc_message = { "SM" : "RSN_SM", "action" : "recvDriverLoc", "requestNo" : input["requestNo"], "route" : ROUTE_NO, "direction" : DIRECTION, "busId" : BUS_ID, "location" : Location.getLocation(), "busIP" : LOCAL_ADDR.ip, "busPort" : LOCAL_ADDR.port } # TODO: TEST ONLY; rsn should be modified MessagePasser.directSend(RSN_ADDR.ip, RSN_ADDR.port, loc_message) return DriverSM.Ready elif action == DriverAction.timeout: # don't hear from RSN for 15 secs # send re-elect message to GSN global ROUTE_NO, DIRECTION, GSN_ADDR, LOCAL_ADDR, BUS_ID, WATCHDOG LOGGER.info("send re-elect request to GSN") RSN_elect_message = { "SM" : "GSN_SM", "action" : "recvElecReq", "busId" : BUS_ID, "route" : ROUTE_NO, "direction" : DIRECTION, "location" : Location.getLocation(), "busIP" : LOCAL_ADDR.ip, "busPort" : LOCAL_ADDR.port } MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, RSN_elect_message) WATCHDOG.petWatchdog() return DriverSM.Hold elif action == DriverAction.turnOff: # TODO: do something to shut-down RESEND_ELECT_NUM = 0 WATCHDOG.StopWatchdog() return DriverSM.Off else: # for other illegal action # assert 0, "Ready: invalid action: %s" % str(input) pass
def next(self, input): action = map(UserAction.UserAction, [input["action"]])[0] if action == UserAction.request: global LOCAL_ADDR, GSN_ADDR, USER_ID, REQUEST_SEQ, WAITING_REQ_LIST, LAST_REQ, WATCHDOG, LAST_RESPONSE, IS_REPORTED # TODO: send a request to GSN LOGGER.info("send user request: %s" % input) REQUEST_SEQ = REQUEST_SEQ + 1 requestId = USER_ID + str(REQUEST_SEQ) request_message = { "SM": "GSN_SM", "action": "recvUserReq", "requestId": requestId, "userId": USER_ID, "route": input["route"], "direction": input["direction"], "destination": input["destination"], "location": input["location"], "userIP": LOCAL_ADDR.ip, "userPort": LOCAL_ADDR.port } LAST_REQ = request_message LAST_RESPONSE = None IS_REPORTED = False # TODO: TEST ONLY; gsn should be modified MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, request_message) WAITING_REQ_LIST.append(requestId) WATCHDOG.startWatchdog() return UserSM.Req_Waiting elif action == UserAction.turnOff: # TODO: do something to shut-down global WATCHDOG WATCHDOG.stopWatchdog() return UserSM.Off else: # for other illegal action # assert 0, "Ready: invalid action: %s" % str(input) pass
def next(self, input): action = map(UserAction.UserAction, [input["action"]])[0] if action == UserAction.request: global LOCAL_ADDR, GSN_ADDR, USER_ID, REQUEST_SEQ, WAITING_REQ_LIST, LAST_REQ, WATCHDOG, LAST_RESPONSE, IS_REPORTED # TODO: send a request to GSN LOGGER.info("send user request: %s" % input) REQUEST_SEQ = REQUEST_SEQ + 1 requestId = USER_ID + str(REQUEST_SEQ) request_message = { "SM": "GSN_SM", "action": "recvUserReq", "requestId": requestId, "userId": USER_ID, "route": input["route"], "direction": input["direction"], "destination": input["destination"], "location": input["location"], "userIP": LOCAL_ADDR.ip, "userPort": LOCAL_ADDR.port, } LAST_REQ = request_message LAST_RESPONSE = None IS_REPORTED = False # TODO: TEST ONLY; gsn should be modified MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, request_message) WAITING_REQ_LIST.append(requestId) WATCHDOG.startWatchdog() return UserSM.Req_Waiting elif action == UserAction.turnOff: # TODO: do something to shut-down global WATCHDOG WATCHDOG.stopWatchdog() return UserSM.Off else: # for other illegal action # assert 0, "Ready: invalid action: %s" % str(input) pass
def next(self, input): action = map(DriverAction.DriverAction, [input["action"]])[0] if action == DriverAction.start: global LOCAL_ADDR, RSN_ADDR, ROUTE_NO, DIRECTION, BUS_ID, WATCHDOG ROUTE_NO = input["route"] DIRECTION = input["direction"] Location.setLocation(int(input["location"])) # TODO: ping RSN to add into the group add_message = { "SM" : "GSN_SM", "action" : "recvBusReq", "type" : "add", "route" : ROUTE_NO, "direction" : DIRECTION, "busId" : BUS_ID, "location" : Location.getLocation(), "busIP" : LOCAL_ADDR.ip, "busPort" : LOCAL_ADDR.port } # TODO: should use real gsn MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, add_message) # start the watchdog WATCHDOG.startWatchdog() return DriverSM.Init_Waiting elif action == DriverAction.timeout: # TODO: re-ping return DriverSM.Idle elif action == DriverAction.turnOff: # TODO: do something to shut-down RESEND_ELECT_NUM = 0 WATCHDOG.stopWatchdog() return DriverSM.Off else: # for other illegal action # assert 0, "Idle: invalid action: %s" % str(input) pass
def next(self, input): action = map(UserAction.UserAction, [input["action"]])[0] if action == UserAction.recvRes: # TODO: return response to GUI global RESPONSE_QUE, WAITING_REQ_LIST, WATCHDOG, LAST_RESPONSE, LAST_REQ, ARRIVE_TIME LOGGER.info("receive response from RSN %s" % input) WATCHDOG.stopWatchdog() if str(input["original"]["requestId"]) in WAITING_REQ_LIST: RESPONSE_QUE.append(input) # if the last res is matched with last req, calculate arrive time if input["original"]["requestId"] == LAST_REQ["requestId"]: if input["location"] == None: diff = -1 else: diff = int(LAST_REQ["location"]) - int( input["location"]) ARRIVE_TIME = diff LAST_RESPONSE = input IS_REPORTED = False LOGGER.info("expected arrive time: %s" % str(ARRIVE_TIME)) return UserSM.Ready elif action == UserAction.reqTimeout: # TODO: re-send request if over threshold global LAST_REQ, WATCHDOG MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, LAST_REQ) WATCHDOG.petWatchdog() return UserSM.Req_Waiting elif action == UserAction.turnOff: # TODO: do something to shut-down global WATCHDOG WATCHDOG.stopWatchdog() return UserSM.Off else: # for other illegal action # assert 0, "Req_Waiting: invalid action: %s" % str(input) pass
def next(self, input): action = map(UserAction.UserAction, [input["action"]])[0] if action == UserAction.recvRes: # TODO: return response to GUI global RESPONSE_QUE, WAITING_REQ_LIST, WATCHDOG, LAST_RESPONSE, LAST_REQ, ARRIVE_TIME LOGGER.info("receive response from RSN %s" % input) WATCHDOG.stopWatchdog() if str(input["original"]["requestId"]) in WAITING_REQ_LIST: RESPONSE_QUE.append(input) # if the last res is matched with last req, calculate arrive time if input["original"]["requestId"] == LAST_REQ["requestId"]: if input["location"] == None: diff = -1 else: diff = int(LAST_REQ["location"]) - int(input["location"]) ARRIVE_TIME = diff LAST_RESPONSE = input IS_REPORTED = False LOGGER.info("expected arrive time: %s" % str(ARRIVE_TIME)) return UserSM.Ready elif action == UserAction.reqTimeout: # TODO: re-send request if over threshold global LAST_REQ, WATCHDOG MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, LAST_REQ) WATCHDOG.petWatchdog() return UserSM.Req_Waiting elif action == UserAction.turnOff: # TODO: do something to shut-down global WATCHDOG WATCHDOG.stopWatchdog() return UserSM.Off else: # for other illegal action # assert 0, "Req_Waiting: invalid action: %s" % str(input) pass
def next(self, input): action = map(RSNAction.RSNAction, [input["action"]])[0] if action == RSNAction.recvLocReq: # TODO: lookup the queried bus location and # TODO: response to user directly global BUS_TABLE, LOC_REQ_NO LOGGER.info("received location request: %s" % input) # fetch the nearest bus available # TODO: this function should be polished nearest_bus = None; nearest_loc = None; nearest_dist = -1; for key in BUS_TABLE: bus = BUS_TABLE[key] if (int(bus["last_update"]) >= int(LOC_REQ_NO) - 1) and (int(bus["last_update"]) <= int(LOC_REQ_NO)): distance = int(input["original"]["location"]) - int(bus["location"]) if (nearest_dist < 0 or distance < nearest_dist) and distance >= 0: nearest_dist = distance nearest_bus = key nearest_loc = bus["location"] response_message = { "SM" : "USER_SM", "action" : "recvRes", "location" : nearest_loc, "busId" : nearest_bus, "original" : input["original"] } MessagePasser.directSend(input["original"]["userIP"], input["original"]["userPort"], response_message) return RSNSM.Ready elif action == RSNAction.askBusLoc: # periodically ask each buses' location # TODO: triggered by host timer global GROUP_MEMBER, RSN_ID, ROUTE_NO, LOCAL_ADDR, LOC_REQ_NO LOGGER.info("asking each bus' location %s" % BUS_TABLE.keys()) LOC_REQ_NO = LOC_REQ_NO + 1 # maybe overflow!!! req_loc_message = { "SM" : "DRIVER_SM", "action" : "recvLocReq", "requestNo" : LOC_REQ_NO, "rsnId" : RSN_ID, "route" : ROUTE_NO, "rsnIP" : LOCAL_ADDR.ip, "rsnPort" : LOCAL_ADDR.port } #MessagePasser.multicast(GROUP_MEMBER, req_loc_message) # TODO: replace the code below with a multicast version for member in BUS_TABLE: MessagePasser.directSend(BUS_TABLE[member]["addr"].ip, BUS_TABLE[member]["addr"].port, req_loc_message) return RSNSM.Ready elif action == RSNAction.recvDriverLoc: # TODO: update local cache global BUS_TABLE, ROUTE_NO if input["route"] == ROUTE_NO \ and input["busId"] in BUS_TABLE \ and input["requestNo"] > BUS_TABLE[input["busId"]]["last_update"]: BUS_TABLE[input["busId"]] = { "direction" : input["direction"], "location" : input["location"], "addr" : Addr(input["busIP"], input["busPort"]), "last_update" : input["requestNo"] # TODO: use local time stamp } return RSNSM.Ready elif action == RSNAction.recvBusChange: # TODO: add or remove a bus from current group LOGGER.info("Receive bus change request: %s" % input) global GROUP_MEMBER, BUS_TABLE, ROUTE_NO, RSN_ID, LOCAL_ADDR, LOC_REQ_NO if input["route"] == ROUTE_NO: if input["type"] == "add": #if not input["busId"] in BUS_TABLE: #GROUP_MEMBER.append(input["busId"]) BUS_TABLE[input["busId"]] = { "direction" : input["direction"], "location" : input["location"], "addr" : Addr(input["busIP"], input["busPort"]), "last_update" : LOC_REQ_NO # TODO: use local time stamp } # send an ACK to driver rsn_ack = { "SM" : "DRIVER_SM", "action" : "recvRSNAck", "route" : ROUTE_NO, "rsnId" : RSN_ID, "rsnIP" : LOCAL_ADDR.ip, "rsnPort" : LOCAL_ADDR.port } MessagePasser.directSend(input["busIP"], input["busPort"], rsn_ack) elif input["type"] == "remove": if input["busId"] in BUS_TABLE: #GROUP_MEMBER.remove(input["busId"]) BUS_TABLE.pop(input["busId"]) return RSNSM.Ready elif action == RSNAction.recvGSNHB: LOGGER.info("Receive GSN heart beat: %s" % input["HBNo"]) global BUS_TABLE, RSN_ID, ROUTE_NO, LOCAL_ADDR, GSN_ADDR, LOC_REQ_NO # filter out some dead buses remove_list = [] for bus in BUS_TABLE: if int(BUS_TABLE[bus]["last_update"]) + 1 < LOC_REQ_NO: remove_list.append(bus) for bus in remove_list: BUS_TABLE.pop(bus) # send current route table to GSN HB_res_message = { "SM" : "GSN_SM", "action" : "recvHBRes", "HBNo" : input["HBNo"], "rsnId" : RSN_ID, "route" : ROUTE_NO, "rsnIP" : LOCAL_ADDR.ip, "rsnPort" : LOCAL_ADDR.port, "busTable" : BUS_TABLE } MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, HB_res_message) return RSNSM.Ready elif action == RSNAction.recvRSNResign: LOGGER.info("Receive GSN resign") TIMER_OFF.set() TIMER_ON.clear() return RSNSM.Idle elif action == RSNAction.turnOff: # TODO: do something to shut-down TIMER_OFF.set() TIMER_ON.clear() return RSNSM.Off else: # for other illegal action # assert 0, "Ready: invalid action: %s" % str(input) pass
def next(self, input): action = map(RSNAction.RSNAction, [input["action"]])[0] if action == RSNAction.recvRSNAssign: # TODO: received the group info from GSN # TODO: store the group info global LOCAL_ADDR, ROUTE_NO, BUS_TABLE, TIMER_ON, TIMER_OFF ROUTE_NO = input["route"] # if the RSN is the Driver itself, send a recvRSNAck to driver role if input["type"] == "self": BUS_TABLE[input["original"]["busId"]] = { "direction" : input["original"]["direction"], "location" : input["original"]["location"], "addr" : Addr(input["original"]["busIP"], input["original"]["busPort"]), "last_update" : 0 # TODO: use local time stamp } rsn_ack = { "SM" : "DRIVER_SM", "action" : "recvRSNAck", "route" : ROUTE_NO, "rsnId" : RSN_ID, "rsnIP" : LOCAL_ADDR.ip, "rsnPort" : LOCAL_ADDR.port } MessagePasser.directSend(input["original"]["busIP"], input["original"]["busPort"], rsn_ack) elif input["type"] == "normal": BUS_TABLE = input["busTable"] if BUS_TABLE == None: BUS_TABLE = {} # reset all time stampes for bus in BUS_TABLE: BUS_TABLE[bus]["last_update"] = 0 # notify each bus global GROUP_MEMBER, RSN_ID, ROUTE_NO, LOCAL_ADDR, LOC_REQ_NO LOGGER.info("asking each bus' location %s" % BUS_TABLE.keys()) LOC_REQ_NO = 0 LOC_REQ_NO = LOC_REQ_NO + 1 # maybe overflow!!! req_loc_message = { "SM" : "DRIVER_SM", "action" : "recvLocReq", "requestNo" : LOC_REQ_NO, "rsnId" : RSN_ID, "route" : ROUTE_NO, "rsnIP" : LOCAL_ADDR.ip, "rsnPort" : LOCAL_ADDR.port } for member in BUS_TABLE: MessagePasser.directSend(BUS_TABLE[member]["addr"].ip, BUS_TABLE[member]["addr"].port, req_loc_message) # unblock the timer thread TIMER_OFF.clear() TIMER_ON.set() return RSNSM.Ready elif action == RSNAction.timeout: # TODO: re-ping # Terry: seems no need to re-ping gsn return RSNSM.Idle elif action == RSNAction.turnOff: global TIMER_ON, TIMER_OFF # TODO: do something to shut-down TIMER_OFF.set() TIMER_ON.clear() return RSNSM.Off else: # for other illegal action # assert 0, "Idle: invalid action: %s" % str(input) pass
def next(self, input): action = map(GSNAction.GSNAction, [input["action"]])[0] if action == GSNAction.recvUserReq: # TODO: forward user request to responding RSN LOGGER.info("receive user request") rsn = getRSNByName(input["route"]) if rsn != None: LOGGER.info("forward user request to RSN") rsnAddr = rsn["rsnAddr"] request_message = { "SM" : "RSN_SM", "action" : "recvLocReq", "original" : input } MessagePasser.directSend(rsnAddr.ip, rsnAddr.port, request_message) else: LOGGER.info("no rsn running") response_message = { "SM" : "USER_SM", "action" : "recvRes", "location" : None, "busId" : None, "original" : input } MessagePasser.directSend(input["userIP"], input["userPort"], response_message) return GSNSM.Ready elif action == GSNAction.heartBeat: LOGGER.info("send heart beat to each RSN") global HB_NO HB_NO = HB_NO + 1 hb_message = { "SM" : "RSN_SM", "action" : "recvGSNHB", "HBNo" : HB_NO } for route in ROUTE_TABLE: MessagePasser.directSend(ROUTE_TABLE[route]["rsnAddr"].ip, ROUTE_TABLE[route]["rsnAddr"].port, hb_message) return GSNSM.Ready elif action == GSNAction.recvHBRes: LOGGER.info("receive HB response") global ROUTE_TABLE, HB_NO # update ROUTE_TABLE if input["route"] in ROUTE_TABLE: if input["rsnId"] == ROUTE_TABLE[input["route"]]["rsnId"]: ROUTE_TABLE[input["route"]]["rsnAddr"] = Addr(input["rsnIP"], input["rsnPort"]) ROUTE_TABLE[input["route"]]["busTable"] = input["busTable"] ROUTE_TABLE[input["route"]]["last_update"] = input["HBNo"] ROUTE_TABLE[input["route"]]["isElect"] = False else: # TODO: the rsnId is not recorded pass else: # TODO: the route is not recorded. pass return GSNSM.Ready elif action == GSNAction.recvBusReq: # TODO: update route table and forward user request to responding RSN LOGGER.info("receive bus request") rsn = getRSNByName(input["route"]) # if there is no RSN, assign the request bus as the RSN if rsn == None: # Qian: some checks: (1) if there is no rsn but receive a remove req LOGGER.info("assign new RSN") """ routeTableElm = RouteTableElm(input["route"], Addr(input["driverIp"], input["driverPort"]), []) routeTableElm.busTable.append(BusTableElm(Addr(input["driverIp"], input["driverPort"]))) """ route_table_entry = { "rsnId" : input["busId"], "rsnAddr" : Addr(input["busIP"], input["busPort"]), "busTable" : None, "last_update" : HB_NO } ROUTE_TABLE[input["route"]] = route_table_entry assign_message = { "SM" : "RSN_SM", "action" : "recvRSNAssign", "type" : "self", "route" : input["route"], "original" : input, "groupMember" : [input["busId"]] } MessagePasser.directSend(input["busIP"], input["busPort"], assign_message) else: # Qian: GSN will just forward it to rsn # may change this design request_message = { "SM" : "RSN_SM", "action" : "recvBusChange", "type" : input["type"], # add or remove "route" : input["route"], "direction" : input["direction"], "location" : input["location"], "busId" : input["busId"], "busIP" : input["busIP"], "busPort" : input["busPort"] } MessagePasser.directSend(rsn["rsnAddr"].ip, rsn["rsnAddr"].port, request_message) return GSNSM.Ready elif action == GSNAction.recvElecReq: # receive election rsn request for a bus LOGGER.info("receive election request") global HB_NO rsn = getRSNByName(input["route"]) # check if the rsn is live by checking the time stamp if rsn["last_update"] + 1 >= HB_NO: # means the RSN is alive, tell the driver to wait or reboot if rsn["isElect"] == True: LOGGER.info("new RSN has been elected, ignore the elect request") else: LOGGER.info("RSN is alive, ask the driver to reboot") restart_message = { "SM" : "DRIVER_SM", "action" : "restart" } MessagePasser.directSend(input["busIP"], input["busPort"], restart_message) else: # the RSN is dead, elect a new one, select the bus who sends the request, #with the longest potential running time bus_table = rsn["busTable"] ''' rsn_candidate = None min_dist = -1 min_bus_id = -1 for bus in bus_table: dist = int(bus_table[bus]["location"]) if min_dist < 0 or dist < min_dist: min_dist = dist rsn_candidate = bus_table[bus] min_bus_id = bus ''' LOGGER.info("RSN is dead, select a new RSN [%s] for route [%s]" % (input["busId"], input["route"])) # explicitly send a message to shut down the previous RSN resign_message = { "SM" : "RSN_SM", "action" : "recvRSNResign" } MessagePasser.directSend(rsn["rsnAddr"].ip, rsn["rsnAddr"].port, resign_message) # assign a new RSN assign_message = { "SM" : "RSN_SM", "action" : "recvRSNAssign", "type" : "normal", "route" : input["route"], "original" : None, "busTable" : bus_table } ROUTE_TABLE[input["route"]] = { "rsnId" : input["busId"], "rsnAddr" : Addr(input["busIP"], input["busPort"]), "busTable" : bus_table, "last_update" : HB_NO, "isElect" : True, } MessagePasser.directSend(input["busIP"], input["busPort"], assign_message) # TODO: select a bus from the table to be the new rsn, below code just selects the first driver ''' elm.rsnIP = elm.busTable[0]["rsnAddr"].ip elm.rsnPort = elm.busTable[0]["rsnAddr"].port LOGGER.info("send message to new rsn") assign_message = { "SM" : "RSN_SM", "action" : "recvRSNAssign", "groupMember" : elm.busTable } # TODO: TEST ONLY; gsn should be modified MessagePasser.directSend(elm.rsnIP, elm.rsnPort, request_message) ''' return GSNSM.Ready elif action == GSNAction.turnOff: # TODO: do something to shut-down return GSNSM.Off
def next(self, input): action = map(DriverAction.DriverAction, [input["action"]])[0] if action == DriverAction.recvLocReq: # TODO: response the current location # check if the rsn is my RSN, route matched? global ROUTE_NO, DIRECTION, RSN_ADDR, LOCAL_ADDR, BUS_ID, WATCHDOG LOGGER.info("received RSN location request: %s" % input) # pet the watch dog WATCHDOG.petWatchdog() # check if the RSN has changed if RSN_ADDR.ip != input["rsnIP"] or RSN_ADDR.port != input["rsnPort"]: LOGGER.info("RSN has changed") RSN_ADDR = Addr(input["rsnIP"], input["rsnPort"]) loc_message = { "SM" : "RSN_SM", "action" : "recvDriverLoc", "requestNo" : input["requestNo"], "route" : ROUTE_NO, "direction" : DIRECTION, "busId" : BUS_ID, "location" : Location.getLocation(), "busIP" : LOCAL_ADDR.ip, "busPort" : LOCAL_ADDR.port } # TODO: TEST ONLY; rsn should be modified MessagePasser.directSend(RSN_ADDR.ip, RSN_ADDR.port, loc_message) return DriverSM.Ready elif action == DriverAction.restart: # restart global LOCAL_ADDR, RSN_ADDR, ROUTE_NO, DIRECTION, BUS_ID, RESEND_ELECT_NUM LOGGER.info("Receive restart message from GSN. Restart now.") # TODO: ping RSN to add into the group add_message = { "SM" : "GSN_SM", "action" : "recvBusReq", "type" : "add", "route" : ROUTE_NO, "direction" : DIRECTION, "busId" : BUS_ID, "location" : Location.getLocation(), "busIP" : LOCAL_ADDR.ip, "busPort" : LOCAL_ADDR.port } # TODO: should use real gsn MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, add_message) RESEND_ELECT_NUM = 0 # pet the watch dog WATCHDOG.petWatchdog() return DriverSM.Init_Waiting elif action == DriverAction.timeout: # if reaches the limit of re-elect, reboot global RESEND_ELECT_NUM if RESEND_ELECT_NUM >= 3: LOGGER.info("RESEND_ELECT_NUM reaches the limit, reboot now.") RESEND_ELECT_NUM = 0 # restart global LOCAL_ADDR, RSN_ADDR, ROUTE_NO, DIRECTION, BUS_ID add_message = { "SM" : "GSN_SM", "action" : "recvBusReq", "type" : "add", "route" : ROUTE_NO, "direction" : DIRECTION, "busId" : BUS_ID, "location" : Location.getLocation(), "busIP" : LOCAL_ADDR.ip, "busPort" : LOCAL_ADDR.port } # TODO: should use real gsn MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, add_message) # pet the watch dog WATCHDOG.petWatchdog() return DriverSM.Init_Waiting else: # re-send re-elect msg LOGGER.info("send re-elect request to GSN, RESEND_ELECT_NUM: %s" % str(RESEND_ELECT_NUM)) RESEND_ELECT_NUM = RESEND_ELECT_NUM + 1 RSN_elect_message = { "SM" : "GSN_SM", "action" : "recvElecReq", "busId" : BUS_ID, "route" : ROUTE_NO, "direction" : DIRECTION, "location" : Location.getLocation(), "busIP" : LOCAL_ADDR.ip, "busPort" : LOCAL_ADDR.port } MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, RSN_elect_message) # pet the watch dog WATCHDOG.petWatchdog() return DriverSM.Hold elif action == DriverAction.turnOff: # TODO: do something to shut-down RESEND_ELECT_NUM = 0 WATCHDOG.stopWatchdog() return DriverSM.Off else: # for other illegal action # assert 0, "Init_Waiting: invalid action: %s" % str(input) pass
def next(self, input): action = map(DriverAction.DriverAction, [input["action"]])[0] if action == DriverAction.recvRSNAck: global MYSELF_ADDR, RSN_ADDR, ROUTE_NO, DIRECTION, BUS_ID # if the response route number doesn't match if input["route"] != ROUTE_NO: return DriverSM.Init_Waiting RSN_ADDR = Addr(input["rsnIP"], input["rsnPort"]) # pet the watch dog WATCHDOG.petWatchdog() return DriverSM.Ready elif action == DriverAction.timeout: # not receive the reponse from RSN for 15 secs global RESEND_ELECT_NUM if RESEND_ELECT_NUM >= 3: LOGGER.info("RESEND_ELECT_NUM reaches the limit, reboot now.") RESEND_ELECT_NUM = 0 # restart global LOCAL_ADDR, RSN_ADDR, ROUTE_NO, DIRECTION, BUS_ID add_message = { "SM" : "GSN_SM", "action" : "recvBusReq", "type" : "add", "route" : ROUTE_NO, "direction" : DIRECTION, "busId" : BUS_ID, "location" : Location.getLocation(), "busIP" : LOCAL_ADDR.ip, "busPort" : LOCAL_ADDR.port } # TODO: should use real gsn MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, add_message) # pet the watch dog WATCHDOG.petWatchdog() return DriverSM.Init_Waiting else: # re-send re-elect msg LOGGER.info("send re-elect request to GSN, RESEND_ELECT_NUM: %s" % str(RESEND_ELECT_NUM)) RESEND_ELECT_NUM = RESEND_ELECT_NUM + 1 RSN_elect_message = { "SM" : "GSN_SM", "action" : "recvElecReq", "busId" : BUS_ID, "route" : ROUTE_NO, "direction" : DIRECTION, "location" : Location.getLocation(), "busIP" : LOCAL_ADDR.ip, "busPort" : LOCAL_ADDR.port } MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, RSN_elect_message) # pet the watch dog WATCHDOG.petWatchdog() return DriverSM.Init_Waiting return DriverSM.Init_Waiting elif action == DriverAction.turnOff: # TODO: do something to shut-down RESEND_ELECT_NUM = 0 WATCHDOG.stopWatchdog() return DriverSM.Off else: # for other illegal action # assert 0, "Init_Waiting: invalid action: %s" % str(input) pass
def next(self, input): action = map(GSNAction.GSNAction, [input["action"]])[0] if action == GSNAction.recvUserReq: # TODO: forward user request to responding RSN LOGGER.info("receive user request") rsn = getRSNByName(input["route"]) if rsn != None: LOGGER.info("forward user request to RSN") rsnAddr = rsn["rsnAddr"] request_message = { "SM": "RSN_SM", "action": "recvLocReq", "original": input } MessagePasser.directSend(rsnAddr.ip, rsnAddr.port, request_message) else: LOGGER.info("no rsn running") response_message = { "SM": "USER_SM", "action": "recvRes", "location": None, "busId": None, "original": input } MessagePasser.directSend(input["userIP"], input["userPort"], response_message) return GSNSM.Ready elif action == GSNAction.heartBeat: LOGGER.info("send heart beat to each RSN") global HB_NO HB_NO = HB_NO + 1 hb_message = {"SM": "RSN_SM", "action": "recvGSNHB", "HBNo": HB_NO} for route in ROUTE_TABLE: MessagePasser.directSend(ROUTE_TABLE[route]["rsnAddr"].ip, ROUTE_TABLE[route]["rsnAddr"].port, hb_message) return GSNSM.Ready elif action == GSNAction.recvHBRes: LOGGER.info("receive HB response") global ROUTE_TABLE, HB_NO # update ROUTE_TABLE if input["route"] in ROUTE_TABLE: if input["rsnId"] == ROUTE_TABLE[input["route"]]["rsnId"]: ROUTE_TABLE[input["route"]]["rsnAddr"] = Addr( input["rsnIP"], input["rsnPort"]) ROUTE_TABLE[input["route"]]["busTable"] = input["busTable"] ROUTE_TABLE[input["route"]]["last_update"] = input["HBNo"] ROUTE_TABLE[input["route"]]["isElect"] = False else: # TODO: the rsnId is not recorded pass else: # TODO: the route is not recorded. pass return GSNSM.Ready elif action == GSNAction.recvBusReq: # TODO: update route table and forward user request to responding RSN LOGGER.info("receive bus request") rsn = getRSNByName(input["route"]) # if there is no RSN, assign the request bus as the RSN if rsn == None: # Qian: some checks: (1) if there is no rsn but receive a remove req LOGGER.info("assign new RSN") """ routeTableElm = RouteTableElm(input["route"], Addr(input["driverIp"], input["driverPort"]), []) routeTableElm.busTable.append(BusTableElm(Addr(input["driverIp"], input["driverPort"]))) """ route_table_entry = { "rsnId": input["busId"], "rsnAddr": Addr(input["busIP"], input["busPort"]), "busTable": None, "last_update": HB_NO } ROUTE_TABLE[input["route"]] = route_table_entry assign_message = { "SM": "RSN_SM", "action": "recvRSNAssign", "type": "self", "route": input["route"], "original": input, "groupMember": [input["busId"]] } MessagePasser.directSend(input["busIP"], input["busPort"], assign_message) else: # Qian: GSN will just forward it to rsn # may change this design request_message = { "SM": "RSN_SM", "action": "recvBusChange", "type": input["type"], # add or remove "route": input["route"], "direction": input["direction"], "location": input["location"], "busId": input["busId"], "busIP": input["busIP"], "busPort": input["busPort"] } MessagePasser.directSend(rsn["rsnAddr"].ip, rsn["rsnAddr"].port, request_message) return GSNSM.Ready elif action == GSNAction.recvElecReq: # receive election rsn request for a bus LOGGER.info("receive election request") global HB_NO rsn = getRSNByName(input["route"]) # check if the rsn is live by checking the time stamp if rsn["last_update"] + 1 >= HB_NO: # means the RSN is alive, tell the driver to wait or reboot if rsn["isElect"] == True: LOGGER.info( "new RSN has been elected, ignore the elect request") else: LOGGER.info("RSN is alive, ask the driver to reboot") restart_message = {"SM": "DRIVER_SM", "action": "restart"} MessagePasser.directSend(input["busIP"], input["busPort"], restart_message) else: # the RSN is dead, elect a new one, select the bus who sends the request, #with the longest potential running time bus_table = rsn["busTable"] ''' rsn_candidate = None min_dist = -1 min_bus_id = -1 for bus in bus_table: dist = int(bus_table[bus]["location"]) if min_dist < 0 or dist < min_dist: min_dist = dist rsn_candidate = bus_table[bus] min_bus_id = bus ''' LOGGER.info( "RSN is dead, select a new RSN [%s] for route [%s]" % (input["busId"], input["route"])) # explicitly send a message to shut down the previous RSN resign_message = {"SM": "RSN_SM", "action": "recvRSNResign"} MessagePasser.directSend(rsn["rsnAddr"].ip, rsn["rsnAddr"].port, resign_message) # assign a new RSN assign_message = { "SM": "RSN_SM", "action": "recvRSNAssign", "type": "normal", "route": input["route"], "original": None, "busTable": bus_table } ROUTE_TABLE[input["route"]] = { "rsnId": input["busId"], "rsnAddr": Addr(input["busIP"], input["busPort"]), "busTable": bus_table, "last_update": HB_NO, "isElect": True, } MessagePasser.directSend(input["busIP"], input["busPort"], assign_message) # TODO: select a bus from the table to be the new rsn, below code just selects the first driver ''' elm.rsnIP = elm.busTable[0]["rsnAddr"].ip elm.rsnPort = elm.busTable[0]["rsnAddr"].port LOGGER.info("send message to new rsn") assign_message = { "SM" : "RSN_SM", "action" : "recvRSNAssign", "groupMember" : elm.busTable } # TODO: TEST ONLY; gsn should be modified MessagePasser.directSend(elm.rsnIP, elm.rsnPort, request_message) ''' return GSNSM.Ready elif action == GSNAction.turnOff: # TODO: do something to shut-down return GSNSM.Off
def next(self, input): action = map(RSNAction.RSNAction, [input["action"]])[0] if action == RSNAction.recvLocReq: # TODO: lookup the queried bus location and # TODO: response to user directly global BUS_TABLE, LOC_REQ_NO LOGGER.info("received location request: %s" % input) # fetch the nearest bus available # TODO: this function should be polished nearest_bus = None nearest_loc = None nearest_dist = -1 for key in BUS_TABLE: bus = BUS_TABLE[key] if (int(bus["last_update"]) >= int(LOC_REQ_NO) - 1) and (int( bus["last_update"]) <= int(LOC_REQ_NO)): distance = int(input["original"]["location"]) - int( bus["location"]) if (nearest_dist < 0 or distance < nearest_dist) and distance >= 0: nearest_dist = distance nearest_bus = key nearest_loc = bus["location"] response_message = { "SM": "USER_SM", "action": "recvRes", "location": nearest_loc, "busId": nearest_bus, "original": input["original"] } MessagePasser.directSend(input["original"]["userIP"], input["original"]["userPort"], response_message) return RSNSM.Ready elif action == RSNAction.askBusLoc: # periodically ask each buses' location # TODO: triggered by host timer global GROUP_MEMBER, RSN_ID, ROUTE_NO, LOCAL_ADDR, LOC_REQ_NO LOGGER.info("asking each bus' location %s" % BUS_TABLE.keys()) LOC_REQ_NO = LOC_REQ_NO + 1 # maybe overflow!!! req_loc_message = { "SM": "DRIVER_SM", "action": "recvLocReq", "requestNo": LOC_REQ_NO, "rsnId": RSN_ID, "route": ROUTE_NO, "rsnIP": LOCAL_ADDR.ip, "rsnPort": LOCAL_ADDR.port } #MessagePasser.multicast(GROUP_MEMBER, req_loc_message) # TODO: replace the code below with a multicast version for member in BUS_TABLE: MessagePasser.directSend(BUS_TABLE[member]["addr"].ip, BUS_TABLE[member]["addr"].port, req_loc_message) return RSNSM.Ready elif action == RSNAction.recvDriverLoc: # TODO: update local cache global BUS_TABLE, ROUTE_NO if input["route"] == ROUTE_NO \ and input["busId"] in BUS_TABLE \ and input["requestNo"] > BUS_TABLE[input["busId"]]["last_update"]: BUS_TABLE[input["busId"]] = { "direction": input["direction"], "location": input["location"], "addr": Addr(input["busIP"], input["busPort"]), "last_update": input["requestNo"] # TODO: use local time stamp } return RSNSM.Ready elif action == RSNAction.recvBusChange: # TODO: add or remove a bus from current group LOGGER.info("Receive bus change request: %s" % input) global GROUP_MEMBER, BUS_TABLE, ROUTE_NO, RSN_ID, LOCAL_ADDR, LOC_REQ_NO if input["route"] == ROUTE_NO: if input["type"] == "add": #if not input["busId"] in BUS_TABLE: #GROUP_MEMBER.append(input["busId"]) BUS_TABLE[input["busId"]] = { "direction": input["direction"], "location": input["location"], "addr": Addr(input["busIP"], input["busPort"]), "last_update": LOC_REQ_NO # TODO: use local time stamp } # send an ACK to driver rsn_ack = { "SM": "DRIVER_SM", "action": "recvRSNAck", "route": ROUTE_NO, "rsnId": RSN_ID, "rsnIP": LOCAL_ADDR.ip, "rsnPort": LOCAL_ADDR.port } MessagePasser.directSend(input["busIP"], input["busPort"], rsn_ack) elif input["type"] == "remove": if input["busId"] in BUS_TABLE: #GROUP_MEMBER.remove(input["busId"]) BUS_TABLE.pop(input["busId"]) return RSNSM.Ready elif action == RSNAction.recvGSNHB: LOGGER.info("Receive GSN heart beat: %s" % input["HBNo"]) global BUS_TABLE, RSN_ID, ROUTE_NO, LOCAL_ADDR, GSN_ADDR, LOC_REQ_NO # filter out some dead buses remove_list = [] for bus in BUS_TABLE: if int(BUS_TABLE[bus]["last_update"]) + 1 < LOC_REQ_NO: remove_list.append(bus) for bus in remove_list: BUS_TABLE.pop(bus) # send current route table to GSN HB_res_message = { "SM": "GSN_SM", "action": "recvHBRes", "HBNo": input["HBNo"], "rsnId": RSN_ID, "route": ROUTE_NO, "rsnIP": LOCAL_ADDR.ip, "rsnPort": LOCAL_ADDR.port, "busTable": BUS_TABLE } MessagePasser.directSend(GSN_ADDR.ip, GSN_ADDR.port, HB_res_message) return RSNSM.Ready elif action == RSNAction.recvRSNResign: LOGGER.info("Receive GSN resign") TIMER_OFF.set() TIMER_ON.clear() return RSNSM.Idle elif action == RSNAction.turnOff: # TODO: do something to shut-down TIMER_OFF.set() TIMER_ON.clear() return RSNSM.Off else: # for other illegal action # assert 0, "Ready: invalid action: %s" % str(input) pass
def next(self, input): action = map(RSNAction.RSNAction, [input["action"]])[0] if action == RSNAction.recvRSNAssign: # TODO: received the group info from GSN # TODO: store the group info global LOCAL_ADDR, ROUTE_NO, BUS_TABLE, TIMER_ON, TIMER_OFF ROUTE_NO = input["route"] # if the RSN is the Driver itself, send a recvRSNAck to driver role if input["type"] == "self": BUS_TABLE[input["original"]["busId"]] = { "direction": input["original"]["direction"], "location": input["original"]["location"], "addr": Addr(input["original"]["busIP"], input["original"]["busPort"]), "last_update": 0 # TODO: use local time stamp } rsn_ack = { "SM": "DRIVER_SM", "action": "recvRSNAck", "route": ROUTE_NO, "rsnId": RSN_ID, "rsnIP": LOCAL_ADDR.ip, "rsnPort": LOCAL_ADDR.port } MessagePasser.directSend(input["original"]["busIP"], input["original"]["busPort"], rsn_ack) elif input["type"] == "normal": BUS_TABLE = input["busTable"] if BUS_TABLE == None: BUS_TABLE = {} # reset all time stampes for bus in BUS_TABLE: BUS_TABLE[bus]["last_update"] = 0 # notify each bus global GROUP_MEMBER, RSN_ID, ROUTE_NO, LOCAL_ADDR, LOC_REQ_NO LOGGER.info("asking each bus' location %s" % BUS_TABLE.keys()) LOC_REQ_NO = 0 LOC_REQ_NO = LOC_REQ_NO + 1 # maybe overflow!!! req_loc_message = { "SM": "DRIVER_SM", "action": "recvLocReq", "requestNo": LOC_REQ_NO, "rsnId": RSN_ID, "route": ROUTE_NO, "rsnIP": LOCAL_ADDR.ip, "rsnPort": LOCAL_ADDR.port } for member in BUS_TABLE: MessagePasser.directSend(BUS_TABLE[member]["addr"].ip, BUS_TABLE[member]["addr"].port, req_loc_message) # unblock the timer thread TIMER_OFF.clear() TIMER_ON.set() return RSNSM.Ready elif action == RSNAction.timeout: # TODO: re-ping # Terry: seems no need to re-ping gsn return RSNSM.Idle elif action == RSNAction.turnOff: global TIMER_ON, TIMER_OFF # TODO: do something to shut-down TIMER_OFF.set() TIMER_ON.clear() return RSNSM.Off else: # for other illegal action # assert 0, "Idle: invalid action: %s" % str(input) pass