Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > perl script to generate server round-robin assignments

Reply
Thread Tools

perl script to generate server round-robin assignments

 
 
inetquestion
Guest
Posts: n/a
 
      08-29-2009
#!/usr/bin/perl

##################
### Main Begin ###
##################

if ($#ARGV < 0) {
&DoUsage;
exit;
}

my ($hostname, $limit) = @ARGV; # Script inputs

if ($hostname =~ /^([\d]+)\.([\d]+)\.([\d]+)\.([\d]+)$/) { # Filter
on IP address
$hostString=$hostname; # Save IP
} else {
($hostString) = split /\./,$hostname; # Obtain first portion
of FQDN component
}

@B = qw(svr01 svr02 svr03 svr04 svr05 svr06); # Array containing
assignable server
$binaryNumber = DoAsc2bin($hostString); # Convert string
into base2
$binaryNumber =~ s/\s+//g; # Remove spaces
from base2 string
$decString = DoBin2dec($binaryNumber); # Convert base2
string to base10
$assignment = DoAssign(scalar(@B), $decString, $hostname, $limit); #
Call subroutine to get assignments

print "$hostname: $assignment\n";
exit;

########################
### Subroutine Begin ###
########################

sub DoUsage() {

print <<EOM;


Generates assignment values where servers in list-A need to
communicate with all or some of the servers in list-B. The input to
the script is a single server hostname or IP from list-A. This server
name will go through a conversion (ascII->Binary->Dec), then the order
of the assignments will be made. As long as no two servers have the
same hostname, the assignment will be varied across the list to ensure
the servers in List-B are distributed evenly across those in List-A.

Usage: $0 <hostname|IP> <entry limit>

EOM
}

sub DoAsc2bin { # Convert ASCII string to binary equivalent
my ($string) = @_; # Input
my @bytes; # Declare byte array
for (split //, $string) { # Run throuh for loop per character
of string being split
push @bytes, unpack "B8", $_; # Store binary equivalent of
each character into @bytes
}
return wantarray ? @bytes : join " ", @bytes; # Return @bytes or
a string of all content of @bytes
}

sub DoBin2dec {
return unpack("N", pack("B32", substr("0" x 32 . shift, -32))); #
Converts binary string to decimal equivalent
}

sub DoAssign {
my ($numListB, $num, $host, $lim) = @_; # Function inputs
$lim ||= 100; # Set lim=100 unless otherwise specified
@B = reverse(@B); # Reverse array, then pop last
my $popNum = $num % $numListB; # Get modulus, then pop that
many elements from reversed array
while ( $popNum != 0 ) { #
Iterate until all values have been popped off array
push(@popSave, pop(@B)); # Save popped elements
$popNum--; # Decrement pop counter
}
@B = reverse(@B); # Reverse array
push(@B, @popSave); # Appennd popped elements to
reversed (original direction) array

for( $i = 0; $i < scalar(@B); $i++) { # Loop
through all array elements, maintain counter
if( $B[$i] eq $host ) { # Look for match
#print "Match on $host\n"; # Debug statement
@B = ($B[$i], @B[0..($i-1)], @B[($i+1)..scalar
(@B)]); # Modify array order by moving the "match" to front

last; # Move on
}
}
return join " ", @B[0..($lim-1)]; # Return space
deleimited string
}
 
Reply With Quote
 
 
 
 
John W. Krahn
Guest
Posts: n/a
 
      08-29-2009
inetquestion wrote:
> #!/usr/bin/perl


use warnings;
use strict;

