[Fwd: ]

Krusty (chad@mfst.com)
Sun, 22 Dec 1996 16:00:07 -0800

Return-Path: chad
Received: (from chad@localhost) by krusty.MFSDatanet.COM (8.7.5/8.7.3) id QAA22077 for chad; Fri, 20 Dec 1996 16:37:25 -0800 (PST)
Date: Fri, 20 Dec 1996 16:37:25 -0800 (PST)
From: chad@MFST.com
Message-Id: <199612210037.QAA22077@krusty.MFSDatanet.COM>
To: chad

This is a scotty/tcl problem that I have:

BACKGROUND

The script that I have created performs asynchronous polling on a list
of nodes for a bunch of snmp data. It is intended to:

1) eliminate the need for running a seperate polling program for each
node
2) To allow polling requests to be sent out without having to wait for
the previous request's reply.

parameters for the script are:

the name of the MIB to be used
a filename of a file that contains a list of nodes to be polled
a filename of a file that contains a list of OIDs to be polled for each
node.
a filename of a file that contains a list of OID's and values to be used
to reset any counters.

The only method for performing asynchronous polling that I could come up
with was to perform a get with a callback. At the time that the get is
performed the ID for the request and what was asked for is stored in a
list. The callback returns the result and the request ID. Through
matching up what was asked for and what resulted the request can be
linked with the data. An 'snmp wait' is performed to ensure that all
results (good or bad) are returned before processing continues.

THE PROBLEM

The script works fine, however I have noticed that the performance
becomes very bad if more than 300 OID's are asked for (nodes x OID's).
I have varied all of the parameters that I could think of (i.e. lots of
nodes few OID's, few nodes many OID's)

I have tried various values for the window, number of nodes, number of
OID's, how many OID's asked for at a time and have always come up with
the limit of 300.

Exactly what happens is:

asking for 10 OID's takes x time to get and y time to sort
asking for 100 OID's takes 10x time to get and 10y time to sort
asking for 200 OID's takes 20x time to get and 20y time to sort
etc...etc..etc..
however
asking for 310 OID's takes 40x to get and 40y to sort
asking for 400 OID's takes 80x to get and 80y to sort.

A plot of the times vs OID's in all situations tried produces the same
result. The plot looks like a diode characteristic, or like a queueing
problem.

It appears to me that the script reaches some limitation in scotty or
TCL for the amount of events outstanding in the eventloop or the number
of requests that it can have outstanding.

The machine that I have this running on is a sparc 5 with 64MB ram (with
little else going on)

scotty 2.1.2 and tcl 7.5 are used.

Also I have noticed that if the window becomes too big many polls are
lost. I know that the window sets how many outstanding requests there
can be so I assume that the data is lost because more requests are sent
out than can be processed by the polled devices agent.

I have attached the code for any interested parties. Any comments,
suggestions or explanations would be appreciated.

Thanks

Chad Verbowski

--------------17B4233727C7
Content-Type: text/plain; charset=us-ascii; name="poller"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="poller"

#!/usr/local/bin/scotty
#########################################################
# poller Version: 0.0.1
# Created by: Chad Verbowski chad@mfst.com
#
################################################################
#
if {($argc < 2)} {
puts "Usage: poller <mibfile> <miblet> node \n";
exit
}

