]> git.p6c8.net - selfforum.git/commitdiff
added submodules of new Lock.pm
authorndparker <>
Wed, 20 Jun 2001 20:34:11 +0000 (20:34 +0000)
committerndparker <>
Wed, 20 Jun 2001 20:34:11 +0000 (20:34 +0000)
selfforum-cgi/shared/Lock/API.pm [new file with mode: 0644]
selfforum-cgi/shared/Lock/Exclusive.pm [new file with mode: 0644]
selfforum-cgi/shared/Lock/Handle.pm [new file with mode: 0644]
selfforum-cgi/shared/Lock/Symlink.pm [new file with mode: 0644]
selfforum-cgi/shared/Lock/Unlink.pm [new file with mode: 0644]
selfforum-cgi/shared/Lock/_simple.pm [new file with mode: 0644]
selfforum-cgi/shared/Lock/_static.pm [new file with mode: 0644]

diff --git a/selfforum-cgi/shared/Lock/API.pm b/selfforum-cgi/shared/Lock/API.pm
new file mode 100644 (file)
index 0000000..21f3ecf
--- /dev/null
@@ -0,0 +1,288 @@
+package Lock::API;
+
+################################################################################
+#                                                                              #
+# File:        shared/Lock/API.pm                                              #
+#                                                                              #
+# Authors:     Andre Malo       <nd@o3media.de>, 2001-05-25                    #
+#                                                                              #
+# Description: system independent part of Locking and Filehandle class         #
+#              NOT FOR PUBLIC USE                                              #
+#                                                                              #
+################################################################################
+
+use strict;
+use vars qw(
+  $VERSION
+);
+
+use Carp;
+
+use base qw(
+  Lock::Handle
+  Lock::_simple
+);
+
+################################################################################
+#
+# Version check
+#
+$VERSION = do { my @r =(q$Revision$ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
+
+### sub lock ###################################################################
+#
+# set a lock on the file
+#
+# Params: $locktype - what kind of locking?
+#         $timeout  - (optional) Timeout
+#
+# Return: success (boolean)
+#
+sub lock {
+  my $self = shift;
+  my $locktype = shift;
+
+  return if $self -> masterlocked;
+
+  ###########################################
+  # shared lock
+  #
+  if ($locktype == $self -> LH_SHARED) {
+    return 1 if $self -> locked_shared;
+    return   if $self -> locked_exclusive;
+
+    my $timeout  = shift || $self -> timeout ('shared');
+
+    # try to increase the reference counter
+    #
+    if ($self -> add_ref($timeout)) {
+      $self -> set_static (locked_shared => 1);
+      return 1;
+    }
+  }
+
+
+  ###########################################
+  # exclusive lock
+  #
+  elsif ($locktype == $self -> LH_EXCL) {
+    return 1 if $self -> locked_exclusive;
+
+    my $timeout  = shift || $self -> timeout ('exclusive');
+
+    #####################
+    # transform exclusive shared lock into exclusive lock
+    #
+    if ($self -> locked_exsh) {
+      my $reflock = new Lock::Handle ($self -> reflock);
+
+      for (0..$timeout) {
+        if ($self -> set_excl_announce and $self -> _simple_lock ($reflock)) {
+          if ($self -> get_ref == 1) {
+            $self -> set_ref(0);
+            $self -> remove_exsh_announce;
+            $self -> set_static (locked_exsh      => 0);
+            $self -> set_static (locked_exclusive => 1);
+            return 1;
+          }
+
+          last unless ($self -> _simple_unlock ($reflock->filename));
+        }
+
+        sleep 1;
+      }
+      $self -> remove_excl_announce;
+    }
+
+    #####################
+    # set exclusive lock
+    #
+    else {
+      my $reflock = new Lock::Handle ($self -> reflock);
+
+      for (0..$timeout) {
+        if ($self -> set_excl_announce and $self -> _simple_lock ($reflock)) {
+          if ($self -> get_ref == 0) {
+            $self -> set_static (locked_exclusive => 1);
+            return 1;
+          }
+
+          last unless ($self -> _simple_unlock ($reflock->filename));
+        }
+
+        sleep 1;
+      }
+      $self -> remove_excl_announce;
+    }
+  }
+
+
+  ###########################################
+  # exclusive shared lock
+  #
+  elsif ($locktype == $self -> LH_EXSH) {
+    return 1 if $self -> locked_exsh;
+    return   if ($self -> locked_shared or $self -> locked_exclusive);
+
+    my $timeout  = shift || $self -> timeout ('shared');
+
+    # try to increase the reference counter
+    #
+    if ($self -> es_add_ref($timeout)) {
+      $self -> set_static (locked_exsh => 1);
+      return 1;
+    }
+  }
+
+
+  ###########################################
+  # master lock
+  #
+  elsif ($locktype == $self -> LH_MASTER) {
+    $self -> lock ($self->LH_EXCL, $self -> timeout('master'))   and
+    $self -> _simple_lock (new Lock::Handle ($self->masterlock)) and
+    return 1;
+  }
+
+  ###########################################
+  # unknown locking type
+  #
+  else {
+    croak "unknown locking type '$locktype'";
+  }
+
+  # timeout
+  #
+  $self -> unlock_violent;
+  return;
+}
+
+### sub unlock #################################################################
+#
+# remove shared or exclusive lock
+#
+# Params: $timeout - (optional) Timeout
+#
+# Return: success (boolean)
+#
+sub unlock {
+  my $self = shift;
+  my $timeout = shift || $self -> timeout ('shared');
+
+  return if $self -> masterlocked;
+
+  ###########################################
+  # shared lock
+  #
+  if ($self -> locked_shared) {
+    # try to decrease the reference counter
+    #
+    if ($self -> sub_ref($timeout)) {
+      $self -> set_static (locked_shared => 0);
+      return 1;
+    }
+  }
+
+
+  ###########################################
+  # exclusive lock
+  #
+  elsif ($self -> locked_exclusive) {
+    my $reflock = new Lock::Handle ($self -> reflock);
+
+    for (0..$timeout) {
+      if ($self -> _simple_unlock ($reflock->filename)) {
+        $self -> remove_excl_announce;
+        $self -> set_static (locked_exclusive => 0);
+        return 1;
+      }
+
+      sleep 1;
+    }
+  }
+
+
+  ###########################################
+  # exclusive shared lock
+  #
+  elsif ($self -> locked_exsh) {
+    # try to decrease the reference counter
+    #
+    if ($self -> es_sub_ref($timeout)) {
+      $self -> remove_exsh_announce;
+      $self -> set_static (locked_exsh => 0);
+      return 1;
+    }
+  }
+
+
+  ###########################################
+  # not locked
+  #
+  else {
+    return 1;
+  }
+
+  # unlocking failed
+  #
+  $self -> unlock_violent;
+  return;
+}
+
+### sub unlock_violent #########################################################
+#
+# remove any lock violently  (excludes master lock)
+#
+# Params: ~none~
+#
+# Return: -none- (the success is undefined)
+#
+sub unlock_violent {
+  my $self = shift;
+
+  unless ($self -> masterlocked) {
+
+    # find out last modification time
+    # and do nothing unless 'violent-timout' is over
+    #
+    my $time = $self -> _reftime;
+
+    if ($time) {
+      return if ((time - $time) < $self -> timeout('violent'));
+    }
+
+    $self -> set_ref (0);                        # reference counter = 0
+    $self -> _simple_unlock ($self -> reflock);  # release reference counter file
+    $self -> _simple_unlock ($self -> exshlock); # remove excl shared lock
+    $self -> _simple_unlock ($self -> lockfile); # release file
+  }
+
+  return;
+}
+
+### sub release ################################################################
+#
+# release a file
+#
+# Params: ~none~
+#
+# Return: ~none~
+#
+sub release {
+  my $self = shift;
+
+  $self -> set_ref (0);                           # reference counter = 0
+  $self -> _simple_unlock ($self -> reflock);     # release reference counter
+  $self -> _simple_unlock ($self -> lockfile);    # remove any write lock announce
+  $self -> _simple_unlock ($self -> exshlock);    # remove any excl shared lock
+  $self -> _simple_unlock ($self -> masterlock);  # remove master lock
+
+  return;
+}
+
+# keep 'require' happy
+1;
+
+#
+#
+### end of Lock::API ###########################################################
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Lock/Exclusive.pm b/selfforum-cgi/shared/Lock/Exclusive.pm
new file mode 100644 (file)
index 0000000..d6243ec
--- /dev/null
@@ -0,0 +1,123 @@
+package Lock::Exclusive;
+
+################################################################################
+#                                                                              #
+# File:        shared/Lock/Exclusive.pm                                        #
+#                                                                              #
+# Authors:     Andre Malo       <nd@o3media.de>, 2001-05-25                    #
+#                                                                              #
+# Description: Locking and Filehandle class                                    #
+#              using O_EXCL and lock files                                     #
+#                                                                              #
+################################################################################
+
+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_lock ###########################################################
+#
+# simple file lock
+# (create lock file)
+#
+# Params: $filename - file to lock
+#         $timeout  - timeout
+#
+# Return: success (boolean)
+#
+sub _simple_lock {
+  my ($self, $fh) = @_;
+
+  sysopen ($fh, $fh->filename, O_CREAT | O_EXCL | O_WRONLY)
+    and close $fh
+    and return 1;
+
+  return;
+}
+
+### sub _simple_unlock #########################################################
+#
+# simple file unlock
+# (unlink lock file)
+#
+# Params: $filename - lockfile name
+#                     ^^^^^^^^
+#
+# Return: success (boolean)
+#
+sub _simple_unlock {
+  my ($self, $filename) = @_;
+
+  return 1 if (!-f $filename or unlink $filename);
+
+  # not able to unlink lock file, hmmm...
+  #
+  return;
+}
+
+### sub _reftime ###############################################################
+#
+# determine reference time for violent unlock
+#
+# Params: ~none~
+#
+# Return: time or zero, if no reference file found
+#
+sub _reftime {
+  my $self = shift;
+  my ($time, $reffile) = 0;
+
+  if (-f ($reffile = $self -> filename)) {
+    $time = (stat $reffile)[9];}
+
+  elsif (-f ($reffile = $self -> lockfile)) {
+    $time = (stat $reffile)[9];}
+
+  $time;
+}
+
+### sub masterlocked ###########################################################
+#
+# check on master lock status of the file
+#
+# Params: ~none~
+#
+# Return: status (boolean)
+#
+sub masterlocked {-f shift -> masterlock}
+
+### sub excl_announced #########################################################
+#
+# check on exclusive lock announced status of the file
+#
+# Params: ~none~
+#
+# Return: status (boolean)
+#
+sub excl_announced {-f shift -> lockfile}
+
+### sub exsh_announced #########################################################
+#
+# check on exclusive shared lock status of the file
+#
+# Params: ~none~
+#
+# Return: status (boolean)
+#
+sub exsh_announced {-f shift -> exshlock}
+
+# keep 'require' happy
+1;
+
+#
+#
+### end of Lock::Exclusive #####################################################
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Lock/Handle.pm b/selfforum-cgi/shared/Lock/Handle.pm
new file mode 100644 (file)
index 0000000..e5a749e
--- /dev/null
@@ -0,0 +1,62 @@
+package Lock::Handle;
+
+################################################################################
+#                                                                              #
+# File:        shared/Lock/Handle.pm                                           #
+#                                                                              #
+# Authors:     Andre Malo       <nd@o3media.de>, 2001-05-30                    #
+#                                                                              #
+# Description: belongs to Locking and Filehandle class                         #
+#              NOT FOR PUBLIC USE                                              #
+#                                                                              #
+################################################################################
+
+use strict;
+use vars qw(
+  $VERSION
+);
+
+use base   qw(Lock::_static);
+
+use Symbol qw(gensym);
+
+################################################################################
+#
+# Version check
+#
+$VERSION = do { my @r =(q$Revision$ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
+
+### sub new ####################################################################
+#
+# constructor
+#
+# Params: $file - filename
+#
+# Return: Lock object
+#
+sub new {
+  my ($instance, $file) = @_;
+  my $class = ref($instance) || $instance;
+  my $self  = bless $class -> _create_handle => $class;
+
+  $self -> set_static (filename => $file);
+
+  $self;
+}
+
+### sub _create_handle #########################################################
+#
+# create a globref
+#
+# Params: ~none~
+#
+# Return: globref
+#
+sub _create_handle {gensym}
+
+# keep 'require' happy
+1;
+
+#
+#
+### end of Lock::Handle ########################################################
\ No newline at end of file
diff --git a/selfforum-cgi/shared/Lock/Symlink.pm b/selfforum-cgi/shared/Lock/Symlink.pm
new file mode 100644 (file)
index 0000000..82ea283
--- /dev/null
@@ -0,0 +1,121 @@
+package Lock::Symlink;
+
+################################################################################
+#                                                                              #
+# File:        shared/Lock/Symlink.pm                                          #
+#                                                                              #
+# Authors:     Andre Malo       <nd@o3media.de>, 2001-05-25                    #
+#                                                                              #
+# Description: Locking and Filehandle class                                    #
+#              using symlinks                                                  #
+#                                                                              #
+################################################################################
+
+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_lock ###########################################################
+#
+# simple file lock
+# (create lock file)
+#
+# Params: $filename - file to lock
+#         $timeout  - timeout
+#
+# Return: success (boolean)
+#
+sub _simple_lock {
+  my ($self, $fh) = @_;
+
+  symlink $self->filename, $fh->filename and return 1;
+
+  return;
+}
+
+### sub _simple_unlock #########################################################
+#
+# simple file unlock
+# (unlink lock file)
+#
+# Params: $filename - lockfile name
+#                     ^^^^^^^^
+#
+# Return: success (boolean)
+#
+sub _simple_unlock {
+  my ($self, $filename) = @_;
+
+  return 1 if (!-l $filename or unlink $filename);
+
+  # not able to unlink symlink, hmmm...
+  #
+  return;
+}
+
+### sub _reftime ###############################################################
+#
+# determine reference time for violent unlock
+#
+# Params: ~none~
+#
+# Return: time or zero, if no reference file found
+#
+sub _reftime {
+  my $self = shift;
+  my ($time, $reffile) = 0;
+
+  if (-f ($reffile = $self -> filename)) {
+    $time = (stat $reffile)[9];}
+
+  elsif (-l ($reffile = $self -> lockfile)) {
+    $time = (lstat $reffile)[9];}
+
+  $time;
+}
+
+### sub masterlocked ###########################################################
+#
+# check on master lock status of the file
+#
+# Params: ~none~
+#
+# Return: status (boolean)
+#
+sub masterlocked {-l shift -> masterlock}
+
+### sub excl_announced #########################################################
+#
+# check on exclusive lock announced status of the file
+#
+# Params: ~none~
+#
+# Return: status (boolean)
+#
+sub excl_announced {-l shift -> lockfile}
+
+### sub exsh_announced #########################################################
+#
+# check on exclusive shared lock status of the file
+#
+# Params: ~none~
+#
+# Return: status (boolean)
+#
+sub exsh_announced {-l shift -> exshlock}
+
+# keep 'require' happy
+1;
+
+#
+#
+### end of Lock::Symlink #######################################################
diff --git a/selfforum-cgi/shared/Lock/Unlink.pm b/selfforum-cgi/shared/Lock/Unlink.pm
new file mode 100644 (file)
index 0000000..d7bd6ec
--- /dev/null
@@ -0,0 +1,124 @@
+package Lock::Unlink;
+
+################################################################################
+#                                                                              #
+# File:        shared/Lock/Unlink.pm                                           #
+#                                                                              #
+# Authors:     Andre Malo       <nd@o3media.de>, 2001-05-25                    #
+#                                                                              #
+# Description: Locking and Filehandle class                                    #
+#              using the atomic behavior of unlinkig files                     #
+#                                                                              #
+################################################################################
+
+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_lock ###########################################################
+#
+# simple file lock
+# (unlink lock file)
+#
+# Params: $filename - file to lock
+#         $timeout  - timeout
+#
+# Return: success (boolean)
+#
+sub _simple_lock {
+  my ($self, $fh) = @_;
+
+  unlink $fh -> filename and return 1;
+
+  return;
+}
+
+### sub _simple_unlock #########################################################
+#
+# simple file unlock
+# (create lock file)
+#
+# Params: $filename - lockfile name
+#                     ^^^^^^^^
+#
+# Return: success (boolean)
+#
+sub _simple_unlock {
+  my ($self, $filename) = @_;
+  local *LF;
+
+  sysopen (LF, $filename, O_WRONLY | O_CREAT | O_TRUNC)
+    and close LF
+    and return 1;
+
+  # not able to create lock file, hmmm...
+  #
+  return;
+}
+
+### sub _reftime ###############################################################
+#
+# determine reference time for violent unlock
+#
+# Params: ~none~
+#
+# Return: time or zero, if no reference file found
+#
+sub _reftime {
+  my $self = shift;
+  my ($time, $reffile) = 0;
+
+  if (-f ($reffile = $self -> filename)) {
+    $time = (stat $reffile)[9];}
+
+  elsif (-f ($reffile = $self -> lockfile)) {
+    $time = (stat $reffile)[9];}
+
+  $time;
+}
+
+### sub masterlocked ###########################################################
+#
+# check on master lock status of the file
+#
+# Params: ~none~
+#
+# Return: status (boolean)
+#
+sub masterlocked {not -f shift -> masterlock}
+
+### sub excl_announced #########################################################
+#
+# check on exclusive lock announced status of the file
+#
+# Params: ~none~
+#
+# Return: status (boolean)
+#
+sub excl_announced {not -f shift -> lockfile}
+
+### sub exsh_announced #########################################################
+#
+# check on exclusive shared lock status of the file
+#
+# Params: ~none~
+#
+# Return: status (boolean)
+#
+sub exsh_announced {not -f shift -> exshlock}
+
+# keep 'require' happy
+1;
+
+#
+#
+### end of Lock::Unlink ########################################################
diff --git a/selfforum-cgi/shared/Lock/_simple.pm b/selfforum-cgi/shared/Lock/_simple.pm
new file mode 100644 (file)
index 0000000..7aae43a
--- /dev/null
@@ -0,0 +1,351 @@
+package Lock::_simple;
+
+################################################################################
+#                                                                              #
+# File:        shared/Lock/_simple.pm                                          #
+#                                                                              #
+# Authors:     Andre Malo       <nd@o3media.de>, 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
diff --git a/selfforum-cgi/shared/Lock/_static.pm b/selfforum-cgi/shared/Lock/_static.pm
new file mode 100644 (file)
index 0000000..37233de
--- /dev/null
@@ -0,0 +1,184 @@
+package Lock::_static;
+
+################################################################################
+#                                                                              #
+# File:        shared/Lock/_static.pm                                          #
+#                                                                              #
+# Authors:     Andre Malo       <nd@o3media.de>, 2001-05-25                    #
+#                                                                              #
+# Description: belongs to Locking and Filehandle class                         #
+#              NO PUBLIC USE                                                   #
+#              save the lock object static information                         #
+#              (because the lock object is a blessed file handle)              #
+#                                                                              #
+################################################################################
+
+use strict;
+use vars qw(
+  $VERSION
+);
+
+use Carp;
+
+################################################################################
+#
+# Version check
+#
+$VERSION = do { my @r =(q$Revision$ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
+
+################################################################################
+#
+# Variables
+#
+my (%static, %access);
+
+# define standard timeouts
+# (seconds)
+#
+my %timeout = (
+  shared     => 10,       # for shared and exclusive shared locks
+  exclusive  => 10,       # for exclusive locks
+  violent    => 600,      # for violent unlocks (10 minutes should justify a process abort)
+  master     => 20        # for master locks
+);
+
+### timeout ####################################################################
+#
+# set and read out the timeout
+#
+# Params: $type - timeout type (defined in %timeout, see above)
+#                 in this case, the specified timeout will be returned
+#         OR
+#         %hash - (type => time) pairs
+#                  the specified timouts will be set
+#
+# Return: specified timeout or nothing
+#
+sub timeout {
+  my ($self, @ary) = @_;
+
+  return if (@ary == 0);
+
+  if (@ary == 1) {
+    my $type = shift @ary;
+    my $hash = $self -> get_static('timeout') || {};
+
+    return defined $hash->{$type}
+    ? $hash -> {$type}
+    : $timeout {$type};
+  }
+
+  my %hash = @ary;
+  $self->set_static(timeout => {%{$self -> get_static('timeout') || {}},%hash});
+
+  return;
+}
+
+### set_static #################################################################
+#
+# set an object property
+#
+# Params: $key   - property and method name
+#         $value - property
+#
+# Return: $value or nothing
+#
+sub set_static {
+  my ($self, $key, $value) = @_;
+
+  $static{$self}={} unless exists($static{$self});
+  $static{$self}->{$key} = $value;
+
+  defined wantarray and return $value;
+  return;
+}
+
+### get_static #################################################################
+#
+# read out an object property
+#
+# Params: $key - property name
+#
+# Return: value or false
+#
+sub get_static {
+  my ($self, $key) = @_;
+
+  return unless exists($static{$self});
+  $static{$self}->{$key};
+}
+
+################################################################################
+#
+# define the lock file names
+#
+sub reffile    {shift -> filename . '.lock.ref'}
+sub lockfile   {shift -> filename . '.lock'}
+sub reflock    {shift -> filename . '.lock.ref.lock'}
+sub exshlock   {shift -> filename . '.exshlock'}
+sub masterlock {shift -> filename . '.masterlock'}
+
+################################################################################
+#
+# autoload the general access methods
+#
+BEGIN {
+  %access = map {$_=>1} qw(
+    filename
+    locked_shared
+    locked_exclusive
+    locked_exsh
+    es_announced
+    announced
+  );
+}
+AUTOLOAD {
+  my $self = shift;
+  (my $attr = $Lock::_static::AUTOLOAD) =~ s/.*:://;
+  return if ($attr eq 'DESTROY');
+
+  if ($access{$attr}) {
+    return $self -> get_static($attr);
+  }
+  else {
+    eval {
+      local $SIG{__DIE__};
+      my $sup = "SUPER::$attr";
+      return $self -> $sup(@_);
+    };
+    croak $@;
+  }
+}
+
+################################################################################
+#
+# destrcutor - try to unlock, if neccessary and possible
+#
+DESTROY {
+  my $self = shift;
+
+  $self -> unlock if ($self =~ /^Lock=/);
+  delete $static{$self};
+}
+
+################################################################################
+#
+# terminator, catch sigTERM and (try to) destroy all objects
+#
+sub destroy_all {
+  $SIG{TERM} = \&destroy_all;
+
+  $_ -> unlock for (grep ((ref $_ and /^Lock=/) => keys %static));
+
+  exit (0);
+}
+BEGIN {
+  $SIG{TERM} = \&destroy_all;
+}
+
+# keep 'require' happy
+1;
+
+#
+#
+### end of Lock::_static #######################################################
\ No newline at end of file

patrick-canterino.de