Browse Source

Allow re-entrance in the same named mutex within the same PHP page.

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@3115 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 11 years ago
parent
commit
3d0c9f4e5c
1 changed files with 34 additions and 8 deletions
  1. 34 8
      core/mutex.class.inc.php

+ 34 - 8
core/mutex.class.inc.php

@@ -31,12 +31,18 @@ class iTopMutex
 {
 {
 	protected $sName;
 	protected $sName;
 	protected $hDBLink;
 	protected $hDBLink;
+	static protected $aAcquiredLocks = array();
 
 
 	public function __construct($sName)
 	public function __construct($sName)
 	{
 	{
 		// Compute the name of a lock for mysql
 		// Compute the name of a lock for mysql
 		// Note: the name is server-wide!!!
 		// Note: the name is server-wide!!!
 		$this->sName = 'itop.'.$sName;
 		$this->sName = 'itop.'.$sName;
+		
+		if (!array_key_exists($this->sName, self::$aAcquiredLocks))
+		{
+			self::$aAcquiredLocks[$this->sName] = 0;
+		}
 
 
 		// It is a MUST to create a dedicated session each time a lock is required, because
 		// It is a MUST to create a dedicated session each time a lock is required, because
 		// using GET_LOCK anytime on the same session will RELEASE the current and unique session lock (known issue)
 		// using GET_LOCK anytime on the same session will RELEASE the current and unique session lock (known issue)
@@ -55,17 +61,21 @@ class iTopMutex
 	 */	
 	 */	
 	public function Lock()
 	public function Lock()
 	{
 	{
-		do
+		if (self::$aAcquiredLocks[$this->sName] == 0)
 		{
 		{
-			$res = $this->QueryToScalar("SELECT GET_LOCK('".$this->sName."', 3600)");
-			if (is_null($res))
+			do
 			{
 			{
-				throw new Exception("Failed to acquire the lock '".$this->sName."'");
+				$res = $this->QueryToScalar("SELECT GET_LOCK('".$this->sName."', 3600)");
+				if (is_null($res))
+				{
+					throw new Exception("Failed to acquire the lock '".$this->sName."'");
+				}
+				// $res === '1' means I hold the lock
+				// $res === '0' means it timed out
 			}
 			}
-			// $res === '1' means I hold the lock
-			// $res === '0' means it timed out
+			while ($res !== '1');
 		}
 		}
-		while ($res !== '1');
+		self::$aAcquiredLocks[$this->sName]++;
 	}
 	}
 
 
 	/**
 	/**
@@ -74,6 +84,12 @@ class iTopMutex
 	 */	
 	 */	
 	public function TryLock()
 	public function TryLock()
 	{
 	{
+		if (self::$aAcquiredLocks[$this->sName] > 0)
+		{
+			self::$aAcquiredLocks[$this->sName]++;
+			return true;
+		}
+		
 		$res = $this->QueryToScalar("SELECT GET_LOCK('".$this->sName."', 0)");
 		$res = $this->QueryToScalar("SELECT GET_LOCK('".$this->sName."', 0)");
 		if (is_null($res))
 		if (is_null($res))
 		{
 		{
@@ -81,6 +97,10 @@ class iTopMutex
 		}
 		}
 		// $res === '1' means I hold the lock
 		// $res === '1' means I hold the lock
 		// $res === '0' means it timed out
 		// $res === '0' means it timed out
+		if ($res === '1')
+		{
+			self::$aAcquiredLocks[$this->sName]++;
+		}
 		return ($res === '1');
 		return ($res === '1');
 	}
 	}
 
 
@@ -89,7 +109,13 @@ class iTopMutex
 	 */	
 	 */	
 	public function Unlock()
 	public function Unlock()
 	{
 	{
-		$res = $this->QueryToScalar("SELECT RELEASE_LOCK('".$this->sName."')");
+		if (self::$aAcquiredLocks[$this->sName] == 0) return; // Safety net
+		
+		if (self::$aAcquiredLocks[$this->sName] == 1)
+		{
+			$res = $this->QueryToScalar("SELECT RELEASE_LOCK('".$this->sName."')");
+		}
+		self::$aAcquiredLocks[$this->sName]--;
 	}
 	}