#################################################################
## This sets the variables from the command line
##
#
global miber;
mib load [lindex $argv 0];
set miblet [lindex $argv 1];
set node [lindex $argv 2];
set setfile 12;
catch {set setfile [lindex $argv 3];}
#######################################################################
# Procedure getCommunity
#
proc getCommunity {node} {

set comm public;
set info [open "community.data" r];
while {![eof $info]} {
gets $info thing;
if {[string first $node $thing] != -1
} {set comm [string range $thing [expr 1+[string first " " $thing]] [string length $thing]];
}
}
close $info;
return $comm;
}
#######################################################################
# Procedure makeNode
#
proc makeNode {node} {

set info [open $node r];
while {![eof $info]} {
gets $info thing;
if {[string length $thing] >2} {
lappend nlist $thing;
}
}
close $info;
return $nlist;
}
#######################################################################
#
#
#
proc clear_data {node} {

catch {set info [open $node r];}
while {![eof $info]} {
gets $info thing;
if {[string length $thing] >2} {
lappend nlist $thing;
}
}
close $info;
return $nlist;
}
#######################################################################
# Procedure makeMib
#
proc makeMib {mfile} {

global miber;
set info [open $mfile r];
while {![eof $info]} {
gets $info thing;
if {[string first :: $thing] != -1} {
set curlist [string range $thing 0 [expr [string first : $thing]-1]];
} elseif {[string length $thing] != 0} {lappend miber($curlist) $thing;}
}
close $info;
}
#########################################################################
proc chopup {info} {

if {[string first "Counter32" $info] != -1} {
set s [expr 10 +[string first Counter32 $info]];
set e [expr [string length $info] - 2 ];
set sho [string range $info $s $e];
return $sho;
} elseif {[string first "Unsigned32" $info] != -1} {
set s [expr 11 +[string first Unsigned32 $info]];
set e [expr [string length $info] - 2 ];
set sho [string range $info $s $e];
return $sho;
} elseif {[string first "INTEGER" $info] != -1} {
set s [expr 8 +[string first INTEGER $info]];
set e [expr [string length $info] - 2 ];
set sho [string range $info $s $e];
return $sho;
} elseif {[string first "STRING" $info] != -1} {
set s [expr 9 +[string first STRING $info]];
set e [expr [string length $info] - 3 ];
set sho [string range $info $s $e];
return $sho;
} elseif {[string first "TimeTick" $info] != -1} {
set s [expr [string last \{ $info]+ 1];
set e [expr [string first \} $info] - 1];
set sho [string range $info $s $e];
return $sho;
}

}
##############################################################################
#
#
#
proc clear { fname slist} {

puts stderr "Reseting the counters"
set rott [clear_data $fname];
foreach elt $rott {
set last [string range $elt 0 [expr [string first " " $elt] -1 ]];
lappend odd $last;
set dta($last) [string range $elt [expr [string first " " $elt] +1 ] [string length $elt]];
}
#______________________
foreach nde $slist {
foreach elmt $odd {
catch {$nde set [list [list $elmt $dta($elmt) ] ];}
}
}
}
###############################################################################
proc poll {thing } {

global miber slist cback rslt;

set nde [string range $thing 0 [expr [string first : $thing]-1]]
;
set slt [string range $thing [expr 1+[string first : $thing]] [expr [string first . $thing]-1]];
set port [string range $thing [expr 1+[string first . $thing]] [string length $thing]];
set rname [nslook $nde];
set hprt [string range $rname [expr 1+[string last . $rname]] [string length $rname]];
set nprt [string range $rname 0 [string last . $rname]] ;
set node "$nprt[expr $hprt + $slt]";

####
set commun [getCommunity $node ];
set s [snmp session -window 20 -address $node -community $commun -timeout 15];
lappend slist $s;
foreach key [array names miber] {
foreach elmt $miber($key) {
catch {set bb [$s get $elmt.$port {

lappend cback "%R::%V";}];lappend rslt "$bb::$thing--$elmt";
}
}
}
}
###########################################################################
#
#
proc newCorr { } {

global rinfo cback rslt;

#lsort $cback;
#lsort $rslt;
foreach thng $cback {
set mtch [string range $thng 0 [string first :: $thng]];
foreach prt $rslt {
if {[string first $mtch $prt] != -1 } {
set chnk [string range $prt [expr 2+ [string first :: $prt]] [string length $prt]];
set answ [string range $thng [expr 2+ [string first :: $thng]] [string length $thng]];
set rinfo($chnk) [chopup $answ];
# puts "$chnk - [chopup $answ]"
#puts "$n $k $e [chopup $out($n.$k.$e)]";
break;
}
}
}
}
#########################################################################
#
#
proc lineup {thing} {

global rinfo miber;

set slot [string range $thing [expr 1+[string first : $thing]] [expr [string first . $thing]-1]];
set port [string range $thing [expr 1+[string first . $thing]] [string length $thing]];

foreach key [array names miber] {
append lne "$key,$slot,$port";
foreach elt $miber($key) {
catch {append lne ",$rinfo($thing--$elt)";}
}
puts "$lne";
set lne "";
}
}
##################################################################################
proc endStamp {} {

global timeStop;

puts "3,$timeStop";
}
#################################################################################
#-----------------------------------------------------------------------------
# Return human readable datetime.
#
proc humanDt {} {
set f [open "|date" r]
gets $f dt
close $f
return $dt
}

#-----------------------------------------------------------------------------
proc headerStamp {host} {

global timeStart miber;

#####
set humt [humanDt];
set addr [nslook $host];
set s [snmp session -address $addr];
set utime [chopup [$s get sysUpTime.0]];
set utme [$s get sysUpTime.0];
set intname [chopup [$s get sysName.0]];
$s destroy;
puts "1,$humt,$utime,$host,$intname,$addr";
#####
foreach key [array names miber] {
append lne "$key$key";
foreach elt $miber($key) {
append lne ",$elt";
}
puts "$lne";
set lne "";
}
puts "3,$timeStart";
}
##################################################################################
#
proc printData {nodes } {

global rinfo miber;

set cnode "bart";
set start 1;

foreach nde $nodes {
set nnode [string range $nde 0 [expr [string first : $nde]-1]];
if {$nnode != $cnode} {
if {$start != 1} { endStamp;}
headerStamp $nnode;
set cnode $nnode;
set start 0;
}
lineup $nde;
}
endStamp;
}
#########################################################################3
#
makeMib $miblet;
set nodes [makeNode $node];
lsort $nodes;
set tt [time {foreach nde $nodes {
poll $nde;
}}];
set timeStart [string range $tt 0 [expr [string first m $tt] -2]];
set tt [time {snmp wait;}];
set timeStop [string range $tt 0 [expr [string first m $tt] -2]];
catch {clear $setfile $slist;}
foreach elt $slist {
$elt destroy ;
}
set t3 [time {newCorr;}]
set t4 [time {printData $nodes;}]
#########################################################################

--------------17B4233727C7--