Package PyFoam :: Package Infrastructure :: Module FoamServer
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.Infrastructure.FoamServer

  1  """A XMLRPC-Server that answeres about the current state of a Foam-Run""" 
  2   
  3  from ServerBase import ServerBase 
  4   
  5  from xmlrpclib import ServerProxy 
  6   
  7  from PyFoam import configuration as config 
  8  from PyFoam import versionString 
  9  from PyFoam.Basics.RingBuffer import RingBuffer 
 10  from PyFoam.Infrastructure.NetworkHelpers import freeServerPort 
 11  from PyFoam.Infrastructure.Logging import foamLogger 
 12  from PyFoam.FoamInformation import getPathFromEnviron,foamMPI 
 13  from PyFoam.RunDictionary.ParameterFile import ParameterFile 
 14   
 15  from Hardcoded import userName 
 16   
 17  from threading import Lock,Thread,Timer 
 18  from time import time 
 19  from os import environ,uname,path,getpid 
 20  import socket 
 21   
 22  import sys,string 
 23  from traceback import extract_tb 
 24   
25 -def findFreePort():
26 """Finds a free server port on this machine and returns it 27 28 Valid server ports are in the range 18000 upward (the function tries to 29 find the lowest possible port number 30 31 ATTENTION: this part may introduce race conditions""" 32 33 return freeServerPort(config().getint("Network","startServerPort"), 34 length=config().getint("Network","nrServerPorts"))
35
36 -class FoamAnswerer(object):
37 """The class that handles the actual requests (only needed to hide the 38 Thread-methods from the world 39 """
40 - def __init__(self,run=None,master=None,lines=100):
41 """ 42 @param run: The thread that controls the run 43 @param master: The Runner-Object that controls everything 44 @param lines: the number of lines the server should remember 45 """ 46 self._run=run 47 self._master=master 48 self._lines=RingBuffer(nr=lines) 49 self._lastTime=time() 50 self._linesLock=Lock() 51 self._maxOutputTime=config().getfloat("IsAlive","maxTimeStart")
52
53 - def _insertLine(self,line):
54 """Inserts a new line, not to be called via XMLRPC""" 55 self._linesLock.acquire() 56 self._lines.insert(line) 57 tmp=time() 58 if (tmp-self._lastTime)>self._maxOutputTime: 59 self._maxOutputTime=tmp-self._lastTime 60 self._lastTime=tmp 61 self._linesLock.release()
62
63 - def isFoamServer(self):
64 """This is a Foam-Server (True by default)""" 65 return True
66
67 - def isLiving(self):
68 """The calculation still generates output and therefor seems to be living""" 69 return self.elapsedTime()<self._maxOutputTime
70
71 - def _kill(self):
72 """Interrupts the FOAM-process""" 73 if self._run: 74 foamLogger().warning("Killed by request") 75 self._run.interrupt() 76 return True 77 else: 78 return False
79
80 - def stop(self):
81 """Stops the run gracefully (after writing the last time-step to disk)""" 82 self._master.stopGracefully() 83 return True
84
85 - def argv(self):
86 """Argument vector with which the runner was called""" 87 if self._master: 88 return self._master.origArgv 89 else: 90 return []
91
92 - def usedArgv(self):
93 """Argument vector with which the runner started the run""" 94 if self._master: 95 return self._master.argv 96 else: 97 return []
98
99 - def isParallel(self):
100 """Is it a parallel run?""" 101 if self._master: 102 return self._master.lam!=None 103 else: 104 return False
105
106 - def procNr(self):
107 """How many processors are used?""" 108 if self._master: 109 if self._master.lam!=None: 110 return self._master.lam.cpuNr() 111 else: 112 return 1 113 else: 114 return 0
115
116 - def nrWarnings(self):
117 """Number of warnings the executable emitted""" 118 if self._master: 119 return self._master.warnings 120 else: 121 return 0
122
123 - def commandLine(self):
124 """The command line""" 125 if self._master: 126 return string.join(self._master.origArgv) 127 else: 128 return ""
129
130 - def actualCommandLine(self):
131 """The actual command line used""" 132 if self._master: 133 return self._master.cmd 134 else: 135 return ""
136
137 - def scriptName(self):
138 """Name of the Python-Script that runs the show""" 139 return sys.argv[0]
140
141 - def lastLine(self):
142 """@return: the last line that was output by the running FOAM-process""" 143 self._linesLock.acquire() 144 result=self._lines.last() 145 self._linesLock.release() 146 if not result: 147 return "" 148 return result
149
150 - def tail(self):
151 """@return: the current last lines as a string""" 152 self._linesLock.acquire() 153 tmp=self._lines.dump() 154 self._linesLock.release() 155 result="" 156 for l in tmp: 157 result+=l 158 159 return result
160
161 - def elapsedTime(self):
162 """@return: time in seconds since the last line was output""" 163 self._linesLock.acquire() 164 result=time()-self._lastTime 165 self._linesLock.release() 166 167 return result
168
169 - def getEnviron(self,name):
170 """@param name: name of an environment variable 171 @return: value of the variable, empty string if non-existing""" 172 result="" 173 if environ.has_key(name): 174 result=environ[name] 175 return result
176
177 - def mpi(self):
178 """@return: name of the MPI-implementation""" 179 return foamMPI()
180
181 - def foamVersion(self):
182 """Version number of the Foam-Version""" 183 return self.getEnviron("WM_PROJECT_VERSION")
184
185 - def pyFoamVersion(self):
186 """@return: Version number of the PyFoam""" 187 return versionString()
188
189 - def uname(self):
190 """@return: the complete uname-information""" 191 return uname()
192
193 - def ip(self):
194 """@return: the ip of this machine""" 195 return socket.gethostbyname(socket.gethostname())
196
197 - def hostname(self):
198 """@return: The name of the computer""" 199 return uname()[1]
200
201 - def configuration(self):
202 """@return: all the configured parameters""" 203 return config().dump()
204
205 - def cwd(self):
206 """@return: the current working directory""" 207 return path.abspath(path.curdir)
208
209 - def pid(self):
210 """@return: the PID of the script""" 211 return getpid()
212
213 - def user(self):
214 """@return: the user that runs this script""" 215 return userName()
216
217 - def id(self):
218 """@return: an ID for this run: IP and process-id""" 219 return "%s:%d" % (self.ip(),self.pid())
220
221 - def time(self):
222 """@return: the current time in the simulation""" 223 if self._master.nowTime: 224 return self._master.nowTime 225 else: 226 return 0
227
228 - def createTime(self):
229 """@return: the time in the simulation for which the mesh was created""" 230 if self._master.nowTime: 231 return self._master.createTime 232 else: 233 return 0
234
235 - def _readParameter(self,name):
236 """Reads a parametr from the controlDict 237 @param name: the parameter 238 @return: The value""" 239 control=ParameterFile(self._master.getSolutionDirectory().controlDict()) 240 return control.readParameter(name)
241
242 - def startTime(self):
243 """@return: parameter startTime from the controlDict""" 244 return float(self._readParameter("startTime"))
245
246 - def endTime(self):
247 """@return: parameter endTime from the controlDict""" 248 return float(self._readParameter("endTime"))
249
250 - def deltaT(self):
251 """@return: parameter startTime from the controlDict""" 252 return float(self._readParameter("deltaT"))
253
254 -class FoamServer(Thread):
255 """This is the class that serves the requests about the FOAM-Run"""
256 - def __init__(self,run=None,master=None,lines=100):
257 """ 258 @param run: The thread that controls the run 259 @param master: The Runner-Object that controls everything 260 @param lines: the number of lines the server should remember 261 """ 262 Thread.__init__(self) 263 self._port=findFreePort() 264 265 self._running=False 266 267 if self._port<0: 268 foamLogger().warning("Could not get a free port. Server not started") 269 return 270 271 foamLogger().info("Serving on port %d" % self._port) 272 self._server=ServerBase(('',self._port),logRequests=False) 273 self._server.register_introspection_functions() 274 self._answerer=FoamAnswerer(run=run,master=master,lines=lines) 275 self._server.register_instance(self._answerer) 276 self._server.register_function(self.killServer) 277 self._server.register_function(self.kill) 278 if run: 279 self._server.register_function(run.cpuTime) 280 self._server.register_function(run.cpuUserTime) 281 self._server.register_function(run.cpuSystemTime) 282 self._server.register_function(run.wallTime) 283 self._server.register_function(run.usedMemory)
284
285 - def run(self):
286 if self._port<0: 287 return 288 # wait befor registering to avoid timeouts 289 reg=Timer(5.,self.register) 290 reg.start() 291 292 self._running=True 293 294 while self._running: 295 self._server.handle_request() 296 297 # self._server.serve_forever() # the old way 298 self._server.server_close() 299 300 foamLogger().info("Stopped serving on port %d" % self._port)
301
302 - def kill(self):
303 """Interrupts the FOAM-process (and kills the server)""" 304 self._answerer._kill() 305 return self.killServer()
306
307 - def killServer(self):
308 """Kills the server process""" 309 tmp=self._running 310 self._running=False 311 return tmp
312
313 - def register(self):
314 """Tries to register with the Meta-Server""" 315 try: 316 meta=ServerProxy("http://%s:%d" % (config().get("Metaserver","ip"),config().getint("Metaserver","port"))) 317 meta.registerServer(self._answerer.ip(),self._answerer.pid(),self._port) 318 except socket.error, reason: 319 foamLogger().warning("Can't connect to meta-server - SocketError: "+str(reason)) 320 except: 321 foamLogger().error("Can't connect to meta-server - Unknown Error: "+str(sys.exc_info()[0])) 322 foamLogger().error(str(sys.exc_info()[1])) 323 foamLogger().error("Traceback: "+str(extract_tb(sys.exc_info()[2])))
324
325 - def deregister(self):
326 """Tries to deregister with the Meta-Server""" 327 self._server.server_close() 328 try: 329 meta=ServerProxy("http://%s:%d" % (config().get("Metaserver","ip"),config().getint("Metaserver","port"))) 330 meta.deregisterServer(self._answerer.ip(),self._answerer.pid(),self._port) 331 except socket.error, reason: 332 foamLogger().warning("Can't connect to meta-server - SocketError: "+str(reason)) 333 except: 334 foamLogger().error("Can't connect to meta-server - Unknown Error: "+str(sys.exc_info()[0])) 335 foamLogger().error(str(sys.exc_info()[1])) 336 foamLogger().error("Traceback: "+str(extract_tb(sys.exc_info()[2])))
337
338 - def _insertLine(self,line):
339 """Inserts a new line, not to be called via XMLRPC""" 340 self._answerer._insertLine(line)
341