MDL-65722 core_lock: Avoid DB calls in postgres lock by using a hash
This commit is contained in:
@@ -33,9 +33,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* Postgres locking implementation using advisory locks. Some important points. Postgres has
|
||||
* 2 different forms of lock functions, some accepting a single int, and some accepting 2 ints. This implementation
|
||||
* uses the 2 int version so that it uses a separate namespace from the session locking. The second note,
|
||||
* is because postgres uses integer keys for locks, we first need to map strings to a unique integer. This is
|
||||
* done by storing the strings in the lock_db table and using the auto-id returned. There is a static cache for
|
||||
* id's in this function.
|
||||
* is because postgres uses integer keys for locks, we first need to map strings to a unique integer. This is done
|
||||
* using a prefix of a sha1 hash converted to an integer.
|
||||
*
|
||||
* @package core
|
||||
* @category lock
|
||||
@@ -127,44 +126,20 @@ class postgres_lock_factory implements lock_factory {
|
||||
}
|
||||
|
||||
/**
|
||||
* This function generates the unique index for a specific lock key.
|
||||
* Once an index is assigned to a key, it never changes - so this is
|
||||
* statically cached.
|
||||
* This function generates the unique index for a specific lock key using
|
||||
* a sha1 prefix converted to decimal.
|
||||
*
|
||||
* @param string $key
|
||||
* @return int
|
||||
* @throws \moodle_exception
|
||||
*/
|
||||
protected function get_index_from_key($key) {
|
||||
if (isset(self::$lockidcache[$key])) {
|
||||
return self::$lockidcache[$key];
|
||||
}
|
||||
|
||||
$index = 0;
|
||||
$record = $this->db->get_record('lock_db', array('resourcekey' => $key));
|
||||
if ($record) {
|
||||
$index = $record->id;
|
||||
}
|
||||
|
||||
if (!$index) {
|
||||
$record = new \stdClass();
|
||||
$record->resourcekey = $key;
|
||||
try {
|
||||
$index = $this->db->insert_record('lock_db', $record);
|
||||
} catch (\dml_exception $de) {
|
||||
// Race condition - never mind - now the value is guaranteed to exist.
|
||||
$record = $this->db->get_record('lock_db', array('resourcekey' => $key));
|
||||
if ($record) {
|
||||
$index = $record->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$index) {
|
||||
throw new \moodle_exception('Could not generate unique index for key');
|
||||
}
|
||||
|
||||
self::$lockidcache[$key] = $index;
|
||||
// A prefix of 7 hex chars is chosen as fffffff is the largest hex code
|
||||
// which when converted to decimal (268435455) fits inside a 4 byte int
|
||||
// which is the second param to pg_try_advisory_lock().
|
||||
$hash = substr(sha1($key), 0, 7);
|
||||
$index = hexdec($hash);
|
||||
return $index;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user