Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

newbie writing a counter

by jrbush82 (Initiate)
on Aug 07, 2001 at 00:59 UTC ( #102607=perlquestion: print w/replies, xml ) Need Help??

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

hello, today is my first day with perl... I've setup plenty of "free" perl scripts. Anybody have any idea on what could be wrong with this?

#!/usr/bin/perl #begins for loop of READCOUNTER so that it has to lock file before rea +ding READCOUNTER: for ($i=0; defined($i); $i++){ #opens counter data file open(COUNTERDAT,"./counter.dat"); #locks file, and if can't, goes back to READCOUNTER to try again flock COUNTERDAT, 1 or next READCOUNTER; #puts first line of counter data file in first array (0) called counte +rdat while (<COUNTERDAT>){ push @counterdat, $_; } #closes counter data file close COUNTERDAT; #ends for loop of READCOUNTER last READCOUNTER; } #sets previous number in counter.dat to one higher $pnum = $counterdat[0]; $pnum++; #begins loop of WRITECOUNTER so that it has to lock file before writin +g WRITECOUNTER: for ($i=0; defined($i); $i++){ #opens counter data file again open(COUNTERDAT,">./counter.dat"); #locks file, and if can't, goes back to WRITECOUNTER flock COUNTERDAT, 2 or next WRITECOUNTER; #writes new number to counter data file print COUNTERDAT "$pnum"; #closes counter data file close COUNTERDAT; #ends loop for WRITECOUNTER last WRITECOUNTER; } #begins for loop of READCOUNTER2 so that it has to lock file before re +ading READCOUNTER2: for ($i=0; defined($i); $i++){ #opens counter data file open(COUNTERDAT2,"./counter.dat"); #locks file, and if can't, goes back to READCOUNTER to try again flock COUNTERDAT2, 1 or next READCOUNTER2; #puts first line of counter data file in first array (0) called counte +rdat2 while (<COUNTERDAT2>){ push @counterdat2, $_; } #closes counter data file close COUNTERDAT; #ends for loop of READCOUNTER2 last READCOUNTER2; } print<<HTMLEND; content type; text/html $counterdat2[0] HTMLEND
and I am using this for my include in a .shtml file
<!--#include virtual="cgi-bin/counter/counter.cgi" -->
Thanks,
jrbush82

Edit ar0n 2001-08-06 -- Added <code> tags.

Replies are listed 'Best First'.
Re: newbie writing a counter
by merlyn (Sage) on Aug 07, 2001 at 05:03 UTC
Are you writing a counter, or learning Perl?
by petdance (Parson) on Aug 07, 2001 at 01:15 UTC
    I've setup plenty of "free" perl scripts.

    What's your goal here? Are you trying to get a counter running, or are you trying to learn Perl?

    If you're trying to get a counter running, then I would suggest that you not reinvent the wheel and just use a canned script.

    If you're trying to learn Perl, then doing it through CGI is not the way to do it. merlyn's 3rd edition of Learning Perl just came out, and is the canonical text for learning our beloved language.

    It seems that you're just trying to throw things together without really learning Perl, and expecting us to clean up your mess. People who clean up things like that are called "consultants", and there are any number of them here at the Monastery who would be glad to send you a rate card.

    xoxo,
    Andy
    --
    <megaphone> Throw down the gun and tiara and come out of the float! </megaphone>

      I'm trying to learn Perl, and adapt it to CGI. I guess from what I have learned, I see that I've opened a file and locked it, and then set the variable and closed it. Opened it again in read/write mode and wrote to the file with the new number. Then closed it. Opened up the file again to get the new number and make a variable of it. Then used it to print in html format.

      Just trying to learn Perl, which is the primary language in which CGI is written. Sorry if its an inconvienance to you the way I learn it.
Re: newbie writing a counter
by petdance (Parson) on Aug 07, 2001 at 01:04 UTC
    Anybody have any idea on what could be wrong with this?

    Not without you telling us what the problem is, no.

    Do you get an error? Is the counter wrong? Does the server catch on fire?

    Please take a look at How to get the most of your question from the monks.

    xoxo,
    Andy
    --
    <megaphone> Throw down the gun and tiara and come out of the float! </megaphone>

(ar0n) Re: newbie writing a counter
by ar0n (Priest) on Aug 07, 2001 at 01:11 UTC
    Apart from the countless other errors
    content type; text/html
    should be
    Content-Type: text/html

    ar0n ]

      well I fixed that, and it still didn't run online correctly... hmm...
