]> git.mxchange.org Git - friendica.git/blob - src/Core/Lock/DatabaseLockDriver.php
9b415753fceecec0663900c682a2e8d5618b1539
[friendica.git] / src / Core / Lock / DatabaseLockDriver.php
1 <?php
2
3 namespace Friendica\Core\Lock;
4
5 use dba;
6 use Friendica\Database\DBM;
7
8 /**
9  * Locking driver that stores the locks in the database
10  */
11 class DatabaseLockDriver extends AbstractLockDriver
12 {
13         /**
14          * @brief Sets a lock for a given name
15          *
16          * @param string  $key      The Name of the lock
17          * @param integer $timeout  Seconds until we give up
18          *
19          * @return boolean Was the lock successful?
20          */
21         public function acquireLock($key, $timeout = 120)
22         {
23                 $got_lock = false;
24                 $start = time();
25
26                 do {
27                         dba::lock('locks');
28                         $lock = dba::selectFirst('locks', ['locked', 'pid'], ['name' => $key]);
29
30                         if (DBM::is_result($lock)) {
31                                 if ($lock['locked']) {
32                                         // When the process id isn't used anymore, we can safely claim the lock for us.
33                                         if (!posix_kill($lock['pid'], 0)) {
34                                                 $lock['locked'] = false;
35                                         }
36                                         // We want to lock something that was already locked by us? So we got the lock.
37                                         if ($lock['pid'] == getmypid()) {
38                                                 $got_lock = true;
39                                         }
40                                 }
41                                 if (!$lock['locked']) {
42                                         dba::update('locks', ['locked' => true, 'pid' => getmypid()], ['name' => $key]);
43                                         $got_lock = true;
44                                 }
45                         } else {
46                                 dba::insert('locks', ['name' => $key, 'locked' => true, 'pid' => getmypid()]);
47                                 $got_lock = true;
48                         }
49
50                         dba::unlock();
51
52                         if (!$got_lock && ($timeout > 0)) {
53                                 usleep(rand(100000, 2000000));
54                         }
55                 } while (!$got_lock && ((time() - $start) < $timeout));
56
57                 $this->markAcquire($key);
58
59                 return $got_lock;
60         }
61
62         /**
63          * @brief Removes a lock if it was set by us
64          *
65          * @param string $key Name of the lock
66          *
67          * @return mixed
68          */
69         public function releaseLock($key)
70         {
71                 dba::delete('locks', ['locked' => false, 'pid' => 0], ['name' => $key, 'pid' => getmypid()]);
72
73                 $this->releaseLock($key);
74
75                 return;
76         }
77
78         /**
79          * @brief Removes all lock that were set by us
80          *
81          * @return void
82          */
83         public function releaseAll()
84         {
85                 dba::delete('locks', ['locked' => false, 'pid' => 0], ['pid' => getmypid()]);
86
87                 $this->acquiredLocks = [];
88         }
89 }