1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
#!/usr/bin/env php
<?php
// Check that the memcache library is enabled
if (!class_exists('Memcache') && !class_exists('Memcached')) {
echo "Error: the memcached (or memcache) PHP extension 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_executable('/usr/sbin/phpenmod')) {
echo "It is possible that running one of the following commands as root will fix it:\n";
echo " phpenmod -s cli memcached\n";
echo " phpenmod -s cli memcache\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 = SimpleSAML\Utils\Config::getConfigDir();
\SimpleSAML\Configuration::setConfigDir($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 = [];
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 string $server The server, as a string with <hostname>:<port>.
*
* @return array An array with all the keys available on the server.
*/
function getServerKeys(string $server): array
{
$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 = [];
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 = [];
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;
}
|