xref: /plugin/combo/ComboStrap/Lock.php (revision aea52b497ecf7ce8a15fd6f9dad705aee722f51f)
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