diff --git a/src/applications/repository/storage/PhabricatorRepositoryWorkingCopyVersion.php b/src/applications/repository/storage/PhabricatorRepositoryWorkingCopyVersion.php index da5d54b57d..e297dfbf0e 100644 --- a/src/applications/repository/storage/PhabricatorRepositoryWorkingCopyVersion.php +++ b/src/applications/repository/storage/PhabricatorRepositoryWorkingCopyVersion.php @@ -1,218 +1,220 @@ false, self::CONFIG_COLUMN_SCHEMA => array( 'repositoryVersion' => 'uint32', 'isWriting' => 'bool', 'writeProperties' => 'text?', 'lockOwner' => 'text255?', ), self::CONFIG_KEY_SCHEMA => array( 'key_workingcopy' => array( 'columns' => array('repositoryPHID', 'devicePHID'), 'unique' => true, ), ), ) + parent::getConfiguration(); } public function getWriteProperty($key, $default = null) { // The "writeProperties" don't currently get automatically serialized or // deserialized. Perhaps they should. try { $properties = phutil_json_decode($this->writeProperties); return idx($properties, $key, $default); } catch (Exception $ex) { return null; } } public static function loadVersions($repository_phid) { $version = new self(); $conn_w = $version->establishConnection('w'); $table = $version->getTableName(); // This is a normal read, but force it to come from the master. $rows = queryfx_all( $conn_w, 'SELECT * FROM %T WHERE repositoryPHID = %s', $table, $repository_phid); return $version->loadAllFromArray($rows); } public static function loadWriter($repository_phid) { $version = new self(); $conn_w = $version->establishConnection('w'); $table = $version->getTableName(); // We're forcing this read to go to the master. $row = queryfx_one( $conn_w, 'SELECT * FROM %T WHERE repositoryPHID = %s AND isWriting = 1 LIMIT 1', $table, $repository_phid); if (!$row) { return null; } return $version->loadFromArray($row); } public static function getReadLock($repository_phid, $device_phid) { - $repository_hash = PhabricatorHash::digestForIndex($repository_phid); - $device_hash = PhabricatorHash::digestForIndex($device_phid); - $lock_key = "repo.read({$repository_hash}, {$device_hash})"; + $parameters = array( + 'repositoryPHID' => $repository_phid, + 'devicePHID' => $device_phid, + ); - return PhabricatorGlobalLock::newLock($lock_key); + return PhabricatorGlobalLock::newLock('repo.read', $parameters); } public static function getWriteLock($repository_phid) { - $repository_hash = PhabricatorHash::digestForIndex($repository_phid); - $lock_key = "repo.write({$repository_hash})"; + $parameters = array( + 'repositoryPHID' => $repository_phid, + ); - return PhabricatorGlobalLock::newLock($lock_key); + return PhabricatorGlobalLock::newLock('repo.write', $parameters); } /** * Before a write, set the "isWriting" flag. * * This allows us to detect when we lose a node partway through a write and * may have committed and acknowledged a write on a node that lost the lock * partway through the write and is no longer reachable. * * In particular, if a node loses its connection to the database the global * lock is released by default. This is a durable lock which stays locked * by default. */ public static function willWrite( AphrontDatabaseConnection $locked_connection, $repository_phid, $device_phid, array $write_properties, $lock_owner) { $version = new self(); $table = $version->getTableName(); queryfx( $locked_connection, 'INSERT INTO %T (repositoryPHID, devicePHID, repositoryVersion, isWriting, writeProperties, lockOwner) VALUES (%s, %s, %d, %d, %s, %s) ON DUPLICATE KEY UPDATE isWriting = VALUES(isWriting), writeProperties = VALUES(writeProperties), lockOwner = VALUES(lockOwner)', $table, $repository_phid, $device_phid, 0, 1, phutil_json_encode($write_properties), $lock_owner); } /** * After a write, update the version and release the "isWriting" lock. */ public static function didWrite( $repository_phid, $device_phid, $old_version, $new_version, $lock_owner) { $version = new self(); $conn_w = $version->establishConnection('w'); $table = $version->getTableName(); queryfx( $conn_w, 'UPDATE %T SET repositoryVersion = %d, isWriting = 0, lockOwner = NULL WHERE repositoryPHID = %s AND devicePHID = %s AND repositoryVersion = %d AND isWriting = 1 AND lockOwner = %s', $table, $new_version, $repository_phid, $device_phid, $old_version, $lock_owner); } /** * After a fetch, set the local version to the fetched version. */ public static function updateVersion( $repository_phid, $device_phid, $new_version) { $version = new self(); $conn_w = $version->establishConnection('w'); $table = $version->getTableName(); queryfx( $conn_w, 'INSERT INTO %T (repositoryPHID, devicePHID, repositoryVersion, isWriting) VALUES (%s, %s, %d, %d) ON DUPLICATE KEY UPDATE repositoryVersion = VALUES(repositoryVersion)', $table, $repository_phid, $device_phid, $new_version, 0); } /** * Explicitly demote a device. */ public static function demoteDevice( $repository_phid, $device_phid) { $version = new self(); $conn_w = $version->establishConnection('w'); $table = $version->getTableName(); queryfx( $conn_w, 'DELETE FROM %T WHERE repositoryPHID = %s AND devicePHID = %s', $table, $repository_phid, $device_phid); } }