Completed
Push — pr21 ( ec1d9e )
by Kamil
02:27
created

FlockLock::getFilePath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * This file is part of ninja-mutex.
4
 *
5
 * (C) Kamil Dziedzic <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace NinjaMutex\Lock;
11
12
/**
13
 * Lock implementor using flock
14
 *
15
 * @author Kamil Dziedzic <[email protected]>
16
 */
17
class FlockLock extends LockAbstract
18
{
19
    protected $dirname;
20
    protected $files = array();
21
22
    /**
23
     * @param string $dirname
24
     */
25
    public function __construct($dirname)
26
    {
27
        parent::__construct();
28
29
        $this->dirname = $dirname;
30
    }
31
32
    /**
33
     * @param  string $name
34
     * @param  bool   $blocking
35
     * @return bool
36
     */
37 32
    protected function getLock($name, $blocking)
38
    {
39 32
        if (!$this->setupFileHandle($name)) {
40
            return false;
41
        }
42
43 32
        $options = LOCK_EX;
44
45
        // Check if we don't want to wait until lock is acquired
46 32
        if (!$blocking) {
47 30
            $options |= LOCK_NB;
48
        }
49
50 32
        if (!flock($this->files[$name], $options)) {
51 4
            return false;
52
        }
53
54 32
        return true;
55
    }
56
57
    /**
58
     * Release lock
59
     *
60
     * @param  string $name name of lock
61
     * @return bool
62
     */
63 32
    public function releaseLock($name)
64
    {
65 32
        if (isset($this->files[$name])) {
66 32
            flock($this->files[$name], LOCK_UN); // @todo Can LOCK_UN fail?
67 32
            unset($this->locks[$name]);
68 32
            fclose($this->files[$name]);
69 32
            unset($this->files[$name]);
70
71 32
            return true;
72
        }
73
74 4
        return false;
75
    }
76
77
    /**
78
     * @param  string $name
79
     * @return string
80
     */
81 32
    protected function getFilePath($name)
82
    {
83 32
        return $this->dirname . DIRECTORY_SEPARATOR . $name . '.lock';
84
    }
85
86
    /**
87
     * @param  string $name
88
     * @return bool
89
     */
90 32
    protected function setupFileHandle($name)
91
    {
92 32
        if (isset($this->files[$name])) {
93
            return true;
94
        }
95
96 32
        $file = fopen($this->getFilePath($name), 'c');
97 32
        if (false === $file) {
98
            return false;
99
        }
100
101 32
        $this->files[$name] = $file;
102
103 32
        return true;
104
    }
105
106 10
    public function __clone()
107
    {
108 10
        parent::__clone();
109 10
        $this->files = array();
110 10
    }
111
112
    /**
113
     * Try to release any obtained locks when object is destroyed
114
     *
115
     * This is a safe guard for cases when your php script dies unexpectedly.
116
     * It's not guaranteed it will work either.
117
     *
118
     * You should not depend on __destruct() to release your locks,
119
     * instead release them with `$released = $this->releaseLock()`A
120
     * and check `$released` if lock was properly released
121
     */
122 10
    public function __destruct()
123
    {
124 10
        while (null !== $file = array_pop($this->files)) {
125 6
            fclose($file);
126
        }
127 10
    }
128
129
    /**
130
     * Check if lock is locked
131
     *
132
     * @param  string $name name of lock
133
     * @return bool
134
     */
135 14
    public function isLocked($name)
136
    {
137 14
        if ($this->acquireLock($name, 0)) {
138 6
            return !$this->releaseLock($name);
139
        }
140
141 14
        return true;
142
    }
143
}
144