3 namespace Friendica\Core\Lock;
5 use Friendica\Core\Cache;
6 use Friendica\Database\DBA;
7 use Friendica\Util\DateTimeFormat;
10 * Locking driver that stores the locks in the database
12 class DatabaseLockDriver extends AbstractLockDriver
15 * The current ID of the process
22 * @param null|int $pid The Id of the current process (null means determine automatically)
24 public function __construct($pid = null)
26 $this->pid = isset($pid) ? $pid : getmypid();
32 public function acquireLock($key, $timeout = 120, $ttl = Cache::FIVE_MINUTES)
39 $lock = DBA::selectFirst('locks', ['locked', 'pid'], ['`name` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]);
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) {
48 if (!$lock['locked']) {
49 DBA::update('locks', ['locked' => true, 'pid' => $this->pid, 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds')], ['name' => $key]);
53 DBA::insert('locks', ['name' => $key, 'locked' => true, 'pid' => $this->pid, 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds')]);
55 $this->markAcquire($key);
60 if (!$got_lock && ($timeout > 0)) {
61 usleep(rand(100000, 2000000));
63 } while (!$got_lock && ((time() - $start) < $timeout));
71 public function releaseLock($key)
73 DBA::delete('locks', ['name' => $key, 'pid' => $this->pid]);
75 $this->markRelease($key);
83 public function releaseAll()
85 DBA::delete('locks', ['pid' => $this->pid]);
87 $this->acquiredLocks = [];
93 public function isLocked($key)
95 $lock = DBA::selectFirst('locks', ['locked'], ['`name` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]);
97 if (DBA::isResult($lock)) {
98 return $lock['locked'] !== false;