For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > August 2005 > Anonymous array of hashes question









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Anonymous array of hashes question
Jason Normandin

2005-08-04, 10:00 pm

Hello

I have a situation where I build an anonymous array of hashes for some
requests and responses found in a file (there can be multiple requests and
responses). It works very nicely and tracks all of the responses and
requests from an ip to another IP address.

Here is my code:

my $time=$1 if /^(\d+:\d+:\d+\.\d+)/;
my $source=$1 if /(\S+) -> \S+/;
my $destination=$1 if /\S+ -> (\S+)/;
my $sourcePort=$1 if /S=(\d+)/;
my $destinationPort=$1 if /D=(\d+)/;
my $sequenceNumber=$1 if /Sequence number: (\d+)/;

if ($protocol =~ /PING REQUEST/) {
push @{$pingRequests{$destination}}, {
time => $time,
sequenceNumber=>$sequenceNumber
};
}
elsif ($protocol =~ /PING RESPONSE/) {
push @{$pingResponses{$source}}, {
time => $time,
sequenceNumber=>$sequenceNumber
};
}

I can then access the contents via code like:

foreach my $record(@{$pingRequests{$request}}) {
$requestCount++;
print "\tRequest Time=$record->{time}\n" if defined $details; }

What I want to do however is track the response time between a request and
response. This would be identified by the same sequence number for a
request/respone pair. I would like to take the time value for each and
subtract the response time from the request time to get the response time
and add that to the response hash.

I cannot figure out how to access the contents of the anonymous hash for
that one value.

Sudo code would be:

elsif ($protocol =~ /PING RESPONSE/) {
responseTime=pingRequests{$source}->time -
pingResponses{$destination)->time if pingRequests{$source}->sequenceNumber =
pingResponses{$destination}->sequenceNumber;

push @{$pingResponses{$source}}, {
time => $time,
sequenceNumber=>$sequenceNumber
responseTime=>$responseTime

};
}

DOes that make any sense? Can I do what I am trying to accomplish using the
logic above? If so, what is that syntax?

Help!

Thanks!
Jason
Philipp Traeder

2005-08-04, 10:00 pm

