00001 """
00002 capture and Filter output
00003 """
00004 import sys
00005 import time
00006 from slimpy_base.Environment.Singleton import Singleton
00007 from slimpy_base.Environment.InstanceManager import InstanceManager
00008 from atexit import register as __register__
00009 from pickle import dump
00010 import threading
00011 from sys import stdout
00012
00013 __copyright__ = """
00014 Copyright 2008 Sean Ross-Ross
00015 """
00016 __license__ = """
00017 This file is part of SLIMpy .
00018
00019 SLIMpy is free software: you can redistribute it and/or modify
00020 it under the terms of the GNU Lesser General Public License as published by
00021 the Free Software Foundation, either version 3 of the License, or
00022 (at your option) any later version.
00023
00024 SLIMpy is distributed in the hope that it will be useful,
00025 but WITHOUT ANY WARRANTY; without even the implied warranty of
00026 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00027 GNU Lesser General Public License for more details.
00028
00029 You should have received a copy of the GNU Lesser General Public License
00030 along with SLIMpy . If not, see <http://www.gnu.org/licenses/>.
00031 """
00032
00033
00034
00035 __env__ = InstanceManager()
00036
00037 def time_format( t ):
00038 if t/(60.*60.) > 1:
00039 tm = "%3.1f hrs" %(t/(60.*60.))
00040 elif t/(60.) > 1:
00041 tm = "%3.1f min" %(t/(60.))
00042 else:
00043 tm = "%3i sec" %(t)
00044
00045 return tm
00046
00047 class Records( Singleton ):
00048 """
00049 class to capture and filter output
00050 oprional dump to file an view with record_viewer scripts
00051 """
00052
00053
00054 def __new_instance__(self, name):
00055 Singleton.__new_instance__(self, name)
00056
00057 self._built_graph = None
00058 self.msg_record = []
00059 self.command_records = []
00060 self.trace_back_records = {}
00061
00062 self._filters = set( )
00063 self._filter_type = "any"
00064
00065 self._abridge = False
00066
00067 __register__( self.dump )
00068
00069 def __call__( self, verbose_level , *debug):
00070 """
00071 records( vlevel, *debug ) -> RecordHelper
00072 returns a RecordHelper instance
00073 vlevel is an integer
00074 debug are optional keywords
00075 """
00076 curthread = threading.currentThread()
00077
00078 node = curthread.getName()
00079 if hasattr(curthread, 'processor'):
00080 processor = getattr(curthread, 'processor')
00081 else:
00082 processor = 0
00083
00084
00085 rh = RecordHelper(verbose_level, (node,processor) , debug)
00086 return rh
00087
00088 def write(self,msg):
00089 """
00090
00091 """
00092 rc = self( 0 )
00093 rc.write(msg)
00094
00095 def _get_graph(self):
00096 return self._built_graph
00097
00098 def _set_graph(self,graph):
00099 self._built_graph = graph
00100
00101 graph = property( _get_graph, _set_graph )
00102
00103 def add_job(self,job_rec):
00104
00105 self.command_records.append(job_rec)
00106
00107 def rec(self,msg_record_item):
00108
00109 if not isinstance(msg_record_item, dict):
00110 raise TypeError('msg_record_item must be a dictionary')
00111
00112 assert msg_record_item.has_key('verb')
00113 assert msg_record_item.has_key('debug')
00114 assert msg_record_item.has_key('node')
00115 assert msg_record_item.has_key('msg')
00116
00117 self.print_record_item( msg_record_item )
00118 self.msg_record.append( msg_record_item )
00119 pass
00120
00121 def add_filter(self,filter):
00122
00123 self._filters.add( filter )
00124
00125
00126 def print_record_item( self, msg_record_item ):
00127 verb = __env__['slimvars']['verbose']
00128 debug = __env__['slimvars']['debug']
00129
00130 rdb = msg_record_item['debug']
00131 db = debug in rdb
00132 if isinstance(debug, (list,tuple) ):
00133 db = db or bool(set( rdb ).intersection(debug))
00134
00135 if db or verb >= msg_record_item['verb']:
00136 msg = msg_record_item['msg']
00137 msg = self.abridge(msg)
00138 print msg,
00139 stdout.flush( )
00140
00141 def dump(self):
00142
00143
00144 self._table_map = __env__['table']._map
00145 logfile = __env__['slimvars']['logfile']
00146
00147
00148 if logfile is not None:
00149
00150 f = open(logfile,'w')
00151 dump(self, f)
00152
00153 f.flush( )
00154 f.close( )
00155
00156 def End(self):
00157
00158 self.dump( )
00159
00160
00161 def _init_env(self):
00162
00163 __env__['table']._map = self._table_map
00164 __env__['table']._do_not_clean( )
00165
00166
00167 def set_filter_type( self, ftype ):
00168 self._filter_type = ftype
00169
00170 def generate_index_list(self):
00171
00172
00173 if self._filter_type == "all":
00174 index = range( len(self.msg_record) )
00175 index_set = set( index )
00176 cat = index_set.intersection_update
00177
00178 elif self._filter_type == "any":
00179 index_set = set( )
00180 cat = index_set.update
00181 else:
00182 raise Exception
00183
00184
00185 for filter in self._filters:
00186
00187 f_iset = filter.gen_index_set( self.msg_record )
00188
00189 cat( f_iset )
00190
00191
00192
00193 index = list( index_set )
00194 index.sort( )
00195
00196 return index
00197
00198
00199 def __getitem__(self,idx):
00200 msg = self.msg_record[idx]['msg']
00201 if self._abridge:
00202
00203 msg = self.abridge( msg )
00204 return msg
00205
00206 def print_log(self, abridge=False):
00207
00208 index = self.generate_index_list( )
00209
00210 for i in index:
00211 print self[i],
00212 stdout.flush()
00213 return
00214
00215
00216 def print_filter(self,verb=1,debug=None, node=None,abridge=False ):
00217
00218 verb_check = lambda item:(item['verb'] <= verb)
00219
00220 if debug:
00221 debug_set = set(debug)
00222
00223 def debug_check(item):
00224 if not debug:
00225 return False
00226 if not item['debug']:
00227 return False
00228 if debug_set.intersection( item['debug'] ):
00229 return True
00230 return False
00231
00232 def node_check(item):
00233 if not node:
00234 return True
00235 nn,pr = node
00236 nodename,proc = item['node']
00237
00238 ret = True
00239 if nn :
00240
00241 if nodename in nn:
00242 if pr:
00243 if proc in pr:
00244 return True
00245 else:
00246 return False
00247 else:
00248 return True
00249 else:
00250 return False
00251 else:
00252 return True
00253
00254
00255
00256 check = lambda item: verb_check(item) or debug_check(item)
00257
00258 filtered_list = [ item for item in self.msg_record if check(item) and node_check(item)]
00259
00260 for item in filtered_list:
00261 if abridge:
00262 print self.abridge(item['msg']),
00263 else:
00264 print item['msg'],
00265 stdout.flush()
00266 return
00267
00268 def print_filter_list(self):
00269
00270 filter_list = [ item['debug'] for item in self.msg_record ]
00271 filter_set = set()
00272 for item in filter_list:
00273 filter_set.update( item )
00274
00275 node_list = [ item['node'] for item in self.msg_record ]
00276 node_set = set()
00277 for item in node_list:
00278 node_set.add( item )
00279
00280 print "\nItems to allow by:\n"
00281 for item in filter_set:
00282 print " '%s'" % item
00283 print
00284
00285 print "Node to filter by:\n"
00286 for item in node_set:
00287 print " node:'%s', processor:'%s'" % item
00288 print
00289
00290 def set_abridge( self, abr ):
00291 self._abridge = abr
00292
00293
00294 def abridge( self, string ):
00295 """
00296 uses the global dict variable 'abridgeMap' in SLIMGlobals
00297 to replace all of the ocurrences of each key with the value
00298 this is helpful in reducing the amount of garbage input
00299 for examle in the simple1 tutorial I replace each $RSFROOT path with ''
00300
00301 """
00302 slimvars = __env__['slimvars']
00303
00304
00305
00306
00307
00308
00309
00310
00311 if slimvars['abridge']:
00312 for item in slimvars['abridgeMap'].items():
00313 string = string.replace( *item )
00314
00315 return string
00316
00317 def stat(self):
00318 if 'stat' in __env__['slimvars']['debug']:
00319 print
00320 graph = self._built_graph
00321 self._starttime = time.time( )
00322 self._tottime = 0
00323 self._numtorun = len([item for item in graph.getInvAdjacencyList().keys() if isinstance(item,tuple)])
00324 self._numran = 0
00325
00326 def stat_done(self):
00327 if 'stat' in __env__['slimvars']['debug']:
00328 print
00329 print "100% Done"
00330
00331 def stat_update(self,msg=None):
00332 if 'stat' in __env__['slimvars']['debug']:
00333 num = self._numtorun
00334 self._numran += 1
00335 i =self._numran
00336
00337 self._tottime = time.time() - self._starttime
00338 tot_time = self._tottime
00339 etime = tot_time/i*(num-i)
00340
00341 tot_time = time_format(tot_time)
00342 etime = time_format(etime)
00343
00344 perc = (float(i)/float(num))*100.
00345 eq = "="*int(perc/2)
00346 sp = " "*(50-int(perc/2))
00347
00348
00349
00350 print "|",eq+'>'+sp+'|', "%3i%%"%int(perc), "( %3i of %3i commands) total time %s || time remaining %s" %(i,num,tot_time,etime),
00351 print "\r",
00352 sys.stdout.flush( )
00353
00354
00355
00356
00357 class RecordHelper( object):
00358
00359 env = InstanceManager()
00360
00361 def __init__(self,verbose_level ,node, debug):
00362
00363 self.msg_record_item = { 'verb':verbose_level,
00364 'node':node,
00365 'debug':debug}
00366
00367 def write(self,msg):
00368
00369 msg_record_item = self.msg_record_item.copy()
00370 msg_record_item['msg'] = msg
00371
00372 self.env['record'].rec( msg_record_item )
00373
00374