mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
#805 Use a mutex to turn the insertion of a new ticket into an atomic operation
SVN:trunk[2953]
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
|
||||
require_once('metamodel.class.php');
|
||||
require_once('deletionplan.class.inc.php');
|
||||
require_once('mutex.class.inc.php');
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -148,7 +148,22 @@
|
||||
<count_max>0</count_max>
|
||||
</field>
|
||||
</fields>
|
||||
<methods/>
|
||||
<methods>
|
||||
<method id="DBInsertNoReload">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>Overload-DBObject</type>
|
||||
<code><![CDATA[ public function DBInsertNoReload()
|
||||
{
|
||||
$oMutex = new iTopMutex('ticket_insert');
|
||||
$oMutex->Lock();
|
||||
$iKey = parent::DBInsertNoReload();
|
||||
$oMutex->Unlock();
|
||||
return $iKey;
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
</methods>
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
|
||||
@@ -96,7 +96,7 @@ Flash version 8 or higher is required.
|
||||
- data
|
||||
- env-production
|
||||
- log
|
||||
3) Point your web browser to the URL corresponding to the directory where the files
|
||||
4) Point your web browser to the URL corresponding to the directory where the files
|
||||
have been unzipped and follow the indications on the screen.
|
||||
|
||||
If you wish to re-launch the installation process (for example in order to install
|
||||
|
||||
@@ -40,13 +40,27 @@ if (!file_exists($sConfigFile))
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
|
||||
|
||||
function LogError($oP, $sErrorMessage, $sSeverity = 'ERROR')
|
||||
{
|
||||
$bModeCLI = utils::IsModeCLI();
|
||||
|
||||
if ($bModeCLI)
|
||||
{
|
||||
error_log(ITOP_APPLICATION." cron.php $sSeverity: ".$sErrorMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p("$sSeverity: $sMessage");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function ReadMandatoryParam($oP, $sParam, $sSanitizationFilter = 'parameter')
|
||||
{
|
||||
$sValue = utils::ReadParam($sParam, null, true /* Allow CLI */, $sSanitizationFilter);
|
||||
if (is_null($sValue))
|
||||
{
|
||||
$oP->p("ERROR: Missing argument '$sParam'\n");
|
||||
LogError($oP, "Missing argument '$sParam'");
|
||||
UsageAndExit($oP);
|
||||
}
|
||||
return trim($sValue);
|
||||
@@ -59,7 +73,7 @@ function UsageAndExit($oP)
|
||||
if ($bModeCLI)
|
||||
{
|
||||
$oP->p("USAGE:\n");
|
||||
$oP->p("php cron.php --auth_user=<login> --auth_pwd=<password> [--param_file=<file>] [--verbose=1] [--debug=1] [--status_only=1]\n");
|
||||
$oP->p("php cron.php --auth_user=<login> --auth_pwd=<password> [--param_file=<file>] [--verbose=1] [--status_only=1]\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -69,7 +83,7 @@ function UsageAndExit($oP)
|
||||
exit -2;
|
||||
}
|
||||
|
||||
function RunTask($oProcess, BackgroundTask $oTask, $oStartDate, $iTimeLimit)
|
||||
function RunTask($oP, $oProcess, BackgroundTask $oTask, $oStartDate, $iTimeLimit)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -111,7 +125,7 @@ function RunTask($oProcess, BackgroundTask $oTask, $oStartDate, $iTimeLimit)
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$sMessage = 'Processing failed, the following exception occured: '.$e->getMessage();
|
||||
LogError($oP, 'Processing failed, the following exception occured: '.$e->getMessage());
|
||||
}
|
||||
return $sMessage;
|
||||
}
|
||||
@@ -199,7 +213,7 @@ function CronExec($oP, $aProcesses, $bVerbose)
|
||||
{
|
||||
$oP->p(">> === ".$oNow->format('Y-m-d H:i:s').sprintf(" Starting:%-'=40s", ' '.$sTaskClass.' '));
|
||||
}
|
||||
$sMessage = RunTask($oProcess, $aTasks[$sTaskClass], $oNow, $iTimeLimit);
|
||||
$sMessage = RunTask($oP, $oProcess, $aTasks[$sTaskClass], $oNow, $iTimeLimit);
|
||||
if ($bVerbose)
|
||||
{
|
||||
if(!empty($sMessage))
|
||||
@@ -291,7 +305,7 @@ if (utils::IsModeCLI())
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->p("Access wrong credentials ('$sAuthUser')");
|
||||
LogError($oP, "Access wrong credentials ('$sAuthUser')");
|
||||
$oP->output();
|
||||
exit -1;
|
||||
}
|
||||
@@ -305,11 +319,19 @@ else
|
||||
|
||||
if (!UserRights::IsAdministrator())
|
||||
{
|
||||
$oP->p("Access restricted to administrators");
|
||||
$oP->Output();
|
||||
LogError($oP, 'Access restricted to administrators');
|
||||
$oP->output();
|
||||
exit -1;
|
||||
}
|
||||
|
||||
if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE))
|
||||
{
|
||||
LogError($oP, 'A database maintenance is ongoing (read-only mode even for admins)', 'WARNING');
|
||||
$oP->output();
|
||||
exit -1;
|
||||
}
|
||||
|
||||
|
||||
// Enumerate classes implementing BackgroundProcess
|
||||
//
|
||||
$aProcesses = array();
|
||||
@@ -329,7 +351,6 @@ foreach(get_declared_classes() as $sPHPClass)
|
||||
|
||||
|
||||
$bVerbose = utils::ReadParam('verbose', false, true /* Allow CLI */);
|
||||
$bDebug = utils::ReadParam('debug', false, true /* Allow CLI */);
|
||||
|
||||
if ($bVerbose)
|
||||
{
|
||||
@@ -348,44 +369,39 @@ if (utils::ReadParam('status_only', false, true /* Allow CLI */))
|
||||
exit(0);
|
||||
}
|
||||
|
||||
require_once(APPROOT.'core/mutex.class.inc.php');
|
||||
// Compute the name of a lock for mysql
|
||||
// The name is server-wide
|
||||
$oConfig = utils::GetConfig();
|
||||
$sLockName = 'itop.cron.'.$oConfig->GetDBName().'_'.$oConfig->GetDBSubname();
|
||||
|
||||
$oP->p("Starting: ".time().' ('.date('Y-m-d H:i:s').')');
|
||||
|
||||
try
|
||||
// CAUTION: using GET_LOCK anytime on the same connexion will RELEASE the lock
|
||||
// Todo: invoke GET_LOCK from a dedicated session (encapsulate that into a mutex class)
|
||||
$res = CMDBSource::QueryToScalar("SELECT GET_LOCK('$sLockName', 1)");// timeout = 1 second (see also IS_FREE_LOCK)
|
||||
if (is_null($res))
|
||||
{
|
||||
$oConfig = utils::GetConfig();
|
||||
$oMutex = new iTopMutex('cron.'.$oConfig->GetDBName().'_'.$oConfig->GetDBSubname());
|
||||
if ($oMutex->TryLock())
|
||||
LogError($oP, "Failed to acquire the lock '$sLockName'");
|
||||
}
|
||||
elseif ($res === '1')
|
||||
{
|
||||
// The current session holds the lock
|
||||
try
|
||||
{
|
||||
// Note: testing this now in case some of the background processes forces the read-only mode for a while
|
||||
// in that case it is better to exit with the check on reentrance (mutex)
|
||||
if (!MetaModel::DBHasAccess(ACCESS_ADMIN_WRITE))
|
||||
{
|
||||
$oP->p("A database maintenance is ongoing (read-only mode even for admins).");
|
||||
$oP->Output();
|
||||
exit -1;
|
||||
}
|
||||
|
||||
CronExec($oP, $aProcesses, $bVerbose);
|
||||
|
||||
$oMutex->Unlock();
|
||||
}
|
||||
else
|
||||
catch(Exception $e)
|
||||
{
|
||||
// Exit silently
|
||||
$oP->p("Already running...");
|
||||
LogError($oP, $e->getMessage()."\n".$e->getTraceAsString());
|
||||
}
|
||||
$res = CMDBSource::QueryToScalar("SELECT RELEASE_LOCK('$sLockName')");
|
||||
}
|
||||
catch (Exception $e)
|
||||
else
|
||||
{
|
||||
$oP->p("ERROR: '".$e->getMessage()."'");
|
||||
if ($bDebug)
|
||||
{
|
||||
// Might contain verb parameters such a password...
|
||||
$oP->p($e->getTraceAsString());
|
||||
}
|
||||
// Lock already held by another session
|
||||
// Exit silently
|
||||
$oP->p("Already running...");
|
||||
}
|
||||
|
||||
$oP->p("Exiting: ".time().' ('.date('Y-m-d H:i:s').')');
|
||||
|
||||
$oP->Output();
|
||||
|
||||
Reference in New Issue
Block a user