Пример #1
0
def ListenForClients(port, messageQueue, taskQueue, IOLock, numberOfConnections, numberOfConnectionsLock,resultsDirectory):
    '''Handles connecting clients
    
    This method opens a port to listen for clients. Whenever a new client connects, a new 'HandleConnection' process is started.
  
    Args
        - port -- the port on which the server should listen for clients
        - messageQueue -- the Queue from which the logger reads
        - taskQueue -- the Queue where all the tasks are located
        - IOLock -- Lock which needs to be aquired before reading or writing tasks to disc
        - numberOfConnections -- a multiprocessing.value which keeps track of the current number of connected clients
        - numberOfConnectionsLock -- a multiprocessing.IOLock which must be aquired when wishing to modify numberOfConnections
    '''
    
    #create a socket
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('',port))
        s.listen(1)
        messageQueue.put(UtilityFunctions.createLogEntry('inf', 'Listening for clients'))
    except socket.error, msg:
        print 'foo'
        messageQueue.put(UtilityFunctions.createLogEntry('inf','Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] + format_exc()))
        raise 
Пример #2
0
def handleClientTask(messageQueue, serverMessage,resultsDirectory):
    '''Processes a task received by the server
    
    Args:
        - messageQueue -- queue used for logging
        - serverMessge -- message received from server
    '''
    
    temporaryDirectory = './client/temp'
    
    if serverMessage['messageType'] == 'task':
        #write task to file
        clientScript = zlib.decompress(serverMessage['task'])#decompress the 
        clientScriptHandle = open(os.path.join(temporaryDirectory,'clientTask.py'),'w')
        clientScriptHandle.writelines(clientScript)
        clientScriptHandle.close()
        dataDirectory = None
        #if data exists, write data to file and extract it to ./temp/receivedData
        if not serverMessage['data'] == None:
            dataDirectory = os.path.join(temporaryDirectory,'receivedData')
            os.mkdir(dataDirectory)
            dataHandle = open(os.path.join(temporaryDirectory,'data.zip'),'w')
            dataHandle.writelines(serverMessage['data'])
            dataHandle.close()
            UtilityFunctions.unzipFile(os.path.join(temporaryDirectory,'data.zip'), dataDirectory)
            
        #execute received script
        subprocess.call(['python',os.path.join(temporaryDirectory,'clientTask.py'),os.path.abspath(dataDirectory)
                         ,os.path.abspath(resultsDirectory),])
        
        #cleanup temp folder
        UtilityFunctions.deleteContentsOfDirectory(temporaryDirectory)
        
    else:
        raise Exception('received an unknown Message type from the server. The type received was: '+serverMessage['task'])
Пример #3
0
def completeTask(messageQueue, IOLock, task, resultData, resultsDirectory):
    '''unzips resultData in results/taskName, writes task into completedTasks.txt
    
    Args:
        - messageQueue -- queue used for logging
        - IOLock -- the lock that must be acquired when reading or writing data  
        - task -- the task that was completed
        - resultData -- a zip file containing the results from the client loaded into memory as a zip file
    
    '''
    IOLock.acquire()
    pathToResult = ''
    
    try:
        #write results to file
        #---------------------
         
        taskName = task.split(',')[0]
        pathToResult = os.path.join(resultsDirectory,taskName)
        pathToCompletedTasks = os.path.join(resultsDirectory,'completedTasks.txt')
        
        #check if directory already exists, if it does, that means the task name was not unique
        if os.path.isdir(pathToResult):
            
            #add a counter to the task
            counter = 1
            pathToResult = os.path.join(resultsDirectory,taskName+str(counter))
            while(os.path.isdir(pathToResult)): #Note that counter will not overflow, as pythons ints are limited by address space, see http://stackoverflow.com/questions/9860588/maximum-value-for-long-integer so there will be other issues long before counter gets to big
                counter = counter+1; 
                pathToResult = os.path.join(resultsDirectory,taskName+str(counter))
            
            messageQueue.put(UtilityFunctions.createLogEntry('err','The following taskname is not unique: '+taskName+' the taskname was stored as: ' 
                                                             + taskName+str(counter)))
        #unzip results into pathToResult
        resultHandle = open('./server/temp/results.zip','w')
        resultHandle.writelines(resultData)
        resultHandle.close()
        os.makedirs(pathToResult)
        UtilityFunctions.unzipFile('./server/temp/results.zip',pathToResult)
        os.remove('./server/temp/results.zip')
        
        #update the completedTasks.txt file in temp to include the completed task
        if os.path.isfile(pathToCompletedTasks) and os.path.getsize(pathToCompletedTasks)>0:
            completedTasksLogHandle = open(pathToCompletedTasks,'a')
        else:
            completedTasksLogHandle = open(pathToCompletedTasks,'w')
        
        completedTasksLogHandle.write(task+'\n')
        completedTasksLogHandle.close()
        messageQueue.put(UtilityFunctions.createLogEntry('inf','Successfuly stored result for task: ' + task))
    
    except:
        messageQueue.put(UtilityFunctions.createLogEntry('deb','error in ServerSideTaskHandler.completeTask:\n'+traceback.format_exc()+'\ntask' + task))
        raise           
    
    finally:
        IOLock.release()
    
    
    return pathToResult
Пример #4
0
def getTask(messageQueue, taskQueue, IOLock):
    '''Takes a task from taskQueue, interprets it, loads instructions and data into memory
    
    Args:
        - messageQueue -- queue used for logging
        - taskQueue -- the global task queue from
        - IOLock -- the lock that must be acquired when reading or writing data  
    Returns:
        - task -- the task itself, if there are no tasks, this will be none
        - clientScript -- a python file loaded into memory and compressed with zlib.compress, if there are no tasks, this will be none
        - data -- a zipped file containing data for the client loaded into memory, if there are no tasks, this will be none, if no data folder exists, this will be none
    Raises:
        - Exceptions.NoTasks: if there are no tasks in the task queue
    
    '''
    
    IOLock.acquire()
    
    try:
        while True:
            try:
                task = taskQueue.get(True,0.1)
            except Queue.Empty:
                return None,None,None
            
            try:
                taskName,pathToScript,pathToData = task.split(',')
            except ValueError:
                messageQueue.put(UtilityFunctions.createLogEntry('err','the following task is in the wrong format: '+task))
                continue
            
            try:
                scriptHandle = open(pathToScript,'r')
                clientScript = zlib.compress(scriptHandle.read());
                scriptHandle.close();
            except IOError:
                messageQueue.put(UtilityFunctions.createLogEntry('err','could not read the following clientScript: '+pathToScript))
                continue
            
            if os.path.isdir(pathToData):
                UtilityFunctions.zipDir(pathToData, './server/temp/transferData.zip');
                transferDataHandle = open('./server/temp/transferData.zip');
                data = transferDataHandle.read();
                transferDataHandle.close();
                os.remove('./server/temp/transferData.zip')
            else:
                data = None
            
            break
        
        return task,clientScript,data
                
                
    except:
        messageQueue.put(UtilityFunctions.createLogEntry('deb','error in ServerSideTaskHandler.getTask:\n'+traceback.format_exc() + '\ntask' + task));
        raise            
            
        
    finally:
        IOLock.release()         
Пример #5
0
def getTask(messageQueue, taskQueue, IOLock):
    '''Takes a task from taskQueue, interprets it, loads instructions and data into memory
    
    Args:
        - messageQueue -- queue used for logging
        - taskQueue -- the global task queue from
        - IOLock -- the lock that must be acquired when reading or writing data  
    Returns:
        - task -- the task itself, if there are no tasks, this will be none
        - clientScript -- a python file loaded into memory and compressed with zlib.compress, if there are no tasks, this will be none
        - data -- a zipped file containing data for the client loaded into memory, if there are no tasks, this will be none, if no data folder exists, this will be none
    Raises:
        - Exceptions.NoTasks: if there are no tasks in the task queue
    
    '''
    
    IOLock.acquire()
    
    try:
        while True:
            try:
                task = taskQueue.get(True,0.1)
            except Queue.Empty:
                return None,None,None
            
            try:
                taskName,pathToScript,pathToData = task.split(',')
            except ValueError:
                messageQueue.put(UtilityFunctions.createLogEntry('err','the following task is in the wrong format: '+task))
                continue
            
            try:
                scriptHandle = open(pathToScript,'r')
                clientScript = zlib.compress(scriptHandle.read());
                scriptHandle.close();
            except IOError:
                messageQueue.put(UtilityFunctions.createLogEntry('err','could not read the following clientScript: '+pathToScript))
                continue
            
            if os.path.isdir(pathToData):
                UtilityFunctions.zipDir(pathToData, './server/temp/transferData.zip');
                transferDataHandle = open('./server/temp/transferData.zip');
                data = transferDataHandle.read();
                transferDataHandle.close();
                os.remove('./server/temp/transferData.zip')
            else:
                data = None
            
            break
        
        return task,clientScript,data
                
                
    except:
        messageQueue.put(UtilityFunctions.createLogEntry('deb','error in ServerSideTaskHandler.getTask:\n'+traceback.format_exc() + '\ntask' + task));
        raise            
            
        
    finally:
        IOLock.release()         
Пример #6
0
def ListenForClients(port, messageQueue, taskQueue, IOLock,
                     numberOfConnections, numberOfConnectionsLock,
                     resultsDirectory):
    '''Handles connecting clients
    
    This method opens a port to listen for clients. Whenever a new client connects, a new 'HandleConnection' process is started.
  
    Args
        - port -- the port on which the server should listen for clients
        - messageQueue -- the Queue from which the logger reads
        - taskQueue -- the Queue where all the tasks are located
        - IOLock -- Lock which needs to be aquired before reading or writing tasks to disc
        - numberOfConnections -- a multiprocessing.value which keeps track of the current number of connected clients
        - numberOfConnectionsLock -- a multiprocessing.IOLock which must be aquired when wishing to modify numberOfConnections
    '''

    #create a socket
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('', port))
        s.listen(1)
        messageQueue.put(
            UtilityFunctions.createLogEntry('inf', 'Listening for clients'))
    except socket.error, msg:
        messageQueue.put(
            UtilityFunctions.createLogEntry(
                'inf', 'Bind failed. Error Code : ' + str(msg[0]) +
                ' Message ' + msg[1] + format_exc()))
        raise
Пример #7
0
def completeTask(messageQueue, IOLock, task, resultData, resultsDirectory):
    '''unzips resultData in results/taskName, writes task into completedTasks.txt
    
    Args:
        - messageQueue -- queue used for logging
        - IOLock -- the lock that must be acquired when reading or writing data  
        - task -- the task that was completed
        - resultData -- a zip file containing the results from the client loaded into memory as a zip file
    
    '''
    IOLock.acquire()
    pathToResult = ''
    
    try:
        #write results to file
        #---------------------
         
        taskName = task.split(',')[0]
        pathToResult = os.path.join(resultsDirectory,taskName)
        pathToCompletedTasks = os.path.join(resultsDirectory,'completedTasks.txt')
        
        #check if directory already exists, if it does, that means the task name was not unique
        if os.path.isdir(pathToResult):
            
            #add a counter to the task
            counter = 1
            pathToResult = os.path.join(resultsDirectory,taskName+str(counter))
            while(os.path.isdir(pathToResult)): #Note that counter will not overflow, as pythons ints are limited by address space, see http://stackoverflow.com/questions/9860588/maximum-value-for-long-integer so there will be other issues long before counter gets to big
                counter = counter+1; 
                pathToResult = os.path.join(resultsDirectory,taskName+str(counter))
            
            messageQueue.put(UtilityFunctions.createLogEntry('err','The following taskname is not unique: '+taskName+' the taskname was stored as: ' 
                                                             + taskName+str(counter)))
        #unzip results into pathToResult
        resultHandle = open('./server/temp/results.zip','w')
        resultHandle.writelines(resultData)
        resultHandle.close()
        os.makedirs(pathToResult)
        UtilityFunctions.unzipFile('./server/temp/results.zip',pathToResult)
        os.remove('./server/temp/results.zip')
        
        #update the completedTasks.txt file in temp to include the completed task
        if os.path.isfile(pathToCompletedTasks) and os.path.getsize(pathToCompletedTasks)>0:
            completedTasksLogHandle = open(pathToCompletedTasks,'a')
        else:
            completedTasksLogHandle = open(pathToCompletedTasks,'w')
        
        completedTasksLogHandle.write(task+'\n')
        completedTasksLogHandle.close()
        messageQueue.put(UtilityFunctions.createLogEntry('inf','Successfuly stored result for task: ' + task))
    
    except:
        messageQueue.put(UtilityFunctions.createLogEntry('deb','error in ServerSideTaskHandler.completeTask:\n'+traceback.format_exc()+'\ntask' + task))
        raise           
    
    finally:
        IOLock.release()
    
    
    return pathToResult
Пример #8
0
def clientMain(serverIP, serverPort):
    '''Starts the client
    
    Args:
        - serverIP -- ip address of server to connect to
        - serverPort -- port on which the server is listening
    
    '''

    #initialization of values
    #timeName = time.strftime("%d%b%Y%H%M%S", time.localtime()) # a unique id created from the time when the script starts 
    messageQueue = multiprocessing.Queue() # the queue where all log messages are written to.
    logControlValue = multiprocessing.Value('i',int(True)) #A boolean indicating the the logging process should continue to run. There is no type for bool, so we use int
    resultsDirectory, logsDirectory = UtilityFunctions.initializeClientFolderStructure() #directories where results and logs should be stored respectively
    UtilityFunctions.deleteContentsOfDirectory('./client/temp')
    #-------------start logging module
    loggingProcess = multiprocessing.Process(target = LoggingModule.log, args=(logControlValue,messageQueue,logsDirectory))
    loggingProcess.start()
    
    #communicate with server    
    
    handleConnection(messageQueue, serverIP,serverPort,resultsDirectory)
    
    
    #exit note that we only get here once the server closes the connection
    logControlValue.value = int(False)
    loggingProcess.join()
    sys.exit(0)
Пример #9
0
def clientMain(port, resultsName, pathToTasks, pathToPreviouslyCompletedTasks = None):
    '''Starts the server. 
    
    Args:
        - port -- port on which the server should listen
        - resultsName -- name to which to append the currentTime in order to create a unique string
        - pathToTasks -- path to the tasks file
        - pathToPreviouslyCompletedTasks -- path to a file containing tasks that have already been completed and should not be executed again.
    '''

    #-------------initialization of values
    timeName = resultsName+datetime.datetime.now().strftime('%d%b%Y%H%M%S.%f') # a unique id created from the time when the script starts 
    messageQueue = multiprocessing.Queue() # the queue where all log messages are written to.
    taskQueue = multiprocessing.Queue() # the queue where all tasks that have been loaded into memory and have not been completed are kept
    logControlValue = multiprocessing.Value('i',int(True)) #A boolean indicating the the logging process should continue to run. There is no type for bool, so we use int
    numberOfConnectionsValue = multiprocessing.Value('i',0) #An integer counting the number of clients that are currently connected to the server
    numberOfConnectionsLock = multiprocessing.Lock() #A Lock that should be acquired when modifying the numberOfConnections value
    IOLock = multiprocessing.Lock() #A lock that should be acquired when performing writing of results to memory
    signal.signal(signal.SIGINT, signal_handler) #register our signal_handler so that we can detect ctrl-C signals
    resultsDirectory, logsDirectory = UtilityFunctions.initializeServerFolderStructure(timeName) #directories where results and logs should be stored respectively

    if not ServerSideTaskHandler.initializeTaskQueue(taskQueue, pathToTasks,resultsDirectory,pathToPreviouslyCompletedTasks):
        sys.exit(1)# initialize Task Queue returns false if initialization and loading of tasks failed
    #-------------done initializing
    
    #-------------start logging module
    loggingProcess = multiprocessing.Process(target = LoggingModule.log, args=(logControlValue,messageQueue,logsDirectory))
    loggingProcess.start()

    #Start listening for clients:    
    #ListenForClients(port,messageQueue,taskHandler) #DEBUG
    listeningProcess = multiprocessing.Process(target = ListenForClients, args=(port, messageQueue, taskQueue, IOLock, numberOfConnectionsValue, numberOfConnectionsLock,resultsDirectory))
    listeningProcess.start()
    
    
    
    #idle while there are clients connected and tasks still incomplete
    now = datetime.datetime.now()
    logPeriod = datetime.timedelta(minutes=10)
    messageQueue.put(UtilityFunctions.createLogEntry('inf','Periodic log entry, there are currently:\t ' 
                             + str(taskQueue.qsize()) + ' tasks yet to complete'))
    while numberOfConnectionsValue.value>0 or taskQueue.qsize() > 0:
        if datetime.datetime.now() > now+logPeriod:
            messageQueue.put(UtilityFunctions.createLogEntry('inf','Periodic log entry, there are currently:\t ' 
                             + str(taskQueue.qsize()) + ' tasks yet to complete'))
            now = datetime.datetime.now()
        time.sleep(1)
    
    messageQueue.put(UtilityFunctions.createLogEntry('inf','Completed all tasks, exiting'))
    listeningProcess.terminate()
    logControlValue.value = int(False)
    loggingProcess.join()
    listeningProcess.join()
    sys.exit(0)
Пример #10
0
def processResult(messageQueue, IOLock, pathToReceivedResult):
    '''Server will call this method just after it received and stored a result from a client. 
    Replace this method with code that should update the data and the clienttasks that have not been
    executed so far if this is necessary. By default this method does nothing.
    
    Args:
        - messageQueue: -- queue used for logging
        - IOLock: -- A lock that should be acquired before any modifications to tasks and data are made to prevent race conditions. Note that if updating tasks takes too long, this will be a bottleneck
        - pathToReceivedResult: -- the path to where the most recent task was stored
    '''

    #This method should eventually implement boosting by updating a vector that

    #sends results to
    timeName = datetime.datetime.now().strftime('%d%b%Y%H%M%S.%f/')
    pathToReceivedResult = pathToReceivedResult + '/..'
    pathToSendResult = '/root/dcap_bnet/results/' + timeName

    try:
        sendResults(messageQueue, pathToReceivedResult, pathToSendResult)
        # pass

    except Exception as e:
        messageQueue.put(
            UtilityFunctions.createLogEntry(
                'err', "Could not send results to %s because: " %
                (pathToSendResult) + str(e) + format_exc()))
def processResult(messageQueue, IOLock, pathToReceivedResult):
    '''Server will call this method just after it received and stored a result from a client. 
    Replace this method with code that should update the data and the clienttasks that have not been
    executed so far if this is necessary. By default this method does nothing.
    
    Args:
        - messageQueue: -- queue used for logging
        - IOLock: -- A lock that should be acquired before any modifications to tasks and data are made to prevent race conditions. Note that if updating tasks takes too long, this will be a bottleneck
        - pathToReceivedResult: -- the path to where the most recent task was stored
    '''

    #This method should eventually implement boosting by updating a vector that 

    #sends results to
    timeName = datetime.datetime.now().strftime('%d%b%Y%H%M%S.%f/')
    print os.getcwd()
    print "path to received result", pathToReceivedResult
    pathToReceivedResult = pathToReceivedResult + '/..'
    pathToSendResult = '/root/dcap_bnet/results/' + timeName

    try:
        sendResults(messageQueue, pathToReceivedResult , pathToSendResult)
        # pass

    except Exception as e:
        messageQueue.put(UtilityFunctions.createLogEntry('err',"Could not send results to %s because: " % (pathToSendResult) + str(e) + format_exc()))
def sendResults(messageQueue, pathToReceivedResult, pathToSendResult):
    '''Server sends results to specified location using FTP
    
    Args:
    	- pathToReceivedResult: -- the path to where the most recent task was stored
        - pathToSendResult: -- path where results should be sent
    '''
    messageQueue.put(UtilityFunctions.createLogEntry('inf','sending results from ' +  pathToReceivedResult + ' to ' + pathToSendResult))
    shutil.copytree(pathToReceivedResult , pathToSendResult)
Пример #13
0
def handleClientTask(messageQueue, serverMessage, resultsDirectory):
    '''Processes a task received by the server
    
    Args:
        - messageQueue -- queue used for logging
        - serverMessge -- message received from server
    '''

    temporaryDirectory = './client/temp'

    if serverMessage['messageType'] == 'task':
        #write task to file
        clientScript = zlib.decompress(serverMessage['task'])  #decompress the
        clientScriptHandle = open(
            os.path.join(temporaryDirectory, 'clientTask.py'), 'w')
        clientScriptHandle.writelines(clientScript)
        clientScriptHandle.close()
        dataDirectory = None
        #if data exists, write data to file and extract it to ./temp/receivedData
        if not serverMessage['data'] == None:
            dataDirectory = os.path.join(temporaryDirectory, 'receivedData')
            os.mkdir(dataDirectory)
            dataHandle = open(os.path.join(temporaryDirectory, 'data.zip'),
                              'w')
            dataHandle.writelines(serverMessage['data'])
            dataHandle.close()
            UtilityFunctions.unzipFile(
                os.path.join(temporaryDirectory, 'data.zip'), dataDirectory)

        #execute received script
        subprocess.call([
            'python',
            os.path.join(temporaryDirectory, 'clientTask.py'),
            os.path.abspath(dataDirectory),
            os.path.abspath(resultsDirectory),
        ])

        #cleanup temp folder
        UtilityFunctions.deleteContentsOfDirectory(temporaryDirectory)

    else:
        raise Exception(
            'received an unknown Message type from the server. The type received was: '
            + serverMessage['task'])
Пример #14
0
def returnTask(messageQueue, taskQueue, task):
    '''If a task fails and needs to be returned, call this method, it returns the task to the taskQueue
    
    Args:
        - messageQueue -- queue used for logging
        - taskQueue -- the global task queue from
        - task -- the task that should be returned
    
    '''
    
    taskQueue.put(task)
    messageQueue.put(UtilityFunctions.createLogEntry('inf', 'successfully put '+task+'back in the task queue'))
Пример #15
0
def returnTask(messageQueue, taskQueue, task):
    '''If a task fails and needs to be returned, call this method, it returns the task to the taskQueue
    
    Args:
        - messageQueue -- queue used for logging
        - taskQueue -- the global task queue from
        - task -- the task that should be returned
    
    '''
    
    taskQueue.put(task)
    messageQueue.put(UtilityFunctions.createLogEntry('inf', 'successfully put '+task+'back in the task queue'))
Пример #16
0
def loadResult(resultsDirectory):
    '''Zips all data in the results directory in a zip file and returns that zip file loaded into memory. Also removes resultsData from disk '''
    temporaryDirectory = './client/temp'
    UtilityFunctions.zipDir(resultsDirectory,
                            os.path.join(temporaryDirectory, 'result.zip'))
    resultHandle = open(os.path.join(temporaryDirectory, 'result.zip'), 'r')
    resultData = resultHandle.readlines()
    resultHandle.close()
    UtilityFunctions.deleteContentsOfDirectory(temporaryDirectory)
    UtilityFunctions.deleteContentsOfDirectory(resultsDirectory)
    return resultData
Пример #17
0
def loadResult(resultsDirectory):
    '''Zips all data in the results directory in a zip file and returns that zip file loaded into memory. Also removes resultsData from disk '''
    temporaryDirectory = './client/temp'
    UtilityFunctions.zipDir(resultsDirectory, os.path.join(temporaryDirectory,'result.zip'))
    resultHandle = open(os.path.join(temporaryDirectory,'result.zip'),'r')
    resultData = resultHandle.readlines()
    resultHandle.close()
    UtilityFunctions.deleteContentsOfDirectory(temporaryDirectory)
    UtilityFunctions.deleteContentsOfDirectory(resultsDirectory)
    return resultData
    
        
Пример #18
0
def HandleConnection(connection, clientAdress, messageQueue, taskQueue, IOLock,
                     numberOfConnections, numberOfConnectionsLock,
                     resultsDirectory):
    '''Handles the connection and communication between the server and an individual client
    
    Basic communication process:
        1. EDOClient sends a 'requestTask' type message
        2. EDOServer asks ServerSideTaskHandler for a Task, ServerSideTaskHandler returns a task.py and a data.zip file that have been loaded into memory. It also returns a string that identifies the task
        3. EDOServer sends message to client
        4. EDOServer waits for reply
        5. EDOClient sends back a 'taskCompleted' type message,
        6. EDOServer calls ServerSideTaskHandler.taskCompleted with the received resultComputed Message
        7. EDOServer continues at step 2
    
    If the connection to the client dies, EDOServer calls ServerSideTaskHandler.returnTask(taskid)

    Args
        - connection -- connection to an individual client
        - clientAdress -- the address of the client
        - messageQueue -- the Queue from which the logger reads
        - taskQueue -- the Queue where all the tasks are located
        - IOLock --
        - numberOfConnections -- a multiprocessing.value which keeps track of the current number of connected clients
        - numberOfConnectionsLock -- a multiprocessing.IOLock which must be aquired when wishing to modify numberOfConnections
        
    '''

    #update number of connections
    numberOfConnectionsLock.acquire()
    numberOfConnections.value = numberOfConnections.value + 1
    numberOfConnectionsLock.release()

    task = None

    try:
        # part of the following while loops was adapted from http://stackoverflow.com/questions/1708835/receving-socket-python

        running = True

        length = None  #parameter telling us the length of the incoming message. Each message is message has the preamble length followed by : followed by data of length length
        messageBuffer = ""  # a buffer where data is stored until we've received the entire message
        data = ""  # the received data from the socket
        while running == True:
            data = connection.recv(1024)
            if not data:
                raise Exception("Client " + str(clientAdress) +
                                "sent an empty string, the connection is dead")

            messageBuffer += data  #add what we received to the buffer
            while True:
                if length is None:  #if length undefined, we must wait until we've received length, we know we have once we see :
                    if ':' not in messageBuffer:
                        break
                    # remove the length bytes from the front of messageBuffer
                    # leave any remaining bytes in the messageBuffer!
                    length_str, ignored, messageBuffer = messageBuffer.partition(
                        ':')
                    length = int(length_str)

                if len(messageBuffer) < length:
                    break
                # split off the full message from the remaining bytes
                # leave any remaining bytes in the messageBuffer!
                message = messageBuffer[:length]
                messageBuffer = messageBuffer[length:]
                length = None

                # PROCESS MESSAGE HERE

                receivedMessage = cPickle.loads(message)
                messageQueue.put(
                    UtilityFunctions.createLogEntry(
                        'inf',
                        'Received a ' + str(receivedMessage['messageType']) +
                        'message from client: ' + str(clientAdress)))

                if receivedMessage['messageType'] == 'requestTask':

                    task, clientScript, data = ServerSideTaskHandler.getTask(
                        messageQueue, taskQueue, IOLock)
                    if task == None:
                        messageQueue.put(
                            UtilityFunctions.createLogEntry(
                                'inf', 'Client ' + str(clientAdress) +
                                ' requested a task, but all tasks are done'))
                        running = False
                        break

                elif receivedMessage['messageType'] == 'result':
                    messageQueue.put(
                        UtilityFunctions.createLogEntry(
                            'inf', 'Client ' + str(clientAdress) +
                            ' completed his task'))
                    pathToReceivedResult = ServerSideTaskHandler.completeTask(
                        messageQueue, IOLock, task, receivedMessage['data'],
                        resultsDirectory)
                    task = None
                    # ServerSideResultsProcessor.processResult(messageQueue, IOLock, pathToReceivedResult)

                    task, clientScript, data = ServerSideTaskHandler.getTask(
                        messageQueue, taskQueue, IOLock)
                    if task == None:
                        messageQueue.put(
                            UtilityFunctions.createLogEntry(
                                'inf', 'Client ' + str(clientAdress) +
                                ' requested a task, but all tasks are done'))
                        running = False
                        break

                else:
                    raise Exception('Received unknown message type' +
                                    receivedMessage['messageType'])

                message = UtilityFunctions.createMessage(
                    'task', clientScript, data)
                UtilityFunctions.sendAll(connection, message)
                messageQueue.put(
                    UtilityFunctions.createLogEntry(
                        'inf',
                        'sent ' + str(task) + 'to ' + str(clientAdress)))

        messageQueue.put(
            UtilityFunctions.createLogEntry(
                'inf', 'Done sending tasks to ' + str(clientAdress)))
    except Exception as e:
        messageQueue.put(
            UtilityFunctions.createLogEntry(
                'err', 'EVOServer: Connection: to ' + str(clientAdress) +
                'failed because: ' + str(e) + format_exc()))
        if not task == None:
            ServerSideTaskHandler.returnTask(messageQueue, taskQueue, task)

    finally:
        numberOfConnectionsLock.acquire()
        numberOfConnections.value = numberOfConnections.value - 1
        numberOfConnectionsLock.release()
Пример #19
0
def cleanUp():
    '''Message to be called when server exits successfully, cleans up temporary Files'''
    
    UtilityFunctions.deleteContentsOfDirectory('./temp')
Пример #20
0
def clientMain(port,
               resultsName,
               pathToTasks,
               pathToPreviouslyCompletedTasks=None):
    '''Starts the server. 
    
    Args:
        - port -- port on which the server should listen
        - resultsName -- name to which to append the currentTime in order to create a unique string
        - pathToTasks -- path to the tasks file
        - pathToPreviouslyCompletedTasks -- path to a file containing tasks that have already been completed and should not be executed again.
    '''

    #-------------initialization of values
    timeName = resultsName + datetime.datetime.now().strftime(
        '%d%b%Y%H%M%S.%f'
    )  # a unique id created from the time when the script starts
    messageQueue = multiprocessing.Queue(
    )  # the queue where all log messages are written to.
    taskQueue = multiprocessing.Queue(
    )  # the queue where all tasks that have been loaded into memory and have not been completed are kept
    logControlValue = multiprocessing.Value(
        'i', int(True)
    )  #A boolean indicating the the logging process should continue to run. There is no type for bool, so we use int
    numberOfConnectionsValue = multiprocessing.Value(
        'i', 0
    )  #An integer counting the number of clients that are currently connected to the server
    numberOfConnectionsLock = multiprocessing.Lock(
    )  #A Lock that should be acquired when modifying the numberOfConnections value
    IOLock = multiprocessing.Lock(
    )  #A lock that should be acquired when performing writing of results to memory
    signal.signal(
        signal.SIGINT, signal_handler
    )  #register our signal_handler so that we can detect ctrl-C signals
    resultsDirectory, logsDirectory = UtilityFunctions.initializeServerFolderStructure(
        timeName
    )  #directories where results and logs should be stored respectively

    if not ServerSideTaskHandler.initializeTaskQueue(
            taskQueue, pathToTasks, resultsDirectory,
            pathToPreviouslyCompletedTasks):
        sys.exit(
            1
        )  # initialize Task Queue returns false if initialization and loading of tasks failed
    #-------------done initializing

    #-------------start logging module
    loggingProcess = multiprocessing.Process(target=LoggingModule.log,
                                             args=(logControlValue,
                                                   messageQueue,
                                                   logsDirectory))
    loggingProcess.start()

    #Start listening for clients:
    #ListenForClients(port,messageQueue,taskHandler) #DEBUG
    listeningProcess = multiprocessing.Process(
        target=ListenForClients,
        args=(port, messageQueue, taskQueue, IOLock, numberOfConnectionsValue,
              numberOfConnectionsLock, resultsDirectory))
    listeningProcess.start()

    #idle while there are clients connected and tasks still incomplete
    now = datetime.datetime.now()
    logPeriod = datetime.timedelta(minutes=10)
    messageQueue.put(
        UtilityFunctions.createLogEntry(
            'inf', 'Periodic log entry, there are currently:\t ' +
            str(taskQueue.qsize()) + ' tasks yet to complete'))
    while numberOfConnectionsValue.value > 0 or taskQueue.qsize() > 0:
        if datetime.datetime.now() > now + logPeriod:
            messageQueue.put(
                UtilityFunctions.createLogEntry(
                    'inf', 'Periodic log entry, there are currently:\t ' +
                    str(taskQueue.qsize()) + ' tasks yet to complete'))
            now = datetime.datetime.now()
        time.sleep(1)

    messageQueue.put(
        UtilityFunctions.createLogEntry('inf', 'Completed all tasks, exiting'))
    listeningProcess.terminate()
    logControlValue.value = int(False)
    loggingProcess.join()
    listeningProcess.join()
    sys.exit(0)
Пример #21
0
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('', port))
        s.listen(1)
        messageQueue.put(
            UtilityFunctions.createLogEntry('inf', 'Listening for clients'))
    except socket.error, msg:
        messageQueue.put(
            UtilityFunctions.createLogEntry(
                'inf', 'Bind failed. Error Code : ' + str(msg[0]) +
                ' Message ' + msg[1] + format_exc()))
        raise

    messageQueue.put(
        UtilityFunctions.createLogEntry(
            'inf',
            'EVOServer: Listener: Accepting connections on port ' + str(port)))

    #accept incoming clients, start a new multiprocessing.Process for each incoming connection
    while True:
        try:
            conn, address = s.accept()
            messageQueue.put(
                UtilityFunctions.createLogEntry(
                    'inf', 'New connection from ' + str(address)))
            #HandleConnection(conn,address,messageQueue,taskHandler) # DEBUG
            multiprocessing.Process(
                target=HandleConnection,
                args=(conn, address, messageQueue, taskQueue, IOLock,
                      numberOfConnections, numberOfConnectionsLock,
                      resultsDirectory)).start()
