Net2/usr/src/contrib/isode/others/quipu/tools/dsastats/dsastats.dist

#!/bin/sh
#
# next 3 lines configured by make dsastats
LOGFILE="QUIPULOG"
TAILORFILE="QUIPUTAILOR"
LOCALORG="QUIPULOCALORG"
ETCDIR="QUIPUETCDIR"

logfile=$LOGFILE
summary="FALSE"

while [ $# -gt 0 ]
do
	case $1 in
	-s|-summary)
		summary="TRUE"; shift;;
	*)
		logfile=$1; shift;;
	esac
done

if [ ! -r $logfile ]; then
	echo "No such file <$logfile>" >&2
	exit 1
fi

echo "$LOCALORG" |tr "A-Z" "a-z" >/tmp/dsastats$$.localorg

# try and sort out the format of the time into something a bit nicer
nicetime () {
awk ' BEGIN {
	montharray[1] = "Jan"
	montharray[2] = "Feb"
	montharray[3] = "Mar"
	montharray[4] = "Apr"
	montharray[5] = "May"
	montharray[6] = "Jun"
	montharray[7] = "Jul"
	montharray[8] = "Aug"
	montharray[9] = "Sep"
	montharray[10] = "Oct"
	montharray[11] = "Nov"
	montharray[12] = "Dec"
}
	{	
		monthno = substr($0, 1, 2) + 0
		dayno = substr($0, 4, 2)
		time = substr($0, 7, 8)
		printf("%s on %02d %s", time, dayno, montharray[monthno])
	} '
}

echo $logfile | grep -s ".usage"
if [ "$?" = "0" ]; then
	dsaname=`basename $logfile .usage`
else
	dsaname=` grep mydsa $TAILORFILE | \
	awk -F@ '{split($NF,parts, "=") 
			  print parts[2] }' |sed 's/"//g'`
fi
starttime=`head -1 $logfile | nicetime`
endtime=`tail -1 $logfile | nicetime`
echo "fordsa $dsaname" >/tmp/dsastats$$.2
echo "starts $starttime" >>/tmp/dsastats$$.2
echo "ends   $endtime" >>/tmp/dsastats$$.2

