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