From 194cf3fa70d791b2d809527d6be6abe100b6c095 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Sun, 17 Apr 2016 17:36:02 +0900 Subject: [PATCH] Enable all cache drivers, and add initial implementation of SQLite driver --- common/framework/cache.php | 2 +- common/framework/drivers/cache/sqlite.php | 241 ++++++++++++++++++++++ 2 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 common/framework/drivers/cache/sqlite.php diff --git a/common/framework/cache.php b/common/framework/cache.php index d30f31438..e9cf22489 100644 --- a/common/framework/cache.php +++ b/common/framework/cache.php @@ -34,7 +34,7 @@ class Cache { $class_name = '\\Rhymix\\Framework\\Drivers\\Cache\\' . $config['driver']; } - elseif (preg_match('/^(apc|memcache|redis|wincache|file)/', strval(array_first($config)), $matches)) + elseif (preg_match('/^(apc|dummy|file|memcache|redis|sqlite|wincache|xcache)/', strval(array_first($config)), $matches)) { $class_name = '\\Rhymix\\Framework\\Drivers\\Cache\\' . $matches[1] . ($matches[1] === 'memcache' ? 'd' : ''); } diff --git a/common/framework/drivers/cache/sqlite.php b/common/framework/drivers/cache/sqlite.php new file mode 100644 index 000000000..22e0747e9 --- /dev/null +++ b/common/framework/drivers/cache/sqlite.php @@ -0,0 +1,241 @@ +_connect($filename); + } + else + { + $this->_connect($filename); + for ($i = 0; $i < 32; $i++) + { + $this->_dbh->exec('CREATE TABLE cache_' . $i . ' (k TEXT PRIMARY KEY, v TEXT, exp INT)'); + } + } + } + + /** + * Connect to an SQLite3 database. + * + * @param string $filename + * @return void + */ + protected function _connect($filename) + { + $this->_dbh = new \SQLite3($filename); + $this->_dbh->exec('PRAGMA journal_mode = MEMORY'); + $this->_dbh->exec('PRAGMA synchronous = OFF'); + } + + /** + * Check if the current cache driver is supported on this server. + * + * This method returns true on success and false on failure. + * + * @return bool + */ + public function isSupported() + { + return class_exists('\\SQLite3'); + } + + /** + * Validate cache settings. + * + * This method returns true on success and false on failure. + * + * @param mixed $config + * @return bool + */ + public static function validateSettings($config) + { + return true; + } + + /** + * Get the value of a key. + * + * This method returns null if the key was not found. + * + * @param string $key + * @return mixed + */ + public function get($key) + { + $table = 'cache_' . (crc32($key) % 32); + $stmt = $this->_dbh->prepare('SELECT v, exp FROM ' . $table . ' WHERE k = :key'); + $stmt->bindValue(':key', $key, \SQLITE3_TEXT); + $result = $stmt->execute(); + $row = $result->fetchArray(\SQLITE3_NUM); + if ($row) + { + if ($row[1] == 0 || $row[1] >= time()) + { + return unserialize($row[0]); + } + else + { + $this->delete($key); + return null; + } + } + else + { + return null; + } + } + + /** + * Set the value to a key. + * + * This method returns true on success and false on failure. + * $ttl is measured in seconds. If it is zero, the key should not expire. + * + * @param string $key + * @param mixed $value + * @param int $ttl + * @return bool + */ + public function set($key, $value, $ttl) + { + $table = 'cache_' . (crc32($key) % 32); + $stmt = $this->_dbh->prepare('INSERT OR REPLACE INTO ' . $table . ' (k, v, exp) VALUES (:key, :val, :exp)'); + $stmt->bindValue(':key', $key, \SQLITE3_TEXT); + $stmt->bindValue(':val', serialize($value), \SQLITE3_TEXT); + $stmt->bindValue(':exp', $ttl ? (time() + $ttl) : 0, \SQLITE3_INTEGER); + return $stmt->execute() ? true : false; + } + + /** + * Delete a key. + * + * This method returns true on success and false on failure. + * If the key does not exist, it should return false. + * + * @param string $key + * @return bool + */ + public function delete($key) + { + $table = 'cache_' . (crc32($key) % 32); + $stmt = $this->_dbh->prepare('DELETE FROM ' . $table . ' WHERE k = :key'); + $stmt->bindValue(':key', $key, \SQLITE3_TEXT); + return $stmt->execute() ? true : false; + } + + /** + * Check if a key exists. + * + * This method returns true on success and false on failure. + * + * @param string $key + * @return bool + */ + public function exists($key) + { + $table = 'cache_' . (crc32($key) % 32); + $stmt = $this->_dbh->prepare('SELECT 1 FROM ' . $table . ' WHERE k = :key AND (exp = 0 OR exp >= :exp)'); + $stmt->bindValue(':key', $key, \SQLITE3_TEXT); + $stmt->bindValue(':exp', time(), \SQLITE3_INTEGER); + $result = $stmt->execute(); + $row = $result->fetchArray(\SQLITE3_NUM); + if ($row) + { + return true; + } + else + { + return false; + } + } + + /** + * Increase the value of a key by $amount. + * + * If the key does not exist, this method assumes that the current value is zero. + * This method returns the new value. + * + * @param string $key + * @param int $amount + * @return int + */ + public function incr($key, $amount) + { + $current_value = $this->get($key); + $new_value = intval($current_value) + $amount; + if ($this->set($key, $new_value)) + { + return $new_value; + } + else + { + return false; + } + } + + /** + * Decrease the value of a key by $amount. + * + * If the key does not exist, this method assumes that the current value is zero. + * This method returns the new value. + * + * @param string $key + * @param int $amount + * @return int + */ + public function decr($key, $amount) + { + return $this->incr($key, 0 - $amount); + } + + /** + * Clear all keys from the cache. + * + * This method returns true on success and false on failure. + * + * @return bool + */ + public function clear() + { + for ($i = 0; $i < 32; $i++) + { + $this->_dbh->exec('DROP TABLE cache_' . $i); + } + + for ($i = 0; $i < 32; $i++) + { + $this->_dbh->exec('CREATE TABLE cache_' . $i . ' (k TEXT PRIMARY KEY, v TEXT, exp INT)'); + } + } +}