@@ -20,6 +20,14 @@ class FileLock implements Lock
20
20
private $ fh ;
21
21
private $ remove_on_release ;
22
22
23
+ private $ logger ;
24
+
25
+ /**
26
+ * @param string $lock_file path to file
27
+ * @param string|null $identifier resource identifier (default to $lock_file) for logging
28
+ * @param string|null $owner owner name for logging
29
+ * @param boolean $remove_on_release remove file on release if no other lock remains
30
+ */
23
31
public function __construct ($ lock_file , $ identifier = null , $ owner = null , $ remove_on_release = false )
24
32
{
25
33
$ this ->lock_file = $ lock_file ;
@@ -30,33 +38,53 @@ public function __construct($lock_file, $identifier = null, $owner = null, $remo
30
38
$ this ->logger = new NullLogger ;
31
39
}
32
40
41
+ /**
42
+ * @param boolean $exclusive true for an exclusive lock, false for shared one
43
+ * @param boolean $blocking true to wait for lock to be available, false to throw exception instead of waiting
44
+ * @inherit
45
+ */
33
46
public function acquire ($ exclusive = FileLock::EXCLUSIVE , $ blocking = FileLock::NON_BLOCKING )
34
47
{
35
- $ operation = ($ exclusive ? LOCK_EX : LOCK_SH ) | ($ blocking ? 0 : LOCK_NB );
36
-
37
- if (!flock ($ this ->fh (), $ operation )) {
38
- $ this ->logger ->debug (($ exclusive ?
39
- '{owner} could not acquire exclusive lock on {identifier} ' :
40
- '{owner} could not acquire shared lock on {identifier} '
41
- ), [
42
- 'identifier ' => $ this ->identifier ,
43
- 'owner ' => $ this ->owner
44
- ]);
45
-
46
- throw new Exception (($ exclusive ?
47
- 'Could not acquire exclusive lock on ' .$ this ->identifier :
48
- 'Could not acquire shared lock on ' .$ this ->identifier
49
- ));
48
+ if ($ exclusive === FileLock::EXCLUSIVE ) {
49
+ $ lock_type = 'exclusive ' ;
50
+ $ operation = LOCK_EX ;
51
+ } else {
52
+ $ lock_type = 'shared ' ;
53
+ $ operation = LOCK_SH ;
54
+ }
50
55
56
+ if ($ blocking === FileLock::NON_BLOCKING ) {
57
+ $ operation |= LOCK_NB ;
51
58
}
52
59
53
- $ this ->logger ->debug (($ exclusive ?
54
- '{owner} exclusive lock acquired on {identifier} ' :
55
- '{owner} shared lock acquired on {identifier} '
56
- ), [
60
+ $ this ->tryAcquire ($ operation , $ lock_type );
61
+ }
62
+
63
+ /**
64
+ * try to acquire lock on file, throw in case of faillure
65
+ * @param int $operation
66
+ * @param string $lock_type lock type description
67
+ * @return void
68
+ * @see https://php.net/flock
69
+ */
70
+ private function tryAcquire ($ operation , $ lock_type )
71
+ {
72
+ $ log_data = [
57
73
'identifier ' => $ this ->identifier ,
58
- 'owner ' => $ this ->owner
59
- ]);
74
+ 'owner ' => $ this ->owner ,
75
+ 'lock_type ' => $ lock_type
76
+ ];
77
+
78
+ if (!$ this ->flock ($ operation )) {
79
+ $ this ->logger ->debug ('{owner} could not acquire {lock_type} lock on {identifier} ' , $ log_data );
80
+
81
+ throw new Exception (
82
+ 'Could not acquire ' .$ lock_type .' lock on ' .$ this ->identifier
83
+ );
84
+
85
+ }
86
+
87
+ $ this ->logger ->debug ('{owner} {lock_type} lock acquired on {identifier} ' , $ log_data );
60
88
}
61
89
62
90
public function release ()
@@ -65,22 +93,18 @@ public function release()
65
93
return ;
66
94
}
67
95
68
- if ($ this ->remove_on_release && flock ($ this ->fh , LOCK_EX )) {
69
- fclose ($ this ->fh );
70
- $ this ->fh = null ;
96
+ if ($ this ->remove_on_release && $ this ->flock (LOCK_EX )) {
71
97
unlink ($ this ->lock_file );
72
- } else {
73
- flock ($ this ->fh , LOCK_UN );
74
98
}
75
99
100
+ $ this ->flock (LOCK_UN );
101
+ fclose ($ this ->fh );
102
+ $ this ->fh = null ;
76
103
77
- $ this ->logger ->debug (
78
- '{owner} lock released on {identifier} ' ,
79
- [
80
- 'identifier ' => $ this ->identifier ,
81
- 'owner ' => $ this ->owner
82
- ]
83
- );
104
+ $ this ->logger ->debug ('{owner} lock released on {identifier} ' , [
105
+ 'identifier ' => $ this ->identifier ,
106
+ 'owner ' => $ this ->owner
107
+ ]);
84
108
}
85
109
86
110
public function setLogger (LoggerInterface $ logger )
@@ -93,12 +117,19 @@ public function __destruct()
93
117
$ this ->release ();
94
118
}
95
119
96
- private function fh ()
120
+ /**
121
+ * @return boolean
122
+ */
123
+ private function flock ($ operation )
97
124
{
98
125
if ($ this ->fh === null ) {
99
126
$ this ->fh = fopen ($ this ->lock_file , 'c ' );
100
127
}
101
128
102
- return $ this ->fh ;
129
+ if (!is_resource ($ this ->fh )) {
130
+ throw new Exception ('Could not open lock file ' .$ this ->lock_file );
131
+ }
132
+
133
+ return flock ($ this ->fh , $ operation );
103
134
}
104
135
}
0 commit comments