Пример #22
0
def cleanUp():
    '''Message to be called when server exits successfully, cleans up temporary Files'''
    
    UtilityFunctions.deleteContentsOfDirectory('./temp')
Пример #23
0
        - numberOfConnectionsLock -- a multiprocessing.IOLock which must be aquired when wishing to modify numberOfConnections
    '''
    
    #create a socket
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind(('',port))
        s.listen(1)
        messageQueue.put(UtilityFunctions.createLogEntry('inf', 'Listening for clients'))
    except socket.error, msg:
        print 'foo'
        messageQueue.put(UtilityFunctions.createLogEntry('inf','Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] + format_exc()))
        raise 

    messageQueue.put(UtilityFunctions.createLogEntry('inf','EVOServer: Listener: Accepting connections on port ' + str(port)))
    
    #accept incoming clients, start a new multiprocessing.Process for each incoming connection
    while True:
        try:
            conn, address = s.accept()
            messageQueue.put(UtilityFunctions.createLogEntry('inf','New connection from ' + str(address)))
            #HandleConnection(conn,address,messageQueue,taskHandler) # DEBUG
            multiprocessing.Process(target=HandleConnection, args=(conn, address, messageQueue, taskQueue, IOLock, numberOfConnections, numberOfConnectionsLock,resultsDirectory)).start()
        except socket.error, msg:
            messageQueue.put(UtilityFunctions.createLogEntry('inf','Accept failed due to : ' + str(msg[0]) + ' Message ' + msg[1] + format_exc()))



def HandleConnection(connection, clientAdress, messageQueue, taskQueue, IOLock, numberOfConnections, numberOfConnectionsLock, resultsDirectory):
    '''Handles the connection and communication between the server and an individual client
