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 23 24 /** 25 * @param string $name 26 */ 27 public function __construct(string $name) 28 { 29 $this->lockName = $name; 30 global $conf; 31 $this->lockFile = $conf['lockdir'] . "/_{$this->lockName}.lock"; 32 $this->perm = $conf['dperm'] ?? null; 33 } 34 35 public static function create(string $name): Lock 36 { 37 return new Lock($name); 38 } 39 40 /** 41 * @throws ExceptionTimeOut - with the timeout 42 */ 43 function acquire() 44 { 45 $run = 0; 46 while (!@mkdir($this->lockFile)) { 47 usleep(1000); 48 /** 49 * Old lock ? More than 5 minutes run 50 */ 51 if (is_dir($this->lockFile) && (time() - @filemtime($this->lockFile)) > 60 * 5) { 52 if (!@rmdir($this->lockFile)) { 53 throw new ExceptionRuntimeInternal("Removing the lock failed ($this->lockFile)"); 54 } 55 } 56 if ($run++ == 5) { 57 // we waited 5 seconds for that lock 58 throw new ExceptionTimeOut("Unable to get the lock ($this->lockFile)"); 59 } 60 } 61 if ($this->perm) { 62 chmod($this->lockFile, $this->perm); 63 } 64 65 } 66 67 /** 68 * Release the indexer lock. 69 * 70 */ 71 function release() 72 { 73 @rmdir($this->lockFile); 74 } 75 76 public function isReleased(): bool 77 { 78 return !is_dir($this->lockFile); 79 } 80 81} 82