John McKown wrote:
>
> I have a bit of a problem and I'm wondering if there is a better solution.
> I have a Perl program (of course) which reads STDIN and breaks it into
> separate files based on a "report separator". I can construct an
> appropriate file name based on information in the "trailing" separator.
> I.e. I don't know the name of the report until the report is complete.
> What I am doing at present is using the routine 'tempfile' in the
> File::Temp package to create a unique file in the output directory.  Once
> I get the report name from the "trailer" separator, I want to rename this
> file to the correct name. However, it is possible that there will be
> multiple, different reports coming in which have the same name. So, what I
> want to do is put a "sequence number" as the last node in the file name.
> This means that I must generate a test file name, then see if that file
> already exists. If it does, increment the sequence number, generate a new
> test file name and loop. Oh, did I mention that it is possible for this
> program to have several copies all running at the same time, possibly
> producing different reports with identical names? So I must worry about
> "race" conditions. My code, so far, looks like:
>
> # $fn contains the file name generated by 'tempname'
> # $report contains the report name
> my ($number,$test);
> for ($number=1;;$number++) {
> $test = "$report.$number";
> last if sysopen JUNK, $test, O_WRONLY|O_EXCL|O_CREAT;
> }
> close JUNK;
> mv($fn,$test);
>
> Using sysopen with those parameters, especially O_EXCL, is the only way
> that I can think to ensure that the name in $test does not exist and is
> created "atomically" so that no other incarnation of this program which
> happens to be running at the same time will exit the for loop with the
> same value in $test.  I then close this file (now a 0 length file). I then
> use the "mv" function from File::Copy to rename my real data file to the
> new name, replacing the 0 length file.
>
> This is running on Linux. I don't know if the sysopen can guarantee the
> "atomicity" of sysopen on other platforms.

As far as I know 'rename' is atomic, so:

  my $number;

  do {
    $number++;
    my $test = "$report.$number";
  } until rename $fn, $test;

HTH,

Rob



-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to