From e062cae706cf9558ec8c71b055ae82149d6de157 Mon Sep 17 00:00:00 2001 From: Olav Morken <olav.morken@uninett.no> Date: Thu, 26 Jun 2008 13:02:08 +0000 Subject: [PATCH] Added script to sync memcache groups. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@718 44740490-163a-0410-bde0-09ae8108e29a --- bin/memcacheSync.php | 165 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100755 bin/memcacheSync.php diff --git a/bin/memcacheSync.php b/bin/memcacheSync.php new file mode 100755 index 000000000..13a41f99f --- /dev/null +++ b/bin/memcacheSync.php @@ -0,0 +1,165 @@ +#!/usr/bin/env php +<?php + + +/* Check that the memcache library is enabled. */ +if(!class_exists('Memcache')) { + echo("Error: the memcache library appears to be unavailable.\n"); + echo("\n"); + echo("This is most likely because PHP doesn't load it for the command line\n"); + echo("version. You probably need to enable it somehow.\n"); + echo("\n"); + if(is_dir('/etc/php5/cli/conf.d')) { + echo("It is possible that running the following command as root will fix it:\n"); + echo(" echo 'extension=memcache.so' >/etc/php5/cli/conf.d/memcache.ini\n"); + } + + exit(1); +} + +/* This is the base directory of the simpleSAMLphp installation. */ +$baseDir = dirname(dirname(__FILE__)); + +/* Add library autoloader. */ +require_once($baseDir . '/lib/_autoload.php'); + +/* Initialize the configuration. */ +$configdir = $baseDir . '/config'; +SimpleSAML_Configuration::init($configdir); + +/* Things we should warn the user about. */ +$warnServerDown = 0; +$warnBigSlab = 0; + +/* We use the stats interface to determine which servers exists. */ +$stats = SimpleSAML_Memcache::getRawStats(); + +$keys = array(); +foreach($stats as $group) { + foreach($group as $server => $state) { + + if($state === FALSE) { + echo("WARNING: Server " . $server . " is down.\n"); + $warnServerDown++; + continue; + } + + $items = $state['curr_items']; + echo("Server " . $server . " has " . $items . " items.\n"); + $serverKeys = getServerKeys($server); + $keys = array_merge($keys, $serverKeys); + } +} + +echo("Total number of keys: " . count($keys) . "\n"); +$keys = array_unique($keys); +echo("Total number of unique keys: " . count($keys) . "\n"); + +echo("Starting synchronization.\n"); + +$skipped = 0; +$sync = 0; +foreach($keys as $key) { + $res = SimpleSAML_Memcache::get($key); + if($res === NULL) { + $skipped += 1; + } else { + $sync += 1; + } +} + + +echo("Synchronization done.\n"); +echo($sync . " keys in sync.\n"); +if($skipped > 0) { + echo($skipped . " keys skipped.\n"); + echo("Keys are skipped because they are either expired, or are of a type unknown\n"); + echo("to simpleSAMLphp.\n"); +} + +if($warnServerDown > 0) { + echo("WARNING: " . $warnServerDown . " server(s) down. Not all servers are synchronized.\n"); +} + +if($warnBigSlab > 0) { + echo("WARNING: " . $warnBigSlab . " slab(s) may have contained more keys than we were told about.\n"); +} + +/** + * Fetch all keys available in an server. + * + * @param $server The server, as a string with <hostname>:<port>. + * @return An array with all the keys available on the server. + */ +function getServerKeys($server) { + $server = explode(':', $server); + $host = $server[0]; + $port = (int)$server[1]; + + echo("Connecting to: " . $host . ":" . $port . "\n"); + $socket = fsockopen($host, $port); + echo("Connected. Finding keys.\n"); + + if(fwrite($socket, "stats slabs\r\n") === FALSE) { + echo("Error requesting slab dump from server.\n"); + exit(1); + } + + /* Read list of slabs. */ + $slabs = array(); + while( ($line = fgets($socket)) !== FALSE) { + $line = rtrim($line); + if($line === 'END') { + break; + } + + if(preg_match('/^STAT (\d+):/', $line, $matches)) { + $slab = (int)$matches[1]; + if(!in_array($slab, $slabs, TRUE)) { + $slabs[] = $slab; + } + } + } + + /* Dump keys in slabs. */ + $keys = array(); + foreach($slabs as $slab) { + + if(fwrite($socket, "stats cachedump " . $slab . " 1000000\r\n") === FALSE) { + echo("Error requesting cache dump from server.\n"); + exit(1); + } + + /* We keep track of the result size, to be able to warn the user if it is + * so big that keys may have been lost. + */ + $resultSize = 0; + + while( ($line = fgets($socket)) !== FALSE) { + $resultSize += strlen($line); + + $line = rtrim($line); + if($line === 'END') { + break; + } + + if(preg_match('/^ITEM (.*) \[\d+ b; \d+ s\]/', $line, $matches)) { + $keys[] = $matches[1]; + } else { + echo("Unknown result from cache dump: " . $line . "\n"); + } + } + if($resultSize > 1900000 || count($keys) >= 1000000) { + echo("WARNING: Slab " . $slab . " on server " . $host . ":" . $port . + " may have contained more keys than we were told about.\n"); + $GLOBALS['warnBigSlab'] += 1; + } + } + + echo("Found " . count($keys) . " key(s).\n"); + fclose($socket); + + return $keys; +} + +?> \ No newline at end of file -- GitLab