Changeset View
Changeset View
Standalone View
Standalone View
branches/5.2.x/core/kernel/utility/temp_handler.php
Show First 20 Lines • Show All 563 Lines • ▼ Show 20 Line(s) | |||||
* @param Array $master | * @param Array $master | ||||
* @param string $parent_prefix | * @param string $parent_prefix | ||||
* @param Array $current_ids | * @param Array $current_ids | ||||
* @return Array | * @return Array | ||||
* @access public | * @access public | ||||
*/ | */ | ||||
public function DoCopyTempToOriginal($master, $parent_prefix = null, $current_ids = Array()) | public function DoCopyTempToOriginal($master, $parent_prefix = null, $current_ids = Array()) | ||||
{ | { | ||||
if ( !$current_ids ) { | $current_ids = $this->getMainIDs($master, $current_ids); | ||||
$query = 'SELECT ' . $master['IdField'] . ' FROM ' . $this->GetTempName($master['TableName']); | |||||
if ( isset($master['Constrain']) ) { | |||||
$query .= ' WHERE ' . $master['Constrain']; | |||||
} | |||||
$current_ids = $this->Conn->GetCol($query); | |||||
} | |||||
$table_sig = $master['TableName'] . (isset($master['Constrain']) ? $master['Constrain'] : ''); | $table_sig = $master['TableName'] . (isset($master['Constrain']) ? $master['Constrain'] : ''); | ||||
if ($current_ids) { | if ($current_ids) { | ||||
// delete all ids from live table - for MasterTable ONLY! | // delete all ids from live table - for MasterTable ONLY! | ||||
// because items from Sub Tables get deteleted in CopySubTablesToLive !BY ForeignKey! | // because items from Sub Tables get deteleted in CopySubTablesToLive !BY ForeignKey! | ||||
if ( $master['TableName'] == $this->MasterTable ) { | if ( $master['TableName'] == $this->MasterTable ) { | ||||
$this->RaiseEvent('OnBeforeDeleteFromLive', $master['Prefix'], '', $current_ids); | $this->RaiseEvent('OnBeforeDeleteFromLive', $master['Prefix'], '', $current_ids); | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Line(s) | |||||
if ( !isset($this->savedIDs[ $master['Prefix'] ]) ) { | if ( !isset($this->savedIDs[ $master['Prefix'] ]) ) { | ||||
$this->savedIDs[ $master['Prefix'] ] = Array (); | $this->savedIDs[ $master['Prefix'] ] = Array (); | ||||
} | } | ||||
return $this->savedIDs[ $master['Prefix'] ]; | return $this->savedIDs[ $master['Prefix'] ]; | ||||
} | } | ||||
/** | /** | ||||
* Returns IDs from main temp table. | |||||
* | |||||
* @param array $master Master table configuration. | |||||
* @param array $current_ids User provided IDs. | |||||
* | |||||
* @return array | |||||
*/ | |||||
protected function getMainIDs(array $master, array $current_ids = array()) | |||||
{ | |||||
if ( $current_ids ) { | |||||
return $current_ids; | |||||
} | |||||
$sql = 'SELECT ' . $master['IdField'] . ' | |||||
FROM ' . $this->GetTempName($master['TableName']); | |||||
if ( isset($master['Constrain']) ) { | |||||
$sql .= ' WHERE ' . $master['Constrain']; | |||||
} | |||||
return $this->Conn->GetCol($sql); | |||||
} | |||||
/** | |||||
* Create separate connection for locking purposes | * Create separate connection for locking purposes | ||||
* | * | ||||
* @return kDBConnection | * @return kDBConnection | ||||
*/ | */ | ||||
function &_getSeparateConnection() | function &_getSeparateConnection() | ||||
{ | { | ||||
static $connection = null; | static $connection = null; | ||||
▲ Show 20 Lines • Show All 178 Lines • ▼ Show 20 Line(s) | |||||
} | } | ||||
function SaveEdit($master_ids = Array()) | function SaveEdit($master_ids = Array()) | ||||
{ | { | ||||
// SessionKey field is required for deleting records from expired sessions | // SessionKey field is required for deleting records from expired sessions | ||||
$conn =& $this->_getSeparateConnection(); | $conn =& $this->_getSeparateConnection(); | ||||
$sleep_count = 0; | $sleep_count = 0; | ||||
$master_ids = $this->getMainIDs($this->Tables, $master_ids); | |||||
do { | do { | ||||
// acquire lock | // acquire lock | ||||
$conn->ChangeQuery('LOCK TABLES '.TABLE_PREFIX.'Semaphores WRITE'); | $conn->ChangeQuery('LOCK TABLES '.TABLE_PREFIX.'Semaphores WRITE'); | ||||
$sql = 'SELECT SessionKey | $another_coping_active = false; | ||||
$sql = 'SELECT MainIDs | |||||
FROM ' . TABLE_PREFIX . 'Semaphores | FROM ' . TABLE_PREFIX . 'Semaphores | ||||
WHERE (MainPrefix = ' . $conn->qstr($this->Tables['Prefix']) . ')'; | WHERE MainPrefix = ' . $conn->qstr($this->Tables['Prefix']) . ' AND MainIDs <> "0"'; | ||||
$another_coping_active = $conn->GetOne($sql); | $other_semaphores_main_ids = $conn->GetCol($sql); | ||||
foreach ( $other_semaphores_main_ids as $other_semaphore_main_ids ) { | |||||
$other_semaphore_main_ids = explode(',', $other_semaphore_main_ids); | |||||
if ( array_intersect($master_ids, $other_semaphore_main_ids) ) { | |||||
$another_coping_active = true; | |||||
break; | |||||
} | |||||
} | |||||
if ($another_coping_active) { | if ($another_coping_active) { | ||||
// another user is coping data from temp table to live -> release lock and try again after 1 second | // another user is coping data from temp table to live -> release lock and try again after 1 second | ||||
$conn->ChangeQuery('UNLOCK TABLES'); | $conn->ChangeQuery('UNLOCK TABLES'); | ||||
$sleep_count++; | $sleep_count++; | ||||
sleep(1); | sleep(1); | ||||
} | } | ||||
} while ($another_coping_active && ($sleep_count <= 30)); | } while ($another_coping_active && ($sleep_count <= 30)); | ||||
if ($sleep_count > 30) { | if ($sleep_count > 30) { | ||||
// another coping process failed to finished in 30 seconds | // another coping process failed to finished in 30 seconds | ||||
$error_message = $this->Application->Phrase('la_error_TemporaryTableCopyingFailed'); | $error_message = $this->Application->Phrase('la_error_TemporaryTableCopyingFailed'); | ||||
$this->Application->SetVar('_temp_table_message', $error_message); | $this->Application->SetVar('_temp_table_message', $error_message); | ||||
return false; | return false; | ||||
} | } | ||||
// mark, that we are coping from temp to live right now, so other similar attempt (from another script) will fail | // mark, that we are coping from temp to live right now, so other similar attempt (from another script) will fail | ||||
$fields_hash = Array ( | $fields_hash = Array ( | ||||
'SessionKey' => $this->Application->GetSID(), | 'SessionKey' => $this->Application->GetSID(), | ||||
'Timestamp' => adodb_mktime(), | 'Timestamp' => adodb_mktime(), | ||||
'MainPrefix' => $this->Tables['Prefix'], | 'MainPrefix' => $this->Tables['Prefix'], | ||||
'MainIDs' => implode(',', $master_ids), | |||||
); | ); | ||||
$conn->doInsert($fields_hash, TABLE_PREFIX.'Semaphores'); | $conn->doInsert($fields_hash, TABLE_PREFIX.'Semaphores'); | ||||
$semaphore_id = $conn->getInsertID(); | $semaphore_id = $conn->getInsertID(); | ||||
// unlock table now to prevent permanent lock in case, when coping will end with SQL error in the middle | // unlock table now to prevent permanent lock in case, when coping will end with SQL error in the middle | ||||
$conn->ChangeQuery('UNLOCK TABLES'); | $conn->ChangeQuery('UNLOCK TABLES'); | ||||
▲ Show 20 Lines • Show All 101 Lines • Show Last 20 Lines |