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()
|