PageRenderTime 40ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/FileLockRegion.php

https://gitlab.com/mario.uriarte/doctrine2.5-tutorial
PHP | 265 lines | 125 code | 40 blank | 100 comment | 18 complexity | 587e8065bd73981ffa89f7f0e7faf0a8 MD5 | raw file
  1. <?php
  2. /*
  3. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14. *
  15. * This software consists of voluntary contributions made by many individuals
  16. * and is licensed under the MIT license. For more information, see
  17. * <http://www.doctrine-project.org>.
  18. */
  19. namespace Doctrine\ORM\Cache\Region;
  20. use Doctrine\ORM\Cache\CollectionCacheEntry;
  21. use Doctrine\ORM\Cache\Lock;
  22. use Doctrine\ORM\Cache\Region;
  23. use Doctrine\ORM\Cache\CacheKey;
  24. use Doctrine\ORM\Cache\CacheEntry;
  25. use Doctrine\ORM\Cache\ConcurrentRegion;
  26. /**
  27. * Very naive concurrent region, based on file locks.
  28. *
  29. * @since 2.5
  30. * @author Fabio B. Silva <fabio.bat.silvagmail.com>
  31. */
  32. class FileLockRegion implements ConcurrentRegion
  33. {
  34. const LOCK_EXTENSION = 'lock';
  35. /**
  36. * var \Doctrine\ORM\Cache\Region
  37. */
  38. private $region;
  39. /**
  40. * @var string
  41. */
  42. private $directory;
  43. /**
  44. * var integer
  45. */
  46. private $lockLifetime;
  47. /**
  48. * @param \Doctrine\ORM\Cache\Region $region
  49. * @param string $directory
  50. * @param string $lockLifetime
  51. *
  52. * @throws \InvalidArgumentException
  53. */
  54. public function __construct(Region $region, $directory, $lockLifetime)
  55. {
  56. if ( ! is_dir($directory) && ! @mkdir($directory, 0775, true)) {
  57. throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $directory));
  58. }
  59. if ( ! is_writable($directory)) {
  60. throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable.', $directory));
  61. }
  62. $this->region = $region;
  63. $this->directory = $directory;
  64. $this->lockLifetime = $lockLifetime;
  65. }
  66. /**
  67. * @param \Doctrine\ORM\Cache\CacheKey $key
  68. * @param \Doctrine\ORM\Cache\Lock $lock
  69. *
  70. * @return boolean
  71. */
  72. private function isLocked(CacheKey $key, Lock $lock = null)
  73. {
  74. $filename = $this->getLockFileName($key);
  75. if ( ! is_file($filename)) {
  76. return false;
  77. }
  78. $time = $this->getLockTime($filename);
  79. $content = $this->getLockContent($filename);
  80. if ( ! $content || ! $time) {
  81. @unlink($filename);
  82. return false;
  83. }
  84. if ($lock && $content === $lock->value) {
  85. return false;
  86. }
  87. // outdated lock
  88. if (($time + $this->lockLifetime) <= time()) {
  89. @unlink($filename);
  90. return false;
  91. }
  92. return true;
  93. }
  94. /**
  95. * @param \Doctrine\ORM\Cache\CacheKey $key
  96. *
  97. * return string
  98. */
  99. private function getLockFileName(CacheKey $key)
  100. {
  101. return $this->directory . DIRECTORY_SEPARATOR . $key->hash . '.' . self::LOCK_EXTENSION;
  102. }
  103. /**
  104. * @param string $filename
  105. *
  106. * return string
  107. */
  108. private function getLockContent($filename)
  109. {
  110. return @file_get_contents($filename);
  111. }
  112. /**
  113. * @param string $filename
  114. *
  115. * return integer
  116. */
  117. private function getLockTime($filename)
  118. {
  119. return @fileatime($filename);
  120. }
  121. /**
  122. * {inheritdoc}
  123. */
  124. public function getName()
  125. {
  126. return $this->region->getName();
  127. }
  128. /**
  129. * {inheritdoc}
  130. */
  131. public function contains(CacheKey $key)
  132. {
  133. if ($this->isLocked($key)) {
  134. return false;
  135. }
  136. return $this->region->contains($key);
  137. }
  138. /**
  139. * {inheritdoc}
  140. */
  141. public function get(CacheKey $key)
  142. {
  143. if ($this->isLocked($key)) {
  144. return null;
  145. }
  146. return $this->region->get($key);
  147. }
  148. /**
  149. * {@inheritdoc}
  150. */
  151. public function getMultiple(CollectionCacheEntry $collection)
  152. {
  153. if (array_filter(array_map([$this, 'isLocked'], $collection->identifiers))) {
  154. return null;
  155. }
  156. return $this->region->getMultiple($collection);
  157. }
  158. /**
  159. * {inheritdoc}
  160. */
  161. public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null)
  162. {
  163. if ($this->isLocked($key, $lock)) {
  164. return false;
  165. }
  166. return $this->region->put($key, $entry);
  167. }
  168. /**
  169. * {inheritdoc}
  170. */
  171. public function evict(CacheKey $key)
  172. {
  173. if ($this->isLocked($key)) {
  174. @unlink($this->getLockFileName($key));
  175. }
  176. return $this->region->evict($key);
  177. }
  178. /**
  179. * {inheritdoc}
  180. */
  181. public function evictAll()
  182. {
  183. // The check below is necessary because on some platforms glob returns false
  184. // when nothing matched (even though no errors occurred)
  185. $filenames = glob(sprintf("%s/*.%s" , $this->directory, self::LOCK_EXTENSION));
  186. if ($filenames) {
  187. foreach ($filenames as $filename) {
  188. @unlink($filename);
  189. }
  190. }
  191. return $this->region->evictAll();
  192. }
  193. /**
  194. * {inheritdoc}
  195. */
  196. public function lock(CacheKey $key)
  197. {
  198. if ($this->isLocked($key)) {
  199. return null;
  200. }
  201. $lock = Lock::createLockRead();
  202. $filename = $this->getLockFileName($key);
  203. if ( ! @file_put_contents($filename, $lock->value, LOCK_EX)) {
  204. return null;
  205. }
  206. chmod($filename, 0664);
  207. return $lock;
  208. }
  209. /**
  210. * {inheritdoc}
  211. */
  212. public function unlock(CacheKey $key, Lock $lock)
  213. {
  214. if ($this->isLocked($key, $lock)) {
  215. return false;
  216. }
  217. if ( ! @unlink($this->getLockFileName($key))) {
  218. return false;
  219. }
  220. return true;
  221. }
  222. }