Приглашаем посетить
Creates an exclusive lock for a file
############################################################################
# #
# lock() Version 2.0 #
# Written by Craig Patchett craig@patchett.com #
# Created 9/16/96 Last Modified 3/28/97 #
# #
# Copyright 1997 Craig Patchett & Matthew Wright. All Rights Reserved. #
# This subroutine is part of The CGI/Perl Cookbook from John Wiley & Sons. #
# License to use this program or install it on a server (in original or #
# modified form) is granted only to those who have purchased a copy of The #
# CGI/Perl Cookbook. (This notice must remain as part of the source code.) #
# #
# Function: Creates an exclusive lock for a file. The lock will #
# only work if other programs accessing the file are also #
# using this subroutine. #
# #
# Usage: &lock($filename, $LOCK_DIR[, $MAX_WAIT]); #
# #
# Variables: $filename -- Name of file being locked. #
# Example "filename.html" #
# $LOCK_DIR -- Path of directory to store lock files #
# Should be "/tmp/" on UNIX sytems #
# Example "/home/lockdir/" #
# $MAX_WAIT -- Maximum seconds to wait if the file is #
# already locked #
# #
# Returns: 0 if successful #
# 1 if $LOCK_DIR/$filename.tmp could not be created #
# 2 if $filename is currently in use #
# 3 if lock file could not be created or opened #
# #
# Uses Globals: $Error_Message for descriptive error messages #
# $NAME_LEN for maximum filename length #
# #
# Files Created: Creates $LOCK_DIR/$filename.tmp #
# Creates $LOCK_DIR/$filename.lok (exists only while file #
# is locked) #
# #
############################################################################
sub lock {
# Initialize variables
local($filename, $LOCK_DIR, $MAX_WAIT) = @_;
local($wait, $lock_pid);
local($temp_file) = "$LOCK_DIR$$.tmp";
$Error_Message = '';
local($lock_file) = $filename;
$lock_file =~ tr/\/\\:.//d; # Remove file separators/periods
if ($NAME_LEN && ($NAME_LEN < length($lock_file))) {
$lock_file = substr($lock_file, -$NAME_LEN);
}
$lock_file = "$LOCK_DIR$lock_file.lok";
# Create temp file with PID
if (!open(TEMP, ">$temp_file")) {
$Error_Message = "Could not create $temp_file ($!).";
return(1);
}
print TEMP $$;
close(TEMP);
# Test for lock file
if (-e $lock_file) {
# Wait for unlock if lock file exists
for ($wait = $MAX_WAIT; $wait; --$wait) {
sleep(1);
last unless -e $lock_file;
}
}
# Check to see if there's still a valid lock
if ((-e $lock_file) && (-M $lock_file < 0)) {
# The file is still locked but has been modified since we started
unlink($temp_file);
$Error_Message = "The file \"$filename\" is currently in use. Please try again later.";
return(2);
}
else {
# There is either no lock or the lock has expired
if (!rename($temp_file, $lock_file)) {
# Problem creating the lock file
unlink($temp_file);
$Error_Message = "Could not lock file \"$filename\" ($!).";
return(3);
}
# Check to make sure the lock is ours
if (!open(LOCK, "<$lock_file")) {
$Error_Message = "Could not verify lock for file \"$filename\" ($!).";
return(3);
}
$lock_pid = <LOCK>;
close(LOCK);
if ($lock_pid ne $$) {
$Error_Message = "The file \"$filename\" is currently in use. Please try again later.";
return(2);
}
else { return(0) }
}
}
############################################################################
# #
# unlock() Version 2.0 #
# Written by Craig Patchett craig@patchett.com #
# Created 9/16/96 Last Modified 3/28/97 #
# #
# Copyright 1997 Craig Patchett & Matthew Wright. All Rights Reserved. #
# This subroutine is part of The CGI/Perl Cookbook from John Wiley & Sons. #
# License to use this program or install it on a server (in original or #
# modified form) is granted only to those who have purchased a copy of The #
# CGI/Perl Cookbook. (This notice must remain as part of the source code.) #
# #
# Function: Unlocks a file that has been locked using lock(). #
# #
# Usage: &unlock($filename, $LOCK_DIR); #
# #
# Variables: $filename -- Name of file being locked. #
# Example "filename.html" #
# $LOCK_DIR -- Path of directory to store lock files #
# Should be "/tmp/" on UNIX sytems #
# Example "/home/lockdir/" #
# #
# Returns: 0 if successful #
# 1 if the lock file could not be deleted #
# #
# Uses Globals: $Error_Message for descriptive error messages #
# $NAME_LEN for maximum filename length #
# #
# Files Created: Removes $LOCK_DIR/$filename.lok #
# #
############################################################################
sub unlock {
# Initialize variables
local($filename, $LOCK_DIR) = @_;
local($lock_file) = $filename;
$Error_Message = '';
$lock_file =~ tr/\/\\:.//d; # Remove file separators/periods
if ($NAME_LEN < length($lock_file)) {
$lock_file = substr($lock_file, -$NAME_LEN);
}
$lock_file = "$LOCK_DIR$lock_file.lok";
# Check to make sure the lock is ours
if (!open(LOCK, "<$lock_file")) {
$Error_Message = "Could not access the lock file for \"$filename\" ($!).";
return(1);
}
$lock_pid = <LOCK>;
close(LOCK);
if ($lock_pid ne $$) {
$Error_Message = "The file \"$filename\" is locked by another process.";
return(2);
}
# Release the lock by unlinking the lock file
if (!unlink($lock_file)) {
$Error_Message = "Could not unlock file \"$filename\" ($!).";
return(3);
}
return(0);
}
1;