1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 08:52:39 +01:00

Remove all optimistic lock code from Lisk

Summary: We never use this and almost certainly never will. It's been in Lisk for ~7 years but is a solution in search of a problem. It causes a conflict with any DAO that has a `version` column.

Test Plan: Browsed around, performed inserts and updates. Edited a Phriction document.

Reviewers: vrana, btrahan

Reviewed By: btrahan

CC: aran, leslie.chong

Differential Revision: https://secure.phabricator.com/D3625
This commit is contained in:
epriestley 2012-10-04 13:55:43 -07:00
parent fe355f7905
commit ea32c541e4

View file

@ -182,7 +182,6 @@
*/ */
abstract class LiskDAO { abstract class LiskDAO {
const CONFIG_OPTIMISTIC_LOCKS = 'enable-locks';
const CONFIG_IDS = 'id-mechanism'; const CONFIG_IDS = 'id-mechanism';
const CONFIG_TIMESTAMPS = 'timestamps'; const CONFIG_TIMESTAMPS = 'timestamps';
const CONFIG_AUX_PHID = 'auxiliary-phid'; const CONFIG_AUX_PHID = 'auxiliary-phid';
@ -211,7 +210,6 @@ abstract class LiskDAO {
protected $id; protected $id;
protected $phid; protected $phid;
protected $version;
protected $dateCreated; protected $dateCreated;
protected $dateModified; protected $dateModified;
@ -329,7 +327,7 @@ abstract class LiskDAO {
/** /**
* Change Lisk behaviors, like optimistic locks and timestamps. If you want * Change Lisk behaviors, like ID configuration and timestamps. If you want
* to change these behaviors, you should override this method in your child * to change these behaviors, you should override this method in your child
* class and change the options you're interested in. For example: * class and change the options you're interested in. For example:
* *
@ -341,21 +339,6 @@ abstract class LiskDAO {
* *
* The available options are: * The available options are:
* *
* CONFIG_OPTIMISTIC_LOCKS
* Lisk automatically performs optimistic locking on objects, which protects
* you from read-modify-write concurrency problems. Lock failures are
* detected at write time and arise when two users read an object, then both
* save it. In theory, you should detect these failures and accommodate them
* in some sensible way (for instance, by showing the user differences
* between the original record and the copy they are trying to update, and
* prompting them to merge them). In practice, most Lisk tools are quick
* and dirty and don't get to that level of sophistication, but optimistic
* locks can still protect you from yourself sometimes. If you don't want
* to use optimistic locks, you can disable them. The performance cost of
* doing this locking is very very small (optimistic locks were chosen
* because they're simple and cheap, and highly optimized for the case where
* collisions are rare). By default, this option is OFF.
*
* CONFIG_IDS * CONFIG_IDS
* Lisk objects need to have a unique identifying ID. The three mechanisms * Lisk objects need to have a unique identifying ID. The three mechanisms
* available for generating this ID are IDS_AUTOINCREMENT (default, assumes * available for generating this ID are IDS_AUTOINCREMENT (default, assumes
@ -405,7 +388,6 @@ abstract class LiskDAO {
*/ */
protected function getConfiguration() { protected function getConfiguration() {
return array( return array(
self::CONFIG_OPTIMISTIC_LOCKS => false,
self::CONFIG_IDS => self::IDS_AUTOINCREMENT, self::CONFIG_IDS => self::IDS_AUTOINCREMENT,
self::CONFIG_TIMESTAMPS => true, self::CONFIG_TIMESTAMPS => true,
self::CONFIG_PARTIAL_OBJECTS => false, self::CONFIG_PARTIAL_OBJECTS => false,
@ -605,9 +587,8 @@ abstract class LiskDAO {
/** /**
* Reload an object from the database, discarding any changes to persistent * Reload an object from the database, discarding any changes to persistent
* properties. If the object uses optimistic locks and you are in a locking * properties. This is primarily useful after entering a transaction but
* mode while transactional, this will effectively synchronize the locks. * before applying changes to an object.
* This is pretty heady. It is unlikely you need to use this method.
* *
* @return this * @return this
* *
@ -619,24 +600,13 @@ abstract class LiskDAO {
throw new Exception("Unable to reload object that hasn't been loaded!"); throw new Exception("Unable to reload object that hasn't been loaded!");
} }
$use_locks = $this->getConfigOption(self::CONFIG_OPTIMISTIC_LOCKS); $result = $this->loadOneWhere(
'%C = %d',
if (!$use_locks) { $this->getIDKeyForUse(),
$result = $this->loadOneWhere( $this->getID());
'%C = %d',
$this->getIDKeyForUse(),
$this->getID());
} else {
$result = $this->loadOneWhere(
'%C = %d AND %C = %d',
$this->getIDKeyForUse(),
$this->getID(),
'version',
$this->getVersion());
}
if (!$result) { if (!$result) {
throw new AphrontQueryObjectMissingException($use_locks); throw new AphrontQueryObjectMissingException();
} }
return $this; return $this;
@ -952,10 +922,6 @@ abstract class LiskDAO {
unset($properties['id']); unset($properties['id']);
} }
if (!$this->getConfigOption(self::CONFIG_OPTIMISTIC_LOCKS)) {
unset($properties['version']);
}
if (!$this->getConfigOption(self::CONFIG_TIMESTAMPS)) { if (!$this->getConfigOption(self::CONFIG_TIMESTAMPS)) {
unset($properties['datecreated']); unset($properties['datecreated']);
unset($properties['datemodified']); unset($properties['datemodified']);
@ -1155,7 +1121,6 @@ abstract class LiskDAO {
*/ */
public function update() { public function update() {
$this->isEphemeralCheck(); $this->isEphemeralCheck();
$use_locks = $this->getConfigOption(self::CONFIG_OPTIMISTIC_LOCKS);
$this->willSaveObject(); $this->willSaveObject();
$data = $this->getPropertyValues(); $data = $this->getPropertyValues();
@ -1166,9 +1131,6 @@ abstract class LiskDAO {
$map = array(); $map = array();
foreach ($data as $k => $v) { foreach ($data as $k => $v) {
if ($use_locks && $k == 'version') {
continue;
}
$map[$k] = $v; $map[$k] = $v;
} }
@ -1179,31 +1141,16 @@ abstract class LiskDAO {
} }
$map = implode(', ', $map); $map = implode(', ', $map);
if ($use_locks) { $id = $this->getID();
$conn->query( $conn->query(
'UPDATE %T SET %Q, version = version + 1 WHERE %C = %d AND %C = %d', 'UPDATE %T SET %Q WHERE %C = '.(is_int($id) ? '%d' : '%s'),
$this->getTableName(), $this->getTableName(),
$map, $map,
$this->getIDKeyForUse(), $this->getIDKeyForUse(),
$this->getID(), $id);
'version', // We can't detect a missing object because updating an object without
$this->getVersion()); // changing any values doesn't affect rows. We could jiggle timestamps
if ($conn->getAffectedRows() !== 1) { // to catch this for objects which track them if we wanted.
throw new AphrontQueryObjectMissingException($use_locks);
}
$this->setVersion($this->getVersion() + 1);
} else {
$id = $this->getID();
$conn->query(
'UPDATE %T SET %Q WHERE %C = '.(is_int($id) ? '%d' : '%s'),
$this->getTableName(),
$map,
$this->getIDKeyForUse(),
$id);
// We can't detect a missing object because updating an object without
// changing any values doesn't affect rows. We could jiggle timestamps
// to catch this for objects which track them if we wanted.
}
$this->didWriteData(); $this->didWriteData();
@ -1274,10 +1221,6 @@ abstract class LiskDAO {
throw new Exception('Unknown CONFIG_IDs mechanism!'); throw new Exception('Unknown CONFIG_IDs mechanism!');
} }
if ($this->getConfigOption(self::CONFIG_OPTIMISTIC_LOCKS)) {
$data['version'] = 0;
}
$this->willWriteData($data); $this->willWriteData($data);
$conn = $this->establishConnection('w'); $conn = $this->establishConnection('w');
@ -1296,11 +1239,6 @@ abstract class LiskDAO {
$columns, $columns,
$data); $data);
// Update the object with the initial Version value
if ($this->getConfigOption(self::CONFIG_OPTIMISTIC_LOCKS)) {
$this->setVersion(0);
}
// Only use the insert id if this table is using auto-increment ids // Only use the insert id if this table is using auto-increment ids
if ($id_mechanism === self::IDS_AUTOINCREMENT) { if ($id_mechanism === self::IDS_AUTOINCREMENT) {
$this->setID($conn->getInsertID()); $this->setID($conn->getInsertID());
@ -1323,24 +1261,12 @@ abstract class LiskDAO {
*/ */
protected function shouldInsertWhenSaved() { protected function shouldInsertWhenSaved() {
$key_type = $this->getConfigOption(self::CONFIG_IDS); $key_type = $this->getConfigOption(self::CONFIG_IDS);
$use_locks = $this->getConfigOption(self::CONFIG_OPTIMISTIC_LOCKS);
if ($key_type == self::IDS_MANUAL) { if ($key_type == self::IDS_MANUAL) {
if ($use_locks) { throw new Exception(
// If we are manually keyed and the object has a version (which means 'You are using manual IDs. You must override the '.
// that it has been saved to the DB before), do an update, otherwise 'shouldInsertWhenSaved() method to properly detect '.
// perform an insert. 'when to insert a new record.');
if ($this->getID() && $this->getVersion() !== null) {
return false;
} else {
return true;
}
} else {
throw new Exception(
'You are not using optimistic locks, but are using manual IDs. You '.
'must override the shouldInsertWhenSaved() method to properly '.
'detect when to insert a new record.');
}
} else { } else {
return !$this->getID(); return !$this->getID();
} }