Bug #18279 » 0007630_v2.patch
t3lib/class.t3lib_lock.php (Arbeitskopie) | ||
---|---|---|
class t3lib_lock {
|
||
private $method;
|
||
private $id; // Identifier used for this lock
|
||
private $resource; // Resource used for this lock (can be a file or a semaphore resource)
|
||
private $filepointer;
|
||
private $isAcquired = false;
|
||
... | ... | |
}
|
||
// Detect locking method
|
||
if (in_array($method, array('disable', 'simple','flock','semaphore'))) {
|
||
if (in_array($method, array('disable', 'simple', 'flock', 'semaphore'))) {
|
||
$this->method = $method;
|
||
} else {
|
||
throw new Exception('No such method "'.$method.'"');
|
||
... | ... | |
case 'simple':
|
||
case 'flock':
|
||
$path = PATH_site.'typo3temp/locks/';
|
||
$this->id = $path.md5($id);
|
||
if (!is_dir($path)) {
|
||
t3lib_div::mkdir($path);
|
||
}
|
||
$this->id = md5($id);
|
||
$this->resource = $path.$this->id;
|
||
$success = true;
|
||
break;
|
||
case 'semaphore':
|
||
$id = abs(crc32($id));
|
||
if (($this->id = sem_get($id, 1))==true) {
|
||
$this->id = abs(crc32($id));
|
||
if (($this->resource = sem_get($this->id, 1))==true) {
|
||
$success = true;
|
||
}
|
||
break;
|
||
... | ... | |
switch ($this->method) {
|
||
case 'simple':
|
||
if (is_file($this->id)) {
|
||
if (is_file($this->resource)) {
|
||
$this->sysLog('Waiting for a different process to release the lock');
|
||
$i = 0;
|
||
while ($i<$this->loops) {
|
||
$i++;
|
||
usleep($this->step*1000);
|
||
clearstatcache();
|
||
if (!is_file($this->id)) { // Lock became free, leave the loop
|
||
if (!is_file($this->resource)) { // Lock became free, leave the loop
|
||
$this->sysLog('Different process released the lock');
|
||
$noWait = false;
|
||
break;
|
||
}
|
||
... | ... | |
$noWait = true;
|
||
}
|
||
if (($this->filepointer = touch($this->id)) == false) {
|
||
if (($this->filepointer = touch($this->resource)) == false) {
|
||
throw new Exception('Lock file could not be created');
|
||
}
|
||
break;
|
||
case 'flock':
|
||
if (($this->filepointer = fopen($this->id, 'w+')) == false) {
|
||
if (($this->filepointer = fopen($this->resource, 'w+')) == false) {
|
||
throw new Exception('Lock file could not be opened');
|
||
}
|
||
... | ... | |
} elseif (flock($this->filepointer, LOCK_EX) == true) { // Lock with blocking (waiting for similar locks to become released)
|
||
$noWait = false;
|
||
} else {
|
||
throw new Exception('Could not lock file "'.$this->id.'"');
|
||
throw new Exception('Could not lock file "'.$this->resource.'"');
|
||
}
|
||
break;
|
||
case 'semaphore':
|
||
if (sem_acquire($this->id)) {
|
||
if (sem_acquire($this->resource)) {
|
||
// Unfortunately it seems not possible to find out if the request was blocked, so we return false in any case to make sure the operation is tried again.
|
||
$noWait = false;
|
||
}
|
||
... | ... | |
$success = true;
|
||
switch ($this->method) {
|
||
case 'simple':
|
||
if (unlink($this->id) == false) {
|
||
if (unlink($this->resource) == false) {
|
||
$success = false;
|
||
}
|
||
break;
|
||
... | ... | |
$success = false;
|
||
}
|
||
fclose($this->filepointer);
|
||
unlink($this->id);
|
||
unlink($this->resource);
|
||
break;
|
||
case 'semaphore':
|
||
if (!sem_release($this->id)) {
|
||
if (sem_release($this->resource)) {
|
||
sem_remove($this->resource);
|
||
} else {
|
||
$success = false;
|
||
}
|
||
break;
|
||
... | ... | |
}
|
||
/**
|
||
* Return the ID of which is currently used
|
||
* Return the ID which is currently used
|
||
*
|
||
* @return string Locking ID
|
||
*/
|
||
... | ... | |
}
|
||
/**
|
||
* Return the resource which is currently used.
|
||
* Depending on the locking method this can be a filename or a semaphore resource.
|
||
*
|
||
* @return mixed Locking resource (filename as string or semaphore as resource)
|
||
*/
|
||
public function getResource() {
|
||
return $this->resource;
|
||
}
|
||
/**
|
||
* Return the status of a lock
|
||
*
|
||
* @return string Returns true if lock is acquired, false otherwise
|
||
... | ... | |
public function getLockStatus() {
|
||
return $this->isAcquired;
|
||
}
|
||
/**
|
||
* Adds a common log entry for this locking API using t3lib_div::sysLog().
|
||
* Example: 25-02-08 17:58 - cms: Locking [simple::0aeafd2a67a6bb8b9543fb9ea25ecbe2]: Acquired
|
||
*
|
||
* @param string $message: The message to be logged
|
||
* @param integer $severity: Severity - 0 is info (default), 1 is notice, 2 is warning, 3 is error, 4 is fatal error
|
||
* @return void
|
||
*/
|
||
public function sysLog($message, $severity=0) {
|
||
t3lib_div::sysLog('Locking ['.$this->method.'::'.$this->id.']: '.trim($message), 'cms', $severity);
|
||
}
|
||
}
|
||
typo3/sysext/cms/tslib/class.tslib_fe.php (Arbeitskopie) | ||
---|---|---|
* Lock the page generation process
|
||
* The lock is used to queue page requests until this page is successfully stored in the cache.
|
||
*
|
||
* @param object Reference to a locking object
|
||
* @param t3lib_lock Reference to a locking object
|
||
* @param string String to identify the lock in the system
|
||
* @return boolean Returns true if the lock could be obtained, false otherwise (= process had to wait for existing lock to be released)
|
||
* @see releasePageGenerationLock()
|
||
*/
|
||
function acquirePageGenerationLock(&$lockObj, $key) {
|
||
if ($this->no_cache || $this->headerNoCache()) {
|
||
$lockObj->sysLog('Page is not cached, no locking required');
|
||
return true; // No locking is needed if caching is disabled
|
||
}
|
||
... | ... | |
// true = Page could get locked without blocking
|
||
// false = Page could get locked but process was blocked before
|
||
$success = $lockObj->acquire();
|
||
if ($lockObj->getLockStatus()) {
|
||
$lockObj->sysLog('Acquired lock');
|
||
}
|
||
}
|
||
} catch (Exception $e) {
|
||
t3lib_div::sysLog('Locking failed: '.$e->getMessage(), 'cms', 3);
|
||
$lockObj->sysLog('Failed to acquire lock: '.$e->getMessage(), 3);
|
||
$success = false; // If locking fails, return with false and continue without locking
|
||
}
|
||
... | ... | |
/**
|
||
* Release the page generation lock
|
||
*
|
||
* @param object Reference to a locking object
|
||
* @param t3lib_lock Reference to a locking object
|
||
* @return boolean Returns true on success, false otherwise
|
||
* @see acquirePageGenerationLock()
|
||
*/
|
||
function releasePageGenerationLock(&$lockObj) {
|
||
if ($this->no_cache || $this->headerNoCache()) {
|
||
return true; // No locking is needed if caching is disabled
|
||
}
|
||
$success = false;
|
||
if (is_object($lockObj)) {
|
||
// If lock object is set and was aquired (may also happen if no_cache was enabled during runtime), release it:
|
||
if (is_object($lockObj) && $lockObj instanceof t3lib_lock && $lockObj->getLockStatus()) {
|
||
$success = $lockObj->release();
|
||
$lockObj->sysLog('Released lock');
|
||
unset($lockObj);
|
||
// Otherwise, if caching is disabled, no locking is required:
|
||
} elseif ($this->no_cache || $this->headerNoCache()) {
|
||
$success = true;
|
||
}
|
||
return $success;
|
||
}
|
||