Results 1 to 14 of 14
  1. #1

    Counter problems

    Hi,

    I currently have a perl counter. What happens is that when a html page is loaded the javascript calls a perl file to update the counter and read the value.

    The perl script works this way:
    It open the counter file in read mode, reads the value updates it by 1 and then closes it. It then opens the file in Write mode and writes the new count and closes.

    If the file does not exist it creates a new oen and sets the counter to 0.

    Problem:
    The problem is that if you try to refresh this script quickly, somewhere along the way the read code locks the file and thus the second read gets a error and it assumes that the files does nto exist and the file is opened in Write mode and the counter is reset.

    It perl script was written by someone else.

    What is a good counter solution that will avoid this problem. Any ASP/Perl/JS solution will do.

  2. #2
    Join Date
    Jan 2003
    Posts
    1,715

    Re: Counter problems

    Originally posted by ruthless
    Problem:
    The problem is that if you try to refresh this script quickly, somewhere along the way the read code locks the file and thus the second read gets a error and it assumes that the files does nto exist and the file is opened in Write mode and the counter is reset.
    I suspect you have trouble finding the solution because you assume too much about the problem.

    You probably open the write with something like this:
    open(FILE, '>filename.txt');

    The problem is, in the time between the open and the print, the file is blank. If a read request fires during that window (which, given enough chances, it eventually will), it will read a blank and increment it to 1. The problem is compounded because you can't hold a lock between two open operations.

    To handle a write like this, you should open the file in read/write mode ('+<filename.txt') and seek() back to 0 after the read. That will at least keep the data intact, so you don't reset, and it will also allow you to use flock to serialize the runs.
    Game Servers are the next hot market!
    Slim margins, heavy support, fickle customers, and moronic suppliers!
    Start your own today!

  3. #3
    Code:
    flock FILEHANDLE,2;
    Locks the file while you are working with it so that other scripts (or the same script being run again) can't touch the file until you are done. Without seeing the code I can't help you much more. You should read up on it here: http://perl.about.com/cs/intermediateperl/a/022704.htm

  4. #4
    Thanks for the replies. hiryuu what you said makes a lot of sense. I really do not know perl and we use it only for counters. This is the code that opens the file reads the counter and then updates it.

    Below is the code used for the counter

    $file = "filename.txt";
    if(! -e $file)
    {
    $count = 0;
    }
    else
    {
    open(CNT, "$file") || die "count not read $file";
    $count = <CNT>;
    chomp($count);
    close(CNT);
    }

    if(!$show)
    {
    $count++;
    open(CNT, ">$file") || die "could not write to $file";
    print CNT $count;
    close(CNT);
    }

    How can this be modified to avoid the problem. Any help will be appreciated.

  5. #5
    I read a few file commands online and modified the write as shown below. Is this right? Also it seems to miss certain counts

    if(!$show) {
    $count++;
    open(CNT, "+>$file") || die "could not write to $file";
    flock (CNT, 2);
    seek(CNT, $curpos, 0);
    print CNT $count;
    close(CNT);
    }

  6. #6
    Join Date
    Jan 2003
    Posts
    1,715
    It will miss counts, since concurrent requests can read the same number during the read stage.

    open CNT, '+<filename.txt';
    flock(CNT, 2);
    $count = <CNT>;
    $count++;
    seek(CNT, 0, 0);
    print CNT $count;
    close(CNT);

    This will not create the file for you, but it's otherwise one clean operation, locked the whole way through.
    Game Servers are the next hot market!
    Slim margins, heavy support, fickle customers, and moronic suppliers!
    Start your own today!

  7. #7
    thanks hiryuu.

    Is there a way to lock the file so that the next time the file is read it is checked to see whether there is a lock on it. Only if there is no lock on it can it been read. There will be a timeout period during which the program waits to see if the lock has been given up and if it has then it goes ahead and reads the count else it does something else.

  8. #8
    Join Date
    Mar 2004
    Location
    USA
    Posts
    4,345
    Do you have database with your plan?

    Peace,
    Testing 1.. Testing 1..2.. Testing 1..2..3...

  9. #9
    Join Date
    Jan 2003
    Posts
    1,715
    Originally posted by ruthless
    Is there a way to lock the file so that the next time the file is read it is checked to see whether there is a lock on it. Only if there is no lock on it can it been read.
    The flock(CNT, 2) obtains an exclusive lock ("flock(CNT, LOCK_EX)" is a little clearer, but requires an include). Since that's done before the read, a second run will block until the first run closes the file (releasing the lock) before it will even read the count. It is possible to do a non-blocking lock check, but it's pointless on such a fast lock.

    As azizny mentions, you may want to use a database server, which transparently handles a lot of this concurrent access mess.
    Game Servers are the next hot market!
    Slim margins, heavy support, fickle customers, and moronic suppliers!
    Start your own today!

  10. #10
    Join Date
    Mar 2004
    Location
    USA
    Posts
    4,345
    or actually maybe its just his server, I have used this counter for my sites and never done me any problems.. (even if you attack it with a billion hit!)..

    Peace,
    Testing 1.. Testing 1..2.. Testing 1..2..3...

  11. #11
    Join Date
    Jan 2003
    Posts
    1,715
    You're probably on a Windows system. Windows uses mandatory locking, which would prevent this issue, but comes with its own hefty can of worms.
    Game Servers are the next hot market!
    Slim margins, heavy support, fickle customers, and moronic suppliers!
    Start your own today!

  12. #12
    Thanks for the replies...

    azizny... yes we have a DB with our connection. I didn't want to use the DB for counters. I will take a look at your perl script.

    hiryuu... my hosting plan is windows

  13. #13
    Originally posted by hiryuu
    It will miss counts, since concurrent requests can read the same number during the read stage.

    open CNT, '+<filename.txt';
    flock(CNT, 2);
    $count = <CNT>;
    $count++;
    seek(CNT, 0, 0);
    print CNT $count;
    close(CNT);

    This will not create the file for you, but it's otherwise one clean operation, locked the whole way through.
    I tried the above code, but all I get is 1. My code is below...

    open CNT, '+<$file';
    flock(CNT, 2);
    $count = <CNT>;
    $count++;
    seek(CNT, 0, 0);
    print CNT $count;
    close(CNT);

  14. #14
    Join Date
    Jan 2003
    Posts
    1,715
    My mistake:
    open CNT, "+<$file";

    The file name wasn't a variable in the code I grabbed, so I used single quotes.
    Game Servers are the next hot market!
    Slim margins, heavy support, fickle customers, and moronic suppliers!
    Start your own today!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •