xref: /template/strap/ComboStrap/Lock.php (revision 9fc13f002cb71fbc6be15f1b2f0abb7436c08989)
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