仓库初始化
This commit is contained in:
126
addons/crontab/library/SimpleFork/Lock/FileLock.php
Normal file
126
addons/crontab/library/SimpleFork/Lock/FileLock.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Jenner
|
||||
* Date: 2015/8/21
|
||||
* Time: 14:30
|
||||
*/
|
||||
|
||||
namespace Jenner\SimpleFork\Lock;
|
||||
|
||||
|
||||
/**
|
||||
* file lock
|
||||
*
|
||||
* @package Jenner\SimpleFork\Lock
|
||||
*/
|
||||
class FileLock implements LockInterface
|
||||
{
|
||||
/**
|
||||
* @var string lock file
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
protected $fp;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $locked = false;
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
*/
|
||||
private function __construct($file)
|
||||
{
|
||||
if (!file_exists($file) || !is_readable($file)) {
|
||||
throw new \RuntimeException("{$file} is not exists or not readable");
|
||||
}
|
||||
$this->fp = fopen($file, "r+");
|
||||
if (!is_resource($this->fp)) {
|
||||
throw new \RuntimeException("open {$file} failed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create a file lock instance
|
||||
* if the file is not exists, it will be created
|
||||
*
|
||||
* @param string $file lock file
|
||||
* @return FileLock
|
||||
*/
|
||||
public static function create($file)
|
||||
{
|
||||
return new FileLock($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* get a lock
|
||||
*
|
||||
* @param bool $blocking
|
||||
* @return mixed
|
||||
*/
|
||||
public function acquire($blocking = true)
|
||||
{
|
||||
if ($this->locked) {
|
||||
throw new \RuntimeException('already lock by yourself');
|
||||
}
|
||||
|
||||
if ($blocking) {
|
||||
$locked = flock($this->fp, LOCK_EX);
|
||||
} else {
|
||||
$locked = flock($this->fp, LOCK_EX | LOCK_NB);
|
||||
}
|
||||
|
||||
if ($locked !== true) {
|
||||
return false;
|
||||
}
|
||||
$this->locked = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* is locked
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function isLocked()
|
||||
{
|
||||
return $this->locked === true ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __destory()
|
||||
{
|
||||
if ($this->locked) {
|
||||
$this->release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* release lock
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function release()
|
||||
{
|
||||
if (!$this->locked) {
|
||||
throw new \RuntimeException('release a non lock');
|
||||
}
|
||||
|
||||
$unlock = flock($this->fp, LOCK_UN);
|
||||
fclose($this->fp);
|
||||
if ($unlock !== true) {
|
||||
return false;
|
||||
}
|
||||
$this->locked = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
40
addons/crontab/library/SimpleFork/Lock/LockInterface.php
Normal file
40
addons/crontab/library/SimpleFork/Lock/LockInterface.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Jenner
|
||||
* Date: 2015/8/21
|
||||
* Time: 14:24
|
||||
*/
|
||||
|
||||
namespace Jenner\SimpleFork\Lock;
|
||||
|
||||
|
||||
/**
|
||||
* lock for processes to mutual exclusion
|
||||
*
|
||||
* @package Jenner\SimpleFork\Lock
|
||||
*/
|
||||
interface LockInterface
|
||||
{
|
||||
/**
|
||||
* get a lock
|
||||
*
|
||||
* @param bool $blocking
|
||||
* @return bool
|
||||
*/
|
||||
public function acquire($blocking = true);
|
||||
|
||||
/**
|
||||
* release lock
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function release();
|
||||
|
||||
/**
|
||||
* is locked
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLocked();
|
||||
}
|
||||
163
addons/crontab/library/SimpleFork/Lock/Semaphore.php
Normal file
163
addons/crontab/library/SimpleFork/Lock/Semaphore.php
Normal file
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Jenner
|
||||
* Date: 2015/8/12
|
||||
* Time: 20:52
|
||||
*/
|
||||
|
||||
namespace Jenner\SimpleFork\Lock;
|
||||
|
||||
|
||||
/**
|
||||
* sem lock
|
||||
*
|
||||
* @package Jenner\SimpleFork\Lock
|
||||
*/
|
||||
class Semaphore implements LockInterface
|
||||
{
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
private $lock_id;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $locked = false;
|
||||
|
||||
/**
|
||||
* init a lock
|
||||
*
|
||||
* @param $key
|
||||
* @param $count
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
private function __construct($key, $count = 1)
|
||||
{
|
||||
if (($this->lock_id = sem_get($this->_stringToSemKey($key), $count)) === false) {
|
||||
throw new \RuntimeException("Cannot create semaphore for key: {$key}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Semaphore requires a numeric value as the key
|
||||
*
|
||||
* @param $identifier
|
||||
* @return int
|
||||
*/
|
||||
protected function _stringToSemKey($identifier)
|
||||
{
|
||||
$md5 = md5($identifier);
|
||||
$key = 0;
|
||||
for ($i = 0; $i < 32; $i++) {
|
||||
$key += ord($md5{$i}) * $i;
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* create a lock instance
|
||||
*
|
||||
* @param $key
|
||||
* @return Semaphore
|
||||
*/
|
||||
public static function create($key)
|
||||
{
|
||||
return new Semaphore($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* release lock
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->isLocked()) {
|
||||
$this->release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* is locked
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLocked()
|
||||
{
|
||||
return $this->locked === true ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* release lock
|
||||
*
|
||||
* @return bool
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function release()
|
||||
{
|
||||
if (!$this->locked) {
|
||||
throw new \RuntimeException("release a non lock");
|
||||
}
|
||||
|
||||
if (!sem_release($this->lock_id)) {
|
||||
return false;
|
||||
}
|
||||
$this->locked = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a lock
|
||||
*
|
||||
* @param bool $blocking
|
||||
* @return bool
|
||||
*/
|
||||
public function acquire($blocking = true)
|
||||
{
|
||||
if ($this->locked) {
|
||||
throw new \RuntimeException('already lock by yourself');
|
||||
}
|
||||
|
||||
if ($blocking === false) {
|
||||
if (version_compare(PHP_VERSION, '5.6.0') < 0) {
|
||||
throw new \RuntimeException('php version is at least 5.6.0 for param blocking');
|
||||
}
|
||||
if (!sem_acquire($this->lock_id, true)) {
|
||||
return false;
|
||||
}
|
||||
$this->locked = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!sem_acquire($this->lock_id)) {
|
||||
return false;
|
||||
}
|
||||
$this->locked = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove the semaphore resource
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
if ($this->locked) {
|
||||
throw new \RuntimeException('can not remove a locked semaphore resource');
|
||||
}
|
||||
if (!is_resource($this->lock_id)) {
|
||||
throw new \RuntimeException('can not remove a empty semaphore resource');
|
||||
}
|
||||
|
||||
if (!sem_release($this->lock_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user