Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F776185
D440.id1131.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Thu, Feb 6, 9:12 PM
Size
12 KB
Mime Type
text/x-diff
Expires
Fri, Feb 7, 9:12 PM (2 h, 4 m)
Engine
blob
Format
Raw Data
Handle
558642
Attached To
D440: INP-1569 - Create System Log record, when stale semaphore is discovered or hit
D440.id1131.diff
View Options
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
Log In to Comment