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, 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"])) { 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; } } } } if ($result === false) { self::$last_error = '系统内存不足,申请失败'; } return $result; } /** * @param string $key * @return null|string * @throws Exception */ public static function get(string $key) { if (self::$kv_table === null) throw new Exception("not initialized LightCache"); self::checkExpire($key); $r = self::$kv_table->get($key); return $r === false ? null : self::parseGet($r); } /** * @param string $key * @return mixed|null * @throws Exception */ public static function getExpire(string $key) { if (self::$kv_table === null) throw new Exception("not initialized LightCache"); self::checkExpire($key); $r = self::$kv_table->get($key, "expire"); return $r === false ? null : $r - time(); } /** * @param string $key * @param string|array|int $value * @param int $expire * @return mixed * @throws Exception */ public static function set(string $key, $value, int $expire = -1) { 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"; } 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 >= 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) { return false; } } public static function getMemoryUsage() { return self::$kv_table->getMemorySize(); } /** * @param string $key * @return bool * @throws Exception */ public static function isset(string $key) { return self::get($key) !== null; } public static function unset(string $key) { return self::$kv_table->del($key); } public static function getAll() { $r = []; $del = []; foreach (self::$kv_table as $k => $v) { if ($v["expire"] <= time() && $v["expire"] >= 0) { $del[] = $k; continue; } $r[$k] = self::parseGet($v); } foreach ($del as $v) { self::unset($v); } return $r; } 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\"!"); } private static function checkExpire($key) { if (($expire = self::$kv_table->get($key, "expire")) >= 0) { if ($expire <= time()) { self::$kv_table->del($key); } } } private static function parseGet($r) { switch ($r["data_type"]) { case "json": case "int": case "bool": return json_decode($r["value"], true); case "": default: return $r["value"]; } } }