Passed
Push — master ( c0a3a7...3b84a4 )
by Jeroen
58:51
created

engine/classes/Elgg/Database/Mutex.php (1 issue)

1
<?php
2
3
namespace Elgg\Database;
4
5
/**
6
 * WARNING: API IN FLUX. DO NOT USE DIRECTLY.
7
 *
8
 * Provides database mutex that can be used to prevent race conditions
9
 * between two processes that affect the same data.
10
 *
11
 * @access private
12
 * @since 2.1.0
13
 */
14
class Mutex {
15
16
	/**
17
	 * @var \Elgg\Database
18
	 */
19
	private $db;
20
21
	/**
22
	 * @var \Elgg\Logger
23
	 */
24
	private $logger;
25
26
	/**
27
	 * Constructor
28
	 *
29
	 * @param \Elgg\Database $db     Database
30
	 * @param \Elgg\Logger   $logger Logger
31
	 */
32 2
	public function __construct(\Elgg\Database $db, \Elgg\Logger $logger) {
33 2
		$this->db = $db;
34 2
		$this->logger = $logger;
35 2
	}
36
37
	/**
38
	 * Creates a table {prefix}{$namespace}_lock that is used as a mutex.
39
	 *
40
	 * @param string $namespace Allows having separate locks for separate processes
41
	 * @return bool
42
	 */
43
	public function lock($namespace) {
44
		$this->assertNamespace($namespace);
45
46
		if (!$this->isLocked($namespace)) {
47
			// Lock it
48
			$this->db->insertData("CREATE TABLE {$this->db->prefix}{$namespace}_lock (id INT)");
49
			$this->logger->info("Locked mutex for $namespace");
50
			return true;
51
		}
52
53
		$this->logger->warn("Cannot lock mutex for {$namespace}: already locked.");
54
		return false;
55
	}
56
57
	/**
58
	 * Unlocks mutex
59
	 *
60
	 * @param string $namespace Namespace to use for the database table
61
	 * @return void
62
	 */
63
	public function unlock($namespace) {
64
		$this->assertNamespace($namespace);
65
66
		$this->db->deleteData("DROP TABLE {$this->db->prefix}{$namespace}_lock");
67
		$this->logger->notice("Mutex unlocked for $namespace.");
68
	}
69
70
	/**
71
	 * Checks if mutex is locked
72
	 *
73
	 * @param string $namespace Namespace to use for the database table
74
	 * @return bool
75
	 */
76
	public function isLocked($namespace) {
77
		$this->assertNamespace($namespace);
78
79
		return (bool) count($this->db->getData("SHOW TABLES LIKE '{$this->db->prefix}{$namespace}_lock'"));
80
	}
81
82
	/**
83
	 * Assert that the namespace contains only characters [A-Za-z]
84
	 *
85
	 * @param string $namespace Namespace to use for the database table
86
	 * @throws InvalidParameterException
87
	 * @return void
88
	 */
89
	private function assertNamespace($namespace) {
90
		if (!ctype_alpha($namespace)) {
91
			throw new InvalidParameterException("Mutex namespace can only have characters [A-Za-z].");
0 ignored issues
show
The type Elgg\Database\InvalidParameterException was not found. Did you mean InvalidParameterException? If so, make sure to prefix the type with \.
Loading history...
92
		}
93
	}
94
}
95