diff options
-rw-r--r-- | src/Agent.pm | 64 | ||||
-rw-r--r-- | src/IvyIO.pm | 53 | ||||
-rwxr-xr-x | src/ivycontrolpanel | 85 |
3 files changed, 161 insertions, 41 deletions
diff --git a/src/Agent.pm b/src/Agent.pm index 4a38434..3c0b835 100644 --- a/src/Agent.pm +++ b/src/Agent.pm @@ -13,19 +13,21 @@ use strict; # #---------------------------------------------------------------------- my ($x0, $y0, $wmax, $dx, $dy, $cmin, $rmax, @matrix, @hosts, $tempo_id, - $mw, $bg, $fg, $selcolor, $hlbg, $darkbg, $fontspec, @fontspec, - $on_img, $off_img, %instances, @instances, $bus, $coef, - $hosts_tl, $selected_host, $preselected_host); + $mw, $bg, $fg, $selcolor, $pbcolor, $hlbg, $darkbg, $fontspec, @fontspec, + $on_img, $off_img, $pb_img, %instances, @instances, $bus, $coef, + $hosts_tl, $selected_host, $preselected_host, $pingThreshold); # configure the class : graphic parameters, geometry and ivy bus sub configure { shift; - ($mw, $bg, $fg, $selcolor, $hlbg, $darkbg, - $fontspec, $x0, $y0, $wmax, $dy, $cmin, $rmax, $bus, $coef) = @_; + ($mw, $bg, $fg, $selcolor, $pbcolor, $hlbg, $darkbg, + $fontspec, $x0, $y0, $wmax, $dy, $cmin, $rmax, $bus, $coef, $pingThreshold) = @_; @fontspec = @$fontspec if $fontspec; $off_img = $mw->Bitmap('off', -file => Tk::findINC('led.bmp'), -foreground => $bg); + $pb_img = $mw->Bitmap('pb', -file => Tk::findINC('led.bmp'), + -foreground => $pbcolor); $on_img = $mw->Bitmap('on', -file => Tk::findINC('led.bmp'), -foreground => $selcolor); &_resetmatrix; @@ -93,6 +95,21 @@ sub disconnect { } # end disconnect +# callback called when a ping/pong is received +sub pingcb { + my ($class, $appname, $host, $pingtime) = @_; + #print "pingtime=$pingtime\n"; + if ($instances{$appname}) { + # if pingtime > $pingThreshold status is changed + if ($pingtime > $pingThreshold) { + $instances{$appname}->pb; + } else { + # print "Stat:".$instances{$appname}->{status}."\n"; + if ($instances{$appname}->{status} == 2) { $instances{$appname}->nopb;} + } + } +} # end pingcb + # class constructor sub new { my ($class, $appname, $host, $command, $params, $status) = @_; @@ -122,7 +139,7 @@ sub new { $instances{$appname} = $self; push(@instances, $self); - # graphical updates + # graphical updates $self->createlabel; $self->on if $status; @@ -160,12 +177,11 @@ sub removetwin { # graphical effect when a known agent connects sub on { my $self = shift; - $self->{status} = 1; - $self->{led}->configure(-image => $on_img); + $self->nopb; $self->{label}->raise; $self->{label}->configure(-highlightthicknes => 2); - $tempo_id = $mw->after(3000, sub { - $self->{label}->configure(highlightthicknes => 0); + $tempo_id = $mw->after(2000, sub { + $self->{label}->configure(-highlightthicknes => 0); }); } # end on @@ -179,6 +195,34 @@ sub off { } # end off +# graphical effect when a know agent has a ping problem (latency) + +sub pb { + my $self = shift; + $self->{status} = 2; + $self->{led}->configure(-image => $pb_img); + my $i = 0; + my $id; + $id = $mw->repeat(100, sub { + if ($i == 4) { + $mw->afterCancel($id); + } elsif ($i % 2 == 0) { + $self->{led}->configure(-image => $on_img); + } else { + $self->{led}->configure(-image => $pb_img); + } + $i++; + }); + +} # end pb + +sub nopb { + my $self = shift; + $self->{status} = 1; + $self->{led}->configure(-image => $on_img); + +} # end pb + # label placement sub setposition { my $self = shift; diff --git a/src/IvyIO.pm b/src/IvyIO.pm index f39d96b..cc9aa8d 100644 --- a/src/IvyIO.pm +++ b/src/IvyIO.pm @@ -2,19 +2,28 @@ package IvyIO; use strict; use Ivy; +use Carp; +use Tk; my $ivy; +my %appNameByhostAndPort = (); +my %diedApp = (); +my $pingcallback; # init an ivy bus sub init { - my ($appname, $bus, $conncb, $disconncb) = @_; + my ($appname, $bus, $conncb, $disconncb, $pingcb, $mw) = @_; Ivy->init(-loopMode => 'TK', -appName => $appname, -ivyBus => $bus, ); + + $pingcallback = $pingcb; + $ivy = Ivy->new(-statusFunc => sub {&_status($conncb, $disconncb, @_);}); $ivy->start; + $mw->repeat (3000 ,[\&sendPings]) if defined $pingcb; } # end init @@ -27,13 +36,17 @@ sub kill { sub _status { - my ($conncb, $disconncb, $ref_array_present, $ref_array_absent, - $ref_hash_present, $agent, $status, $host) = @_; - if ($status eq "new") { - &$conncb($agent, $host); - } elsif ($status eq "died") { - &$disconncb($agent, $host); - } + my ($conncb, $disconncb, $ref_array_present, $ref_array_absent, + $ref_hash_present, $agent, $status, $host) = @_; + #print "Status : @_\n"; + if ($status eq "new") { + &$conncb($agent, $host); + $appNameByhostAndPort{$host} = $agent; + delete $diedApp{$host}; + } elsif ($status eq "died") { + &$disconncb($agent, $host); + $diedApp{$host} = 1; + } } # end _status @@ -110,6 +123,7 @@ sub bind_for_clock_and_rate_event { } # end bind_for_clock_event + # execute the callback kill all sub bind_for_kill_all { my $cb = shift; @@ -121,4 +135,27 @@ sub bind_for_kill_all { } # end bind_for_clock_event +# send a ping to agent(s) +sub sendPings () +{ + my $appf; + foreach $appf (keys (%appNameByhostAndPort)) { + next if exists $diedApp{$appf}; + $ivy->ping ($appf, \&receivePongCb); + } +} # end sendPings + + +# received pong, Agent is notified with the ping/pong time value +sub receivePongCb($$) +{ + my ($time, $appf) = @_; # time = ping/pong duration in ms + + $received ++; + #printf ("DBG> :$received: $appf [$time]".$appNameByhostAndPort{$appf}."\n"); + &$pingcallback($appNameByhostAndPort{$appf}, $appf, $time); + +} # end receivePongCb + + 1; diff --git a/src/ivycontrolpanel b/src/ivycontrolpanel index 887d50c..6848628 100755 --- a/src/ivycontrolpanel +++ b/src/ivycontrolpanel @@ -9,10 +9,12 @@ use strict; use Carp; + # where you may find bitmap files use lib "/usr/share/ivycontrolpanel"; # where you may find the IvyIO and Agent modules -use lib "/usr/lib/ivycontrolpanel"; +#use lib "/usr/lib/ivycontrolpanel"; +use lib "."; # where you may find the FugueConfig module use lib "/usr/lib/ivylaunch"; @@ -61,6 +63,8 @@ my $bg = '#5C5655'; my $hlbg = '#7CC452'; my $fg = '#FCFAFC'; my $selcolor = 'yellow'; +my $pbcolor = '#c9b900000000'; +my $pingThreshold = 20; # traffic rate spec my @rate = (-20..-1, -0.5, 0, 0.5, 1..20); @@ -79,6 +83,17 @@ my $settingtime; my $selectedtimelabel; my $ivylaunch_agent; +# ivy version +my $ivy_version = $Ivy::VERSION; +my $ivy_versionstring = "v$ivy_version"; +my $ivy_cvsrevision = 0; +if ($ivy_version =~ s/Revision: (.*)//) { + $ivy_version = $1; + $ivy_cvsrevision = 1; + $ivy_versionstring = "v$ivy_version (cvs revision)"; +} +my $newapi4_18 = 1 if (($ivy_cvsrevision == 1 and $ivy_version ge 1.40) or + ($ivy_cvsrevision == 0 and $ivy_version ge 4.18)); #--------------------------------------------------------------------------------- # @@ -87,18 +102,12 @@ my $ivylaunch_agent; #--------------------------------------------------------------------------------- Getopt::Long::Configure('pass_through'); -&usage unless Getopt::Long::GetOptions(\%opt, 'b=s', 'nocursor', 'help', 'smallsize', 'position=s'); +&usage unless Getopt::Long::GetOptions(\%opt, 'b=s', 'nocursor', 'help', 'smallsize', + 'position=s','pingthreshold=s'); &usage(1) if $opt{help}; my ($fuguefile) = @ARGV; -#--------------------------------------------------------------------------------- -# -# init ivy -# -#--------------------------------------------------------------------------------- - -IvyIO::init("ivycontrolpanel", $opt{b}, \&connected, \&disconnected); #--------------------------------------------------------------------------------- # @@ -122,9 +131,24 @@ if ($opt{smallsize}) '-adobe-helvetica-medium-r-normal--11-80-100-100-p-60-iso10646-1'); } +if ($opt{pingthreshold}) { + $pingThreshold = $opt{pingthreshold}; +} my $mw = MainWindow->new (-bg => 'black'); +#--------------------------------------------------------------------------------- +# +# init ivy +# +#--------------------------------------------------------------------------------- + +if ($newapi4_18) { + IvyIO::init("ivycontrolpanel", $opt{b}, \&connected, \&disconnected, \&pingcb, $mw); +} else { + IvyIO::init("ivycontrolpanel", $opt{b}, \&connected, \&disconnected, undef, $mw); +} + if ($opt{nocursor}) { open(CURSOR, ">/tmp/cursor-ivybanner"); print CURSOR "#define cursor_width 1\n"; @@ -141,7 +165,7 @@ if ($opt{nocursor}) { $mw->configure(-cursor => 'circle'); } $mw->geometry ($width."x".$height.$opt{position}); -$mw->title ('ivycontrolpanel'); +$mw->title ('ivycontrolpanel - Ivy '.$ivy_versionstring); $mw->client ('ivycontrolpanel'); $mw->resizable(0,0); @@ -376,8 +400,8 @@ my $wmax = ($width-2*$x0); my $dy = 64*$coef; my %hosts; -Agent->configure($mw, $bg, $fg, $selcolor, $hlbg, $darkbg, \@fontspec20, - $x0, $y0, $wmax, $dy, $cmin, $rmax, $opt{b}, $coef); +Agent->configure($mw, $bg, $fg, $selcolor, $pbcolor, $hlbg, $darkbg, \@fontspec20, + $x0, $y0, $wmax, $dy, $cmin, $rmax, $opt{b}, $coef, $pingThreshold); for (@fugueconfigdata) { next unless $_->[0] eq 'global' or $_->[0] eq 'local'; @@ -403,13 +427,16 @@ MainLoop; sub usage { my $exitflag = shift; - print "Usage : ivycontrolpanel [-help] [-b ivybus] [-nocursor] [fugueconfigfile]\n"; + print "Usage : ivycontrolpanel [-help] [-b ivybus] [-nocursor] [-smallsize]\n"; + print " [-pingthreshold threshold] [fugueconfigfile]\n"; print "\n"; print "Options :\n"; print " -b ivybus bus ivy\n"; - print " -nocursor hide mouse cursor\n"; - print " -smallsize display the app in 640x480 mode\n"; - print " -position position set the window position\n"; + print " -nocursor hide mouse cursor\n"; + print " -smallsize display the app in 640x480 mode\n"; + print " -pingthreshold ms [def=20] set the ping threshold in ms for detecting\n"; + print " performance problems (requires Ivy >= 4.18)\n"; + print " -position position set the window position\n"; print "\n"; exit 0 if $exitflag ; @@ -419,8 +446,8 @@ sub usage { sub killandquit { Agent->killall; $mw->after(1500, sub { - Agent->kill('ivylaunch') if $ivylaunch_agent > 0; - &quit;}); + Agent->kill('ivylaunch') if $ivylaunch_agent > 0; + &quit;}); } # end killandquit @@ -536,6 +563,16 @@ sub disconnected { } # end disconnected +# called when an ivy ping/pong +sub pingcb { + my ($agent, $host, $pingvalue) = @_; + if ($agent eq 'ivylaunch') { + $ivylaunch_agent++; + } elsif ($agent ne 'ivycontrolpanel') { + Agent->pingcb($agent, $host, $pingvalue); + } +} + #--------------------------------------------------------------------------------- # # Functions dedicated to play/pause buttons @@ -782,15 +819,13 @@ sub display_time { } # end display_time - - =head1 NAME ivycontrolpanel - an interface for controlling ivy agents =head1 SYNOPSIS -ivycontrolpanel [-help] [-b bus] [-nocursor] [-smallsize] [-position pos] [fugueconfigfile] +ivycontrolpanel [-help] [-b bus] [-nocursor] [-smallsize] [-position pos] [-pingthreshold ms] [fugueconfigfile] =head1 DESCRIPTION @@ -818,9 +853,13 @@ Hide mouse cursor (for touchscreen usage). Set the window size to 640x480 pixels. -=item B<-position> window position +=item B<-position> XOFF+YOFF + +Specify the window position. + +=item B<-pingthreshold> duration in ms -Specifie window position (x geometry format ex: -0+200). +Set the ping threshold for detecting performance problems. ivycontrolpanel periodically pings agents and compares the ping/pong duration with the given threshold. If duration exceeds it, the agent's led becomes blinking red. Default is 20 ms. Requires Ivy v4.18 or higher. =back |