From c961f32bb3b88384441b26fe25ad7aa4ea2c5b90 Mon Sep 17 00:00:00 2001 From: xiaomlove <353856593@qq.com> Date: Sat, 26 Dec 2020 20:09:15 +0800 Subject: [PATCH] add Redis for cache and Mysqli for database query --- classes/class_cache_redis.php | 304 ++++++++++++++++++++++++++++++++++ classes/class_db.php | 94 +++++++++++ classes/class_db_mysqli.php | 67 ++++++++ classes/interface_db.php | 25 +++ include/bittorrent.php | 11 +- include/config.php | 17 +- include/core.php | 9 +- include/functions.php | 14 +- include/functions_db.php | 57 +++++++ 9 files changed, 582 insertions(+), 16 deletions(-) create mode 100644 classes/class_cache_redis.php create mode 100644 classes/class_db.php create mode 100644 classes/class_db_mysqli.php create mode 100644 classes/interface_db.php create mode 100644 include/functions_db.php diff --git a/classes/class_cache_redis.php b/classes/class_cache_redis.php new file mode 100644 index 00000000..0b24c61c --- /dev/null +++ b/classes/class_cache_redis.php @@ -0,0 +1,304 @@ +createRedisClient(); // Connect to Redis + if ($success) { + $this->isEnabled = 1; + } else { + $this->isEnabled = 0; + } + } + + private function createRedisClient() + { + global $BASIC; + $redis = new Redis(); + $params = [ + $BASIC['redis_host'], + ]; + if (!empty($BASIC['redis_port'])) { + $params[] = $BASIC['redis_port']; + } + if (!empty($BASIC['redis_timeout'])) { + $params[] = $BASIC['redis_timeout']; + } + $connectResult = $redis->connect(...$params); + $auth = []; + if (!empty($BASIC['redis_password'])) { + $auth['pass'] = $BASIC['redis_password']; + if (!empty($BASIC['redis_username'])) { + $auth['user'] = $BASIC['redis_username']; + } + $connectResult = $connectResult && $redis->auth($auth); + } + if ($connectResult) { + if (is_numeric($BASIC['redis_database'])) { + $selectDatabaseResult = $redis->select($BASIC['redis_database']); + if (!$selectDatabaseResult) { + $msg = "select redis database: {$BASIC['redis_database']} fail"; + write_log($msg); + throw new \RuntimeException($msg); + } + } + $this->redis = $redis; + } else { + write_log(sprintf('connect to redis with params: %s , with auth: %s fail', json_encode($params), json_encode($auth))); + } + return $connectResult; + } + + function getIsEnabled() { + return $this->isEnabled; + } + + function setClearCache($isEnabled) { + $this->clearCache = $isEnabled; + } + + function getLanguageFolderArray() { + return $this->languageFolderArray; + } + + function setLanguageFolderArray($languageFolderArray) { + $this->languageFolderArray = $languageFolderArray; + } + + function getClearCache() { + return $this->clearCache; + } + + function setLanguage($language) { + $this->language = $language; + } + + function getLanguage() { + return $this->language; + } + + function new_page($MemKey = '', $Duration = 3600, $Lang = true) { + if ($Lang) { + $language = $this->getLanguage(); + $this->MemKey = $language."_".$MemKey; + } else { + $this->MemKey = $MemKey; + } + $this->Duration = $Duration; + $this->Row = 1; + $this->Part = 0; + $this->Page = array(); + } + + function set_key(){ + + } + + //---------- Adding functions ----------// + + function add_row(){ + $this->Part = 0; + $this->Page[$this->Row] = array(); + } + + function end_row(){ + $this->Row++; + } + + function add_part(){ + ob_start(); + } + + function end_part(){ + $this->Page[$this->Row][$this->Part]=ob_get_clean(); + $this->Part++; + } + + // Shorthand for: + // add_row(); + // add_part(); + // You should only use this function if the row is only going to have one part in it (convention), + // although it will theoretically work with multiple parts. + function add_whole_row(){ + $this->Part = 0; + $this->Page[$this->Row] = array(); + ob_start(); + } + + // Shorthand for: + // end_part(); + // end_row(); + // You should only use this function if the row is only going to have one part in it (convention), + // although it will theoretically work with multiple parts. + function end_whole_row(){ + $this->Page[$this->Row][$this->Part]=ob_get_clean(); + $this->Row++; + } + + // Set a variable that will only be availabe when the system is on its row + // This variable is stored in the same way as pages, so don't use an integer for the $Key. + function set_row_value($Key, $Value){ + $this->Page[$this->Row][$Key] = $Value; + } + + // Set a variable that will always be available, no matter what row the system is on. + // This variable is stored in the same way as rows, so don't use an integer for the $Key. + function set_constant_value($Key, $Value){ + $this->Page[$Key] = $Value; + } + + // Inserts a 'false' value into a row, which breaks out of while loops. + // This is not necessary if the end of $this->Page is also the end of the while loop. + function break_loop(){ + if(count($this->Page)>0){ + $this->Page[$this->Row] = FALSE; + $this->Row++; + } + } + + //---------- Locking functions ----------// + + // These functions 'lock' a key. + // Users cannot proceed until it is unlocked. + + function lock($Key){ + $this->cache_value('lock_'.$Key, 'true', 3600); + } + + function unlock($Key) { +// $this->delete('lock_'.$Key); + $this->redis->del('lock_'.$Key); + } + + //---------- Caching functions ----------// + + // Cache $this->Page and resets $this->Row and $this->Part + function cache_page(){ + $this->cache_value($this->MemKey,$this->Page, $this->Duration); + $this->Row = 0; + $this->Part = 0; + } + + // Exact same as cache_page, but does not store the page in cache + // This is so that we can use classes that normally cache values in + // situations where caching is not required + function setup_page(){ + $this->Row = 0; + $this->Part = 0; + } + + // Wrapper for Memcache::set, with the zlib option removed and default duration of 1 hour + function cache_value($Key, $Value, $Duration = 3600){ +// $this->set($Key,$Value, 0, $Duration); + $this->redis->set($Key, $Value, $Duration); + $this->cacheWriteTimes++; + $this->keyHits['write'][$Key] = !$this->keyHits['write'][$Key] ? 1 : $this->keyHits['write'][$Key]+1; + } + + //---------- Getting functions ----------// + + // Returns the next row in the page + // If there's only one part in the row, return that part. + function next_row(){ + $this->Row++; + $this->Part = 0; + if($this->Page[$this->Row] == false){ + return false; + } + elseif(count($this->Page[$this->Row]) == 1){ + return $this->Page[$this->Row][0]; + } + else { + return $this->Page[$this->Row]; + } + } + + // Returns the next part in the row + function next_part(){ + $Return = $this->Page[$this->Row][$this->Part]; + $this->Part++; + return $Return; + } + + // Returns a 'row value' (a variable that changes for each row - see above). + function get_row_value($Key){ + return $this->Page[$this->Row][$Key]; + } + + // Returns a 'constant value' (a variable that doesn't change with the rows - see above) + function get_constant_value($Key){ + return $this->Page[$Key]; + } + + // If a cached version of the page exists, set $this->Page to it and return true. + // Otherwise, return false. + function get_page(){ + $Result = $this->get_value($this->MemKey); + if($Result){ + $this->Row = 0; + $this->Part = 0; + $this->Page = $Result; + return true; + } else { + return false; + } + } + + // Wrapper for Memcache::get. Why? Because wrappers are cool. + function get_value($Key) { + if($this->getClearCache()){ + $this->delete_value($Key); + return false; + } + // If we've locked it + // Xia Zuojie: we disable the following lock feature 'cause we don't need it and it doubles the time to fetch a value from a key + /*while($Lock = $this->get('lock_'.$Key)){ + sleep(2); + }*/ + + $Return = $this->redis->get($Key); + $this->cacheReadTimes++; + $this->keyHits['read'][$Key] = !$this->keyHits['read'][$Key] ? 1 : $this->keyHits['read'][$Key]+1; + return $Return; + } + + // Wrapper for Memcache::delete. For a reason, see above. + function delete_value($Key, $AllLang = false){ + if ($AllLang){ + $langfolder_array = $this->getLanguageFolderArray(); + foreach($langfolder_array as $lf) + $this->redis->del($lf."_".$Key); + } + else { + $this->redis->del($Key); + } + } + + function getCacheReadTimes() { + return $this->cacheReadTimes; + } + + function getCacheWriteTimes() { + return $this->cacheWriteTimes; + } + + function getKeyHits ($type='read') { + return (array)$this->keyHits[$type]; + } +} diff --git a/classes/class_db.php b/classes/class_db.php new file mode 100644 index 00000000..84f35a43 --- /dev/null +++ b/classes/class_db.php @@ -0,0 +1,94 @@ +driver = $driver; + + return $this; + } + + public static function getInstance() + { + if (self::$instance) { + return self::$instance; + } + $instance = new self; + $driver = new DBMysqli(); + $instance->setDriver($driver); + return self::$instance = $instance; + } + + + public function connect($host, $username, $password, $database, $port) + { + return $this->driver->connect($host, $username, $password, $database, $port); + } + + public function query(string $sql) + { + return $this->driver->query($sql); + } + + public function error() + { + return $this->driver->error(); + } + + public function errno() + { + return $this->driver->errno(); + } + + public function numRows($result) + { + return $this->driver->numRows($result); + } + + public function select_db($database) + { + return $this->driver->selectDb($database); + } + + public function fetchAssoc($result) + { + return $this->driver->fetchAssoc($result); + } + + public function fetchRow($result) + { + return $this->driver->fetchRow($result); + } + + public function affectedRows() + { + return $this->driver->affectedRows(); + } + + public function escapeString(string $string) + { + return $this->driver->escapeString($string); + } + + + + + +} \ No newline at end of file diff --git a/classes/class_db_mysqli.php b/classes/class_db_mysqli.php new file mode 100644 index 00000000..754dfbe7 --- /dev/null +++ b/classes/class_db_mysqli.php @@ -0,0 +1,67 @@ +report_mode = MYSQLI_REPORT_ALL & ~MYSQLI_REPORT_INDEX; + + return $this->mysqli = $mysqli; + } + + public function query(string $sql) + { + return $this->mysqli->query($sql); + } + + public function error(): string + { + return $this->mysqli->error; + } + + public function errno(): int + { + return $this->mysqli->errno; + } + + public function numRows($mysqliResult): int + { + return $mysqliResult->num_rows; + } + + public function selectDb($database) + { + return $this->mysqli->select_db($database); + } + + public function fetchAssoc($mysqliResult): array|null + { + return $mysqliResult->fetch_assoc(); + } + + public function fetchRow($mysqliResult): array|null + { + return $mysqliResult->fetch_row(); + } + + public function affectedRows(): int + { + return $this->mysqli->affected_rows; + } + + public function escapeString(string $string): string + { + return $this->mysqli->real_escape_string($string); + } + + +} \ No newline at end of file diff --git a/classes/interface_db.php b/classes/interface_db.php new file mode 100644 index 00000000..0ac07825 --- /dev/null +++ b/classes/interface_db.php @@ -0,0 +1,25 @@ +setLanguageFolderArray(get_langfolder_list()); define('TIMENOW', time()); $USERUPDATESET = array(); diff --git a/include/functions.php b/include/functions.php index 9299f932..774fdda6 100644 --- a/include/functions.php +++ b/include/functions.php @@ -3,7 +3,6 @@ if(!defined('IN_TRACKER')) die('Hacking attempt!'); include_once($rootpath . 'include/globalfunctions.php'); -include_once($rootpath . 'include/config.php'); include_once($rootpath . 'classes/class_advertisement.php'); require_once($rootpath . get_langfile_path("functions.php")); @@ -1690,8 +1689,9 @@ function dbconn($autoclean = false) global $lang_functions; global $mysql_host, $mysql_user, $mysql_pass, $mysql_db; global $useCronTriggerCleanUp; + global $BASIC; - if (!mysql_connect($mysql_host, $mysql_user, $mysql_pass)) + if (!mysql_connect($mysql_host, $mysql_user, $mysql_pass, $BASIC['mysql_db'], $BASIC['mysql_port'])) { switch (mysql_errno()) { @@ -4322,4 +4322,14 @@ function return_category_image($categoryid, $link="") } return $catimg; } + +function dd($vars) +{ + echo '
';
+    array_map(function ($var) {
+        var_dump($var);
+    }, func_get_args());
+    echo '
'; + exit(0); +} ?> diff --git a/include/functions_db.php b/include/functions_db.php new file mode 100644 index 00000000..5a19b42c --- /dev/null +++ b/include/functions_db.php @@ -0,0 +1,57 @@ +connect($host, $username, $password, $database, $port); +} + +function mysql_errno() +{ + return DB::getInstance()->errno(); +} + +function mysql_error() +{ + return DB::getInstance()->error(); +} + +function mysql_query(string $sql) +{ + return DB::getInstance()->query($sql); +} + +function mysql_select_db($database) +{ + return DB::getInstance()->select_db($database); +} + +function mysql_num_rows($result) +{ + return DB::getInstance()->numRows($result); +} + +function mysql_fetch_array($result) +{ + return DB::getInstance()->fetchAssoc($result); +} + +function mysql_fetch_assoc($result) +{ + return DB::getInstance()->fetchAssoc($result); +} + +function mysql_fetch_row($result) +{ + return DB::getInstance()->fetchRow($result); +} + +function mysql_affected_rows() +{ + return DB::getInstance()->affectedRows(); +} + +function mysql_real_escape_string($string) +{ + return DB::getInstance()->escapeString($string); +} +