MDL-65722 core_lock: Avoid DB calls in postgres lock by using a hash

This commit is contained in:
Brendan Heywood
2019-12-11 12:49:03 +11:00
parent 8cf4c97217
commit cdf3fe7b7e
+9 -34
View File
@@ -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;
}