K_M_McMahon has asked for the wisdom of the Perl Monks concerning the following question:

I come beseeching the wisdom of the perl monks once again.

I am working on a script that I am using to monitor remote processes and I have an array "@sof_i" that is full of connection data. A start time, a stop time, connnection status etc, for several days worth of connections. Each connection is seperated by a line of "=" signs. Here is the code in question:

if (!defined($sof_i[2])) { print "There is no data in the ISTAT file\n"; print "The RTS/DPS monitor is down.\n"; close(PAGE); system(@sendpage); exit(1); } @sof_i=reverse @sof_i; &get_i; sub get_i { if ($sof_i[0]=~m/={30}/){shift(@sof_i);} foreach(@sof_i) { last if $_=~/^={30}/; ($i_day, $i_month, $i_date, $i_hour, $i_minute, $i_second, $i_ +year)=$_=~/(^\D{3}) (\D{3})\s+(\d{1,2}) (\d{2}):(\d{2}):(\d{2}) (\d{4 +}) sw_eof \[.+\] try / if $_=~m/try/; ($i_con_day, $i_con_month, $i_con_date, $i_con_hour, $i_con_mi +nute, $i_con_second, $i_con_year)=$_=~/(^\D{3}) (\D{3})\s+(\d{1,2}) ( +\d{2}):(\d{2}):(\d{2}) (\d{4}) sw_eof \[.+\]/ if $_=~m/connected/; ($i_socket_status)=$_=~/\[(.*)\]/ if $_=~m/EOF Socket Status/; $sof_to_delete++ } for ($i=0;$sof_to_delete>0;$sof_to_delete--) {shift(@sof_i);} $i_num_month=0 if $i_month=~m/Jan/; $i_num_month=1 if $i_month=~m/Feb/; $i_num_month=2 if $i_month=~m/Mar/; $i_num_month=3 if $i_month=~m/Apr/; $i_num_month=4 if $i_month=~m/May/; $i_num_month=5 if $i_month=~m/Jun/; $i_num_month=6 if $i_month=~m/Jul/; $i_num_month=7 if $i_month=~m/Aug/; $i_num_month=8 if $i_month=~m/Sep/; $i_num_month=9 if $i_month=~m/Oct/; $i_num_month=10 if $i_month=~m/Nov/; $i_num_month=11 if $i_month=~m/Dec/; $i_sof_time=timegm($i_second, $i_minute, $i_hour, $i_date,$i_num_m +onth,$i_year); } if (!defined($i_sof_time)) { print "I did not find any connection attempts in the istat file.\n +"; print "RTS/DPS Monitor is down.\n"; close(PAGE); system(@sendpage); exit(1); }


In the first step, it checks that the array has information in it. After it is reversed (to put the newest info first in the array) it attempts to extract information. Then when it comes back from the subroutine it should have an $i_sof_time that is defined. I have watched it using the debugger and sometimes (not always) the array has the data in it before going into the subroutine, but then once in the subroutine, the array is empty!

any ideas?

Thanx for your help!
-Kevin

