]>
git.p6c8.net - selfforum.git/blob - selfforum-cgi/shared/Lock.pm
3f01861712c1a2c562af21ac2a83b9288f9967e7
3 ################################################################################
5 # File: shared/Lock.pm #
7 # Authors: Andre Malo <nd@o3media.de>, 2001-04-01 #
9 # Description: file locking #
11 ################################################################################
27 ################################################################################
31 use base
qw(Exporter);
57 ### sub ~file ($) ##############################################################
59 # create lock file names
62 return $_[0].'.lock.ref';
68 return $_[0].'.master';
70 sub masterlockfile
($) {
71 return lockfile
(masterfile
$_[0]);
74 ################################################################################
76 # Windows section (no symlinks)
79 ### sub w_lock_file ($;$) ######################################################
81 # set read lock (shared lock)
82 # (for no-symlink-systems)
84 # Params: $filename - file to lock
85 # $timeout - Lock Timeout (sec.)
87 # Return: Status Code (Bool)
89 sub w_lock_file
($;$) {
91 my $timeout = +shift || $Timeout;
93 unless ($LOCKED{$filename}) {
94 if (-f masterlockfile
($filename)) {
97 # try to increment the reference counter
99 if (set_ref
($filename,1,$timeout)) {
100 $LOCKED{$filename}=1;
107 # master lock is set or file has not been released yet
113 # maybe the system is occupied
117 ### sub w_unlock_file ($;$) ####################################################
119 # remove read lock (shared lock)
120 # (for no-symlink-systems)
122 # Params: $filename - locked file
123 # $timeout - timeout (sec.)
125 # Return: Status Code (Bool)
127 sub w_unlock_file
($;$) {
128 my $filename = shift;
129 my $timeout = shift || $Timeout;
131 if ($LOCKED{$filename}) {
132 if ($LOCKED{$filename} == 3) {
133 return unless write_unlock_file
($filename, $timeout);
134 $LOCKED{$filename} = 1;
136 if ($LOCKED{$filename} == 1) {
137 if (-f masterlockfile
($filename)) {
139 # try do decrement the reference counter
141 if (set_ref
($filename,-1,$timeout)) {
142 delete $LOCKED{$filename};
153 ### sub w_write_lock_file ($;$) ################################################
155 # set write lock (exclusive lock)
156 # (for no-symlink-systems)
158 # Params: $filename - file to lock
159 # $timeout - timeout (sec.)
161 # Return: Status Code (Bool)
163 sub w_write_lock_file
($;$) {
165 my $timeout= shift || $Timeout;
166 my $rest = ($LOCKED{$filename} and $LOCKED{$filename} == 1) ?
1 : 0;
168 if (-f masterlockfile
($filename) or $iAmMaster) {
170 # announce the write lock
171 # and wait $timeout seconds for
172 # references == 0 (no shared locks set)
174 simple_lock
($filename,$timeout) or return 0;
176 # lock reference counter
179 unless (simple_lock
(reffile
($filename),$timeout)) {
180 simple_unlock
($filename,$timeout);
184 # ready if we have no shared locks
186 if (get_ref
($filename) == $rest) {
187 $LOCKED{$filename} = 2 | ($rest ?
1 : 0);
191 # release reference counter
192 # shared locks get the chance to be removed
194 unless (simple_unlock
(reffile
($filename),$timeout)) {
195 simple_unlock
($filename,$timeout);
202 # remove the announcement
204 simple_unlock
($filename);
208 # master lock is set or file has not been released yet
216 ### sub w_write_unlock_file ($;$) ##############################################
218 # remove write lock (exclusive lock)
219 # (for no-symlink-systems)
221 # Params: $filename - locked file
222 # $timeout - timeout (sec.)
224 # Return: Status Code (Bool)
226 sub w_write_unlock_file
($;$) {
227 my $filename = shift;
228 my $timeout = shift || $Timeout;
230 if (-f masterlockfile
($filename) or $iAmMaster) {
232 # remove reference counter lock
234 simple_unlock
(reffile
($filename),$timeout) or return;
236 # remove the write lock announce
238 simple_unlock
($filename,$timeout) or return;
242 delete $LOCKED{$filename};
246 ### sub w_violent_unlock_file ($) ##############################################
248 # remove any lock violent (excl. master lock)
249 # (for no-symlink-systems)
251 # Params: $filename - locked file
253 # Return: -none- (the success is not defined)
255 sub w_violent_unlock_file
($) {
256 my $filename = shift;
258 if (-f masterlockfile
($filename)) {
260 # find out last modification time
261 # and do nothing unless 'violent-timout' is over
264 if (-f
($reffile = $filename) or -f
($reffile = lockfile
($filename))) {
265 my $time = (stat $reffile)[9];
266 (time - $time) >= $violentTimeout or return;
269 write_lock_file
($filename,1); # last try, to set an exclusive lock on $filename
270 unlink (reffile
($filename)); # reference counter = 0
271 simple_unlock
(reffile
($filename)); # release reference counter file
272 simple_unlock
($filename);} # release file
273 delete $LOCKED{$filename};
278 ### sub w_set_master_lock ($;$) ################################################
281 # (for no-symlink-systems)
283 # Params: $filename - file to lock
284 # $timeout - timeout (sec.)
286 # Return: Status Code (Bool)
288 sub w_set_master_lock
($;$) {
289 my $filename = shift;
290 my $timeout = shift || $masterTimeout;
292 # set exclusive lock or fail
294 return unless (write_lock_file
($filename,$timeout));
298 unlink masterlockfile
($filename) and return 1;
300 # no chance (occupied?, master lock set yet?)
304 ### sub w_release_file ($) #####################################################
306 # remove any locks (incl. master lock)
307 # (for no-symlink-systems)
309 # Params: $filename - file to lock
310 # $timeout - timeout (sec.)
312 # Return: Status Code (Bool)
314 sub w_release_file
($) {
317 unlink (reffile
($filename)); # reference counter = 0
318 return if (-f reffile
($filename)); # really?
319 return unless (simple_unlock
(reffile
($filename))); # release reference counter
320 return unless (simple_unlock
($filename)); # remove any write lock announce
321 return unless (simple_unlock
(masterfile
($filename))); # remove master lock
322 delete $LOCKED{$filename};
328 ################################################################################
330 # *n*x section (symlinks possible)
333 ### sub x_lock_file ($;$) ######################################################
335 # set read lock (shared lock)
336 # (symlinks possible)
338 # Params: $filename - file to lock
339 # $timeout - Lock Timeout (sec.)
341 # Return: Status Code (Bool)
343 sub x_lock_file
($;$) {
344 my $filename = shift;
345 my $timeout = shift || $Timeout;
347 unless ($LOCKED{$filename}) {
348 unless (-l masterlockfile
($filename)) {
351 # try to increment the reference counter
353 if (set_ref
($filename,1,$timeout)) {
354 $LOCKED{$filename} = 1;
362 # master lock is set or file has not been realeased yet
371 ### sub x_unlock_file ($;$) ####################################################
373 # remove read lock (shared lock)
374 # (symlinks possible)
376 # Params: $filename - locked file
377 # $timeout - timeout (sec.)
379 # Return: Status Code (Bool)
381 sub x_unlock_file
($;$) {
383 my ($timeout)=(shift (@_) or $Timeout);
385 if ($LOCKED{$filename}) {
386 if ($LOCKED{$filename} == 3) {
387 return unless write_unlock_file
($filename, $timeout);
388 $LOCKED{$filename} = 1;
390 if ($LOCKED{$filename} == 1) {
391 unless (-l masterlockfile
($filename)) {
392 # try to decrement the reference counter
394 set_ref
($filename,-1,$timeout) and do {
395 delete $LOCKED{$filename};
406 ### sub x_write_lock_file ($;$) ################################################
408 # set write lock (exclusive lock)
409 # (symlinks possible)
411 # Params: $filename - file to lock
412 # $timeout - timeout (sec.)
414 # Return: Status Code (Bool)
416 sub x_write_lock_file
($;$) {
417 my $filename = shift;
418 my $timeout = shift || $Timeout;
419 my $rest = ($LOCKED{$filename} and $LOCKED{$filename} == 1) ?
1 : 0;
421 unless (-l masterlockfile
($filename) and not $iAmMaster) {
422 # announce the write lock
423 # and wait $timeout seconds for
424 # references == 0 (no shared locks set)
426 simple_lock
($filename,$timeout) or return 0;
429 # lock reference counter
432 unless (simple_lock
(&reffile
($filename),$timeout)) {
433 simple_unlock
($filename,$timeout);
437 # ready if we have no shared locks
439 if (get_ref
($filename) == $rest) {
440 $LOCKED{$filename} = 2 | ($rest ?
1 : 0);
444 # release reference counter
445 # shared locks get the chance to be removed
447 unless (simple_unlock
(&reffile
($filename),$timeout)) {
448 simple_unlock
($filename,$timeout);
455 # remove the announcement
457 simple_unlock
($filename);
462 # or file has not been released yet
468 # maybe the system is occupied
473 ### sub x_write_unlock_file ($;$) ##############################################
475 # remove write lock (exclusive lock)
476 # (symlinks possible)
478 # Params: $filename - locked file
479 # $timeout - timeout (sec.)
481 # Return: Status Code (Bool)
483 sub x_write_unlock_file
($;$) {
484 my $filename = shift;
485 my $timeout = shift || $Timeout;
487 unless (-l
&masterlockfile
($filename) and not $iAmMaster) {
488 # remove reference counter lock
490 simple_unlock
(reffile
($filename),$timeout) or return;
492 # remove the write lock announce
494 simple_unlock
($filename,$timeout) or return;
498 delete $LOCKED{$filename};
502 ### sub x_violent_unlock_file ($) ##############################################
504 # remove any lock violent (excl. master lock)
505 # (symlinks possible)
507 # Params: $filename - locked file
509 # Return: -none- (the success is not defined)
511 sub x_violent_unlock_file
($) {
514 unless (-l
&masterlockfile
($filename)) {
516 # find out last modification time
517 # and do nothing unless 'violent-timout' is over
521 if (-f
($reffile = $filename)) {
522 $time = (stat $reffile)[9];}
524 elsif (-l
($reffile = lockfile
($filename))) {
525 $time = (lstat $reffile)[9];}
528 return if ((time - $time) < $violentTimeout);}
530 write_lock_file
($filename,1); # last try, to set an exclusive lock on $filename
531 unlink (reffile
($filename)); # reference counter = 0
532 simple_unlock
(reffile
($filename)); # release reference counter file
533 simple_unlock
($filename);} # release file
534 delete $LOCKED{$filename};
537 ### sub x_set_master_lock ($;$) ################################################
540 # (symlinks possible)
542 # Params: $filename - file to lock
543 # $timeout - timeout (sec.)
545 # Return: Status Code (Bool)
547 sub x_set_master_lock
($;$) {
548 my $filename = shift;
549 my $timeout = shift || $masterTimeout;
551 # set exclusive lock or fail
553 return unless (write_lock_file
($filename,$timeout));
557 symlink $filename, masterlockfile
($filename) and return 1;
559 # no chance (occupied?, master lock set yet?)
563 ### sub x_release_file ($) #####################################################
565 # remove any locks (incl. master lock)
566 # (symlinks possible)
568 # Params: $filename - file to lock
569 # $timeout - timeout (sec.)
571 # Return: Status Code (Bool)
573 sub x_release_file
($) {
576 unlink (reffile
($filename)); # reference counter = 0
577 return if (-f reffile
($filename)); # really?
578 return unless (simple_unlock
(reffile
($filename))); # release reference counter
579 return unless (simple_unlock
($filename)); # remove any write lock announce
580 return unless (simple_unlock
(masterfile
($filename))); # remove master lock
581 delete $LOCKED{$filename};
587 ### sub w_simple_lock ($;$) ####################################################
588 ### sub w_simple_unlock ($) ####################################################
590 # simple file lock/unlock
591 # (for no-symlink-systems: kill/create lockfile)
593 # Params: $filename - file to lock
594 # [ $timeout - Lock time out (sec.) ]
596 # Return: Status Code (Bool)
598 sub w_simple_lock
($;$) {
599 my $filename = shift;
600 my $timeout = shift || $Timeout;
601 my $lockfile = lockfile
$filename;
604 unlink $lockfile and return 1;
613 sub w_simple_unlock
($) {
614 my $filename = shift;
615 my $lockfile = lockfile
$filename;
618 if (sysopen(LF
, $lockfile, O_WRONLY
|O_CREAT
|O_TRUNC
)) {
619 return 1 if close (LF
);
622 # not able to create lockfile, hmmm...
627 ### sub x_simple_lock ($;$) ####################################################
628 ### sub x_simple_unlock ($) ####################################################
630 # simple file lock/unlock
631 # (symlinks possible: create/unlink symlink)
633 # Params: $filename - file to lock
634 # [ $timeout - Lock time out (sec.) ]
636 # Return: Status Code (Bool)
638 sub x_simple_lock
($;$) {
639 my $filename = shift;
640 my $timeout = shift || $Timeout;
641 my $lockfile = lockfile
$filename;
644 symlink $filename,$lockfile and return 1;
652 sub x_simple_unlock
($) {
655 unlink (lockfile
$filename) and return 1;
657 # not able to unlink symlink, hmmm...
662 ### sub w_set_ref ($$$) ########################################################
664 # add $_[1] to reference counter
665 # (may be negative...)
666 # (for no-symlink-systems)
668 # Params: $filename - file, reference counter belongs to
669 # $z - value, added to reference counter
670 # $timeout - lock time out
672 # Return: Status Code (Bool)
674 sub w_set_ref
($$$) {
675 my $filename = shift;
677 my $timeout = shift || $Timeout;
678 my $reffile = reffile
$filename;
681 # if write lock announced, only count down allowed
683 ($z < 0 or -f lockfile
($filename)) or return;
685 # lock reference counter file
687 simple_lock
($reffile,$timeout) or return;
689 # load reference counter
691 my $old = get_ref
($filename);
693 # compute and write new ref. counter
696 $old = 0 if ($old < 0);
698 # kill reference counter file
699 # if ref. counter == 0
702 unlink $reffile or return;
706 sysopen (REF
, $reffile, O_WRONLY
| O_TRUNC
| O_CREAT
) or return;
707 print REF
$old or do {
714 # release ref. counter file
716 simple_unlock
($reffile) or return;
722 ### sub x_set_ref ($$$) ########################################################
724 # add $_[1] to reference counter
725 # (may be negative...)
726 # (symlinks possible)
728 # Params: $filename - file, reference counter belongs to
729 # $z - value, added to reference counter
730 # $timeout - lock time out
732 # Return: Status Code (Bool)
734 sub x_set_ref
($$$) {
735 my $filename = shift;
737 my $timeout = shift || $Timeout;
738 my $reffile = reffile
$filename;
741 # if write lock announced, only count down allowed
744 return if(-l lockfile
($filename));
747 # lock reference counter file
749 return unless(simple_lock
($reffile,$timeout));
751 # load reference counter
753 my $old = get_ref
($filename);
755 # compute and write new ref. counter
758 $old = 0 if ($old < 0);
761 unlink $reffile or return;
765 sysopen (REF
, $reffile, O_WRONLY
| O_TRUNC
| O_CREAT
) or return;
766 print REF
$old or do {
773 # release ref. counter file
775 simple_unlock
($reffile) or return;
781 ### sub get_ref ($) ############################################################
783 # read out the reference counter
784 # (system independant)
787 # Params: $filename - file, the ref. counter belongs to
789 # Return: reference counter
792 my $filename = shift;
793 my $reffile = reffile
$filename;
797 if (sysopen (REF
, $reffile, O_RDONLY
)) {
799 read REF
, $old, -s
$reffile;
808 ################################################################################
810 # initializing the module
813 # global variables (time in seconds)
815 $Timeout = 10; # normal timeout
816 $violentTimeout = 600; # violent timeout (10 minutes)
817 $masterTimeout = 20; # master timeout
819 $iAmMaster = 0; # default: I am nobody
823 # assign the aliases to the needed functions
824 # (perldoc -f symlink)
826 if ( eval {local $SIG{__DIE__
}; symlink('',''); 1 } ) {
827 *lock_file
= \
&x_lock_file
;
828 *unlock_file
= \
&x_unlock_file
;
829 *write_lock_file
= \
&x_write_lock_file
;
830 *write_unlock_file
= \
&x_write_unlock_file
;
831 *violent_unlock_file
= \
&x_violent_unlock_file
;
832 *set_master_lock
= \
&x_set_master_lock
;
833 *release_file
= \
&x_release_file
;
835 *simple_lock
= \
&x_simple_lock
;
836 *simple_unlock
= \
&x_simple_unlock
;
837 *set_ref
= \
&x_set_ref
;
841 *lock_file
= \
&w_lock_file
;
842 *unlock_file
= \
&w_unlock_file
;
843 *write_lock_file
= \
&w_write_lock_file
;
844 *write_unlock_file
= \
&w_write_unlock_file
;
845 *violent_unlock_file
= \
&w_violent_unlock_file
;
846 *set_master_lock
= \
&w_set_master_lock
;
847 *release_file
= \
&w_release_file
;
849 *simple_lock
= \
&w_simple_lock
;
850 *simple_unlock
= \
&w_simple_unlock
;
851 *set_ref
= \
&w_set_ref
;
855 # keeping require happy
860 ### end of Lock ################################################################
patrick-canterino.de