gyorgyf@0: #!/usr/bin/env python gyorgyf@0: # encoding: utf-8 gyorgyf@0: """ gyorgyf@0: mcserver.py gyorgyf@0: gyorgyf@0: Created by George Fazekas on 2012-06-16. mathieu@54: Modifications by Mathieu Barthet. gyorgyf@0: Copyright (c) 2012 . All rights reserved. gyorgyf@0: """ gyorgyf@0: gyorgyf@12: import os,sys,optparse,signal,time,math gyorgyf@0: import cherrypy as cp gyorgyf@0: gyorgyf@0: from cherrypy.lib import static gyorgyf@0: import subprocess as sp gyorgyf@0: from subprocess import Popen as spopen gyorgyf@0: gyorgyf@0: gyorgyf@0: op = optparse.OptionParser() gyorgyf@0: op.add_option('-u', '--user', action="store", dest="USER", default="server", type="str") gyorgyf@0: options, args = op.parse_args() gyorgyf@0: CONFIG_FILE = "mc%(USER)s.cfg" %options.__dict__ gyorgyf@0: gyorgyf@0: if not os.path.isfile(CONFIG_FILE) : gyorgyf@4: print >> sys.stderr, "Config file not found: %s" %CONFIG_FILE gyorgyf@0: sys.exit(-1) gyorgyf@0: gyorgyf@0: gyorgyf@12: class Input(object): gyorgyf@12: gyorgyf@27: def __init__(self,x,y,age,dist): gyorgyf@12: self.time = time.time() gyorgyf@12: self.x=float(x) gyorgyf@12: self.y=float(y) gyorgyf@12: self.count = 1 gyorgyf@27: self.age = age gyorgyf@27: self.dist = dist gyorgyf@12: gyorgyf@12: def __cmp__(self,other): gyorgyf@12: d = math.sqrt( math.pow((self.x-other.x),2) + math.pow((self.y-other.y),2) ) gyorgyf@27: if d < self.dist : gyorgyf@12: return 0 gyorgyf@12: else : gyorgyf@12: return -1 gyorgyf@12: gyorgyf@12: def dead(self): gyorgyf@27: return time.time()-self.time > self.age gyorgyf@12: gyorgyf@12: def __repr__(self): gyorgyf@27: # return (self.x,self.y,self.count).__repr__() gyorgyf@27: return "(%.4f,%.4f,%i)" %(self.x,self.y,self.count) gyorgyf@12: gyorgyf@12: def inc(self): gyorgyf@12: self.time = time.time() gyorgyf@12: self.count += 1 gyorgyf@27: # print self.count gyorgyf@12: gyorgyf@12: gyorgyf@0: class MoodConductor: gyorgyf@0: gyorgyf@5: def __init__(self): gyorgyf@12: self.inputs = [] gyorgyf@27: self.age = 3 gyorgyf@27: self.dist = 0.1 gyorgyf@29: self.ninp = 18 gyorgyf@5: gyorgyf@27: # def index(self): gyorgyf@27: # return str() gyorgyf@0: gyorgyf@0: @cp.expose gyorgyf@33: def test(self): gyorgyf@33: print "Server test function accessed." gyorgyf@33: cp.log.error("Server test function accessed.") gyorgyf@33: return "Server: Test passed." gyorgyf@33: gyorgyf@33: @cp.expose gyorgyf@0: def mood(self,x,y): gyorgyf@33: print "Received coordinates", x,y gyorgyf@27: i = Input(x,y,self.age,self.dist) gyorgyf@12: if i in self.inputs : gyorgyf@12: self.inputs[self.inputs.index(i)].inc() gyorgyf@12: else : gyorgyf@12: self.inputs.insert(0,i) gyorgyf@27: self.inputs = self.inputs[:self.ninp] gyorgyf@29: cp.log.error("%s,%.6s,%.6s,%s" %(str(cp.request.remote.ip),x,y,i.time)) gyorgyf@12: return str() gyorgyf@5: gyorgyf@5: @cp.expose gyorgyf@5: def result(self): gyorgyf@12: for i in self.inputs : gyorgyf@12: if i.dead() : self.inputs.remove(i) gyorgyf@12: return self.inputs.__repr__() gyorgyf@27: gyorgyf@27: @cp.expose gyorgyf@27: def config(self,**kwargs): gyorgyf@27: if kwargs.has_key('age') : gyorgyf@27: self.age = float(kwargs['age']) gyorgyf@27: if kwargs.has_key('dist') : gyorgyf@27: self.dist = float(kwargs['dist']) gyorgyf@27: if kwargs.has_key('ninp') : gyorgyf@27: self.ninp = int(kwargs['ninp']) gyorgyf@29: # cp.log.error("Config changed...") gyorgyf@32: print "New configuration received from visual client." gyorgyf@27: return str() gyorgyf@27: gyorgyf@27: @cp.expose gyorgyf@27: def getconf(self): gyorgyf@27: self.config_list = ['age','dist','ninp'] gyorgyf@29: cp.log.error(str(map(lambda x: (x,"%.3f" % self.__dict__[x]),self.config_list))) gyorgyf@27: return str(map(lambda x: (x,"%.3f" % self.__dict__[x]),self.config_list)) #+ " Sessions: " + str(cp.tools.sessions) gyorgyf@5: mathieu@54: @cp.expose mathieu@54: def start(self): mathieu@54: timelog = "Performance start time: %s"%time.time() mathieu@54: print "Start function accessed." mathieu@54: cp.log.error(timelog) mathieu@54: return timelog gyorgyf@0: gyorgyf@0: gyorgyf@0: def getProcessPids(port,kill=False): gyorgyf@0: '''Get the pid of the offending Python process given a port after an unsuccessful restart.''' gyorgyf@0: print "Running lsof -i :"+str(port)," ...\n\n" gyorgyf@0: command = "lsof -i :"+str(port) gyorgyf@0: w = spopen(command,stdout=sp.PIPE,stderr=sp.PIPE,shell=True) gyorgyf@0: se = w.stderr.readlines() gyorgyf@0: result = w.stdout.readlines() gyorgyf@0: exitcode = w.wait() gyorgyf@0: if not result : gyorgyf@33: print "getProcessPid:: Unable to obtain process pid. (lsof returned nothing. exitcode: %s) This is fine in most cases..." %str(exitcode) gyorgyf@0: return False gyorgyf@0: import pprint gyorgyf@0: pprint.pprint(result) gyorgyf@0: gyorgyf@0: # get heading: gyorgyf@0: ix = None gyorgyf@0: head = result[0].upper() gyorgyf@0: if 'PID' in head: gyorgyf@0: head = filter(lambda x: x != str(), head.split(' ')) gyorgyf@0: head = map(lambda x: x.strip().replace(' ',''), head) gyorgyf@0: if 'PID' in head : ix = head.index('PID') gyorgyf@0: # get process pid gyorgyf@0: pids = [] gyorgyf@0: for line in result : gyorgyf@0: if 'python' in line.lower() : gyorgyf@0: line = filter(lambda x: x != str(), line.split(' ')) gyorgyf@0: line = map(lambda x: x.strip().replace(' ',''), line) gyorgyf@0: try : gyorgyf@0: if ix : gyorgyf@0: pids.append(int(line[ix])) gyorgyf@0: else: gyorgyf@0: numbers = filter(lambda x: x.isdigit(), line) gyorgyf@0: pids.append(int(numbers[0])) gyorgyf@0: except: gyorgyf@0: print 'Error parsing lsof results.' gyorgyf@0: return False gyorgyf@0: print 'Pids found: ',pids gyorgyf@0: # kill if specified gyorgyf@0: if kill : gyorgyf@0: pids_killed = [] gyorgyf@0: import signal gyorgyf@0: for pid in pids: gyorgyf@0: print 'Killing process: ',pid gyorgyf@0: try : gyorgyf@0: os.kill(pid,signal.SIGKILL) gyorgyf@0: pids_killed.append(pid) gyorgyf@0: except : gyorgyf@0: print 'Failed: ',pid gyorgyf@0: if pids_killed : gyorgyf@0: print 'Processes killed:',pids_killed,' Waiting 10 secods...' gyorgyf@0: import time gyorgyf@0: time.sleep(10) gyorgyf@32: print "Starting..." gyorgyf@0: return True gyorgyf@0: return False gyorgyf@0: gyorgyf@0: gyorgyf@0: def main(argv=None): gyorgyf@0: gyorgyf@0: # Configure and start gyorgyf@3: cp.config.update(CONFIG_FILE) gyorgyf@0: cp.config.update({'tools.staticdir.root': os.getcwd()}) gyorgyf@3: cp.tree.mount(MoodConductor(),script_name="/moodconductor",config=CONFIG_FILE) gyorgyf@2: port = int(cp.server.socket_port) gyorgyf@3: ip = cp.server.socket_host gyorgyf@3: print "Trying to bind: %(ip)s:%(port)s" %locals() gyorgyf@0: getProcessPids(port,kill=True) gyorgyf@33: print "Starting..." gyorgyf@0: cp.quickstart() gyorgyf@0: gyorgyf@0: if __name__ == "__main__": gyorgyf@0: main()