mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-21 07:35:34 +08:00
initial 2.0.0-a4 commit
This commit is contained in:
@@ -12,6 +12,8 @@ class LightCache
|
||||
{
|
||||
/** @var Table|null */
|
||||
private static $kv_table = null;
|
||||
/** @var Table|null */
|
||||
private static $kv_lock = null;
|
||||
|
||||
private static $config = [];
|
||||
|
||||
@@ -22,17 +24,21 @@ class LightCache
|
||||
self::$kv_table = new Table($config["size"], $config["hash_conflict_proportion"]);
|
||||
self::$kv_table->column("value", Table::TYPE_STRING, $config["max_strlen"]);
|
||||
self::$kv_table->column("expire", Table::TYPE_INT);
|
||||
self::$kv_table->column("data_type", Table::TYPE_STRING, 12);
|
||||
self::$kv_table->column("data_type", Table::TYPE_STRING, 8);
|
||||
$result = self::$kv_table->create();
|
||||
self::$kv_lock = new Table($config["size"], $config["hash_conflict_proportion"]);
|
||||
$result = $result && self::$kv_lock->create();
|
||||
if ($result === true && isset($config["persistence_path"])) {
|
||||
$r = json_decode(file_get_contents($config["persistence_path"]), true);
|
||||
if ($r === null) $r = [];
|
||||
foreach ($r as $k => $v) {
|
||||
$write = self::set($k, $v);
|
||||
Console::debug("Writing LightCache: " . $k);
|
||||
if ($write === false) {
|
||||
self::$last_error = '可能是由于 Hash 冲突过多导致动态空间无法分配内存';
|
||||
return false;
|
||||
if (file_exists($config["persistence_path"])) {
|
||||
$r = json_decode(file_get_contents($config["persistence_path"]), true);
|
||||
if ($r === null) $r = [];
|
||||
foreach ($r as $k => $v) {
|
||||
$write = self::set($k, $v, -2);
|
||||
Console::verbose("Writing LightCache: " . $k);
|
||||
if ($write === false) {
|
||||
self::$last_error = '可能是由于 Hash 冲突过多导致动态空间无法分配内存';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,13 +89,46 @@ class LightCache
|
||||
$data_type = "";
|
||||
} elseif (is_int($value)) {
|
||||
$data_type = "int";
|
||||
} else {
|
||||
} elseif (is_bool($value)) {
|
||||
$data_type = "bool";
|
||||
$value = json_encode($value);
|
||||
}else {
|
||||
throw new Exception("Only can set string, array and int");
|
||||
}
|
||||
try {
|
||||
return self::$kv_table->set($key, [
|
||||
"value" => $value,
|
||||
"expire" => $expire != -1 ? $expire + time() : -1,
|
||||
"expire" => $expire >= 0 ? $expire + time() : $expire,
|
||||
"data_type" => $data_type
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param $value
|
||||
* @return bool|mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function update(string $key, $value) {
|
||||
if (self::$kv_table === null) throw new Exception("not initialized LightCache.");
|
||||
if (is_array($value)) {
|
||||
$value = json_encode($value, JSON_UNESCAPED_UNICODE);
|
||||
if (strlen($value) >= self::$config["max_strlen"]) return false;
|
||||
$data_type = "json";
|
||||
} elseif (is_string($value)) {
|
||||
$data_type = "";
|
||||
} elseif (is_int($value)) {
|
||||
$data_type = "int";
|
||||
} else {
|
||||
throw new Exception("Only can set string, array and int");
|
||||
}
|
||||
try {
|
||||
if(self::$kv_table->get($key) === false) return false;
|
||||
return self::$kv_table->set($key, [
|
||||
"value" => $value,
|
||||
"data_type" => $data_type
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
@@ -131,14 +170,16 @@ class LightCache
|
||||
}
|
||||
|
||||
public static function savePersistence() {
|
||||
if(self::$kv_table === null) return;
|
||||
$r = [];
|
||||
foreach (self::$kv_table as $k => $v) {
|
||||
if ($v["expire"] === -2) {
|
||||
Console::verbose("Saving " . $k);
|
||||
$r[$k] = self::parseGet($v);
|
||||
}
|
||||
}
|
||||
$r = file_put_contents(self::$config["persistence_path"], json_encode($r, 128 | 256));
|
||||
if($r === false) Console::error("Not saved, please check your \"persistence_path\"!");
|
||||
if ($r === false) Console::error("Not saved, please check your \"persistence_path\"!");
|
||||
}
|
||||
|
||||
private static function checkExpire($key) {
|
||||
@@ -153,6 +194,7 @@ class LightCache
|
||||
switch ($r["data_type"]) {
|
||||
case "json":
|
||||
case "int":
|
||||
case "bool":
|
||||
return json_decode($r["value"], true);
|
||||
case "":
|
||||
default:
|
||||
|
||||
55
src/ZM/Store/LightCacheInside.php
Normal file
55
src/ZM/Store/LightCacheInside.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Store;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Swoole\Table;
|
||||
|
||||
class LightCacheInside
|
||||
{
|
||||
/** @var Table[]|null */
|
||||
private static $kv_table = [];
|
||||
|
||||
public static $last_error = '';
|
||||
|
||||
public static function init() {
|
||||
self::$kv_table["wait_api"] = new Table(2, 0);
|
||||
self::$kv_table["wait_api"]->column("value", Table::TYPE_STRING, 65536);
|
||||
$result = self::$kv_table["wait_api"]->create();
|
||||
if ($result === false) {
|
||||
self::$last_error = '系统内存不足,申请失败';
|
||||
return $result;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function get(string $table, string $key) {
|
||||
if (!isset(self::$kv_table[$table])) throw new Exception("not initialized LightCache");
|
||||
$r = self::$kv_table[$table]->get($key);
|
||||
return $r === false ? null : json_decode($r["value"], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $table
|
||||
* @param string $key
|
||||
* @param string|array|int $value
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function set(string $table, string $key, $value) {
|
||||
if (self::$kv_table === null) throw new Exception("not initialized LightCache");
|
||||
try {
|
||||
return self::$kv_table[$table]->set($key, [
|
||||
"value" => json_encode($value, 256)
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function unset(string $table, string $key) {
|
||||
return self::$kv_table[$table]->del($key);
|
||||
}
|
||||
}
|
||||
44
src/ZM/Store/Lock/SpinLock.php
Normal file
44
src/ZM/Store/Lock/SpinLock.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Store\Lock;
|
||||
|
||||
|
||||
use Swoole\Coroutine;
|
||||
use Swoole\Coroutine\System;
|
||||
use Swoole\Table;
|
||||
|
||||
class SpinLock
|
||||
{
|
||||
/** @var null|Table */
|
||||
private static $kv_lock = null;
|
||||
|
||||
private static $delay = 1;
|
||||
|
||||
public static function init($key_cnt, $delay = 1)
|
||||
{
|
||||
self::$kv_lock = new Table($key_cnt, 0.7);
|
||||
self::$delay = $delay;
|
||||
self::$kv_lock->column('lock_num', Table::TYPE_INT, 8);
|
||||
return self::$kv_lock->create();
|
||||
}
|
||||
|
||||
public static function lock(string $key)
|
||||
{
|
||||
while (($r = self::$kv_lock->incr($key, 'lock_num')) > 1) { //此资源已经被锁上了
|
||||
if(Coroutine::getCid() != -1) System::sleep(self::$delay / 1000);
|
||||
else usleep(self::$delay * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
public static function tryLock(string $key) {
|
||||
if (($r = self::$kv_lock->incr($key, 'lock_num')) > 1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function unlock(string $key) {
|
||||
return self::$kv_lock->set($key, ['lock_num' => 0]);
|
||||
}
|
||||
}
|
||||
13
src/ZM/Store/MySQL/SqlPoolStorage.php
Normal file
13
src/ZM/Store/MySQL/SqlPoolStorage.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Store\MySQL;
|
||||
|
||||
|
||||
use Swoole\Database\PDOPool;
|
||||
|
||||
class SqlPoolStorage
|
||||
{
|
||||
/** @var PDOPool */
|
||||
public static $sql_pool = null;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Store\Redis;
|
||||
|
||||
|
||||
class Redis
|
||||
{
|
||||
}
|
||||
47
src/ZM/Store/Redis/ZMRedis.php
Normal file
47
src/ZM/Store/Redis/ZMRedis.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php /** @noinspection PhpComposerExtensionStubsInspection */
|
||||
|
||||
|
||||
namespace ZM\Store\Redis;
|
||||
|
||||
use Redis;
|
||||
use ZM\Exception\NotInitializedException;
|
||||
|
||||
class ZMRedis
|
||||
{
|
||||
private $conn;
|
||||
|
||||
/**
|
||||
* @param callable $callable
|
||||
* @return mixed
|
||||
* @throws NotInitializedException
|
||||
*/
|
||||
public static function call(callable $callable) {
|
||||
if(ZMRedisPool::$pool === null) throw new NotInitializedException("Redis pool is not initialized.");
|
||||
$r = ZMRedisPool::$pool->get();
|
||||
$result = $callable($r);
|
||||
if (isset($r->wasted)) ZMRedisPool::$pool->put(null);
|
||||
else ZMRedisPool::$pool->put($r);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ZMRedis constructor.
|
||||
* @throws NotInitializedException
|
||||
*/
|
||||
public function __construct() {
|
||||
if(ZMRedisPool::$pool === null) throw new NotInitializedException("Redis pool is not initialized.");
|
||||
$this->conn = ZMRedisPool::$pool->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Redis
|
||||
*/
|
||||
public function get() {
|
||||
return $this->conn;
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
if (isset($this->conn->wasted)) ZMRedisPool::$pool->put(null);
|
||||
else ZMRedisPool::$pool->put($this->conn);
|
||||
}
|
||||
}
|
||||
37
src/ZM/Store/Redis/ZMRedisPool.php
Normal file
37
src/ZM/Store/Redis/ZMRedisPool.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php /** @noinspection PhpComposerExtensionStubsInspection */
|
||||
|
||||
|
||||
namespace ZM\Store\Redis;
|
||||
|
||||
|
||||
use RedisException;
|
||||
use Swoole\Database\RedisConfig;
|
||||
use Swoole\Database\RedisPool;
|
||||
use ZM\Console\Console;
|
||||
|
||||
class ZMRedisPool
|
||||
{
|
||||
/** @var null|RedisPool */
|
||||
public static $pool = null;
|
||||
|
||||
public static function init($config) {
|
||||
self::$pool = new RedisPool((new RedisConfig())
|
||||
->withHost($config['host'])
|
||||
->withPort($config['port'])
|
||||
->withAuth($config['auth'])
|
||||
->withDbIndex($config['db_index'])
|
||||
->withTimeout($config['timeout'] ?? 1)
|
||||
);
|
||||
try {
|
||||
$r = self::$pool->get()->ping('123');
|
||||
if(strpos(strtolower($r), "123") !== false) {
|
||||
Console::debug("成功连接redis连接池!");
|
||||
} else {
|
||||
var_dump($r);
|
||||
}
|
||||
} catch (RedisException $e) {
|
||||
Console::error("Redis init failed! ".$e->getMessage());
|
||||
self::$pool = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/ZM/Store/ZMAtomic.php
Normal file
38
src/ZM/Store/ZMAtomic.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Store;
|
||||
|
||||
|
||||
use Swoole\Atomic;
|
||||
use ZM\Config\ZMConfig;
|
||||
|
||||
class ZMAtomic
|
||||
{
|
||||
/** @var Atomic[] */
|
||||
public static $atomics;
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return Atomic|null
|
||||
*/
|
||||
public static function get($name) {
|
||||
return self::$atomics[$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化atomic计数器
|
||||
*/
|
||||
public static function init() {
|
||||
foreach (ZMConfig::get("global", "init_atomics") as $k => $v) {
|
||||
self::$atomics[$k] = new Atomic($v);
|
||||
}
|
||||
self::$atomics["stop_signal"] = new Atomic(0);
|
||||
self::$atomics["wait_msg_id"] = new Atomic(0);
|
||||
for ($i = 0; $i < 10; ++$i) {
|
||||
self::$atomics["_tmp_" . $i] = new Atomic(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -8,46 +8,10 @@
|
||||
|
||||
namespace ZM\Store;
|
||||
|
||||
use Swoole\Atomic;
|
||||
use Swoole\Database\PDOPool;
|
||||
use ZM\Config\ZMConfig;
|
||||
|
||||
class ZMBuf
|
||||
{
|
||||
//读写的缓存数据,需要在worker_num = 1下才能正常使用
|
||||
//Swoole SQL连接池,多进程下每个进程一个连接池
|
||||
/** @var PDOPool */
|
||||
static $sql_pool = null;//保存sql连接池的类
|
||||
|
||||
/** @var array 事件注解的绑定对 */
|
||||
public static $events = [];
|
||||
|
||||
// 下面的有用,上面的没用了
|
||||
/** @var Atomic[] */
|
||||
public static $atomics;
|
||||
public static $instance = [];
|
||||
public static $context_class = [];
|
||||
public static $terminal = null;
|
||||
|
||||
/**
|
||||
* 初始化atomic计数器
|
||||
*/
|
||||
public static function initAtomic() {
|
||||
foreach (ZMConfig::get("global", "init_atomics") as $k => $v) {
|
||||
self::$atomics[$k] = new Atomic($v);
|
||||
}
|
||||
self::$atomics["stop_signal"] = new Atomic(0);
|
||||
self::$atomics["wait_msg_id"] = new Atomic(0);
|
||||
for($i = 0; $i < 10; ++$i) {
|
||||
self::$atomics["_tmp_".$i] = new Atomic(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return Atomic|null
|
||||
*/
|
||||
public static function atomic($name) {
|
||||
return self::$atomics[$name] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user