Added support for memcache as an alternative to cache_lite. The goal was to use memcache since it provides better scalability in a clustered environment.

public/htdocs/rss.php
    cacheLiteId => memcacheId

public/htdocs/update.php
    cacheLiteId => memcacheId,
    removed premature mysql_real_escape_string() calls

public/inc/config-dist.php
    modified config-dist.php to contain proper config stuff,
    cleaned up comments.

public/inc/finish.php
    added memcache support using memcache::set()

public/inc/init.php
    added error logging for failed connections,
    added calls to memcache::addServer for adding multiple memcached hosts,
    replaced Cache_Lite::get() with memcache::get()
This commit is contained in:
mike.morgan%oregonstate.edu 2006-03-17 00:43:09 +00:00
parent 6c450d021d
commit 4c420a1b61
5 changed files with 164 additions and 90 deletions

View File

@ -6,7 +6,7 @@
* @subpackage docs
*/
startProcessing('rss.tpl',$cacheLiteId,$compileId,'xml');
startProcessing('rss.tpl',$memcacheId,$compileId,'xml');
/**
* Pull our input params.

View File

@ -11,7 +11,7 @@
* @subpackage pub
*/
startProcessing('update.tpl', $cacheLiteId, $compileId, 'xml');
startProcessing('update.tpl', $memcacheId, $compileId, 'xml');
/**
* VARIABLES
@ -44,8 +44,6 @@ $sql['os_id'] = get_os_id();
foreach ($required_vars as $var) {
if (empty($_GET[$var])) {
$errors[] = 'Required variable '.$var.' not set.'; // set debug error
} else {
$sql[$var] = mysql_real_escape_string($_GET[$var]);
}
}
@ -57,6 +55,11 @@ if (empty($errors)) {
// We will need our DB in order to perform our query.
require_once('includes.php');
// Iterate through required variables, and escape/assign them as necessary.
foreach ($required_vars as $var) {
$sql[$var] = mysql_real_escape_string($_GET[$var]);
}
/*

View File

@ -6,45 +6,74 @@
* @subpackage inc
*/
// Set runtime error options.
// See http://php.oregonstate.edu/manual/en/ref.errorfunc.php#errorfunc.constants
/**
* Global settings.
*/
/**
* Set runtime error options.
* See http://php.oregonstate.edu/manual/en/ref.errorfunc.php#errorfunc.constants
*/
define('DISPLAY_ERRORS',1);
define('ERROR_REPORTING',2047);
// This is the base of the URL. It includes https|http.
define('HTTP_HOST','https://YOURHOST.DOMAIN.TLD');
/**
* This is the base of the URL. It includes https|http.
*/
define('HTTP_HOST','https://addons-test.mozilla.org');
// This is the root directory for public.
define('ROOT_PATH','/file/path/to/public');
/**
* This is the root directory for public.
*/
define('ROOT_PATH','/data/www/addons-test.mozilla.org/v2-memcache/public');
// This is the web path from the hostname.
// In production, it's typically just ''.
// However, if the URL to your installation is something like:
// https://update-staging.mozilla.org/~morgamic/v2/public/htdocs/
// Then WEB_PATH would be:
// /~morgamic/v2/public/htdocs
define('WEB_PATH','/web/relative/path/to/htdocs');
/**
*
* This is the web path from the hostname.
* In production, it's typically just ''.
* However, if the URL to your installation is something like:
* https://update-staging.mozilla.org/~morgamic/v2/public/htdocs/
* Then WEB_PATH would be:
* /~morgamic/v2/public/htdocs
*/
define('WEB_PATH','/v2-memcache/public/htdocs');
// Shared library directory contains all class definitions and central code.
define('LIB','/file/path/to/shared/lib');
/**
* Shared library directory contains all class definitions and central code.
*/
define('LIB','/data/www/addons-test.mozilla.org/v2-memcache/shared/lib');
// Smarty configuration.
/**
* Smarty configuration. The _DIR paths need to be writeable by the web user.
*/
define('SMARTY_BASEDIR','/usr/local/lib/php/Smarty');
define('TEMPLATE_DIR',ROOT_PATH.'/tpl');
define('COMPILE_DIR',ROOT_PATH.'/templates_c');
define('CACHE_DIR',ROOT_PATH.'/cache');
define('CONFIG_DIR',ROOT_PATH.'/configs');
// DB configuration.
// This database has read/write capabilities.
/**
* Database configuration.
*/
/**
* This database has read/write capabilities.
*/
define('DB_USER','');
define('DB_PASS','');
define('DB_HOST','');
define('DB_NAME','');
define('DB_PORT', '3306');
// Shadow DB configuration.
// This database has read-only access.
/**
* The shadow_db has read-only access.
*/
define('SHADOW_USER','');
define('SHADOW_PASS','');
define('SHADOW_HOST','');
@ -64,15 +93,17 @@ define('SHADOW_PORT', '3306');
* and lets sysadmins tweak things without creating CVS conflicts in production.
*/
// Shadow array defines which pages are going to use the shadow database.
// Filenames found in this array must work with read-only access to the database.
//
// Array contains [script name] values. For example, we could set the main page to
// use the shadow database:
// 'index.php'
//
// In the case where the PHP script is in a subdirectory, use the relative path from webroot:
// 'somedirectory/index.php'
/**
* Shadow array defines which pages are going to use the shadow database.
* Filenames found in this array must work with read-only access to the database.
*
* Array contains [script name] values. For example, we could set the main page to
* use the shadow database:
* 'index.php'
*
* In the case where the PHP script is in a subdirectory, use the relative path from webroot:
* 'somedirectory/index.php'
*/
$shadow_config = array(
'addon.php',
'author.php',
@ -91,12 +122,17 @@ $shadow_config = array(
'update.php'
);
// Array contains [script name] => [timeout] entries. For example, we could set
// a timeout of 1800 for index.php:
// 'index.php' => '1800'
//
// In the case where the PHP script is in a subdirectory, use the relative path from webroot:
// 'somedirectory/index.php' => '1800'
/**
* Array contains [script name] => [timeout] entries. For example, we could set
* a timeout of 1800 for index.php:
* 'index.php' => '1800'
*
* In the case where the PHP script is in a subdirectory, use the relative path from webroot:
* 'somedirectory/index.php' => '1800'
*
* If you have having any issues with memcached not being available, you should just comment out these array entries.
* It would also make sense to do this if you are developing / testing, since caching stuff would just confuse you.
*/
$cache_config = array(
'addon.php' => 900,
'author.php' => 900,
@ -115,8 +151,31 @@ $cache_config = array(
'update.php' => 900
);
// Array contains [script name] => [content type string] entries. These entries flag files that need to have a specific
// content-type that is not text/html.
/**
* memcache configuration.
*
* The memcache_config array lists all possible memcached servers to use in case the default server does not have the appropriate key.
*/
$memcache_config = array(
'localhost' => array(
'port' => '11211',
'persistent' => true,
'weight' => '1',
'timeout' => '1',
'retry_interval' => 15
)
);
/**
* Content type configuration.
*
* Array contains [script name] => [content type string] entries. These entries flag files that need to have a specific
* content-type that is not text/html.
*/
$contentType_config = array(
'update.php' => 'text/xml; charset=utf-8',
'rss.php' => 'text/xml; charset=utf-8'

View File

@ -2,6 +2,10 @@
/**
* Finish script.
*
* Pushes data to template for output generation.
* If the output is set to be cahced, it is stored in memcache.
* The timeout value is taken from the central configuration.
*
* @package amo
* @subpackage inc
*/
@ -69,11 +73,13 @@ if ($pageType != 'xml') {
/**
* If our config says so, the page should be cached.
*
* Only set the cache if we have a valid connection to our cache server (see $memcachedConnected in init.php).
*/
if (!empty($cache_config[SCRIPT_NAME])) {
if (!empty($cache_config[SCRIPT_NAME]) && !empty($memcacheConnected) && $memcacheConnected) {
// Save our page output to our cache.
$cache->save($pageOutput,$cacheLiteId,SCRIPT_NAME);
$cache->set($memcacheId, $pageOutput, false, $cache_config[SCRIPT_NAME]);
}

View File

@ -35,33 +35,45 @@ define('SCRIPT_NAME',substr($_SERVER['SCRIPT_NAME'], strlen(WEB_PATH.'/'), strle
/**
* Set up caching if this page requires caching. First we will include Cache_Lite and create an object.
* Page output caching.
*
* First we will create a memcache object.
* Second, we will check to see if the cache has already been compiled for our ID.
*
* This is all done before anything else happens because we want to save cycles.
*/
// Set our cacheLiteId based on our params.
// We'll keep it around even if we aren't using the cache.
$cacheLiteId = md5($_SERVER['QUERY_STRING']);
/**
* Set our memcacheId based on our params.
* We'll keep it around even if we aren't using the cache.
*/
$memcacheId = md5(SCRIPT_NAME.$_SERVER['QUERY_STRING']);
// Is the current page set to be cached?
/**
* Instantiate our memcache object.
*/
$cache = new memcache();
/**
* Check the cache_config to see if the current page is supposed to be cached.
* If it is, try to connect. If connection to the cache server fails, fall back on regular runtime.
* We also are storing the status of the connection in $memcacheConnected for use in finish.php.
*/
if (!empty($cache_config[SCRIPT_NAME]) ) {
require_once('Cache/Lite.php');
$memcacheConnected = false;
// Set options.
$cacheOptions = array(
'cacheDir' => CACHE_DIR.'/',
'lifeTime' => $cache_config[SCRIPT_NAME]
);
if (is_array($memcache_config)) {
foreach ($memcache_config as $host=>$options) {
if ($cache->addServer($host, $options['port'], $options['persistent'], $options['weight'], $options['timeout'], $options['retry_interval'])) {
$memcacheConnected = true;
}
}
}
// Instantiate Cache_Lite() object.
$cache = new Cache_Lite($cacheOptions);
if ($memcacheConnected) {
// If our page is already cached, display from cache and exit.
if ($cacheData = $cache->get($cacheLiteId,SCRIPT_NAME)) {
if ($cacheData = $cache->get($memcacheId)) {
// If we have specified a custom content-type for this script, echo the header here.
if (!empty($contentType_config[SCRIPT_NAME])) {
@ -71,6 +83,14 @@ if (!empty($cache_config[SCRIPT_NAME])) {
echo $cacheData;
exit;
}
} else {
/**
* If we get here, it means we were supposed to read from cache, but couldn't connect to memcached.
* Log the message, then continue with runtime.
*/
error_log('Memcache Error: Unable connect to memcache server. Please check configuration and try again.');
}
}
@ -87,27 +107,17 @@ $compileId = null; // Name of the compileId for use with Smarty caching.
$clean = array(); // General array for verified inputs. These variables should not be formatted for a specific medium.
$sql = array(); // Trusted for SQL. Items in this array must be trusted through logic or through escaping.
// If app is not set or empty, set it to null for our switch.
$_GET['app'] = (!empty($_GET['app'])) ? $_GET['app'] : null;
// Determine our application, and set the compileId to match it.
// cacheId is set per page, since that is a bit more complicated.
switch( $_GET['app'] ) {
case 'mozilla':
$compileId = 'mozilla';
break;
case 'thunderbird':
$compileId = 'thunderbird';
break;
case 'firefox':
default:
$compileId = 'firefox';
break;
}
/**
* CompileId is used for the compiled template generated by Smarty.
* If app is not a valid format, not set or just empty, set it to firefox.
*/
$compileId = (!empty($_GET['app']) && ctype_alpha($_GET['app'])) ? $_GET['app'] : 'firefox';
/**
* Smarty configuration.
*
* Include Smarty class. If we get here, we're going to generate the page.
*/
require_once(SMARTY_BASEDIR.'/Smarty.class.php'); // Smarty
@ -138,11 +148,7 @@ class AMO_Smarty extends Smarty
/**
* Begin template processing. Check to see if page output is cached.
* If it is already cached, display cached output.
* If it is not cached, continue typical runtime.
*
* NOTE: In order to avoid/disable caching, pass null as the argument for aCacheId and aCompileId.
* Begin template processing.
*
* @param string $aTplName name of the template to process
* @param string $aCacheId name of the cache to check - this corresponds to other $_GET params