mirror of
https://github.com/phpbb/phpbb.git
synced 2025-06-28 06:08:52 +00:00
[ticket/11495] Acquire locks for operations that manipulate the tree
PHPBB3-11495
This commit is contained in:
parent
153b29c6c9
commit
b28180be1d
1 changed files with 66 additions and 9 deletions
|
@ -20,9 +20,18 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
/** @var phpbb_db_driver*/
|
/** @var phpbb_db_driver*/
|
||||||
protected $db;
|
protected $db;
|
||||||
|
|
||||||
|
/** @var phpbb_lock_db */
|
||||||
|
protected $lock;
|
||||||
|
|
||||||
/** @var String */
|
/** @var String */
|
||||||
protected $table_name;
|
protected $table_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefix for the language keys returned by exceptions
|
||||||
|
* @var String
|
||||||
|
*/
|
||||||
|
protected $message_prefix = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Column names in the table
|
* Column names in the table
|
||||||
* @var String
|
* @var String
|
||||||
|
@ -145,6 +154,11 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$this->lock->acquire())
|
||||||
|
{
|
||||||
|
throw new phpbb_nestedset_exception($this->message_prefix . 'LOCK_FAILED_ACQUIRE');
|
||||||
|
}
|
||||||
|
|
||||||
$action = ($delta > 0) ? 'move_up' : 'move_down';
|
$action = ($delta > 0) ? 'move_up' : 'move_down';
|
||||||
$delta = abs($delta);
|
$delta = abs($delta);
|
||||||
|
|
||||||
|
@ -180,6 +194,7 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
|
|
||||||
if (is_null($target))
|
if (is_null($target))
|
||||||
{
|
{
|
||||||
|
$this->lock->release();
|
||||||
// The item is already on top or bottom
|
// The item is already on top or bottom
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -231,6 +246,8 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
" . $this->get_sql_where();
|
" . $this->get_sql_where();
|
||||||
$this->db->sql_query($sql);
|
$this->db->sql_query($sql);
|
||||||
|
|
||||||
|
$this->lock->release();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,11 +277,17 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$this->lock->acquire())
|
||||||
|
{
|
||||||
|
throw new phpbb_nestedset_exception($this->message_prefix . 'LOCK_FAILED_ACQUIRE');
|
||||||
|
}
|
||||||
|
|
||||||
$move_items = array_keys($this->get_branch_data($current_parent, 'children', true, false));
|
$move_items = array_keys($this->get_branch_data($current_parent, 'children', true, false));
|
||||||
|
|
||||||
if (in_array($new_parent[$this->column_item_id], $move_items))
|
if (in_array($new_parent[$this->column_item_id], $move_items))
|
||||||
{
|
{
|
||||||
throw new phpbb_nestedset_exception('INVALID_PARENT');
|
$this->lock->release();
|
||||||
|
throw new phpbb_nestedset_exception($this->message_prefix . 'INVALID_PARENT');
|
||||||
}
|
}
|
||||||
|
|
||||||
$diff = sizeof($move_items) * 2;
|
$diff = sizeof($move_items) * 2;
|
||||||
|
@ -272,7 +295,7 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
|
|
||||||
$this->db->sql_transaction('begin');
|
$this->db->sql_transaction('begin');
|
||||||
|
|
||||||
$this->remove_subset($move_items, $current_parent, false);
|
$this->remove_subset($move_items, $current_parent, false, true);
|
||||||
|
|
||||||
if ($new_parent[$this->column_item_id])
|
if ($new_parent[$this->column_item_id])
|
||||||
{
|
{
|
||||||
|
@ -287,10 +310,11 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
if (!$new_parent)
|
if (!$new_parent)
|
||||||
{
|
{
|
||||||
$this->db->sql_transaction('rollback');
|
$this->db->sql_transaction('rollback');
|
||||||
throw new phpbb_nestedset_exception('INVALID_PARENT');
|
$this->lock->release();
|
||||||
|
throw new phpbb_nestedset_exception($this->message_prefix . 'INVALID_PARENT');
|
||||||
}
|
}
|
||||||
|
|
||||||
$new_right_id = $this->prepare_adding_subset($move_items, $new_parent);
|
$new_right_id = $this->prepare_adding_subset($move_items, $new_parent, true);
|
||||||
|
|
||||||
if ($new_right_id > $current_parent[$this->column_right_id])
|
if ($new_right_id > $current_parent[$this->column_right_id])
|
||||||
{
|
{
|
||||||
|
@ -324,6 +348,7 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
$this->db->sql_query($sql);
|
$this->db->sql_query($sql);
|
||||||
|
|
||||||
$this->db->sql_transaction('commit');
|
$this->db->sql_transaction('commit');
|
||||||
|
$this->lock->release();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -333,11 +358,17 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
*/
|
*/
|
||||||
public function set_parent(array $item, array $new_parent)
|
public function set_parent(array $item, array $new_parent)
|
||||||
{
|
{
|
||||||
|
if (!$this->lock->acquire())
|
||||||
|
{
|
||||||
|
throw new phpbb_nestedset_exception($this->message_prefix . 'LOCK_FAILED_ACQUIRE');
|
||||||
|
}
|
||||||
|
|
||||||
$move_items = array_keys($this->get_branch_data($item, 'children'));
|
$move_items = array_keys($this->get_branch_data($item, 'children'));
|
||||||
|
|
||||||
if (in_array($new_parent[$this->column_item_id], $move_items))
|
if (in_array($new_parent[$this->column_item_id], $move_items))
|
||||||
{
|
{
|
||||||
throw new phpbb_nestedset_exception('INVALID_PARENT');
|
$this->lock->release();
|
||||||
|
throw new phpbb_nestedset_exception($this->message_prefix . 'INVALID_PARENT');
|
||||||
}
|
}
|
||||||
|
|
||||||
$diff = sizeof($move_items) * 2;
|
$diff = sizeof($move_items) * 2;
|
||||||
|
@ -345,7 +376,7 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
|
|
||||||
$this->db->sql_transaction('begin');
|
$this->db->sql_transaction('begin');
|
||||||
|
|
||||||
$this->remove_subset($move_items, $item, false);
|
$this->remove_subset($move_items, $item, false, true);
|
||||||
|
|
||||||
if ($new_parent[$this->column_item_id])
|
if ($new_parent[$this->column_item_id])
|
||||||
{
|
{
|
||||||
|
@ -360,10 +391,11 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
if (!$new_parent)
|
if (!$new_parent)
|
||||||
{
|
{
|
||||||
$this->db->sql_transaction('rollback');
|
$this->db->sql_transaction('rollback');
|
||||||
throw new phpbb_nestedset_exception('INVALID_PARENT');
|
$this->lock->release();
|
||||||
|
throw new phpbb_nestedset_exception($this->message_prefix . 'INVALID_PARENT');
|
||||||
}
|
}
|
||||||
|
|
||||||
$new_right_id = $this->prepare_adding_subset($move_items, $new_parent);
|
$new_right_id = $this->prepare_adding_subset($move_items, $new_parent, true);
|
||||||
|
|
||||||
if ($new_right_id > (int) $item[$this->column_right_id])
|
if ($new_right_id > (int) $item[$this->column_right_id])
|
||||||
{
|
{
|
||||||
|
@ -397,6 +429,7 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
$this->db->sql_query($sql);
|
$this->db->sql_query($sql);
|
||||||
|
|
||||||
$this->db->sql_transaction('commit');
|
$this->db->sql_transaction('commit');
|
||||||
|
$this->lock->release();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -497,10 +530,16 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
* @param array $subset_items Subset of items to remove
|
* @param array $subset_items Subset of items to remove
|
||||||
* @param array $bounding_item Item containing the right bound of the subset
|
* @param array $bounding_item Item containing the right bound of the subset
|
||||||
* @param bool $set_subset_zero Should the parent, left and right id of the item be set to 0, or kept unchanged?
|
* @param bool $set_subset_zero Should the parent, left and right id of the item be set to 0, or kept unchanged?
|
||||||
|
* @param bool $table_already_locked Is the table already locked, or should we acquire a new lock?
|
||||||
* @return null
|
* @return null
|
||||||
*/
|
*/
|
||||||
protected function remove_subset(array $subset_items, array $bounding_item, $set_subset_zero = true)
|
protected function remove_subset(array $subset_items, array $bounding_item, $set_subset_zero = true, $table_already_locked = false)
|
||||||
{
|
{
|
||||||
|
if (!$table_already_locked && !$this->lock->acquire())
|
||||||
|
{
|
||||||
|
throw new phpbb_nestedset_exception($this->message_prefix . 'LOCK_FAILED_ACQUIRE');
|
||||||
|
}
|
||||||
|
|
||||||
$diff = sizeof($subset_items) * 2;
|
$diff = sizeof($subset_items) * 2;
|
||||||
$sql_subset_items = $this->db->sql_in_set($this->column_item_id, $subset_items);
|
$sql_subset_items = $this->db->sql_in_set($this->column_item_id, $subset_items);
|
||||||
$sql_not_subset_items = $this->db->sql_in_set($this->column_item_id, $subset_items, true);
|
$sql_not_subset_items = $this->db->sql_in_set($this->column_item_id, $subset_items, true);
|
||||||
|
@ -526,6 +565,11 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
' . $this->column_item_parents . " = ''
|
' . $this->column_item_parents . " = ''
|
||||||
" . ((!$set_subset_zero) ? ' WHERE ' . $sql_not_subset_items . ' ' . $this->get_sql_where('AND') : $this->get_sql_where('WHERE'));
|
" . ((!$set_subset_zero) ? ' WHERE ' . $sql_not_subset_items . ' ' . $this->get_sql_where('AND') : $this->get_sql_where('WHERE'));
|
||||||
$this->db->sql_query($sql);
|
$this->db->sql_query($sql);
|
||||||
|
|
||||||
|
if (!$table_already_locked)
|
||||||
|
{
|
||||||
|
$this->lock->release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -581,6 +625,12 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
{
|
{
|
||||||
if ($reset_ids)
|
if ($reset_ids)
|
||||||
{
|
{
|
||||||
|
if (!$this->lock->acquire())
|
||||||
|
{
|
||||||
|
throw new phpbb_nestedset_exception($this->message_prefix . 'LOCK_FAILED_ACQUIRE');
|
||||||
|
}
|
||||||
|
$this->db->sql_transaction('begin');
|
||||||
|
|
||||||
$sql = 'UPDATE ' . $this->table_name . '
|
$sql = 'UPDATE ' . $this->table_name . '
|
||||||
SET ' . $this->db->sql_build_array('UPDATE', array(
|
SET ' . $this->db->sql_build_array('UPDATE', array(
|
||||||
$this->column_left_id => 0,
|
$this->column_left_id => 0,
|
||||||
|
@ -627,6 +677,13 @@ abstract class phpbb_nestedset_base implements phpbb_nestedset_interface
|
||||||
}
|
}
|
||||||
$this->db->sql_freeresult($result);
|
$this->db->sql_freeresult($result);
|
||||||
|
|
||||||
|
|
||||||
|
if ($reset_ids)
|
||||||
|
{
|
||||||
|
$this->db->sql_transaction('commit');
|
||||||
|
$this->lock->release();
|
||||||
|
}
|
||||||
|
|
||||||
return $new_id;
|
return $new_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue