Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

file reading / writing collisions

by simonodell (Acolyte)
on Sep 11, 2007 at 03:24 UTC ( [id://638209]=perlquestion: print w/replies, xml ) Need Help??

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

All-knowing monks

I have these two routines;
sub getFile { my $fileName = shift(@_); unless ($gotFiles->{$fileName}) { undef $/; open $file, $fileName; my $buf = <$file>; close $file; $gotFiles->{$fileName} = $buf; } return $gotFiles->{$fileName}; } sub writeFile { my $data = shift(@_); if ($data =~ m@<filename>(.*?)</filename>@s) { $filename = $1; } if ($data =~ m@<data>(.*)</data>@s) { $filedata = $1; } open(DAT,">$ENV{DOCUMENT_ROOT}/$filename") || return 0; print DAT $filedata; close(DAT); $gotFiles->{"$ENV{DOCUMENT_ROOT}/$filename"} = $filedata; return 1; }
My question is, how should I modify these in order to avoid lockups when multiple users are attempting to read/write the same files? is there some way perhaps to shunt off the writing to a background process?

Replies are listed 'Best First'.
Re: file reading / writing collisions
by ikegami (Patriarch) on Sep 11, 2007 at 04:37 UTC
    • Uses flock to handle multiple users.
    • Added use strict;, which revealed many errors.
    • Stopped using globals for every variable.
    • Localized changes to required globals.
    • Fixed bug where $filename and $filedata weren't always defined.
    • Used safer 3-arg open.
    • Used or instead of || when used instead of if.
    use strict; use warnings; use Fcntl ':flock'; # Import LOCK_* constants sub getFile { my $fileName = shift(@_); unless (defined $gotFiles->{$fileName}) { local $/; open(my $fh, '<', $fileName) or die; flock($fh, LOCK_SH) or die; $gotFiles->{$fileName} = <$fh>; # File handle automatically closed and unlocked here. } return $gotFiles->{$fileName}; } sub writeFile { my $data = shift(@_); my ($filename) = $data =~ m@<filename>(.*?)</filename>@s or return 0; my ($filedata) = $data =~ m@<data>(.*)</data>@s or return 0; { open(my $fh, '>', "$ENV{DOCUMENT_ROOT}/$filename") or return 0; flock($fh, LOCK_EX) or return 0; print $fh $filedata; # File handle automatically closed and unlocked here. } $gotFiles->{"$ENV{DOCUMENT_ROOT}/$filename"} = $filedata; return 1; }
      Thanks! just for the sake of curiosity, what happens now when a multiple file write occurs? I mean does the routine simply return 0 or does it wait for the file handle to be available and then write? is there some way to have the routine order a background write in the case of a locked file, so the rest of the script can carry on with what its doing.. or is that a bad idea??

        Well you have to test for your system, but usually perl's flock will block, and you are right it's a problem as you might end up with too many processes! I prefer non-blocking handles and do the polling myself. 'perldoc -f fcntl' will tell you how to set up non-blocking flags.

        cheers --stephan

        flock: "it waits indefinitely until the lock is granted"

        I don't know of an easy to do what you want without polling. From the looks of it though, your locks are really short lived, so it should not be a problem.

        Update: s/should be/should not be/

Re: file reading / writing collisions
by kyle (Abbot) on Sep 11, 2007 at 03:30 UTC

    This is usually done with flock. You want to get a shared lock for reading (which means you can have any number of processes reading the file at once) and an exclusive lock for writing (which means no other process can read or write at the same time).

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2024-04-18 11:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found