diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index ec66dcd5fcbee..3b8d20c4eebb0 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -515,7 +515,7 @@ protected function lock(Request $request, Response $entry) // wait for the lock to be released $wait = 0; - while (is_file($lock) && $wait < 5000000) { + while ($this->store->isLocked($request) && $wait < 5000000) { usleep(50000); $wait += 50000; } diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Store.php b/src/Symfony/Component/HttpKernel/HttpCache/Store.php index b60c647e743b2..6d45e5c5936c8 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Store.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Store.php @@ -71,15 +71,20 @@ public function cleanup() */ public function lock(Request $request) { - if (false !== $lock = @fopen($path = $this->getPath($this->getCacheKey($request).'.lck'), 'x')) { + $path = $this->getPath($this->getCacheKey($request).'.lck'); + if (!is_dir(dirname($path)) && false === @mkdir(dirname($path), 0777, true)) { + return false; + } + + $lock = @fopen($path, 'x'); + if (false !== $lock) { fclose($lock); $this->locks[] = $path; return true; } - - return $path; + return !file_exists($path) ?: $path; } /** @@ -92,6 +97,11 @@ public function unlock(Request $request) return @unlink($this->getPath($this->getCacheKey($request).'.lck')); } + public function isLocked(Request $request) + { + return is_file($this->getPath($this->getCacheKey($request).'.lck')); + } + /** * Locates a cached Response for the Request provided. * diff --git a/src/Symfony/Component/HttpKernel/HttpCache/StoreInterface.php b/src/Symfony/Component/HttpKernel/HttpCache/StoreInterface.php index dd8c8869798d5..483b6d6c68e5f 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/StoreInterface.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/StoreInterface.php @@ -69,6 +69,15 @@ public function lock(Request $request); */ public function unlock(Request $request); + /** + * Returns whether or not a lock exists. + * + * @param Request $request A Request instance + * + * @return Boolean true if lock exists, false otherwise + */ + public function isLocked(Request $request); + /** * Purges data for the given URL. * diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php index 747d350f43808..46e5e6b630970 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/StoreTest.php @@ -194,6 +194,18 @@ public function testOverwritesNonVaryingResponseWithStore() $this->assertCount(2, $this->getStoreMetadata($key)); } + public function testLocking() + { + $req = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); + $this->assertTrue($this->store->lock($req)); + + $path = $this->store->lock($req); + $this->assertTrue($this->store->isLocked($req)); + + $this->store->unlock($req); + $this->assertFalse($this->store->isLocked($req)); + } + protected function storeSimpleEntry($path = null, $headers = array()) { if (null === $path) {