1a6d63b89Sgerardnico<?php 2a6d63b89Sgerardnico 3a6d63b89Sgerardniconamespace ComboStrap; 4a6d63b89Sgerardnico 5a6d63b89Sgerardnico 6a6d63b89Sgerardnicouse dokuwiki\Search\Indexer; 7a6d63b89Sgerardnico 8a6d63b89Sgerardnico/** 9a6d63b89Sgerardnico * Adapted from the {@link Indexer::lock()} 10a6d63b89Sgerardnico * because the TaskRunner does not run serially 11a6d63b89Sgerardnico * Only the indexer does 12a6d63b89Sgerardnico * https://forum.dokuwiki.org/d/21044-taskrunner-running-multiple-times-eating-the-memory-lock 13a6d63b89Sgerardnico */ 14a6d63b89Sgerardnicoclass Lock 15a6d63b89Sgerardnico{ 16a6d63b89Sgerardnico private string $lockName; 17a6d63b89Sgerardnico private string $lockFile; 18a6d63b89Sgerardnico /** 19a6d63b89Sgerardnico * @var mixed|null 20a6d63b89Sgerardnico */ 21a6d63b89Sgerardnico private $perm; 22*9fc13f00Sgerardnico private int $timeOut = 5; 23a6d63b89Sgerardnico 24a6d63b89Sgerardnico 25a6d63b89Sgerardnico /** 26a6d63b89Sgerardnico * @param string $name 27a6d63b89Sgerardnico */ 28a6d63b89Sgerardnico public function __construct(string $name) 29a6d63b89Sgerardnico { 30a6d63b89Sgerardnico $this->lockName = $name; 31a6d63b89Sgerardnico global $conf; 32a6d63b89Sgerardnico $this->lockFile = $conf['lockdir'] . "/_{$this->lockName}.lock"; 33a6d63b89Sgerardnico $this->perm = $conf['dperm'] ?? null; 34a6d63b89Sgerardnico } 35a6d63b89Sgerardnico 36a6d63b89Sgerardnico public static function create(string $name): Lock 37a6d63b89Sgerardnico { 38a6d63b89Sgerardnico return new Lock($name); 39a6d63b89Sgerardnico } 40a6d63b89Sgerardnico 41a6d63b89Sgerardnico /** 42a6d63b89Sgerardnico * @throws ExceptionTimeOut - with the timeout 43a6d63b89Sgerardnico */ 44*9fc13f00Sgerardnico function acquire(): Lock 45a6d63b89Sgerardnico { 46a6d63b89Sgerardnico $run = 0; 47a6d63b89Sgerardnico while (!@mkdir($this->lockFile)) { 48a6d63b89Sgerardnico usleep(1000); 49a6d63b89Sgerardnico /** 50a6d63b89Sgerardnico * Old lock ? More than 5 minutes run 51a6d63b89Sgerardnico */ 52a6d63b89Sgerardnico if (is_dir($this->lockFile) && (time() - @filemtime($this->lockFile)) > 60 * 5) { 53a6d63b89Sgerardnico if (!@rmdir($this->lockFile)) { 54a6d63b89Sgerardnico throw new ExceptionRuntimeInternal("Removing the lock failed ($this->lockFile)"); 55a6d63b89Sgerardnico } 56a6d63b89Sgerardnico } 57*9fc13f00Sgerardnico $run++; 58*9fc13f00Sgerardnico if ($run >= $this->timeOut) { 59*9fc13f00Sgerardnico throw new ExceptionTimeOut("Unable to get the lock ($this->lockFile) for ($this->timeOut) seconds"); 60a6d63b89Sgerardnico } 61a6d63b89Sgerardnico } 62a6d63b89Sgerardnico if ($this->perm) { 63a6d63b89Sgerardnico chmod($this->lockFile, $this->perm); 64a6d63b89Sgerardnico } 65*9fc13f00Sgerardnico return $this; 66a6d63b89Sgerardnico 67a6d63b89Sgerardnico } 68a6d63b89Sgerardnico 69a6d63b89Sgerardnico /** 70a6d63b89Sgerardnico * Release the indexer lock. 71a6d63b89Sgerardnico * 72a6d63b89Sgerardnico */ 73a6d63b89Sgerardnico function release() 74a6d63b89Sgerardnico { 75a6d63b89Sgerardnico @rmdir($this->lockFile); 76a6d63b89Sgerardnico } 77a6d63b89Sgerardnico 780360a848Sgerardnico public function isReleased(): bool 790360a848Sgerardnico { 800360a848Sgerardnico return !is_dir($this->lockFile); 810360a848Sgerardnico } 820360a848Sgerardnico 83*9fc13f00Sgerardnico public function setTimeout(int $int) 84*9fc13f00Sgerardnico { 85*9fc13f00Sgerardnico $this->timeOut = $int; 86*9fc13f00Sgerardnico return $this; 87*9fc13f00Sgerardnico } 88*9fc13f00Sgerardnico 89a6d63b89Sgerardnico} 90