TYPO3 CMS  TYPO3_8-7
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/var/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/var, typo3temp/var 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 (!$this->isAcquired) {
108  // Make sure to cleanup any dangling resources for this process/thread, which are not needed any longer
109  fclose($this->filePointer);
110  }
111  if ($mode & self::LOCK_CAPABILITY_NOBLOCK && !$this->isAcquired && $wouldBlock) {
112  throw new LockAcquireWouldBlockException('Failed to acquire lock because the request would block.', 1428700748);
113  }
114 
115  return $this->isAcquired;
116  }
117 
123  public function release()
124  {
125  if (!$this->isAcquired) {
126  return true;
127  }
128  $success = true;
129  if (is_resource($this->filePointer)) {
130  if (flock($this->filePointer, LOCK_UN) === false) {
131  $success = false;
132  }
133  fclose($this->filePointer);
134  }
135  $this->isAcquired = false;
136  return $success;
137  }
138 
144  public function isAcquired()
145  {
146  return $this->isAcquired;
147  }
148 
152  public static function getPriority()
153  {
154  return 75;
155  }
156 
160  public static function getCapabilities()
161  {
162  if (PHP_SAPI === 'isapi') {
163  // From php docs: When using a multi-threaded server API like ISAPI you may not be able to rely on flock()
164  // to protect files against other PHP scripts running in parallel threads of the same server instance!
165  return 0;
166  }
167  $capabilities = self::LOCK_CAPABILITY_EXCLUSIVE | self::LOCK_CAPABILITY_SHARED | self::LOCK_CAPABILITY_NOBLOCK;
168 
169  return $capabilities;
170  }
171 
175  public function destroy()
176  {
177  @unlink($this->filePath);
178  }
179 }
static fixPermissions($path, $recursive=false)
acquire($mode=self::LOCK_CAPABILITY_EXCLUSIVE)