]>
git.p6c8.net - selfforum.git/blob - selfforum-cgi/shared/Lock.pm
f3291c6daaeb1c57487b8fb54ddb7fda308f3d36
3 ################################################################################
5 # File: shared/Lock.pm #
7 # Authors: Andre Malo <nd@o3media.de>, 2001-04-01 #
9 # Description: file locking #
11 ################################################################################
24 ################################################################################
28 use base
qw(Exporter);
62 ################################################################################
64 # Windows section (no symlinks)
67 ### sub w_lock_file ($;$) ######################################################
69 # set read lock (shared lock)
70 # (for no-symlink-systems)
72 # Params: $filename - file to lock
73 # $timeout - Lock Timeout (sec.)
75 # Return: Status Code (Bool)
77 sub w_lock_file
($;$) {
79 my $timeout = +shift || $Timeout;
81 if (-f
&masterlockfile
($filename)) {
84 # try to increment the reference counter
86 &set_ref
($filename,1,$timeout) and return 1;
93 # or file has not been realeased yet
99 # maybe the system is occupied
103 ### sub w_unlock_file ($;$) ####################################################
105 # remove read lock (shared lock)
106 # (for no-symlink-systems)
108 # Params: $filename - locked file
109 # $timeout - timeout (sec.)
111 # Return: Status Code (Bool)
113 sub w_unlock_file
($;$) {
114 my $filename = shift;
115 my $timeout = shift || $Timeout;
117 if (-f
&masterlockfile
($filename)) {
119 # try do decrement the reference counter
121 &set_ref
($filename,-1,$timeout) and return 1;
125 # maybe the system is occupied
126 # or file has not been released yet
131 ### sub w_write_lock_file ($;$) ################################################
133 # set write lock (exclusive lock)
134 # (for no-symlink-systems)
136 # Params: $filename - file to lock
137 # $timeout - timeout (sec.)
139 # Return: Status Code (Bool)
141 sub w_write_lock_file
($;$) {
143 my $timeout= shift || $Timeout;
145 if (-f
&masterlockfile
($filename) or $iAmMaster) {
147 # announce the write lock
148 # and wait $timeout seconds for
149 # references == 0 (no shared locks set)
151 &simple_lock
($filename,$timeout) or return 0;
153 # lock reference counter
156 unless (&simple_lock
(&reffile
($filename),$timeout)) {
157 &simple_unlock
($filename,$timeout);
161 # ready if we have no shared locks
163 return 1 if (&get_ref
($filename) == 0);
165 # release reference counter
166 # shared locks get the chance to be removed
168 unless (&simple_unlock
(&reffile
($filename),$timeout)) {
169 &simple_unlock
($filename,$timeout);
176 # remove the announcement
178 &simple_unlock
($filename);}
182 # or file has not been released yet
187 # maybe the system is occupied
192 ### sub w_write_unlock_file ($;$) ##############################################
194 # remove write lock (exclusive lock)
195 # (for no-symlink-systems)
197 # Params: $filename - locked file
198 # $timeout - timeout (sec.)
200 # Return: Status Code (Bool)
202 sub w_write_unlock_file
($;$) {
203 my $filename = shift;
204 my $timeout = shift || $Timeout;
206 if (-f
&masterlockfile
($filename) or $iAmMaster) {
208 # remove reference counter lock
210 &simple_unlock
(&reffile
($filename),$timeout) or return;
212 # remove the write lock announce
214 &simple_unlock
($filename,$timeout) or return;}
220 ### sub w_violent_unlock_file ($) ##############################################
222 # remove any lock violent (excl. master lock)
223 # (for no-symlink-systems)
225 # Params: $filename - locked file
227 # Return: -none- (the success is not defined)
229 sub w_violent_unlock_file
($) {
230 my $filename = shift;
232 if (-f
&masterlockfile
($filename)) {
234 # find out last modification time
235 # and do nothing unless 'violent-timout' is over
238 if (-f
($reffile = $filename) or -f
($reffile = &lockfile
($filename))) {
239 my $time = (stat $reffile)[9];
240 return if ((time - $time) < $violentTimeout);}
242 write_lock_file
($filename,1); # last try, to set an exclusive lock on $filename
243 unlink (&reffile
($filename)); # reference counter = 0
244 simple_unlock
(&reffile
($filename)); # release reference counter file
245 simple_unlock
($filename);} # release file
250 ### sub w_set_master_lock ($;$) ################################################
253 # (for no-symlink-systems)
255 # Params: $filename - file to lock
256 # $timeout - timeout (sec.)
258 # Return: Status Code (Bool)
260 sub w_set_master_lock
($;$) {
261 my $filename = shift;
262 my $timeout = shift || $masterTimeout;
264 # set exclusive lock or fail
266 return unless (&write_lock_file
($filename,$timeout));
270 unlink &masterlockfile
($filename) and return 1;
272 # no chance (occupied?, master lock set yet?)
276 ### sub w_release_file ($) #####################################################
278 # remove any locks (incl. master lock)
279 # (for no-symlink-systems)
281 # Params: $filename - file to lock
282 # $timeout - timeout (sec.)
284 # Return: Status Code (Bool)
286 sub w_release_file
($) {
289 unlink (&reffile
($filename)); # reference counter = 0
290 return if (-f
&reffile
($filename)); # really?
291 return unless (simple_unlock
(&reffile
($filename))); # release reference counter
292 return unless (&simple_unlock
($filename)); # remove any write lock announce
293 return unless (&simple_unlock
(&masterfile
($filename))); # remove master lock
299 ################################################################################
301 # *n*x section (symlinks possible)
304 ### sub x_lock_file ($;$) ######################################################
306 # set read lock (shared lock)
307 # (symlinks possible)
309 # Params: $filename - file to lock
310 # $timeout - Lock Timeout (sec.)
312 # Return: Status Code (Bool)
314 sub x_lock_file
($;$) {
315 my $filename = shift;
316 my $timeout = shift || $Timeout;
318 unless (-l
&masterlockfile
($filename)) {
321 # try to increment the reference counter
323 &set_ref
($filename,1,$timeout) and return 1;
330 # or file has not been realeased yet
336 # maybe the system is occupied
340 ### sub x_unlock_file ($;$) ####################################################
342 # remove read lock (shared lock)
343 # (symlinks possible)
345 # Params: $filename - locked file
346 # $timeout - timeout (sec.)
348 # Return: Status Code (Bool)
350 sub x_unlock_file
($;$) {
352 my ($timeout)=(shift (@_) or $Timeout);
354 unless (-l
&masterlockfile
($filename)) {
355 # try do decrement the reference counter
357 &set_ref
($filename,-1,$timeout) and return 1;}
360 # maybe the system is occupied
361 # or file has not been released yet
366 ### sub x_write_lock_file ($;$) ################################################
368 # set write lock (exclusive lock)
369 # (symlinks possible)
371 # Params: $filename - file to lock
372 # $timeout - timeout (sec.)
374 # Return: Status Code (Bool)
376 sub x_write_lock_file
($;$) {
377 my $filename = shift;
378 my $timeout = shift || $Timeout;
380 unless (-l
&masterlockfile
($filename) and not $iAmMaster) {
381 # announce the write lock
382 # and wait $timeout seconds for
383 # references == 0 (no shared locks set)
385 &simple_lock
($filename,$timeout) or return 0;
388 # lock reference counter
391 unless (&simple_lock
(&reffile
($filename),$timeout)) {
392 &simple_unlock
($filename,$timeout);
396 # ready if we have no shared locks
398 return 1 if (&get_ref
($filename) == 0);
400 # release reference counter
401 # shared locks get the chance to be removed
403 unless (&simple_unlock
(&reffile
($filename),$timeout)) {
404 &simple_unlock
($filename,$timeout);
411 # remove the announcement
413 &simple_unlock
($filename);}
417 # or file has not been released yet
423 # maybe the system is occupied
428 ### sub x_write_unlock_file ($;$) ##############################################
430 # remove write lock (exclusive lock)
431 # (symlinks possible)
433 # Params: $filename - locked file
434 # $timeout - timeout (sec.)
436 # Return: Status Code (Bool)
438 sub x_write_unlock_file
($;$) {
439 my $filename = shift;
440 my $timeout = shift || $Timeout;
442 unless (-l
&masterlockfile
($filename) and not $iAmMaster) {
443 # remove reference counter lock
445 &simple_unlock
(&reffile
($filename),$timeout) or return;
447 # remove the write lock announce
449 &simple_unlock
($filename,$timeout) or return;
456 ### sub x_violent_unlock_file ($) ##############################################
458 # remove any lock violent (excl. master lock)
459 # (symlinks possible)
461 # Params: $filename - locked file
463 # Return: -none- (the success is not defined)
465 sub x_violent_unlock_file
($) {
468 unless (-l
&masterlockfile
($filename)) {
470 # find out last modification time
471 # and do nothing unless 'violent-timout' is over
475 if (-f
($reffile = $filename)) {
476 $time = (stat $reffile)[9];}
478 elsif (-l
($reffile = &lockfile
($filename))) {
479 $time = (lstat $reffile)[9];}
482 return if ((time - $time) < $violentTimeout);}
484 write_lock_file
($filename,1); # last try, to set an exclusive lock on $filename
485 unlink (&reffile
($filename)); # reference counter = 0
486 simple_unlock
(&reffile
($filename)); # release reference counter file
487 simple_unlock
($filename);} # release file
490 ### sub x_set_master_lock ($;$) ################################################
493 # (symlinks possible)
495 # Params: $filename - file to lock
496 # $timeout - timeout (sec.)
498 # Return: Status Code (Bool)
500 sub x_set_master_lock
($;$) {
501 my $filename = shift;
502 my $timeout = shift || $masterTimeout;
504 # set exclusive lock or fail
506 return unless (&write_lock_file
($filename,$timeout));
510 symlink $filename, &masterlockfile
($filename) and return 1;
512 # no chance (occupied?, master lock set yet?)
516 ### sub x_release_file ($) #####################################################
518 # remove any locks (incl. master lock)
519 # (symlinks possible)
521 # Params: $filename - file to lock
522 # $timeout - timeout (sec.)
524 # Return: Status Code (Bool)
526 sub x_release_file
($) {
529 unlink (&reffile
($filename)); # reference counter = 0
530 return if (-f
&reffile
($filename)); # really?
531 return unless (simple_unlock
(&reffile
($filename))); # release reference counter
532 return unless (&simple_unlock
($filename)); # remove any write lock announce
533 return unless (&simple_unlock
(&masterfile
($filename))); # remove master lock
539 ################################################################################
544 ### sub ~file ($) ##############################################################
546 # create lock file names
554 sub masterlockfile
($) {
555 &lockfile
(&masterfile
($_[0]));
558 confess
unless defined $_[0];
562 ### sub w_simple_lock ($;$) ####################################################
563 ### sub w_simple_unlock ($) ####################################################
565 # simple file lock/unlock
566 # (for no-symlink-systems: kill/create lockfile)
568 # Params: $filename - file to lock
569 # [ $timeout - Lock time out (sec.) ]
571 # Return: Status Code (Bool)
573 sub w_simple_lock
($;$) {
574 my $filename = shift;
575 my $timeout = shift || $Timeout;
576 my $lockfile = lockfile
$filename;
579 unlink $lockfile and return 1;
588 sub w_simple_unlock
($) {
589 my $filename = shift;
590 my $lockfile = lockfile
$filename;
593 if (open(LF
, "> $lockfile")) {
594 return 1 if close (LF
);
597 # not able to create lockfile, hmmm...
602 ### sub w_simple_lock ($;$) ####################################################
603 ### sub w_simple_unlock ($) ####################################################
605 # simple file lock/unlock
606 # (symlinks possible: create/unlink symlink)
608 # Params: $filename - file to lock
609 # [ $timeout - Lock time out (sec.) ]
611 # Return: Status Code (Bool)
613 sub x_simple_lock
($;$) {
614 my $filename = shift;
615 my $timeout = shift || $Timeout;
616 my $lockfile = lockfile
$filename;
619 symlink $filename,$lockfile and return 1;
624 # locking failed (occupied?)
629 sub x_simple_unlock
($) {
632 unlink (&lockfile
($filename)) and return 1;
634 # not able to unlink symlink, hmmm...
639 ### sub w_set_ref ($$$) ########################################################
641 # add $_[1] to reference counter
642 # (may be negative...)
643 # (for no-symlink-systems)
645 # Params: $filename - file, reference counter belongs to
646 # $z - value, added to reference counter
647 # $timeout - lock time out
649 # Return: Status Code (Bool)
651 sub w_set_ref
($$$) {
652 my $filename = shift;
654 my $timeout = shift || $Timeout;
656 my $reffile = reffile
$filename;
659 # if write lock announced, only count down allowed
662 return unless(-f lockfile
($filename));
665 # lock reference counter file
667 return unless(&simple_lock
($reffile,$timeout));
669 # load reference counter
671 unless (open REF
,"<$reffile") {
680 # compute and write new ref. counter
683 $old = 0 if ($old < 0);
685 # kill reference counter file
686 # if ref. counter == 0
689 unlink $reffile or return;
692 open REF
,">$reffile" or return;
693 print REF
$old or return;
697 # release ref. counter file
699 return unless(&simple_unlock
($reffile));
705 ### sub x_set_ref ($$$) ########################################################
707 # add $_[1] to reference counter
708 # (may be negative...)
709 # (symlinks possible)
711 # Params: $filename - file, reference counter belongs to
712 # $z - value, added to reference counter
713 # $timeout - lock time out
715 # Return: Status Code (Bool)
717 sub x_set_ref
($$$) {
718 my $filename = shift;
720 my $timeout = shift || $Timeout;
722 my $reffile = reffile
$filename;
725 # if write lock announced, only count down allowed
728 return if(-l
&lockfile
($filename));
731 # lock reference counter file
733 return unless(&simple_lock
($reffile,$timeout));
735 # load reference counter
737 unless (open REF
,"<$reffile") {
746 # compute and write new ref. counter
749 $old = 0 if ($old < 0);
751 unlink $reffile or return;
754 open REF
,">$reffile" or return;
755 print REF
$old or return;
759 # release ref. counter file
761 return unless(&simple_unlock
($reffile));
767 ### sub get_ref ($) ############################################################
769 # read out the reference counter
770 # (system independant)
773 # Params: $filename - file, the ref. counter belongs to
775 # Return: reference counter
778 my $filename = shift;
779 my $reffile = reffile
$filename;
783 unless (open REF
,"< $reffile") {
796 ################################################################################
798 # initializing the module
801 # global variables (time in seconds)
803 $Timeout = 10; # normal timeout
804 $violentTimeout = 600; # violent timeout (10 minutes)
805 $masterTimeout = 20; # master timeout
807 $iAmMaster = 0; # default: I am nobody
809 # assign the aliases to the needed functions
810 # (perldoc -f symlink)
812 if ( eval {local $SIG{__DIE__
}; symlink('',''); 1 } ) {
813 *lock_file
= \
&x_lock_file
;
814 *unlock_file
= \
&x_unlock_file
;
815 *write_lock_file
= \
&x_write_lock_file
;
816 *write_unlock_file
= \
&x_write_unlock_file
;
817 *violent_unlock_file
= \
&x_violent_unlock_file
;
818 *set_master_lock
= \
&x_set_master_lock
;
819 *release_file
= \
&x_release_file
;
821 *simple_lock
= \
&x_simple_lock
;
822 *simple_unlock
= \
&x_simple_unlock
;
823 *set_ref
= \
&x_set_ref
;
827 *lock_file
= \
&w_lock_file
;
828 *unlock_file
= \
&w_unlock_file
;
829 *write_lock_file
= \
&w_write_lock_file
;
830 *write_unlock_file
= \
&w_write_unlock_file
;
831 *violent_unlock_file
= \
&w_violent_unlock_file
;
832 *set_master_lock
= \
&w_set_master_lock
;
833 *release_file
= \
&w_release_file
;
835 *simple_lock
= \
&w_simple_lock
;
836 *simple_unlock
= \
&w_simple_unlock
;
837 *set_ref
= \
&w_set_ref
;
841 # keeping require happy
846 ### end of Lock ################################################################
patrick-canterino.de