1#! /bin/sh
2#	$Id$
3#
4# Display environment's deadlocks based on "db_stat -Co" output.
5
6t1=__a
7t2=__b
8
9trap 'rm -f $t1 $t2; exit 0' 0 1 2 3 13 15
10
11if [ $# -ne 1 ]; then
12	echo "Usage: dd.sh [db_stat -Co output]"
13	exit 1
14fi
15
16if `egrep '\<WAIT\>.*\<page\>' $1 > /dev/null`; then
17	n=`egrep '\<WAIT\>.*\<page\>' $1 | wc -l | awk '{print $1}'`
18	echo "dd.sh: $1: $n page locks in a WAIT state."
19else
20	echo "dd.sh: $1: No page locks in a WAIT state found."
21	exit 1
22fi
23
24# Print out list of node wait states, and output cycles in the graph.
25egrep '\<WAIT\>.*\<page\>' $1 | awk '{print $1 " " $5 " " $7}' |
26while read l f p; do
27	for i in `egrep "\<HELD\>.*\<$f\>.*\<page\>.*\<$p\>" $1 |
28	    awk '{print $1}'`; do
29		echo "$l $i"
30	done
31done | tsort > /dev/null 2>$t1
32
33# Display the locks in a single cycle.
34c=1
35display_one() {
36	if [ -s $1 ]; then
37		echo "Deadlock #$c ============"
38		c=`expr $c + 1`
39		cat $1 | sort -n +6
40		:> $1
41	fi
42}
43
44# Display the locks in all of the cycles.
45#
46# Requires tsort output some text before each list of nodes in the cycle,
47# and the actual node displayed on the line be the second (white-space)
48# separated item on the line.  For example:
49#
50#	tsort: cycle in data
51#	tsort: 8000177f
52#	tsort: 80001792
53#	tsort: 80001774
54#	tsort: cycle in data
55#	tsort: 80001776
56#	tsort: 80001793
57#	tsort: cycle in data
58#	tsort: 8000176a
59#	tsort: 8000178a
60#
61# XXX
62# Currently, db_stat doesn't display the implicit wait relationship between
63# parent and child transactions, where the parent won't release a lock until
64# the child commits/aborts.  This means the deadlock where parent holds a
65# lock, thread A waits on parent, child waits on thread A won't be shown.
66if [ -s $t1 ]; then
67	:>$t2
68	while read a b; do
69		case $b in
70		[0-9]*)
71			egrep $b $1 >> $t2;;
72		*)
73			display_one $t2;;
74		esac
75	done < $t1
76	display_one $t2
77else
78	echo 'No deadlocks found.'
79fi
80
81exit 0
82