annotate mcserver/mcserver.py @ 54:c0b34039917a tip

Server: added an exposed function to log the start time of a performance (for log-to-audio sync)
author Mathieu Barthet <mathieu.barthet@eecs.qmul.ac.uk>
date Wed, 14 Oct 2015 19:20:08 +0100
parents fe04ff3547c7
children
rev   line source
gyorgyf@0 1 #!/usr/bin/env python
gyorgyf@0 2 # encoding: utf-8
gyorgyf@0 3 """
gyorgyf@0 4 mcserver.py
gyorgyf@0 5
gyorgyf@0 6 Created by George Fazekas on 2012-06-16.
mathieu@54 7 Modifications by Mathieu Barthet.
gyorgyf@0 8 Copyright (c) 2012 . All rights reserved.
gyorgyf@0 9 """
gyorgyf@0 10
gyorgyf@12 11 import os,sys,optparse,signal,time,math
gyorgyf@0 12 import cherrypy as cp
gyorgyf@0 13
gyorgyf@0 14 from cherrypy.lib import static
gyorgyf@0 15 import subprocess as sp
gyorgyf@0 16 from subprocess import Popen as spopen
gyorgyf@0 17
gyorgyf@0 18
gyorgyf@0 19 op = optparse.OptionParser()
gyorgyf@0 20 op.add_option('-u', '--user', action="store", dest="USER", default="server", type="str")
gyorgyf@0 21 options, args = op.parse_args()
gyorgyf@0 22 CONFIG_FILE = "mc%(USER)s.cfg" %options.__dict__
gyorgyf@0 23
gyorgyf@0 24 if not os.path.isfile(CONFIG_FILE) :
gyorgyf@4 25 print >> sys.stderr, "Config file not found: %s" %CONFIG_FILE
gyorgyf@0 26 sys.exit(-1)
gyorgyf@0 27
gyorgyf@0 28
gyorgyf@12 29 class Input(object):
gyorgyf@12 30
gyorgyf@27 31 def __init__(self,x,y,age,dist):
gyorgyf@12 32 self.time = time.time()
gyorgyf@12 33 self.x=float(x)
gyorgyf@12 34 self.y=float(y)
gyorgyf@12 35 self.count = 1
gyorgyf@27 36 self.age = age
gyorgyf@27 37 self.dist = dist
gyorgyf@12 38
gyorgyf@12 39 def __cmp__(self,other):
gyorgyf@12 40 d = math.sqrt( math.pow((self.x-other.x),2) + math.pow((self.y-other.y),2) )
gyorgyf@27 41 if d < self.dist :
gyorgyf@12 42 return 0
gyorgyf@12 43 else :
gyorgyf@12 44 return -1
gyorgyf@12 45
gyorgyf@12 46 def dead(self):
gyorgyf@27 47 return time.time()-self.time > self.age
gyorgyf@12 48
gyorgyf@12 49 def __repr__(self):
gyorgyf@27 50 # return (self.x,self.y,self.count).__repr__()
gyorgyf@27 51 return "(%.4f,%.4f,%i)" %(self.x,self.y,self.count)
gyorgyf@12 52
gyorgyf@12 53 def inc(self):
gyorgyf@12 54 self.time = time.time()
gyorgyf@12 55 self.count += 1
gyorgyf@27 56 # print self.count
gyorgyf@12 57
gyorgyf@12 58
gyorgyf@0 59 class MoodConductor:
gyorgyf@0 60
gyorgyf@5 61 def __init__(self):
gyorgyf@12 62 self.inputs = []
gyorgyf@27 63 self.age = 3
gyorgyf@27 64 self.dist = 0.1
gyorgyf@29 65 self.ninp = 18
gyorgyf@5 66
gyorgyf@27 67 # def index(self):
gyorgyf@27 68 # return str()
gyorgyf@0 69
gyorgyf@0 70 @cp.expose
gyorgyf@33 71 def test(self):
gyorgyf@33 72 print "Server test function accessed."
gyorgyf@33 73 cp.log.error("Server test function accessed.")
gyorgyf@33 74 return "Server: Test passed."
gyorgyf@33 75
gyorgyf@33 76 @cp.expose
gyorgyf@0 77 def mood(self,x,y):
gyorgyf@33 78 print "Received coordinates", x,y
gyorgyf@27 79 i = Input(x,y,self.age,self.dist)
gyorgyf@12 80 if i in self.inputs :
gyorgyf@12 81 self.inputs[self.inputs.index(i)].inc()
gyorgyf@12 82 else :
gyorgyf@12 83 self.inputs.insert(0,i)
gyorgyf@27 84 self.inputs = self.inputs[:self.ninp]
gyorgyf@29 85 cp.log.error("%s,%.6s,%.6s,%s" %(str(cp.request.remote.ip),x,y,i.time))
gyorgyf@12 86 return str()
gyorgyf@5 87
gyorgyf@5 88 @cp.expose
gyorgyf@5 89 def result(self):
gyorgyf@12 90 for i in self.inputs :
gyorgyf@12 91 if i.dead() : self.inputs.remove(i)
gyorgyf@12 92 return self.inputs.__repr__()
gyorgyf@27 93
gyorgyf@27 94 @cp.expose
gyorgyf@27 95 def config(self,**kwargs):
gyorgyf@27 96 if kwargs.has_key('age') :
gyorgyf@27 97 self.age = float(kwargs['age'])
gyorgyf@27 98 if kwargs.has_key('dist') :
gyorgyf@27 99 self.dist = float(kwargs['dist'])
gyorgyf@27 100 if kwargs.has_key('ninp') :
gyorgyf@27 101 self.ninp = int(kwargs['ninp'])
gyorgyf@29 102 # cp.log.error("Config changed...")
gyorgyf@32 103 print "New configuration received from visual client."
gyorgyf@27 104 return str()
gyorgyf@27 105
gyorgyf@27 106 @cp.expose
gyorgyf@27 107 def getconf(self):
gyorgyf@27 108 self.config_list = ['age','dist','ninp']
gyorgyf@29 109 cp.log.error(str(map(lambda x: (x,"%.3f" % self.__dict__[x]),self.config_list)))
gyorgyf@27 110 return str(map(lambda x: (x,"%.3f" % self.__dict__[x]),self.config_list)) #+ " Sessions: " + str(cp.tools.sessions)
gyorgyf@5 111
mathieu@54 112 @cp.expose
mathieu@54 113 def start(self):
mathieu@54 114 timelog = "Performance start time: %s"%time.time()
mathieu@54 115 print "Start function accessed."
mathieu@54 116 cp.log.error(timelog)
mathieu@54 117 return timelog
gyorgyf@0 118
gyorgyf@0 119
gyorgyf@0 120 def getProcessPids(port,kill=False):
gyorgyf@0 121 '''Get the pid of the offending Python process given a port after an unsuccessful restart.'''
gyorgyf@0 122 print "Running lsof -i :"+str(port)," ...\n\n"
gyorgyf@0 123 command = "lsof -i :"+str(port)
gyorgyf@0 124 w = spopen(command,stdout=sp.PIPE,stderr=sp.PIPE,shell=True)
gyorgyf@0 125 se = w.stderr.readlines()
gyorgyf@0 126 result = w.stdout.readlines()
gyorgyf@0 127 exitcode = w.wait()
gyorgyf@0 128 if not result :
gyorgyf@33 129 print "getProcessPid:: Unable to obtain process pid. (lsof returned nothing. exitcode: %s) This is fine in most cases..." %str(exitcode)
gyorgyf@0 130 return False
gyorgyf@0 131 import pprint
gyorgyf@0 132 pprint.pprint(result)
gyorgyf@0 133
gyorgyf@0 134 # get heading:
gyorgyf@0 135 ix = None
gyorgyf@0 136 head = result[0].upper()
gyorgyf@0 137 if 'PID' in head:
gyorgyf@0 138 head = filter(lambda x: x != str(), head.split(' '))
gyorgyf@0 139 head = map(lambda x: x.strip().replace(' ',''), head)
gyorgyf@0 140 if 'PID' in head : ix = head.index('PID')
gyorgyf@0 141 # get process pid
gyorgyf@0 142 pids = []
gyorgyf@0 143 for line in result :
gyorgyf@0 144 if 'python' in line.lower() :
gyorgyf@0 145 line = filter(lambda x: x != str(), line.split(' '))
gyorgyf@0 146 line = map(lambda x: x.strip().replace(' ',''), line)
gyorgyf@0 147 try :
gyorgyf@0 148 if ix :
gyorgyf@0 149 pids.append(int(line[ix]))
gyorgyf@0 150 else:
gyorgyf@0 151 numbers = filter(lambda x: x.isdigit(), line)
gyorgyf@0 152 pids.append(int(numbers[0]))
gyorgyf@0 153 except:
gyorgyf@0 154 print 'Error parsing lsof results.'
gyorgyf@0 155 return False
gyorgyf@0 156 print 'Pids found: ',pids
gyorgyf@0 157 # kill if specified
gyorgyf@0 158 if kill :
gyorgyf@0 159 pids_killed = []
gyorgyf@0 160 import signal
gyorgyf@0 161 for pid in pids:
gyorgyf@0 162 print 'Killing process: ',pid
gyorgyf@0 163 try :
gyorgyf@0 164 os.kill(pid,signal.SIGKILL)
gyorgyf@0 165 pids_killed.append(pid)
gyorgyf@0 166 except :
gyorgyf@0 167 print 'Failed: ',pid
gyorgyf@0 168 if pids_killed :
gyorgyf@0 169 print 'Processes killed:',pids_killed,' Waiting 10 secods...'
gyorgyf@0 170 import time
gyorgyf@0 171 time.sleep(10)
gyorgyf@32 172 print "Starting..."
gyorgyf@0 173 return True
gyorgyf@0 174 return False
gyorgyf@0 175
gyorgyf@0 176
gyorgyf@0 177 def main(argv=None):
gyorgyf@0 178
gyorgyf@0 179 # Configure and start
gyorgyf@3 180 cp.config.update(CONFIG_FILE)
gyorgyf@0 181 cp.config.update({'tools.staticdir.root': os.getcwd()})
gyorgyf@3 182 cp.tree.mount(MoodConductor(),script_name="/moodconductor",config=CONFIG_FILE)
gyorgyf@2 183 port = int(cp.server.socket_port)
gyorgyf@3 184 ip = cp.server.socket_host
gyorgyf@3 185 print "Trying to bind: %(ip)s:%(port)s" %locals()
gyorgyf@0 186 getProcessPids(port,kill=True)
gyorgyf@33 187 print "Starting..."
gyorgyf@0 188 cp.quickstart()
gyorgyf@0 189
gyorgyf@0 190 if __name__ == "__main__":
gyorgyf@0 191 main()