sed 's/[^)]*)  //' < $logfile | awk ' BEGIN {
	gotfirst = "FALSE"
}
/^(Add|Read|List|Modify|Modifyrdn|Remove|Search|Compare|Getedb) \(.*/	{
	split ($2,opids,":")
	lastassoc = opids[1]
}

{
	if (gotfirst == "TRUE")
	{
		split($0, op, ":")
		if (op[1] != "DSA control")
		{
			print saveline
			saveline = $0
		}
		else
			saveline = "DSAControl " lastassoc ": " $(NF-1) " " $(NF)
	}
	else
	{
		gotfirst = "TRUE"
		saveline = $0
	}
}
END {
	print saveline
} ' >/tmp/dsastats$$.1
cat $ETCDIR/quipulocaladds /tmp/dsastats$$.1 | awk '
BEGIN {
	nextdsa = 1;
	lastcn=0
	conns_open["dummy"] = ""
	locadd["dummy"] = 0
        while (getline > 0)
        {
		if (substr($0, 1, 1) == "#")
			break
                no_localadds++
                locadd[no_localadds] = $0
        }
}

/^Bind.*/	{
	conn_op[$2] = 1
	conn [$2 "#" 1] = conn[$2 "#" 1] " " $0
	conns_open[$2] = $2
}
/^(Add|Read|List|Modify|Modifyrdn|Remove|Search|Compare|Getedb|DSAControl) \(.*/	{
	split ($2,opids,":")
	opid = opids[1]
	conn_op[opid]++
	split ($0,oper,":")
	if (oper[2] == " ") 
		conn [opid "#" conn_op[opid]] = $1 " ROOT"
	else
		conn [opid "#" conn_op[opid]] = $1 oper[2]
	lastcn = opid
}
/^Unbind.*/	{
	if (conn[$2 "#" 0] == "") 
	{
		print conn[$2 "#" 1]
		if (chain[$2] == 1)
			print "\tChained " chain[$2] " operation"
		else
			print "\tChained " chain[$2] " operations"
	} 
	else 
	{
		print conntype[$2] " " conn[$2 "#" 1]
		for ( i=2; i<= conn_op[$2]; i++) 
			print "  " conn[$2 "#" i]
	}
	print ""
	conn_op[$2] = 0
	conns_open[$2] = ""
}

/ has started / {
	for (j in conns_open)
	{
		if (conns_open[j] != "")
		{
			if (conn[j "#" 0] == "") 
			{
				print conn[j "#" 1]
				if (chain[j] == 1)
					print "\tChained " chain[j] " operation"
				else
					print "\tChained " chain[j] " operations"
			} 
			else 
			{
				print conntype[j] " " conn[j "#" 1]
				for (i = 2; i <= conn_op[j]; i++)
					print "  " conn[j "#" i]
			}
			print ""
			conn_op[j] = 0
			conns_open[j] = ""
		}
	}
}

/^X500 DAP.*/	{
	split ($5,opids,":")
	opid = opids[1]
	conn_op[opid] = 0
	split ($0,oper,":")
	conn [opid "#" 0] = "from" oper[2]
	conn [opid "#" 1] = "DAP"
	conntype [opid] = "remote"
	y = index($0, ":")
	thisadd = substr($0, y+1)
	for (z =1 ; z <= no_localadds; z++)
		if (substr(thisadd, 2, length(locadd[z])) == locadd[z])
		{
			conntype [opid] = "local"
			break
		}
}
/^QUIPU DSP.*/	{
	split ($5,opids,":")
	opid = opids[1]
	conn_op[opid] = 0
	split ($0,oper,":")
	conn [opid "#" 0] = "Quipu DSP from" oper[2]
	conn [opid "#" 1] = "QuipuDSP"
	conntype [opid] = "remote"
	y = index($0, ":")
	thisadd = substr($0, y+1)
	for (z =1 ; z <= no_localadds; z++)
		if (substr(thisadd, 2, length(locadd[z])) == locadd[z])
		{
			conntype [opid] = "local"
			break
		}
}
/^X500 DSP.*/	{
	split ($5,opids,":")
	opid = opids[1]
	conn_op[opid] = 0
	split ($0,oper,":")
	conn [opid "#" 0] = "from" oper[2]
	conn [opid "#" 1] = "DSP"
	conntype [opid] = "remote"
	y = index($0, ":")
	thisadd = substr($0, y+1)
	for (z =1 ; z <= no_localadds; z++)
		if (substr(thisadd, 2, length(locadd[z])) == locadd[z])
		{
			conntype [opid] = "local"
			break
		}
}
/^DAP Originator.*/ {
	split ($0,dn,":")
	if (dn[2] != " ")
		conn [lastcn "#" conn_op[lastcn]] = conn [lastcn "#" conn_op[lastcn]] "\n\tDAP Originator: " dn[2]
	else
		conn [lastcn "#" conn_op[lastcn]] = conn [lastcn "#" conn_op[lastcn]] "\n\tDAP Originator:  anonymous"
}
/^Bound.*/ {
	split ($6,opids,":")
	opid = opids[1]
	conn[opid "#" 0] = ""
	conn[opid "#" 1] = $0
	conn_op[opid] = 1
}
/^Chain.*/ 	{
	chain[opid]++
}
/^Trying.*/	{
	split ($0,dn,":")
	if (dsa[dn[2]] == 0) 
	{
		dsa[dn[2]] = nextdsa
		dsadn[nextdsa]=dn[2]
		try[nextdsa]++
		nextdsa++
	} 
	else
		try[dsa[dn[2]]]++
}
/^Failed.*/	{
	split ($0,dn,":")
	fail[dsa[dn[2]]]++
}
END {
	print "Connections: " 
	for (i=1; i< nextdsa; i++) 
	{
		printf "  %-30s: tried %s", dsadn[i], try[i]
		if (fail[i] != 0)
			print ", failed " fail[i]
		else 
			print
	}
} ' >> /tmp/dsastats$$.2

cat /tmp/dsastats$$.localorg $ETCDIR/quiputechusers /tmp/dsastats$$.2 |tr "A-Z" "a-z" | awk '
BEGIN {
	techies["dummy"] = 0
	getline
	localorg = $0
        while (getline > 0)
        {
		if (substr($0, 1, 1) == "#")
			break
                no_techs++
                techies[$0] = 0
        }
	gotdspbind = "FALSE"
	userorgnames["dummy"] = 0
	originators["dummy"] = 0
	realaccessed["dummy"] = 0
	sysaccessed["dummy"] = 0
	summary = "'$summary'"
}
/^fordsa/ {
	dsaname = substr($0, 8, length($0)-8+1)
}

/^starts/ {
	starttime = substr($0, 8, 40)
}

/^ends/ {
	endtime = substr($0, 8, 40)
}

# add any originators from last DSP connection examined to usernames array
/ bind/ {
	if (gotdspbind == "TRUE")
		for (origuser in originators)
			if (originators[origuser] != 0)
			{
				usernames[origuser]++
				if (origuser == "anonymous")
					if (remote == "TRUE")
						remoteanon++
					else
						localanon++
				originators[origuser] = 0
			}
	if (substr($0, 1, 6) == "remote")
		remote = "TRUE"
	else
		remote = "FALSE"
}

/.* bind.*\(anonymous\).*/	{
	if (substr($0, 1, 6) == "remote")
		remoteanon++
	else
		localanon++
	if ($2 == "dap")
		gotdspbind = "FALSE"
	else
		gotdspbind = "TRUE"
	usernames["anonymous"]++
}

/.* bind.*\(no auth\).*/ {
	if (substr($0, 1, 6) == "remote")
		if ($2 == "dap")
			remotenoauthdap++
		else
			remotenoauthdsp++
	else
		if ($2 == "dap")
			localnoauthdap++
		else
			localnoauthdsp++
}

/.* bind.*\(simple\).*/ {
	if (substr($0, 1, 6) == "remote")
		remotesimple++
	else
		localsimple++
}

/ bind.*\(no auth\)| bind.*\(simple\)/ {
	n = index($0, ":")
	username = substr($0, n+2)
	if ($2 == "dap")
	{
		gotdspbind = "FALSE"
		usernames[username]++
	}
	else
		gotdspbind = "TRUE"
}

#/dap originator:/ {
#	n = index($0, ":")
#	username = substr($0, n+3)
#	if (username != "anonymous")
#		originators[username]++
#}

/^  getedb/ {
	getedb++
}

/^  modifyrdn / {
	modifyrdnops++
	opDN = substr($0, 13)
}

/^  add/ {
	addops++
	opDN = substr($0, 7)
}

/^  modify / {
	modifyops++
	opDN = substr($0, 10)
}

/^  search/ {
	searchops++
	opDN = substr($0, 10)
}

/^  list/ {
	listops++
	opDN = substr($0, 8)
}

/^  read/ {
	readops++
	opDN = substr($0, 8)
}

/^  read|^  list|^  search|^  modify|^  add/ {
	n = split(opDN, RDNparts, "@")
	if (substr(RDNparts[n], 1, 2) == "cn")
		if (($1 == "read") && (n < 3)) #reading a DSA entry
		{
			dsaread++
			next
		}
		else
		{
			opDN = RDNparts[1]
			for (i = 2; i < n-1; i++)
				opDN = opDN "@" RDNparts[i]
		}
	# was this a system or real use?
	if (gotdspbind == "TRUE")
	{
		# get the originator
		getline
		n = index($0, ":")
		origname = substr($0, n+3)
		if (origname == username)
		{
			spotshadows++
			next
		}
		else
			originators[origname]++
	}
	else
		origname = username
	techfound = "false"
	for (techperson in techies)
		if (techperson == origname)
			{
				techfound = "true"			
				break
			}
	if (techfound == "true")
		sysaccessed[opDN]++
	else
		realaccessed[opDN]++
}

END {
# pick up any last dsp originators
	if (gotdspbind == "TRUE")
		for (origuser in originators)
			if (originators[origuser] != 0)
			{
				usernames[origuser]++
				if (origuser == "anonymous")
					if (remote == "TRUE")
						remoteanon++
					else
						localanon++
				originators[origuser] = 0
			}

	printf "Summary of calls to DSA <%s>\nFrom %s to %s\n\n", dsaname, \
		starttime, endtime
	printf "%-30s%8s%8s\n\n", "No. of binds", "local", "remote"
	printf "%-20s%10s%8d%8d\n", "Anonymous", "", localanon, remoteanon
	printf "%-20s%10s%8d%8d\n", "Unauth name DAP", "", localnoauthdap, remotenoauthdap
	printf "%-20s%10s%8d%8d\n", "Unauth name DSP", "",localnoauthdsp, remotenoauthdsp
	printf "%-20s%10s%8d%8d\n", "Simple", "", localsimple, remotesimple

#print "have this list of users"
#for (user in usernames)
#	print user "   " usernames[user]
#print ""

	for (user in usernames)
	{
		techfound = "false"
		for (techperson in techies)
			if (techperson == user)
			{
				techfound = "true"			
				break
			}
		if (techfound == "true")
			techbinds += usernames[user]
		else
		{
			n = split(user, RDNparts, "@")
			if (n == 1)
				userorg = user
			else
				userorg =  RDNparts[1] ", " RDNparts[2]
			orgfound = "false"
			for (org in userorgnames)
				if (org == userorg)
				{
					orgfound = "true"
					break
				}
			if (orgfound == "false")
				nontech++
			userorgnames[userorg]++
			userorgbinds[userorg] += usernames[user]
		}
	}

	printf "\nSystem usage (calls received)\n\n"
	printf "%-38s%8d\n", "Binds by Directory technicians", techbinds
	printf "%-38s%8d\n", "Reads of DSA entries", dsaread
	printf "%-38s%8d\n", "Getedb operations", getedb
	printf "%-38s%8d\n", "Spot shadows", spotshadows

	printf "\nWho has used the directory?\n"
	printf "*Real* usage by organisation\n"
	printf "%9s%10s\n", "No. users", "No. binds"
	for (name in userorgnames)
		if (userorgnames[name] != 0)
			printf "%9d%10d    %s\n", userorgnames[name], userorgbinds[name], name

	printf "\nWhich parts of the Directory have been accessed - real usage?\n"
	printf "%s  %s\n", "No. ops", "Subtree"
	printf "Local subtree\n"
	if (realaccessed[localorg] != 0)
	{
		printf "%7d  %s\n", realaccessed[localorg], localorg
		realaccessed[localorg] = 0
	}
	n = 0
	for (dn in realaccessed)
		if ((realaccessed[dn] != 0) && \
			(substr(dn, 1, length(localorg)) == localorg))
		{
			n++
			sortarray[n] = dn
		}
	m = n
	for (i = 1; i<n-1; i++)
	{
		change = "FALSE"
		for (j=1; j <m; j++)
			if (sortarray[j+1] < sortarray[j])
			{
				tmp = sortarray[j]
				sortarray[j] = sortarray[j+1]
				sortarray[j+1] = tmp
				change = "TRUE"
			}
		if (change == "FALSE")
			break
		m--
	}
	for (i = 1; i <= n; i++)
	{
		printf "%7d  %s\n", realaccessed[sortarray[i]], sortarray[i]
		realaccessed[sortarray[i]] = 0
	}
		
	printf "\nOther parts of the DIT\n"
	for (dn in realaccessed)
		if (realaccessed[dn] != 0)
		{
			n = split(dn, RDNparts, "@")
			if (substr(RDNparts[1], 1, 2) == "c=")
				if (n == 1)
					otherditaccess[dn] += realaccessed[dn]
				else if (substr(RDNparts[2], 1, 2) == "o=")
					otherditaccess[RDNparts[1] "@" RDNparts[2]] += realaccessed[dn]
		}

	printf "%7d  %s\n", otherditaccess["root"], "root"
	otherditaccess["root"] = 0
	n = 0
	for (dn in otherditaccess)
		if (otherditaccess[dn] != 0)
		{
			n++
			sortarray[n] = dn
		}
	m = n
	for (i = 1; i<n-1; i++)
	{
		change = "FALSE"
		for (j=1; j <m; j++)
			if (sortarray[j+1] < sortarray[j])
			{
				tmp = sortarray[j]
				sortarray[j] = sortarray[j+1]
				sortarray[j+1] = tmp
				change = "TRUE"
			}
		if (change == "FALSE")
			break
		m--
	}
	for (i = 1; i <= n; i++)
	{
		printf "%7d  %s\n", otherditaccess[sortarray[i]], sortarray[i]
		otherditaccess[sortarray[i]] = 0
	}

	printf "\n\nWhich parts of the Directory have been accessed - system usage?\n"
	printf "%s  %s\n", "No. ops", "Subtree"
	printf "Local subtree\n"
	if (sysaccessed[localorg] != 0)
	{
		printf "%7d  %s\n", sysaccessed[localorg], localorg
		sysaccessed[localorg] = 0
	}
	n = 0
	for (dn in sysaccessed)
		if ((sysaccessed[dn] != 0) && \
			(substr(dn, 1, length(localorg)) == localorg))
		{
			n++
			sortarray[n] = dn
		}
	m = n
	for (i = 1; i<n-1; i++)
	{
		change = "FALSE"
		for (j=1; j <m; j++)
			if (sortarray[j+1] < sortarray[j])
			{
				tmp = sortarray[j]
				sortarray[j] = sortarray[j+1]
				sortarray[j+1] = tmp
				change = "TRUE"
			}
		if (change == "FALSE")
			break
		m--
	}
	for (i = 1; i <= n; i++)
	{
		printf "%7d  %s\n", sysaccessed[sortarray[i]], sortarray[i]
		sysaccessed[sortarray[i]] = 0
	}
		
	printf "\nOther parts of the DIT\n"
	for (dn in sysaccessed)
		if (sysaccessed[dn] != 0)
		{
			n = split(dn, RDNparts, "@")
			if (n == 1)
				otherditaccess[dn] += sysaccessed[dn]
			else
				otherditaccess[RDNparts[1] "@" RDNparts[2]] += sysaccessed[dn]
		}

	if (otherditaccess["root"] != 0)
	{
		printf "%7d  %s\n", otherditaccess["root"], "root"
		otherditaccess["root"] = 0
	}
	n = 0
	for (dn in otherditaccess)
		if (otherditaccess[dn] != 0)
		{
			n++
			sortarray[n] = dn
		}
	m = n
	for (i = 1; i<n-1; i++)
	{
		change = "FALSE"
		for (j=1; j <m; j++)
			if (sortarray[j+1] < sortarray[j])
			{
				tmp = sortarray[j]
				sortarray[j] = sortarray[j+1]
				sortarray[j+1] = tmp
				change = "TRUE"
			}
		if (change == "FALSE")
			break
		m--
	}
	for (i = 1; i <= n; i++)
	{
		printf "%7d  %s\n", otherditaccess[sortarray[i]], sortarray[i]
		otherditaccess[sortarray[i]] = 0
	}
} ' 

rm -f /tmp/dsastats$$.1 /tmp/dsastats$$.2 /tmp/dsastats$$.localorg