TYPO3 CMS  TYPO3_7-6
FileLockStrategy.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 
21 
26 {
27  const FILE_LOCK_FOLDER = 'typo3temp/locks/';
28 
32  protected $filePointer;
33 
37  protected $filePath;
38 
42  protected $isAcquired = false;
43 
48  public function __construct($subject)
49  {
50  /*
51  * Tests if the directory for simple locks is available.
52  * If not, the directory will be created. The lock path is usually
53  * below typo3temp, typo3temp itself should exist already
54  */
55  $path = PATH_site . self::FILE_LOCK_FOLDER;
56  if (!is_dir($path)) {
57  // Not using mkdir_deep on purpose here, if typo3temp itself
58  // does not exist, this issue should be solved on a different
59  // level of the application.
60  if (!GeneralUtility::mkdir($path)) {
61  throw new LockCreateException('Cannot create directory ' . $path, 1395140007);
62  }
63  }
64  if (!is_writable($path)) {
65  throw new LockCreateException('Cannot write to directory ' . $path, 1396278700);
66  }
67  $this->filePath = $path . 'flock_' . md5((string)$subject);
68  }
69 
74  public function __destruct()
75  {
76  $this->release();
77  }
78 
87  public function acquire($mode = self::LOCK_CAPABILITY_EXCLUSIVE)
88  {
89  if ($this->isAcquired) {
90  return true;
91  }
92 
93  $this->filePointer = fopen($this->filePath, 'c');
94  if ($this->filePointer === false) {
95  throw new LockAcquireException('Lock file could not be opened', 1294586099);
96  }
97  GeneralUtility::fixPermissions($this->filePath);
98 
99  $operation = $mode & self::LOCK_CAPABILITY_EXCLUSIVE ? LOCK_EX : LOCK_SH;
100  if ($mode & self::LOCK_CAPABILITY_NOBLOCK) {
101  $operation |= LOCK_NB;
102  }
103 
104  $wouldBlock = 0;
105  $this->isAcquired = flock($this->filePointer, $operation, $wouldBlock);
106 
107  if ($mode & self::LOCK_CAPABILITY_NOBLOCK && !$this->isAcquired && $wouldBlock) {
108  throw new LockAcquireWouldBlockException('Failed to acquire lock because the request would block.', 1428700748);
109  }
110 
111  return $this->isAcquired;
112  }
113 
119  public function release()
120  {
121  if (!$this->isAcquired) {
122  return true;
123  }
124  $success = true;
125  if (is_resource($this->filePointer)) {
126  if (flock($this->filePointer, LOCK_UN) === false) {
127  $success = false;
128  }
129  fclose($this->filePointer);
130  }
131  $this->isAcquired = false;
132  return $success;
133  }
134 
140  public function isAcquired()
141  {
142  return $this->isAcquired;
143  }
144 
148  public static function getPriority()
149  {
150  return 75;
151  }
152 
156  public static function getCapabilities()
157  {
158  if (PHP_SAPI === 'isapi') {
159  // From php docs: When using a multi-threaded server API like ISAPI you may not be able to rely on flock()
160  // to protect files against other PHP scripts running in parallel threads of the same server instance!
161  return 0;
162  }
163  $capabilities = self::LOCK_CAPABILITY_EXCLUSIVE | self::LOCK_CAPABILITY_SHARED;
164  if (TYPO3_OS !== 'WIN'
165  || version_compare(PHP_VERSION, '5.5.22', '>') && version_compare(PHP_VERSION, '5.6.0', '<')
166  || version_compare(PHP_VERSION, '5.6.6', '>')
167  ) {
168  $capabilities |= self::LOCK_CAPABILITY_NOBLOCK;
169  }
170 
171  return $capabilities;
172  }
173 
179  public function destroy()
180  {
181  @unlink($this->filePath);
182  }
183 }
static fixPermissions($path, $recursive=false)
acquire($mode=self::LOCK_CAPABILITY_EXCLUSIVE)