Re: newbie writing a counter
by nardo (Friar) on Aug 07, 2001 at 01:47 UTC
    #opens counter data file open(COUNTERDAT,"./counter.dat"); #locks file, and if can't, goes back to READCOUNTER to try again flock COUNTERDAT, 1 or next READCOUNTER;
    ...and later...
    #opens counter data file again open(COUNTERDAT,">./counter.dat"); #locks file, and if can't, goes back to WRITECOUNTER flock COUNTERDAT, 2 or next WRITECOUNTER;
    What happens when open(COUNTERDAT,">./counter.dat"); runs and then your operating system switches to another process which runs
    open(COUNTERDAT,"./counter.dat"); flock COUNTERDAT, 1 or next READCOUNTER;
    Answer: The second process now has the file locked but the contents was destroyed with the open from the first process. The second process will see that the count is zero and will write '1' to the file. The solution is to open the file for reading/writing: open(COUNTERDAT, "<+./counter.dat"); then seek to the beginning of the file when you want to write the new number (if you were potentially writing a smaller byte count you would want to truncate the file, but since a number will always be at least as long as the previous number (assuming positives) this is not necessary).
      In the first file open, I set an array so that I can then add 1 to the number. Even if all the information is destroyed in the first file open (which is read only right?), I have still written the array which is stored. When the first process is done, it goes to the second, which opens the file as read/write and then writes the new variable, which was the first item in the array plus one. When that is done, I then open it one last time in read only, and then set a new array so that I can then post the number as output to HTML. This is the way I see what is going on. I don't quite follow you on what you are saying.
        When the first process is done, it goes to the second

        If you're running on an operating system which does not support multitasking, then this statement is correct, but if you're running on any modern OS (Windows 9x/NT, unix) then you can not control when the OS switches to another process. Your operating system, in order to run multiple processes at once, will periodically switch from one process to another (assuming it is a preemptive multitasking OS, you will have no control over when it does this) so after the first process opens the file for writing (thus erasing the contents of the file) you can not ensure that the flock call will occur before another process runs.

        First process erases file
        OS switches to second process
        Second process opens locks and reads in empty file, closes file releasing the lock which allows first process to lock the file
        OS switches to first process which locks and writes correct count to file
        First process terminates leaving file with correct count
        Second process increments empty count to 1 and writes 1 to the file
        Second process terminates leaving the file with the count of 1 regardless of what it was when process one started.
Re: newbie writing a counter
by scain (Curate) on Aug 07, 2001 at 17:18 UTC
    Hello,

    While I agree with merlyn, writing a counter as a tutorial is a fine idea. I haven't seen anyone give these pointers yet, so I will:

    • add use CARP::FatalsToBrowser; so you can get the error messages there.
    • until you add that, look at your browsers error log for the exact errors.
    • "An error processing this directive" often means that the path to perl is incorrect or the file is not an executable (ie, chmod a+x file.pl).
    Once you start getting useable error messages, this should be a lot easier to debug.

    Scott

You have to tell us what's going wrong before we can help you.
by dragonchild (Archbishop) on Aug 07, 2001 at 01:05 UTC
    None of us will have a single idea what's wrong with it until you tell us ... It looks good to me. I could give you a number of Perl style suggestions, but everything looks good from this end.

    ------
    /me wants to be the brightest bulb in the chandelier!

    Vote paco for President!

        Does the script run properly when you go to /cgi-bin/counter/counter.cgi versus pulling it in through SSI?

        Does the script run properly from the command line?

        Do you have access to the web server logs? If so, can you copy the error you see there?

