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

Hi, Im worried that 2 users could pick up the same ID number from a COUNT file when adding articles. The problem is I want each article added to have a unique ID file. I presume I have to first open the COUNT file, get the current number, then re-open the COUNT file in order to write the current number +1 back to it. I feel there's an easier way to do this however as I'm completely stupid. Am I doing the following right?
#GET CURRENT NUMBER open(FH, "counter.dat"); flock(FH, 1); $id = <FH>; close(FH); #INCREASE COUNT $id++; #WRITE NUMBER BACK open(FH, "+< counter.dat"); flock(FH, 2); seek(FH, 0, 0); truncate(FH, 0); print FH $id; close(FH);
With the method up above I was worried that the second user could still pick up the same ID file from the first read of the COUNT file before the first user had actually written the updated number back to it. Any ideas?

ThAtH0M

Replies are listed 'Best First'.
Re: Flock Updating Counter
by busunsl (Vicar) on Dec 06, 2002 at 10:42 UTC
    You have the solution in your code:

    #WRITE NUMBER BACK open(FH, "+< counter.dat");
    This opens the file for reading and writing, so this should work:

    #READ NUMBER, INCREASE AND WRITE NUMBER BACK open(FH, "+< counter.dat"); flock(FH, 2); $id = <FH>; $id++; seek(FH, 0, 0); truncate(FH, 0); print FH $id; close(FH);
Re: Flock Updating Counter
by Zaxo (Archbishop) on Dec 06, 2002 at 10:54 UTC

    You should simplify your code to only open the counter once. Otherwise you have a race condition.

    open FH, "+< counter.dat" or die $!; flock(FH, 2); $id = <FH>; $id++; seek(FH, 0, 0); truncate(FH, 0); print FH $id or die $!; close FH or die $!;

    It would be more elegant to use a database with an autoincrementing key.

    After Compline,
    Zaxo

•Re: Flock Updating Counter
by merlyn (Sage) on Dec 06, 2002 at 17:41 UTC
Re: Flock Updating Counter
by jreades (Friar) on Dec 06, 2002 at 11:29 UTC

    There are also a number of locking modules that might help you (if this snippet is part of a larger script and not something quick and dirty):

    http://search.cpan.org/search?query=File+locking&mode=all

    LockFile::Simple especially can be quite handy -- it's very lightweight, however, and on the whole a database is a better way to handle this type of thing (unless the overhead is unecessary).

    But the general answer is that you want to hold on to the lock until you're done writing out the new id and not grab one, release it after a read, then grab it again. Also, if you're using flock() it seems like you want an exclusive lock since you don't want another process to read the id value until it has been updated.

Re: Flock Updating Counter
by Chief of Chaos (Friar) on Dec 06, 2002 at 12:33 UTC
    Or may take a look at How to apply flock.

    Important : The filelock is gone, when you close the filehandle.