X-Git-Url: https://git.p6c8.net/selfforum.git/blobdiff_plain/85946d0838c74882bd707bd1f5dbeeb7ea80944f..4efca15bb2136c3e226eb4e372776fad95a955c9:/selfforum-cgi/shared/Lock/_simple.pm diff --git a/selfforum-cgi/shared/Lock/_simple.pm b/selfforum-cgi/shared/Lock/_simple.pm new file mode 100644 index 0000000..7aae43a --- /dev/null +++ b/selfforum-cgi/shared/Lock/_simple.pm @@ -0,0 +1,351 @@ +package Lock::_simple; + +################################################################################ +# # +# File: shared/Lock/_simple.pm # +# # +# Authors: Andre Malo , 2001-05-25 # +# # +# Description: belongs to Locking and Filehandle class # +# NOT FOR PUBLIC USE # +# # +################################################################################ + +use strict; +use vars qw( + $VERSION +); + +use Fcntl; + +################################################################################ +# +# Version check +# +$VERSION = do { my @r =(q$Revision$ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; + +### sub _simple_esna ########################################################### +# +# simple file lock +# excl shared lock announced, no locking possible +# +# Params: $filename - filename +# $timeout - timeout +# +# Return: success code (boolean) +# +sub _simple_esna { + my ($self, $filename, $timeout) = @_; + my $fh = new Lock::Handle ($filename); + + for (0..$timeout) { + unless ($self -> exsh_announced) { + $self -> _simple_lock ($fh) and return 1; + } + sleep 1; + } + + # timeout + return; +} + +### sub _simple_ana ############################################################ +# +# simple file lock +# while excl lock announced, no locking possible +# +# Params: $filename - filename +# $timeout - timeout +# +# Return: success code (boolean) +# +sub _simple_ana { + my ($self, $filename, $timeout) = @_; + my $fh = new Lock::Handle ($filename); + + for (0..$timeout) { + unless ($self -> excl_announced) { + $self -> _simple_lock ($fh) and return 1; + } + sleep 1; + } + + # timeout + return; +} + +### sub _simple_aa ############################################################# +# +# simple file lock +# while excl lock announced, locking is possible +# +# Params: $filename - filename +# $timeout - timeout +# +# Return: success code (boolean) +# +sub _simple_aa { + my ($self, $filename, $timeout) = @_; + my $fh = new Lock::Handle ($filename); + + for (0..$timeout) { + $self -> _simple_lock ($fh) and return 1; + sleep 1; + } + + # timeout + return; +} + +### sub es_add_ref ############################################################# +# +# increase shared lock reference counter +# (for excl shared lock) +# +# Params: $timeout - timeout +# +# Return: success code (boolean) +# +sub es_add_ref { + my ($self, $timeout) = @_; + + # lock reference counter file + # increase reference counter + # set excl shared lock + # release ref. counter file + # + return unless($self -> _simple_esna ($self->reflock, $timeout)); + $self -> set_ref ($self -> get_ref + 1) or return; + $self -> set_exsh_announce or return; + $self -> _simple_unlock ($self -> reflock) or return; + + # successfully done + 1; +} + +### sub es_sub_ref ############################################################# +# +# decrease shared lock reference counter +# (of an excl shared locked file) +# +# Params: $timeout - timeout +# +# Return: success code (boolean) +# +sub es_sub_ref { + my ($self, $timeout) = @_; + + # lock reference counter file + # increase reference counter + # release ref. counter file + # + return unless($self -> _simple_aa ($self->reflock, $timeout)); + $self -> set_ref ($self -> get_ref - 1) or return; + $self -> remove_exsh_announce; + $self -> _simple_unlock ($self -> reflock) or return; + + # successfully done + 1; +} + +### sub add_ref ################################################################ +# +# increase shared lock reference counter +# +# Params: $timeout - timeout +# +# Return: success code (boolean) +# +sub add_ref { + my ($self, $timeout) = @_; + + # lock reference counter file + # increase reference counter + # release ref. counter file + # + return unless($self -> _simple_ana ($self->reflock, $timeout)); + $self -> set_ref ($self -> get_ref + 1) or return; + $self -> _simple_unlock ($self -> reflock) or return; + + # successfully done + 1; +} + +### sub sub_ref ################################################################ +# +# decrease shared lock reference counter +# +# Params: $timeout - timeout +# +# Return: success code (boolean) +# +sub sub_ref { + my ($self, $timeout) = @_; + + # lock reference counter file + # increase reference counter + # release ref. counter file + # + return unless($self -> _simple_aa ($self->reflock, $timeout)); + $self -> set_ref ($self -> get_ref - 1) or return; + $self -> _simple_unlock ($self -> reflock) or return; + + # successfully done + 1; +} + +### sub get_ref ################################################################ +# +# read out the reference counter +# NO LOCKING HERE! +# +# Params: ~none~ +# +# Return: counter value +# +sub get_ref { + my $self = shift; + my ($fh, $val) = new Lock::Handle ($self -> reffile); + + { + local $/; + sysopen ($fh, $fh->filename, O_RDONLY) or return 0; + $val = <$fh>; + close $fh; + } + + # return value + # + $val; +} + +### sub set_ref ################################################################ +# +# write reference counter into file +# NO LOCKING HERE! +# +# Params: counter value +# +# Return: success code (boolean) +# +sub set_ref { + my ($self, $val) = @_; + my $fh = new Lock::Handle ($self -> reffile); + + if ($val == 0) { + if (-f $fh->filename) { + unlink $fh->filename or return; + } + } + else { + local $\; + sysopen ($fh, $fh->filename, O_WRONLY | O_TRUNC | O_CREAT) or return; + print $fh $val or do { + close $fh; + unlink $fh->filename; + return; + }; + + close $fh or do { + unlink $fh->filename; + return; + }; + } + + # successfully done + # + 1; +} + +### sub set_excl_announce ###################################################### +# +# try to announce an exclusive lock +# +# Params: ~none~ +# +# Return: status (boolean) +# +sub set_excl_announce { + my $self = shift; + + if ($self -> excl_announced) { + return ($self -> announced) ? 1 : return; + } + + if ($self -> _simple_lock (new Lock::Handle ($self -> lockfile))) { + $self -> set_static (announced => 1); + return 1; + } + + return; +} + +### sub remove_excl_announce ################################################### +# +# remove announce of an exclusive lock, if it's set by ourself +# +# Params: ~none~ +# +# Return: ~none~ +# +sub remove_excl_announce { + my $self = shift; + + if ($self -> excl_announced and $self -> announced) { + $self -> _simple_unlock ($self -> lockfile); + } + + $self -> set_static (announced => 0); + + return; +} + +### sub set_exsh_announce ###################################################### +# +# try to announce an exclusive shared lock +# +# Params: ~none~ +# +# Return: status (boolean) +# +sub set_exsh_announce { + my $self = shift; + + if ($self -> exsh_announced) { + return ($self -> es_announced) ? 1 : return; + } + + if ($self -> _simple_lock (new Lock::Handle ($self -> exshlock))) { + $self -> set_static (es_announced => 1); + return 1; + } + + return; +} + +### sub remove_exsh_announce ################################################### +# +# remove an exclusive shared lock, if it's set by ourself +# +# Params: ~none~ +# +# Return: ~none~ +# +sub remove_exsh_announce { + my $self = shift; + + if ($self -> exsh_announced and $self -> es_announced) { + $self -> _simple_unlock ($self -> exshlock); + } + + $self -> set_static (es_announced => 0); + + return; +} + +# keep 'require' happy +1; + +# +# +### end of Lock::_simple ####################################################### \ No newline at end of file