| File-Lock-Multi documentation | Contained in the File-Lock-Multi distribution. |
File::Lock::Multi - Lock files more than once
use File::Lock::Multi::Fuser; my $lock = File::Lock::Multi::Fuser->new(name => "/path/to/file", max => 3); $lock->lock or die; # no more than 3 locks have been taken out on "/path/to/file" [...]
flock() (flock in perlfunc) (and co-operative locks in general) are a handy tool used for various synchronization tasks;
POSIX supports the concept of "exclusive" ("write") and "shared" ("read") locks on files -- many processes may take out a "shared" lock on any particular file, but only one process may have an "exclusive" lock, and that process can not take out this lock unless there are no "shared" locks open.
Part of what makes this such an effective and worry-free system, is that these locks are maintained on the kernel level -- so if you kill off a process, you do not need to be concerned that the locks it had will stick around and get in some other process's way.
... But let's say you have a CPU-intensive operation that you want to limit to, oh, 5 running copies at a time? Or 3 different types of CPU-intensive operation that you want to collectively limit to 2 running copies at a time? You could keep a counter somewhere, but if processes are killed off manually, what is going to come along and decrement your counter?
"exclusive" locks are just that -- exclusive -- and there is no simple way to tell how many processes have taken out a "shared" lock on a file (from perl, anyway).
File::Lock::Multi is designed to work around this problem by providing
it's own type of "locks" that behave like POSIX "exclusive" locks, except
that you can specify how many locks are allowed to be taken out. So long
as each process agrees on the maximum number of locks, they can work in
parallel, but within the limits you have specified.
There are three locking mechanisms available; File::Lock::Multi::Fuser
allows you to have multi-locks using just one file, but only works on linux
and has some drawbacks (see the documentation for details);
File::Lock::Multi::FlockFiles uses the flock() call on several files
named after the file you specify in order to emulate allowing more than one
lock. File::Lock::Multi::MySQL allows you to use a MySQL backend to
take out multiple locks on a resource that is shared across multiple servers,
using MySQL's GET_LOCK function.
Creates a new File::Lock::Multi object, which will represent a lock
on a file. Once you have an object, you can attempt to aquire a lock
with the "lock" method; the lock will be relinquished when you call
the "release" method, or when the object falls out of scope.
Note that you cannot call new directly on File::Lock::Multi, you
must do so on a particular implementation such as
File::Lock::Multi::Fuser or File::Lock::Multi::MySQL
"new" takes the following parameters; only "file" is required:
The name of the resource you wish to lock; this parameter is required. When dealing with files, if the file does not already exist, a zero-byte file will be created when you attempt to acquire the lock with lock.
This parameter is required.
The maximum number of lockers that may lock this file.
Default: 1
How long to wait to acquire the lock, in seconds. A value of zero means don't wait at all, and a negative value means to wait forever (block).
Default: -1 (wait forever).
How often to check if the lock is available when waiting, in seconds.
For example, if "timeout" was set to "5", and "polling_interval" was
set to "0.5", File::Lock::Multi would try to obtain the lock
every half a second, up to a maximum of five seconds, before giving up.
Default: 0.2 (1/5th of a second).
Acquire a lock, obeying timeout and polling_interval above. Returns a true value on success, or a false value if the the lock could not be acquired in time.
This method actually works by taking out the lock anyway, and then checking if there are too many lockers -- if there are too many lockers, it releases the lock, and optionally waits for polling_interval and tries again.
If $timeout is specified, this overrides the object's default.
Returns a true value if an attempt to take out the lock would succeed. This method works by calling lock with a timeout of zero (non-blocking), then immediately releases the lock if it obtained one.
Returns true if this lock is active, false otherwise.
Release a lock if we have taken one out. Raises an exception if we have not.
Returns an array with an entry for each entity that has locked this file. Presumedly each entry in the array is some sort of identifier indicating _who_ has locked this file, but that would be implementation specific. :-)
Copyright 2010 Tyler "Crackerjack" MacDonald <japh@crackerjack.net>
This is free software; You may distribute it under the same terms as perl itself.
File::Lock::Multi::Fuser for technical details about the linux /proc implementation.
File::Lock::Multi::FlockFiles for technical details about the multiple-file implementation.
l<File::Lock::Multi::MySQL> for technical details about the MySQL implementation.
IPC::Locker for a network-based locking solution that may help if you don't want to use MySQL for distributed locking ("Multiple locks may be requested, in which case the first lock to be free will be used.")
| File-Lock-Multi documentation | Contained in the File-Lock-Multi distribution. |
package File::Lock::Multi; use 5.006000; use strict; use warnings (FATAL => 'all'); use File::Lock::Multi::Base; use base q(File::Lock::Multi::Base); our $VERSION = '1.01'; return 1; __END__