package KinoSearch::Store::FSLock; use strict; use warnings; use KinoSearch::Util::ToolSet; use base qw( KinoSearch::Store::Lock ); BEGIN { __PACKAGE__->init_instance_vars() } use Fcntl qw( :DEFAULT :flock ); use File::Spec::Functions qw( catfile ); use KinoSearch::Store::FSInvIndex; my $disable_locks = 0; # placeholder -- locks always enabled for now sub init_instance { my $self = shift; # derive the lockfile's filepath $self->{lock_name} = catfile( $KinoSearch::Store::FSInvIndex::LOCK_DIR, # TODO fix this stupid hack $self->{invindex}->get_lock_prefix . "-$self->{lock_name}" ); } sub do_obtain { my $self = shift; return 1 if $disable_locks; my $lock_name = $self->{lock_name}; # check for locks created by old processes and remove them if ( -e $lock_name ) { open( my $fh, $lock_name ) or confess "Can't open $lock_name: $!"; my $line = <$fh>; $line =~ /pid: (\d+)/; my $pid = $1; close $fh or confess "Can't close '$lock_name': $!"; unless ( kill 0 => $pid ) { warn "Lockfile looks dead - removing"; unlink $lock_name or confess "Can't unlink '$lock_name: $!"; } } # create a lock by creating a lockfile return unless sysopen( my $fh, $lock_name, O_CREAT | O_WRONLY | O_EXCL ); # print pid and path to the lock file, using YAML for future compat print $fh "pid: $$\ninvindex: " . $self->{invindex}->get_path . "\n"; close $fh or confess "Can't close '$lock_name': $!"; # success! return 1; } sub release { my $self = shift; return if $disable_locks; # release the lock by removing the lockfile from the file system unlink $self->{lock_name} or confess("Couldn't unlink file '$self->{lock_name}': $!"); } sub is_locked { # if the lockfile exists, the resource is locked return ( -e $_[0]->{lock_name} or $disable_locks ); } 1; __END__ =begin devdocs =head1 NAME KinoSearch::Store::FSLock - lock an FSInvIndex =head1 DESCRIPTION File-system-based implementation of L. =head1 COPYRIGHT Copyright 2005-2009 Marvin Humphrey =head1 LICENSE, DISCLAIMER, BUGS, etc. See L version 0.165. =end devdocs =cut