File::Lock::Multi::Fuser - Lock files based on how many times they are open


File-Lock-Multi documentation Contained in the File-Lock-Multi distribution.

Index


Code Index:

NAME

Top

File::Lock::Multi::Fuser - Lock files based on how many times they are open

DESCRIPTION

Top

This module provides a linux-specific concurrent locking mechanism. It uses the /proc filesystem to determine how many times a lockfile is open, and counts each open filehandle as a "lock". Locks are obtained by opening the given lockfile in append mode, which means that if the file does not exist when you attempt to gain (or check for) a lock, it will be created.

CAVEATS

Top

File::Lock::Multi::Fuser makes use of Linux::Fuser to obtain the list of processes that have opened the file -- it then looks in /proc to see how many times each process has the file opened. There is a ticket opened with the Linux::Fuser manpage (http://rt.cpan.org/Public/Bug/Display.html?id=43979) requesting that the latter functionality be added there.

File::Lock::Multi::Fuser considers any filehandle that is opened on your lockfile (read or write, flock'ed or not) to be a "lock". There is a /proc extension ("fdinfo") that can give more detailed information about what processes are doing with your files, so options may be added to refine this in the future.

Since the "fd" directories in the /proc filesystem are protected, you can only "see" locks if you are root, or the locks have been taken out by processes that match your userid.

LICENSE

Top

Copyright 2009 Tyler "Crackerjack" MacDonald <japh@crackerjack.net>

This is free software; You may distribute it under the same terms as perl itself.

SEE ALSO

Top

File::Lock::Multi, Linux::Fuser


File-Lock-Multi documentation Contained in the File-Lock-Multi distribution.

#!perl

package File::Lock::Multi::Fuser;

use strict;
use warnings (FATAL => 'all');

use File::Lock::Multi;
use base q(File::Lock::Multi);

use Linux::Fuser 1.5;
use Carp q(croak);

__PACKAGE__->mk_accessors(qw(_fuser _fh));

return 1;

sub new {
  my $class = shift;
  my $self = $class->SUPER::new(@_);
  $self->_fuser(Linux::Fuser->new());
  return $self;
}

sub locked {
  my $self = shift;
  return $self->_fh ? 1 : 0;
}

sub lockers {
  my $self = shift;
  my @procs = $self->_fuser->fuser($self->file);
  my @ids;
  foreach my $proc (@procs) {
    my $id = $proc->pid;
    my $fd = $proc->filedes->fd;
    push(@ids, "$id:$fd");
  }
  return @ids;
}

sub _release {
  my $self = shift;
  $self->_fh->close;
  $self->_fh(undef);
  return 1;
}

sub _lock {
  my $self = shift;
  if(open(my $fh, '>>', $self->file)) {
    my $fn = fileno($fh);
    my $id = "$$:$fn";
    $self->_fh($fh);
    return $id;
  } else {
    croak "open ", $self->file, " for write: $!";
  }
}

__END__