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