class TaskServer: ############################# def __init__(self, address, configDesc): self.configDesc = configDesc self.address = address self.curPort = configDesc.startPort self.taskHeaders = {} self.taskManager = TaskManager(configDesc.clientUid) self.taskComputer = TaskComputer(configDesc.clientUid, self, self.configDesc.estimatedPerformance, self.configDesc.taskRequestInterval) self.taskSeesions = {} self.taskSeesionsIncoming = [] self.lastMessages = [] self.resultsToSend = {} self.__startAccepting() ############################# def syncNetwork(self): self.taskComputer.run() self.__removeOldTasks() self.__sendWaitingResults() ############################# # This method chooses random task from the network to compute on our machine def requestTask(self, estimatedPerformance): if len(self.taskHeaders.values()) > 0: tn = random.randrange(0, len(self.taskHeaders.values())) theader = self.taskHeaders.values()[tn] self.__connectAndSendTaskRequest(theader.taskOwnerAddress, theader.taskOwnerPort, theader.taskId, estimatedPerformance) return theader.taskId else: return 0 ############################# def requestResource(self, subTaskId, resourceHeader, address, port): self.__connectAndSendResourceRequest(address, port, subTaskId, resourceHeader) return subTaskId ############################# def sendResults(self, subTaskId, result, ownerAddress, ownerPort): if subTaskId not in self.resultsToSend: self.resultsToSend[subTaskId] = WaitingTaskResult( subTaskId, result, 0.0, 0.0, ownerAddress, ownerPort) else: assert False return True ############################# def newConnection(self, session): session.taskServer = self session.taskComputer = self.taskComputer session.taskManager = self.taskManager self.taskSeesionsIncoming.append(session) ############################# def getTasksHeaders(self): ths = self.taskHeaders.values() + self.taskManager.getTasksHeaders() ret = [] for th in ths: ret.append({ "id": th.taskId, "address": th.taskOwnerAddress, "port": th.taskOwnerPort, "ttl": th.ttl, "clientId": th.clientId }) return ret ############################# def addTaskHeader(self, thDictRepr): try: id = thDictRepr["id"] if id not in self.taskHeaders.keys(): # dont have it if id not in self.taskManager.tasks.keys( ): # It is not my task id print "Adding task {}".format(id) self.taskHeaders[id] = TaskHeader(thDictRepr["clientId"], id, thDictRepr["address"], thDictRepr["port"], thDictRepr["ttl"]) return True except: print "Wrong task header received" return False ############################# def removeTaskHeader(self, taskId): if taskId in self.taskHeaders: del self.taskHeaders[taskId] ############################# def removeTaskSession(self, taskSession): for tsk in self.taskSeesions.keys(): if self.taskSeesions[tsk] == taskSession: del self.taskSeesions[tsk] ############################# def setLastMessage(self, type, t, msg, address, port): if len(self.lastMessages) >= 5: self.lastMessages = self.lastMessages[-4:] self.lastMessages.append([type, t, address, port, msg]) ############################# def getLastMessages(self): return self.lastMessages ############################# def getWaitingTaskResult(self, subTaskId): if subTaskId in self.resultsToSend: return self.resultsToSend[subTaskId] else: return None ############################# def taskResultSent(self, subTaskId): if subTaskId in self.resultsToSend: del self.resultsToSend[subTaskId] else: assert False ############################# # PRIVATE SECTION ############################# def __startAccepting(self): print "Enabling tasks accepting state" Network.listen(self.configDesc.startPort, self.configDesc.endPort, TaskServerFactory(self), None, self.__listeningEstablished, self.__listeningFailure) ############################# def __listeningEstablished(self, port): self.curPort = port print "Port {} opened - listening".format(port) self.taskManager.listenAddress = self.address self.taskManager.listenPort = self.curPort ############################# def __listeningFailure(self, p): print "Opening {} port for listening failed, trying the next one".format( self.curPort) self.curPort = self.curPort + 1 if self.curPort <= self.configDesc.endPort: self.__runListenOnce() else: #FIXME: some graceful terminations should take place here sys.exit(0) ############################# def __connectAndSendTaskRequest(self, address, port, taskId, estimatedPerformance): Network.connect(address, port, TaskSession, self.__connectionForTaskRequestEstablished, self.__connectionForTaskRequestFailure, taskId, estimatedPerformance) ############################# def __connectAndSendResourceRequest(self, address, port, subTaskId, resourceHeader): Network.connect(address, port, TaskSession, self.__connectionForResourceRequestEstablished, self.__connectionForResourceRequestFailure, subTaskId, resourceHeader) ############################# def __connectionForTaskRequestEstablished(self, session, taskId, estimatedPerformance): session.taskServer = self session.taskComputer = self.taskComputer session.taskManager = self.taskManager self.taskSeesions[taskId] = session session.requestTask(taskId, estimatedPerformance) ############################# def __connectionForTaskRequestFailure(self, session, taskId, estimatedPerformance): print "Cannot connect to task {} owner".format(taskId) print "Removing task {} from task list".format(taskId) self.taskComputer.taskRequestRejected(taskId, "Connection failed") self.removeTaskHeader(taskId) ############################# def __connectAndSendTaskResults(self, address, port, waitingTaskResult): Network.connect(address, port, TaskSession, self.__connectionForTaskResultEstablished, self.__connectionForTaskResultFailure, waitingTaskResult) ############################# def __connectionForTaskResultEstablished(self, session, waitingTaskResult): session.taskServer = self session.taskComputer = self.taskComputer session.taskManager = self.taskManager self.taskSeesions[waitingTaskResult.subTaskId] = session session.sendReportComputedTask(waitingTaskResult.subTaskId) ############################# def __connectionForTaskResultFailure(self, waitingTaskResult): print "Cannot connect to task {} owner".format( waitingTaskResult.subTaskId) print "Removing task {} from task list".format( waitingTaskResult.subTaskId) waitingTaskResult.lastSendingTrial = time.time() waitingTaskResult.delayTime = self.configDesc.maxResultsSendignDelay waitingTaskResult.alreadySending = False ############################# def __connectionForResourceRequestEstablished(self, session, subTaskId, resourceHeader): session.taskServer = self session.taskComputer = self.taskComputer session.taskManager = self.taskManager self.taskSeesions[subTaskId] = session session.taskId = subTaskId session.requestResource(subTaskId, resourceHeader) ############################# def __connectionForResourceRequestFailure(self, session, subTaskId, resourceHeader): print "Cannot connect to task {} owner".format(subTaskId) print "Removing task {} from task list".format(subTaskId) self.taskComputer.resourceRequestRejected(subTaskId, "Connection failed") self.removeTaskHeader(subTaskId) ############################# def __removeOldTasks(self): for t in self.taskHeaders.values(): currTime = time.time() t.ttl = t.ttl - (currTime - t.lastChecking) t.lastChecking = currTime if t.ttl <= 0: print "Task {} dies".format(t.id) self.removeTaskHeader(t.id) self.taskManager.removeOldTasks() def __sendWaitingResults(self): for wtr in self.resultsToSend: waitingTaskResult = self.resultsToSend[wtr] if not waitingTaskResult.alreadySending: if time.time( ) - waitingTaskResult.lastSendingTrial > waitingTaskResult.delayTime: subTaskId = waitingTaskResult.subTaskId waitingTaskResult.alreadySending = True self.__connectAndSendTaskResults( waitingTaskResult.ownerAddress, waitingTaskResult.ownerPort, waitingTaskResult)