+
+sub cleanUp
+{
+ rmdir $httpdPidDir;
+ unlink $exclusiveLockFile;
+ unlink $myLockFile if $myLockFile;
+}
+
+sub extractLockNumber
+{
+ my ($lockFile) = @_;
+ return -1 unless $lockFile;
+ return substr($lockFile, length($httpdLockPrefix));
+}
+
+sub getLockFiles
+{
+ opendir(TMPDIR, $tmpDir) or die "Could not open " . $tmpDir . ".";
+ my @lockFiles = grep {m/^$httpdLockPrefix\d+$/} readdir(TMPDIR);
+ @lockFiles = sort { extractLockNumber($a) <=> extractLockNumber($b) } @lockFiles;
+ closedir(TMPDIR);
+ return @lockFiles;
+}
+
+sub getNextAvailableLockNumber
+{
+ my @lockFiles = getLockFiles();
+ return 0 unless @lockFiles;
+ return extractLockNumber($lockFiles[-1]) + 1;
+}
+
+sub getLockNumberForCurrentRunning
+{
+ my @lockFiles = getLockFiles();
+ return 0 unless @lockFiles;
+ return extractLockNumber($lockFiles[0]);
+}
+
+sub waitForHTTPDLock
+{
+ $waitBeginTime = time;
+ scheduleHttpTesting();
+ # If we are the only one waiting for Apache just run the tests without any further checking
+ if (scalar getLockFiles() > 1) {
+ my $currentLockFile = File::Spec->catfile($tmpDir, "$httpdLockPrefix" . getLockNumberForCurrentRunning());
+ my $currentLockPid = <SCHEDULER_LOCK> if (-f $currentLockFile && open(SCHEDULER_LOCK, "<$currentLockFile"));
+ # Wait until we are allowed to run the http tests
+ while ($currentLockPid && $currentLockPid != $$) {
+ $currentLockFile = File::Spec->catfile($tmpDir, "$httpdLockPrefix" . getLockNumberForCurrentRunning());
+ if ($currentLockFile eq $myLockFile) {
+ $currentLockPid = <SCHEDULER_LOCK> if open(SCHEDULER_LOCK, "<$currentLockFile");
+ if ($currentLockPid != $$) {
+ print STDERR "\nPID mismatch.\n";
+ last;
+ }
+ } else {
+ sleep 1;
+ }
+ }
+ }
+ $waitEndTime = time;
+}
+
+sub scheduleHttpTesting
+{
+ # We need an exclusive lock file to avoid deadlocks and starvation and ensure that the scheduler lock numbers are sequential.
+ # The scheduler locks are used to schedule the running test sessions in first come first served order.
+ while (!(open(SEQUENTIAL_GUARD_LOCK, ">$exclusiveLockFile") && flock(SEQUENTIAL_GUARD_LOCK, LOCK_EX|LOCK_NB))) {}
+ $myLockFile = File::Spec->catfile($tmpDir, "$httpdLockPrefix" . getNextAvailableLockNumber());
+ open(SCHEDULER_LOCK, ">$myLockFile");
+ print SCHEDULER_LOCK "$$";
+ print SEQUENTIAL_GUARD_LOCK "$$";
+ close(SCHEDULER_LOCK);
+ close(SEQUENTIAL_GUARD_LOCK);
+ unlink $exclusiveLockFile;
+}
+
+sub getWaitTime
+{
+ my $waitTime = 0;
+ if ($waitBeginTime && $waitEndTime) {
+ $waitTime = $waitEndTime - $waitBeginTime;
+ }
+ return $waitTime;
+}