Skip to content

Commit

Permalink
LockManager::lock() second parameter $blockOnBusy added for non-block…
Browse files Browse the repository at this point in the history
…ing locks
  • Loading branch information
feedbee committed Aug 25, 2013
1 parent ecd0bb6 commit 8b74b0b
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 17 deletions.
3 changes: 2 additions & 1 deletion Driver/DriverInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ interface DriverInterface
* or any internal error).
*
* @param string $key
* @param bool $blockOnBusy Would the function be blocked until lock is acquired?
* @return bool
*/
public function doLock($key);
public function doLock($key, $blockOnBusy);
/**
* Lock release back-end implementation. Returns true on success or false on any internal error.
*
Expand Down
5 changes: 3 additions & 2 deletions Driver/Flock.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ public function __construct()
$this->lockFilesDir = sys_get_temp_dir();
}

public function doLock($key)
public function doLock($key, $blockOnBusy)
{
$key = urlencode($key);
$this->lockHandlers[$key] = fopen("{$this->lockFilesDir}/lock-$key", "w+");
if ($this->lockHandlers[$key]) {
if (flock($this->lockHandlers[$key], LOCK_EX)) {
$flags = LOCK_EX | ($blockOnBusy ? LOCK_NB : 0);
if (flock($this->lockHandlers[$key], $flags)) {
return true;
}
}
Expand Down
9 changes: 7 additions & 2 deletions Driver/Memcached.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ public function getMemcached()
return $this->memcached;
}

public function doLock($key)
public function doLock($key, $blockOnBusy)
{
$storageKey = self::KEY . ":{$key}";
$lockAcquireTimeout = $blockOnBusy ? self::LOCK_ACQUIRE_TIMEOUT : 0;

try {
$start = time();
Expand Down Expand Up @@ -103,9 +104,13 @@ public function doLock($key)
// BUSY
}

if ($lockAcquireTimeout === 0) {
break;
}

usleep(self::SLEEP);

} while (!is_numeric(self::LOCK_ACQUIRE_TIMEOUT) || time() < $start + self::LOCK_ACQUIRE_TIMEOUT);
} while (!is_numeric($lockAcquireTimeout) || time() < $start + $lockAcquireTimeout);

return $acquired;

Expand Down
7 changes: 4 additions & 3 deletions Driver/Redis.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ public function getRedis()
return $this->redis;
}

public function doLock($key)
public function doLock($key, $blockOnBusy)
{
$storageKey = self::KEY . ":{$key}";
$lockAcquireTimeout = $blockOnBusy ? self::LOCK_ACQUIRE_TIMEOUT : 0;

try {
$start = time();
Expand All @@ -66,10 +67,10 @@ public function doLock($key)

if ($acquired = ($this->redis->setnx($storageKey, $this->expire[$key]))) break;
if ($acquired = ($this->recover($key))) break;
if (self::LOCK_ACQUIRE_TIMEOUT === 0) break;
if ($lockAcquireTimeout === 0) break;

usleep(self::SLEEP);
} while (!is_numeric(self::LOCK_ACQUIRE_TIMEOUT) || time() < $start + self::LOCK_ACQUIRE_TIMEOUT);
} while (!is_numeric($lockAcquireTimeout) || time() < $start + $lockAcquireTimeout);

return $acquired;
} catch (\RedisException $e) {
Expand Down
10 changes: 6 additions & 4 deletions LockManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,22 @@ public function getDriver()
/**
* Try to acquire lock
* Returns true on success or false on failure (can't acquire lock or any back-end internal error).
* $blockOnBusy parameter sets work-mode: would the function be blocked until lock is acquired?
*
* @param $key
* @param string $key
* @param bool $blockOnBusy True to wait while lock is acquired, false to return immediately
* @return bool
*/
public function lock($key)
public function lock($key, $blockOnBusy = true)
{
return $this->driver->doLock($key);
return $this->driver->doLock($key, $blockOnBusy);
}

/**
* Release lock
* Returns true on success or false on any back-end internal error.
*
* @param $key
* @param string $key
* @return bool
*/
public function release($key)
Expand Down
13 changes: 8 additions & 5 deletions tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
use LockManager\Driver\Redis as RedisDriver;
use LockManager\Driver\Flock as FlockDriver;

$opt = getopt('mrfs');
$opt = getopt('mrfsn');
if (isset($opt['m'])) {
print "LockManager: Memcached back-end test" . PHP_EOL;
$memcached = new \Memcached;
Expand All @@ -43,13 +43,15 @@
else {
die('Set back-end parameter: -m, -r, or -f' . PHP_EOL);
}
$block = !isset($opt['n']);
print 'Block mode: ' . ($block ? 'BLOCK' : 'NOT BLOCK') . PHP_EOL;

$lockManager = new LockManager($backend);

if (isset($opt['s'])) {
// Run simple test (for debug purpose)
echo 'Before lock' . PHP_EOL;
var_dump($lockManager->lock('test'));
var_dump($lockManager->lock('test', $block));
echo 'After lock' . PHP_EOL;
sleep(5);
echo 'Before release' . PHP_EOL;;
Expand All @@ -64,13 +66,14 @@
$testFilePath = "{$sysTmpDir}/lock-test-file";
$fd = fopen($testFilePath, "w+");

$all = $failed = 0;
$all = $acquired = $failed = 0;

do {

print "Tests launched: {$all}\tTests failed: {$failed}\r";
print "Tests launched: {$all}\tLock acquired: {$acquired}\tTests failed: {$failed}\r";

if ($lockManager->lock('test-key')) {
if ($success = $lockManager->lock('test-key', $block)) {
$acquired++;
if (!flock($fd, LOCK_EX)) {
$failed++;
continue;
Expand Down

0 comments on commit 8b74b0b

Please sign in to comment.