On Friday 05 August 2005 01:37, Jason Normandin wrote:
[..]
>
> if ($protocol =~ /PING REQUEST/) {
> push @{$pingRequests{$destination}}, {
> time => $time,
> sequenceNumber=>$sequenceNumber
> };
> }
> elsif ($protocol =~ /PING RESPONSE/) {
> push @{$pingResponses{$source}}, {
> time => $time,
> sequenceNumber=>$sequenceNumber

[..]

> What I want to do however is track the response time between a request and
> response. This would be identified by the same sequence number for a
> request/respone pair. I would like to take the time value for each and
> subtract the response time from the request time to get the response time
> and add that to the response hash.
>
> I cannot figure out how to access the contents of the anonymous hash for
> that one value.
>
> Sudo code would be:
>
> elsif ($protocol =~ /PING RESPONSE/) {
> responseTime=pingRequests{$source}->time -
> pingResponses{$destination)->time if pingRequests{$source}->sequenceNumber
> = pingResponses{$destination}->sequenceNumber;
>
> push @{$pingResponses{$source}}, {
> time => $time,
> sequenceNumber=>$sequenceNumber
> responseTime=>$responseTime
>
> };
> }
>



Hi Jason,

I think you might want to take a look at the map function - using it, you
could do something like this:

my $response = $pingResponse{$destination};
my $responseTime;
map { $responseTime = ($response->{'time'} - $_->{'time'})
if ($_->{'sequenceNumber'} == $response->{'sequenceNumber'})
} @{$pingRequests{$destination}};

> DOes that make any sense? Can I do what I am trying to accomplish using the
> logic above? If so, what is that syntax?


I'm not sure if I would approach your problem the same way - I don't know what
exactly you need to have as result, but I would think about storing all
request/response pairs in a hash with the sequence number as key. This might
make things easier.

HTH,

Philipp
John W. Krahn

2005-08-05, 4:00 am

Jason Normandin wrote:
> Hello


Hello,

> I have a situation where I build an anonymous array of hashes for some
> requests and responses found in a file (there can be multiple requests and
> responses). It works very nicely and tracks all of the responses and
> requests from an ip to another IP address.
>
> Here is my code:
>
> my $time=$1 if /^(\d+:\d+:\d+\.\d+)/;


perldoc perlsyn
[snip]
NOTE: The behaviour of a "my" statement modified with a statement
modifier conditional or loop construct (e.g. "my $x if ...") is
undefined. The value of the "my" variable may be "undef", any
previously assigned value, or possibly anything else. Don't rely
on it. Future versions of perl might do something different from
the version of perl you try it out on. Here be dragons.

So don't do that! :-)

If you want to declare and assign from a match in one statement you have
to do either:

my ( $time ) = /^(\d+:\d+:\d+\.\d+)/;

Or:

/^(\d+:\d+:\d+\.\d+)/ and my $time = $1;


> my $source=$1 if /(\S+) -> \S+/;
> my $destination=$1 if /\S+ -> (\S+)/;
> my $sourcePort=$1 if /S=(\d+)/;
> my $destinationPort=$1 if /D=(\d+)/;
> my $sequenceNumber=$1 if /Sequence number: (\d+)/;
>
> if ($protocol =~ /PING REQUEST/) {
> push @{$pingRequests{$destination}}, {
> time => $time,
> sequenceNumber=>$sequenceNumber
> };
> }
> elsif ($protocol =~ /PING RESPONSE/) {
> push @{$pingResponses{$source}}, {
> time => $time,
> sequenceNumber=>$sequenceNumber
> };
> }


You are duplicating a lot of code there. You could simplify that like:

if ( $protocol =~ /PING RE(?:QUEST|SPONSE)/ ) {
push @{ $pingRequests{ $destination } }, {
time => $time,
sequenceNumber => $sequenceNumber
};
}


> I can then access the contents via code like:
>
> foreach my $record(@{$pingRequests{$request}}) {
> $requestCount++;
> print "\tRequest Time=$record->{time}\n" if defined $details; }
>
> What I want to do however is track the response time between a request and
> response. This would be identified by the same sequence number for a
> request/respone pair. I would like to take the time value for each and
> subtract the response time from the request time to get the response time
> and add that to the response hash.
>
> I cannot figure out how to access the contents of the anonymous hash for
> that one value.
>
> Sudo code would be:
>
> elsif ($protocol =~ /PING RESPONSE/) {
> responseTime=pingRequests{$source}->time -
> pingResponses{$destination)->time if pingRequests{$source}->sequenceNumber =
> pingResponses{$destination}->sequenceNumber;
>
> push @{$pingResponses{$source}}, {
> time => $time,
> sequenceNumber=>$sequenceNumber
> responseTime=>$responseTime
>
> };
> }
>
> DOes that make any sense? Can I do what I am trying to accomplish using the
> logic above? If so, what is that syntax?


The first thing you need to do is convert the time string into a number
that can be added and subtracted and then determine how to store that in
your structure. Something like (untested):

use Time::Local;

my ( $hour, $minute, $second, $fraction ) = /^(\d+):(\d+):(\d+)(\.\d+)/;

my $time = timegm( 35, 7, 8, ( gmtime 0 )[ 3 .. 5 ] ) . $fraction;


if ( $protocol =~ /PING REQUEST/ ) {
$pingRequests{ $destination }{ $sequenceNumber } -= $time;
}
elsif ( $protocol =~ /PING RESPONSE/ ) {
$pingRequests{ $destination }{ $sequenceNumber } += $time;
}


Season to taste. :-)



John
--
use Perl;
program
fulfillment
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2009 codecomments.com