diff --git a/mozilla/webtools/aus/xml/flush.php b/mozilla/webtools/aus/xml/flush.php new file mode 100644 index 00000000000..1d8ea07be53 --- /dev/null +++ b/mozilla/webtools/aus/xml/flush.php @@ -0,0 +1,15 @@ +flush(); +echo "Flushing memcache entries... \n"; +echo "Updated stats: \n\n"; +print_r($m->getExtendedStats()); +echo "\n"; +?> diff --git a/mozilla/webtools/aus/xml/inc/config-dist.php b/mozilla/webtools/aus/xml/inc/config-dist.php index f3a7dda34dd..ffafedf1472 100644 --- a/mozilla/webtools/aus/xml/inc/config-dist.php +++ b/mozilla/webtools/aus/xml/inc/config-dist.php @@ -103,6 +103,25 @@ $productBranchVersions = array( ) ); +// Config for memcache. +define('MEMCACHE_NAMESPACE', 'aus'); // set memcache namespace. Keep this string as short and simple as possible. +define('MEMCACHE_EXPIRE', 1800); // how long items are stored in memcache +define('MEMCACHE_ON', true); // whether or not to cache ever + +/** + * Memcache configuration. + * See http://php.oregonstate.edu/memcache for info. + */ +$memcache_config = array( + 'localhost' => array( + 'port' => '11211', + 'persistent' => true, + 'weight' => '1', + 'timeout' => '1', + 'retry_interval' => 15 + ) +); + // Array that defines which %OS_VERSION% values are no longer supported. // For incoming URIs containing these as their platformVersion, no updates // will be offered. diff --git a/mozilla/webtools/aus/xml/inc/init.php b/mozilla/webtools/aus/xml/inc/init.php index 3af9e32dcff..e202c473f77 100644 --- a/mozilla/webtools/aus/xml/inc/init.php +++ b/mozilla/webtools/aus/xml/inc/init.php @@ -51,4 +51,5 @@ require_once('aus.class.php'); // Generic object definition. require_once('xml.class.php'); // XML class for output generation. require_once('update.class.php'); // Update class for each update. require_once('patch.class.php'); // Patch class for update patches. +require_once('memcaching.php'); // Class for memcache. ?> diff --git a/mozilla/webtools/aus/xml/inc/memcaching.php b/mozilla/webtools/aus/xml/inc/memcaching.php new file mode 100644 index 00000000000..e41b652878f --- /dev/null +++ b/mozilla/webtools/aus/xml/inc/memcaching.php @@ -0,0 +1,156 @@ + (Original Author) + * Mike Morgan + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/** + * This model is an interface to Memcache. + * It's called Memcaching to not interfere with the actual Memcache class. + */ +class Memcaching { + var $cache; // holds the memcache object + var $memcacheConnected; // did we find a valid memcache server? + + function Memcaching() { + global $memcache_config; + + if (class_exists('Memcache') && defined('MEMCACHE_ON') && MEMCACHE_ON) + $this->cache = new Memcache(); + else + return false; + + if (defined('MEMCACHE_NAMESPACE')) + $this->namespace = MEMCACHE_NAMESPACE; + else + $this->namespace = ''; + + if (is_array($memcache_config)) { + foreach ($memcache_config as $host=>$options) { + if ($this->cache->addServer($host, $options['port'], $options['persistent'], $options['weight'], $options['timeout'], $options['retry_interval'])) { + $this->memcacheConnected = true; + } + } + } + + if (!$this->memcacheConnected) + error_log('Memcache Error: Unable connect to memcache server. Please check configuration and try again.'); + } + + /** + * Get an item from the cache, if it exists + * @return mixed item if found, else false + */ + function get($key) { + if (!$this->memcacheConnected) return false; + return $this->cache->get($this->namespaceKey($key)); + } + + /** + * Store an item in the cache. Replaces an existing item. + * @return bool success + */ + function set($key, $var, $flag = null, $expire = MEMCACHE_EXPIRE) { + if (!$this->memcacheConnected) return false; + return $this->cache->set($this->namespaceKey($key), $var, $flag, $expire); + } + + /** + * Store an item in the cache. Returns false if the key is + * already present in the cache. + * @return bool success + */ + function add($key, $var, $flag = null, $expire = MEMCACHE_EXPIRE) { + if (!$this->memcacheConnected) return false; + return $this->cache->add($this->namespaceKey($key), $var, $flag, $expire); + } + + /** + * Store an item in the cache. Returns false if the key did + * NOT exist in the cache before. + * @return bool success + */ + function replace($key, $var, $flag = null, $expire = MEMCACHE_EXPIRE) { + if (!$this->memcacheConnected) return false; + return $this->cache->replace($this->namespaceKey($key), $var, $flag, $expire); + } + + /** + * Close the connection to _ALL_ cache servers + * @return bool success + */ + function close() { + if (!$this->memcacheConnected) return false; + return $this->cache->close(); + } + + /** + * Delete something off the cache + * @return bool success + */ + function delete($key, $timeout = null) { + if (!$this->memcacheConnected) return false; + return $this->cache->delete($this->namespaceKey($key), $timeout); + } + + /** + * Returns key in the appropriate namespace. + * @param string $key memcache key + * @return string Namespaced key + */ + function namespaceKey($key) { + return $this->namespace . $key; + } + + /** + * Flush the cache + * @return bool success + */ + function flush() { + if (!$this->memcacheConnected) return false; + return $this->cache->flush(); + } + + /** + * Get server statistics. + * return array + */ + function getExtendedStats() { + if (!$this->memcacheConnected) return false; + return $this->cache->getExtendedStats(); + } +} +?> diff --git a/mozilla/webtools/aus/xml/index.php b/mozilla/webtools/aus/xml/index.php index dc012331a07..ea77b85b8fa 100644 --- a/mozilla/webtools/aus/xml/index.php +++ b/mozilla/webtools/aus/xml/index.php @@ -80,154 +80,162 @@ if ( (empty($_GET['force']) || $_GET['force']!=1) && // Find everything between our CWD and 255 in QUERY_STRING. $rawPath = substr(urldecode($_SERVER['QUERY_STRING']),5,255); -// Munge he resulting string and store it in $path. -$path = explode('/',$rawPath); +// Connect to memcache and try to pull output. +$memcache = new Memcaching(); +$_cached_xml = $memcache->get($rawPath); -// Determine incoming request and clean inputs. -// These are common URI elements, agreed upon in revision 0. -// For successive versions, the path of least resistence is to append and not reorder. -$clean = Array(); -$clean['updateVersion'] = isset($path[0]) ? intval($path[0]) : null; -$clean['product'] = isset($path[1]) ? trim($path[1]) : null; -$clean['version'] = isset($path[2]) ? urlencode($path[2]) : null; -$clean['build'] = isset($path[3]) ? trim($path[3]) : null; -$clean['platform'] = isset($path[4]) ? trim($path[4]) : null; -$clean['locale'] = isset($path[5]) ? trim($path[5]) : null; +if ($_cached_xml) { + $xml = $_cached_xml; +} else { + // Munge he resulting string and store it in $path. + $path = explode('/',$rawPath); -/** - * For each updateVersion, we will run separate code when it differs. - * Our case statements below are ordered by date added, desc (recent ones first). - * - * If the only difference is an added parameter, etc., then we may blend cases - * together by omitting a break. - */ -switch ($clean['updateVersion']) { - - /* - * This is for the fourth revision, adding %DISTRIBUTION% and - * %DISTRIBUTION_VERSION%. - * /update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml + // Determine incoming request and clean inputs. + // These are common URI elements, agreed upon in revision 0. + // For successive versions, the path of least resistence is to append and not reorder. + $clean = Array(); + $clean['updateVersion'] = isset($path[0]) ? intval($path[0]) : null; + $clean['product'] = isset($path[1]) ? trim($path[1]) : null; + $clean['version'] = isset($path[2]) ? urlencode($path[2]) : null; + $clean['build'] = isset($path[3]) ? trim($path[3]) : null; + $clean['platform'] = isset($path[4]) ? trim($path[4]) : null; + $clean['locale'] = isset($path[5]) ? trim($path[5]) : null; + + /** + * For each updateVersion, we will run separate code when it differs. + * Our case statements below are ordered by date added, desc (recent ones first). + * + * If the only difference is an added parameter, etc., then we may blend cases + * together by omitting a break. */ - case 3: - // Parse out dist information. For now, though, we aren't doing - // anything with it. - $clean['dist'] = isset($path[8]) ? trim($path[8]) : null; - $clean['distVersion'] = isset($path[9]) ? trim($path[9]) : null; - - /* - * This is for the third revision of the URI schema, with %OS_VERSION%. - * /update2/2/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/update.xml - */ - case 2: + switch ($clean['updateVersion']) { + + /* + * This is for the fourth revision, adding %DISTRIBUTION% and + * %DISTRIBUTION_VERSION%. + * /update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml + */ + case 3: + // Parse out dist information. For now, though, we aren't doing + // anything with it. + $clean['dist'] = isset($path[8]) ? trim($path[8]) : null; + $clean['distVersion'] = isset($path[9]) ? trim($path[9]) : null; + + /* + * This is for the third revision of the URI schema, with %OS_VERSION%. + * /update2/2/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/update.xml + */ + case 2: - // Parse out the %OS_VERSION% if it exists. - $clean['platformVersion'] = isset($path[7]) ? trim($path[7]) : null; + // Parse out the %OS_VERSION% if it exists. + $clean['platformVersion'] = isset($path[7]) ? trim($path[7]) : null; - // Check for OS_VERSION values and scrub the URI to make sure we aren't getting a malformed request - // from a client suffering from bug 360127. - if (empty($clean['platformVersion']) || $clean['platformVersion']=='%OS_VERSION%' || preg_match('/^1\.5.*$/',$clean['version'])) { + // Check for OS_VERSION values and scrub the URI to make sure we aren't getting a malformed request + // from a client suffering from bug 360127. + if (empty($clean['platformVersion']) || $clean['platformVersion']=='%OS_VERSION%' || preg_match('/^1\.5.*$/',$clean['version'])) { + break; + } + + // Check to see if the %OS_VERSION% value passed in the URI is in our no-longer-supported + // array which is set in our config. + if (!empty($clean['platformVersion']) && !empty($unsupportedPlatforms) && is_array($unsupportedPlatforms) && in_array($clean['platformVersion'], $unsupportedPlatforms)) { + + // If the passed OS_VERSION is in our array of unsupportedPlatforms, break the switch() and skip to the end. + // + // The default behavior is "no updates", so essentially the client would get an empty XML doc. + break; + } + + /* + * This is for the second revision of the URI schema, with %CHANNEL% added. + * /update2/1/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/update.xml + */ + case 1: + + // Check for a set channel. + $clean['channel'] = isset($path[6]) ? trim($path[6]) : null; + + // Instantiate Update object and set updateVersion. + $update = new Update(); + + // Instantiate our complete patch. + $completePatch = new Patch($productBranchVersions,$nightlyChannels,'complete'); + + // If our complete patch exists and is valid, set the patch line. + if ($completePatch->findPatch($clean['product'],$clean['platform'],$clean['locale'],$clean['version'],$clean['build'],$clean['channel']) && $completePatch->isPatch()) { + + // Set our patchLine. + $xml->setPatchLine($completePatch); + + // If available, pull update information from the build snippet. + if ($completePatch->hasUpdateInfo()) { + $update->setVersion($completePatch->updateVersion); + $update->setExtensionVersion($completePatch->updateExtensionVersion); + $update->setBuild($completePatch->build); + } + + // If there is details url information, add it to the update object. + if ($completePatch->hasDetailsUrl()) { + $update->setDetails($completePatch->detailsUrl); + } + + // If we found an update type, pass it along. + if ($completePatch->hasUpdateType()) { + $update->setType($completePatch->updateType); + } + + // If we have a license URL, pass it along. + if ($completePatch->hasLicenseUrl()) { + $update->setLicense($completePatch->licenseUrl); + } + } + + // Instantiate our partial patch. + $partialPatch = new Patch($productBranchVersions,$nightlyChannels,'partial'); + + // If our partial patch exists and is valid, set the patch line. + if ($partialPatch->findPatch($clean['product'],$clean['platform'],$clean['locale'],$clean['version'],$clean['build'],$clean['channel']) + && $partialPatch->isPatch() + && $partialPatch->isOneStepFromLatest($completePatch->build)) { + $xml->setPatchLine($partialPatch); + } + + // If we have valid patchLine(s), set up our output. + if ($xml->hasPatchLine()) { + $xml->startUpdate($update); + $xml->drawPatchLines(); + $xml->endUpdate(); + } break; - } - // Check to see if the %OS_VERSION% value passed in the URI is in our no-longer-supported - // array which is set in our config. - if (!empty($clean['platformVersion']) && !empty($unsupportedPlatforms) && is_array($unsupportedPlatforms) && in_array($clean['platformVersion'], $unsupportedPlatforms)) { + /* + * This is for the first revision of the URI schema. + * /update2/0/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/update.xml + */ + case 0: + default: - // If the passed OS_VERSION is in our array of unsupportedPlatforms, break the switch() and skip to the end. - // - // The default behavior is "no updates", so essentially the client would get an empty XML doc. + // Instantiate Update object and set updateVersion. + $update = new Update(); + + // Instantiate Patch object and set Path based on passed args. + $patch = new Patch($productBranchVersions,$nightlyChannels,'complete'); + + $patch->findPatch($clean['product'],$clean['platform'],$clean['locale'],$clean['version'],$clean['build'],null); + + if ($patch->isPatch()) { + $xml->setPatchLine($patch); + } + + // If we have a new build, draw the update block and patch line. + // If there is no valid patch file, client will receive no updates by default. + if ($xml->hasPatchLine()) { + $xml->startUpdate($update); + $xml->drawPatchLines(); + $xml->endUpdate(); + } break; - } - - /* - * This is for the second revision of the URI schema, with %CHANNEL% added. - * /update2/1/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/update.xml - */ - case 1: - - // Check for a set channel. - $clean['channel'] = isset($path[6]) ? trim($path[6]) : null; - - // Instantiate Update object and set updateVersion. - $update = new Update(); - - // Instantiate our complete patch. - $completePatch = new Patch($productBranchVersions,$nightlyChannels,'complete'); - - // If our complete patch exists and is valid, set the patch line. - if ($completePatch->findPatch($clean['product'],$clean['platform'],$clean['locale'],$clean['version'],$clean['build'],$clean['channel']) && $completePatch->isPatch()) { - - // Set our patchLine. - $xml->setPatchLine($completePatch); - - // If available, pull update information from the build snippet. - if ($completePatch->hasUpdateInfo()) { - $update->setVersion($completePatch->updateVersion); - $update->setExtensionVersion($completePatch->updateExtensionVersion); - $update->setBuild($completePatch->build); - } - - // If there is details url information, add it to the update object. - if ($completePatch->hasDetailsUrl()) { - $update->setDetails($completePatch->detailsUrl); - } - - // If we found an update type, pass it along. - if ($completePatch->hasUpdateType()) { - $update->setType($completePatch->updateType); - } - - // If we have a license URL, pass it along. - if ($completePatch->hasLicenseUrl()) { - $update->setLicense($completePatch->licenseUrl); - } - } - - // Instantiate our partial patch. - $partialPatch = new Patch($productBranchVersions,$nightlyChannels,'partial'); - - // If our partial patch exists and is valid, set the patch line. - if ($partialPatch->findPatch($clean['product'],$clean['platform'],$clean['locale'],$clean['version'],$clean['build'],$clean['channel']) - && $partialPatch->isPatch() - && $partialPatch->isOneStepFromLatest($completePatch->build)) { - $xml->setPatchLine($partialPatch); - } - - // If we have valid patchLine(s), set up our output. - if ($xml->hasPatchLine()) { - $xml->startUpdate($update); - $xml->drawPatchLines(); - $xml->endUpdate(); - } - break; - - /* - * This is for the first revision of the URI schema. - * /update2/0/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/update.xml - */ - case 0: - default: - - // Instantiate Update object and set updateVersion. - $update = new Update(); - - // Instantiate Patch object and set Path based on passed args. - $patch = new Patch($productBranchVersions,$nightlyChannels,'complete'); - - $patch->findPatch($clean['product'],$clean['platform'],$clean['locale'],$clean['version'],$clean['build'],null); - - if ($patch->isPatch()) { - $xml->setPatchLine($patch); - } - - // If we have a new build, draw the update block and patch line. - // If there is no valid patch file, client will receive no updates by default. - if ($xml->hasPatchLine()) { - $xml->startUpdate($update); - $xml->drawPatchLines(); - $xml->endUpdate(); - } - break; + } } // If we are debugging output plaintext and exit. @@ -280,6 +288,7 @@ if ( defined('DEBUG') && DEBUG == true ) { } // Set header and send info. +$memcache->set($rawPath,$xml); $xml->printXml(); exit; ?> diff --git a/mozilla/webtools/aus/xml/status.php b/mozilla/webtools/aus/xml/status.php new file mode 100644 index 00000000000..f49bda73306 --- /dev/null +++ b/mozilla/webtools/aus/xml/status.php @@ -0,0 +1,14 @@ +getExtendedStats()); +echo "\n"; +?>