Re: newbie writing a counter
by buckaduck (Chaplain) on Aug 08, 2001 at 01:09 UTC
    There are many things to fix in your code. First, I should emphasize some points made earlier:
    1. Fix the "content type" line.
    2. Check that perl is really in /usr/bin/perl and that your program is executable. Check your web server logs.

    These may fix your program if it works on the command line but not in a web browser.

    Your code also seems needlessly complicated. Here's some simpler code which I adapted (okay, stole) from an answer to your frequently asked question:

    # Let the Fcntl module define some constants use Fcntl qw(:DEFAULT :flock); # Open the counter file read/write and lock it. # If the file hasn't been created yet, it creates one. # Of course, the usual flock cautions apply. sysopen(FH, $file, O_RDWR|O_CREAT) or die "Can't open $file_banner: $!\n"; flock(FH, LOCK_EX) or die "Can't write-lock $file: $!\n"; # Read one line from the file. Set $num to the # value from that line, or to zero by default. # It's a little silly to read every line into an array # and reference the first element if you only want # this one value, isn't it? $num = <FH> || 0; # Start at the beginning of the file seek(FH, 0, 0) or die "Can't rewind $file: $!\n"; truncate(FH,0) or die "Can't truncate $file: $!\n"; # Print the new number to the file and close it print FH $num+1, "\n" or die "Can't write to $file: $!\n"; close(FH) or die "Can't close $file: $!\n";

    Note how the error checking is done wherever feasible so that you can get more feedback on your success/failure than that things "don't work".

    buckaduck

Re: newbie writing a counter
by jrbush82 (Initiate) on Aug 07, 2001 at 01:04 UTC
    oops, I did all this manually, and code was still messed up.. here is the real code that html doesn't mess with...
    #!/usr/bin/perl #begins for loop of READCOUNTER so that it has to lock file before rea +ding READCOUNTER: for ($i=0; defined($i); $i++){ #opens counter data file open(COUNTERDAT,"./counter.dat"); #locks file, and if can't, goes back to READCOUNTER to try again flock COUNTERDAT, 1 or next READCOUNTER; #puts first line of counter data file in first array (0) called counte +rdat while (<COUNTERDAT>){ push @counterdat, $_; } #closes counter data file close COUNTERDAT; #ends for loop of READCOUNTER last READCOUNTER; } #sets previous number in counter.dat to one higher $pnum = $counterdat[0]; $pnum++; #begins loop of WRITECOUNTER so that it has to lock file before writin +g WRITECOUNTER: for ($i=0; defined($i); $i++){ #opens counter data file again open(COUNTERDAT,">./counter.dat"); #locks file, and if can't, goes back to WRITECOUNTER flock COUNTERDAT, 2 or next WRITECOUNTER; #writes new number to counter data file print COUNTERDAT "$pnum"; #closes counter data file close COUNTERDAT; #ends loop for WRITECOUNTER last WRITECOUNTER; } #begins for loop of READCOUNTER2 so that it has to lock file before re +ading READCOUNTER2: for ($i=0; defined($i); $i++){ #opens counter data file open(COUNTERDAT2,"./counter.dat"); #locks file, and if can't, goes back to READCOUNTER to try again flock COUNTERDAT2, 1 or next READCOUNTER2; #puts first line of counter data file in first array (0) called counte +rdat2 while (<COUNTERDAT2>){ push @counterdat2, $_; } #closes counter data file close COUNTERDAT; #ends for loop of READCOUNTER2 last READCOUNTER2; } print<<HTMLEND; content type; text/html $counterdat2[0] HTMLEND

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://102607]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (2)
As of 2022-09-25 11:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    I prefer my indexes to start at:




    Results (116 votes). Check out past polls.

    Notices?