TYPO3 CMS  TYPO3_7-6
SimpleLockStrategy.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Locking;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
20 
25 {
26  const FILE_LOCK_FOLDER = 'typo3temp/locks/';
27 
31  protected $filePath;
32 
36  protected $isAcquired = false;
37 
41  protected $loops = 150;
42 
46  protected $step = 200;
47 
52  public function __construct($subject)
53  {
54  // Tests if the directory for simple locks is available.
55  // If not, the directory will be created. The lock path is usually
56  // below typo3temp, typo3temp itself should exist already
57  $path = PATH_site . self::FILE_LOCK_FOLDER;
58  if (!is_dir($path)) {
59  // Not using mkdir_deep on purpose here, if typo3temp itself
60  // does not exist, this issue should be solved on a different
61  // level of the application.
62  if (!GeneralUtility::mkdir($path)) {
63  throw new LockCreateException('Cannot create directory ' . $path, 1395140007);
64  }
65  }
66  if (!is_writable($path)) {
67  throw new LockCreateException('Cannot write to directory ' . $path, 1396278700);
68  }
69  $this->filePath = $path . 'simple_' . md5((string)$subject);
70  }
71 
77  public function init($loops = 0, $step = 0)
78  {
79  $this->loops = (int)$loops;
80  $this->step = (int)$step;
81  }
82 
87  public function __destruct()
88  {
89  $this->release();
90  }
91 
97  public function release()
98  {
99  if (!$this->isAcquired) {
100  return true;
101  }
102 
103  $success = true;
104  if (
105  GeneralUtility::isAllowedAbsPath($this->filePath)
106  && GeneralUtility::isFirstPartOfStr($this->filePath, PATH_site . self::FILE_LOCK_FOLDER)
107  ) {
108  if (@unlink($this->filePath) === false) {
109  $success = false;
110  }
111  }
112 
113  $this->isAcquired = false;
114  return $success;
115  }
116 
122  public function isAcquired()
123  {
124  return $this->isAcquired;
125  }
126 
130  public static function getCapabilities()
131  {
132  return self::LOCK_CAPABILITY_EXCLUSIVE | self::LOCK_CAPABILITY_NOBLOCK;
133  }
134 
142  public function acquire($mode = self::LOCK_CAPABILITY_EXCLUSIVE)
143  {
144  if ($this->isAcquired) {
145  return true;
146  }
147 
148  if (file_exists($this->filePath)) {
149  $maxExecutionTime = (int)ini_get('max_execution_time');
150  $maxAge = time() - ($maxExecutionTime ?: 120);
151  if (@filectime($this->filePath) < $maxAge) {
152  // Remove stale lock file
153  @unlink($this->filePath);
154  }
155  }
156 
157  $this->isAcquired = false;
158  $wouldBlock = false;
159  for ($i = 0; $i < $this->loops; $i++) {
160  $filePointer = @fopen($this->filePath, 'x');
161  if ($filePointer !== false) {
162  fclose($filePointer);
163  GeneralUtility::fixPermissions($this->filePath);
164  $this->isAcquired = true;
165  break;
166  }
167  if ($mode & self::LOCK_CAPABILITY_NOBLOCK) {
168  $wouldBlock = true;
169  break;
170  }
171  usleep($this->step * 1000);
172  }
173 
174  if ($mode & self::LOCK_CAPABILITY_NOBLOCK && !$this->isAcquired && $wouldBlock) {
175  throw new LockAcquireWouldBlockException('Failed to acquire lock because the request would block.', 1428700748);
176  }
177 
178  return $this->isAcquired;
179  }
180 
184  public static function getPriority()
185  {
186  return 50;
187  }
188 
194  public function destroy()
195  {
196  @unlink($this->filePath);
197  }
198 }
static isFirstPartOfStr($str, $partStr)
static fixPermissions($path, $recursive=false)
acquire($mode=self::LOCK_CAPABILITY_EXCLUSIVE)