From cde1f998386a59f2eba65bff37a177d9e7a428f9 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sat, 2 Jan 2010 22:46:13 -1000 Subject: Disk cache plugin --- plugins/DiskCachePlugin.php | 155 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 plugins/DiskCachePlugin.php (limited to 'plugins/DiskCachePlugin.php') diff --git a/plugins/DiskCachePlugin.php b/plugins/DiskCachePlugin.php new file mode 100644 index 000000000..86aedd19c --- /dev/null +++ b/plugins/DiskCachePlugin.php @@ -0,0 +1,155 @@ +. + * + * @category Cache + * @package StatusNet + * @author Evan Prodromou + * @copyright 2009 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +if (!defined('STATUSNET')) { + // This check helps protect against security problems; + // your code file can't be executed directly from the web. + exit(1); +} + +/** + * A plugin to cache data on local disk + * + * @category Cache + * @package StatusNet + * @author Evan Prodromou + * @copyright 2009 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class DiskCachePlugin extends Plugin +{ + var $root = '/tmp'; + + function keyToFilename($key) + { + return $this->root . '/' . str_replace(':', '/', $key); + } + + /** + * Get a value associated with a key + * + * The value should have been set previously. + * + * @param string &$key in; Lookup key + * @param mixed &$value out; value associated with key + * + * @return boolean hook success + */ + + function onStartCacheGet(&$key, &$value) + { + $filename = $this->keyToFilename($key); + if (file_exists($filename)) { + $this->log(LOG_INFO, "Cache hit on key '$key'"); + $data = file_get_contents($filename); + $value = unserialize($data); + } else { + $this->log(LOG_INFO, "Cache miss on key '$key'"); + } + + Event::handle('EndCacheGet', array($key, &$value)); + return false; + } + + /** + * Associate a value with a key + * + * @param string &$key in; Key to use for lookups + * @param mixed &$value in; Value to associate + * @param integer &$flag in; Flag (passed through to Memcache) + * @param integer &$expiry in; Expiry (passed through to Memcache) + * @param boolean &$success out; Whether the set was successful + * + * @return boolean hook success + */ + + function onStartCacheSet(&$key, &$value, &$flag, &$expiry, &$success) + { + $this->log(LOG_INFO, "Setting value for key '$key'"); + + $filename = $this->keyToFilename($key); + $parent = dirname($filename); + + $sofar = ''; + + foreach (explode('/', $parent) as $part) { + if (empty($part)) { + continue; + } + $sofar .= '/' . $part; + if (!is_dir($sofar)) { + $this->debug("Creating new directory '$sofar'"); + $success = mkdir($sofar, 0750); + if (!$success) { + $this->log(LOG_ERR, "Can't create directory '$sofar'"); + return false; + } + } + } + + if (is_dir($filename)) { + $success = false; + return false; + } + + file_put_contents($filename, serialize($value)); + + Event::handle('EndCacheSet', array($key, $value, $flag, + $expiry)); + + return false; + } + + /** + * Delete a value associated with a key + * + * @param string &$key in; Key to lookup + * @param boolean &$success out; whether it worked + * + * @return boolean hook success + */ + + function onStartCacheDelete(&$key, &$success) + { + $this->log(LOG_INFO, "Deleting value for key '$key'"); + + $filename = $this->keyToFilename($key); + + if (file_exists($filename) && !is_dir($filename)) { + unlink($filename); + } + + Event::handle('EndCacheDelete', array($key)); + return false; + } +} + -- cgit v1.2.3-54-g00ecf From f13cad656e1f53d8f801a4787bd8b28df427c6c2 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 4 Jan 2010 22:48:48 -1000 Subject: remove logging stuff from DiskCache --- plugins/DiskCachePlugin.php | 7 ------- 1 file changed, 7 deletions(-) (limited to 'plugins/DiskCachePlugin.php') diff --git a/plugins/DiskCachePlugin.php b/plugins/DiskCachePlugin.php index 86aedd19c..2b788decb 100644 --- a/plugins/DiskCachePlugin.php +++ b/plugins/DiskCachePlugin.php @@ -69,11 +69,8 @@ class DiskCachePlugin extends Plugin { $filename = $this->keyToFilename($key); if (file_exists($filename)) { - $this->log(LOG_INFO, "Cache hit on key '$key'"); $data = file_get_contents($filename); $value = unserialize($data); - } else { - $this->log(LOG_INFO, "Cache miss on key '$key'"); } Event::handle('EndCacheGet', array($key, &$value)); @@ -94,8 +91,6 @@ class DiskCachePlugin extends Plugin function onStartCacheSet(&$key, &$value, &$flag, &$expiry, &$success) { - $this->log(LOG_INFO, "Setting value for key '$key'"); - $filename = $this->keyToFilename($key); $parent = dirname($filename); @@ -140,8 +135,6 @@ class DiskCachePlugin extends Plugin function onStartCacheDelete(&$key, &$success) { - $this->log(LOG_INFO, "Deleting value for key '$key'"); - $filename = $this->keyToFilename($key); if (file_exists($filename) && !is_dir($filename)) { -- cgit v1.2.3-54-g00ecf From 04c76fc4e5d711ba38d22ffe201bb93d40126071 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 11 Jan 2010 16:23:34 -0800 Subject: safer storage for diskcacheplugin --- plugins/DiskCachePlugin.php | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'plugins/DiskCachePlugin.php') diff --git a/plugins/DiskCachePlugin.php b/plugins/DiskCachePlugin.php index 2b788decb..b709ea3b3 100644 --- a/plugins/DiskCachePlugin.php +++ b/plugins/DiskCachePlugin.php @@ -68,9 +68,12 @@ class DiskCachePlugin extends Plugin function onStartCacheGet(&$key, &$value) { $filename = $this->keyToFilename($key); + if (file_exists($filename)) { $data = file_get_contents($filename); - $value = unserialize($data); + if ($data !== false) { + $value = unserialize($data); + } } Event::handle('EndCacheGet', array($key, &$value)); @@ -116,7 +119,24 @@ class DiskCachePlugin extends Plugin return false; } - file_put_contents($filename, serialize($value)); + // Write to a temp file and move to destination + + $tempname = tempnam(null, 'statusnetdiskcache'); + + $result = file_put_contents($tempname, serialize($value)); + + if ($result === false) { + $this->log(LOG_ERR, "Couldn't write '$key' to temp file '$tempname'"); + return false; + } + + $result = rename($tempname, $filename); + + if (!$result) { + $this->log(LOG_ERR, "Couldn't move temp file '$tempname' to path '$filename' for key '$key'"); + @unlink($tempname); + return false; + } Event::handle('EndCacheSet', array($key, $value, $flag, $expiry)); -- cgit v1.2.3-54-g00ecf