]> git.mxchange.org Git - friendica.git/blob - src/Core/Lock/DatabaseLockDriver.php
Merge pull request #6920 from nupplaphil/feature/basepath/hostname_config
[friendica.git] / src / Core / Lock / DatabaseLockDriver.php
1 <?php
2
3 namespace Friendica\Core\Lock;
4
5 use Friendica\Core\Cache;
6 use Friendica\Database\DBA;
7 use Friendica\Util\DateTimeFormat;
8
9 /**
10  * Locking driver that stores the locks in the database
11  */
12 class DatabaseLockDriver extends AbstractLockDriver
13 {
14         /**
15          * The current ID of the process
16          *
17          * @var int
18          */
19         private $pid;
20
21         /**
22          * @param null|int $pid The Id of the current process (null means determine automatically)
23          */
24         public function __construct($pid = null)
25         {
26                 $this->pid = isset($pid) ? $pid : getmypid();
27         }
28
29         /**
30          * (@inheritdoc)
31          */
32         public function acquireLock($key, $timeout = 120, $ttl = Cache::FIVE_MINUTES)
33         {
34                 $got_lock = false;
35                 $start = time();
36
37                 do {
38                         DBA::lock('locks');
39                         $lock = DBA::selectFirst('locks', ['locked', 'pid'], ['`name` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]);
40
41                         if (DBA::isResult($lock)) {
42                                 if ($lock['locked']) {
43                                         // We want to lock something that was already locked by us? So we got the lock.
44                                         if ($lock['pid'] == $this->pid) {
45                                                 $got_lock = true;
46                                         }
47                                 }
48                                 if (!$lock['locked']) {
49                                         DBA::update('locks', ['locked' => true, 'pid' => $this->pid, 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds')], ['name' => $key]);
50                                         $got_lock = true;
51                                 }
52                         } else {
53                                 DBA::insert('locks', ['name' => $key, 'locked' => true, 'pid' => $this->pid, 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds')]);
54                                 $got_lock = true;
55                                 $this->markAcquire($key);
56                         }
57
58                         DBA::unlock();
59
60                         if (!$got_lock && ($timeout > 0)) {
61                                 usleep(rand(100000, 2000000));
62                         }
63                 } while (!$got_lock && ((time() - $start) < $timeout));
64
65                 return $got_lock;
66         }
67
68         /**
69          * (@inheritdoc)
70          */
71         public function releaseLock($key, $override = false)
72         {
73                 if ($override) {
74                         $where = ['name' => $key];
75                 } else {
76                         $where = ['name' => $key, 'pid' => $this->pid];
77                 }
78
79                 $return = DBA::delete('locks', $where);
80
81                 $this->markRelease($key);
82
83                 return $return;
84         }
85
86         /**
87          * (@inheritdoc)
88          */
89         public function releaseAll()
90         {
91                 $return = DBA::delete('locks', ['pid' => $this->pid]);
92
93                 $this->acquiredLocks = [];
94
95                 return $return;
96         }
97
98         /**
99          * (@inheritdoc)
100          */
101         public function isLocked($key)
102         {
103                 $lock = DBA::selectFirst('locks', ['locked'], ['`name` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]);
104
105                 if (DBA::isResult($lock)) {
106                         return $lock['locked'] !== false;
107                 } else {
108                         return false;
109                 }
110         }
111 }