diff --git a/framework/mutex/PgsqlMutex.php b/framework/mutex/PgsqlMutex.php new file mode 100644 index 0000000000..c98dadbe55 --- /dev/null +++ b/framework/mutex/PgsqlMutex.php @@ -0,0 +1,93 @@ + [ + * 'db' => [ + * 'class' => 'yii\db\Connection', + * 'dsn' => 'pgsql:host=127.0.0.1;dbname=demo', + * ] + * 'mutex' => [ + * 'class' => 'yii\mutex\PgsqlMutex', + * ], + * ], + * ] + * ``` + * + * @see Mutex + * + * @author nineinchnick + * @since 2.0.5 + */ +class PgsqlMutex extends DbMutex +{ + /** + * Initializes PgSQL specific mutex component implementation. + * @throws InvalidConfigException if [[db]] is not PgSQL connection. + */ + public function init() + { + parent::init(); + if ($this->db->driverName !== 'pgsql') { + throw new InvalidConfigException('In order to use PgsqlMutex connection must be configured to use PgSQL database.'); + } + } + + /** + * Converts a string into two 32 bit integer keys using the SHA1 hash function. + * @param string $name + * @return array contains two 32 bit integer keys + */ + private function getKeysFromName($name) + { + return array_values(unpack('N2', sha1($name, true))); + } + + /** + * Acquires lock by given name. + * @param string $name of the lock to be acquired. + * @param integer $timeout to wait for lock to become released. + * @return boolean acquiring result. + * @see http://www.postgresql.org/docs/9.0/static/functions-admin.html + */ + protected function acquireLock($name, $timeout = 0) + { + if ($timeout !== 0) { + throw new InvalidParamException('PgsqlMutex does not support timeout.'); + } + list($key1, $key2) = $this->getKeysFromName($name); + return (bool) $this->db + ->createCommand('SELECT pg_try_advisory_lock(:key1, :key2)', [':key1' => $key1, ':key2' => $key2]) + ->queryScalar(); + } + + /** + * Releases lock by given name. + * @param string $name of the lock to be released. + * @return boolean release result. + * @see http://www.postgresql.org/docs/9.0/static/functions-admin.html + */ + protected function releaseLock($name) + { + list($key1, $key2) = $this->getKeysFromName($name); + return (bool) $this->db + ->createCommand('SELECT pg_advisory_unlock(:key1, :key2)', [':key1' => $key1, ':key2' => $key2]) + ->queryScalar(); + } +}