Subject: Developers of Sympa
List archive
- From: IKEDA Soji <address@concealed>
- To: address@concealed
- Subject: Re: [sympa-developpers] Lock problem?
- Date: Mon, 5 Aug 2013 01:11:18 +0900
Hi,
Though direct use of File::NFSLock is possible, I wrote a small
module wrapping it. Some notes:
o The feature File::NFSLock argues support for NFS is anticipating
cache of filesystem. It may make lock processing a bit less
efficient on local filesystems.
o Current Sympa::Lock takes care of upgrading "read" locking to
"write" one (shared to exclusive), but it seems not to be used.
So my module doesn't implement it.
o Sympa::Lock::lock() is non-blocking, namely, it won't wait
competing lock and fails immediately. This module follows this
feature, but it can be discussed.
Regards,
--- Soji
On Tue, 23 Jul 2013 19:36:21 +0200
Guillaume Rousse <address@concealed> wrote:
> Le 23/07/2013 18:40, IKEDA Soji a écrit :
> > "Hardlink magic" (I named it) is, as I understood:
> > (1) There may be only one main lock file (i-node) by each target
> > file;
> > (2) Each proccess or routine creates a hardlink to the file above
> > so that add shared-lock to the target file, and unlink it to
> > unlock target file;
> > (3) When the main lock file does not have hardlinks anymore,
> > it is removed from filesystem by the kernel.
> >
> > - Lock file will be removed by kernel automatically.
> > - As lock files may exist independent from target files, forward
> > locking is possible.
> > - As hardlink is usual thing on Unix-like systems, it may work
> > on environmets not limited to NFS.
> Despite my initial understanding, the module name actually means
> 'NFS-compatible' locking, not 'NFS-based' locking.
>
> It seems to be light and easily readable, so I'm OK for the change. And
> a full replacement for Sympa::Lock, instead of an underlying mechanism
> for this class. As they work the same way ((maintaining a 'foo.NFSlock'
> file whose existence is enough to advertise 'foo' is currently locked),
> so I don't see much point in encapsulating it in our custom API.
>
> --
> Guillaume Rousse
> INRIA, Direction des systèmes d'information
> Domaine de Voluceau
> Rocquencourt - BP 105
> 78153 Le Chesnay
> Tel: 01 39 63 58 31
>
--
株式会社 コンバージョン セキュリティ&OSSソリューション部 池田荘児
〒231-0004 神奈川県横浜市中区元浜町3-21-2 ヘリオス関内ビル7F
e-mail address@concealed TEL 045-640-3550
http://www.conversion.co.jp/
# -*- indent-tabs-mode: t; -*-
# vim:ft=perl:noet:sw=8:textwidth=78
# $Id$
# Sympa - SYsteme de Multi-Postage Automatique
# Copyright (c) 1997, 1998, 1999, 2000, 2001 Comite Reseau des Universites
# Copyright (c) 1997,1998, 1999 Institut Pasteur & Christophe Wolfhugel
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses>.
=head1 NAME
Sympa::LockedFile - Filehandle with locking
=head1 SYNOPSIS
use Sympa::LockedFile;
# Create filehandle acquiring lock.
my $fh = Sympa::LockedFile->new('/path/to/file', 1200, '+<') or die;
# or,
my $fh = Sympa::LockedFile->new();
$fh->open('/path/to/file', 1200, '+<') or die;
# Operations...
while (<$fh>) { ... }
seek $fh, 0, 0;
truncate $fh, 0;
print $fh "blah blah\n";
# et cetera.
# Close filehandle releasing lock.
$fh->close;
=head1 DESCRIPTION
This class implements a filehadle with locking.
=cut
package Sympa::LockedFile;
use strict;
use warnings;
use Carp qw(croak);
use English qw(-no_match_vars);
use Fcntl qw(LOCK_EX LOCK_NB LOCK_SH);
use File::NFSLock;
use Sympa::Log::Syslog;
use base qw(IO::File);
our %locks;
my $default_timeout = 60 * 20; # After this period a lock can be stolen
=head2 Class Method
=over
=item Sympa::LockedFile->new ( [ $path, [ $timeout, [ $mode ] ] ] )
Creates new object.
If any of optional parameters are specified, opens a file acquiring lock.
Parameters:
See open().
Returns:
New object or, if something went wrong, false value.
=back
=head2 Instance Methods
Instance of L<Sympa::LockedFile> supports the methods provided by L<IO::File>.
=over
=item $fh->open ( $path, [ $timeout, [ $mode ] ] )
Opens a file specified by $path acquiring lock.
Parameters:
=over
=item $path
Path of file to be locked and opened.
=item $timeout
If existing lock is older than this timeout (seconds), lock will be stolen.
Default is 1200, i.e. 20 minutes.
=item $mode
Mode to open file.
If it includes any writing operations (C<'E<gt>'>, C<'E<gt>E<gt>'>,
C<'+E<lt>'>, ...), trys to acquire exclusive lock (C<LOCK_EX>),
otherwise shared lock (C<LOCK_SH>).
Default is C<'E<lt>'>.
=back
Returns:
New filehandle.
If acquiring lock failed, won't open file.
If opening file failed, releases acquired lock.
In both cases returns false value.
=back
=cut
sub open {
Sympa::Log::Syslog::do_log('debug2', '(%s, %s, %s)', @_);
my ($self, $path, $timeout, $mode) = @_;
$timeout ||= $default_timeout;
$mode ||= '<';
my $hold = 30; #FIXME: seems ignored by LOCK_NB
my $operation;
if ($mode =~ /[+>aw]/) {
$operation = LOCK_EX;
} else {
$operation = LOCK_SH;
}
my $lock = File::NFSLock->new(
$path, $operation | LOCK_NB, $hold, $timeout
);
unless ($lock) {
Sympa::Log::Syslog::do_log('err',
'Failed locking %s: %s', $path, $ERRNO
);
return undef;
}
unless ($self->SUPER::open($path, $mode)) {
Sympa::Log::Syslog::do_log('err',
'Failed opening %s: %s', $path, $ERRNO
);
$lock->unlock; # make sure unlock to occur immediately.
return undef;
}
$locks{$self+0} = $lock; # register lock object, i.e. keep locking.
return 1;
}
=over
=item $fh->close ( )
Closes filehandle and releases lock on it.
Parameters:
None.
Returns:
If close succeeded, returns true value, otherwise false value.
If filehandle had not been locked by current process,
this method will safely close filehandle and die.
=back
=cut
sub close {
Sympa::Log::Syslog::do_log('debug2', '(%s)', @_);
my ($self) = @_;
my $ret = $self->SUPER::close;
croak 'Lock not found'
unless exists $locks{$self+0};
$locks{$self+0}->unlock; # make sure unlock to occur immediately.
delete $locks{$self+0}; # lock object will be destructed.
return $ret;
}
# Destruct inside reference to lock object to release it.
# Corresponding filehandle will automatically closed.
sub DESTROY {
delete $locks{shift+0}; # lock object will be destructed.
}
1;
__END__
=head1 SEE ALSO
L<perlfunc/Functions for filehandles, files or directories>.
L<IO::File>, L<File::NFSLock>.
=head1 AUTHORS
Sympa developers and contributors.
-
Re: [sympa-developpers] Lock problem?,
IKEDA Soji, 08/04/2013
- Re: [sympa-developpers] Lock problem?, Guillaume Rousse, 08/06/2013
Archive powered by MHonArc 2.6.19+.