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

Source Code for Module PyFoam.Infrastructure.FoamServer

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