Package PyFoam :: Package Execution :: Module FoamThread
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.Execution.FoamThread

  1  """Thread wrappers for OpenFOAM""" 
  2  from threading import Thread,Lock,Timer 
  3  from popen2 import Popen4 
  4  from time import time,sleep 
  5  from resource import getrusage,getpagesize,RUSAGE_SELF,RUSAGE_CHILDREN 
  6  from os import uname,kill 
  7  import signal 
  8   
  9  from PyFoam.Basics.LineReader import LineReader 
 10  from PyFoam.Infrastructure.Logging import foamLogger 
 11   
12 -def getLinuxMem(thrd):
13 """Reads the Memory usage of a thread on a linux-System 14 15 @param thrd: the thread object in question""" 16 17 # print "Timer called" 18 19 if not thrd.isLinux or thrd.threadPid<0: 20 return 21 22 mem=0 23 24 try: 25 t=open('/proc/%d/status' % thrd.threadPid) 26 v=t.read() 27 t.close() 28 # f=open('/tmp/test%dstatus' % thrd.threadPid,'w') 29 # f.write(v) 30 # f.close() 31 32 i=v.index('VmRSS') 33 tmp=v[i:].split() 34 if len(tmp)>=3: 35 mem=long(tmp[1]) 36 if tmp[2].lower()=='kb': 37 mem*=1024 38 elif tmp[2].lower()=='mb': 39 mem*=1024*1024 40 else: 41 mem=-1 42 except Exception,e: 43 print "Getting LinuxMem:",e 44 mem=-1 45 46 if mem>thrd.linuxMaxMem: 47 # print "Setting Memory to: ",mem 48 thrd.linuxMaxMem=mem 49 50 # print "Restarting Timer" 51 52 thrd.timer=Timer(thrd.timerTime,getLinuxMem,args=[thrd]) 53 thrd.timer.start()
54
55 -class FoamThread(Thread):
56 """Thread running an OpenFOAM command 57 58 The output of the command can be accessed in a thread-safe manner, 59 line by line 60 61 Designed to be used by the BasicRunner-class""" 62
63 - def __init__(self,cmdline):
64 """cmdline - Command line of the OpenFOAM command""" 65 Thread.__init__(self) 66 self.cmdline=cmdline 67 self.output=None 68 self.reader=LineReader() 69 70 self.isLinux=False 71 self.isDarwin=False 72 self.threadPid=-1 73 self.who=RUSAGE_CHILDREN 74 75 if uname()[0]=="Linux": 76 self.isLinux=True 77 self.linuxMaxMem=0 78 elif uname()[0]=="Darwin": 79 self.isDarwin=True 80 # self.who=RUSAGE_SELF 81 82 self.resStart=None 83 self.resEnd=None 84 85 self.timeStart=None 86 self.timeEnd=None 87 88 self.timerTime=5. 89 90 self.stateLock=Lock() 91 self.setState(False) 92 93 self.status=None 94 95 self.lineLock=Lock() 96 self.line="" 97 98 self.stateLock.acquire()
99
100 - def run(self):
101 """start the command""" 102 # print "Starting ",self.cmdline 103 self.resStart=getrusage(self.who) 104 self.timeStart=time() 105 106 run=Popen4(self.cmdline) 107 self.output=run.fromchild 108 self.threadPid=run.pid 109 foamLogger().info("Started with PID %d" % self.threadPid) 110 if self.isLinux: 111 # print "Starting Timer" 112 self.timer=Timer(0.1*self.timerTime,getLinuxMem,args=[self]) 113 self.timer.start() 114 115 self.hasSomethingToSay=True 116 self.stateLock.release() 117 118 try: 119 # print "Waiting",time() 120 self.status=run.wait() 121 # Python 2.3 on Mac OS X never seems to reach this point 122 # print "After wait",time() 123 # print "Status:",self.status 124 125 # to give a chance to read the remaining output 126 if self.hasSomethingToSay: 127 sleep(2.) 128 129 while self.reader.read(self.output): 130 print "Unused output:",self.reader.line 131 except OSError,e: 132 print "Exeption caught:",e 133 134 self.stopTimer() 135 136 self.threadPid=-1 137 138 self.resEnd=getrusage(self.who) 139 self.timeEnd=time()
140 # print "End:",self.timeEnd 141 # print "Returned",self.status 142
143 - def stopTimer(self):
144 if self.isLinux: 145 self.timer.cancel()
146
147 - def read(self):
148 """read another line from the output""" 149 self.setState(self.reader.read(self.output)) 150 self.lineLock.acquire() 151 self.line=self.reader.line 152 self.lineLock.release()
153
154 - def getLine(self):
155 """gets the last line from the output""" 156 self.lineLock.acquire() 157 val=self.line 158 self.lineLock.release() 159 160 return val
161
162 - def interrupt(self):
163 """A keyboard-interrupt is reported""" 164 self.reader.wasInterupted=True 165 self.setState(False)
166
167 - def setState(self,state):
168 """sets the state of the thread (is there any more output)""" 169 self.stateLock.acquire() 170 self.hasSomethingToSay=state 171 if not self.hasSomethingToSay and self.timeStart and self.reader.wasInterupted: 172 if self.threadPid>0: 173 msg="Killing PID %d" % self.threadPid 174 print msg 175 foamLogger().warning(msg) 176 kill(self.threadPid,signal.SIGKILL) 177 # print "Set: ",state 178 self.stateLock.release()
179
180 - def check(self):
181 """@return: False if there is no more output of the command""" 182 self.stateLock.acquire() 183 state=self.hasSomethingToSay 184 # print "Get: ",state 185 self.stateLock.release() 186 187 return state
188
189 - def cpuTime(self):
190 """@return: number of seconds CPU-Time used""" 191 return self.cpuUserTime()+self.cpuSystemTime()
192
193 - def cpuUserTime(self):
194 """@return: number of seconds CPU-Time used in user mode""" 195 if self.resEnd==None: # and self.isDarwin: 196 # Mac OS X needs this (Ubuntu too?) 197 self.resEnd=getrusage(self.who) 198 if self.resStart==None or self.resEnd==None: 199 return 0 200 else: 201 return self.resEnd.ru_utime-self.resStart.ru_utime
202
203 - def cpuSystemTime(self):
204 """@return: number of seconds CPU-Time used in system mode""" 205 if self.resEnd==None: # and self.isDarwin: 206 # Mac OS X needs this (Ubuntu too?) 207 self.resEnd=getrusage(self.who) 208 if self.resStart==None or self.resEnd==None: 209 return 0 210 else: 211 return self.resEnd.ru_stime-self.resStart.ru_stime
212
213 - def usedMemory(self):
214 """@return: maximum resident set size in MegaByte""" 215 scale=1024.*1024. 216 if self.isLinux: 217 return self.linuxMaxMem/scale 218 219 if self.resStart==None or self.resEnd==None: 220 return 0. 221 else: 222 return getpagesize()*(self.resEnd.ru_maxrss-self.resStart.ru_maxrss)/scale
223
224 - def wallTime(self):
225 """@return: the wall-clock-time needed by the process""" 226 if self.timeEnd==None: # and self.isDarwin: 227 # Mac OS X needs this (Ubuntu too?) 228 self.timeEnd=time() 229 230 self.timeEnd=time() 231 232 # print "Wall:",self.timeEnd,self.timeStart 233 if self.timeStart==None or self.timeEnd==None: 234 return 0 235 else: 236 return self.timeEnd-self.timeStart
237