2
2
3
3
namespace hiqdev \assetpackagist \models ;
4
4
5
+ use Exception ;
5
6
use Yii ;
6
7
use yii \helpers \Json ;
7
8
8
9
class Storage
9
10
{
10
11
protected static $ _instance ;
12
+ protected static $ _lockHandle ;
13
+ protected static $ _lockCount = 0 ;
11
14
12
15
protected function __construct ()
13
16
{
@@ -24,7 +27,70 @@ static public function getInstance()
24
27
25
28
public function getNextID ()
26
29
{
27
- return rand (1000000 , 2000000 );
30
+ $ this ->getLock ();
31
+ $ nextID = $ this ->readLastID () + 1 ;
32
+ $ this ->writeLastID ($ nextID );
33
+ $ this ->releaseLock ();
34
+
35
+ return $ nextID ;
36
+ }
37
+
38
+ protected function readLastId ()
39
+ {
40
+ $ path = $ this ->getLastIDPath ();
41
+
42
+ return file_exists ($ path ) ? (int )file_get_contents ($ path ) : 1000000 ;
43
+ }
44
+
45
+ protected function writeLastId ($ value )
46
+ {
47
+ file_put_contents ($ this ->getLastIDPath (), $ value );
48
+ }
49
+
50
+ protected function getLastIDPath ()
51
+ {
52
+ return Yii::getAlias ('@web/lastid ' );
53
+ }
54
+
55
+ protected function getLockHandle ()
56
+ {
57
+ if (static ::$ _lockHandle === null ) {
58
+ $ path = Yii::getAlias ('@web/lock ' );
59
+ if (!file_exists ($ path )) {
60
+ file_put_contents ($ path , 'lock ' );
61
+ }
62
+ static ::$ _lockHandle = fopen ($ path , 'r+ ' );
63
+ }
64
+
65
+ return static ::$ _lockHandle ;
66
+ }
67
+
68
+ public function hasLock ()
69
+ {
70
+ return (bool )static ::$ _lockCount ;
71
+ }
72
+
73
+ protected function getLock ()
74
+ {
75
+ if (!$ this ->hasLock ()) {
76
+ if (!flock ($ this ->getLockHandle (), LOCK_EX )) {
77
+ throw new Exception ('failed get lock ' );
78
+ }
79
+ }
80
+ ++$ this ->_lockCount ;
81
+ }
82
+
83
+ protected function releaseLock ()
84
+ {
85
+ if ($ this ->_lockCount <1 ) {
86
+ throw new Exception ('no lock to release ' );
87
+ }
88
+ if ($ this ->_lockCount === 1 ) {
89
+ if (!flock ($ this ->getLockHandle (), LOCK_UN )) {
90
+ throw new Exception ('failed release lock ' );
91
+ }
92
+ }
93
+ --$ this ->_lockCount ;
28
94
}
29
95
30
96
public function writePackage (AssetPackage $ package )
@@ -39,10 +105,14 @@ public function writePackage(AssetPackage $package)
39
105
$ hash = hash ('sha256 ' , $ json );
40
106
$ path = static ::buildPath ($ name , $ hash );
41
107
if (!file_exists ($ path )) {
42
- static ::mkdir (dirname ($ path ));
43
- file_put_contents ($ path , $ json );
44
- file_put_contents (static ::buildPath ($ name ), $ json );
45
- $ this ->writeProviderLatest ($ name , $ hash );
108
+ $ this ->getLock ();
109
+ {
110
+ static ::mkdir (dirname ($ path ));
111
+ file_put_contents ($ path , $ json );
112
+ file_put_contents (static ::buildPath ($ name ), $ json );
113
+ $ this ->writeProviderLatest ($ name , $ hash );
114
+ }
115
+ $ this ->releaseLock ();
46
116
}
47
117
48
118
return $ hash ;
@@ -85,10 +155,13 @@ protected function writeProviderLatest($name, $hash)
85
155
$ hash = hash ('sha256 ' , $ json );
86
156
$ path = Yii::getAlias ("@web/p/provider-latest$ $ hash.json " );
87
157
if (!file_exists ($ path )) {
88
- file_put_contents ($ path , $ json );
89
- /// TODO lock
90
- file_put_contents ($ latest_path , Json::encode ($ data ));
91
- $ this ->writePackagesJson ($ hash );
158
+ $ this ->getLock ();
159
+ {
160
+ file_put_contents ($ path , $ json );
161
+ file_put_contents ($ latest_path , Json::encode ($ data ));
162
+ $ this ->writePackagesJson ($ hash );
163
+ }
164
+ $ this ->releaseLock ();
92
165
}
93
166
94
167
return $ hash ;
@@ -105,8 +178,11 @@ protected function writePackagesJson($hash)
105
178
],
106
179
],
107
180
];
108
- /// TODO lock
109
- file_put_contents (Yii::getAlias ('@web/packages.json ' ), Json::encode ($ data ));
181
+ $ this ->getLock ();
182
+ {
183
+ file_put_contents (Yii::getAlias ('@web/packages.json ' ), Json::encode ($ data ));
184
+ }
185
+ $ this ->releaseLock ();
110
186
}
111
187
112
188
public static function mkdir ($ dir )
0 commit comments