/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
- <?php
- /*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * This software consists of voluntary contributions made by many individuals
- * and is licensed under the MIT license. For more information, see
- * <http://www.doctrine-project.org>.
- */
- namespace Doctrine\ORM\Cache\Region;
- use Doctrine\ORM\Cache\CollectionCacheEntry;
- use Doctrine\ORM\Cache\Lock;
- use Doctrine\ORM\Cache\Region;
- use Doctrine\ORM\Cache\CacheKey;
- use Doctrine\ORM\Cache\CacheEntry;
- use Doctrine\ORM\Cache\ConcurrentRegion;
- /**
- * Very naive concurrent region, based on file locks.
- *
- * @since 2.5
- * @author Fabio B. Silva <fabio.bat.silvagmail.com>
- */
- class FileLockRegion implements ConcurrentRegion
- {
- const LOCK_EXTENSION = 'lock';
- /**
- * var \Doctrine\ORM\Cache\Region
- */
- private $region;
- /**
- * @var string
- */
- private $directory;
- /**
- * var integer
- */
- private $lockLifetime;
- /**
- * @param \Doctrine\ORM\Cache\Region $region
- * @param string $directory
- * @param string $lockLifetime
- *
- * @throws \InvalidArgumentException
- */
- public function __construct(Region $region, $directory, $lockLifetime)
- {
- if ( ! is_dir($directory) && ! @mkdir($directory, 0775, true)) {
- throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $directory));
- }
- if ( ! is_writable($directory)) {
- throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable.', $directory));
- }
- $this->region = $region;
- $this->directory = $directory;
- $this->lockLifetime = $lockLifetime;
- }
- /**
- * @param \Doctrine\ORM\Cache\CacheKey $key
- * @param \Doctrine\ORM\Cache\Lock $lock
- *
- * @return boolean
- */
- private function isLocked(CacheKey $key, Lock $lock = null)
- {
- $filename = $this->getLockFileName($key);
- if ( ! is_file($filename)) {
- return false;
- }
- $time = $this->getLockTime($filename);
- $content = $this->getLockContent($filename);
- if ( ! $content || ! $time) {
- @unlink($filename);
- return false;
- }
- if ($lock && $content === $lock->value) {
- return false;
- }
- // outdated lock
- if (($time + $this->lockLifetime) <= time()) {
- @unlink($filename);
- return false;
- }
- return true;
- }
- /**
- * @param \Doctrine\ORM\Cache\CacheKey $key
- *
- * return string
- */
- private function getLockFileName(CacheKey $key)
- {
- return $this->directory . DIRECTORY_SEPARATOR . $key->hash . '.' . self::LOCK_EXTENSION;
- }
- /**
- * @param string $filename
- *
- * return string
- */
- private function getLockContent($filename)
- {
- return @file_get_contents($filename);
- }
- /**
- * @param string $filename
- *
- * return integer
- */
- private function getLockTime($filename)
- {
- return @fileatime($filename);
- }
- /**
- * {inheritdoc}
- */
- public function getName()
- {
- return $this->region->getName();
- }
- /**
- * {inheritdoc}
- */
- public function contains(CacheKey $key)
- {
- if ($this->isLocked($key)) {
- return false;
- }
- return $this->region->contains($key);
- }
- /**
- * {inheritdoc}
- */
- public function get(CacheKey $key)
- {
- if ($this->isLocked($key)) {
- return null;
- }
- return $this->region->get($key);
- }
- /**
- * {@inheritdoc}
- */
- public function getMultiple(CollectionCacheEntry $collection)
- {
- if (array_filter(array_map([$this, 'isLocked'], $collection->identifiers))) {
- return null;
- }
- return $this->region->getMultiple($collection);
- }
- /**
- * {inheritdoc}
- */
- public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null)
- {
- if ($this->isLocked($key, $lock)) {
- return false;
- }
- return $this->region->put($key, $entry);
- }
- /**
- * {inheritdoc}
- */
- public function evict(CacheKey $key)
- {
- if ($this->isLocked($key)) {
- @unlink($this->getLockFileName($key));
- }
- return $this->region->evict($key);
- }
- /**
- * {inheritdoc}
- */
- public function evictAll()
- {
- // The check below is necessary because on some platforms glob returns false
- // when nothing matched (even though no errors occurred)
- $filenames = glob(sprintf("%s/*.%s" , $this->directory, self::LOCK_EXTENSION));
- if ($filenames) {
- foreach ($filenames as $filename) {
- @unlink($filename);
- }
- }
- return $this->region->evictAll();
- }
- /**
- * {inheritdoc}
- */
- public function lock(CacheKey $key)
- {
- if ($this->isLocked($key)) {
- return null;
- }
- $lock = Lock::createLockRead();
- $filename = $this->getLockFileName($key);
- if ( ! @file_put_contents($filename, $lock->value, LOCK_EX)) {
- return null;
- }
- chmod($filename, 0664);
- return $lock;
- }
- /**
- * {inheritdoc}
- */
- public function unlock(CacheKey $key, Lock $lock)
- {
- if ($this->isLocked($key, $lock)) {
- return false;
- }
- if ( ! @unlink($this->getLockFileName($key))) {
- return false;
- }
- return true;
- }
- }