X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FCore%2FLock%2FDatabaseLockDriver.php;h=a137ef12edcac6e6766af4f704128e3ce97085d3;hb=df5ea1fab0cefd3db0257a1774e944aee0dbd6d2;hp=8761a1479ee219ca24c86cace4481bc240fbe7d0;hpb=0218d16335cd4b873c3edd59fbcc110306d87e71;p=friendica.git diff --git a/src/Core/Lock/DatabaseLockDriver.php b/src/Core/Lock/DatabaseLockDriver.php index 8761a1479e..a137ef12ed 100644 --- a/src/Core/Lock/DatabaseLockDriver.php +++ b/src/Core/Lock/DatabaseLockDriver.php @@ -2,52 +2,60 @@ namespace Friendica\Core\Lock; -use dba; -use Friendica\Database\DBM; +use Friendica\Core\Cache; +use Friendica\Database\DBA; +use Friendica\Util\DateTimeFormat; /** * Locking driver that stores the locks in the database */ -class DatabaseLockDriver implements ILockDriver +class DatabaseLockDriver extends AbstractLockDriver { /** - * @brief Sets a lock for a given name + * The current ID of the process * - * @param string $key The Name of the lock - * @param integer $timeout Seconds until we give up - * - * @return boolean Was the lock successful? + * @var int + */ + private $pid; + + /** + * @param null|int $pid The Id of the current process (null means determine automatically) */ - public function acquireLock($key, $timeout = 120) + public function __construct($pid = null) + { + $this->pid = isset($pid) ? $pid : getmypid(); + } + + /** + * (@inheritdoc) + */ + public function acquireLock($key, $timeout = 120, $ttl = Cache::FIVE_MINUTES) { $got_lock = false; $start = time(); do { - dba::lock('locks'); - $lock = dba::selectFirst('locks', ['locked', 'pid'], ['name' => $key]); + DBA::lock('locks'); + $lock = DBA::selectFirst('locks', ['locked', 'pid'], ['`name` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]); - if (DBM::is_result($lock)) { + if (DBA::isResult($lock)) { if ($lock['locked']) { - // When the process id isn't used anymore, we can safely claim the lock for us. - if (!posix_kill($lock['pid'], 0)) { - $lock['locked'] = false; - } // We want to lock something that was already locked by us? So we got the lock. - if ($lock['pid'] == getmypid()) { + if ($lock['pid'] == $this->pid) { $got_lock = true; } } if (!$lock['locked']) { - dba::update('locks', ['locked' => true, 'pid' => getmypid()], ['name' => $key]); + DBA::update('locks', ['locked' => true, 'pid' => $this->pid, 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds')], ['name' => $key]); $got_lock = true; } - } elseif (!DBM::is_result($lock)) { - dba::insert('locks', ['name' => $key, 'locked' => true, 'pid' => getmypid()]); + } else { + DBA::insert('locks', ['name' => $key, 'locked' => true, 'pid' => $this->pid, 'expires' => DateTimeFormat::utc('now + ' . $ttl . 'seconds')]); $got_lock = true; + $this->markAcquire($key); } - dba::unlock(); + DBA::unlock(); if (!$got_lock && ($timeout > 0)) { usleep(rand(100000, 2000000)); @@ -58,26 +66,44 @@ class DatabaseLockDriver implements ILockDriver } /** - * @brief Removes a lock if it was set by us - * - * @param string $key Name of the lock - * - * @return mixed + * (@inheritdoc) */ - public function releaseLock($key) + public function releaseLock($key, $override = false) { - dba::update('locks', ['locked' => false, 'pid' => 0], ['name' => $key, 'pid' => getmypid()]); + if ($override) { + $where = ['name' => $key]; + } else { + $where = ['name' => $key, 'pid' => $this->pid]; + } + + DBA::delete('locks', $where); + + $this->markRelease($key); return; } /** - * @brief Removes all lock that were set by us - * - * @return void + * (@inheritdoc) */ public function releaseAll() { - dba::update('locks', ['locked' => false, 'pid' => 0], ['pid' => getmypid()]); + DBA::delete('locks', ['pid' => $this->pid]); + + $this->acquiredLocks = []; + } + + /** + * (@inheritdoc) + */ + public function isLocked($key) + { + $lock = DBA::selectFirst('locks', ['locked'], ['`name` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]); + + if (DBA::isResult($lock)) { + return $lock['locked'] !== false; + } else { + return false; + } } }