Пример #24
0
def HandleConnection(connection, clientAdress, messageQueue, taskQueue, IOLock, numberOfConnections, numberOfConnectionsLock, resultsDirectory):
    '''Handles the connection and communication between the server and an individual client
    
    Basic communication process:
        1. EDOClient sends a 'requestTask' type message
        2. EDOServer asks ServerSideTaskHandler for a Task, ServerSideTaskHandler returns a task.py and a data.zip file that have been loaded into memory. It also returns a string that identifies the task
        3. EDOServer sends message to client
        4. EDOServer waits for reply
        5. EDOClient sends back a 'taskCompleted' type message,
        6. EDOServer calls ServerSideTaskHandler.taskCompleted with the received resultComputed Message
        7. EDOServer continues at step 2
    
    If the connection to the client dies, EDOServer calls ServerSideTaskHandler.returnTask(taskid)

    Args
        - connection -- connection to an individual client
        - clientAdress -- the address of the client
        - messageQueue -- the Queue from which the logger reads
        - taskQueue -- the Queue where all the tasks are located
        - IOLock --
        - numberOfConnections -- a multiprocessing.value which keeps track of the current number of connected clients
        - numberOfConnectionsLock -- a multiprocessing.IOLock which must be aquired when wishing to modify numberOfConnections
        
    '''
    
    
    #update number of connections
    numberOfConnectionsLock.acquire()
    numberOfConnections.value = numberOfConnections.value+1
    numberOfConnectionsLock.release()


    
    task = None
    
    try:
        # part of the following while loops was adapted from http://stackoverflow.com/questions/1708835/receving-socket-python
        
        running = True
        
        length = None #parameter telling us the length of the incoming message. Each message is message has the preamble length followed by : followed by data of length length
        messageBuffer = "" # a buffer where data is stored until we've received the entire message
        data = "" # the received data from the socket
        while running == True:
            data = connection.recv(1024)
            if not data:
                raise Exception("Client "+str(clientAdress)+"sent an empty string, the connection is dead")

            messageBuffer += data #add what we received to the buffer
            while True:
                if length is None: #if length undefined, we must wait until we've received length, we know we have once we see :
                    if ':' not in messageBuffer:
                        break
                    # remove the length bytes from the front of messageBuffer
                    # leave any remaining bytes in the messageBuffer!
                    length_str, ignored, messageBuffer = messageBuffer.partition(':')
                    length = int(length_str)
        
                if len(messageBuffer) < length:
                    break
                # split off the full message from the remaining bytes
                # leave any remaining bytes in the messageBuffer!
                message = messageBuffer[:length]
                messageBuffer = messageBuffer[length:]
                length = None
                
                
                # PROCESS MESSAGE HERE

                receivedMessage = cPickle.loads(message)
                messageQueue.put(UtilityFunctions.createLogEntry('inf','Received a ' + str(receivedMessage['messageType']) + 'message from client: ' + str(clientAdress)))                            
            

                if receivedMessage['messageType'] == 'requestTask':
                
                    task, clientScript,data = ServerSideTaskHandler.getTask(messageQueue,taskQueue,IOLock)
                    if task == None:
                        messageQueue.put(UtilityFunctions.createLogEntry('inf','Client '+str(clientAdress)+' requested a task, but all tasks are done'))
                        running = False
                        break;
                    
                elif receivedMessage['messageType'] == 'result':
                    messageQueue.put(UtilityFunctions.createLogEntry('inf','Client '+str(clientAdress)+' completed his task'))
                    pathToReceivedResult = ServerSideTaskHandler.completeTask(messageQueue,IOLock, task, receivedMessage['data'], resultsDirectory)
                    task = None
                    ServerSideResultsProcessor.processResult(messageQueue, IOLock, pathToReceivedResult)
                    
                    task, clientScript,data = ServerSideTaskHandler.getTask(messageQueue,taskQueue,IOLock)
                    if task == None:
                        messageQueue.put(UtilityFunctions.createLogEntry('inf','Client '+str(clientAdress)+' requested a task, but all tasks are done'))
                        running = False
                        break;
                
                    
                else:
                    raise Exception('Received unknown message type'+receivedMessage['messageType'])
                
                message = UtilityFunctions.createMessage('task', clientScript, data)
                UtilityFunctions.sendAll(connection,message)
                messageQueue.put(UtilityFunctions.createLogEntry('inf','sent ' + str(task) + 'to ' + str(clientAdress)))
        
        messageQueue.put(UtilityFunctions.createLogEntry('inf','Done sending tasks to ' + str(clientAdress)))
    except Exception as e:
        messageQueue.put(UtilityFunctions.createLogEntry('err','EVOServer: Connection: to ' + str(clientAdress) + 'failed because: ' + str(e) + format_exc()))
        if not task == None:
            ServerSideTaskHandler.returnTask(messageQueue,taskQueue,task)
    
    finally:
        numberOfConnectionsLock.acquire()
        numberOfConnections.value = numberOfConnections.value-1
        numberOfConnectionsLock.release()
