initial 2.0.0-a4 commit

This commit is contained in:
jerry
2020-11-03 21:02:24 +08:00
parent da584e0542
commit 29fa9d8662
48 changed files with 794 additions and 1470 deletions

View File

@@ -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:

View 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);
}
}

View 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]);
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace ZM\Store\MySQL;
use Swoole\Database\PDOPool;
class SqlPoolStorage
{
/** @var PDOPool */
public static $sql_pool = null;
}

View File

@@ -1,9 +0,0 @@
<?php
namespace ZM\Store\Redis;
class Redis
{
}

View 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);
}
}

View 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
View 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);
}
}
}

View File

@@ -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;
}
}