Долгожданный новый дизайн от Nightmare git-svn-id: https://torrentpier2.googlecode.com/svn/trunk@353 a8ac35ab-4ca4-ca47-4c2d-a49a94f06293
This commit is contained in:
nanosimbiot 2012-02-03 05:54:29 +00:00
commit 09ae2d7085
159 changed files with 55 additions and 5985 deletions

View file

@ -1,28 +0,0 @@
<?php
return array (
'stats_api' => 'Server',
'slabs_api' => 'Server',
'items_api' => 'Server',
'get_api' => 'Server',
'set_api' => 'Server',
'delete_api' => 'Server',
'flush_all_api' => 'Server',
'connection_timeout' => '1',
'max_item_dump' => '100',
'refresh_rate' => 5,
'memory_alert' => '80',
'hit_rate_alert' => '90',
'eviction_alert' => '0',
'file_path' => 'Temp/',
'servers' =>
array (
'Default' =>
array (
'127.0.0.1:11211' =>
array (
'hostname' => '127.0.0.1',
'port' => '11211',
),
),
),
);

View file

@ -1,332 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Analysis of memcached command response
*
* @author c.mahieux@of2m.fr
* @since 20/03/2010
*/
class Library_Analysis
{
/**
* Merge two arrays of stats from MemCacheAdmin_ServerCommands::stats()
*
* @param $array Statistic from MemCacheAdmin_ServerCommands::stats()
* @param $stats Statistic from MemCacheAdmin_ServerCommands::stats()
*
* @return Array
*/
public static function merge($array, $stats)
{
# Checking input
if(!is_array($array))
{
return $stats;
}
elseif(!is_array($stats))
{
return $array;
}
# Merging Stats
foreach($stats as $key => $value)
{
if(isset($array[$key]) && ($key != 'version') && ($key != 'uptime'))
{
$array[$key] += $value;
}
else
{
$array[$key] = $value;
}
}
return $array;
}
/**
* Diff two arrays of stats from MemCacheAdmin_ServerCommands::stats()
*
* @param Array $array Statistic from MemCacheAdmin_ServerCommands::stats()
* @param Array $stats Statistic from MemCacheAdmin_ServerCommands::stats()
*
* @return Array
*/
public static function diff($array, $stats)
{
# Checking input
if(!is_array($array))
{
return $stats;
}
elseif(!is_array($stats))
{
return $array;
}
# Diff for each key
foreach($stats as $key => $value)
{
if(isset($array[$key]))
{
$stats[$key] = $value - $array[$key];
}
}
return $stats;
}
/**
* Analyse and return memcache stats command
*
* @param Array $stats Statistic from MemCacheAdmin_ServerCommands::stats()
*
* @return Array
*/
public static function stats($stats)
{
if(!is_array($stats) || (count($stats) == 0))
{
return false;
}
# Command set()
$stats['set_rate'] = ($stats['cmd_set'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_set'] / $stats['uptime'], 1);
# Command get()
$stats['get_hits_percent'] = ($stats['cmd_get'] == 0) ? ' - ' : sprintf('%.1f', $stats['get_hits'] / $stats['cmd_get'] * 100, 1);
$stats['get_misses_percent'] = ($stats['cmd_get'] == 0) ? ' - ' : sprintf('%.1f', $stats['get_misses'] / $stats['cmd_get'] * 100, 1);
$stats['get_rate'] = ($stats['cmd_get'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_get'] / $stats['uptime'], 1);
# Command delete(), version > 1.2.X
if(isset($stats['delete_hits'], $stats['delete_misses']))
{
$stats['cmd_delete'] = $stats['delete_hits'] + $stats['delete_misses'];
$stats['delete_hits_percent'] = ($stats['cmd_delete'] == 0) ? ' - ' : sprintf('%.1f', $stats['delete_hits'] / $stats['cmd_delete'] * 100, 1);
$stats['delete_misses_percent'] = ($stats['cmd_delete'] == 0) ? ' - ' : sprintf('%.1f', $stats['delete_misses'] / $stats['cmd_delete'] * 100, 1);
}
else
{
$stats['cmd_delete'] = 0;
$stats['delete_hits_percent'] = ' - ';
$stats['delete_misses_percent'] = ' - ';
}
$stats['delete_rate'] = ($stats['cmd_delete'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_delete'] / $stats['uptime'], 1);
# Command cas(), version > 1.2.X
if(isset($stats['cas_hits'], $stats['cas_misses'], $stats['cas_badval']))
{
$stats['cmd_cas'] = $stats['cas_hits'] + $stats['cas_misses'] + $stats['cas_badval'];
$stats['cas_hits_percent'] = ($stats['cmd_cas'] == 0) ? ' - ' : sprintf('%.1f', $stats['cas_hits'] / $stats['cmd_cas'] * 100, 1);
$stats['cas_misses_percent'] = ($stats['cmd_cas'] == 0) ? ' - ' : sprintf('%.1f', $stats['cas_misses'] / $stats['cmd_cas'] * 100, 1);
$stats['cas_badval_percent'] = ($stats['cmd_cas'] == 0) ? ' - ' : sprintf('%.1f', $stats['cas_badval'] / $stats['cmd_cas'] * 100, 1);
}
else
{
$stats['cmd_cas'] = 0;
$stats['cas_hits_percent'] = ' - ';
$stats['cas_misses_percent'] = ' - ';
$stats['cas_badval_percent'] = ' - ';
}
$stats['cas_rate'] = ($stats['cmd_cas'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_cas'] / $stats['uptime'], 1);
# Command increment(), version > 1.2.X
if(isset($stats['incr_hits'], $stats['incr_misses']))
{
$stats['cmd_incr'] = $stats['incr_hits'] + $stats['incr_misses'];
$stats['incr_hits_percent'] = ($stats['cmd_incr'] == 0) ? ' - ' : sprintf('%.1f', $stats['incr_hits'] / $stats['cmd_incr'] * 100, 1);
$stats['incr_misses_percent'] = ($stats['cmd_incr'] == 0) ? ' - ' : sprintf('%.1f', $stats['incr_misses'] / $stats['cmd_incr'] * 100, 1);
}
else
{
$stats['cmd_incr'] = 0;
$stats['incr_hits_percent'] = ' - ';
$stats['incr_misses_percent'] = ' - ';
}
$stats['incr_rate'] = ($stats['cmd_incr'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_incr'] / $stats['uptime'], 1);
# Command decrement(), version > 1.2.X
if(isset($stats['decr_hits'], $stats['decr_misses']))
{
$stats['cmd_decr'] = $stats['decr_hits'] + $stats['decr_misses'];
$stats['decr_hits_percent'] = ($stats['cmd_decr'] == 0) ? ' - ' : sprintf('%.1f', $stats['decr_hits'] / $stats['cmd_decr'] * 100, 1);
$stats['decr_misses_percent'] = ($stats['cmd_decr'] == 0) ? ' - ' : sprintf('%.1f', $stats['decr_misses'] / $stats['cmd_decr'] * 100, 1);
}
else
{
$stats['cmd_decr'] = 0;
$stats['decr_hits_percent'] = ' - ';
$stats['decr_misses_percent'] = ' - ';
}
$stats['decr_rate'] = ($stats['cmd_decr'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_decr'] / $stats['uptime'], 1);
# Total hit & miss
#$stats['cmd_total'] = $stats['cmd_get'] + $stats['cmd_set'] + $stats['cmd_delete'] + $stats['cmd_cas'] + $stats['cmd_incr'] + $stats['cmd_decr'];
#$stats['hit_percent'] = ($stats['cmd_get'] == 0) ? '0.0' : sprintf('%.1f', ($stats['get_hits']) / ($stats['get_hits'] + $stats['get_misses']) * 100, 1);
#$stats['miss_percent'] = ($stats['cmd_get'] == 0) ? '0.0' : sprintf('%.1f', ($stats['get_misses']) / ($stats['get_hits'] + $stats['get_misses']) * 100, 1);
# Command flush_all
if(isset($stats['cmd_flush']))
{
$stats['flush_rate'] = ($stats['cmd_flush'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_flush'] / $stats['uptime'], 1);
}
else
{
$stats['flush_rate'] = '0.0';
}
# Cache size
$stats['bytes_percent'] = ($stats['limit_maxbytes'] == 0) ? '0.0' : sprintf('%.1f', $stats['bytes'] / $stats['limit_maxbytes'] * 100, 1);
# Request rate
$stats['request_rate'] = sprintf('%.1f', ($stats['cmd_get'] + $stats['cmd_set'] + $stats['cmd_delete'] + $stats['cmd_cas'] + $stats['cmd_incr'] + $stats['cmd_decr']) / $stats['uptime'], 1);
$stats['hit_rate'] = sprintf('%.1f', ($stats['get_hits']) / $stats['uptime'], 1);
$stats['miss_rate'] = sprintf('%.1f', ($stats['get_misses']) / $stats['uptime'], 1);
# Eviction & reclaimed rate
$stats['eviction_rate'] = ($stats['evictions'] == 0) ? '0.0' : sprintf('%.1f', $stats['evictions'] / $stats['uptime'], 1);
$stats['reclaimed_rate'] = (!isset($stats['reclaimed']) || ($stats['reclaimed'] == 0)) ? '0.0' : sprintf('%.1f', $stats['reclaimed'] / $stats['uptime'], 1);
return $stats;
}
/**
* Analyse and return memcache slabs command
*
* @param Array $slabs Statistic from MemCacheAdmin_ServerCommands::slabs()
*
* @return Array
*/
public static function slabs($slabs)
{
# Initializing Used Slabs
$slabs['used_slabs'] = 0;
$slabs['total_wasted'] = 0;
# Request Rate par Slabs
foreach($slabs as $id => $slab)
{
# Check if it's a Slab
if(is_numeric($id))
{
# Check if Slab is used
if($slab['used_chunks'] > 0)
{
$slabs['used_slabs']++;
}
$slabs[$id]['request_rate'] = sprintf('%.1f', ($slab['get_hits'] + $slab['cmd_set'] + $slab['delete_hits'] + $slab['cas_hits'] + $slab['cas_badval'] + $slab['incr_hits'] + $slab['decr_hits']) / $slabs['uptime'], 1);
$slabs[$id]['mem_wasted'] = (($slab['total_chunks'] * $slab['chunk_size']) < $slab['mem_requested']) ?(($slab['total_chunks'] - $slab['used_chunks']) * $slab['chunk_size']):(($slab['total_chunks'] * $slab['chunk_size']) - $slab['mem_requested']);
$slabs['total_wasted'] += $slabs[$id]['mem_wasted'];
}
}
return $slabs;
}
/**
* Calculate Uptime
*
* @param Integer $uptime Uptime timestamp
*
* @return String
*/
public static function uptime($uptime)
{
if($uptime > 0)
{
$days = floor($uptime/60/60/24);
$hours = $uptime/60/60%24;
$mins = $uptime/60%60;
if(($days + $hours + $mins) == 0)
{
return ' less than 1 min';
}
return $days . ' days ' . $hours . ' hrs ' . $mins . ' min';
}
return ' - ';
}
/**
* Resize a byte value
*
* @param Integer $value Value to resize
*
* @return String
*/
public static function byteResize($value)
{
# Unit list
$units = array('', 'K', 'M', 'G', 'T');
# Resizing
foreach($units as $unit)
{
if($value < 1024)
{
break;
}
$value /= 1024;
}
return sprintf('%.1f %s', $value, $unit);
}
/**
* Resize a value
*
* @param Integer $value Value to resize
*
* @return String
*/
public static function valueResize($value)
{
# Unit list
$units = array('', 'K', 'M', 'G', 'T');
# Resizing
foreach($units as $unit)
{
if($value < 1000)
{
break;
}
$value /= 1000;
}
return sprintf('%.1f%s', $value, $unit);
}
/**
* Resize a hit value
*
* @param Integer $value Hit value to resize
*
* @return String
*/
public static function hitResize($value)
{
# Unit list
$units = array('', 'K', 'M', 'G', 'T');
# Resizing
foreach($units as $unit)
{
if($value < 10000000)
{
break;
}
$value /= 1000;
}
return sprintf('%.0f%s', $value, $unit);
}
}

View file

@ -1,111 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Factory for communication with Memcache Server
*
* @author c.mahieux@of2m.fr
* @since 30/03/2010
*/
class Library_Command_Factory
{
private static $_object = array();
# No explicit call of constructor
private function __construct() {}
# No explicit call of clone()
private function __clone() {}
/**
* Accessor to command class instance by command type
*
* @param String $command Type of command
*
* @return void
*/
public static function instance($command)
{
# Importing configuration
$_ini = Library_Configuration_Loader::singleton();
# Instance does not exists
if(!isset(self::$_object[$_ini->get($command)]) || ($_ini->get($command) != 'Server'))
{
# Switching by API
switch($_ini->get($command))
{
case 'Memcache':
# PECL Memcache API
require_once 'Memcache.php';
self::$_object['Memcache'] = new Library_Command_Memcache();
break;
case 'Memcached':
# PECL Memcached API
require_once 'Memcached.php';
self::$_object['Memcached'] = new Library_Command_Memcached();
break;
case 'Server':
default:
# Server API (eg communicating directly with the memcache server)
require_once 'Server.php';
self::$_object['Server'] = new Library_Command_Server();
break;
}
}
return self::$_object[$_ini->get($command)];
}
/**
* Accessor to command class instance by type
*
* @param String $command Type of command
*
* @return void
*/
public static function api($api)
{
# Instance does not exists
if(!isset(self::$_object[$api]) || ($api != 'Server'))
{
# Switching by API
switch($api)
{
case 'Memcache':
# PECL Memcache API
require_once 'Memcache.php';
self::$_object['Memcache'] = new Library_Command_Memcache();
break;
case 'Memcached':
# PECL Memcached API
require_once 'Memcached.php';
self::$_object['Memcached'] = new Library_Command_Memcached();
break;
case 'Server':
default:
# Server API (eg communicating directly with the memcache server)
require_once 'Server.php';
self::$_object['Server'] = new Library_Command_Server();
break;
}
}
return self::$_object[$api];
}
}

View file

@ -1,139 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Interface of communication to MemCache Server
*
* @author c.mahieux@of2m.fr
* @since 20/03/2010
*/
interface Library_Command_Interface
{
/**
* Constructor
*
* @return void
*/
function __construct();
/**
* Send stats command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
function stats($server, $port);
/**
* Retrieve slabs stats
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
function slabs($server, $port);
/**
* Retrieve items from a slabs
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Integer $slab Slab ID
*
* @return Array|Boolean
*/
function items($server, $port, $slab);
/**
* Send get command to server to retrieve an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to retrieve
*
* @return String
*/
function get($server, $port, $key);
/**
* Set an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to store
* @param Mixed $data Data to store
* @param Integer $duration Duration
*
* @return String
*/
function set($server, $port, $key, $data, $duration);
/**
* Delete an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to delete
*
* @return String
*/
function delete($server, $port, $key);
/**
* Flush all items on a server after delay
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Integer $delay Delay before flushing server
*
* @return String
*/
function flush_all($server, $port, $delay);
/**
* Search for item
* Return all the items matching parameters if successful, false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to search
*
* @return array
*/
function search($server, $port, $search);
/**
* Execute a telnet command on a server
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $command Command to execute
*
* @return String
*/
function telnet($server, $port, $command);
}

View file

@ -1,257 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Sending command to memcache server via PECL memcache API http://pecl.php.net/package/memcache
*
* @author c.mahieux@of2m.fr
* @since 20/03/2010
*/
class Library_Command_Memcache implements Library_Command_Interface
{
private static $_ini;
private static $_memcache;
/**
* Constructor
*
* @param Array $ini Array from ini_parse
*
* @return void
*/
public function __construct()
{
# Importing configuration
self::$_ini = Library_Configuration_Loader::singleton();
# Initializing
self::$_memcache = new Memcache();
}
/**
* Send stats command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function stats($server, $port)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command
if(($return = self::$_memcache->getExtendedStats()))
{
# Delete server key based
$stats = $return[$server.':'.$port];
return $stats;
}
return false;
}
/**
* Send stats items command to server to retrieve slabs stats
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function slabs($server, $port)
{
# Initializing
$slabs = array();
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : slabs
if(($slabs = self::$_memcache->getStats('slabs')))
{
# Finding uptime
$stats = $this->stats($server, $port);
$slabs['uptime'] = $stats['uptime'];
unset($stats);
# Executing command : items
if(($result = self::$_memcache->getStats('items')))
{
# Indexing by slabs
foreach($result['items'] as $id => $items)
{
foreach($items as $key => $value)
{
$slabs[$id]['items:' . $key] = $value;
}
}
return $slabs;
}
}
return false;
}
/**
* Send stats cachedump command to server to retrieve slabs items
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Interger $slab Slab ID
*
* @return Array|Boolean
*/
public function items($server, $port, $slab)
{
# Initializing
$items = false;
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : slabs stats
if(($items = self::$_memcache->getStats('cachedump', $slab, self::$_ini->get('max_item_dump'))))
{
return $items;
}
return false;
}
/**
* Send get command to server to retrieve an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to retrieve
*
* @return String
*/
public function get($server, $port, $key)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : get
if($item = self::$_memcache->get($key))
{
return print_r($item, true);
}
return 'NOT_FOUND';
}
/**
* Set an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to store
* @param Mixed $data Data to store
* @param Integer $duration Duration
*
* @return String
*/
function set($server, $port, $key, $data, $duration)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : set
if(self::$_memcache->set($key, $data, 0, $duration))
{
return 'STORED';
}
return 'ERROR';
}
/**
* Delete an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to delete
*
* @return String
*/
public function delete($server, $port, $key)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : delete
if(self::$_memcache->delete($key))
{
return 'DELETED';
}
return 'NOT_FOUND';
}
/**
* Flush all items on a server
* Warning, delay won't work with Memcache API
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Integer $delay Delay before flushing server
*
* @return String
*/
function flush_all($server, $port, $delay)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : flush_all
self::$_memcache->flush();
return 'OK';
}
/**
* Search for item
* Return all the items matching parameters if successful, false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to search
*
* @return array
*/
function search($server, $port, $search)
{
throw new Exception('PECL Memcache does not support search function, use Server instead');
}
/**
* Execute a telnet command on a server
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $command Command to execute
*
* @return String
*/
function telnet($server, $port, $command)
{
throw new Exception('PECL Memcache does not support telnet, use Server instead');
}
}

View file

@ -1,226 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Sending command to memcache server via PECL memcache API http://pecl.php.net/package/memcache
*
* @author c.mahieux@of2m.fr
* @since 20/03/2010
*/
class Library_Command_Memcached implements Library_Command_Interface
{
private static $_ini;
private static $_memcache;
/**
* Constructor
*
* @param Array $ini Array from ini_parse
*
* @return void
*/
public function __construct()
{
# Importing configuration
self::$_ini = Library_Configuration_Loader::singleton();
# Initializing
self::$_memcache = new Memcached();
}
/**
* Send stats command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function stats($server, $port)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command
if(($return = self::$_memcache->getStats()))
{
# Delete server key based
$stats = $return[$server.':'.$port];
# Adding value that miss
$stats['delete_hits'] = '';
$stats['delete_misses'] = '';
$stats['incr_hits'] = '';
$stats['incr_misses'] = '';
$stats['decr_hits'] = '';
$stats['decr_misses'] = '';
$stats['cas_hits'] = '';
$stats['cas_misses'] = '';
$stats['cas_badval'] = '';
return $stats;
}
return false;
}
/**
* Send stats items command to server to retrieve slabs stats
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function slabs($server, $port)
{
throw new Exception('PECL Memcache does not support slabs stats, use Server or Memcache instead');
}
/**
* Send stats cachedump command to server to retrieve slabs items
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Interger $slab Slab ID
*
* @return Array|Boolean
*/
public function items($server, $port, $slab)
{
throw new Exception('PECL Memcache does not support slabs items stats, use Server or Memcache instead');
}
/**
* Send get command to server to retrieve an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to retrieve
*
* @return String
*/
public function get($server, $port, $key)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : get
if($item = self::$_memcache->get($key))
{
return print_r($item, true);
}
return self::$_memcache->getResultMessage();
}
/**
* Set an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to store
* @param Mixed $data Data to store
* @param Integer $duration Duration
*
* @return String
*/
function set($server, $port, $key, $data, $duration)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Checking duration
if($duration == '') { $duration = 0; }
# Executing command : set
self::$_memcache->set($key, $data, $duration);
return self::$_memcache->getResultMessage();
}
/**
* Delete an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to delete
*
* @return String
*/
public function delete($server, $port, $key)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : delete
self::$_memcache->delete($key);
return self::$_memcache->getResultMessage();
}
/**
* Flush all items on a server
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Integer $delay Delay before flushing server
*
* @return String
*/
public function flush_all($server, $port, $delay)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : delete
self::$_memcache->flush($delay);
return self::$_memcache->getResultMessage();
}
/**
* Search for item
* Return all the items matching parameters if successful, false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to search
*
* @return array
*/
function search($server, $port, $search)
{
throw new Exception('PECL Memcached does not support search function, use Server instead');
}
/**
* Execute a telnet command on a server
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $command Command to execute
*
* @return String
*/
function telnet($server, $port, $command)
{
throw new Exception('PECL Memcached does not support telnet, use Server instead');
}
}

View file

@ -1,443 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Sending command to memcache server
*
* @author c.mahieux@of2m.fr
* @since 20/03/2010
*/
class Library_Command_Server implements Library_Command_Interface
{
private static $_ini;
private static $_log;
/**
* Constructor
*
* @param Array $ini Array from ini_parse
*
* @return void
*/
public function __construct()
{
# Importing configuration
self::$_ini = Library_Configuration_Loader::singleton();
}
/**
* Executing a Command on a MemCache Server
* With the help of http://github.com/memcached/memcached/blob/master/doc/protocol.txt
* Return the response, or false otherwise
*
* @param String $command Command
* @param String $server Server Hostname
* @param Integer $port Server Port
*
* @return String|Boolean
*/
public function exec($command, $server, $port)
{
# Variables
$buffer = '';
$handle = null;
# Socket Opening
if(!($handle = @fsockopen($server, $port, $errno, $errstr, self::$_ini->get('connection_timeout'))))
{
# Adding error to log
self::$_log = utf8_encode($errstr);
Library_Data_Error::add(utf8_encode($errstr));
return false;
}
# Sending Command ...
fwrite($handle, $command . "\r\n");
# Getting first line
$buffer = fgets($handle);
# Checking if result is valid
if($this->end($buffer))
{
# Closing socket
fclose($handle);
# Adding error to log
self::$_log = $buffer;
return false;
}
# Reading Results
while((!feof($handle)))
{
# Getting line
$line = fgets($handle);
$buffer .= $line;
# Checking for end of MemCache command
if($this->end($line))
{
break;
}
}
# Closing socket
fclose($handle);
return $buffer;
}
/**
* Check if response is at the end from memcache server
* Return true if response end, true otherwise
*
* @param String $buffer Buffer received from memcache server
*
* @return Boolean
*/
private function end($buffer)
{
# Checking command response end
if(preg_match('/(END|DELETED|OK|ERROR|SERVER_ERROR|CLIENT_ERROR|NOT_FOUND|STORED|RESET)\r\n$/', $buffer))
{
return true;
}
return false;
}
/**
* Parse result to make an array
*
* @param String $string String to parse
* @param Boolean $string (optionnal) Parsing stats ?
*
* @return Array
*/
public function parse($string, $stats = true)
{
# Variable
$return = array();
# Exploding by \r\n
$lines = preg_split('/\r\n/', $string);
# Stats
if($stats)
{
# Browsing each line
foreach($lines as $line)
{
$data = preg_split('/ /', $line);
if(isset($data[2]))
{
$return[$data[1]] = $data[2];
}
}
}
# Items
else
{
# Browsing each line
foreach($lines as $line)
{
$data = preg_split('/ /', $line);
if(isset($data[1]))
{
$return[$data[1]] = array(substr($data[2], 1), $data[4]);
}
}
}
return $return;
}
/**
* Send stats command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function stats($server, $port)
{
# Executing command
if(($return = $this->exec('stats', $server, $port)))
{
return $this->parse($return);
}
return false;
}
/**
* Send stats settings command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function settings($server, $port)
{
# Executing command
if(($return = $this->exec('stats settings', $server, $port)))
{
return $this->parse($return);
}
return false;
}
/**
* Send stats items command to server to retrieve slabs stats
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function slabs($server, $port)
{
# Initializing
$slabs = array();
# Finding uptime
$stats = $this->stats($server, $port);
$slabs['uptime'] = $stats['uptime'];
unset($stats);
# Executing command : slabs stats
if(($result = $this->exec('stats slabs', $server, $port)))
{
# Parsing result
$result = $this->parse($result);
$slabs['active_slabs'] = $result['active_slabs'];
$slabs['total_malloced'] = $result['total_malloced'];
unset($result['active_slabs']);
unset($result['total_malloced']);
# Indexing by slabs
foreach($result as $key => $value)
{
$key = preg_split('/:/', $key);
$slabs[$key[0]][$key[1]] = $value;
}
# Executing command : items stats
if(($result = $this->exec('stats items', $server, $port)))
{
# Parsing result
$result = $this->parse($result);
# Indexing by slabs
foreach($result as $key => $value)
{
$key = preg_split('/:/', $key);
$slabs[$key[1]]['items:' . $key[2]] = $value;
}
return $slabs;
}
}
return false;
}
/**
* Send stats cachedump command to server to retrieve slabs items
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Interger $slab Slab ID
*
* @return Array|Boolean
*/
public function items($server, $port, $slab)
{
# Initializing
$items = false;
# Executing command : stats cachedump
if(($result = $this->exec('stats cachedump ' . $slab . ' ' . self::$_ini->get('max_item_dump'), $server, $port)))
{
# Parsing result
$items = $this->parse($result, false);
}
return $items;
}
/**
* Send get command to server to retrieve an item
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to retrieve
*
* @return String
*/
public function get($server, $port, $key)
{
# Executing command : get
if(($string = $this->exec('get ' . $key, $server, $port)))
{
return preg_replace('/^VALUE ' . preg_quote($key, '/') . '[0-9 ]*\r\n/', '', $string);
}
return self::$_log;
}
/**
* Set an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to store
* @param Mixed $data Data to store
* @param Integer $duration Duration
*
* @return String
*/
function set($server, $port, $key, $data, $duration)
{
# Formatting data
$data = preg_replace('/\r/', '', $data);
# Executing command : set
if(($result = $this->exec('set ' . $key . ' 0 ' . $duration . ' ' . strlen($data) . "\r\n" . $data, $server, $port)))
{
return $result;
}
return self::$_log;
}
/**
* Delete an item
* Return true if successful, false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to delete
*
* @return String
*/
public function delete($server, $port, $key)
{
# Executing command : delete
if(($result = $this->exec('delete ' . $key, $server, $port)))
{
return $result;
}
return self::$_log;
}
/**
* Flush all items on a server
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Integer $delay Delay before flushing server
*
* @return String
*/
function flush_all($server, $port, $delay)
{
# Executing command : flush_all
if(($result = $this->exec('flush_all ' . $delay, $server, $port)))
{
return $result;
}
return self::$_log;
}
/**
* Search for item
* Return all the items matching parameters if successful, false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to search
*
* @return array
*/
function search($server, $port, $search)
{
$slabs = array();
$items = false;
# Executing command : slabs stats
if(($result = $this->exec('stats slabs', $server, $port)))
{
# Parsing result
$result = $this->parse($result);
unset($result['active_slabs']);
unset($result['total_malloced']);
# Indexing by slabs
foreach($result as $key => $value)
{
$key = preg_split('/:/', $key);
$slabs[$key[0]] = true;
}
}
# Exploring each slabs
foreach($slabs as $slab => $unused)
{
# Executing command : stats cachedump
if(($result = $this->exec('stats cachedump ' . $slab . ' 0', $server, $port)))
{
# Parsing result
preg_match_all('/^ITEM ((?:.*)' . preg_quote($search, '/') . '(?:.*)) \[(?:.*)\]\r\n/mU', $result, $matchs, PREG_SET_ORDER);
foreach($matchs as $item)
{
$items[] = $item[1];
}
}
unset($slabs[$slab]);
}
if(is_array($items))
{
sort($items);
}
return $items;
}
/**
* Execute a telnet command on a server
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $command Command to execute
*
* @return String
*/
function telnet($server, $port, $command)
{
# Executing command
if(($result = $this->exec($command, $server, $port)))
{
return $result;
}
return self::$_log;
}
}

View file

@ -1,187 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Configuration class for editing, saving, ...
*
* @author c.mahieux@of2m.fr
* @since 19/05/2010
*/
class Library_Configuration_Loader
{
# Singleton
protected static $_instance = null;
# Configuration file
protected static $_iniPath = './Config/Memcache.php';
# Configuration needed keys
protected static $_iniKeys = array('stats_api',
'slabs_api',
'items_api',
'get_api',
'set_api',
'delete_api',
'flush_all_api',
'connection_timeout',
'max_item_dump',
'refresh_rate',
'memory_alert',
'hit_rate_alert',
'eviction_alert',
'file_path',
'servers');
# Storage
protected static $_ini = array();
/**
* Constructor, load configuration file and parse server list
*
* @return Void
*/
protected function __construct()
{
# Opening ini file
self::$_ini = require self::$_iniPath;
}
/**
* Get Library_Configuration_Loader singleton
*
* @return Library_Configuration_Loader
*/
public static function singleton()
{
if(!isset(self::$_instance))
{
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Config key to retrieve
* Return the value, or false if does not exists
*
* @param String $key Key to get
*
* @return Mixed
*/
public function get($key)
{
if(isset(self::$_ini[$key]))
{
return self::$_ini[$key];
}
return false;
}
/**
* Servers to retrieve from cluster
* Return the value, or false if does not exists
*
* @param String $cluster Cluster to retreive
*
* @return Array
*/
public function cluster($cluster)
{
if(isset(self::$_ini['servers'][$cluster]))
{
return self::$_ini['servers'][$cluster];
}
return array();
}
/**
* Check and return server data
* Return the value, or false if does not exists
*
* @param String $server Server to retreive
*
* @return Array
*/
public function server($server)
{
foreach(self::$_ini['servers'] as $cluster => $servers)
{
if(isset(self::$_ini['servers'][$cluster][$server]))
{
return self::$_ini['servers'][$cluster][$server];
}
}
return array();
}
/**
* Config key to set
*
* @param String $key Key to set
* @param Mixed $value Value to set
*
* @return Boolean
*/
public function set($key, $value)
{
self::$_ini[$key] = $value;
}
/**
* Return actual ini file path
*
* @return String
*/
public function path()
{
return self::$_iniPath;
}
/**
* Check if every ini keys are set
* Return true if ini is correct, false otherwise
*
* @return Boolean
*/
public function check()
{
# Checking configuration keys
foreach(self::$_iniKeys as $iniKey)
{
# Ini file key not set
if(!isset(self::$_ini[$iniKey]))
{
return false;
}
}
return true;
}
/**
* Write ini file
* Return true if written, false otherwise
*
* @return Boolean
*/
public function write()
{
if($this->check())
{
return is_numeric(file_put_contents(self::$_iniPath, '<?php' . PHP_EOL . 'return ' . var_export(self::$_ini, true) . ';'));
}
return false;
}
}

View file

@ -1,59 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Error container
*
* @author elijaa@free.fr
* @since 11/10/2010
*/
class Library_Data_Error
{
private static $_errors = array();
/**
* Add an error to the container
* Return true if successful, false otherwise
*
* @param String $error Error message
*
* @return Boolean
*/
public static function add($error)
{
return array_push(self::$_errors, $error);
}
/**
* Return last Error message
*
* @return Mixed
*/
public static function last()
{
return (isset(self::$_errors[count(self::$_errors) - 1])) ? self::$_errors[count(self::$_errors) - 1] : null;
}
/**
* Return errors count
*
* @return Integer
*/
public static function count()
{
return count(self::$_errors);
}
}

View file

@ -1,147 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Manipulation of HTML
*
* @author c.mahieux@of2m.fr
* @since 05/04/2010
*/
class Library_HTML_Components
{
/**
* Dump server list in an HTML select
*
* @return string
*/
public static function serverSelect($name, $selected = '', $class = '', $events = '')
{
# Loading ini file
$_ini = Library_Configuration_Loader::singleton();
# Select Name
$serverList = '<select id="' . $name . '" ';
# CSS Class
$serverList .= ($class != '') ? 'class="' . $class . '"' : '';
# Javascript Events
$serverList .= ' ' . $events .'>';
foreach($_ini->get('servers') as $cluster => $servers)
{
# Cluster
$serverList .= '<option value="' . $cluster . '" ';
$serverList .= ($selected == $cluster) ? 'selected="selected"' : '';
$serverList .= '>' . $cluster . ' cluster</option>';
# Cluster server
foreach($servers as $server)
{
$serverList .= '<option value="' . $server['hostname'] . ':' . $server['port'] . '" ';
$serverList .= ($selected == $server['hostname'] . ':' . $server['port']) ? 'selected="selected"' : '';
$serverList .= '>&nbsp;&nbsp;-&nbsp;' . $server['hostname'] . ':' . $server['port'] . '</option>';
}
}
return $serverList . '</select>';
}
/**
* Dump cluster list in an HTML select
*
* @return string
*/
public static function clusterSelect($name, $selected = '', $class = '', $events = '')
{
# Loading ini file
$_ini = Library_Configuration_Loader::singleton();
# Select Name
$clusterList = '<select id="' . $name . '" ';
# CSS Class
$clusterList .= ($class != '') ? 'class="' . $class . '"' : '';
# Javascript Events
$clusterList .= ' ' . $events .'>';
foreach($_ini->get('servers') as $cluster => $servers)
{
# Option value and selected case
$clusterList .= '<option value="' . $cluster . '" ';
$clusterList .= ($selected == $cluster) ? 'selected="selected"' : '';
$clusterList .= '>' . $cluster . ' cluster</option>';
}
return $clusterList . '</select>';
}
/**
* Dump server response in proper formatting
*
* @param string $hostname Hostname
* @param string $port Port
* @param mixed $data Data (reponse)
*
* @return string
*/
public static function serverResponse($hostname, $port, $data)
{
$header = '<span class="red">Server ' . $hostname . ':' . $port . "</span>\r\n";
$return = '';
if(is_array($data))
{
foreach($data as $string)
{
$return .= $string . "\r\n";
}
return $header . htmlentities($return, ENT_NOQUOTES | ENT_IGNORE, "UTF-8") . "\r\n";
}
return $header . $return . $data . "\r\n";
}
/**
* Dump api list un HTML select with select name
*
* @param String $iniAPI API Name from ini file
* @param String $id Select ID
*
* @return String
*/
public static function apiList($iniAPI = '', $id)
{
return '<select id="' . $id . '" name="' . $id . '">
<option value="Server" ' . self::selected('Server', $iniAPI) . '>Server API</option>
<option value="Memcache" ' . self::selected('Memcache', $iniAPI) . '>Memcache API</option>
<option value="Memcached" ' . self::selected('Memcached', $iniAPI) . '>Memcached API</option>
</select>';
}
/**
* Used to see if an option is selected
*
* @param String $actual Actual value
* @param String $selected Selected value
*
* @return String
*/
private static function selected($actual, $selected)
{
if($actual == $selected)
{
return 'selected="selected"';
}
}
}

View file

@ -1,9 +0,0 @@
<?php
# Constants declaration
define('CURRENT_VERSION', '1.2.1');
# Autoloader
function __autoload($class)
{
require_once str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

View file

@ -1,29 +0,0 @@
function changeServer(obj){if(obj.options[obj.selectedIndex].value!=''){window.location='index.php?server='+obj.options[obj.selectedIndex].value;}else{window.location='index.php';}}
function changeCluster(obj){if(obj.options[obj.selectedIndex].value!=''){window.location='stats.php?cluster='+obj.options[obj.selectedIndex].value;}else{window.location='stats.php';}}
function changeCommand(obj){document.getElementById('request_key').value='';document.getElementById('request_duration').value='';document.getElementById('request_data').value='';document.getElementById('request_delay').value='';var command=obj.options[obj.selectedIndex].value;var div_key=document.getElementById('div_key');var div_duration=document.getElementById('div_duration');var div_data=document.getElementById('div_data');var div_delay=document.getElementById('div_delay');if(command=='get'||command=='delete'){div_key.style.display='';div_duration.style.display='none';div_data.style.display='none';div_delay.style.display='none';}else if(command=='set'){div_key.style.display='';div_duration.style.display='';div_data.style.display='';div_delay.style.display='none';}else if(command=='flush_all'){div_key.style.display='none';div_duration.style.display='none';div_data.style.display='none';div_delay.style.display='';}else{div_key.style.display='none';div_duration.style.display='none';div_data.style.display='none';div_delay.style.display='none';}}
function executeClear(target)
{var object=document.getElementById(target);object.innerHTML='';}
function executeCommand(target){if(document.getElementById('request_command').value!='')
{var request_url='commands.php?request_command='+document.getElementById('request_command').value+'&request_key='+document.getElementById('request_key').value+'&request_duration='+document.getElementById('request_duration').value+'&request_data='+document.getElementById('request_data').value+'&request_delay='+document.getElementById('request_delay').value+'&request_server='+document.getElementById('request_server').value+'&request_api='+document.getElementById('request_api').value;execute(request_url,target,true);}}
function searchKey(target){if(document.getElementById('search_key').value!='')
{var request_url='commands.php?request_command=search'+'&request_key='+document.getElementById('search_key').value+'&request_server='+document.getElementById('search_server').value;execute(request_url,target,true);}}
function executeTelnet(target){if(document.getElementById('request_telnet').value!='')
{var request_url='commands.php?request_command=telnet'+'&request_telnet='+document.getElementById('request_telnet').value+'&request_server='+document.getElementById('request_telnet_server').value;execute(request_url,target,true);}}
function execute(url,target,append){if(window.XMLHttpRequest){req=new XMLHttpRequest();req.onreadystatechange=function(){onExecute(target,append);};req.open('GET',url,true);req.send(null);}else if(window.ActiveXObject){req=new ActiveXObject('Microsoft.XMLHTTP');if(req){req.onreadystatechange=function(){onExecute(target,append);};req.open('GET',url,true);req.send();}}}
function onExecute(target,append){if(req.readyState==1){document.getElementById('loading').style.visibility="visible";}
else if(req.readyState==4){document.getElementById('loading').style.visibility="hidden";if(req.status==200||req.status==304){if(append==true)
{var object=document.getElementById(target);object.innerHTML+=req.responseText;object.scrollTop=object.scrollHeight;}
else
{var object=document.getElementById(target);object.innerHTML=req.responseText;object.scrollTop=object.scrollHeight;}}}
else{document.getElementById('loading').style.visibility="hidden";}}
var server_id=1;var cluster_id=1;function addCluster(){var clusterDiv=document.createElement('div');cluster_id++;clusterDiv.innerHTML='<hr/><strong>Cluster '+'<input type="text" style="width:200px;" name="cluster['+cluster_id+']" value=""/></strong>'+'<div style="margin-left:40px;margin-top:6px;" id="cluster_'+cluster_id+'_commands"><a class="list button" href="javascript:addServer('+cluster_id+')">'+'Add New Server to Cluster</a> <a class="list" style="padding:1px 2px;-moz-border-radius:3px;-webkit-border-radius:3px;" '+'href="#" onclick="deleteServerOrCluster(\'cluster_'+cluster_id+'\')">Delete Cluster</a></div><br/>';clusterDiv.setAttribute('id','cluster_'+cluster_id);document.getElementById('server_form').appendChild(clusterDiv);}
function addServer(current_cluster_id){var serverDiv=document.createElement('div');server_id++;serverDiv.innerHTML='<div id="server_'+server_id+'"><div style="margin-left:40px;margin-top:3px;">'+'<input type="text" style="width:200px;" name="server['+current_cluster_id+']['+server_id+'][hostname]" value="hostname" onfocus="hostnameOnFocus(this)" onblur="hostnameOnBlur(this)"/> '+'<input type="text" style="width:50px;" name="server['+current_cluster_id+']['+server_id+'][port]" value="port" onfocus="portOnFocus(this)" onblur="portOnBlur(this)"/> '+'<a class="list button" style="padding:1px 2px;" href="#" onclick="deleteServerOrCluster(\'server_'+server_id+'\')">Delete</a>'+'</div></div>';serverDiv.setAttribute('id','server_'+server_id);document.getElementById('cluster_'+current_cluster_id).insertBefore(serverDiv,document.getElementById('cluster_'+current_cluster_id+'_commands'));}
function deleteServerOrCluster(divID){var div=document.getElementById(divID);div.parentNode.removeChild(div);}
function hostnameOnFocus(obj){if(obj.value=='hostname'){obj.value='';}}
function hostnameOnBlur(obj){if(obj.value==''){obj.value='hostname';}}
function portOnFocus(obj){if(obj.value=='port'){obj.value='';}}
function portOnBlur(obj){if(obj.value==''){obj.value='port';}}
function ajax(url,target){if(window.XMLHttpRequest){req=new XMLHttpRequest();req.onreadystatechange=function(){ajaxDone(target);};req.open("GET",url,true);req.send(null);}else if(window.ActiveXObject){req=new ActiveXObject('Microsoft.XMLHTTP');if(req){req.onreadystatechange=function(){ajaxDone(target);};req.open("GET",url,true);req.send();}}
setTimeout("ajax(page, 'stats')",timeout);}
function ajaxDone(target){if(req.readyState==4){if(req.status==200||req.status==304){results=req.responseText;document.getElementById(target).innerHTML=results;}else{document.getElementById(target).innerHTML="Loading stats error : "
+req.statusText;}}}

View file

@ -1 +0,0 @@
body{background-color:#FEFEFE;font-family:Verdana,Tahoma,Segoe UI,Arial;font-size:0.8em;margin-top:10px}a{ color:#EEE; text-decoration:none}a:hover{ color:#A00}input,select,textarea{ -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; border:solid 1px #AAA; width:298px; font-family:tahoma; font-size:1em}textarea{ width:494px; resize:none}select{ width:300px}input:focus,textarea:focus{ border:solid 1px #EEE}input:hover{ color:#A00}img{ border:none}/** hr */hr{ height:0; border:none; border-bottom:solid 1px #eee}.menu{ border:solid 1px #a0312a; color:#eee; width:198px}.item{ font-family:Bitstream Vera Sans Mono}#loading{ text-decoration:blink; width:680px; visibility:hidden}.full-size{width:980px}.size-0{width:494px}.size-1{width:696px}.size-2{width:398px}.size-4{width:290px}.size-5{width:226px}.padding{padding:3px 7px 3px 7px}.corner{-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}.header{border:1px solid #9c3c36;background:url("../Images/b5463f.png") repeat-x scroll 50% 50% #B5463F;font-weight:bold;color:#fff;clear:both}.sub-header{border:1px solid #514845;background:url("../Images/635855.png") repeat-x scroll 50% 50% #635855;font-weight:bold;color:#fff;clear:both;margin-top:10px}.container{border:1px solid #d0d0d0;background:#ebebeb;font-weight:none;color:#000;margin-top:1px;clear:both}.list{border:1px solid #9c3c36;background:#B5463F;font-weight:bold;color:#fff}.button{padding:1px 20px;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px}.live{font-family:Bitstream Vera Sans Mono,Lucida Sans Typewriter,DejaVu Sans Mono;font-size:12px;overflow:visible;white-space:pre-wrap}.line{min-height:18px;padding-top:3px;padding-bottom:2px;clear:both}.left{float:left;min-width:126px;font-weight:bold}.right{float:right}.setting{min-width:180px}.slabs{min-width:104px}.container hr{height:0;border:none;border-bottom:solid 1px #fff}.grey{ color:#EEE}.green{color:#40aaba}.red{background:#b5463f;color:#fff;font-weight:bold}

View file

@ -1 +0,0 @@
a:1:{s:15:"127.0.0.1:11211";a:38:{s:3:"pid";s:4:"2049";s:6:"uptime";s:6:"779472";s:4:"time";s:10:"1326282322";s:7:"version";s:5:"1.4.5";s:12:"pointer_size";s:2:"32";s:11:"rusage_user";s:9:"20.137258";s:13:"rusage_system";s:9:"33.862116";s:16:"curr_connections";s:1:"6";s:17:"total_connections";s:5:"13230";s:21:"connection_structures";s:2:"17";s:7:"cmd_get";s:5:"25856";s:7:"cmd_set";s:5:"21025";s:9:"cmd_flush";s:1:"0";s:8:"get_hits";s:5:"22412";s:10:"get_misses";s:4:"3444";s:13:"delete_misses";s:1:"2";s:11:"delete_hits";s:2:"85";s:11:"incr_misses";s:1:"0";s:9:"incr_hits";s:1:"0";s:11:"decr_misses";s:1:"0";s:9:"decr_hits";s:1:"0";s:10:"cas_misses";s:1:"0";s:8:"cas_hits";s:1:"0";s:10:"cas_badval";s:1:"0";s:9:"auth_cmds";s:1:"0";s:11:"auth_errors";s:1:"0";s:10:"bytes_read";s:8:"34784259";s:13:"bytes_written";s:8:"61237342";s:14:"limit_maxbytes";s:8:"67108864";s:15:"accepting_conns";s:1:"1";s:19:"listen_disabled_num";s:1:"0";s:7:"threads";s:1:"4";s:11:"conn_yields";s:1:"0";s:5:"bytes";s:6:"175257";s:10:"curr_items";s:2:"45";s:11:"total_items";s:5:"21025";s:9:"evictions";s:1:"0";s:9:"reclaimed";s:4:"1746";}}

View file

@ -1,162 +0,0 @@
<div style="float:left;">
<div class="sub-header corner full-size padding">Console</div>
<div class="container corner full-size padding">
<pre id="container" style="font-size:11px;overflow:auto;min-height:180px;max-height:500px;" class="full-size"></pre>
</div>
<div class="container corner full-size padding" style="text-align:right;">
<span style="float:left;">
<input class="header" type="submit" id="loading" value="Waiting for server response ..."/>
</span>
<input class="header" type="submit" onclick="javascript:executeClear('container')" value="Clear Console"/>
</div>
<div class="sub-header corner full-size padding">Execute predefined <span class="green">Command</span></div>
<div class="container corner full-size padding">
<table>
<tr valign="top">
<td class="size-0 padding" style="padding-right:14px;">
<form action="commands.php" onsubmit="return false">
<div class="line" style="text-align:center;">
Execute command on one or all memcached servers<br/>
<hr/>
</div>
<div class="line">
<span class="left">Command</span>
<span class="right">
<select id="request_command" onchange="javascript:changeCommand(this);">
<option value="">Choose a Command</option>
<option value="get">Get</option>
<option value="set">Set</option>
<option value="delete">Delete</option>
<option value="flush_all">Flush All</option>
</select>
</span>
</div>
<div id="div_key" class="line" style="display:none;">
<span class="left">Key</span>
<span class="right">
<input id="request_key"/>
</span>
</div>
<div id="div_duration" class="line" style="display:none;">
<span class="left">Duration</span>
<span class="right">
<input id="request_duration"/>
</span>
</div>
<div id="div_data" class="line" style="display:none;">
<span class="left">Data</span>
<span class="right">
<textarea id="request_data" rows="2" cols="2"></textarea>
</span>
</div>
<div id="div_delay" class="line" style="display:none;">
<span class="left">Delay</span>
<span class="right">
<input id="request_delay"/>
</span>
</div>
<div class="line">
<span class="left">Server</span>
<span class="right">
<?php echo Library_HTML_Components::serverSelect('request_server'); ?>
</span>
</div>
<div class="line">
<span class="left">API</span>
<span class="right">
<?php echo Library_HTML_Components::apiList($_ini->get('get_api'), 'request_api'); ?>
</span>
</div>
<div class="line" style="text-align:center;">
<hr/>
<input class="header" type="submit"
onclick="javascript:executeCommand('container');javascript:this.blur();" value="Execute Command"/>
</div>
</form>
</td>
<td class="padding" style="border-left:1px solid #ffffff;padding-left:14px;">
<br/>
</td>
</tr>
</table>
</div>
<div class="sub-header corner full-size padding">Execute Telnet <span class="green">Commands</span></div>
<div class="container corner full-size padding">
<table>
<tr valign="top">
<td class="size-0 padding" style="padding-right:14px;">
<div class="line" style="text-align:center;">
Execute telnet command on one or all memcached servers<br/>
<hr/>
</div>
<div class="line" style="text-align:center;">
<textarea id="request_telnet" rows="2" cols="2"></textarea>
</div>
<div class="line">
<span class="left">Server</span>
<span class="right">
<?php echo Library_HTML_Components::serverSelect('request_telnet_server'); ?>
</span>
</div>
<div class="line" style="text-align:center;">
<hr/>
<input class="header" type="submit"
onclick="javascript:executeTelnet('container');javascript:this.blur();" value="Execute Telnet Command"/>
</div>
</td>
<td class="padding" style="border-left:1px solid #ffffff;padding-left:14px;">
You can use this thing to execute any telnet command to any memcached server
<br/>
It will connect to the server, execute the command and return it in the console
<br/>
<br/>
<br/>
<br/>
For more informations about memcached commands, see memcached protocol
<a href="http://github.com/memcached/memcached/blob/master/doc/protocol.txt" target="_blank"><span class="green">here</span></a>
</td>
</tr>
</table>
</div>
<div class="sub-header corner full-size padding">Search <span class="green">Key</span></div>
<div class="container corner full-size padding">
<table>
<tr valign="top">
<td class="size-0 padding" style="padding-right:14px;">
<div class="line" style="text-align:center;">
Search for a key on one or all memcached servers<br/>
<hr/>
</div>
<div class="line">
<span class="left">Key</span>
<span class="right">
<input id="search_key" name="search_key"/>
</span>
</div>
<div class="line">
<span class="left">Server</span>
<span class="right">
<?php echo Library_HTML_Components::serverSelect('search_server'); ?>
</span>
</div>
<div class="line" style="text-align:center;">
<hr/>
<input class="header" type="submit"
onclick="javascript:searchKey('container');javascript:this.blur();" value="Search Key"/>
</div>
</td>
<td class="padding" style="border-left:1px solid #ffffff;padding-left:14px;">
<span class="red">Warning !</span><br/>This thing is only for debuging issue, do not use it in a production environment as it can lock
or impact your memcached servers performances.
<br/>Also keep in mind that it does not list all keys. It lists keys up to a certain buffer size (1 or 2MB), and it list key that are expired.
<br/>
<br/>You can also use a PCRE regular expression
</td>
</tr>
</table>
</div>
</div>

View file

@ -1,161 +0,0 @@
<div style="float:left;">
<div class="size-0" style="float:left;">
<div class="sub-header corner padding">Commands <span class="green">Configuration</span></div>
<div class="container corner padding" style="padding-right:14px;">
<form method="post" action="configure.php?request_write=commands">
<div class="line">
Memcached commands API used by phpMemCacheAdmin<br/>
<hr/>
</div>
<div class="line">
<span class="left">Stats</span>
<span class="right"><?php echo Library_HTML_Components::apiList($_ini->get('stats_api'), 'stats_api'); ?></span>
</div>
<div class="line">
<span class="left">Slabs</span>
<span class="right"><?php echo Library_HTML_Components::apiList($_ini->get('slabs_api'), 'slabs_api'); ?></span>
</div>
<div class="line">
<span class="left">Items</span>
<span class="right"><?php echo Library_HTML_Components::apiList($_ini->get('items_api'), 'items_api'); ?></span>
</div>
<div class="line">
<span class="left">Get</span>
<span class="right"><?php echo Library_HTML_Components::apiList($_ini->get('get_api'), 'get_api'); ?></span>
</div>
<div class="line">
<span class="left">Set</span>
<span class="right"><?php echo Library_HTML_Components::apiList($_ini->get('set_api'), 'set_api'); ?></span>
</div>
<div class="line">
<span class="left">Delete</span>
<span class="right"><?php echo Library_HTML_Components::apiList($_ini->get('delete_api'), 'delete_api'); ?></span>
</div>
<div class="line">
<span class="left">Flush All</span>
<span class="right"><?php echo Library_HTML_Components::apiList($_ini->get('flush_all_api'), 'flush_all_api'); ?></span>
</div>
<div class="line" style="text-align:center;">
<hr/>
<input class="list" type="submit" value="Save API Configuration"/>
</div>
</form>
</div>
<div class="sub-header corner padding">Live Stats <span class="green">Configuration</span></div>
<div class="container corner padding" style="padding-right:14px;">
<form method="post" action="configure.php?request_write=live_stats">
<div class="line">
Alert &amp; refresh rate for Live Stats<br/>
<hr/>
</div>
<div class="line">
<span class="left">Refresh Rate in sec</span>
<span class="right"><input type="text" name="refresh_rate" value="<?php echo $_ini->get('refresh_rate'); ?>"/></span>
</div>
<div class="line">
<span class="left">Memory Alert</span>
<span class="right"><input type="text" name="memory_alert" value="<?php echo $_ini->get('memory_alert'); ?>"/></span>
</div>
<div class="line">
<span class="left">Hit Rate Alert</span>
<span class="right"><input type="text" name="hit_rate_alert" value="<?php echo $_ini->get('hit_rate_alert'); ?>"/></span>
</div>
<div class="line">
<span class="left">Eviction Alert</span>
<span class="right"><input type="text" name="eviction_alert" value="<?php echo $_ini->get('eviction_alert'); ?>"/></span>
</div>
<div class="line">
<span class="left">Temp Path</span>
<span class="right"><input type="text" name="file_path" value="<?php echo $_ini->get('file_path'); ?>"/></span>
</div>
<div class="line" style="text-align:center;">
<hr/>
<input class="list" type="submit" value="Save Live Configuration"/>
</div>
</form>
</div>
<div class="sub-header corner padding">Miscellaneous <span class="green">Configuration</span></div>
<div class="container corner padding" style="padding-right:14px;">
<form method="post" action="configure.php?request_write=miscellaneous">
<div class="line">
Server connection timeout &amp; miscellaneous<br/>
<hr/>
</div>
<div class="line">
<span class="left">Timeout in sec</span>
<span class="right"><input type="text" name="connection_timeout" value="<?php echo $_ini->get('connection_timeout'); ?>"/></span>
</div>
<div class="line">
<span class="left">Max Items</span>
<span class="right"><input type="text" name="max_item_dump" value="<?php echo $_ini->get('max_item_dump'); ?>"/></span>
</div>
<div class="line" style="text-align:center;">
<hr/>
<input class="list" type="submit" value="Save API Configuration"/>
</div>
</form>
</div>
</div>
<div class="size-0" style="float:left;padding-left:9px;">
<div class="sub-header corner padding">Server <span class="green">List</span></div>
<div class="container corner padding" style="padding-right:14px;">
<form method="post" action="configure.php?request_write=servers">
<div class="line">
Servers list used by phpMemCacheAdmin<br/>
</div>
<div id="server_form">
<?php
# Initializing variables
$server_id = 0;
$cluster_id = 0;
# Looking into each cluster
foreach($_ini->get('servers') as $cluster => $servers)
{
$cluster_id++; ?>
<div id="cluster_<?php echo $cluster_id; ?>">
<hr/>
<strong>Cluster <input type="text" style="width:200px;" name="cluster[<?php echo $cluster_id; ?>]" value="<?php echo $cluster; ?>"/></strong>
<?php # Adding input for each server
foreach($servers as $server)
{
$server_id++; ?>
<div id="server_<?php echo $server_id; ?>">
<div style="margin-left:40px;margin-top:3px;">
<input type="text" style="width:200px;" name="server[<?php echo $cluster_id; ?>][<?php echo $server_id; ?>][hostname]" value="<?php echo $server['hostname']; ?>" onfocus="hostnameOnFocus(this)" onblur="hostnameOnBlur(this)"/>
<input type="text" style="width:50px;" name="server[<?php echo $cluster_id; ?>][<?php echo $server_id; ?>][port]" value="<?php echo $server['port']; ?>" onfocus="portOnFocus(this)" onblur="portOnBlur(this)"/>
<a class="list button" style="padding:1px 2px;" href="#" onclick="deleteServerOrCluster('server_<?php echo $server_id; ?>')">Delete</a>
</div>
</div>
<?php } ?>
<div id="cluster_<?php echo $cluster_id; ?>_commands" style="margin-left:40px;margin-top:6px;">
<a class="list button" href="javascript:addServer(<?php echo $cluster_id; ?>)">Add New Server to Cluster</a> <a class="list" style="padding:1px 2px;-moz-border-radius:3px;-webkit-border-radius:3px;" href="#" onclick="deleteServerOrCluster('cluster_<?php echo $cluster_id; ?>')">Delete Cluster</a>
</div>
<br/>
</div>
<?php } ?>
</div>
<div class="line">
<hr/>
<a class="list button" href="javascript:addCluster()">Add New Cluster</a>
<input class="list" type="submit" value="Save Servers Configuration"/>
</div>
</form>
</div>
<script type="text/javascript">
server_id = <?php echo $server_id; ?>;
cluster_id = <?php echo $cluster_id; ?>;
</script>
<div class="container corner padding" style="margin-top:10px;">
<div class="line">
For more information about configuring phpMemcachedAdmin, see installation guide
<a href="http://code.google.com/p/phpmemcacheadmin/wiki/InstallationGuide" target="_blank"><span class="green">here</span></a>
</div>
</div>
</div>
</div>

View file

@ -1,7 +0,0 @@
<div class="sub-header corner full-size padding" style="float:left; text-align:center; margin-top:10px;">
<a href="http://code.google.com/p/phpmemcacheadmin/" target="_blank">phpMemcachedAdmin on GoogleCode</a>
- <a href="http://memcached.org/" target="_blank">Memcached.org</a>
</div>
</div>
</body>
</html>

View file

@ -1,62 +0,0 @@
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>phpMemcachedAdmin <?php echo CURRENT_VERSION; ?></title>
<link rel="stylesheet" type="text/css" href="Public/Styles/Style.css"/>
<script type="text/javascript" src="Public/Scripts/Script.js"></script>
</head>
<body>
<div style="margin:0pt auto; width:1000px; clear:both;">
<div style="font-weight:bold;font-size:1.2em;">phpMemcachedAdmin <sup><?php echo CURRENT_VERSION; ?></sup></div>
<div class="header corner full-size padding" style="text-align:center;margin-top:5px;">
<?php
# Live Stats view
if(basename($_SERVER['PHP_SELF']) == 'stats.php')
{ ?>
Live Stats |
<?php
} else { ?>
<a href="stats.php">See Live Stats </a> |
<?php
}
# Stats view
if(basename($_SERVER['PHP_SELF']) == 'index.php')
{ ?>
Actually seeing
<?php
} else { ?>
<a href="index.php">See Stats for </a>
<?php
}
# Server HTML select
echo Library_HTML_Components::serverSelect('server_select', (isset($_GET['server'])) ? $_GET['server'] : '', 'list', 'onchange="changeServer(this)"'); ?>
|
<?php
# Commands view
if(basename($_SERVER['PHP_SELF']) == 'commands.php')
{ ?>
Executing Commands on Servers
<?php
} else { ?>
<a href="commands.php">Execute Commands on Servers</a>
<?php
}?>
|
<?php
# Configure view
if(basename($_SERVER['PHP_SELF']) == 'configure.php')
{ ?>
Editing Configuration
<?php
} else { ?>
<a href="configure.php">Edit Configuration</a>
<?php
} ?>
</div>
<!--[if IE]>
<div class="header corner full-size padding" style="text-align:center;margin-top:10px;">
Support browsers that contribute to open source, try <a href="http://www.firefox.com" target="_blank">Firefox</a> or <a href="http://www.google.com/chrome" target="_blank">Google Chrome</a>.
</div>
<![endif]-->

View file

@ -1,70 +0,0 @@
<script type="text/javascript">
var timeout = <?php echo $refresh_rate * 1000; ?>;
var page = 'stats.php?request_command=live_stats&cluster=<?php echo $cluster; ?>';
setTimeout("ajax(page,'stats')", <?php echo (5 + $refresh_rate - $_ini->get('refresh_rate')) * 1000; ?>);
</script>
<div style="float:left;">
<div class="sub-header corner full-size padding">Live <span class="green">Stats</span></div>
<?php
# Refresh rate increased
if($refresh_rate > $_ini->get('refresh_rate'))
{ ?>
<div class="container corner" style="padding:9px;">
Connections errors were discovered, to prevent any problem, refresh rate was increased by
<?php echo sprintf('%.1f', $refresh_rate - $_ini->get('refresh_rate')); ?> seconds.
</div>
<?php
} ?>
<div class="full-size padding">
<br/>
<span class="live">Actually looking at <?php echo Library_HTML_Components::clusterSelect('cluster_select', (isset($_GET['cluster'])) ? $_GET['cluster'] : '', 'live', 'onchange="changeCluster(this);"'); ?> stats</span>
<pre id="stats" class="live">
Loading live stats, please wait ~<?php echo sprintf('%.0f', 5 + $refresh_rate - $_ini->get('refresh_rate')); ?> seconds ...
</pre>
</div>
<div class="container corner full-size padding">
<div class="line">
<span class="left setting">SIZE</span>
Total cache size on this server
</div>
<div class="line">
<span class="left setting">%MEM</span>
Percentage of total cache size used on this server
</div>
<div class="line">
<span class="left setting">%HIT</span>
Global hit percent on this server : get_hits / (get_hits + get_misses)
</div>
<div class="line">
<span class="left setting">TIME</span>
Time taken to connect to the server and proceed the request, high value can indicate a latency or server problem
</div>
<div class="line">
<span class="left setting">REQ/s</span>
Total request per second (get, set, delete, incr, ...) issued to this server
</div>
<div class="line">
<span class="left setting">CONN</span>
Current connections, monitor that this number doesn't come too close to the server max connection setting
</div>
<div class="line">
<span class="left setting">GET/s, SET/s, DEL/s</span>
Get, set or delete commands per second issued to this server
</div>
<div class="line">
<span class="left setting">EVI/s</span>
Number of times an item which had an explicit expire time set had to be evicted before it expired
</div>
<div class="line">
<span class="left setting">READ/s</span>
Total number of bytes read by this server from network
</div>
<div class="line">
<span class="left setting">WRITE/s</span>
Total number of bytes sent by this server to network
</div>
</div>
</div>

View file

@ -1,87 +0,0 @@
<?php
# CRLF/EOL
define('EOL', "\r\n");
# Header
echo 'Last update : ' . date('r', time()) . ' (refresh rate : ' . $_ini->get('refresh_rate') . ' sec)' . EOL . EOL;
# Table header
echo '<strong>' . sprintf('%-40s', 'SERVER:PORT') . sprintf('%10s', 'SIZE') . sprintf('%7s', '%MEM') . sprintf('%8s', 'TIME') .
sprintf('%6s', 'CONN') . sprintf('%7s', '%HIT') . sprintf('%8s', 'REQ/s') . sprintf('%8s', 'GET/s') . sprintf('%8s', 'SET/s') .
sprintf('%8s', 'DEL/s') . sprintf('%8s', 'EVI/s') . sprintf('%11s', 'READ/s') . sprintf('%10s', 'WRITE/s') . '</strong>' . EOL . '<hr>';
# Showing stats for every server
foreach($stats as $server => $data)
{
# Server name
echo sprintf('%-40.40s', $server);
# Checking for stats validity
if((isset($data['time'], $data['bytes_percent'], $data['get_hits_percent'], $data['query_time'], $data['request_rate'], $data['curr_connections'],
$data['get_rate'], $data['set_rate'], $data['delete_rate'], $data['eviction_rate'], $data['bytes_read'], $data['bytes_written'])) && ($data['time'] > 0))
{
# Total Memory
echo sprintf('%10s', Library_Analysis::byteResize($data['limit_maxbytes']) . 'b');
# Memory Occupation / Alert State
if($data['bytes_percent'] > $_ini->get('memory_alert'))
{
echo str_pad('', 7 - strlen($data['bytes_percent']), ' ') . '<span class="red">' . sprintf('%.1f', $data['bytes_percent']) . '</span>';
}
else
{
echo sprintf('%7.1f', $data['bytes_percent']);
}
# Query Time
echo sprintf('%5.0f', Library_Analysis::valueResize($data['query_time'])) . ' ms';
# Current connection
echo sprintf('%6s', $data['curr_connections']);
# Hit percent (get, delete, cas, incr & decr)
if($data['get_hits_percent'] < $_ini->get('hit_rate_alert'))
{
echo str_pad('', 7 - strlen($data['get_hits_percent']), ' ') . '<span class="red">' . sprintf('%.1f', $data['get_hits_percent']) . '</span>';
}
else
{
echo sprintf('%7.1f', $data['get_hits_percent']);
}
# Request rate
echo sprintf('%8s', Library_Analysis::valueResize($data['request_rate']));
# Get rate
echo sprintf('%8s', Library_Analysis::valueResize($data['get_rate']));
# Set rate
echo sprintf('%8s', Library_Analysis::valueResize($data['set_rate']));
# Delete rate
echo sprintf('%8s', Library_Analysis::valueResize($data['delete_rate']));
# Eviction rate
if($data['eviction_rate'] > $_ini->get('eviction_alert'))
{
echo str_pad('', 8 - strlen(Library_Analysis::valueResize($data['eviction_rate'])), ' ') . '<span class="red">' . Library_Analysis::valueResize($data['eviction_rate']) . '</span>';
}
else
{
echo sprintf('%8s', Library_Analysis::valueResize($data['eviction_rate']));
}
# Bytes read
echo sprintf('%11s', Library_Analysis::byteResize($data['bytes_read'] / $data['time']) . 'b');
# Bytes written
echo sprintf('%10s', Library_Analysis::byteResize($data['bytes_written'] / $data['time']) . 'b');
}
else
{
echo str_pad('', 20, ' ') . '<span class="alert">An error has occured when retreiving or calculating stats</span>';
}
# End of Line
echo EOL . '<hr>';
}

View file

@ -1,58 +0,0 @@
<?php
# Server seems down
if((isset($stats)) && (($stats === false) || ($stats == array())))
{ ?>
<div class="header corner full-size padding" style="margin-top:10px;text-align:center;">
<?php
# Asking server of cluster stats
if(isset($_GET['server']))
{
echo ($_ini->cluster($_GET['server'])) ? 'All servers from Cluster ' . $_GET['server'] : 'Server ' . $_GET['server'], ' did not respond !';
}
# All servers stats
else
{
echo 'Servers did not respond !';
} ?>
</div>
<div class="container corner full-size padding">
<span class="left">Error message</span>
<br/>
<?php echo Library_Data_Error::last(); ?>
<br/>
<br/>
Please check above error message, your <a href="configure.php" class="green">configuration</a> or your server status and retry
</div>
<?php
}
# No slabs used
elseif((isset($slabs)) && ($slabs === false))
{
?>
<div class="header corner full-size padding" style="margin-top:10px;text-align:center;">
No slabs used in this server !
</div>
<div class="container corner full-size padding">
<span class="left">Error message</span>
<br/>
Maybe this server is not used, check your <a href="configure.php" class="green">configuration</a> or your server status and retry
</div>
<?php
}
# No Items in slab
elseif((isset($items)) && ($items === false))
{
?>
<div class="header corner full-size padding" style="margin-top:10px;text-align:center;">
No item in this slab !
</div>
<div class="container corner full-size padding">
<span class="left">Error message</span>
<br/>
This slab is allocated, but is empty
<br/>
<br/>
Go back to <a href="?server=<?php echo $_GET['server']; ?>&amp;show=slabs" class="green">Server Slabs</a>
</div>
<?php
}

View file

@ -1,52 +0,0 @@
<?php
if((isset($response)) && ($response != array()))
{ ?>
<div class="sub-header corner full-size padding">Result</div>
<div class="container corner full-size padding">
<?php
foreach($response as $server => $result)
{ ?>
<pre style="font-size:12px;overflow:auto;" class="full-size"><?php echo htmlentities(trim($result), ENT_NOQUOTES, 'UTF-8'); ?></pre>
<?php
}
?>
</div>
<?php
} ?>
<div class="sub-header corner full-size padding">
Items in Slab <?php echo $_GET['slab']; ?>, only showing first <?php echo $_ini->get('max_item_dump'); ?> items
<span style="float:right;"><a href="?server=<?php echo $_GET['server']; ?>&amp;show=slabs">Back to Server Slabs</a></span>
</div>
<div class="container corner full-size padding">
<?php
$notFirst = false;
# Items
foreach($items as $key => $data)
{
# Checking if first item
if($notFirst) { echo '<hr/>'; }
?>
<a class="green item" href="index.php?server=<?php echo $_GET['server']; ?>&amp;show=items&amp;slab=<?php echo $_GET['slab']; ?>&amp;request_key=<?php echo $key; ?>&amp;request_api=<?php echo $_ini->get('get_api'); ?>&amp;request_command=get"><?php echo ((strlen($key) > 70) ? substr($key, 0, 70) . '[..]' : $key); ?></a>
<span class="right" style="clear:right;">
<strong>Size</strong> : <?php echo Library_Analysis::byteResize($data[0]); ?>Bytes,
<strong>Expiration</strong> :
<?php
# Infinite expiration
if($data[1] == $infinite)
{
echo '&#8734;';
}
# Timestamp expiration
else
{
echo Library_Analysis::uptime($data[1] - time());
} ?>
</span>
<?php
# First item done
$notFirst = true;
} ?>
</div>

View file

@ -1,126 +0,0 @@
<div class="size-4" style="float:left;">
<div class="sub-header corner padding">Slabs <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Slabs Used</span>
<?php echo $slabs['active_slabs']; ?>
</div>
<div class="line">
<span class="left">Memory Used</span>
<?php echo Library_Analysis::byteResize($slabs['total_malloced']); ?>Bytes
</div>
<div class="line">
<span class="left">Wasted</span>
<?php echo Library_Analysis::byteResize($slabs['total_wasted']); ?>Bytes
</div>
</div>
</div>
<div class="size-2" style="float:left;padding-left:9px;margin-top:10px;">
<div class="header corner padding size-3cols" style="text-align:center;">
<a href="?server=<?php echo $_GET['server']; ?>">See this Server Stats</a>
</div>
<br/>
</div>
<div class="size-1" style="float:left;padding-left:9px;">
<div class="container corner" style="padding:9px;">
For more informations about memcached slabs stats, see memcached protocol
<a href="http://github.com/memcached/memcached/blob/master/doc/protocol.txt#L470" target="_blank"><span class="green">here</span></a>
</div>
</div>
<table class="full-size" cellspacing="0" cellpadding="0">
<tr>
<?php
$actualSlab = 0;
# Slabs parsing
foreach($slabs as $id => $slab)
{
# If Slab is Used
if(is_numeric($id))
{
# Making a new line
if($actualSlab >= 4)
{
?>
</tr>
<tr>
<?php
$actualSlab = 0;
}
?>
<td <?php if($actualSlab > 0) { echo 'style="padding-left:9px;"'; } ?> valign="top">
<div class="sub-header corner padding size-5">Slab <?php echo $id; ?> <span class="green">Stats</span>
<span style="float:right;"><a href="?server=<?php echo $_GET['server']; ?>&amp;show=items&amp;slab=<?php echo $id; ?>">See Slab Items</a></span>
</div>
<div class="container corner padding size-5">
<div class="line">
<span class="left slabs">Chunk Size</span>
<?php echo Library_Analysis::byteResize($slab['chunk_size']); ?>Bytes
</div>
<div class="line">
<span class="left slabs">Used Chunk</span>
<?php echo Library_Analysis::hitResize($slab['used_chunks']); ?>
<span class="right">[<?php echo Library_Analysis::valueResize($slab['used_chunks'] / $slab['total_chunks'] * 100); ?> %]</span>
</div>
<div class="line">
<span class="left slabs">Total Chunk</span>
<?php echo Library_Analysis::hitResize($slab['total_chunks']); ?>
</div>
<div class="line">
<span class="left slabs">Total Page</span>
<?php echo $slab['total_pages']; ?>
</div>
<div class="line">
<span class="left slabs">Wasted</span>
<?php echo Library_Analysis::byteResize($slab['mem_wasted']); ?>Bytes
</div>
<div class="line">
<span class="left slabs">Hits</span>
<?php echo $slab['request_rate']; ?> Request/sec
</div>
<?php
if($slab['used_chunks'] > 0)
{ ?>
<div class="line">
<span class="left slabs">Evicted</span>
<?php echo (isset($slab['items:evicted'])) ? $slab['items:evicted'] : 'N/A'; ?>
</div>
<!--
<div class="line">
<span class="left slabs">Evicted Last</span>
<?php echo Library_Analysis::uptime($slab['items:evicted_time']); ?>
</div>
<div class="line">
<span class="left slabs">Out of Memory</span>
<?php echo $slab['items:outofmemory']; ?>
</div>
<div class="line">
<span class="left slabs">Tail Repairs</span>
<?php echo $slab['items:tailrepairs']; ?>
</div>
-->
<?php }
else
{?>
<div class="line">
<span class="left slabs">Slab is allocated but empty</span>
</div>
<?php } ?>
</div>
</td>
<?php
$actualSlab++;
}
?>
<?php
}
for(true; $actualSlab < 4 ; $actualSlab++)
{
echo '<td style="width:100%;"></td>';
}
?>
</tr>
</table>

View file

@ -1,356 +0,0 @@
<div class="size-4" style="float:left;">
<div class="sub-header corner padding">Get <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Hits</span>
<?php echo Library_Analysis::hitResize($stats['get_hits']); ?>
<span class="right">[<?php echo $stats['get_hits_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Miss</span>
<?php echo Library_Analysis::hitResize($stats['get_misses']); ?>
<span class="right">[<?php echo $stats['get_misses_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo $stats['get_rate']; ?> Request/sec
</div>
</div>
<div class="sub-header corner padding">Set <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Total</span>
<?php echo Library_Analysis::hitResize($stats['cmd_set']); ?>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo $stats['set_rate']; ?> Request/sec
</div>
</div>
<div class="sub-header corner padding">Delete <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Hits</span>
<?php echo (isset($stats['delete_hits'])) ? Library_Analysis::hitResize($stats['delete_hits']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['delete_hits_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Miss</span>
<?php echo (isset($stats['delete_misses'])) ? Library_Analysis::hitResize($stats['delete_misses']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['delete_misses_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo (isset($stats['delete_hits'])) ? $stats['delete_rate'] . ' Request/sec' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<div class="sub-header corner padding">Cas <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Hits</span>
<?php echo (isset($stats['cas_hits'])) ? Library_Analysis::hitResize($stats['cas_hits']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['cas_hits_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Miss</span>
<?php echo (isset($stats['cas_misses'])) ? Library_Analysis::hitResize($stats['cas_misses']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['cas_misses_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Bad Value</span>
<?php echo (isset($stats['cas_badval'])) ? Library_Analysis::hitResize($stats['cas_badval']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['cas_badval_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo (isset($stats['cas_hits'])) ? $stats['cas_rate'] . ' Request/sec' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<div class="sub-header corner padding">Increment <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Hits</span>
<?php echo (isset($stats['incr_hits'])) ? Library_Analysis::hitResize($stats['incr_hits']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['incr_hits_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Miss</span>
<?php echo (isset($stats['incr_misses'])) ? Library_Analysis::hitResize($stats['incr_misses']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['incr_misses_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo (isset($stats['incr_hits'])) ? $stats['incr_rate'] . ' Request/sec' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<div class="sub-header corner padding">Decrement <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Hits</span>
<?php echo (isset($stats['decr_hits'])) ? Library_Analysis::hitResize($stats['decr_hits']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['decr_hits_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Miss</span>
<?php echo (isset($stats['decr_misses'])) ? Library_Analysis::hitResize($stats['decr_misses']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['decr_misses_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo (isset($stats['decr_hits'])) ? $stats['decr_rate'] . ' Request/sec' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<div class="sub-header corner padding">Flush <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Total</span>
<?php echo (isset($stats['cmd_flush'])) ? Library_Analysis::hitResize($stats['cmd_flush']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo (isset($stats['cmd_flush'])) ? $stats['flush_rate'] . ' Request/sec' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
</div>
<div class="size-2" style="float:left;padding-left:9px;">
<?php
# Viewing a single server
if((isset($_GET['server'])) && ($_ini->server($_GET['server'])))
{ ?>
<div class="header corner padding size-3cols" style="text-align:center;margin-top:10px;">
<a href="?server=<?php echo $_GET['server']; ?>&amp;show=slabs">See this Server Slabs Stats</a>
</div>
<?php
} ?>
<div class="sub-header corner padding"><?php echo (isset($_GET['server'])) && ($_ini->server($_GET['server'])) ? 'Server' : 'Cluster'; ?> <span class="green">Stats</span></div>
<div class="container corner padding size-3cols">
<?php
# Viewing a single server
if((isset($_GET['server'])) && ($_ini->server($_GET['server'])))
{ ?>
<div class="line">
<span class="left setting">Uptime</span>
<?php echo Library_Analysis::uptime($stats['uptime']); ?>
</div>
<div class="line" style="margin-bottom:4px;">
<span class="left setting">Memcached</span>
Version <?php echo $stats['version']; ?>
</div>
<?php
} ?>
<div class="line">
<span class="left setting">Curr Connections</span>
<?php echo $stats['curr_connections']; ?>
</div>
<div class="line">
<span class="left setting">Total Connections</span>
<?php echo Library_Analysis::hitResize($stats['total_connections']); ?>
</div>
<div class="line">
<span class="left setting">Max Connections Errors</span>
<?php echo (isset($stats['listen_disabled_num'])) ? Library_Analysis::hitResize($stats['listen_disabled_num']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line" style="margin-top:4px;">
<span class="left setting">Current Items</span>
<?php echo Library_Analysis::hitResize($stats['curr_items']); ?>
</div>
<div class="line">
<span class="left setting">Total Items</span>
<?php echo Library_Analysis::hitResize($stats['total_items']); ?>
</div>
<?php
# Viewing a single server
if((isset($_GET['server'])) && ($_ini->server($_GET['server'])))
{ ?>
<div class="line">
<span class="left setting">Oldest Item</span>
<?php echo (isset($settings['oldest'])) ? Library_Analysis::uptime($settings['oldest']) : 'N/A on ' . $stats['version']; ?>
</div>
<?php
} ?>
</div>
<div class="sub-header corner padding">Eviction &amp; Reclaimed <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left setting">Items Eviction</span>
<?php echo Library_Analysis::hitResize($stats['evictions']); ?>
</div>
<div class="line">
<span class="left setting">Rate</span>
<?php echo $stats['eviction_rate']; ?> Eviction/sec
</div>
<div class="line" style="margin-top:4px;">
<span class="left setting">Reclaimed</span>
<?php echo (isset($stats['reclaimed'])) ? Library_Analysis::hitResize($stats['reclaimed']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting">Rate</span>
<?php echo (isset($stats['reclaimed'])) ? $stats['reclaimed_rate'] . ' Reclaimed/sec' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<?php
# Viewing a server
if((isset($_GET['server'])) && ($_ini->server($_GET['server'])))
{ ?>
<div class="sub-header corner padding">Server <span class="green">Configuration</span></div>
<div class="container corner padding">
<div class="line">
<span class="left setting" title="Internal name : accepting_conns&#013;Whether the server is accepting connection or not">Accepting Connections</span>
<?php
# Northscale/Membase server specific
if(isset($stats['accepting_conns']))
{
if($stats['accepting_conns']) { echo 'Yes'; } else { echo 'No'; }
}
else
{
echo 'N/A on ' . $stats['version'];
}?>
</div>
<div class="line">
<span class="left setting" title="Internal name : maxbytes&#013;Maximum number of bytes allowed in this cache">Max Bytes</span>
<?php echo (isset($settings['maxbytes'])) ? Library_Analysis::byteResize($settings['maxbytes']) . 'Bytes' : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : maxconns&#013;Maximum number of clients allowed">Max Connection</span>
<?php echo (isset($settings['maxconns'])) ? $settings['maxconns'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : tcpport &amp; udpport&#013;TCP &amp; UDP listen port">TCP/UDP Port</span>
<?php echo (isset($settings['tcpport'], $settings['udpport'])) ? 'TCP : ' . $settings['tcpport'] . ', UDP : ' . $settings['udpport'] : 'N/A on ' . $stats['version'] ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : inter&#013;Listen interface">Listen Interface</span>
<?php echo (isset($settings['inter'])) ? $settings['inter'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : evictions&#013;When Off, LRU evictions are disabled">Evictions</span>
<?php echo (isset($settings['evictions'])) ? ucfirst($settings['evictions']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : domain_socket&#013;Path to the domain socket (if any)">Path to Domain Socket</span>
<?php echo (isset($settings['domain_socket'])) ? $settings['domain_socket'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : umask&#013;Umask for the creation of the domain socket">Domain Socket Umask</span>
<?php echo (isset($settings['umask'])) ? $settings['umask'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : chunk_size&#013;Minimum space allocated for key + value + flags">Chunk Size</span>
<?php echo (isset($settings['chunk_size'])) ? $settings['chunk_size'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : growth_factor&#013;Chunk size growth factor">Chunk Growth Factor</span>
<?php echo (isset($settings['growth_factor'])) ? $settings['growth_factor'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : num_threads&#013;Number of threads (including dispatch)">Max Threads</span>
<?php echo (isset($settings['num_threads'])) ? $settings['num_threads'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : detail_enabled&#013;If yes, stats detail is enabled">Detail Enabled</span>
<?php echo (isset($settings['detail_enabled'])) ? ucfirst($settings['detail_enabled']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : reqs_per_event&#013;Max num IO ops processed within an event">Max IO Ops/Event</span>
<?php echo (isset($settings['reqs_per_event'])) ? $settings['reqs_per_event'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : cas_enabled&#013;When no, CAS is not enabled for this server">CAS Enabled</span>
<?php echo (isset($settings['cas_enabled'])) ? ucfirst($settings['cas_enabled']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : tcp_backlog&#013;TCP listen backlog">TCP Listen Backlog</span>
<?php echo (isset($settings['tcp_backlog'])) ? $settings['tcp_backlog'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting" title="Internal name : auth_enabled_sasl&#013;SASL auth requested and enabled">SASL Auth</span>
<?php echo (isset($settings['auth_enabled_sasl'])) ? ucfirst($settings['auth_enabled_sasl']) : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<?php
}
# Viewing a cluster
elseif((isset($_GET['server'])) && ($cluster = $_ini->cluster($_GET['server'])))
{ ?>
<div class="sub-header corner padding">Cluster <?php echo $_GET['server']; ?> <span class="green">Servers List</span></div>
<div class="container corner padding">
<?php
foreach($cluster as $server)
{ ?>
<div class="line">
<span class="left setting"><?php echo $server['hostname'] . ':' . $server['port']; ?></span>
<span class="right" style="font-weight:bold;"><a href="index.php?server=<?php echo $server['hostname'] . ':' . $server['port']; ?>" class="green">See Server Stats</a></span>
<div class="line" style="margin-left:5px;">
<?php echo ($status[$server['hostname'] . ':' . $server['port']] != '') ? 'Version ' . $status[$server['hostname'] . ':' . $server['port']] . ', Uptime : ' . Library_Analysis::uptime($uptime[$server['hostname'] . ':' . $server['port']]) : 'Server did not respond'; ?>
</div>
</div>
<?php
} ?>
</div>
<?php
} ?>
</div>
<?php
# Making cache size stats
$wasted_percent = sprintf('%.0u', $slabs['total_wasted'] / $stats['limit_maxbytes'] * 100);
$used_percent = sprintf('%.0u', ($slabs['total_malloced'] - $slabs['total_wasted']) / $stats['limit_maxbytes'] * 100);
$free_percent = sprintf('%.0u', ($stats['limit_maxbytes'] - $slabs['total_malloced']) / $stats['limit_maxbytes'] * 100);
?>
<div class="size-4" style="float:left; padding-left:9px;clear:right;">
<div class="sub-header corner padding">Cache Size <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Used</span>
<?php echo Library_Analysis::byteResize($slabs['total_malloced']); ?>Bytes
</div>
<div class="line">
<span class="left">Total</span>
<?php echo Library_Analysis::byteResize($stats['limit_maxbytes']); ?>Bytes
</div>
<div class="line">
<span class="left">Wasted</span>
<?php echo Library_Analysis::byteResize($slabs['total_wasted']); ?>Bytes
</div>
<!--
<div class="line">
<span class="left">Percent</span>
<?php echo sprintf('%.1f', $stats['bytes'] / $stats['limit_maxbytes'] * 100, 1); ?>%
</div>-->
</div>
<div class="sub-header corner padding">Cache Size <span class="green">Graphic</span></div>
<div class="container corner padding">
<div class="line">
<img src="http://chart.apis.google.com/chart?chf=bg,s,ebebeb&amp;chs=280x225&amp;cht=p&amp;chco=b5463f|2a707b|ffffff&amp;chd=t:<?php echo $wasted_percent; ?>,<?php echo $used_percent; ?>,<?php echo $free_percent; ?>&amp;chdl=Wasted%20:%20<?php echo $wasted_percent; ?>%|Used%20:%20<?php echo $used_percent; ?>%|Free%20:%20<?php echo $free_percent; ?>%&amp;chdlp=b" alt="Cache Size by GoogleCharts" width="280" height="225"/>
</div>
</div>
<div class="sub-header corner padding">Hit &amp; Miss Rate <span class="green">Graphic</span></div>
<div class="container corner padding">
<div class="line">
<img src="http://chart.apis.google.com/chart?cht=bvg&amp;chd=t:<?php echo $stats['get_hits_percent']; ?>,<?php echo $stats['get_misses_percent']; ?>&amp;chs=280x235&amp;chl=Hit|Miss&amp;chf=bg,s,ebebeb&amp;chco=2a707b|b5463f&amp;chxt=y&amp;chbh=a&amp;chm=N,000000,0,-1,11" alt="Cache Hit &amp; Miss Rate by GoogleChart" width="280" height="235"/>
</div>
</div>
<div class="sub-header corner padding">Network <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Bytes Read</span>
<?php echo Library_Analysis::byteResize($stats['bytes_read']); ?>Bytes
</div>
<div class="line">
<span class="left">Bytes Written</span>
<?php echo Library_Analysis::byteResize($stats['bytes_written']); ?>Bytes
</div>
</div>
</div>

View file

@ -1,276 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Executing commands
*
* @author c.mahieux@of2m.fr
* @since 06/04/2010
*/
# Headers
header('Content-type: text/html;');
header('Cache-Control: no-cache, must-revalidate');
# Require
require_once 'Library/Loader.php';
# Date timezone
date_default_timezone_set('Europe/Paris');
# Loading ini file
$_ini = Library_Configuration_Loader::singleton();
# Initializing requests & response
$request = (isset($_GET['request_command'])) ? $_GET['request_command'] : null;
# Starting
ob_start();
# Display by request rype
switch($request)
{
# Memcache::get command
case 'get':
# Ask for get on a cluster
if(isset($_GET['request_server']) && ($cluster = $_ini->cluster($_GET['request_server'])))
{
foreach($cluster as $server)
{
# Dumping server get command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api($_GET['request_api'])->get($server['hostname'], $server['port'], $_GET['request_key']));
}
}
# Ask for get on one server
elseif(isset($_GET['request_server']) && ($server = $_ini->server($_GET['request_server'])))
{
# Dumping server get command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api($_GET['request_api'])->get($server['hostname'], $server['port'], $_GET['request_key']));
}
# Ask for get on all servers
else
{
foreach($_ini->get('servers') as $cluster => $servers)
{
# Asking for each server stats
foreach($servers as $server)
{
# Dumping server get command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api($_GET['request_api'])->get($server['hostname'], $server['port'], $_GET['request_key']));
}
}
}
break;
# Memcache::set command
case 'set':
# Ask for set on a cluster
if(isset($_GET['request_server']) && ($cluster = $_ini->cluster($_GET['request_server'])))
{
foreach($cluster as $server)
{
# Dumping server get command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api($_GET['request_api'])->set($server['hostname'], $server['port'], $_GET['request_key'], $_GET['request_data'], $_GET['request_duration']));
}
}
# Ask for set on one server
elseif(isset($_GET['request_server']) && ($server = $_ini->server($_GET['request_server'])))
{
# Dumping server set command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api($_GET['request_api'])->set($server['hostname'], $server['port'], $_GET['request_key'], $_GET['request_data'], $_GET['request_duration']));
}
# Ask for set on all servers
else
{
foreach($_ini->get('servers') as $cluster => $servers)
{
# Asking for each server stats
foreach($servers as $server)
{
# Dumping server set command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api($_GET['request_api'])->set($server['hostname'], $server['port'], $_GET['request_key'], $_GET['request_data'], $_GET['request_duration']));
}
}
}
break;
# Memcache::delete command
case 'delete':
# Ask for delete on a cluster
if(isset($_GET['request_server']) && ($cluster = $_ini->cluster($_GET['request_server'])))
{
foreach($cluster as $server)
{
# Dumping server get command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api($_GET['request_api'])->delete($server['hostname'], $server['port'], $_GET['request_key']));
}
}
# Ask for delete on one server
elseif(isset($_GET['request_server']) && ($server = $_ini->server($_GET['request_server'])))
{
# Dumping server delete command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api($_GET['request_api'])->delete($server['hostname'], $server['port'], $_GET['request_key']));
}
# Ask for delete on all servers
else
{
foreach($_ini->get('servers') as $cluster => $servers)
{
# Asking for each server stats
foreach($servers as $server)
{
# Dumping server delete command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api($_GET['request_api'])->delete($server['hostname'], $server['port'], $_GET['request_key']));
}
}
}
break;
# Memcache::flush_all command
case 'flush_all':
# Checking delay
if(!isset($_GET['request_delay']) || !is_numeric($_GET['request_delay']))
{
$_GET['request_delay'] = 0;
}
# Ask for flush_all on a cluster
if(isset($_GET['request_server']) && ($cluster = $_ini->cluster($_GET['request_server'])))
{
foreach($cluster as $server)
{
# Dumping server get command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api($_GET['request_api'])->flush_all($server['hostname'], $server['port'], $_GET['request_delay']));
}
}
# Ask for flush_all on one server
elseif(isset($_GET['request_server']) && ($server = $_ini->server($_GET['request_server'])))
{
# Dumping server flush_all command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api($_GET['request_api'])->flush_all($server['hostname'], $server['port'], $_GET['request_delay']));
}
# Ask for flush_all on all servers
else
{
foreach($_ini->get('servers') as $cluster => $servers)
{
# Asking for each server stats
foreach($servers as $server)
{
# Dumping server flush_all command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api($_GET['request_api'])->flush_all($server['hostname'], $server['port'], $_GET['request_delay']));
}
}
}
break;
# Memcache::search command
case 'search':
# Ask for flush_all on a cluster
if(isset($_GET['request_server']) && ($cluster = $_ini->cluster($_GET['request_server'])))
{
foreach($cluster as $server)
{
# Dumping server get command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api('Server')->search($server['hostname'], $server['port'], $_GET['request_key']));
}
}
# Ask for search on one server
elseif(isset($_GET['request_server']) && ($server = $_ini->server($_GET['request_server'])))
{
# Dumping server search command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api('Server')->search($server['hostname'], $server['port'], $_GET['request_key']));
}
# Ask for search on all servers
else
{
# Looking into each cluster
foreach($_ini->get('servers') as $cluster => $servers)
{
# Asking for each server stats
foreach($servers as $server)
{
# Dumping server search command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api('Server')->search($server['hostname'], $server['port'], $_GET['request_key']));
}
}
}
break;
# Memcache::telnet command
case 'telnet':
# Ask for a telnet command on a cluster
if(isset($_GET['request_server']) && ($cluster = $_ini->cluster($_GET['request_server'])))
{
foreach($cluster as $server)
{
# Dumping server telnet command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api('Server')->telnet($server['hostname'], $server['port'], $_GET['request_telnet']));
}
}
# Ask for a telnet command on one server
elseif(isset($_GET['request_server']) && ($server = $_ini->server($_GET['request_server'])))
{
# Dumping server telnet command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api('Server')->telnet($server['hostname'], $server['port'], $_GET['request_telnet']));
}
# Ask for a telnet command on all servers
else
{
# Looking into each cluster
foreach($_ini->get('servers') as $cluster => $servers)
{
# Asking for each server stats
foreach($servers as $server)
{
# Dumping server telnet command response
echo Library_HTML_Components::serverResponse($server['hostname'], $server['port'],
Library_Command_Factory::api('Server')->telnet($server['hostname'], $server['port'], $_GET['request_telnet']));
}
}
}
break;
# Default : No command
default :
# Showing header
include 'View/Header.tpl';
# Showing formulary
include 'View/Commands/Commands.tpl';
# Showing footer
include 'View/Footer.tpl';
break;
}
ob_end_flush();

View file

@ -1,127 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Configuration
*
* @author c.mahieux@of2m.fr
* @since 06/04/2010
*/
# Headers
header('Content-type: text/html;');
header('Cache-Control: no-cache, must-revalidate');
# Require
require_once 'Library/Loader.php';
# Date timezone
date_default_timezone_set('Europe/Paris');
# Loading ini file
$_ini = Library_Configuration_Loader::singleton();
# Initializing requests
$request = (isset($_GET['request_write'])) ? $_GET['request_write'] : null;
$write = null;
# Display by request rype
switch($request)
{
# Unlock configuration file & temp directory
case 'unlock':
# chmod 0755
chmod(Library_Configuration_Loader::path(), 0755);
chmod($_ini->get('file_path'), 0755);
break;
# Live stats configuration save
case 'live_stats':
# Updating configuration
$_ini->set('refresh_rate', round(max(2, $_POST['refresh_rate'])));
$_ini->set('memory_alert', $_POST['memory_alert']);
$_ini->set('hit_rate_alert', $_POST['hit_rate_alert']);
$_ini->set('eviction_alert', $_POST['eviction_alert']);
$_ini->set('file_path', $_POST['file_path']);
# Writing configuration file
$write = Library_Configuration_Loader::singleton()->write();
break;
# Commands configuration save
case 'commands':
# Updating configuration
$_ini->set('stats_api', $_POST['stats_api']);
$_ini->set('slabs_api', $_POST['slabs_api']);
$_ini->set('items_api', $_POST['items_api']);
$_ini->set('get_api', $_POST['get_api']);
$_ini->set('set_api', $_POST['set_api']);
$_ini->set('delete_api', $_POST['delete_api']);
$_ini->set('flush_all_api', $_POST['flush_all_api']);
# Writing configuration file
$write = Library_Configuration_Loader::singleton()->write();
break;
# Server configuration save
case 'servers':
$array = array();
foreach($_POST['server'] as $cluster => $servers)
{
foreach($servers as $data)
{
$array[$_POST['cluster'][$cluster]][$data['hostname'] . ':' . $data['port']] = $data;
}
}
# Sorting clusters
ksort($array);
foreach($array as $cluster => $servers)
{
# Sorting servers
ksort($servers);
$array[$cluster] = $servers;
}
# Updating configuration
$_ini->set('servers', $array);
# Writing configuration file
$write = Library_Configuration_Loader::singleton()->write();
break;
# Miscellaneous configuration save
case 'miscellaneous':
# Updating configuration
$_ini->set('connection_timeout', $_POST['connection_timeout']);
$_ini->set('max_item_dump', $_POST['max_item_dump']);
# Writing configuration file
$write = Library_Configuration_Loader::singleton()->write();
break;
# Default : No command
default :
break;
}
# Showing header
include 'View/Header.tpl';
# Showing formulary
include 'View/Configure/Configure.tpl';
# Showing footer
include 'View/Footer.tpl';

View file

@ -1,176 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Stats viewing
*
* @author c.mahieux@of2m.fr
* @since 20/03/2010
*/
# Headers
header('Content-type: text/html; charset=UTF-8');
header('Cache-Control: no-cache, must-revalidate');
# Require
require_once 'Library/Loader.php';
# Date timezone
date_default_timezone_set('Europe/Paris');
# Loading ini file
$_ini = Library_Configuration_Loader::singleton();
# Initializing requests
$request = (isset($_GET['show'])) ? $_GET['show'] : null;
# Getting default cluster
if(!isset($_GET['server']))
{
$clusters = array_keys($_ini->get('servers'));
$cluster = isset($clusters[0]) ? $clusters[0] : null;
$_GET['server'] = $cluster;
}
# Showing header
include 'View/Header.tpl';
# Display by request type
switch($request)
{
# Items : Display of all items for a single slab for a single server
case 'items':
# Initializing items array
$server = null;
$items = false;
$response = array();
# Ask for one server and one slabs items
if(isset($_GET['server']) && ($server = $_ini->server($_GET['server'])))
{
$items = Library_Command_Factory::instance('items_api')->items($server['hostname'], $server['port'], $_GET['slab']);
}
# Cheking if asking an item
if(isset($_GET['request_key']))
{
$response[$server['hostname'] . ':' . $server['port']] = Library_Command_Factory::instance('get_api')->get($server['hostname'], $server['port'], $_GET['request_key']);
}
# Getting stats to calculate server boot time
$stats = Library_Command_Factory::instance('stats_api')->stats($server['hostname'], $server['port']);
$infinite = (isset($stats['time'], $stats['uptime'])) ? ($stats['time'] - $stats['uptime']) : 0;
# Items are well formed
if($items !== false)
{
# Showing items
include 'View/Stats/Items.tpl';
}
# Items are not well formed
else
{
include 'View/Stats/Error.tpl';
}
unset($items);
break;
# Slabs : Display of all slabs for a single server
case 'slabs':
# Initializing slabs array
$slabs = false;
# Ask for one server slabs
if(isset($_GET['server']) && ($server = $_ini->server($_GET['server'])))
{
# Spliting server in hostname:port
$slabs = Library_Command_Factory::instance('slabs_api')->slabs($server['hostname'], $server['port']);
}
# Slabs are well formed
if($slabs !== false)
{
# Analysis
$slabs = Library_Analysis::slabs($slabs);
include 'View/Stats/Slabs.tpl';
}
# Slabs are not well formed
else
{
include 'View/Stats/Error.tpl';
}
unset($slabs);
break;
# Default : Stats for all or specific single server
default :
# Initializing stats & settings array
$stats = array();
$slabs = array();
$slabs['total_malloced'] = 0;
$slabs['total_wasted'] = 0;
$settings = array();
$status = array();
$cluster = null;
$server = null;
# Ask for a particular cluster stats
if(isset($_GET['server']) && ($cluster = $_ini->cluster($_GET['server'])))
{
foreach($cluster as $server)
{
# Getting Stats & Slabs stats
$data = array();
$data['stats'] = Library_Command_Factory::instance('stats_api')->stats($server['hostname'], $server['port']);
$data['slabs'] = Library_Analysis::slabs(Library_Command_Factory::instance('slabs_api')->slabs($server['hostname'], $server['port']));
$stats = Library_Analysis::merge($stats, $data['stats']);
# Computing stats
if(isset($data['slabs']['total_malloced'], $data['slabs']['total_wasted']))
{
$slabs['total_malloced'] += $data['slabs']['total_malloced'];
$slabs['total_wasted'] += $data['slabs']['total_wasted'];
}
$status[$server['hostname'] . ':' . $server['port']] = ($data['stats'] != array()) ? $data['stats']['version'] : '';
$uptime[$server['hostname'] . ':' . $server['port']] = ($data['stats'] != array()) ? $data['stats']['uptime'] : '';
}
}
# Asking for a server stats
elseif(isset($_GET['server']) && ($server = $_ini->server($_GET['server'])))
{
# Getting Stats & Slabs stats
$stats = Library_Command_Factory::instance('stats_api')->stats($server['hostname'], $server['port']);
$slabs = Library_Analysis::slabs(Library_Command_Factory::instance('slabs_api')->slabs($server['hostname'], $server['port']));
$settings = Library_Command_Factory::instance('stats_api')->settings($server['hostname'], $server['port']);
}
# Stats are well formed
if(($stats !== false) && ($stats != array()))
{
# Analysis
$stats = Library_Analysis::stats($stats);
include 'View/Stats/Stats.tpl';
}
# Stats are not well formed
else
{
include 'View/Stats/Error.tpl';
}
unset($stats);
break;
}
# Showing footer
include 'View/Footer.tpl';

View file

@ -1,171 +0,0 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Live Stats top style
*
* @author Cyrille Mahieux : elijaa(at)free.fr
* @since 12/04/2010
*/
# Headers
header('Content-type: text/html;');
header('Cache-Control: no-cache, must-revalidate');
# Require
require_once 'Library/Loader.php';
# Date timezone
date_default_timezone_set('Europe/Paris');
# Loading ini file
$_ini = Library_Configuration_Loader::singleton();
# Initializing requests
$request = (isset($_GET['request_command'])) ? $_GET['request_command'] : null;
# Stat of a particular cluster
if(isset($_GET['cluster']) && ($_GET['cluster'] != null))
{
$cluster = $_GET['cluster'];
}
# Getting default cluster
else
{
$clusters = array_keys($_ini->get('servers'));
$cluster = isset($clusters[0]) ? $clusters[0] : null;
$_GET['cluster'] = $cluster;
}
# Hashing cluster
$hash = md5($_GET['cluster']);
# Cookie @FIXME not a perfect method
if(!isset($_COOKIE['live_stats_id' . $hash]))
{
# Cleaning temporary directory
$files = glob($_ini->get('file_path') . '*', GLOB_NOSORT );
foreach($files as $path)
{
$stats = @stat($path);
if(isset($stats[9]) && ($stats[9] < (time() - 60*60*24)))
{
@unlink($path);
}
}
# Generating unique id
$live_stats_id = rand() . $hash;
# Cookie
setcookie('live_stats_id' . $hash, $live_stats_id, time() + 60*60*24);
}
else
{
# Backup from a previous request
$live_stats_id = $_COOKIE['live_stats_id' . $hash];
}
# Live stats dump file
$file_path = rtrim($_ini->get('file_path'), '/') . DIRECTORY_SEPARATOR . 'live_stats.' . $live_stats_id;
# Display by request type
switch($request)
{
# Ajax ask : stats
case 'live_stats':
# Opening old stats dump
$previous = @unserialize(file_get_contents($file_path));
# Initializing variables
$actual = array();
$stats = array();
$time = 0;
# Requesting stats for each server
foreach($_ini->cluster($cluster) as $server)
{
# Start query time calculation
$time = microtime(true);
# Asking server for stats
$actual[$server['hostname'] . ':' . $server['port']] = Library_Command_Factory::instance('stats_api')->stats($server['hostname'], $server['port']);
# Calculating query time length
$actual[$server['hostname'] . ':' . $server['port']]['query_time'] = max((microtime(true) - $time) * 1000, 1);
}
# Analysing stats
foreach($_ini->cluster($cluster) as $server)
{
# Making an alias
$server = $server['hostname'] . ':' . $server['port'];
# Diff between old and new dump
$stats[$server] = Library_Analysis::diff($previous[$server], $actual[$server]);
}
# Making stats for each server
foreach($stats as $server => $array)
{
# Analysing request
if((isset($stats[$server]['uptime'])) && ($stats[$server]['uptime'] > 0))
{
# Computing stats
$stats[$server] = Library_Analysis::stats($stats[$server]);
# Because we make a diff on every key, we must reasign some values
$stats[$server]['bytes_percent'] = sprintf('%.1f', $actual[$server]['bytes'] / $actual[$server]['limit_maxbytes'] * 100);
$stats[$server]['bytes'] = $actual[$server]['bytes'];
$stats[$server]['limit_maxbytes'] = $actual[$server]['limit_maxbytes'];
$stats[$server]['curr_connections'] = $actual[$server]['curr_connections'];
$stats[$server]['query_time'] = $actual[$server]['query_time'];
}
}
# Saving new stats dump
file_put_contents($file_path, serialize($actual));
# Showing stats
include 'View/LiveStats/Stats.tpl';
break;
# Default : No command
default :
# Initializing : making stats dump
$stats = array();
foreach($_ini->cluster($cluster) as $server)
{
$stats[$server['hostname'] . ':' . $server['port']] = Library_Command_Factory::instance('stats_api')->stats($server['hostname'], $server['port']);
}
# Saving first stats dump
file_put_contents($file_path, serialize($stats));
# Searching for connection error, adding some time to refresh rate to prevent error
$refresh_rate = max($_ini->get('refresh_rate'), count($_ini->cluster($cluster)) * 0.25 + (Library_Data_Error::count() * (0.5 + $_ini->get('connection_timeout'))));
# Showing header
include 'View/Header.tpl';
# Showing live stats frame
include 'View/LiveStats/Frame.tpl';
# Showing footer
include 'View/Footer.tpl';
break;
}

View file

@ -1,39 +0,0 @@
phpRedisAdmin
=============
phpRedisAdmin is a simple web interface to manage [Redis](http://redis.io/) databases. It is released under the [Creative Commons Attribution 3.0 license](http://creativecommons.org/licenses/by/3.0/). This code is being developed and maintained by [Erik Dubbelboer](https://github.com/ErikDubbelboer/).
You can send comments, patches, questions [here on github](https://github.com/ErikDubbelboer/phpRedisAdmin/issues) or to erik@dubbelboer.com.
Example
=======
You can find an example database at [http://dubbelboer.com/phpRedisAdmin/](http://dubbelboer.com/phpRedisAdmin/?view&key=example:hash)
Installing/Configuring
======================
You will need [phpredis](https://github.com/nicolasff/phpredis). See phpredis for install instructions.
You will need to edit config.inc.php with your redis information. You might also want to uncomment and change the login information in config.inc.php.
TODO
====
* Javascript sorting of tables
* Better error handling
* Move or Copy key to different server
* Importing JSON
* JSON export with seperate objects based on your seperator
Credits
=======
Icons by [http://p.yusukekamiyamane.com/](http://p.yusukekamiyamane.com/) ([https://github.com/yusukekamiyamane/fugue-icons/tree/master/icons-shadowless](https://github.com/yusukekamiyamane/fugue-icons/tree/master/icons-shadowless))
Favicon from [https://github.com/antirez/redis-io/blob/master/public/images/favicon.png](https://github.com/antirez/redis-io/blob/master/public/images/favicon.png)

View file

@ -1,115 +0,0 @@
<?php
if (!class_exists('Redis')) {
die('ERROR: phpredis is required. You can find phpredis at <a href="https://github.com/nicolasff/phpredis">https://github.com/nicolasff/phpredis</a>');
}
// Undo magic quotes (both in keys and values)
if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
$process = array(&$_GET, &$_POST);
while (list($key, $val) = each($process)) {
foreach ($val as $k => $v) {
unset($process[$key][$k]);
if (is_array($v)) {
$process[$key][stripslashes($k)] = $v;
$process[] = &$process[$key][stripslashes($k)];
} else {
$process[$key][stripslashes($k)] = stripslashes($v);
}
}
}
unset($process);
}
// These includes are needed by each script.
require_once 'config.inc.php';
require_once 'functions.inc.php';
require_once 'page.inc.php';
if (isset($config['login'])) {
require_once 'login.inc.php';
}
// phpredis types to string conversion array.
$redistypes = array(
Redis::REDIS_STRING => 'string',
Redis::REDIS_SET => 'set',
Redis::REDIS_LIST => 'list',
Redis::REDIS_ZSET => 'zset',
Redis::REDIS_HASH => 'hash',
);
if (isset($login['servers'])) {
$i = current($login['servers']);
} else {
$i = 0;
}
if (isset($_GET['s']) && is_numeric($_GET['s']) && ($_GET['s'] < count($config['servers']))) {
$i = $_GET['s'];
}
$server = $config['servers'][$i];
$server['id'] = $i;
if (isset($login, $login['servers'])) {
if (array_search($i, $login['servers']) === false) {
die('You are not allowed to access this database.');
}
foreach ($config['servers'] as $key => $ignore) {
if (array_search($key, $login['servers']) === false) {
unset($config['servers'][$key]);
}
}
}
if (!isset($server['db'])) {
$server['db'] = 0;
}
// Setup a connection to Redis.
$redis = new Redis();
try {
$redis->connect($server['host'], $server['port']);
} catch (Exception $e) {
die('ERROR: Could not connect to Redis ('.$server['host'].':'.$server['port'].')');
}
if (isset($server['auth'])) {
if (!$redis->auth($server['auth'])) {
die('ERROR: Authentication failed ('.$server['host'].':'.$server['port'].')');
}
}
if ($server['db'] != 0) {
if (!$redis->select($server['db'])) {
die('ERROR: Selecting database failed ('.$server['host'].':'.$server['port'].','.$server['db'].')');
}
}
?>

View file

@ -1,56 +0,0 @@
<?php
$config = array(
'servers' => array(
0 => array(
'name' => 'local server', // Optional name.
'host' => '127.0.0.1',
'port' => 6379,
// Optional Redis authentication.
//'auth' => 'redispasswordhere' // Warning: The password is sent in plain-text to the Redis server.
),
/*1 => array(
'host' => 'localhost',
'port' => 6380
),*/
/*2 => array(
'name' => 'local db 2',
'host' => 'localhost',
'port' => 6379,
'db' => 1 // Optional database number, see http://redis.io/commands/select
)*/
),
'seperator' => ':',
// Uncomment to show less information and make phpRedisAdmin fire less commands to the Redis server. Recommended for a really busy Redis server.
//'faster' => true,
// Uncomment to enable HTTP authentication
/*'login' => array(
// Username => Password
// Multiple combinations can be used
'admin' => array(
'password' => 'adminpassword',
),
'guest' => array(
'password' => '',
'servers' => array(1) // Optional list of servers this user can access.
)
),*/
// You can ignore settings below this point.
'maxkeylen' => 100
);
?>

View file

@ -1,53 +0,0 @@
html {
font-size: x-small; /* Wikipedia font-size scaling method */
}
body {
font: 116%/1.4em Verdana, sans-serif;
color: #000;
margin: 0;
padding: 0;
border: 0;
height: 100%;
max-height: 100%;
background-color: #fff;
}
h1 {
font: bold 190% "Helvetica Neue", Helvetica, Arial, sans-serif;
}
h2 {
font: bold 160% "Helvetica Neue", Helvetica, Arial, sans-serif;
}
h3 {
font: bold 130% "Helvetica Neue", Helvetica, Arial, sans-serif;
}
abbr {
border-bottom: 1px dotted #666;
}
img {
border: 0;
}
.clear {
clear: left;
}
.info {
color: #aaa;
font-weight: normal;
}
.add {
padding: 3px 0 1px 20px;
background: url(../images/add.png) left center no-repeat;
}

View file

@ -1,56 +0,0 @@
form {
margin: 0;
}
form p {
padding-left: 8em;
margin: 1em 0;
}
form label {
float: left;
width: 7em;
margin-left: -8em;
}
form .button {
margin-left: -7em;
}
#hkeyp, #indexp, #scorep {
display: none;
}
table {
border-spacing: 0;
border-collapse: collapse;
}
td {
background-color: #eee;
border: 2px solid #fff;
}
.alt td {
background-color: #ccc;
}
td div, th div {
padding: .5em;
}
.imgbut {
vertical-align: middle;
margin-top: -4px;
}
.server {
float: left;
margin: 1em;
}

View file

@ -1,122 +0,0 @@
#sidebar {
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 24em;
height: 100%;
padding-left: 1em;
border-right: 1px solid #000;
overflow: hidden;
}
#sidebar a, #sidebar a:visited {
color: #000;
}
#sidebar a {
text-decoration: none;
}
#sidebar a:hover {
text-decoration: underline;
}
#keys {
position: fixed;
top: 15.5em;
bottom: 0;
width: 24em;
padding-bottom: 1em;
overflow: auto;
}
#keys ul {
list-style-type: none;
margin: 0;
padding: 0;
}
#keys li {
font-weight: normal;
}
#keys li.folder {
font-weight: bold;
margin-top: .05em;
}
#keys li.current a {
background-color: #eee;
}
#keys li.hidden {
display: none;
}
#keys .icon {
padding: 1px 0 1px 20px;
background: url(../images/folder-open.png) left center no-repeat;
white-space: nowrap;
}
#keys li.collapsed ul {
display: none;
}
#keys ul ul {
margin-left: 6px;
background: url(../images/tree-vline.gif) repeat-y;
}
#keys ul ul li {
padding-left: 16px;
background: url(../images/tree-node.gif) no-repeat;
}
#keys ul ul li.folder {
background-image: url(../images/tree-folder-expanded.gif);
}
#keys ul ul li.folder.collapsed {
background-image: url(../images/tree-folder-collapsed.gif);
}
#keys ul ul li.last { /* Hard-coded substitute for :last-child */
margin-bottom: .3em;
background: #fff url(../images/tree-lastnode.gif) no-repeat;
}
#keys ul ul li.last.folder {
background-image: url(../images/tree-lastnode-expanded.gif);
}
#keys ul ul li.last.folder.collapsed {
background-image: url(../images/tree-lastnode-collapsed.gif);
}
#keys .deltree {
display: none;
}
#keys .icon:hover .deltree {
display: inline;
}
#frame {
position: fixed;
top: 0;
left: 25em;
right: 0;
bottom: 0;
padding-left: 1em;
}
#frame iframe {
width: 100%;
height: 100%;
}

View file

@ -1,63 +0,0 @@
<?php
if (!isset($_POST['post'])) {
die('Javascript needs to be enabled for you to delete keys.');
}
require_once 'common.inc.php';
if (isset($_GET['key'])) {
// String
if (!isset($_GET['type']) || ($_GET['type'] == 'string')) {
// Delete the whole key.
$redis->delete($_GET['key']);
}
// Hash
else if (($_GET['type'] == 'hash') && isset($_GET['hkey'])) {
// Delete only the field in the hash.
$redis->hDel($_GET['key'], $_GET['hkey']);
}
// List
else if (($_GET['type'] == 'list') && isset($_GET['index'])) {
// Lists don't have simple delete operations.
// You can only remove something based on a value so we set the value at the index to some random value we hope doesn't occur elsewhere in the list.
$value = str_rand(69);
// This code assumes $value is not present in the list. To make sure of this we would need to check the whole list and place a Watch on it to make sure the list isn't modified in between.
$redis->lSet($_GET['key'], $_GET['index'], $value);
$redis->lRem($_GET['key'], $value, 1);
}
// Set
else if (($_GET['type'] == 'set') && isset($_GET['value'])) {
// Removing members from a set can only be done by supplying the member.
$redis->sRem($_GET['key'], $_GET['value']);
}
// ZSet
else if (($_GET['type'] == 'zset') && isset($_GET['value'])) {
// Removing members from a zset can only be done by supplying the value.
$redis->zDelete($_GET['key'], $_GET['value']);
}
die('?view&s='.$server['id'].'&key='.urlencode($_GET['key']));
}
if (isset($_GET['tree'])) {
$keys = $redis->keys($_GET['tree'].'*');
foreach ($keys as $key) {
$redis->delete($key);
}
die;
}
?>

View file

@ -1,186 +0,0 @@
<?php
require_once 'common.inc.php';
// Are we editing or creating a new key?
$edit = false;
if (isset($_GET['key'], $_GET['type'])) {
if (($_GET['type'] == 'string') ||
(($_GET['type'] == 'hash') && isset($_GET['hkey'])) ||
(($_GET['type'] == 'list') && isset($_GET['index'])) ||
(($_GET['type'] == 'set' ) && isset($_GET['value'])) ||
(($_GET['type'] == 'zset') && isset($_GET['value']))) {
$edit = true;
}
}
if (isset($_POST['type'], $_POST['key'], $_POST['value'])) {
// Don't allow keys that are to long (Redis supports keys that can be way to long to put in an url).
if (strlen($_POST['key']) > $config['maxkeylen']) {
die('ERROR: Your key is to long (max length is '.$config['maxkeylen'].')');
}
// String
if ($_POST['type'] == 'string') {
$redis->set($_POST['key'], $_POST['value']);
}
// Hash
else if (($_POST['type'] == 'hash') && isset($_POST['hkey'])) {
if (strlen($_POST['hkey']) > $config['maxkeylen']) {
die('ERROR: Your hash key is to long (max length is '.$config['maxkeylen'].')');
}
if ($edit && !$redis->hExists($_POST['key'], $_POST['hkey'])) {
$redis->hDel($_POST['key'], $_GET['hkey']);
}
$redis->hSet($_POST['key'], $_POST['hkey'], $_POST['value']);
}
// List
else if (($_POST['type'] == 'list') && isset($_POST['index'])) {
$size = $redis->lSize($_POST['key']);
if (($_POST['index'] == '') ||
($_POST['index'] == $size) ||
($_POST['index'] == -1)) {
// Push it at the end
$redis->rPush($_POST['key'], $_POST['value']);
} else if (($_POST['index'] >= 0) &&
($_POST['index'] < $size)) {
// Overwrite an index
$redis->lSet($_POST['key'], $_POST['index'], $_POST['value']);
} else {
die('ERROR: Out of bounds index');
}
}
// Set
else if ($_POST['type'] == 'set') {
if ($_POST['value'] != $_POST['oldvalue']) {
// The only way to edit a Set value is to add it and remove the old value.
$redis->sRem($_POST['key'], $_POST['oldvalue']);
$redis->sAdd($_POST['key'], $_POST['value']);
}
}
// ZSet
else if (($_POST['type'] == 'zset') && isset($_POST['score'])) {
if ($_POST['value'] != $_POST['oldvalue']) {
// The only way to edit a ZSet value is to add it and remove the old value.
$redis->zDelete($_POST['key'], $_POST['oldvalue']);
$redis->zAdd($_POST['key'], $_POST['score'], $_POST['value']);
}
}
// Refresh the top so the key tree is updated.
require 'header.inc.php';
?>
<script>
top.location.href = top.location.pathname+'?view&s=<?php echo $server['id']?>&key=<?php echo urlencode($_POST['key'])?>';
</script>
<?php
require 'footer.inc.php';
die;
}
// Get the current value.
$value = '';
if ($edit) {
// String
if ($_GET['type'] == 'string') {
$value = $redis->get($_GET['key']);
}
// Hash
else if (($_GET['type'] == 'hash') && isset($_GET['hkey'])) {
$value = $redis->hGet($_GET['key'], $_GET['hkey']);
}
// List
else if (($_GET['type'] == 'list') && isset($_GET['index'])) {
$value = $redis->lGet($_GET['key'], $_GET['index']);
}
// Set, ZSet
else if ((($_GET['type'] == 'set') || ($_GET['type'] == 'zset')) && isset($_GET['value'])) {
$value = $_GET['value'];
}
}
$page['css'][] = 'frame';
$page['js'][] = 'frame';
require 'header.inc.php';
?>
<h2><?php echo $edit ? 'Edit' : 'Add'?></h2>
<form action="<?php echo format_html($_SERVER['REQUEST_URI'])?>" method="post">
<p>
<label for="type">Type:</label>
<select name="type" id="type">
<option value="string" <?php echo (isset($_GET['type']) && ($_GET['type'] == 'string')) ? 'selected="selected"' : ''?>>String</option>
<option value="hash" <?php echo (isset($_GET['type']) && ($_GET['type'] == 'hash' )) ? 'selected="selected"' : ''?>>Hash</option>
<option value="list" <?php echo (isset($_GET['type']) && ($_GET['type'] == 'list' )) ? 'selected="selected"' : ''?>>List</option>
<option value="set" <?php echo (isset($_GET['type']) && ($_GET['type'] == 'set' )) ? 'selected="selected"' : ''?>>Set</option>
<option value="zset" <?php echo (isset($_GET['type']) && ($_GET['type'] == 'zset' )) ? 'selected="selected"' : ''?>>ZSet</option>
</select>
</p>
<p>
<label for="key">Key:</label>
<input type="text" name="key" id="key" size="30" maxlength="30" <?php echo isset($_GET['key']) ? 'value="'.format_html($_GET['key']).'"' : ''?>>
</p>
<p id="hkeyp">
<label for="khey">Hash key:</label>
<input type="text" name="hkey" id="hkey" size="30" maxlength="30" <?php echo isset($_GET['hkey']) ? 'value="'.format_html($_GET['hkey']).'"' : ''?>>
</p>
<p id="indexp">
<label for="index">Index:</label>
<input type="text" name="index" id="index" size="30" <?php echo isset($_GET['index']) ? 'value="'.format_html($_GET['index']).'"' : ''?>> <span class="info">empty to append, -1 to prepend</span>
</p>
<p id="scorep">
<label for="score">Score:</label>
<input type="text" name="score" id="score" size="30" <?php echo isset($_GET['score']) ? 'value="'.format_html($_GET['score']).'"' : ''?>>
</p>
<p>
<label for="value">Value:</label>
<textarea name="value" id="value" cols="80" rows="20"><?php echo nl2br(format_html($value))?></textarea>
</p>
<input type="hidden" name="oldvalue" value="<?php echo format_html($value)?>">
<p>
<input type="submit" class="button" value="<?php echo $edit ? 'Edit' : 'Add'?>">
</p>
</form>
<?php
require 'footer.inc.php';
?>

View file

@ -1,197 +0,0 @@
<?php
require_once 'common.inc.php';
// Export to redis-cli commands
function export_redis($key) {
global $redistypes, $redis;
$type = $redis->type($key);
if (!isset($redistypes[$type])) {
return;
}
$type = $redistypes[$type];
// String
if ($type == 'string') {
echo 'SET "',addslashes($key),'" "',addslashes($redis->get($key)),'"',PHP_EOL;
}
// Hash
else if ($type == 'hash') {
$values = $redis->hGetAll($key);
foreach ($values as $k => $v) {
echo 'HSET "',addslashes($key),'" "',addslashes($k),'" "',addslashes($v),'"',PHP_EOL;
}
}
// List
else if ($type == 'list') {
$size = $redis->lSize($key);
for ($i = 0; $i < $size; ++$i) {
echo 'RPUSH "',addslashes($key),'" "',addslashes($redis->lGet($key, $i)),'"',PHP_EOL;
}
}
// Set
else if ($type == 'set') {
$values = $redis->sMembers($key);
foreach ($values as $v) {
echo 'SADD "',addslashes($key),'" "',addslashes($v),'"',PHP_EOL;
}
}
// ZSet
else if ($type == 'zset') {
$values = $redis->zRange($key, 0, -1);
foreach ($values as $v) {
$s = $redis->zScore($key, $v);
echo 'ZADD "',addslashes($key),'" ',$s,' "',addslashes($v),'"',PHP_EOL;
}
}
}
// Return the JSON for this key
function export_json($key) {
global $redistypes, $redis;
$type = $redis->type($key);
if (!isset($redistypes[$type])) {
return 'undefined';
}
$type = $redistypes[$type];
// String
if ($type == 'string') {
$value = $redis->get($key);
}
// Hash
else if ($type == 'hash') {
$value = $redis->hGetAll($key);
}
// List
else if ($type == 'list') {
$size = $redis->lSize($key);
$value = array();
for ($i = 0; $i < $size; ++$i) {
$value[] = $redis->lGet($key, $i);
}
}
// Set
else if ($type == 'set') {
$value = $redis->sMembers($key);
}
// ZSet
else if ($type == 'zset') {
$value = $redis->zRange($key, 0, -1);
}
return $value;
}
// Export
if (isset($_POST['type'])) {
if ($_POST['type'] == 'json') {
$ext = 'js';
$ct = 'application/json';
} else {
$ext = 'redis';
$ct = 'text/plain';
}
header('Content-type: '.$ct.'; charset=utf-8');
header('Content-Disposition: inline; filename="export.'.$ext.'"');
// JSON
if ($_POST['type'] == 'json') {
// Single key
if (isset($_GET['key'])) {
echo json_encode(export_json($_GET['key']));
} else { // All keys
$keys = $redis->keys('*');
$vals = array();
foreach ($keys as $key) {
$vals[$key] = export_json($key);
}
echo json_encode($vals);
}
}
// Redis Commands
else {
// Single key
if (isset($_GET['key'])) {
export_redis($_GET['key']);
} else { // All keys
$keys = $redis->keys('*');
foreach ($keys as $key) {
export_redis($key);
}
}
}
die;
}
$page['css'][] = 'frame';
$page['js'][] = 'frame';
require 'header.inc.php';
?>
<h2>Export <?php echo isset($_GET['key']) ? format_html($_GET['key']) : ''?></h2>
<form action="<?php echo format_html($_SERVER['REQUEST_URI'])?>" method="post">
<p>
<label for="type">Type:</label>
<select name="type" id="type">
<option value="redis" <?php echo (isset($_GET['type']) && ($_GET['type'] == 'redis')) ? 'selected="selected"' : ''?>>Redis</option>
<option value="json" <?php echo (isset($_GET['type']) && ($_GET['type'] == 'json' )) ? 'selected="selected"' : ''?>>JSON</option>
</select>
</p>
<p>
<input type="submit" class="button" value="Export">
</p>
</form>
<?php
require 'footer.inc.php';
?>

View file

@ -1,3 +0,0 @@
</body>
</html>

View file

@ -1,66 +0,0 @@
<?php
function format_html($str) {
return htmlentities($str, ENT_COMPAT, 'UTF-8');
}
function format_ago($time, $ago = false) {
$minute = 60;
$hour = $minute * 60;
$day = $hour * 24;
$when = $time;
if ($when >= 0)
$suffix = 'ago';
else {
$when = -$when;
$suffix = 'in the future';
}
if ($when > $day) {
$when = round($when / $day);
$what = 'day';
} else if ($when > $hour) {
$when = round($when / $hour);
$what = 'hour';
} else if ($when > $minute) {
$when = round($when / $minute);
$what = 'minute';
} else {
$what = 'second';
}
if ($when != 1) $what .= 's';
if ($ago) {
return "$when $what $suffix";
} else {
return "$when $what";
}
}
function format_size($size) {
$sizes = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
if ($size == 0) {
return '0 B';
} else {
return round($size / pow(1024, ($i = floor(log($size, 1024)))), 1).' '.$sizes[$i];
}
}
function str_rand($length) {
$r = '';
for (; $length > 0; --$length) {
$r .= chr(rand(32, 126)); // 32 - 126 is the printable ascii range
}
return $r;
}

View file

@ -1,39 +0,0 @@
<?php
header('Content-Type: text/html; charset=utf-8');
header('Cache-Control: private');
?><!DOCTYPE html>
<html lang=en>
<head>
<meta charset=utf-8>
<?php if (is_ie()) {
// Always force latest IE rendering engine and chrome frame (also hides compatibility mode button)
?><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><?php
} ?>
<?php /* Disable phone number detection on apple devices. */?>
<meta name=format-detection content="telephone=no">
<?php /* I don't think we ever want this to be indexed*/ ?>
<meta name=robots content="noindex,nofollow,noarchive">
<meta name=author content="https://github.com/ErikDubbelboer/">
<title><?php echo format_html($server['host'])?> - phpRedisAdmin</title>
<?php foreach ($page['css'] as $css) { ?>
<link rel=stylesheet href="css/<?php echo $css; ?>.css?v1" media=all>
<?php } ?>
<link rel="shortcut icon" href="images/favicon.png">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"></script>
<?php foreach ($page['js'] as $js) { ?>
<script src="js/<?php echo $js; ?>.js?v1"></script>
<?php } ?>
</head>
<body>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 732 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 657 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 B

View file

@ -1,122 +0,0 @@
<?php
require_once 'common.inc.php';
// This mess could need some cleanup!
if (isset($_POST['commands'])) {
// Append some spaces at the end to make sure we always have enough arguments for the last function.
$commands = str_getcsv(str_replace(array("\r", "\n"), array('', ' '), $_POST['commands']).' ', ' ');
foreach ($commands as &$command) {
$command = stripslashes($command);
}
unset($command);
for ($i = 0; $i < count($commands); ++$i) {
if (empty($commands[$i])) {
continue;
}
$commands[$i] = strtoupper($commands[$i]);
switch ($commands[$i]) {
case 'SET': {
$redis->set($commands[$i+1], $commands[$i+2]);
$i += 2;
break;
}
case 'HSET': {
$redis->hSet($commands[$i+1], $commands[$i+2], $commands[$i+3]);
$i += 3;
break;
}
case 'LPUSH': {
$redis->lPush($commands[$i+1], $commands[$i+2]);
$i += 2;
break;
}
case 'RPUSH': {
$redis->rPush($commands[$i+1], $commands[$i+2]);
$i += 2;
break;
}
case 'LSET': {
$redis->lSet($commands[$i+1], $commands[$i+2], $commands[$i+3]);
$i += 3;
break;
}
case 'SADD': {
$redis->sAdd($commands[$i+1], $commands[$i+2]);
$i += 2;
break;
}
case 'ZADD': {
$redis->zAdd($commands[$i+1], $commands[$i+2], $commands[$i+3]);
$i += 3;
break;
}
}
}
// Refresh the top so the key tree is updated.
require 'header.inc.php';
?>
<script>
top.location.href = top.location.pathname+'?overview&s=<?php echo $server['id']?>';
</script>
<?php
require 'footer.inc.php';
die;
}
$page['css'][] = 'frame';
$page['js'][] = 'frame';
require 'header.inc.php';
?>
<h2>Import</h2>
<form action="<?php echo format_html($_SERVER['REQUEST_URI'])?>" method="post">
<p>
<label for="commands">Commands:<br>
<br>
<span class="info">
Valid are:<br>
SET<br>
HSET<br>
LPUSH<br>
RPUSH<br>
LSET<br>
SADD<br>
ZADD
</span>
</label>
<textarea name="commands" id="commands" cols="80" rows="20"></textarea>
</p>
<p>
<input type="submit" class="button" value="Import">
</p>
</form>
<?php
require 'footer.inc.php';
?>

View file

@ -1,205 +0,0 @@
<?php
require_once 'common.inc.php';
// Get all keys from Redis.
$keys = $redis->keys('*');
sort($keys);
$namespaces = array(); // Array to hold our top namespaces.
// Build an array of nested arrays containing all our namespaces and containing keys.
foreach ($keys as $key) {
// Ignore keys that are to long (Redis supports keys that can be way to long to put in an url).
if (strlen($key) > $config['maxkeylen']) {
continue;
}
$key = explode($config['seperator'], $key);
// $d will be a reference to the current namespace.
$d = &$namespaces;
// We loop though all the namespaces for this key creating the array for each.
// Each time updating $d to be a reference to the last namespace so we can create the next one in it.
for ($i = 0; $i < (count($key) - 1); ++$i) {
if (!isset($d[$key[$i]])) {
$d[$key[$i]] = array();
}
$d = &$d[$key[$i]];
}
// Containing an item named __phpredisadmin__ means it's also a key.
// This means that creating an actual key named __phpredisadmin__ will make this bug.
$d[$key[count($key) - 1]] = array('__phpredisadmin__' => true);
// Unset $d so we don't accidentally overwrite it somewhere else.
unset($d);
}
// This is basically the same as the click code in index.js.
// Just build the url for the frame based on our own url.
if (count($_GET) == 0) {
$iframe = 'overview.php';
} else {
$iframe = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], '?') + 1);
if (strpos($iframe, '&') !== false) {
$iframe = substr_replace($iframe, '.php?', strpos($iframe, '&'), 1);
} else {
$iframe .= '.php';
}
}
// Recursive function used to print the namespaces.
function print_namespace($item, $name, $fullkey, $islast) {
global $config, $redistypes, $server, $redis;
// Is this also a key and not just a namespace?
if (isset($item['__phpredisadmin__'])) {
// Unset it so we won't loop over it when printing this namespace.
unset($item['__phpredisadmin__']);
$type = $redis->type($fullkey);
if (!isset($redistypes[$type])) {
return;
}
$type = $redistypes[$type];
$class = array();
$len = false;
if (isset($_GET['key']) && ($fullkey == $_GET['key'])) {
$class[] = 'current';
}
if ($islast) {
$class[] = 'last';
}
// Get the number of items in the key.
if (!isset($config['faster']) || !$config['faster']) {
switch ($type) {
case 'hash':
$len = $redis->hLen($fullkey);
break;
case 'list':
$len = $redis->lSize($fullkey);
break;
case 'set':
// This is currently the only way to do this, this can be slow since we need to retrieve all keys
$len = count($redis->sMembers($fullkey));
break;
case 'zset':
// This is currently the only way to do this, this can be slow since we need to retrieve all keys
$len = count($redis->zRange($fullkey, 0, -1));
break;
}
}
?>
<li<?php echo empty($class) ? '' : ' class="'.implode(' ', $class).'"'?>>
<a href="?view&amp;s=<?php echo $server['id']?>&amp;key=<?php echo urlencode($fullkey)?>"><?php echo format_html($name)?><?php if ($len !== false) { ?><span class="info">(<?php echo $len?>)</span><?php } ?></a>
</li>
<?php
}
// Does this namespace also contain subkeys?
if (count($item) > 0) {
?>
<li class="folder<?php echo empty($fullkey) ? '' : ' collapsed'?><?php echo $islast ? ' last' : ''?>">
<div class="icon"><?php echo format_html($name)?>&nbsp;<span class="info">(<?php echo count($item)?>)</span>
<?php if (!empty($fullkey)) { ?><a href="delete.php?s=<?php echo $server['id']?>&amp;tree=<?php echo urlencode($fullkey)?>:" class="deltree"><img src="images/delete.png" width="10" height="10" title="Delete tree" alt="[X]"></a><?php } ?>
</div><ul>
<?php
$l = count($item);
foreach ($item as $childname => $childitem) {
// $fullkey will be empty on the first call.
if (empty($fullkey)) {
$childfullkey = $childname;
} else {
$childfullkey = $fullkey.$config['seperator'].$childname;
}
print_namespace($childitem, $childname, $childfullkey, (--$l == 0));
}
?>
</ul>
</li>
<?php
}
}
$page['css'][] = 'index';
$page['js'][] = 'index';
require 'header.inc.php';
?>
<div id="sidebar">
<h1 class="logo"><a href="?overview&amp;s=<?php echo $server['id']?>">phpRedisAdmin</a></h1>
<p>
<select id="server">
<?php foreach ($config['servers'] as $i => $srv) { ?>
<option value="<?php echo $i?>" <?php echo ($server['id'] == $i) ? 'selected="selected"' : ''?>><?php echo isset($srv['name']) ? format_html($srv['name']) : $srv['host'].':'.$srv['port']?></option>
<?php } ?>
</select>
</p>
<p>
<?php if (isset($login)) { ?>
<a href="logout.php"><img src="images/logout.png" width="16" height="16" title="Logout" alt="[L]"></a>
<?php } ?>
<a href="?info&amp;s=<?php echo $server['id']?>"><img src="images/info.png" width="16" height="16" title="Info" alt="[I]"></a>
<a href="?export&amp;s=<?php echo $server['id']?>"><img src="images/export.png" width="16" height="16" title="Export" alt="[E]"></a>
<a href="?import&amp;s=<?php echo $server['id']?>"><img src="images/import.png" width="16" height="16" title="Import" alt="[I]"></a>
</p>
<p>
<a href="?edit&amp;s=<?php echo $server['id']?>" class="add">Add another key</a>
</p>
<p>
<input type="text" id="filter" size="24" value="type here to filter" class="info">
</p>
<div id="keys">
<ul>
<?php print_namespace($namespaces, 'Keys', '', empty($namespaces))?>
</ul>
</div><!-- #keys -->
<div id="frame">
<iframe src="<?php echo format_html($iframe)?>" id="iframe" frameborder="0" scrolling="0"></iframe>
</div><!-- #frame -->
</div><!-- #sidebar -->
<?php
require 'footer.inc.php';
?>

View file

@ -1,60 +0,0 @@
<?php
require_once 'common.inc.php';
if (isset($_GET['reset']) && method_exists($redis, 'resetStat')) {
$redis->resetStat();
header('Location: info.php');
die;
}
// Fetch the info
$info = $redis->info();
$alt = false;
$page['css'][] = 'frame';
$page['js'][] = 'frame';
require 'header.inc.php';
?>
<h2>Info</h2>
<?php if (method_exists($redis, 'resetStat')) { ?>
<p>
<a href="?reset&amp;s=<?php echo $server['id']?>" class="reset">Reset usage statistics</a>
</p>
<?php } ?>
<table>
<tr><th><div>Key</div></th><th><div>Value</div></th></tr>
<?php
foreach ($info as $key => $value) {
if ($key == 'allocation_stats') { // This key is very long to split it into multiple lines
$value = str_replace(',', ",\n", $value);
}
?>
<tr <?php echo $alt ? 'class="alt"' : ''?>><td><div><?php echo format_html($key)?></div></td><td><div><?php echo nl2br(format_html($value))?></div></td></tr>
<?php
$alt = !$alt;
}
?>
</table>
<?php
require 'footer.inc.php';
?>

View file

@ -1,30 +0,0 @@
$(function() {
if (history.replaceState) {
window.parent.history.replaceState({}, '', document.location.href.replace('?', '&').replace(/([a-z]*)\.php/, '?$1'));
}
$('#type').change(function(e) {
$('#hkeyp' ).css('display', e.target.value == 'hash' ? 'block' : 'none');
$('#indexp').css('display', e.target.value == 'list' ? 'block' : 'none');
$('#scorep').css('display', e.target.value == 'zset' ? 'block' : 'none');
}).change();
$('.delkey, .delval').click(function(e) {
e.preventDefault();
if (confirm($(this).hasClass('delkey') ? 'Are you sure you want to delete this key and all it\'s values?' : 'Are you sure you want to delete this value?')) {
$.ajax({
type: "POST",
url: this.href,
data: 'post=1',
success: function(url) {
top.location.href = top.location.pathname+url;
}
});
}
});
});

View file

@ -1,103 +0,0 @@
$(function() {
$('#sidebar a').click(function(e) {
if (e.currentTarget.href.indexOf('/?') == -1) {
return;
}
e.preventDefault();
var href;
if ((e.currentTarget.href.indexOf('?') == -1) ||
(e.currentTarget.href.indexOf('?') == (e.currentTarget.href.length - 1))) {
href = 'overview.php';
} else {
href = e.currentTarget.href.substr(e.currentTarget.href.indexOf('?') + 1);
if (href.indexOf('&') != -1) {
href = href.replace('&', '.php?');
} else {
href += '.php';
}
}
$('#iframe').attr('src', href);
});
$('#server').change(function(e) {
if (location.href.indexOf('?') == -1) {
location.href = location.href+'?s='+e.target.value;
} else if (location.href.indexOf('&s=') == -1) {
location.href = location.href+'&s='+e.target.value;
} else {
location.href = location.href.replace(/s=[0-9]*/, 's='+e.target.value);
}
});
$('li.current').parents('li.folder').removeClass('collapsed');
$('li.folder').click(function(e) {
var t = $(this);
if ((e.pageY >= t.offset().top) &&
(e.pageY <= t.offset().top + t.children('div').height())) {
e.stopPropagation();
t.toggleClass('collapsed');
}
});
$('a').click(function() {
$('li.current').removeClass('current');
});
$('li a').click(function() {
$(this).parent().addClass('current');
});
$('#filter').focus(function() {
if ($(this).hasClass('info')) {
$(this).removeClass('info').val('');
}
}).keyup(function() {
var val = $(this).val();
$('li:not(.folder)').each(function(i, el) {
var key = $('a', el).get(0);
var key = unescape(key.href.substr(key.href.indexOf('key=') + 4));
if (key.indexOf(val) == -1) {
$(el).addClass('hidden');
} else {
$(el).removeClass('hidden');
}
});
$('li.folder').each(function(i, el) {
if ($('li:not(.hidden, .folder)', el).length == 0) {
$(el).addClass('hidden');
} else {
$(el).removeClass('hidden');
}
});
});
$('.deltree').click(function(e) {
e.preventDefault();
if (confirm('Are you sure you want to delete this whole tree and all it\'s keys?')) {
$.ajax({
type: "POST",
url: this.href,
data: 'post=1',
success: function(url) {
top.location.href = top.location.pathname;
}
});
}
});
});

View file

@ -1,63 +0,0 @@
<?php
// This fill will perform HTTP digest authentication. This is not the most secure form of authentication so be carefull when using this.
$realm = 'phpRedisAdmin';
// Using the md5 of the user agent and IP should make it a bit harder to intercept and reuse the responses.
$opaque = md5('phpRedisAdmin'.$_SERVER['HTTP_USER_AGENT'].$_SERVER['REMOTE_ADDR']);
if (!isset($_SERVER['PHP_AUTH_DIGEST']) || empty($_SERVER['PHP_AUTH_DIGEST'])) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.'",qop="auth",nonce="'.uniqid().'",opaque="'.$opaque.'"');
die;
}
$needed_parts = array(
'nonce' => 1,
'nc' => 1,
'cnonce' => 1,
'qop' => 1,
'username' => 1,
'uri' => 1,
'response' => 1
);
$data = array();
$keys = implode('|', array_keys($needed_parts));
preg_match_all('/('.$keys.')=(?:([\'"])([^\2]+?)\2|([^\s,]+))/', $_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
unset($needed_parts[$m[1]]);
}
if (!empty($needed_parts)) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.'",qop="auth",nonce="'.uniqid().'",opaque="'.$opaque.'"');
die;
}
if (!isset($config['login'][$data['username']])) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.'",qop="auth",nonce="'.uniqid().'",opaque="'.$opaque.'"');
die('Invalid username and/or password combination.');
}
$login = $config['login'][$data['username']];
$login['name'] = $data['username'];
$password = md5($login['name'].':'.$realm.':'.$login['password']);
$response = md5($password.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']));
if ($data['response'] != $response) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.'",qop="auth",nonce="'.uniqid().'",opaque="'.$opaque.'"');
die('Invalid username and/or password combination.');
}
?>

View file

@ -1,40 +0,0 @@
<?php
$needed_parts = array(
'nonce' => 1,
'nc' => 1,
'cnonce' => 1,
'qop' => 1,
'username' => 1,
'uri' => 1,
'response' => 1
);
$data = array();
$keys = implode('|', array_keys($needed_parts));
preg_match_all('/('.$keys.')=(?:([\'"])([^\2]+?)\2|([^\s,]+))/', $_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
unset($needed_parts[$m[1]]);
}
if (!isset($_GET['nonce'])) {
header('Location: logout.php?nonce='.$data['nonce']);
die;
}
if ($data['nonce'] == $_GET['nonce']) {
unset($_SERVER['PHP_AUTH_DIGEST']);
require 'login.inc.php';
}
header('Location: '.substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], 'logout.php')));
?>

View file

@ -1,84 +0,0 @@
<?php
require_once 'common.inc.php';
$info = array();
foreach ($config['servers'] as $i => $server) {
if (!isset($server['db'])) {
$server['db'] = 0;
}
// Setup a connection to this Redis server.
$redis->close();
try {
$redis->connect($server['host'], $server['port']);
} catch (Exception $e) {
die('ERROR: Could not connect to Redis ('.$server['host'].':'.$server['port'].')');
}
if (isset($server['auth'])) {
if (!$redis->auth($server['auth'])) {
die('ERROR: Authentication failed ('.$server['host'].':'.$server['port'].')');
}
}
if ($server['db'] != 0) {
if (!$redis->select($server['db'])) {
die('ERROR: Selecting database failed ('.$server['host'].':'.$server['port'].','.$server['db'].')');
}
}
$info[$i] = $redis->info();
$info[$i]['size'] = $redis->dbSize();
}
$page['css'][] = 'frame';
$page['js'][] = 'frame';
require 'header.inc.php';
?>
<?php foreach ($config['servers'] as $i => $server) { ?>
<div class="server">
<h2><?php echo isset($server['name']) ? $server['name'] : format_html($server['host'])?></h2>
<table>
<tr><td><div>Redis version:</div></td><td><div><?php echo $info[$i]['redis_version']?></div></td></tr>
<tr><td><div>Keys:</div></td><td><div><?php echo $info[$i]['size']?></div></td></tr>
<tr><td><div>Memory used:</div></td><td><div><?php echo format_size($info[$i]['used_memory'])?></div></td></tr>
<tr><td><div>Uptime:</div></td><td><div><?php echo format_ago($info[$i]['uptime_in_seconds'])?></div></td></tr>
<tr><td><div>Last save:</div></td><td><div><?php echo format_ago(time() - $info[$i]['last_save_time'], true)?> <a href="save.php?s=<?php echo $i?>"><img src="images/save.png" width="16" height="16" title="Save Now" alt="[S]" class="imgbut"></a></div></td></tr>
</table>
</div>
<?php } ?>
<p class="clear">
<a href="https://github.com/ErikDubbelboer/phpRedisAdmin" target="_blank">phpRedisAdmin on GitHub</a>
</p>
<p>
<a href="http://redis.io/documentation" target="_blank">Redis Documentation</a>
</p>
<?php
require 'footer.inc.php';
?>

View file

@ -1,22 +0,0 @@
<?php
// Returns true when the user is using IE
function is_ie() {
if (isset($_SERVER['HTTP_USER_AGENT']) &&
(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false)) {
return true;
} else {
return false;
}
}
$page = array(
'css' => array('common'),
'js' => array()
);
?>

View file

@ -1,56 +0,0 @@
<?php
require_once 'common.inc.php';
if (isset($_POST['old'], $_POST['key'])) {
if (strlen($_POST['key']) > $config['maxkeylen']) {
die('ERROR: Your key is to long (max length is '.$config['maxkeylen'].')');
}
$redis->rename($_POST['old'], $_POST['key']);
// Refresh the top so the key tree is updated.
require 'header.inc.php';
?>
<script>
top.location.href = top.location.pathname+'?view&s=<?php echo $server['id']?>&key=<?php echo urlencode($_POST['key'])?>';
</script>
<?php
require 'footer.inc.php';
die;
}
$page['css'][] = 'frame';
$page['js'][] = 'frame';
require 'header.inc.php';
?>
<h2>Edit Name of <?php echo format_html($_GET['key'])?></h2>
<form action="<?php echo format_html($_SERVER['REQUEST_URI'])?>" method="post">
<input type="hidden" name="old" value="<?php echo format_html($_GET['key'])?>">
<p>
<label for="key">Key:</label>
<input type="text" name="key" id="key" size="30" <?php echo isset($_GET['key']) ? 'value="'.format_html($_GET['key']).'"' : ''?>>
</p>
<p>
<input type="submit" class="button" value="Rename">
</p>
</form>
<?php
require 'footer.inc.php';
?>

View file

@ -1,30 +0,0 @@
<?php
require_once 'common.inc.php';
$page['css'][] = 'frame';
$page['js'][] = 'frame';
require 'header.inc.php';
?>
<h2>Saving</h2>
...
<?php
// Flush everything so far cause the next command could take some time.
flush();
$redis->save();
?>
done.
<?php
require 'footer.inc.php';
?>

View file

@ -1,50 +0,0 @@
<?php
require_once 'common.inc.php';
if (isset($_POST['key'], $_POST['ttl'])) {
if ($_POST['ttl'] == -1) {
$redis->persist($_POST['key']);
} else {
$redis->setTimeout($_POST['key'], $_POST['ttl']);
}
header('Location: view.php?key='.urlencode($_POST['key']));
die;
}
$page['css'][] = 'frame';
$page['js'][] = 'frame';
require 'header.inc.php';
?>
<h2>Edit TTL</h2>
<form action="<?php echo format_html($_SERVER['REQUEST_URI'])?>" method="post">
<p>
<label for="key">Key:</label>
<input type="text" name="key" id="key" size="30" <?php echo isset($_GET['key']) ? 'value="'.format_html($_GET['key']).'"' : ''?>>
</p>
<p>
<label for="ttl"><abbr title="Time To Live">TTL</abbr>:</label>
<input type="text" name="ttl" id="ttl" size="30" <?php echo isset($_GET['ttl']) ? 'value="'.format_html($_GET['ttl']).'"' : ''?>> <span class="info">(-1 to remove the TTL)</span>
</p>
<p>
<input type="submit" class="button" value="Edit TTL">
</p>
</form>
<?php
require 'footer.inc.php';
?>

View file

@ -1,207 +0,0 @@
<?php
require_once 'common.inc.php';
$page['css'][] = 'frame';
$page['js'][] = 'frame';
require 'header.inc.php';
if (!isset($_GET['key'])) {
?>
Invalid key
<?php
require 'footer.inc.php';
die;
}
$type = $redis->type($_GET['key']);
$exists = $redis->exists($_GET['key']);
?>
<h2><?php echo format_html($_GET['key'])?>
<?php if ($exists) { ?>
<a href="rename.php?s=<?php echo $server['id']?>&amp;key=<?php echo urlencode($_GET['key'])?>"><img src="images/edit.png" width="16" height="16" title="Rename" alt="[R]"></a>
<a href="delete.php?s=<?php echo $server['id']?>&amp;key=<?php echo urlencode($_GET['key'])?>" class="delkey"><img src="images/delete.png" width="16" height="16" title="Delete" alt="[X]"></a>
<a href="export.php?s=<?php echo $server['id']?>&amp;key=<?php echo urlencode($_GET['key'])?>"><img src="images/export.png" width="16" height="16" title="Export" alt="[E]"></a>
<?php } ?>
</h2>
<?php
if (!$exists) {
?>
This key does not exist.
<?php
require 'footer.inc.php';
die;
}
$alt = false;
$type = $redistypes[$type];
$ttl = $redis->ttl($_GET['key']);
$encoding = $redis->object('encoding', $_GET['key']);
switch ($type) {
case 'string':
$value = $redis->get($_GET['key']);
$size = strlen($value);
break;
case 'hash':
$values = $redis->hGetAll($_GET['key']);
$size = count($values);
break;
case 'list':
$size = $redis->lSize($_GET['key']);
break;
case 'set':
$values = $redis->sMembers($_GET['key']);
$size = count($values);
break;
case 'zset':
$values = $redis->zRange($_GET['key'], 0, -1);
$size = count($values);
break;
}
?>
<table>
<tr><td><div>Type:</div></td><td><div><?php echo format_html($type)?></div></td></tr>
<tr><td><div><abbr title="Time To Live">TTL</abbr>:</div></td><td><div><?php echo ($ttl == -1) ? 'does not expire' : $ttl?> <a href="ttl.php?s=<?php echo $server['id']?>&amp;key=<?php echo urlencode($_GET['key'])?>&amp;ttl=<?php echo $ttl?>"><img src="images/edit.png" width="16" height="16" title="Edit TTL" alt="[E]" class="imgbut"></a></div></td></tr>
<tr><td><div>Encoding:</div></td><td><div><?php echo format_html($encoding)?></div></td></tr>
<tr><td><div>Size:</div></td><td><div><?php echo $size?> <?php echo ($type == 'string') ? 'characters' : 'items'?></div></td></tr>
</table>
<p>
<?php
// String
if ($type == 'string') { ?>
<table>
<tr><td><div><?php echo nl2br(format_html($value))?></div></td><td><div>
<a href="edit.php?s=<?php echo $server['id']?>&amp;type=string&amp;key=<?php echo urlencode($_GET['key'])?>"><img src="images/edit.png" width="16" height="16" title="Edit" alt="[E]"></a>
</div></td><td><div>
<a href="delete.php?s=<?php echo $server['id']?>&amp;type=string&amp;key=<?php echo urlencode($_GET['key'])?>" class="delval"><img src="images/delete.png" width="16" height="16" title="Delete" alt="[X]"></a>
</div></td></tr>
</table>
<?php }
// Hash
else if ($type == 'hash') { ?>
<table>
<tr><th><div>Key</div></th><th><div>Value</div></th><th><div>&nbsp;</div></th><th><div>&nbsp;</div></th></tr>
<?php foreach ($values as $hkey => $value) { ?>
<tr <?php echo $alt ? 'class="alt"' : ''?>><td><div><?php echo format_html($hkey)?></div></td><td><div><?php echo nl2br(format_html($value))?></div></td><td><div>
<a href="edit.php?s=<?php echo $server['id']?>&amp;type=hash&amp;key=<?php echo urlencode($_GET['key'])?>&amp;hkey=<?php echo urlencode($hkey)?>"><img src="images/edit.png" width="16" height="16" title="Edit" alt="[E]"></a>
</div></td><td><div>
<a href="delete.php?s=<?php echo $server['id']?>&amp;type=hash&amp;key=<?php echo urlencode($_GET['key'])?>&amp;hkey=<?php echo urlencode($hkey)?>" class="delval"><img src="images/delete.png" width="16" height="16" title="Delete" alt="[X]"></a>
</div></td></tr>
<?php $alt = !$alt; } ?>
<?php }
// List
else if ($type == 'list') { ?>
<table>
<tr><th><div>Index</div></th><th><div>Value</div></th><th><div>&nbsp;</div></th><th><div>&nbsp;</div></th></tr>
<?php for ($i = 0; $i < $size; ++$i) {
$value = $redis->lGet($_GET['key'], $i);
?>
<tr <?php echo $alt ? 'class="alt"' : ''?>><td><div><?php echo $i?></div></td><td><div><?php echo nl2br(format_html($value))?></div></td><td><div>
<a href="edit.php?s=<?php echo $server['id']?>&amp;type=list&amp;key=<?php echo urlencode($_GET['key'])?>&amp;index=<?php echo $i?>"><img src="images/edit.png" width="16" height="16" title="Edit" alt="[E]"></a>
</div></td><td><div>
<a href="delete.php?s=<?php echo $server['id']?>&amp;type=list&amp;key=<?php echo urlencode($_GET['key'])?>&amp;index=<?php echo $i?>" class="delval"><img src="images/delete.png" width="16" height="16" title="Delete" alt="[X]"></a>
</div></td></tr>
<?php $alt = !$alt; } ?>
<?php }
// Set
else if ($type == 'set') {
?>
<table>
<tr><th><div>Value</div></th><th><div>&nbsp;</div></th><th><div>&nbsp;</div></th></tr>
<?php foreach ($values as $value) {
$display_value = $redis->exists($value) ? '<a href="view.php?s='.$server['id'].'&key='.urlencode($value).'">'.nl2br(format_html($value)).'</a>' : nl2br(format_html($value));
?>
<tr <?php echo $alt ? 'class="alt"' : ''?>><td><div><?php echo $display_value ?></div></td><td><div>
<a href="edit.php?s=<?php echo $server['id']?>&amp;type=set&amp;key=<?php echo urlencode($_GET['key'])?>&amp;value=<?php echo urlencode($value)?>"><img src="images/edit.png" width="16" height="16" title="Edit" alt="[E]"></a>
</div></td><td><div>
<a href="delete.php?s=<?php echo $server['id']?>&amp;type=set&amp;key=<?php echo urlencode($_GET['key'])?>&amp;value=<?php echo urlencode($value)?>" class="delval"><img src="images/delete.png" width="16" height="16" title="Delete" alt="[X]"></a>
</div></td></tr>
<?php $alt = !$alt; } ?>
<?php }
// ZSet
else if ($type == 'zset') { ?>
<table>
<tr><th><div>Score</div></th><th><div>Value</div></th><th><div>&nbsp;</div></th><th><div>&nbsp;</div></th></tr>
<?php foreach ($values as $value) {
$score = $redis->zScore($_GET['key'], $value);
$display_value = $redis->exists($value) ? '<a href="view.php?s='.$server['id'].'&key='.urlencode($value).'">'.nl2br(format_html($value)).'</a>' : nl2br(format_html($value));
?>
<tr <?php echo $alt ? 'class="alt"' : ''?>><td><div><?php echo $score?></div></td><td><div><?php echo $display_value ?></div></td><td><div>
<a href="edit.php?s=<?php echo $server['id']?>&amp;type=zset&amp;key=<?php echo urlencode($_GET['key'])?>&amp;score=<?php echo $score?>&amp;value=<?php echo urlencode($value)?>"><img src="images/edit.png" width="16" height="16" title="Edit" alt="[E]"></a>
<a href="delete.php?s=<?php echo $server['id']?>&amp;type=zset&amp;key=<?php echo urlencode($_GET['key'])?>&amp;value=<?php echo urlencode($value)?>" class="delval"><img src="images/delete.png" width="16" height="16" title="Delete" alt="[X]"></a>
</div></td></tr>
<?php $alt = !$alt; } ?>
<?php }
if ($type != 'string') { ?>
</table>
<p>
<a href="edit.php?s=<?php echo $server['id']?>&amp;type=<?php echo $type?>&amp;key=<?php echo urlencode($_GET['key'])?>" class="add">Add another value</a>
</p>
<?php }
require 'footer.inc.php';

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 407 B

After

Width:  |  Height:  |  Size: 3.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 B

After

Width:  |  Height:  |  Size: 2.8 KiB

Before After
Before After

View file

@ -74,7 +74,7 @@ body, th, td, font {
#body_container { background: #E3E3E3; padding: 0 2px 4px; } #body_container { background: #E3E3E3; padding: 0 2px 4px; }
#page_container { #page_container {
margin: 0 auto; margin: 0 auto;
background: #FFFFFF; border: 1px solid #D1D7DC; background: #FFFFFF; border: 1px solid #CFD4D8;
} }
#page_header { #page_header {
position: relative; width: 100%; position: relative; width: 100%;
@ -114,11 +114,11 @@ wbr { display: inline-block; }
/* ---------------------------------- * /* ---------------------------------- *
Links Links
* ---------------------------------- */ * ---------------------------------- */
:link:focus, :visited:focus { color: #DD6900; } :link:focus, :visited:focus { color: #444; }
:link { color: #006699; text-decoration: none !important; } :link { color: #222; text-decoration: none !important; }
:visited { color: #006699; text-decoration: none !important; } :visited { color: #222; text-decoration: none !important; }
:link:hover, :visited:hover { color: #DD6900; text-decoration: underline !important; } :link:hover, :visited:hover { color: #444; text-decoration: underline !important; }
:link:active, :visited:active { color: #DD6900; text-decoration: underline !important; } :link:active, :visited:active { color: #444; text-decoration: underline !important; }
.colorAdmin, a.colorAdmin, a.colorAdmin:visited { color: #A00 !important; } .colorAdmin, a.colorAdmin, a.colorAdmin:visited { color: #A00 !important; }
.colorSuperMod, a.colorSuperMod, a.colorSuperMod:visited { color: #0080FF !important; } .colorSuperMod, a.colorSuperMod, a.colorSuperMod:visited { color: #0080FF !important; }
@ -164,14 +164,14 @@ a.seed:visited, a.seedmed:visited, a.seedsmall:visited
font-size: 11px; text-decoration: none; font-size: 11px; text-decoration: none;
} }
a.topictitle:visited, a.torTopic:visited, a.tLink:visited { a.topictitle:visited, a.torTopic:visited, a.tLink:visited {
color: #5493B4; color: #444;
} }
/* ---------------------------------- * /* ---------------------------------- *
Backgrounds Backgrounds
* ---------------------------------- */ * ---------------------------------- */
.row1, .row1 td { background: #EFEFEF; } .row1, .row1 td { background: #eff0f3; }
.row2, .row2 td { background: #DEE3E7; } .row2, .row2 td { background: #e3e8ed; }
.row3, .row3 td { background: #D1D7DC; } .row3, .row3 td { background: #d2d7e2; }
.row4, .row4 td { background: #ECECEC; } .row4, .row4 td { background: #ECECEC; }
.row5, .row5 td { background: #E7E7E7; } .row5, .row5 td { background: #E7E7E7; }
.row6, .row6 td { background: #E9E9E6; } .row6, .row6 td { background: #E9E9E6; }
@ -213,7 +213,7 @@ td.small { font-size: 10px !important; }
.gen, .med, .genmed, .gen, .med, .genmed,
.small, .gensmall { color: #000000; } .small, .gensmall { color: #000000; }
a.gen, a.med, a.genmed, a.gen, a.med, a.genmed,
a.small, a.gensmall { color: #006699; text-decoration: none; } a.small, a.gensmall { color: #222; text-decoration: none; }
/* ---------------------------------- * /* ---------------------------------- *
Post elements Post elements
* ---------------------------------- */ * ---------------------------------- */
@ -253,7 +253,7 @@ a.small, a.gensmall { color: #006699; text-decoration: none; }
/* ---------------------------------- * /* ---------------------------------- *
Spoiler Spoiler
* ---------------------------------- */ * ---------------------------------- */
.sp-wrap { padding: 0; background: #E9E9E6; } .sp-wrap { padding: 0; background: #EDEDED; }
.sp-head { border-width: 0; font-size: 11px; padding: 1px 14px 3px; margin-left: 6px; line-height: 15px; font-weight: bold; color: #2A2A2A; cursor: pointer; } .sp-head { border-width: 0; font-size: 11px; padding: 1px 14px 3px; margin-left: 6px; line-height: 15px; font-weight: bold; color: #2A2A2A; cursor: pointer; }
.sp-body { border-width: 1px 0 0 0; display: none; font-weight: normal; background: #F5F5F5; border-bottom: 1px solid #C3CBD1;} .sp-body { border-width: 1px 0 0 0; display: none; font-weight: normal; background: #F5F5F5; border-bottom: 1px solid #C3CBD1;}
.sp-fold { width: 98%; margin: 0 auto; text-align: right; font-size: 10px; color: #444444; } .sp-fold { width: 98%; margin: 0 auto; text-align: right; font-size: 10px; color: #444444; }
@ -311,12 +311,12 @@ input.mainoption, input.main {
} }
/* The buttons used for bbCode styling in message post */ /* The buttons used for bbCode styling in message post */
input.button, .buttons input { border: 1px solid; background: #F5F5F5; } input.button, .buttons input { border:1px dotted; background: #F6F6FF; }
input.long { padding-left: 20px; padding-right: 20px; } input.long { padding-left: 20px; padding-right: 20px; }
.buttons input:hover {border:1px solid #DEDEDE; background:#FFF;}
input.button, .buttons input, input.button, .buttons input,
input.mainoption, input.main, input.liteoption, input.lite { input.mainoption, input.main, input.liteoption, input.lite {
color: #000000; border-color: #B4B4B4 #000000 #000000 #B4B4B4; color: #000000; border-color: #ABABAB;
} }
/* "gte IE 7" in page_header.tpl */ /* "gte IE 7" in page_header.tpl */
@ -406,7 +406,7 @@ table.forumline {
.forumline th, .thHead { .forumline th, .thHead {
padding: 6px 8px 7px; text-align: center; padding: 6px 8px 7px; text-align: center;
color: #D5E4EC; font-size: 11px; font-weight: bold; color: #D5E4EC; font-size: 11px; font-weight: bold;
background: #006699 url(../images/cellpic3.gif) repeat-x; background: #1C508C url(../images/cellpic1.gif) repeat-x;
} }
/* "lte IE 6" in page_header.tpl */ /* "lte IE 6" in page_header.tpl */
.forumline th:first-child { border-left-color: #92A3A4; } .forumline th:first-child { border-left-color: #92A3A4; }
@ -427,7 +427,7 @@ table.message td {
.cat, td.cat, td.catTitle, td.catHead, td.catBottom { .cat, td.cat, td.catTitle, td.catHead, td.catBottom {
padding: 5px 4px 6px; padding: 5px 4px 6px;
background: #E0E5E9 url(../images/cellpic1.gif) repeat-x; background: #E0E5E9 url(../images/cellpic.gif) repeat-x;
} }
.catTitle { .catTitle {
font-weight: bold; letter-spacing: 1px; font-weight: bold; letter-spacing: 1px;
@ -482,7 +482,7 @@ table.smilies td { padding: 3px; text-align: center; }
TopMenu, Quick Login, PM Info, Loguot.. TopMenu, Quick Login, PM Info, Loguot..
* ---------------------------------- */ * ---------------------------------- */
.topmenu { .topmenu {
background: #EFEFEF; border: 1px solid #CFD4D8; background: #eff0f3; border: 1px solid #CFD4D8;
margin: 3px 4px 0; padding: 0 3px; overflow: hidden; margin: 3px 4px 0; padding: 0 3px; overflow: hidden;
} }
.topmenu a:link, .topmenu a:visited { text-decoration: none; } .topmenu a:link, .topmenu a:visited { text-decoration: none; }
@ -509,11 +509,11 @@ table.smilies td { padding: 3px; text-align: center; }
Main navigation Main navigation
* ---------------------------------- */ * ---------------------------------- */
#main-nav { #main-nav {
padding: 2px 10px; margin: 0 4px; padding: 4px 10px; margin: 0px;
border: solid #CFD4D8; border-width: 1px 0; background: #CFD4D8; border: solid #C3CBD1 /*#CFD4D8*/; border-width: 0 0 1px 0px; background: #eff0f3 url('../images/cellpic.gif');
} }
#main-nav b { padding: 0 4px 0 1px; } #main-nav b { padding: 0 4px 0 1px; }
#main-nav a { color: #535F62; text-decoration: none; } #main-nav a { color: #444; text-decoration: none; }
#main-nav a:hover, #main-nav a:active { #main-nav a:hover, #main-nav a:active {
text-decoration: none !important; color: #000000; text-decoration: none !important; color: #000000;
} }
@ -594,7 +594,7 @@ table.smilies td { padding: 3px; text-align: center; }
#forums_wrap { clear: both; padding-top: 1px; } #forums_wrap { clear: both; padding-top: 1px; }
.cat_title { /* Category header */ .cat_title { /* Category header */
padding: 3px 8px 5px; letter-spacing: 1px; text-indent: 0.6em; padding: 3px 8px 5px; letter-spacing: 1px; text-indent: 0.6em;
background: #DEE3E7 url(../images/cellpic1.gif) repeat-x; background: #DEE3E7 url(../images/cellpic.gif) repeat-x;
} }
.cat_title a { text-decoration: none; color: #333333 !important; } .cat_title a { text-decoration: none; color: #333333 !important; }
table.forums { width: 100%; } table.forums { width: 100%; }
@ -622,7 +622,7 @@ table.forums { width: 100%; }
} }
.subforums em { display: none; } .subforums em { display: none; }
.subforums + .moderators { margin-top: 0; } .subforums + .moderators { margin-top: 0; }
.dot-sf { color: #417998 !important; font-size: 11px; margin-right: 4px; } .dot-sf { color: #444 !important; font-size: 11px; margin-right: 4px; }
.new .dot-sf { color: #CA4200 !important; } .new .dot-sf { color: #CA4200 !important; }
.sf_title { white-space: normal; } .sf_title { white-space: normal; }
.sf_icon { margin-right: 1px; } .sf_icon { margin-right: 1px; }
@ -866,7 +866,7 @@ a.menu-root, a.menu-root:visited, a.menu-root:hover {
text-decoration: none !important; } text-decoration: none !important; }
.menu-sub { position: absolute; display: none; z-index: 1000; } .menu-sub { position: absolute; display: none; z-index: 1000; }
.menu-sub table { background: #FFFFFF; border: 1px solid #92A3A4; } .menu-sub table { background: #FFFFFF; border: 1px solid #92A3A4; }
.menu-sub table th { background: #71869F; color: #F0F8FF; font-weight: bold; font-size: 11px; } .menu-sub table th { background: #566C98; color: #F0F8FF; font-weight: bold; font-size: 11px; }
.menu-sub table td { background: #E7E7E7; font-size: 11px; } .menu-sub table td { background: #E7E7E7; font-size: 11px; }
.menu-sub table td.cat { background: #B5BEC3; } .menu-sub table td.cat { background: #B5BEC3; }
.menu-sub legend { font-weight: bold; } .menu-sub legend { font-weight: bold; }
@ -877,8 +877,8 @@ a.menu-root, a.menu-root:visited, a.menu-root:hover {
display/**/: block; display/**/: block;
position: absolute; z-index: -1; filter: mask(); } position: absolute; z-index: -1; filter: mask(); }
.menu-a { background: #FFFFFF; border: 1px solid #92A3A4; } .menu-a { background: #FFFFFF; border: 1px solid #92A3A4; }
.menu-a a { color: #0000A0; background: #E7E7E7; padding: 4px 10px 5px; margin: 1px; display: block; text-decoration: none !important; } .menu-a a { color: #222; background: #E7E7E7; padding: 4px 10px 5px; margin: 1px; display: block; text-decoration: none !important; }
.menu-a a:hover { color: #0000FF; background: #D1D7DC; text-decoration: none !important; } .menu-a a:hover { color: #444; background: #EFEFEF; text-decoration: none !important; }
/* ================================================================ * /* ================================================================ *
Ajax Ajax
* ================================================================ */ * ================================================================ */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 722 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 246 B

After

Width:  |  Height:  |  Size: 1.8 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 344 B

After

Width:  |  Height:  |  Size: 989 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 289 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 677 B

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 344 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 341 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 459 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 B

After

Width:  |  Height:  |  Size: 2.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

After

Width:  |  Height:  |  Size: 1,001 B

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 663 B

After

Width:  |  Height:  |  Size: 2.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 344 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

Some files were not shown because too many files have changed in this diff Show more