Page MenuHomeIn-Portal Phabricator

D440.id1131.diff
No OneTemporary

File Metadata

Created
Thu, Feb 6, 9:12 PM

D440.id1131.diff

Index: core/admin_templates/config/custom_variables.tpl
===================================================================
--- core/admin_templates/config/custom_variables.tpl
+++ core/admin_templates/config/custom_variables.tpl
@@ -143,4 +143,8 @@
<inp2:m_DefineElement name="cf_AllowAdminConsoleInterfaceChange_value">
<inp2:m_RenderElement name="cf_default_value" pass_params="1"/> <label for="_cb_<inp2:InputName name='VariableValue'/>"><inp2:m_Phrase name="la_AllowChangingAdminConsoleInterface"/></label>
-</inp2:m_DefineElement>
\ No newline at end of file
+</inp2:m_DefineElement>
+
+<inp2:m_DefineElement name="cf_SemaphoreLifetimeInSeconds_value">
+ <inp2:m_RenderElement name="cf_default_value" pass_params="1"/> <inp2:m_Phrase name="la_text_seconds"/>
+</inp2:m_DefineElement>
Index: core/install/english.lang
===================================================================
--- core/install/english.lang
+++ core/install/english.lang
@@ -203,6 +203,7 @@
<PHRASE Label="la_config_require_ssl" Module="Core" Type="1">UmVxdWlyZSBTU0wgZm9yIGxvZ2luICYgY2hlY2tvdXQ=</PHRASE>
<PHRASE Label="la_config_ResizableFrames" Module="Core" Type="1">RnJhbWVzIGluIGFkbWluaXN0cmF0aXZlIGNvbnNvbGUgYXJlIHJlc2l6YWJsZQ==</PHRASE>
<PHRASE Label="la_config_Search_MinKeyword_Length" Module="Core" Type="1">TWluaW1hbCBTZWFyY2ggS2V5d29yZCBMZW5ndGg=</PHRASE>
+ <PHRASE Label="la_config_SemaphoreLifetimeInSeconds" Module="Core" Type="1" Hint="VGltZSwgYWZ0ZXIgd2hpY2ggc3RhbGUgc2VtYXBob3JlcyBhcmUgYXV0b21hdGljYWxseSBkZWxldGVkLg==">U2VtYXBob3JlIEluYWN0aXZpdHkgVGltZW91dA==</PHRASE>
<PHRASE Label="la_config_SessionBrowserSignatureCheck" Module="Core" Type="1">U2Vzc2lvbiBTZWN1cml0eSBDaGVjayBiYXNlZCBvbiBCcm93c2VyIFNpZ25hdHVyZQ==</PHRASE>
<PHRASE Label="la_config_SessionCookieDomains" Module="Core" Type="1">U2Vzc2lvbiBDb29raWUgRG9tYWlucyAoc2luZ2xlIGRvbWFpbiBwZXIgbGluZSk=</PHRASE>
<PHRASE Label="la_config_SessionIPAddressCheck" Module="Core" Type="1">U2Vzc2lvbiBTZWN1cml0eSBDaGVjayBiYXNlZCBvbiBJUA==</PHRASE>
@@ -1377,6 +1378,7 @@
<PHRASE Label="la_Text_Reviews" Module="Core" Type="1">Q29tbWVudHM=</PHRASE>
<PHRASE Label="la_Text_RootCategory" Module="Core" Type="1">TW9kdWxlIFJvb3QgU2VjdGlvbg==</PHRASE>
<PHRASE Label="la_text_Save" Module="Core" Type="1">U2F2ZQ==</PHRASE>
+ <PHRASE Label="la_text_seconds" Module="Core" Type="1">c2Vjb25kcw==</PHRASE>
<PHRASE Label="la_Text_Select" Module="Core" Type="1">U2VsZWN0</PHRASE>
<PHRASE Label="la_text_sess_expired" Module="Core" Type="1">U2Vzc2lvbiBFeHBpcmVk</PHRASE>
<PHRASE Label="la_Text_Simple" Module="Core" Type="1">U2ltcGxl</PHRASE>
Index: core/install/install_data.sql
===================================================================
--- core/install/install_data.sql
+++ core/install/install_data.sql
@@ -100,6 +100,7 @@
INSERT INTO SystemSettings VALUES(DEFAULT, 'Backup_Path', '/home/alex/web/in-portal.rc/system/backupdata', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsSystem', 'la_config_backup_path', 'text', '', '', 60.07, 0, 1, NULL);
INSERT INTO SystemSettings VALUES(DEFAULT, 'SystemTagCache', '0', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsSystem', 'la_prompt_syscache_enable', 'checkbox', NULL, NULL, 60.08, 0, 0, NULL);
INSERT INTO SystemSettings VALUES(DEFAULT, 'SocketBlockingMode', '0', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsSystem', 'la_prompt_socket_blocking_mode', 'checkbox', NULL, NULL, 60.09, 0, 0, NULL);
+INSERT INTO SystemSettings VALUES(DEFAULT, 'SemaphoreLifetimeInSeconds', '300', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsSystem', 'la_config_SemaphoreLifetimeInSeconds', 'text', '', 'style=\"width: 50px;\"', 60.1, 0, 1, 'hint:la_config_SemaphoreLifetimeInSeconds');
INSERT INTO SystemSettings VALUES(DEFAULT, 'EnableEmailLog', '1', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsLogs', 'la_config_EnableEmailLog', 'radio', NULL, '1=la_Yes||0=la_No', 65.01, 0, 1, 'hint:la_config_EnableEmailLog');
INSERT INTO SystemSettings VALUES(DEFAULT, 'EmailLogRotationInterval', '2419200', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsLogs', 'la_config_EmailLogRotationInterval', 'select', NULL, '86400=la_opt_OneDay||604800=la_opt_OneWeek||1209600=la_opt_TwoWeeks||2419200=la_opt_OneMonth||7257600=la_opt_ThreeMonths||29030400=la_opt_OneYear||-1=la_opt_EmailLogKeepForever', 65.02, 0, 0, 'hint:la_config_EmailLogRotationInterval');
INSERT INTO SystemSettings VALUES(DEFAULT, 'SystemLogRotationInterval', '2419200', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsLogs', 'la_config_SystemLogRotationInterval', 'select', NULL, '86400=la_opt_OneDay||604800=la_opt_OneWeek||1209600=la_opt_TwoWeeks||2419200=la_opt_OneMonth||7257600=la_opt_ThreeMonths||29030400=la_opt_OneYear||-1=la_opt_SystemLogKeepForever', 65.03, 0, 1, 'hint:la_config_SystemLogRotationInterval');
Index: core/install/install_schema.sql
===================================================================
--- core/install/install_schema.sql
+++ core/install/install_schema.sql
@@ -1279,15 +1279,20 @@
);
CREATE TABLE Semaphores (
- SemaphoreId int(11) NOT NULL AUTO_INCREMENT,
- SessionKey int(10) unsigned NOT NULL DEFAULT '0',
+ `SemaphoreId` int(11) NOT NULL AUTO_INCREMENT,
+ `SessionKey` int(10) unsigned NOT NULL DEFAULT '0',
`Timestamp` int(10) unsigned NOT NULL DEFAULT '0',
- MainPrefix varchar(255) NOT NULL DEFAULT '',
- MainIDs text,
- PRIMARY KEY (SemaphoreId),
- KEY SessionKey (SessionKey),
+ `MainPrefix` varchar(255) NOT NULL DEFAULT '',
+ `MainIDs` text,
+ `UserId` int(11) DEFAULT NULL,
+ `IpAddress` varchar(15) NOT NULL DEFAULT '',
+ `Hostname` varchar(255) NOT NULL DEFAULT '',
+ `RequestURI` varchar(255) NOT NULL DEFAULT '',
+ `Backtrace` longtext,
+ PRIMARY KEY (`SemaphoreId`),
+ KEY `SessionKey` (`SessionKey`),
KEY `Timestamp` (`Timestamp`),
- KEY MainPrefix (MainPrefix)
+ KEY `MainPrefix` (`MainPrefix`)
);
CREATE TABLE CachedUrls (
Index: core/install/upgrades.sql
===================================================================
--- core/install/upgrades.sql
+++ core/install/upgrades.sql
@@ -2958,3 +2958,11 @@
ALTER TABLE Semaphores CHANGE MainIDs MainIDs TEXT NULL;
ALTER TABLE Users ADD KEY Email (Email);
+
+ALTER TABLE Semaphores
+ ADD COLUMN `UserId` int(11) NULL,
+ ADD COLUMN `IpAddress` varchar(15) NOT NULL DEFAULT '',
+ ADD COLUMN `Hostname` varchar(255) NOT NULL DEFAULT '',
+ ADD COLUMN `RequestURI` varchar(255) NOT NULL DEFAULT '',
+ ADD COLUMN `Backtrace` longtext NULL;
+INSERT INTO SystemSettings VALUES(DEFAULT, 'SemaphoreLifetimeInSeconds', '300', 'In-Portal', 'in-portal:configure_advanced', 'la_section_SettingsSystem', 'la_config_SemaphoreLifetimeInSeconds', 'text', '', 'style=\"width: 50px;\"', 60.1, 0, 1, 'hint:la_config_SemaphoreLifetimeInSeconds');
Index: core/kernel/utility/temp_handler.php
===================================================================
--- core/kernel/utility/temp_handler.php
+++ core/kernel/utility/temp_handler.php
@@ -988,23 +988,23 @@
} while ($another_coping_active && ($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');
$this->Application->SetVar('_temp_table_message', $error_message);
+ $log = $this->Application->log('Parallel item saving attempt detected');
+ $log->addTrace();
+ $log->setLogLevel(kLogger::LL_ERROR);
+ $log->write();
+
return false;
}
- // mark, that we are coping from temp to live right now, so other similar attempt (from another script) will fail
- $fields_hash = Array (
- 'SessionKey' => $this->Application->GetSID(),
- 'Timestamp' => adodb_mktime(),
- 'MainPrefix' => $this->Tables['Prefix'],
- 'MainIDs' => implode(',', $master_ids),
- );
-
- $conn->doInsert($fields_hash, TABLE_PREFIX.'Semaphores');
- $semaphore_id = $conn->getInsertID();
+ /*
+ * Mark, that we are coping from temp to live right now,
+ * so other similar attempt (from another script) will fail.
+ */
+ $semaphore_id = $this->createSemaphore($conn, $master_ids);
// unlock table now to prevent permanent lock in case, when coping will end with SQL error in the middle
$conn->ChangeQuery('UNLOCK TABLES');
@@ -1023,6 +1023,33 @@
return $ids;
}
+ /**
+ * Creates a semaphore.
+ *
+ * @param IDBConnection $conn Database connection.
+ * @param array $master_ids Master record IDs.
+ *
+ * @return integer
+ */
+ protected function createSemaphore(IDBConnection $conn, array $master_ids)
+ {
+ $fields_hash = array(
+ 'SessionKey' => $this->Application->GetSID(),
+ 'Timestamp' => adodb_mktime(),
+ 'MainPrefix' => $this->Tables['Prefix'],
+ 'MainIDs' => implode(',', $master_ids),
+ 'UserId' => $this->Application->RecallVar('user_id'),
+ 'IPAddress' => $this->Application->getClientIp(),
+ 'Hostname' => $_SERVER['HTTP_HOST'],
+ 'RequestURI' => $_SERVER['REQUEST_URI'],
+ 'Backtrace' => serialize(debug_backtrace()),
+ );
+
+ $conn->doInsert($fields_hash, TABLE_PREFIX . 'Semaphores');
+
+ return $conn->getInsertID();
+ }
+
function CancelEdit($master=null)
{
if (!isset($master)) $master = $this->Tables;
Index: core/units/admin/admin_config.php
===================================================================
--- core/units/admin/admin_config.php
+++ core/units/admin/admin_config.php
@@ -32,6 +32,7 @@
'optimize_performance' => Array ('EventName' => 'OnOptimizePerformance', 'RunSchedule' => '0 0 * * *'),
'purge_expired_database_cache' => Array ('EventName' => 'OnPurgeExpiredDatabaseCacheScheduledTask', 'RunSchedule' => '0 0,12 * * *'),
'populate_url_unit_cache' => array('EventName' => 'OnPopulateUrlUnitCacheScheduledTask', 'RunSchedule' => '0 * * * *'),
+ 'delete_stuck_semaphores' => array('EventName' => 'OnDeleteStuckSemaphoresScheduledTask', 'RunSchedule' => '*/5 * * * *'),
),
'TitlePresets' => Array (
Index: core/units/admin/admin_events_handler.php
===================================================================
--- core/units/admin/admin_events_handler.php
+++ core/units/admin/admin_events_handler.php
@@ -1265,6 +1265,57 @@
}
}
+ /**
+ * Deletes stuck semaphore records.
+ *
+ * @param kEvent $event Event.
+ *
+ * @return void
+ */
+ protected function OnDeleteStuckSemaphoresScheduledTask(kEvent $event)
+ {
+ $semaphore_lifetime = $this->Application->ConfigValue('SemaphoreLifetimeInSeconds');
+
+ $sql = 'SELECT *
+ FROM ' . TABLE_PREFIX . 'Semaphores
+ WHERE Timestamp < ' . strtotime('-' . $semaphore_lifetime . ' seconds');
+ $stuck_semaphores = $this->Conn->Query($sql, 'SemaphoreId');
+
+ if ( !$stuck_semaphores ) {
+ return;
+ }
+
+ /** @var LanguagesItem $language */
+ $language = $this->Application->recallObject('lang.current', null, array('skip_autoload' => true));
+ $date_format = $language->GetDBField('DateFormat') . ' ' . $language->GetDBField('TimeFormat');
+
+ foreach ( $stuck_semaphores as $semaphore_id => $semaphore_data ) {
+ $log = $this->Application->log('Stuck semaphore detected (unit: ' . $semaphore_data['MainPrefix'] . ')');
+ $log->setLogLevel(kLogger::LL_ERROR);
+ $log->addTrace(unserialize($semaphore_data['Backtrace']));
+ $log->setUserData(implode(PHP_EOL, array(
+ 'Main Prefix: ' . $semaphore_data['MainPrefix'],
+ 'Main IDs: ' . $semaphore_data['MainIDs'],
+ 'Created On: ' . date($date_format, $semaphore_data['Timestamp']),
+ 'Deleted On: ' . date($date_format),
+ )));
+
+ $log->setLogField('LogHostname', $semaphore_data['Hostname']);
+ $log->setLogField('LogRequestSource', 1); // Web.
+ $log->setLogField('LogInterface', kLogger::LI_ADMIN);
+ $log->setLogField('LogRequestURI', $semaphore_data['RequestURI']);
+ $log->setLogField('LogUserId', $semaphore_data['UserId']);
+ $log->setLogField('IpAddress', $semaphore_data['IpAddress']);
+ $log->setLogField('LogSessionKey', $semaphore_data['SessionKey']);
+
+ $log->write();
+
+ $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Semaphores
+ WHERE SemaphoreId = ' . $semaphore_id;
+ $this->Conn->Query($sql);
+ }
+ }
+
}

Event Timeline