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

I'm having a difficult time getting NFSLock to work as I understand it through the documentation. I was able to get the example "lock_test" provided with the CPAN module to correctly work simultaneously on 4 servers using NFS file system so

However, what I need to do is determine if a server can get an NFSLock on a new file- and if so I need the server to create and lock it, and write to it. If it is unable to get the lock, simply have the server move on. I could have up to 50 servers trying to determine if the file exists, but only need one of them to create it. The "README" file that comes with the module states "Blocking locks will wait until other locks are removed before the process continues. Non blocking locks will return undef if another process currently has the lock." It seemed to me that if I simply changed the code from "LOCK_EX" to "LOCK_NB" that this would do what I need but this isn't the case. Instead, two things happen 1) NONE of the servers are able to ever get an NFSLock, and 2)hundreds if not thousands of "tmp" files are created (depending on the increment I choose) in the directory and not removed.

Am I using this module incorrectly or missing something? I also know through research that the NFS system can be troublesome, but it seemed that occurred for older versions of NFS, and finding this module gave me hope that I'd be able to do what I need. For the code given, I just change the line comment for the "my $lock"

command line: ./my_lock_test.pl nfs_lock_test.txt 1000 > server_A.out

#!/usr/bin/perl5.10.1 -w use strict; use File::NFSLock (); use Fcntl qw( O_CREAT LOCK_EX LOCK_NB); use lib '../lib/perl/'; my $datafile = shift; my $inc = shift || do { print "Usage: $0 <filename> <increment>\n"; exit; }; while ( $inc -- > 0 ) { my $lock = new File::NFSLock ($datafile, LOCK_NB); #my $lock = new File::NFSLock ($datafile, LOCK_EX); if ($lock) { print "true\n"; } else { print "false\n"; } }
  • Comment on NFSLock - Continue in code if another server already has lock on file
  • Download Code

Replies are listed 'Best First'.
Re: NFSLock - Continue in code if another server already has lock on file (updated)
by haukex (Archbishop) on Jan 11, 2017 at 09:55 UTC

    Hi mightyMrJawz,

    I could have up to 50 servers trying to determine if the file exists

    To be honest, it really sounds like you need a database instead. Update: Note this quote from the File::NFSLock documentation: "Locks are not necessarily obtained on a first come first serve basis. Not only does this not seem fair to new processes trying to obtain a lock, but it may cause a process starvation condition on heavily locked files."

    changed the code from "LOCK_EX" to "LOCK_NB"

    AFAIK LOCK_NB is an option that is needed in addition to either LOCK_EX or LOCH_SH (Update: see also flock). See the example code at the top of File::NFSLock (I trimmed it down slightly):

    use File::NFSLock; use Fcntl qw(LOCK_EX LOCK_NB); my $file = "somefile"; if (my $lock = new File::NFSLock { file => $file, lock_type => LOCK_EX|LOCK_NB, blocking_timeout => 10, # 10 sec stale_lock_timeout => 30 * 60, # 30 min }) { open(FILE, "+<$file") || die $!; # or open it any way you like # ... $lock->unlock(); }else{ die "I couldn't lock the file [$File::NFSLock::errstr]"; }

    Instead of dieing, you would let your code continue.

    BTW, there seems to be something wrong with the <code> tags in your post. Perhaps you could edit your node to fix that.

    Hope this helps,
    -- Hauke D

      Thanks for the input haukex. Making the change you suggested seems to have resolved my issue. My assumption was that the lock_type was a singular input- which I now know was incorrect. For various reasons, a database wouldn't work well for my situation, and I'm not worried about a first come first serve basis. For the simple code change, I used:

      my $lock = new File::NFSLock ($datafile, LOCK_EX|LOCK_NB);