Here is an example of a call to OpenFile(). You will notice that I'm
additionally locking the file itself as well as the lock file (I figured
it would not hurt to have both methods):
my $LockFileHandle = authlib::FileLock("udata_" . $strRespNum .
"_lck.cgi", 1);
#Read restart question name
my ($DataFileHandle, $blnError) = authlib::OpenFile($strDataFileName,
"update", 1, 1);
authlib::LockMe($DataFileHandle, 1);
authlib::RestartQNameWrite($DataFileHandle, $strRestartQName);
close $DataFileHandle;
close authlib::FileUnLock($LockFileHandle);
And here are the supporting functions:
sub OpenFile
{
my ($strFileName, $strMode, $blnWriteLog, $blnShowError) = @_;
my $FileHandle = Symbol::gensym();
my $strOpenChar = "";
if ($strMode eq "write")
{
$strOpenChar = ">";
}
elsif ($strMode eq "read")
{
$strOpenChar = "<";
}
elsif ($strMode eq "update")
{
$strOpenChar = "+<";
}
elsif ($strMode eq "create_update")
{
$strOpenChar = "+>";
}
elsif ($strMode eq "append")
{
$strOpenChar = ">>";
}
else
{
authlib::ssiDie ("Unrecognized parameter in OpenFile()
with: " . $strFileName, 0, 1);
}
my $blnError = 0;
open $FileHandle, $strOpenChar . $strFileName or eval{$blnError =
1};
if ($blnError)
{
if ($blnShowError)
{
authlib::ssiDie ("Can't open file " .
$strFileName, $!, $blnWriteLog);
}
}
return ($FileHandle, $blnError);
}
#--------------------------------------------------------------
# Marks a file as locked, will not hand out another lock to the same
file until their are no locks on it (unless it is a shared lock in which
case it can hand out multiple shared locks but not an exclusive lock)
#--------------------------------------------------------------
sub LockMe
{
my ($FileHandle, $blnExclusive) = @_;
my $blnFlockSupported = 1;
eval
{
if ($blnExclusive)
{
#Lock for exclusive write access.
flock $FileHandle, 2;
}
else
{
#Lock it as a shared for multiple readers, but
it will not let a writer in.
flock $FileHandle, 1;
}
};
if ($@)
{
$blnFlockSupported = 0;
$authlib::blnGlobalFlockSupported = 0;
}
#Another process might have changed the file position.
seek $FileHandle, 0, 0;
return $blnFlockSupported;
}
#-----------------------------------------------
#
#-----------------------------------------------
sub FileLock
{
my($strFileName, $blnExclusive) = @_;
my $FileHandle = 0;
my $strLockDir = $authlib::GlobalPaths[0] .
$authlib::strGlobalStudyName . "_lockfiles/";
eval
{
$FileHandle = CreateLockFile($strLockDir . $strFileName,
$blnExclusive, 0);
};
if ($@)
{
#If the lock folder has not been created, create it.
my $blnOpenDir = opendir(LOCKDIR, $strLockDir);
closedir TESTDIR;
#If you cannot open the directory (or it does not exist)
if (!$blnOpenDir)
{
$blnOpenDir = mkdir($strLockDir, 0707);
if (!$blnOpenDir)
{
authlib::ssiDie("Can't create lock
directory <i>" . $strLockDir . "</i>", $!, 1);
}
}
$FileHandle = CreateLockFile($strLockDir . $strFileName,
$blnExclusive, 1);
}
return $FileHandle;
}
#-----------------------------------------------
#
#-----------------------------------------------
sub FileUnLock
{
my($LockFileHandle) = @_;
close $LockFileHandle;
#If flock is not supported delete lock file
if ($authlib::blnGlobalFlockSupported == 0)
{
NoFlockUnLock($LockFileHandle);
}
}
#-----------------------------------------------
#
#-----------------------------------------------
sub CreateLockFile
{
my($strLockFile, $blnExclusive, $blnDisplayError) = @_;
my $LockFileHandle = 0;
my $blnError = 0;
if ($blnDisplayError)
{
($LockFileHandle, $blnError) = OpenFile($strLockFile,
"write", 1, 1);
}
else
{
($LockFileHandle, $blnError) = OpenFile($strLockFile,
"write", 0, 0);
if ($blnError)
{
die();
}
}
my $blnFlockSupported = authlib::LockMe($LockFileHandle,
$blnExclusive);
if ($blnFlockSupported == 0)
{
if ($authlib::strGlobalEXT eq ".pl")
{
print authlib::PrintHeader();
print "<h4><u>Error</u>: This system does not
support flock() for file locking. Please call Sawtooth Software.</h4>";
exit();
}
NoFlockLock($LockFileHandle);
}
return($LockFileHandle);
}
-----Original Message-----
From: Dondi M. Stroma [mailto:[EMAIL PROTECTED]
Sent: Friday, April 13, 2007 1:27 PM
To: Justin Luster
Subject: Re: Lock Files - File is permanently locked
What does your call to your OpenFile() sub look like? Since OpenFile
returns a copy of the file handle, the caller of that function will also
need to store it in a lexical variable, too, but you didn't include that
part of your program.
Also, where and how did you declare and define variables such as
"$strOpenChar" and "$strFileName" used in OpenFile()?
----- Original Message -----
From: Justin Luster
To: [EMAIL PROTECTED]
Sent: Friday, April 13, 2007 1:50 PM
Subject: Lock Files - File is permanently locked
Hi,
I've read through some of the documentation on perl.apache.org about
file
locking and mod_perl. I believe that I'm following the advice there but
I'm
still having problems.
...
Does anyone know what might be happening? We are only using
Apache::Registry in this instance. I can't see how a lexically scoped
file
handle that is being locked is not being unlocked once the process ends.