Пример #25
0
def handleConnection(messageQueue, server_address,port,resultsDirectory):
    '''Handles Connection to Server. Passes on messages to the ClientSideTaskHandler'''

    while True:
        try:
            connection = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            connection.connect((server_address,port))
            break
        
        except Exception as e:
            messageQueue.put(UtilityFunctions.createLogEntry('err','Unable to connect to PyComputeServer, received the following error: ' + str(e)))
            time.sleep(20)
            
        
    
    messageQueue.put(UtilityFunctions.createLogEntry('inf','Connected to PyComputeServer. ' + server_address + 
            ':' + str(port)))
            
    
    try:
        #tell the server we are ready to process tasks
        requestTaskMessage = UtilityFunctions.createMessage('requestTask')
        UtilityFunctions.sendAll(connection,requestTaskMessage)
        #begin to process tasks sent by the server
        running = True
        length = None
        messageBuffer = ""
        data = ""        
        while running == True:
            data = connection.recv(1024)
            if not data:
                messageQueue.put(UtilityFunctions.createLogEntry('err',"Server sent an empty string, the connection is dead"))
                break
            messageBuffer += data
            #the following loop allows for making sure the entire receivedMessage arrives
            while True:
                if length is None:
                    if ':' not in messageBuffer:
                        break
                    # remove the length bytes from the front of messageBuffer
                    # leave any remaining bytes in the messageBuffer!
                    length_str, ignored, messageBuffer = messageBuffer.partition(':')
                    length = int(length_str)
        
                if len(messageBuffer) < length:
                    break
                # split off the full receivedMessage from the remaining bytes
                # leave any remaining bytes in the messageBuffer!
                message = messageBuffer[:length]
                messageBuffer = messageBuffer[length:]
                length = None
                # PROCESS MESSAGE HERE
                serverMessage = cPickle.loads(message)
                
                #exec('osreturn='+receivedMessage['data'])
                #if osreturn == 0:
                print 'executing task'
                ClientSideTaskHandler.handleClientTask(messageQueue, serverMessage, resultsDirectory)
                resultData = ClientSideTaskHandler.loadResult(resultsDirectory) #we expect the client has put the data in the resultsDirectory
                returnMessage = UtilityFunctions.createMessage('result', data=resultData)
                UtilityFunctions.sendAll(connection,returnMessage)
    
    except Exception as e:
        messageQueue.put(UtilityFunctions.createLogEntry('err',"Connection to server failed because: " + str(e) + format_exc()))