From: Christian Dickmann Date: Sat, 6 Jul 2002 14:44:05 +0000 (+0000) Subject: add local XMLRPC cache X-Git-Tag: INITIAL_IMPORT_SOURCEFORGE~27 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d04c8495d37b475451f279c0c88d2d154046109a;p=php add local XMLRPC cache --- diff --git a/pear/PEAR/Config.php b/pear/PEAR/Config.php index 84a6f94400..b039a0acd0 100644 --- a/pear/PEAR/Config.php +++ b/pear/PEAR/Config.php @@ -19,6 +19,7 @@ // $Id$ require_once 'PEAR.php'; +require_once 'System.php'; /** * Last created PEAR_Config instance. @@ -49,6 +50,9 @@ define('PEAR_CONFIG_DEFAULT_DATADIR', PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data'); define('PEAR_CONFIG_DEFAULT_TESTDIR', PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests'); + +define('PEAR_CONFIG_DEFAULT_CACHEDIR', (System::tmpdir()).'/pear/cache'); + if (@is_dir(PHP_SYSCONFDIR)) { define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR); } else { @@ -172,6 +176,13 @@ class PEAR_Config extends PEAR 'prompt' => 'PEAR test directory', 'group' => 'File Locations (Advanced)', ), + 'cache_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_CACHEDIR, + 'doc' => 'directory which is used for XMLRPC cache', + 'prompt' => 'PEAR Installer cache directory', + 'group' => 'File Locations (Advanced)', + ), // Maintainers 'username' => array( 'type' => 'string', @@ -215,6 +226,13 @@ class PEAR_Config extends PEAR 'prompt' => 'Unix file mask', 'group' => 'Advanced', ), + 'cache_ttl' => array( + 'type' => 'integer', + 'default' => 0, + 'doc' => 'amount of secs where the local cache is used and not updated', + 'prompt' => 'Cache TimeToLive', + 'group' => 'Advanced', + ), /* 'testset1' => array( 'type' => 'set', diff --git a/pear/PEAR/Remote.php b/pear/PEAR/Remote.php index 4d892dd568..ffc7af2fe4 100644 --- a/pear/PEAR/Remote.php +++ b/pear/PEAR/Remote.php @@ -34,6 +34,7 @@ class PEAR_Remote extends PEAR // {{{ properties var $config = null; + var $cache = null; // }}} @@ -46,19 +47,63 @@ class PEAR_Remote extends PEAR } // }}} - + + function getCache($args) + { + $id = md5(serialize($args)); + $cachedir = $this->config->get('cache_dir'); + if (!file_exists($cachedir)) { + System::mkdir('-p '.$cachedir); + } + $filename = $cachedir.'/xmlrpc_cache_'.$id; + if (!file_exists($filename)) { + return null; + }; + $result = array( + 'age' => time() - filemtime($filename), + 'lastChange' => filemtime($filename), + 'content' => unserialize(implode('', file($filename))), + ); + return $result; + } + + function saveCache($args, $data) + { + $id = md5(serialize($args)); + $cachedir = $this->config->get('cache_dir'); + if (!file_exists($cachedir)) { + System::mkdir('-p '.$cachedir); + } + $filename = $cachedir.'/xmlrpc_cache_'.$id; + + $fp = @fopen($filename, "w"); + if ($fp !== null) { + fwrite($fp, serialize($data)); + fclose($fp); + }; + } + // {{{ call(method, [args...]) function call($method) { + $_args = $args = func_get_args(); + + $this->cache = $this->getCache($args); + $cachettl = $this->config->get('cache_ttl'); + // If cache is newer than $cachettl seconds, we use the cache! + if ($this->cache !== null && $this->cache['age'] < $cachettl) { + return $this->cache['content']; + }; + if (extension_loaded("xmlrpc")) { - $args = func_get_args(); - return call_user_func_array(array(&$this, 'call_epi'), $args); + $result = call_user_func_array(array(&$this, 'call_epi'), $args); + $this->saveCache($_args, $result); + return $result; } if (!@include_once("XML/RPC.php")) { return $this->raiseError("For this remote PEAR operation you need to install the XML_RPC package"); } - $args = func_get_args(); array_shift($args); $server_host = $this->config->get('master_server'); $username = $this->config->get('username'); @@ -66,7 +111,12 @@ class PEAR_Remote extends PEAR $eargs = array(); foreach($args as $arg) $eargs[] = $this->_encode($arg); $f = new XML_RPC_Message($method, $eargs); - $c = new XML_RPC_Client('/xmlrpc.php', $server_host, 80); + if ($this->cache !== null) { + $maxAge = '?maxAge='.$this->cache['lastChange']; + } else { + $maxAge = ''; + }; + $c = new XML_RPC_Client('/xmlrpc.php'.$maxAge, $server_host, 80); if ($username && $password) { $c->setCredentials($username, $password); } @@ -79,10 +129,15 @@ class PEAR_Remote extends PEAR } $v = $r->value(); if ($e = $r->faultCode()) { + if ($e == $GLOBALS['XML_RPC_err']['http_error'] && strstr($r->faultString(), '304 Not Modified') !== false) { + return $this->cache['content']; + } return $this->raiseError($r->faultString(), $e); } - return XML_RPC_decode($v); + $result = XML_RPC_decode($v); + $this->saveCache($_args, $result); + return $result; } // }}} @@ -139,22 +194,31 @@ class PEAR_Remote extends PEAR $tmp = base64_encode("$username:$password"); $req_headers .= "Authorization: Basic $tmp\r\n"; } + if ($this->cache !== null) { + $maxAge = '?maxAge='.$this->cache['lastChange']; + } else { + $maxAge = ''; + }; + if ($this->config->get('verbose') > 3) { print "XMLRPC REQUEST HEADERS:\n"; var_dump($req_headers); print "XMLRPC REQUEST BODY:\n"; var_dump($request); } - fwrite($fp, ("POST /xmlrpc.php HTTP/1.0\r\n$req_headers\r\n$request")); + + fwrite($fp, ("POST /xmlrpc.php$maxAge HTTP/1.0\r\n$req_headers\r\n$request")); $response = ''; $line1 = fgets($fp, 2048); if (!preg_match('!^HTTP/[0-9\.]+ (\d+) (.*)!', $line1, $matches)) { return $this->raiseError("PEAR_Remote: invalid HTTP response from XML-RPC server"); } switch ($matches[1]) { - case "200": + case "200": // OK break; - case "401": + case "304": // Not Modified + return $this->cache['content']; + case "401": // Unauthorized if ($username && $password) { return $this->raiseError("PEAR_Remote: authorization failed", 401); } else {