Replies are listed 'Best First'.
Re: Array undefining istelf?
by Grygonos (Chaplain) on Feb 27, 2004 at 15:19 UTC

    I see no my's in your code so i'm going to venture to say you're not using strict here. I would add

    use strict; use warnings;
    to the top of the script and see what develops. It also seems that you are not passing any parameters to your subs and using global variables instead. Passing references to your variables into your subroutine makes your code a little more understandable (because you know what data you will be working due to explicitly passing references to the subroutine).

    I'm not trying to be dismissive of your question at all.. but using strict pragma can reveal so many problems you didn't even know existed in your code. If you're serious about learning more perl and becoming exceedingly efficient at coding and debugging it.. then I would strongly reccomend using strict.

    Put the strict and warnings after your shebang and correct the errors it displays, then you may have a clearer picture of what's going on in the program. This whole problem could be as simple as mispelling a variable in one place of the program.

    This piece of code

    foreach(@sof_i) { last if $_=~/^={30}/; ($i_day, $i_month, $i_date, $i_hour, $i_minute, $i_second, $i_ +year)=$_=~/(^\D{3}) (\D{3})\s+(\d{1,2}) (\d{2}):(\d{2}):(\d{2}) (\d{4 +}) sw_eof \[.+\] try / if $_=~m/try/; ($i_con_day, $i_con_month, $i_con_date, $i_con_hour, $i_con_mi +nute, $i_con_second, $i_con_year)=$_=~/(^\D{3}) (\D{3})\s+(\d{1,2}) ( +\d{2}):(\d{2}):(\d{2}) (\d{4}) sw_eof \[.+\]/ if $_=~m/connected/; ($i_socket_status)=$_=~/\[(.*)\]/ if $_=~m/EOF Socket Status/; $sof_to_delete++ } ##This just randomly deletes the first elements of the array for ho +wever many times you did $sof_to_delete++ for ($i=0;$sof_to_delete>0;$sof_to_delete--) {shift(@sof_i);}
    confuses me. Of corse your array @sof_i will be empty.. you don't have a condition around $soft_to_delete++; so effectively what your code is doing (unless i'm totally crazy) is
    foreach(@sof_i) { $sof_to_delete++; } shift @sof_i for (0..$sof_to_delete)
    In turn looping through every value .. doing some regex and then marking it for deletion and then in fact deleting it..,

    am I way off base here?

    Grygonos
      I will try the use strict and use warning. But as far as the $sof_to_delete, it is incrementing at each iteration of the for (@sof_i) statement, but that for (@sof_i) statement has a last if $_=~/^={30}/; statement which should stop the for statement after about 5 lines. (every 5 lines is a line of =========== .

      -Kevin
        so then the sub would be called multiple times and the ^={30}, is just tellin it to stop for now right? btw, simple print debugging can be very revealing. checking the value interactively as you go through the code. something like
        print $var_to_check; my $dummy = <STDIN>; #so it doesn' fly by in programs that generate lo +ts of output

        Grygonos
Re: Array undefining istelf?
by broquaint (Abbot) on Feb 27, 2004 at 15:16 UTC
    Your offending lines are here
    for ($i=0;$sof_to_delete>0;$sof_to_delete--) {shift(@sof_i);
    Which is shifting off all the elements in @sof_i, where $sof_to_delete was incremented in the foreach loop immediately above it for every element in @sof_i.
    HTH

    _________
    broquaint

      The array appears to be undefining itself prior to it reaching this point in the script. $sof_to_delete is equal to the number of lines parsed through in the previous part of the subroutine. It is so that if I have to look past the last connection to an earlier connection, it is removed from the array prior to the next iteration of the subruotine (if it is called later.)
      -Kevin
        stop saying that :) An array is a data structure. It's a data structure. It cannot undefine itself.

        ps -- I of course am ignoring perltie because the OP is not using perltie

Re: Array undefining istelf?
by Fletch (Bishop) on Feb 27, 2004 at 15:13 UTC

    Not directly related, but a more compact month parse would be:

    $i_num_month = { Jan => 0, Feb => 1, Mar => 2, Apr => 3, May => 4, Jun => 5, Jul => 6, Aug => 7, Sep => 8, Oct => 9, Nov => 10, Dec => 11 } ->{ $i_month };
Re: Array undefining istelf?
by Limbic~Region (Chancellor) on Feb 27, 2004 at 15:52 UTC
    K_M_McMahon,
    I can not make heads or tails of your code. It does not appear that you have supplied enough information since none of your variables have a defined scope. I have taken the liberty of re-writing your code to something a bit easier on my eyes. It will not work but it might help you to see where the problem is yourself (I hope). Cheers - L~R
Re: Array undefining istelf?
by ysth (Canon) on Feb 27, 2004 at 15:58 UTC
    I don't spot the problem; are you getting the amount of output you expect? That is, do you have evidence that the last is triggering correctly? It would be good to have a check that each of your regexes in the foreach() loop is matching only once.

    Your code is complicated enough that you should be using strict and declaring all variables (in the sub as my() variables where possible).

    A more concise way to say:

    for ($i=0;$sof_to_delete>0;$sof_to_delete--) {shift(@sof_i);}
    is
    splice(@sof_i, 0, $sof_to_delete);
    A perhaps better way to destructively use the beginning of an array, would be to replace both for loops in get_i with:
    while (defined($_ = shift(@sof_i)) { ... body of your foreach (@sof_i) ... }
    Another possibility is to set the input record separator to "="x30 where you are reading into @sof_i (assuming it comes from a filehandle at some point) so you get only one array element per thing you want to handle.
Re: Array undefining istelf?
by Popcorn Dave (Abbot) on Feb 27, 2004 at 16:39 UTC
    The first thing I would do is step through it with a debugger to see where it was holding and failing. My favorite debugger is a Perl/Tk based one that can be found here.

    Good luck!

    There is no emoticon for what I'm feeling now.