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

Mutex   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 78
Duplicated Lines 0 %

Test Coverage

Coverage 17.39%

Importance

Changes 0
Metric Value
dl 0
loc 78
rs 10
c 0
b 0
f 0
ccs 4
cts 23
cp 0.1739
wmc 7

5 Methods

Rating   Name   Duplication   Size   Complexity  
A isLocked() 0 4 1
A __construct() 0 3 1
A lock() 0 12 2
A unlock() 0 5 1
A assertNamespace() 0 3 2
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
Bug introduced by Juho Jaakkola
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