#!/usr/bin/env python import os, sys, getopt, re __revision__ = "$Id: hanganalyze.py,v 1.1.1.2 2007/09/05 10:36:17 egor_starostin Exp $" __version__ = __revision__.split()[2] def displayHelp(msg): if msg: print >>sys.stderr, msg print >>sys.stderr, "hanganalyze.py v%s, (c) 2005,2007 Egor Starostin" % __version__ print >>sys.stderr, "usage: hanganalyze.py [-f tracefile.trc] [-h] [-k]" print >>sys.stderr, " -f specify tracefile to parse" print >>sys.stderr, " -h this screen" print >>sys.stderr, " -k keep trace file in {user_dump_dest} directory" def makeTrcFile(): prfx = "__hanganalyze%s" % os.getpid() cmdfile = open("%s.sql" % prfx,"w") cmdfile.write("""set head off set feedb off set trims on spool %s connect / as sysdba exec dbms_application_info.set_client_info('hanganalyze.py'); alter session set tracefile_identifier='hanganalyze'; alter session set events 'immediate trace name hanganalyze level 2'; select * from ( select par.value||','||p.spid from v$parameter par, v$process p, v$session s where p.addr=s.paddr and par.name='user_dump_dest' and client_info='hanganalyze.py' order by last_call_et) where rownum < 2; exit / """ % prfx) cmdfile.close() if sys.platform == 'win32': os.system("sqlplus -s /nolog @%s.sql >nul" % prfx) else: os.system("sqlplus -s /nolog @%s.sql >/dev/null" % prfx) sout = open("%s.lst" % prfx).readlines() os.unlink("%s.sql" % prfx) os.unlink("%s.lst" % prfx) (udd,spid) = sout[-1].split(',') trctail = "%s_hanganalyze.trc" % spid.rstrip("\n") tlen = len(trctail) files = filter(lambda x: x[-tlen:].lower() == trctail.lower(),os.listdir(udd)) return ("%s/%s" % (udd,files[0])) def uniqlist(l): h = {}; for e in l: h[e] = 1 return h.keys() def parseTrcFile(f): stnodespat = re.compile("^State of nodes") instnodes = False inhang = {} sid = {} parent = {} child = {} for l in open(f): l = l.rstrip("\n") if stnodespat.search(l): instnodes = True continue if instnodes: if l[:10] == '==========': instnodes = False elif l[0] == '(': l = l[1:] # remove ( l = l[:-2] # remove ): fnames = l.split('/') sidi = fnames.index('sid') seriali = fnames.index('sess_srno') statei = fnames.index('state') elif l[0] == '[': items = l.split('/') nodenum = items[0][1:-1] # remove '[' and ']' sid[nodenum] = "[%s, %s]" % (items[sidi],items[seriali]) predecessor = items[fnames.index('predecessor')] adjlist = items[fnames.index('[adjlist]')] adjlist = [e[1:] for e in adjlist.split(']')[:-1]] # [1][2] => [1,2] if items[statei] == 'IN_HANG': inhang[nodenum] = adjlist else: # predecessor if predecessor != 'none': if not child.has_key(nodenum): child[nodenum] = [] if not parent.has_key(predecessor): parent[predecessor] = [] child[nodenum].append(predecessor) parent[predecessor].append(nodenum) # adjlist if adjlist and not parent.has_key(nodenum): parent[nodenum] = [] for e in adjlist: if not child.has_key(e): child[e] = [] if not parent.has_key(e): parent[e] = [] child[e].append(nodenum) parent[nodenum].append(e) else: pass # just ignore unknown lines (like 'Dumping Proces information ...') for k in parent.keys(): parent[k] = uniqlist(parent[k]) for k in child.keys(): child[k] = uniqlist(child[k]) print "Results for trace file %s:\n" % f return (inhang,sid,parent,child) def printTree(k,lvl): for el in child[k]: print '%s%s' % (' '*(lvl),sid[el]) if child.has_key(el): printTree(el,lvl+1) # # begin # if __name__ == '__main__': inhang = {} sid = {} parent = {} child = {} keepFile = False try: opts, args = getopt.getopt(sys.argv[1:],'hf:k',['help','file=','keep']) except getopt.error, msg: displayHelp(msg) sys.exit(1) trcFile = '' for opt,val in opts: if opt in ('-h','--help'): displayHelp(''); sys.exit(0) if opt in ('-k','--keep'): keepFile = True if opt in ('-f','--file'): trcFile = val; keepFile = True # don't remove file when we explicitly specify it if not trcFile: trcFile = makeTrcFile() (inhang,sid,parent,child) = parseTrcFile(trcFile) if not keepFile: os.unlink(trcFile) # deadlocks if inhang: print "-- DEADLOCK(S) [sid, serial#]\n" for e in inhang: print sid[e],'<->', for x in inhang[e]: print sid[x], print "" print "\n" else: print "-- NO DEADLOCKS\n" # locks if parent: lvl = 0 print "-- LOCK TREES [sid, serial#]\n" for k in [e for e in parent.keys() if parent[e] == []]: print '%s%s' % (' '*lvl,sid[k]) printTree(k,lvl+1) print "" else: print "-- NO LOCKS\n"