> ##################
> ### Main Begin ###
> ##################
>
> if ($#ARGV < 0) {
> &DoUsage;


if ( @ARGV < 1 ) {
DoUsage();

Or probably better as:

if ( @ARGV != 2 ) {
DoUsage();

> exit;
> }
>
> my ($hostname, $limit) = @ARGV; # Script inputs
>
> if ($hostname =~ /^([\d]+)\.([\d]+)\.([\d]+)\.([\d]+)$/) { # Filter


Why use capturing parentheses? Why put the \d character class inside a
character class?

if ( $hostname =~ /^\d+\.\d+\.\d+\.\d+$/ ) {

> on IP address
> $hostString=$hostname; # Save IP
> } else {
> ($hostString) = split /\./,$hostname; # Obtain first portion
> of FQDN component
> }
>
> @B = qw(svr01 svr02 svr03 svr04 svr05 svr06); # Array containing
> assignable server
> $binaryNumber = DoAsc2bin($hostString); # Convert string
> into base2
> $binaryNumber =~ s/\s+//g; # Remove spaces


Why does DoAsc2bin() add the whitespace if you are just going to remove it?

> from base2 string
> $decString = DoBin2dec($binaryNumber); # Convert base2
> string to base10
> $assignment = DoAssign(scalar(@B), $decString, $hostname, $limit); #


You should probably pass a reference to @B instead of using it globally.

> Call subroutine to get assignments
>
> print "$hostname: $assignment\n";
> exit;
>
> ########################
> ### Subroutine Begin ###
> ########################
>
> sub DoUsage() {
>
> print <<EOM;
>
>
> Generates assignment values where servers in list-A need to
> communicate with all or some of the servers in list-B. The input to
> the script is a single server hostname or IP from list-A. This server
> name will go through a conversion (ascII->Binary->Dec), then the order
> of the assignments will be made. As long as no two servers have the
> same hostname, the assignment will be varied across the list to ensure
> the servers in List-B are distributed evenly across those in List-A.
>
> Usage: $0 <hostname|IP> <entry limit>
>
> EOM
> }
>
> sub DoAsc2bin { # Convert ASCII string to binary equivalent
> my ($string) = @_; # Input
> my @bytes; # Declare byte array
> for (split //, $string) { # Run throuh for loop per character
> of string being split
> push @bytes, unpack "B8", $_; # Store binary equivalent of
> each character into @bytes
> }
> return wantarray ? @bytes : join " ", @bytes; # Return @bytes or

^^^^
Why are you adding these spaces if you don't really want them?

> a string of all content of @bytes
> }
>
> sub DoBin2dec {
> return unpack("N", pack("B32", substr("0" x 32 . shift, -32))); #
> Converts binary string to decimal equivalent
> }
>
> sub DoAssign {
> my ($numListB, $num, $host, $lim) = @_; # Function inputs
> $lim ||= 100; # Set lim=100 unless otherwise specified
> @B = reverse(@B); # Reverse array, then pop last
> my $popNum = $num % $numListB; # Get modulus, then pop that
> many elements from reversed array
> while ( $popNum != 0 ) { #
> Iterate until all values have been popped off array
> push(@popSave, pop(@B)); # Save popped elements
> $popNum--; # Decrement pop counter
> }
> @B = reverse(@B); # Reverse array
> push(@B, @popSave); # Appennd popped elements to
> reversed (original direction) array
>
> for( $i = 0; $i < scalar(@B); $i++) { # Loop
> through all array elements, maintain counter
> if( $B[$i] eq $host ) { # Look for match
> #print "Match on $host\n"; # Debug statement
> @B = ($B[$i], @B[0..($i-1)], @B[($i+1)..scalar
> (@B)]); # Modify array order by moving the "match" to front
>
> last; # Move on
> }
> }
> return join " ", @B[0..($lim-1)]; # Return space
> deleimited string
> }


There is no need to reverse the contents of @B to get the same results:

sub DoAssign {
# Here $ListB contains a reference to @B
my ( $ListB, $num, $host, $lim ) = @_;

$lim ||= 100;

push @$ListB, splice @$ListB, 0, $num % @$ListB;

for my $i ( 0 .. $#$ListB ) {
if ( $ListB->[ $i ] eq $host ) {
#print "Match on $host\n"; # Debug statement
# Modify array order by moving the "match" to front
unshift @$ListB, splice @$ListB, $i, 1;
last;
}
}

return "@{ $ListB }[ 0 .. $lim - 1 ]";
}




John
--
Those people who think they know everything are a great
annoyance to those of us who do. -- Isaac Asimov
 
Reply With Quote
 
 
 
 
inetquestion
Guest
Posts: n/a
 
      08-29-2009
On Aug 28, 10:14*pm, "John W. Krahn" <some...@example.com> wrote:
> inetquestionwrote:
> > #!/usr/bin/perl

>
> use warnings;
> use strict;
>
> > ##################
> > ### Main Begin ###
> > ##################

>
> > if ($#ARGV < 0) {
> > * * &DoUsage;

>
> if ( @ARGV < 1 ) {
> * * *DoUsage();
>
> Or probably better as:
>
> if ( @ARGV != 2 ) {
> * * *DoUsage();
>
> > * * exit;
> > }

>
> > my ($hostname, $limit) = @ARGV; * * * * * * * * * * * * * * * * * *# Script inputs

>
> > if ($hostname =~ /^([\d]+)\.([\d]+)\.([\d]+)\.([\d]+)$/) { * * * * * * * * # Filter

>
> Why use capturing parentheses? *Why put the \d character class inside a
> character class?
>
> if ( $hostname =~ /^\d+\.\d+\.\d+\.\d+$/ ) {
>
> > on IP address
> > * * * $hostString=$hostname; * * * * * * * * * * * * * * * * * * * * * * * # Save IP
> > } else {
> > * * *($hostString) = split /\./,$hostname; * * * * * * * * * * * * # Obtain first portion
> > of FQDN component
> > }

>
> > @B = qw(svr01 svr02 svr03 svr04 svr05 svr06); * * * * * ** * * * *# Array containing
> > assignable server
> > $binaryNumber = DoAsc2bin($hostString); * * * * * * * * * * * * * *# Convert string
> > into base2
> > $binaryNumber =~ s/\s+//g; * * * * * * * * * * * * * * * * * * * * * * * * # Remove spaces

>
> Why does DoAsc2bin() add the whitespace if you are just going to remove it?
>
> > from base2 string
> > $decString = DoBin2dec($binaryNumber); * * * * * * * * * * * * * * # Convert base2
> > string to base10
> > $assignment = DoAssign(scalar(@B), $decString, $hostname, $limit); #

>
> You should probably pass a reference to @B instead of using it globally.
>
>
>
> > Call subroutine to get assignments

>
> > print "$hostname: $assignment\n";
> > exit;

>
> > ########################
> > ### Subroutine Begin ###
> > ########################

>
> > sub DoUsage() {

>
> > print <<EOM;

>
> > Generates assignment values where servers in list-A need to
> > communicate with all or some of the servers in list-B. *The input to
> > the script is a single server hostname or IP from list-A. *This server
> > name will go through a conversion (ascII->Binary->Dec), then the order
> > of the assignments will be made. *As long as no two servers have the
> > same hostname, the assignment will be varied across the list to ensure
> > the servers in List-B are distributed evenly across those in List-A.

>
> > Usage: $0 <hostname|IP> <entry limit>

>
> > EOM
> > }

>
> > sub DoAsc2bin { * * * * * * * * * * * * * ** * * * * * * * * * * *# Convert ASCII string to binary equivalent
> > * * my ($string) = @_; * * * * * * * * * * * * * * * * * * * * * * * * * * # Input
> > * * my @bytes; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * # Declare byte array
> > * * for (split //, $string) { * * * * * * * * * * * * * * * * * * * * * * *# Run throuh for loop per character
> > of string being split
> > * * * push @bytes, unpack "B8", $_; * * * * * * * * * * * * * * *# Store binary equivalent of
> > each character into @bytes
> > * * }
> > * * return wantarray ? @bytes : join " ", @bytes; * * * * * * * *# Return @bytes or

>
> * * * * * * * * * * * * * * * * * * * * ^^^^
> Why are you adding these spaces if you don't really want them?
>
>
>
> > a string of all content of @bytes
> > }

>
> > sub DoBin2dec {
> > * * return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));*#
> > Converts binary string to decimal equivalent
> > }

>
> > sub DoAssign {
> > * * my ($numListB, $num, $host, $lim) = @_; * * * *# Function inputs
> > * * $lim ||= 100; * * * * * * * * * * * ** * * * * * * * * * * * *# Set lim=100 unless otherwise specified
> > * * @B = reverse(@B); * * * * * * * * * * ** * * * * * * *# Reverse array, then pop last
> > * * my $popNum = $num % $numListB; * * * * * * * * # Get modulus, then pop that
> > many elements from reversed array
> > * * while ( $popNum != 0 ) { * * * * * * * * * * * * * * * * * * * #
> > Iterate until all values have been popped off array
> > * * * * push(@popSave, pop(@B)); * * * * * * * * * # Save popped elements
> > * * * * $popNum--; * * * * * * * * * * * * * * * * * * * * # Decrement pop counter
> > * * }
> > * * @B = reverse(@B); * * * * * * * * * * ** * * * * * * *# Reverse array
> > * * push(@B, @popSave); * * * * * * * * * * ** * * * * * *# Appennd popped elements to
> > reversed (original direction) array

>
> > * * for( $i = 0; $i < scalar(@B); $i++) { * * * * * ** * * * * # Loop
> > through all array elements, maintain counter
> > * *if( $B[$i] eq $host ) { * * * * * * * * * * * * * * * * # Look for match
> > * * * * * * #print "Match on $host\n"; * * * * * * * * * # Debug statement
> > * * * * * * @B = ($B[$i], @B[0..($i-1)], @B[($i+1)..scalar
> > (@B)]); * * * # Modify array order by moving the "match" to front

>
> > last; * * * * * * * * * * * * * * * * * * * * * * * * * * * # Move on
> > * * * * }
> > * * }
> > * * return join " ", @B[0..($lim-1)]; * * * * * * * * * *# Return space
> > deleimited string
> > }

>
> There is no need to reverse the contents of @B to get the same results:
>
> sub DoAssign {
> * * *# Here $ListB contains a reference to @B
> * * *my ( $ListB, $num, $host, $lim ) = @_;
>
> * * *$lim ||= 100;
>
> * * *push @$ListB, splice @$ListB, 0, $num % @$ListB;
>
> * * *for my $i ( 0 .. $#$ListB ) {
> * * * * *if ( $ListB->[ $i ] eq $host ) {
> * * * * * * *#print "Match on $host\n"; * * * * *# Debug statement
> * * * * * * *# Modify array order by moving the "match" to front
> * * * * * * *unshift @$ListB, splice @$ListB, $i, 1;
> * * * * * * *last;
> * * * * * * *}
> * * * * *}
>
> * * *return "@{ $ListB }[ 0 .. $lim - 1 ]";
> * * *}
>
> John
> --
> Those people who think they know everything are a great
> annoyance to those of us who do. * * * *-- Isaac Asimov




Thanks for the suggestion; that clears up the questions I had. As i
was writing that I thought there must be an easier way to do
that...
 
Reply With Quote
 
inetquestion
Guest
Posts: n/a
 
      08-29-2009
On Aug 28, 10:14*pm, "John W. Krahn" <some...@example.com> wrote:
> inetquestionwrote:
> > #!/usr/bin/perl

>
> use warnings;
> use strict;
>
> > ##################
> > ### Main Begin ###
> > ##################

>
> > if ($#ARGV < 0) {
> > * * &DoUsage;

>
> if ( @ARGV < 1 ) {
> * * *DoUsage();
>
> Or probably better as:
>
> if ( @ARGV != 2 ) {
> * * *DoUsage();
>
> > * * exit;
> > }

>
> > my ($hostname, $limit) = @ARGV; * * * * * * * * * * * * * * * * * *# Script inputs

>
> > if ($hostname =~ /^([\d]+)\.([\d]+)\.([\d]+)\.([\d]+)$/) { * * * * * * * * # Filter

>
> Why use capturing parentheses? *Why put the \d character class inside a
> character class?
>
> if ( $hostname =~ /^\d+\.\d+\.\d+\.\d+$/ ) {
>
> > on IP address
> > * * * $hostString=$hostname; * * * * * * * * * * * * * * * * * * * * * * * # Save IP
> > } else {
> > * * *($hostString) = split /\./,$hostname; * * * * * * * * * * * * # Obtain first portion
> > of FQDN component
> > }

>
> > @B = qw(svr01 svr02 svr03 svr04 svr05 svr06); * * * * * ** * * * *# Array containing
> > assignable server
> > $binaryNumber = DoAsc2bin($hostString); * * * * * * * * * * * * * *# Convert string
> > into base2
> > $binaryNumber =~ s/\s+//g; * * * * * * * * * * * * * * * * * * * * * * * * # Remove spaces

>
> Why does DoAsc2bin() add the whitespace if you are just going to remove it?
>
> > from base2 string
> > $decString = DoBin2dec($binaryNumber); * * * * * * * * * * * * * * # Convert base2
> > string to base10
> > $assignment = DoAssign(scalar(@B), $decString, $hostname, $limit); #

>
> You should probably pass a reference to @B instead of using it globally.
>
>
>
> > Call subroutine to get assignments

>
> > print "$hostname: $assignment\n";
> > exit;

>
> > ########################
> > ### Subroutine Begin ###
> > ########################

>
> > sub DoUsage() {

>
> > print <<EOM;

>
> > Generates assignment values where servers in list-A need to
> > communicate with all or some of the servers in list-B. *The input to
> > the script is a single server hostname or IP from list-A. *This server
> > name will go through a conversion (ascII->Binary->Dec), then the order
> > of the assignments will be made. *As long as no two servers have the
> > same hostname, the assignment will be varied across the list to ensure
> > the servers in List-B are distributed evenly across those in List-A.

>
> > Usage: $0 <hostname|IP> <entry limit>

>
> > EOM
> > }

>
> > sub DoAsc2bin { * * * * * * * * * * * * * ** * * * * * * * * * * *# Convert ASCII string to binary equivalent
> > * * my ($string) = @_; * * * * * * * * * * * * * * * * * * * * * * * * * * # Input
> > * * my @bytes; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * # Declare byte array
> > * * for (split //, $string) { * * * * * * * * * * * * * * * * * * * * * * *# Run throuh for loop per character
> > of string being split
> > * * * push @bytes, unpack "B8", $_; * * * * * * * * * * * * * * *# Store binary equivalent of
> > each character into @bytes
> > * * }
> > * * return wantarray ? @bytes : join " ", @bytes; * * * * * * * *# Return @bytes or

>
> * * * * * * * * * * * * * * * * * * * * ^^^^
> Why are you adding these spaces if you don't really want them?
>
>
>
> > a string of all content of @bytes
> > }

>
> > sub DoBin2dec {
> > * * return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));*#
> > Converts binary string to decimal equivalent
> > }

>
> > sub DoAssign {
> > * * my ($numListB, $num, $host, $lim) = @_; * * * *# Function inputs
> > * * $lim ||= 100; * * * * * * * * * * * ** * * * * * * * * * * * *# Set lim=100 unless otherwise specified
> > * * @B = reverse(@B); * * * * * * * * * * ** * * * * * * *# Reverse array, then pop last
> > * * my $popNum = $num % $numListB; * * * * * * * * # Get modulus, then pop that
> > many elements from reversed array
> > * * while ( $popNum != 0 ) { * * * * * * * * * * * * * * * * * * * #
> > Iterate until all values have been popped off array
> > * * * * push(@popSave, pop(@B)); * * * * * * * * * # Save popped elements
> > * * * * $popNum--; * * * * * * * * * * * * * * * * * * * * # Decrement pop counter
> > * * }
> > * * @B = reverse(@B); * * * * * * * * * * ** * * * * * * *# Reverse array
> > * * push(@B, @popSave); * * * * * * * * * * ** * * * * * *# Appennd popped elements to
> > reversed (original direction) array

>
> > * * for( $i = 0; $i < scalar(@B); $i++) { * * * * * ** * * * * # Loop
> > through all array elements, maintain counter
> > * *if( $B[$i] eq $host ) { * * * * * * * * * * * * * * * * # Look for match
> > * * * * * * #print "Match on $host\n"; * * * * * * * * * # Debug statement
> > * * * * * * @B = ($B[$i], @B[0..($i-1)], @B[($i+1)..scalar
> > (@B)]); * * * # Modify array order by moving the "match" to front

>
> > last; * * * * * * * * * * * * * * * * * * * * * * * * * * * # Move on
> > * * * * }
> > * * }
> > * * return join " ", @B[0..($lim-1)]; * * * * * * * * * *# Return space
> > deleimited string
> > }

>
> There is no need to reverse the contents of @B to get the same results:
>
> sub DoAssign {
> * * *# Here $ListB contains a reference to @B
> * * *my ( $ListB, $num, $host, $lim ) = @_;
>
> * * *$lim ||= 100;
>
> * * *push @$ListB, splice @$ListB, 0, $num % @$ListB;
>
> * * *for my $i ( 0 .. $#$ListB ) {
> * * * * *if ( $ListB->[ $i ] eq $host ) {
> * * * * * * *#print "Match on $host\n"; * * * * *# Debug statement
> * * * * * * *# Modify array order by moving the "match" to front
> * * * * * * *unshift @$ListB, splice @$ListB, $i, 1;
> * * * * * * *last;
> * * * * * * *}
> * * * * *}
>
> * * *return "@{ $ListB }[ 0 .. $lim - 1 ]";
> * * *}
>
> John
> --
> Those people who think they know everything are a great
> annoyance to those of us who do. * * * *-- Isaac Asimov




It is impressive you "can and would" take the time to make my original
function more efficient. Being able to take someone else's code in
which wasn't explained at all, and modify it so quickly truly
impresses me. Your version worked immediately after I changed my
calling code to pass a reference array.

Thanks again!

-Inet
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Failed to generate a user instance of SQL Server. Only an integratedconnection can generate a user instance. Harlan Messinger ASP .Net 2 03-28-2010 06:51 PM
what's wrong calling a Perl/CGI script in Perl/CGI script under Tomcat server? kath Perl Misc 4 04-09-2007 09:21 PM
problem calling perl script from SOAP server perl script pj Perl Misc 3 04-09-2004 10:23 PM
Perl Help - Windows Perl script accessing a Unix perl Script dpackwood Perl 3 09-30-2003 02:56 AM
How to make Perl Script "POST" call from another Perl Script??? Wet Basement Perl 1 07-15-2003 10:25 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57