From a7fabcaa5f2f795e831c55a7df6deda798e5ea8a Mon Sep 17 00:00:00 2001 From: dimka3210 Date: Sun, 22 Jan 2012 09:51:09 +0000 Subject: [PATCH] r341 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Сам в своё время искал. Думаю что пригодится. git-svn-id: https://torrentpier2.googlecode.com/svn/trunk@341 a8ac35ab-4ca4-ca47-4c2d-a49a94f06293 --- .../MemcacheAdmin/Config/Memcache.php | 28 ++ .../MemcacheAdmin/Library/Analysis.php | 332 +++++++++++++ .../MemcacheAdmin/Library/Command/Factory.php | 111 +++++ .../Library/Command/Interface.php | 139 ++++++ .../Library/Command/Memcache.php | 257 ++++++++++ .../Library/Command/Memcached.php | 226 +++++++++ .../MemcacheAdmin/Library/Command/Server.php | 443 ++++++++++++++++++ .../Library/Configuration/Loader.php | 187 ++++++++ .../MemcacheAdmin/Library/Data/Error.php | 59 +++ .../MemcacheAdmin/Library/HTML/Components.php | 147 ++++++ .../MemcacheAdmin/Library/Loader.php | 9 + .../MemcacheAdmin/Public/Images/635855.png | Bin 0 -> 2896 bytes .../MemcacheAdmin/Public/Images/b5463f.png | Bin 0 -> 3115 bytes .../MemcacheAdmin/Public/Scripts/Script.js | 29 ++ .../MemcacheAdmin/Public/Styles/Style.css | 1 + ...12857559947a1920d61156abc05a60135aefe8bc67 | 1 + .../MemcacheAdmin/View/Commands/Commands.tpl | 162 +++++++ .../View/Configure/Configure.tpl | 161 +++++++ .../cachetools/MemcacheAdmin/View/Footer.tpl | 7 + .../cachetools/MemcacheAdmin/View/Header.tpl | 62 +++ .../MemcacheAdmin/View/LiveStats/Frame.tpl | 70 +++ .../MemcacheAdmin/View/LiveStats/Stats.tpl | 87 ++++ .../MemcacheAdmin/View/Stats/Error.tpl | 58 +++ .../MemcacheAdmin/View/Stats/Items.tpl | 52 ++ .../MemcacheAdmin/View/Stats/Slabs.tpl | 126 +++++ .../MemcacheAdmin/View/Stats/Stats.tpl | 356 ++++++++++++++ other/cachetools/MemcacheAdmin/commands.php | 276 +++++++++++ other/cachetools/MemcacheAdmin/configure.php | 127 +++++ other/cachetools/MemcacheAdmin/index.php | 176 +++++++ other/cachetools/MemcacheAdmin/stats.php | 171 +++++++ .../cachetools/phpRedisAdmin/README.markdown | 39 ++ other/cachetools/phpRedisAdmin/common.inc.php | 115 +++++ other/cachetools/phpRedisAdmin/config.inc.php | 56 +++ other/cachetools/phpRedisAdmin/css/common.css | 53 +++ other/cachetools/phpRedisAdmin/css/frame.css | 56 +++ other/cachetools/phpRedisAdmin/css/index.css | 122 +++++ other/cachetools/phpRedisAdmin/delete.php | 63 +++ other/cachetools/phpRedisAdmin/edit.php | 186 ++++++++ other/cachetools/phpRedisAdmin/export.php | 197 ++++++++ other/cachetools/phpRedisAdmin/footer.inc.php | 3 + .../phpRedisAdmin/functions.inc.php | 66 +++ other/cachetools/phpRedisAdmin/header.inc.php | 39 ++ other/cachetools/phpRedisAdmin/images/add.png | Bin 0 -> 355 bytes .../phpRedisAdmin/images/delete.png | Bin 0 -> 346 bytes .../cachetools/phpRedisAdmin/images/edit.png | Bin 0 -> 553 bytes .../phpRedisAdmin/images/export.png | Bin 0 -> 640 bytes .../phpRedisAdmin/images/favicon.png | Bin 0 -> 6740 bytes .../phpRedisAdmin/images/folder-open.png | Bin 0 -> 534 bytes .../phpRedisAdmin/images/import.png | Bin 0 -> 692 bytes .../cachetools/phpRedisAdmin/images/info.png | Bin 0 -> 732 bytes .../phpRedisAdmin/images/logout.png | Bin 0 -> 657 bytes .../cachetools/phpRedisAdmin/images/reset.png | Bin 0 -> 323 bytes .../cachetools/phpRedisAdmin/images/save.png | Bin 0 -> 465 bytes .../images/tree-folder-collapsed.gif | Bin 0 -> 118 bytes .../images/tree-folder-expanded.gif | Bin 0 -> 114 bytes .../images/tree-lastnode-collapsed.gif | Bin 0 -> 109 bytes .../images/tree-lastnode-expanded.gif | Bin 0 -> 105 bytes .../phpRedisAdmin/images/tree-lastnode.gif | Bin 0 -> 64 bytes .../phpRedisAdmin/images/tree-node.gif | Bin 0 -> 74 bytes .../phpRedisAdmin/images/tree-vline.gif | Bin 0 -> 44 bytes other/cachetools/phpRedisAdmin/import.php | 122 +++++ other/cachetools/phpRedisAdmin/index.php | 205 ++++++++ other/cachetools/phpRedisAdmin/info.php | 60 +++ other/cachetools/phpRedisAdmin/js/frame.js | 30 ++ other/cachetools/phpRedisAdmin/js/index.js | 103 ++++ other/cachetools/phpRedisAdmin/login.inc.php | 63 +++ other/cachetools/phpRedisAdmin/logout.php | 40 ++ other/cachetools/phpRedisAdmin/overview.php | 84 ++++ other/cachetools/phpRedisAdmin/page.inc.php | 22 + other/cachetools/phpRedisAdmin/rename.php | 56 +++ other/cachetools/phpRedisAdmin/save.php | 30 ++ other/cachetools/phpRedisAdmin/ttl.php | 50 ++ other/cachetools/phpRedisAdmin/view.php | 207 ++++++++ 73 files changed, 5927 insertions(+) create mode 100644 other/cachetools/MemcacheAdmin/Config/Memcache.php create mode 100644 other/cachetools/MemcacheAdmin/Library/Analysis.php create mode 100644 other/cachetools/MemcacheAdmin/Library/Command/Factory.php create mode 100644 other/cachetools/MemcacheAdmin/Library/Command/Interface.php create mode 100644 other/cachetools/MemcacheAdmin/Library/Command/Memcache.php create mode 100644 other/cachetools/MemcacheAdmin/Library/Command/Memcached.php create mode 100644 other/cachetools/MemcacheAdmin/Library/Command/Server.php create mode 100644 other/cachetools/MemcacheAdmin/Library/Configuration/Loader.php create mode 100644 other/cachetools/MemcacheAdmin/Library/Data/Error.php create mode 100644 other/cachetools/MemcacheAdmin/Library/HTML/Components.php create mode 100644 other/cachetools/MemcacheAdmin/Library/Loader.php create mode 100644 other/cachetools/MemcacheAdmin/Public/Images/635855.png create mode 100644 other/cachetools/MemcacheAdmin/Public/Images/b5463f.png create mode 100644 other/cachetools/MemcacheAdmin/Public/Scripts/Script.js create mode 100644 other/cachetools/MemcacheAdmin/Public/Styles/Style.css create mode 100644 other/cachetools/MemcacheAdmin/Temp/live_stats.12857559947a1920d61156abc05a60135aefe8bc67 create mode 100644 other/cachetools/MemcacheAdmin/View/Commands/Commands.tpl create mode 100644 other/cachetools/MemcacheAdmin/View/Configure/Configure.tpl create mode 100644 other/cachetools/MemcacheAdmin/View/Footer.tpl create mode 100644 other/cachetools/MemcacheAdmin/View/Header.tpl create mode 100644 other/cachetools/MemcacheAdmin/View/LiveStats/Frame.tpl create mode 100644 other/cachetools/MemcacheAdmin/View/LiveStats/Stats.tpl create mode 100644 other/cachetools/MemcacheAdmin/View/Stats/Error.tpl create mode 100644 other/cachetools/MemcacheAdmin/View/Stats/Items.tpl create mode 100644 other/cachetools/MemcacheAdmin/View/Stats/Slabs.tpl create mode 100644 other/cachetools/MemcacheAdmin/View/Stats/Stats.tpl create mode 100644 other/cachetools/MemcacheAdmin/commands.php create mode 100644 other/cachetools/MemcacheAdmin/configure.php create mode 100644 other/cachetools/MemcacheAdmin/index.php create mode 100644 other/cachetools/MemcacheAdmin/stats.php create mode 100644 other/cachetools/phpRedisAdmin/README.markdown create mode 100644 other/cachetools/phpRedisAdmin/common.inc.php create mode 100644 other/cachetools/phpRedisAdmin/config.inc.php create mode 100644 other/cachetools/phpRedisAdmin/css/common.css create mode 100644 other/cachetools/phpRedisAdmin/css/frame.css create mode 100644 other/cachetools/phpRedisAdmin/css/index.css create mode 100644 other/cachetools/phpRedisAdmin/delete.php create mode 100644 other/cachetools/phpRedisAdmin/edit.php create mode 100644 other/cachetools/phpRedisAdmin/export.php create mode 100644 other/cachetools/phpRedisAdmin/footer.inc.php create mode 100644 other/cachetools/phpRedisAdmin/functions.inc.php create mode 100644 other/cachetools/phpRedisAdmin/header.inc.php create mode 100644 other/cachetools/phpRedisAdmin/images/add.png create mode 100644 other/cachetools/phpRedisAdmin/images/delete.png create mode 100644 other/cachetools/phpRedisAdmin/images/edit.png create mode 100644 other/cachetools/phpRedisAdmin/images/export.png create mode 100644 other/cachetools/phpRedisAdmin/images/favicon.png create mode 100644 other/cachetools/phpRedisAdmin/images/folder-open.png create mode 100644 other/cachetools/phpRedisAdmin/images/import.png create mode 100644 other/cachetools/phpRedisAdmin/images/info.png create mode 100644 other/cachetools/phpRedisAdmin/images/logout.png create mode 100644 other/cachetools/phpRedisAdmin/images/reset.png create mode 100644 other/cachetools/phpRedisAdmin/images/save.png create mode 100644 other/cachetools/phpRedisAdmin/images/tree-folder-collapsed.gif create mode 100644 other/cachetools/phpRedisAdmin/images/tree-folder-expanded.gif create mode 100644 other/cachetools/phpRedisAdmin/images/tree-lastnode-collapsed.gif create mode 100644 other/cachetools/phpRedisAdmin/images/tree-lastnode-expanded.gif create mode 100644 other/cachetools/phpRedisAdmin/images/tree-lastnode.gif create mode 100644 other/cachetools/phpRedisAdmin/images/tree-node.gif create mode 100644 other/cachetools/phpRedisAdmin/images/tree-vline.gif create mode 100644 other/cachetools/phpRedisAdmin/import.php create mode 100644 other/cachetools/phpRedisAdmin/index.php create mode 100644 other/cachetools/phpRedisAdmin/info.php create mode 100644 other/cachetools/phpRedisAdmin/js/frame.js create mode 100644 other/cachetools/phpRedisAdmin/js/index.js create mode 100644 other/cachetools/phpRedisAdmin/login.inc.php create mode 100644 other/cachetools/phpRedisAdmin/logout.php create mode 100644 other/cachetools/phpRedisAdmin/overview.php create mode 100644 other/cachetools/phpRedisAdmin/page.inc.php create mode 100644 other/cachetools/phpRedisAdmin/rename.php create mode 100644 other/cachetools/phpRedisAdmin/save.php create mode 100644 other/cachetools/phpRedisAdmin/ttl.php create mode 100644 other/cachetools/phpRedisAdmin/view.php diff --git a/other/cachetools/MemcacheAdmin/Config/Memcache.php b/other/cachetools/MemcacheAdmin/Config/Memcache.php new file mode 100644 index 000000000..14a4fa9cf --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Config/Memcache.php @@ -0,0 +1,28 @@ + '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', + ), + ), + ), +); \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/Library/Analysis.php b/other/cachetools/MemcacheAdmin/Library/Analysis.php new file mode 100644 index 000000000..5d5689bcd --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Library/Analysis.php @@ -0,0 +1,332 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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); + } +} \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/Library/Command/Factory.php b/other/cachetools/MemcacheAdmin/Library/Command/Factory.php new file mode 100644 index 000000000..a94d930d2 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Library/Command/Factory.php @@ -0,0 +1,111 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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]; + } +} \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/Library/Command/Interface.php b/other/cachetools/MemcacheAdmin/Library/Command/Interface.php new file mode 100644 index 000000000..cf080c903 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Library/Command/Interface.php @@ -0,0 +1,139 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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); +} \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/Library/Command/Memcache.php b/other/cachetools/MemcacheAdmin/Library/Command/Memcache.php new file mode 100644 index 000000000..5808cb042 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Library/Command/Memcache.php @@ -0,0 +1,257 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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'); + } +} \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/Library/Command/Memcached.php b/other/cachetools/MemcacheAdmin/Library/Command/Memcached.php new file mode 100644 index 000000000..2493b1740 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Library/Command/Memcached.php @@ -0,0 +1,226 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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'); + } +} \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/Library/Command/Server.php b/other/cachetools/MemcacheAdmin/Library/Command/Server.php new file mode 100644 index 000000000..7d44f2076 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Library/Command/Server.php @@ -0,0 +1,443 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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; + } +} diff --git a/other/cachetools/MemcacheAdmin/Library/Configuration/Loader.php b/other/cachetools/MemcacheAdmin/Library/Configuration/Loader.php new file mode 100644 index 000000000..9e2a91baf --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Library/Configuration/Loader.php @@ -0,0 +1,187 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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, '<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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); + } +} \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/Library/HTML/Components.php b/other/cachetools/MemcacheAdmin/Library/HTML/Components.php new file mode 100644 index 000000000..a94597aaf --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Library/HTML/Components.php @@ -0,0 +1,147 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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 = ''; + } + + /** + * 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 = ''; + } + + /** + * 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 = 'Server ' . $hostname . ':' . $port . "\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 ''; + } + + /** + * 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"'; + } + } +} \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/Library/Loader.php b/other/cachetools/MemcacheAdmin/Library/Loader.php new file mode 100644 index 000000000..24b766374 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Library/Loader.php @@ -0,0 +1,9 @@ +#bl|xBwkK=TTNrtypoxcVxUo)DWcGJI=QK6 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 Y7LRqGgu%*(^b literal 0 HcmV?d00001 diff --git a/other/cachetools/MemcacheAdmin/Public/Images/b5463f.png b/other/cachetools/MemcacheAdmin/Public/Images/b5463f.png new file mode 100644 index 0000000000000000000000000000000000000000..426d2b7abc401eac9fefa549a4ffa2a7940562d5 GIT binary patch literal 3115 zcmb7GX*iqd8vZb?E>w+nx+v{jmZ_pTrS@35AXQ6Kqa>$EO%a5~z9bEqX;l?Txn5Z}7I3yw5@Gt7NFBU|t5D0IuQD<9 zL-;pKX8aIWo2iZOUQIi$*1a(?$|}QrOi#gqQ!flkb6Y*96xfhnL=wn!G>b9yQjj}yxHGe)tGch6s7hKJ>l7Zf+UZfXTB{c?PQ;Bg zaQjNwR{4i3K|>&qBD2Hk#h{fB7taq>Bqbiw5Pg_%bvNMVF6fmM%*sq$49L0d8%e34 zQo=AusCNYs+9s{egMIXXWciZpZyv7^<8Q5R96CUyDBt=SbYu_4;iwoduk&fQ()Y29 zDF0@L^q$HH);; zn3aRFFf|M0Pfk7>TaC)wws2B+5+gw7i~2SnhsIM!7g~a}^TX?<_*+*#?0qPZs7Kd( zxf>vkcX;HT=S9?ey&X~XARIHurAumU3_TrX*K$N4a6w%53&@0qV#LE zYaq}Oc>~={rRHCi@xUBU>j+>LjR(5B6%-xLC~pH0R}~bi^1PUKzAuaHFQtHK!%Jb0 z)}d+FN-A0BX~QyXY*3wxXsAjZi%EDnSwquHa;dLv?3ep6%X5PzZPSya#f&dDU|Ozs zPS3(`dq*!3bZL^c-W4Z9dcR$p8s$ca-y@T{{u6CJf;f{5=h<||dfck491eCj`KUpD z7WaX`X~cx?UmwW{NbXv?=*mw;vHjY#+h8W2syk7#3s@#|;oh#@K%kw{cX)Mq`7nsx zQJ~4XU}b7!(kR4Hl6VZFF`Z7fTZY6n_6Z9P*QJ-4cyn}=8Ga2;Bc9VKqQO6E5nf4_ zF|_EncPzARsu!(atVVX1exj;C`(g}uQQLVMJ1uARe+{>bS*Nt;lk(!Rb?e)F{wYsd z+NAg$o<@{sHeOdy443UEC~N;YO#ChIb3s<%9zi^jG{YP}KPJe!#6-I?TzqXiXx4gpK?*`k5QOAx?edhKb&~f70(>>*6tb z*3BP5w7nI5g^KuXo8+%0s2%}AcWvJdXpbl;HW6(cfcR+nR!@Vt zRsjSv6kA_XEcD6qYzG~FHaEjciloXGAWWYd0N%pUHtba~qv`2wLl3a8$EEAGu4`UL z9}Z-jxOIG7e(D*?$W(JhXhTGVXE?woU$8PiAEF678RNHH=lug`KdwY~2OA)!c~<8( zj%7!+d&q7nh3_i)l&g8VTOe8F`!D>un!ax+BPAZ#U%EcsAM1U&WC8WQAfU@*OjNj# z4l0ydB={^vT?N-ApG)Y6DYh(jwMxxx6yyvXtQfcqn1|wgnBVH1u;VxWYrXjw2X61`R9#I z^{}ag-0S+C75r`e)tX%pvNg5zvkHRT@t6Tuj5DL=CeopimSqE^f_B*L`>OpABVo3g zV52AThJWhko`46WdgtA^h0&yqLN#rFqPb$I-^jhkDgQ*C5q}cCZ|g*7 zB8n~95nbo6y(d+ivVu|@S8A}?)EzLOB8(D=N=v?XNAI?;9 z?I&aez-#Xcg18pPy6&2OCd6s>A_dj6g+D)+PDsRJe_NC%p_voxiDnhZUH+10Tb`3Y z<9^F?H)2?llQc`h?VHRpNv^bhj*>dz__czmC)5(%!y^`$(88FRqG+=x+&5=<59|f4 z3`t^ItQlPB;^Yte>+@c=;en-%FNGM9m4qPVHHc6A4MD|k$C*Ze*7qkE9^?XqS1=#tJR zkNGX|*-ci%!3KK#y*SBUs@vs9RT8KxZ0op0obk?}dA+~1Xx93b{%AE!M9^z#cU`6F zkG2#1QEKP|8NIdYnwhQkkVFvMdxTYCJnR&fHI9-RHQ1VK`PHbNmr@c5<0xxmMEvx0 z5Qrp(CWu$MH0jrJEGYDSlu>Ux=LKTM6`e2^>u^vt#;=yz6@VgXRlg5SnRG)X!=#P% zfyyx*w|i=kssQKqnEY=b=`5!~Wm?-8*$XmcxH$6y79DZA7g&o|Zq{48l5%WRrr`%D nvA8c!IIdCsPwaGPlnwg~jYz1mPhz>eQ2>0-{cOeQtH1vnD9R{P literal 0 HcmV?d00001 diff --git a/other/cachetools/MemcacheAdmin/Public/Scripts/Script.js b/other/cachetools/MemcacheAdmin/Public/Scripts/Script.js new file mode 100644 index 000000000..139ec99ec --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Public/Scripts/Script.js @@ -0,0 +1,29 @@ +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='
Cluster '+''+'
';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='
'+' '+' '+'Delete'+'
';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;}}} \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/Public/Styles/Style.css b/other/cachetools/MemcacheAdmin/Public/Styles/Style.css new file mode 100644 index 000000000..bbfa49fef --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Public/Styles/Style.css @@ -0,0 +1 @@ +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} \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/Temp/live_stats.12857559947a1920d61156abc05a60135aefe8bc67 b/other/cachetools/MemcacheAdmin/Temp/live_stats.12857559947a1920d61156abc05a60135aefe8bc67 new file mode 100644 index 000000000..ed948be0d --- /dev/null +++ b/other/cachetools/MemcacheAdmin/Temp/live_stats.12857559947a1920d61156abc05a60135aefe8bc67 @@ -0,0 +1 @@ +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";}} \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/View/Commands/Commands.tpl b/other/cachetools/MemcacheAdmin/View/Commands/Commands.tpl new file mode 100644 index 000000000..044b48545 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/View/Commands/Commands.tpl @@ -0,0 +1,162 @@ +
+
Console
+
+

+        
+
+ + + + +
+ +
Execute predefined Command
+
+ + + + + +
+
+
+ Execute command on one or all memcached servers
+
+
+
+ Command + + + +
+ + + + +
+ Server + + + +
+
+ API + + get('get_api'), 'request_api'); ?> + +
+
+
+ +
+
+
+ +
+
+
+ +
Execute Telnet Commands
+
+ + + + + +
+
+ Execute telnet command on one or all memcached servers
+
+
+
+ +
+
+ Server + + + +
+
+
+ +
+
+ You can use this thing to execute any telnet command to any memcached server +
+ It will connect to the server, execute the command and return it in the console +
+
+
+
+ For more informations about memcached commands, see memcached protocol + here +
+
+ +
Search Key
+
+ + + + + +
+
+ Search for a key on one or all memcached servers
+
+
+
+ Key + + + +
+
+ Server + + + +
+
+
+ +
+
+ Warning !
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. +
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. +
+
You can also use a PCRE regular expression +
+
+
\ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/View/Configure/Configure.tpl b/other/cachetools/MemcacheAdmin/View/Configure/Configure.tpl new file mode 100644 index 000000000..9da6d0c8a --- /dev/null +++ b/other/cachetools/MemcacheAdmin/View/Configure/Configure.tpl @@ -0,0 +1,161 @@ +
+
+ +
Commands Configuration
+
+
+
+ Memcached commands API used by phpMemCacheAdmin
+
+
+
+ Stats + get('stats_api'), 'stats_api'); ?> +
+
+ Slabs + get('slabs_api'), 'slabs_api'); ?> +
+
+ Items + get('items_api'), 'items_api'); ?> +
+
+ Get + get('get_api'), 'get_api'); ?> +
+
+ Set + get('set_api'), 'set_api'); ?> +
+
+ Delete + get('delete_api'), 'delete_api'); ?> +
+
+ Flush All + get('flush_all_api'), 'flush_all_api'); ?> +
+
+
+ +
+
+
+ +
Live Stats Configuration
+
+
+
+ Alert & refresh rate for Live Stats
+
+
+
+ Refresh Rate in sec + +
+
+ Memory Alert + +
+
+ Hit Rate Alert + +
+
+ Eviction Alert + +
+
+ Temp Path + +
+
+
+ +
+
+
+ +
Miscellaneous Configuration
+
+
+
+ Server connection timeout & miscellaneous
+
+
+
+ Timeout in sec + +
+
+ Max Items + +
+
+
+ +
+
+
+ +
+
+
Server List
+
+
+
+ Servers list used by phpMemCacheAdmin
+
+
+get('servers') as $cluster => $servers) + { + $cluster_id++; ?> +
+
+ Cluster + +
+
+ + + Delete +
+
+ + +
+
+ +
+
+
+ Add New Cluster + +
+
+
+ + +
+
+ For more information about configuring phpMemcachedAdmin, see installation guide + here +
+
+
+
\ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/View/Footer.tpl b/other/cachetools/MemcacheAdmin/View/Footer.tpl new file mode 100644 index 000000000..3ddfec358 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/View/Footer.tpl @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/View/Header.tpl b/other/cachetools/MemcacheAdmin/View/Header.tpl new file mode 100644 index 000000000..c52eededa --- /dev/null +++ b/other/cachetools/MemcacheAdmin/View/Header.tpl @@ -0,0 +1,62 @@ +'; ?> + + + + phpMemcachedAdmin <?php echo CURRENT_VERSION; ?> + + + + +
+
phpMemcachedAdmin
+
+ + Live Stats | + + See Live Stats | + + Actually seeing + + See Stats for + + | + + Executing Commands on Servers + + Execute Commands on Servers + + | + + Editing Configuration + + Edit Configuration + +
+ + diff --git a/other/cachetools/MemcacheAdmin/View/LiveStats/Frame.tpl b/other/cachetools/MemcacheAdmin/View/LiveStats/Frame.tpl new file mode 100644 index 000000000..bb0fbe5f8 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/View/LiveStats/Frame.tpl @@ -0,0 +1,70 @@ + + +
+
Live Stats
+ $_ini->get('refresh_rate')) + { ?> +
+ Connections errors were discovered, to prevent any problem, refresh rate was increased by + get('refresh_rate')); ?> seconds. +
+ + +
+
+ Actually looking at stats +
+
+        Loading live stats, please wait ~get('refresh_rate')); ?> seconds ...
+        
+
+
+
+ SIZE + Total cache size on this server +
+
+ %MEM + Percentage of total cache size used on this server +
+
+ %HIT + Global hit percent on this server : get_hits / (get_hits + get_misses) +
+
+ TIME + Time taken to connect to the server and proceed the request, high value can indicate a latency or server problem +
+
+ REQ/s + Total request per second (get, set, delete, incr, ...) issued to this server +
+
+ CONN + Current connections, monitor that this number doesn't come too close to the server max connection setting +
+
+ GET/s, SET/s, DEL/s + Get, set or delete commands per second issued to this server +
+
+ EVI/s + Number of times an item which had an explicit expire time set had to be evicted before it expired +
+
+ READ/s + Total number of bytes read by this server from network +
+
+ WRITE/s + Total number of bytes sent by this server to network +
+
+
diff --git a/other/cachetools/MemcacheAdmin/View/LiveStats/Stats.tpl b/other/cachetools/MemcacheAdmin/View/LiveStats/Stats.tpl new file mode 100644 index 000000000..14bc9dd6b --- /dev/null +++ b/other/cachetools/MemcacheAdmin/View/LiveStats/Stats.tpl @@ -0,0 +1,87 @@ +get('refresh_rate') . ' sec)' . EOL . EOL; + +# Table header +echo '' . 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') . '' . EOL . '
'; + +# 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']), ' ') . '' . sprintf('%.1f', $data['bytes_percent']) . ''; + } + 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']), ' ') . '' . sprintf('%.1f', $data['get_hits_percent']) . ''; + } + 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'])), ' ') . '' . Library_Analysis::valueResize($data['eviction_rate']) . ''; + } + 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, ' ') . 'An error has occured when retreiving or calculating stats'; + } + + # End of Line + echo EOL . '
'; +} \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/View/Stats/Error.tpl b/other/cachetools/MemcacheAdmin/View/Stats/Error.tpl new file mode 100644 index 000000000..76aef8860 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/View/Stats/Error.tpl @@ -0,0 +1,58 @@ + +
+ cluster($_GET['server'])) ? 'All servers from Cluster ' . $_GET['server'] : 'Server ' . $_GET['server'], ' did not respond !'; + } + # All servers stats + else + { + echo 'Servers did not respond !'; + } ?> +
+
+ Error message +
+ +
+
+ Please check above error message, your configuration or your server status and retry +
+ +
+ No slabs used in this server ! +
+
+ Error message +
+ Maybe this server is not used, check your configuration or your server status and retry +
+ +
+ No item in this slab ! +
+
+ Error message +
+ This slab is allocated, but is empty +
+
+ Go back to Server Slabs +
+ +
Result
+
+ $result) + { ?> +
+ +
+ +
+ Items in Slab , only showing first get('max_item_dump'); ?> items + Back to Server Slabs +
+
+ $data) +{ + # Checking if first item + if($notFirst) { echo '
'; } + ?> + + 70) ? substr($key, 0, 70) . '[..]' : $key); ?> + + + Size : Bytes, + Expiration : + + + +
\ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/View/Stats/Slabs.tpl b/other/cachetools/MemcacheAdmin/View/Stats/Slabs.tpl new file mode 100644 index 000000000..f0ba9d2b0 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/View/Stats/Slabs.tpl @@ -0,0 +1,126 @@ +
+
Slabs Stats
+
+
+ Slabs Used + +
+
+ Memory Used + Bytes +
+
+ Wasted + Bytes +
+
+
+ + + +
+
+ For more informations about memcached slabs stats, see memcached protocol + here +
+
+ + + + $slab) +{ + # If Slab is Used + if(is_numeric($id)) + { + # Making a new line + if($actualSlab >= 4) + { +?> + + + + + +'; +} +?> + +
0) { echo 'style="padding-left:9px;"'; } ?> valign="top"> +
Slab Stats + See Slab Items +
+
+
+ Chunk Size + Bytes +
+
+ Used Chunk + + [ %] +
+
+ Total Chunk + +
+
+ Total Page + +
+
+ Wasted + Bytes +
+
+ Hits + Request/sec +
+ 0) +{ ?> +
+ Evicted + +
+ + +
+ Slab is allocated but empty +
+ +
+
\ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/View/Stats/Stats.tpl b/other/cachetools/MemcacheAdmin/View/Stats/Stats.tpl new file mode 100644 index 000000000..bfa79a6dc --- /dev/null +++ b/other/cachetools/MemcacheAdmin/View/Stats/Stats.tpl @@ -0,0 +1,356 @@ +
+
Get Stats
+
+
+ Hits + + [%] +
+
+ Miss + + [%] +
+
+ Rate + Request/sec +
+
+ +
Set Stats
+
+
+ Total + +
+
+ Rate + Request/sec +
+
+ +
Delete Stats
+
+
+ Hits + + [%] +
+
+ Miss + + [%] +
+
+ Rate + +
+
+ +
Cas Stats
+
+
+ Hits + + [%] +
+
+ Miss + + [%] +
+
+ Bad Value + + [%] +
+
+ Rate + +
+
+ +
Increment Stats
+
+
+ Hits + + [%] +
+
+ Miss + + [%] +
+
+ Rate + +
+
+ +
Decrement Stats
+
+
+ Hits + + [%] +
+
+ Miss + + [%] +
+
+ Rate + +
+
+ +
Flush Stats
+
+
+ Total + +
+
+ Rate + +
+
+
+ +
+server($_GET['server']))) +{ ?> + + +
server($_GET['server'])) ? 'Server' : 'Cluster'; ?> Stats
+
+server($_GET['server']))) +{ ?> +
+ Uptime + +
+
+ Memcached + Version +
+ +
+ Curr Connections + +
+
+ Total Connections + +
+
+ Max Connections Errors + +
+
+ Current Items + +
+
+ Total Items + +
+server($_GET['server']))) +{ ?> +
+ Oldest Item + +
+ +
+ +
Eviction & Reclaimed Stats
+
+
+ Items Eviction + +
+
+ Rate + Eviction/sec +
+
+ Reclaimed + +
+
+ Rate + +
+
+ +server($_GET['server']))) +{ ?> +
Server Configuration
+
+
+ Accepting Connections + +
+
+ Max Bytes + +
+
+ Max Connection + +
+
+ TCP/UDP Port + +
+
+ Listen Interface + +
+
+ Evictions + +
+
+ Path to Domain Socket + +
+
+ Domain Socket Umask + +
+
+ Chunk Size + +
+
+ Chunk Growth Factor + +
+
+ Max Threads + +
+
+ Detail Enabled + +
+
+ Max IO Ops/Event + +
+
+ CAS Enabled + +
+
+ TCP Listen Backlog + +
+
+ SASL Auth + +
+
+cluster($_GET['server']))) +{ ?> +
Cluster Servers List
+
+ +
+ + See Server Stats +
+ +
+
+ +
+ +
+ +
+
Cache Size Stats
+
+
+ Used + Bytes +
+
+ Total + Bytes +
+
+ Wasted + Bytes +
+ +
+ +
Cache Size Graphic
+
+
+ Cache Size by GoogleCharts +
+
+ +
Hit & Miss Rate Graphic
+
+
+ Cache Hit & Miss Rate by GoogleChart +
+
+ +
Network Stats
+
+
+ Bytes Read + Bytes +
+
+ Bytes Written + Bytes +
+
+
diff --git a/other/cachetools/MemcacheAdmin/commands.php b/other/cachetools/MemcacheAdmin/commands.php new file mode 100644 index 000000000..53a14a4f8 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/commands.php @@ -0,0 +1,276 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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(); \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/configure.php b/other/cachetools/MemcacheAdmin/configure.php new file mode 100644 index 000000000..b0f9f70f9 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/configure.php @@ -0,0 +1,127 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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'; \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/index.php b/other/cachetools/MemcacheAdmin/index.php new file mode 100644 index 000000000..719fa8765 --- /dev/null +++ b/other/cachetools/MemcacheAdmin/index.php @@ -0,0 +1,176 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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'; \ No newline at end of file diff --git a/other/cachetools/MemcacheAdmin/stats.php b/other/cachetools/MemcacheAdmin/stats.php new file mode 100644 index 000000000..3ce90511a --- /dev/null +++ b/other/cachetools/MemcacheAdmin/stats.php @@ -0,0 +1,171 @@ +<)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> + * + * 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; +} diff --git a/other/cachetools/phpRedisAdmin/README.markdown b/other/cachetools/phpRedisAdmin/README.markdown new file mode 100644 index 000000000..daec73c04 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/README.markdown @@ -0,0 +1,39 @@ +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) + diff --git a/other/cachetools/phpRedisAdmin/common.inc.php b/other/cachetools/phpRedisAdmin/common.inc.php new file mode 100644 index 000000000..80f47bb0d --- /dev/null +++ b/other/cachetools/phpRedisAdmin/common.inc.php @@ -0,0 +1,115 @@ +https://github.com/nicolasff/phpredis'); +} + + + + +// 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'].')'); + } +} + +?> diff --git a/other/cachetools/phpRedisAdmin/config.inc.php b/other/cachetools/phpRedisAdmin/config.inc.php new file mode 100644 index 000000000..a0fdf4d0a --- /dev/null +++ b/other/cachetools/phpRedisAdmin/config.inc.php @@ -0,0 +1,56 @@ + 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 +); + +?> diff --git a/other/cachetools/phpRedisAdmin/css/common.css b/other/cachetools/phpRedisAdmin/css/common.css new file mode 100644 index 000000000..942c49a35 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/css/common.css @@ -0,0 +1,53 @@ + +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; +} + diff --git a/other/cachetools/phpRedisAdmin/css/frame.css b/other/cachetools/phpRedisAdmin/css/frame.css new file mode 100644 index 000000000..c467b85cf --- /dev/null +++ b/other/cachetools/phpRedisAdmin/css/frame.css @@ -0,0 +1,56 @@ + +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; +} + diff --git a/other/cachetools/phpRedisAdmin/css/index.css b/other/cachetools/phpRedisAdmin/css/index.css new file mode 100644 index 000000000..b562ccf47 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/css/index.css @@ -0,0 +1,122 @@ + +#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%; +} + diff --git a/other/cachetools/phpRedisAdmin/delete.php b/other/cachetools/phpRedisAdmin/delete.php new file mode 100644 index 000000000..e7a96caba --- /dev/null +++ b/other/cachetools/phpRedisAdmin/delete.php @@ -0,0 +1,63 @@ +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; +} + +?> diff --git a/other/cachetools/phpRedisAdmin/edit.php b/other/cachetools/phpRedisAdmin/edit.php new file mode 100644 index 000000000..dbc331574 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/edit.php @@ -0,0 +1,186 @@ + $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'; + + ?> + + 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'; + +?> +

+
+ +

+ + +

+ +

+ +> +

+ +

+ +> +

+ +

+ +> empty to append, -1 to prepend +

+ +

+ +> +

+ +

+ + +

+ + + +

+ +

+ +
+ diff --git a/other/cachetools/phpRedisAdmin/export.php b/other/cachetools/phpRedisAdmin/export.php new file mode 100644 index 000000000..01f8541c8 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/export.php @@ -0,0 +1,197 @@ +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'; + +?> +

Export

+ +
+ +

+ + +

+ +

+ +

+ +
+ diff --git a/other/cachetools/phpRedisAdmin/footer.inc.php b/other/cachetools/phpRedisAdmin/footer.inc.php new file mode 100644 index 000000000..11a09caf8 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/footer.inc.php @@ -0,0 +1,3 @@ + + + diff --git a/other/cachetools/phpRedisAdmin/functions.inc.php b/other/cachetools/phpRedisAdmin/functions.inc.php new file mode 100644 index 000000000..388f535db --- /dev/null +++ b/other/cachetools/phpRedisAdmin/functions.inc.php @@ -0,0 +1,66 @@ += 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; +} + diff --git a/other/cachetools/phpRedisAdmin/header.inc.php b/other/cachetools/phpRedisAdmin/header.inc.php new file mode 100644 index 000000000..1d09a8889 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/header.inc.php @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + +<?php echo format_html($server['host'])?> - phpRedisAdmin + + + + + + + + + + + + + + + diff --git a/other/cachetools/phpRedisAdmin/images/add.png b/other/cachetools/phpRedisAdmin/images/add.png new file mode 100644 index 0000000000000000000000000000000000000000..db594c8215f200c679ef35e4dc889692b2903533 GIT binary patch literal 355 zcmV-p0i6DcP)Px$9Z5t%R5;7ElD|p=K@i5joZ%29MG8AX?CsV%;sa=DDcG3a#wW1IBbZ7^mtL?D zMB8lP8z_Q}Ma&7ecei`cbn5-b#!p7j4>ctoSE+IbyWF22m(AkKbC&r2x~2@wEzIp>q#_09LE3v>ntcf zISj+1tQkPx-QOPx$6iGxuR5;7ckG~5+VHAe%zo1xcR%Njnl|dP-A{MJ|VP~)~uuzm=iKHxw3?`Yb zGAPO_gT*R?<2_$K(Y=>UoO=5@=XuV#T}An;>MM#5(fIv_iRuC%8l}_3Z}&-*?3_sG z*rVD2*Hntuem`AQmAFTI_h`phOt5_@B$)0%6Ji746pz!)?WRLGOx$xefqGFK5& z3GxtM9bj38XT?tk@(>CTCs;5Fv%J}n8~~!tArWlo`q<-u=Jxx;yr8O;X0U^E=8U?i2(Md|&SQe7@&*&J~0+E^kA{egCUR zsinqy56|ifQ*Z7(vl$=nDT6%-ym;`Jl~oJ2aclF0-6lEb=Wtrw125Gd{dY0!6ESV9 z!_Ox-!3sVJcH6j=&1R9ygcBS6*KrVOhijx3hUZT)W~iEC1s4Qr*EH?KWFszY zn3x=GhvvJDsJRHst;M^+wkwzTy%v35&;*5|N+Q<#%8%q*T>kapV#eQ6RCfHT9yiiE ziZ0tB8v7a!!fjlRS(w~$nF_A{_p)x6h;%v)MN#reg+zYm{qTEe-WyzA?J9-GVTbP5 zh~J%uC#GZ`Iml!h`$&#|VRC0Fwj*mGR#)I$nCBCuJ zSY3f*ZkBJ#$piw+UW8^kp?Yfaa)QaUM+~vLg4u5~P*oL)cnk{`6C5AkV!&9BKwl+d zn|}VCLJYCGg6Xf5hvTzTUN;$F?d`_Oq6@KTBp=!%W^$syBYw7+rOi-~1DQ;wU}%pR rVs!-;^H4L3WE~sDX(5JK;k?&B=dLZ_Er>C%00000NkvXXu0mjfApHMc literal 0 HcmV?d00001 diff --git a/other/cachetools/phpRedisAdmin/images/export.png b/other/cachetools/phpRedisAdmin/images/export.png new file mode 100644 index 0000000000000000000000000000000000000000..79a7ce538dc6d33f18b99347c1e2171f774c6dbf GIT binary patch literal 640 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 Y1?(z5m_dDDVgLXD07*qoM6N<$g7X~Z00000 literal 0 HcmV?d00001 diff --git a/other/cachetools/phpRedisAdmin/images/import.png b/other/cachetools/phpRedisAdmin/images/import.png new file mode 100644 index 0000000000000000000000000000000000000000..17ac67b1b943181a3b93cd625aa12bcfca74debc GIT binary patch literal 692 zcmV;l0!#ggP)fjXn3S&e~( zAR(RGSOhke5w!`pDJ4}Jiy$m)lU{HGl3x%AY$2qxGm|2%MIPqST4*hakI|hqJ~NM; zJL;gDEpp(@IrnhxcjtWfyIek>$HtzJAL9S)XRTIKSt4#L%jNR$;^N}XbUMX+K8InL z7z}<>Zo%i1pePE0!5~7RAd1DOr`vsEtJT8M(UG$-3I{bQ-#TNq{TZRI@p2?O6M+u@Ulv!Qif{s>ozAPH{LK z;`sO>K7MM_MjvgmH=9kz_W(GKyWi<_UhNhw%ffg(M)*KMx7)?9ZX1C>faVXO-EM!N zmhanMP7s7=6z{P`xm-SHF`LaI61k1fU%o*K96%xB0*W6YB9Re!RxF&>>-Ep`UpL(hcU&;^a_8BB5}eR65yJVxRs%pHCrrdH4eo5vbr%F8lb!^D`#nuMPlH9Wx@&W~b@8 z?w;JEtJGIhcx4Z6*+KB44O#Yr4squYNkm&2i#NX;`yVCJ0fGzA@Aubjwk?aI=!nJR z@i-$0UJ3Hz3cQzdMv!F*g2*$ax(~t~fjH1&vDmq3nheYl8FMoB0nhU++AJsWXPKC{iI%^yJ^5_25;nUPUPA#k+Vb{-Am~xKxcYY2mAK|0 zN%+F#H!#XO24ue246v__Tc&pB{JFkDe&9%#W2bGA;Lc71FaGeZeEPaJ5rpv*zV6+D z4EErhYuvwC93EwqIrSidKO3H$a9uZ>KatB09MAQE(iSaX| zezoTK{tkGa2h)!VQo{Cq3?UAjYgY$H&9pKpn05e0iz8=y3cg=+Fb*ILLx`fNm71`H zPs}yK(8&+v3W8~skWg~5x7+EeR{R#k7=yy~X`qyWrfWb6m3~!Ic}a)51jC2VnrFaB zpQ?aGDFwn8R(S~+V|f0spZ^d9w;q&0(bCOgx#E~uf@vQjBZv@!!UlnAtt+u0!v38o!@l2Umq3~;16YRU#xy6O^k90#ffCD6fC}vK&W^$H>UefIKPwa>Q#?k3HpO z#E^s)Nb0zkUyK`k?h;r3Zuk|h4}jEZWZ3J-?BKi(bnSLC!2h&=0t^7>r5@pTaNc16 O0000J!9Xa1)PwdQF`-C| z*f!bCW|Cd!H=ErirNx1_GyB_lZ{EC_mEJyt+azF(ch4;g8Ck~vT7%EqQD!fK=naIn z*EZ9!$jVLi;NUCt2QT6C`D}4Xg3MJN{CtxabrN{(^M|%qH*d!R%h%O*yNz#qdk6%V z1X)$p1+vHE5%^)+E6b*d%>74CxB92L+G@4X>2#1xCSlGdTtuevlz%74^k9sk+wCGA zk0Tn5!s45w`gwA{-^XAu5aY=d0*X+YP7w?S`KqQMQ!mudt*q<1fFmF>;9NnViSq(9 zfoi>84~Aj5(H9B@l*?s&XUkuX$L5&>vPPlNc-{fk^ZC3hFdPn%%jHlk7MuKaMGKrva7XFgGUTfzAwa8seDws$MD#3!*%nf% z6cj}fV)c3*)oNAL)_v?Aj~_yS2zR$u;rIK6W#PcI9XMnXqo5;^2oi||m=mJofSNfw zd`g>|wzj7B4Ya5#(;4GUy~L#Fok)P}nSP16vI#c*=q0 zN56VnbN_K>9Lf4ghfJ5UV0D=Dr@3)-X_|HCMq~EdAmC^ zZ(nwI45bvEVkSO92#?|FZ=ls`z2y}Qhr?TjC-#rcW|I)GUH5vuMi2y4tyXC|ol?8~ z*j%sII@s?&YveUrE|=e<(MVul_IHsI2q`6kG@H#dhT)3Gp?1u-Yn4jn!t=Za*F5Zg z0R)f}h9Q+oC5?*(2&E2U4#OJ8*eq4BBRGrWnCA02mCI#~QYum^3A=7rqm+@3As00n zf+&i3hXwh*uNOL<`@)k)?mq&sI*xPH)fFmmU6<^7eQ)vCcua%AAYZ|yZIevo6&iB# z6qryTIk3I^BC~$az|0VU6$GmT1WJglf((I$cOcmh5eUm7j|vojvM_QnurTO=RDjenFk5?gZF={1uZH+q zp6IoCU%eFi9t-hgSh1vWEy;OtNH^j3>IL&(bRT26cVK(g$~rZnmxoUlI80U(QCh3Q Hz+epkvb!>V literal 0 HcmV?d00001 diff --git a/other/cachetools/phpRedisAdmin/images/tree-folder-expanded.gif b/other/cachetools/phpRedisAdmin/images/tree-folder-expanded.gif new file mode 100644 index 0000000000000000000000000000000000000000..682130a403591e0f257ea396141df845bf28d7a9 GIT binary patch literal 114 zcmZ?wbhEHbp-5efv6Hg<>b6!jg F)&K*eBkuqJ literal 0 HcmV?d00001 diff --git a/other/cachetools/phpRedisAdmin/images/tree-lastnode-collapsed.gif b/other/cachetools/phpRedisAdmin/images/tree-lastnode-collapsed.gif new file mode 100644 index 0000000000000000000000000000000000000000..0d4e21d36f6538acd615efdd35723556e31aef8c GIT binary patch literal 109 zcmZ?wbhEHb!!TcB9$5`$i*q*hrPE9CtA_Idp06E7Z Ag#Z8m literal 0 HcmV?d00001 diff --git a/other/cachetools/phpRedisAdmin/images/tree-lastnode-expanded.gif b/other/cachetools/phpRedisAdmin/images/tree-lastnode-expanded.gif new file mode 100644 index 0000000000000000000000000000000000000000..f1cd23d60aa46a1a6d3ee0a375b440880da7a305 GIT binary patch literal 105 zcmZ?wbhEHbp7$<`@0KcpuAOHXW literal 0 HcmV?d00001 diff --git a/other/cachetools/phpRedisAdmin/images/tree-lastnode.gif b/other/cachetools/phpRedisAdmin/images/tree-lastnode.gif new file mode 100644 index 0000000000000000000000000000000000000000..238e38291a403c99e65004a7fca1e52751ff48b1 GIT binary patch literal 64 zcmZ?wbhEHb{z1B2pE7Dg@xMg|=qn*k)lz$D(oynNQ~w|qSvUfF3^ R`s`y8<(Q|a1u!sJ0|2-w4=(@! literal 0 HcmV?d00001 diff --git a/other/cachetools/phpRedisAdmin/images/tree-node.gif b/other/cachetools/phpRedisAdmin/images/tree-node.gif new file mode 100644 index 0000000000000000000000000000000000000000..2bfed48d2799efd36fd742efc50caefc72277ca5 GIT binary patch literal 74 zcmZ?wbhEHb{z1B2pE7Dg@xMg|=qn*k)lz@*s2ynNQ~w|qSvUfF3^ b`s`y8<(Q{DGl^50k@jZyu`p>pRt9STg)kI? literal 0 HcmV?d00001 diff --git a/other/cachetools/phpRedisAdmin/images/tree-vline.gif b/other/cachetools/phpRedisAdmin/images/tree-vline.gif new file mode 100644 index 0000000000000000000000000000000000000000..9793ee3afa0995174d7633a61641d60d677695bd GIT binary patch literal 44 vcmZ?wbhEHbWMyDvXkcVmvv>{z1B2pE7Dg_hfDVw&0Fq%~V(wvPWv~VSvabe9 literal 0 HcmV?d00001 diff --git a/other/cachetools/phpRedisAdmin/import.php b/other/cachetools/phpRedisAdmin/import.php new file mode 100644 index 000000000..dc8bebccb --- /dev/null +++ b/other/cachetools/phpRedisAdmin/import.php @@ -0,0 +1,122 @@ +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'; + + ?> + + +

Import

+
+ +

+ + +

+ +

+ +

+ +
+ diff --git a/other/cachetools/phpRedisAdmin/index.php b/other/cachetools/phpRedisAdmin/index.php new file mode 100644 index 000000000..001b0d306 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/index.php @@ -0,0 +1,205 @@ +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; + } + } + + + ?> + > + () + + 0) { + ?> +
  • +
     () + [X] +
      + $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)); + } + + ?> +
    +
  • + + + diff --git a/other/cachetools/phpRedisAdmin/info.php b/other/cachetools/phpRedisAdmin/info.php new file mode 100644 index 000000000..69c5338f9 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/info.php @@ -0,0 +1,60 @@ +resetStat(); + + header('Location: info.php'); + die; +} + + + +// Fetch the info +$info = $redis->info(); +$alt = false; + + + + +$page['css'][] = 'frame'; +$page['js'][] = 'frame'; + +require 'header.inc.php'; + +?> +

    Info

    + + +

    +Reset usage statistics +

    + + + + + $value) { + if ($key == 'allocation_stats') { // This key is very long to split it into multiple lines + $value = str_replace(',', ",\n", $value); + } + + ?> + > + +
    Key
    Value
    + diff --git a/other/cachetools/phpRedisAdmin/js/frame.js b/other/cachetools/phpRedisAdmin/js/frame.js new file mode 100644 index 000000000..2fb031dac --- /dev/null +++ b/other/cachetools/phpRedisAdmin/js/frame.js @@ -0,0 +1,30 @@ + +$(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; + } + }); + } + }); +}); + diff --git a/other/cachetools/phpRedisAdmin/js/index.js b/other/cachetools/phpRedisAdmin/js/index.js new file mode 100644 index 000000000..e2fb7e8d3 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/js/index.js @@ -0,0 +1,103 @@ + +$(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; + } + }); + } + }); +}); + diff --git a/other/cachetools/phpRedisAdmin/login.inc.php b/other/cachetools/phpRedisAdmin/login.inc.php new file mode 100644 index 000000000..633bd9460 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/login.inc.php @@ -0,0 +1,63 @@ + 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.'); +} + +?> diff --git a/other/cachetools/phpRedisAdmin/logout.php b/other/cachetools/phpRedisAdmin/logout.php new file mode 100644 index 000000000..502d33959 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/logout.php @@ -0,0 +1,40 @@ + 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'))); + +?> diff --git a/other/cachetools/phpRedisAdmin/overview.php b/other/cachetools/phpRedisAdmin/overview.php new file mode 100644 index 000000000..3d73bc0d4 --- /dev/null +++ b/other/cachetools/phpRedisAdmin/overview.php @@ -0,0 +1,84 @@ + $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'; + +?> + + $server) { ?> +
    +

    + + + + + + + + + + + + + +
    Redis version:
    Keys:
    Memory used:
    Uptime:
    Last save:
    [S]
    +
    + + +

    +phpRedisAdmin on GitHub +

    + +

    +Redis Documentation +

    + diff --git a/other/cachetools/phpRedisAdmin/page.inc.php b/other/cachetools/phpRedisAdmin/page.inc.php new file mode 100644 index 000000000..474a8c80f --- /dev/null +++ b/other/cachetools/phpRedisAdmin/page.inc.php @@ -0,0 +1,22 @@ + array('common'), + 'js' => array() +); + +?> \ No newline at end of file diff --git a/other/cachetools/phpRedisAdmin/rename.php b/other/cachetools/phpRedisAdmin/rename.php new file mode 100644 index 000000000..8264f1bed --- /dev/null +++ b/other/cachetools/phpRedisAdmin/rename.php @@ -0,0 +1,56 @@ + $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'; + + ?> + + +

    Edit Name of

    +
    + + + +

    + +> +

    + +

    + +

    + +
    + diff --git a/other/cachetools/phpRedisAdmin/save.php b/other/cachetools/phpRedisAdmin/save.php new file mode 100644 index 000000000..56214a9ff --- /dev/null +++ b/other/cachetools/phpRedisAdmin/save.php @@ -0,0 +1,30 @@ + +

    Saving

    + +... +save(); + +?> + done. + \ No newline at end of file diff --git a/other/cachetools/phpRedisAdmin/ttl.php b/other/cachetools/phpRedisAdmin/ttl.php new file mode 100644 index 000000000..fd9752d7e --- /dev/null +++ b/other/cachetools/phpRedisAdmin/ttl.php @@ -0,0 +1,50 @@ +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'; + +?> +

    Edit TTL

    +
    + +

    + +> +

    + +

    + +> (-1 to remove the TTL) +

    + +

    + +

    + +
    + diff --git a/other/cachetools/phpRedisAdmin/view.php b/other/cachetools/phpRedisAdmin/view.php new file mode 100644 index 000000000..6f55f38de --- /dev/null +++ b/other/cachetools/phpRedisAdmin/view.php @@ -0,0 +1,207 @@ + + Invalid key + type($_GET['key']); +$exists = $redis->exists($_GET['key']); + + +?> +

    + + [R] + [X] + [E] + +

    + + This key does not exist. + 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; +} + + +?> + + + + + + + + + + +
    Type:
    TTL:
    [E]
    Encoding:
    Size:
    + +

    + + + + +
    + [E] +
    + [X] +
    + + + + + + + $value) { ?> + > + + + + +
    Key
    Value
     
     
    + [E] +
    + [X] +
    + + +lGet($_GET['key'], $i); +?> + > + + + +
    Index
    Value
     
     
    + [E] +
    + [X] +
    + + +exists($value) ? ''.nl2br(format_html($value)).'' : nl2br(format_html($value)); +?> + > + + + + +
    Value
     
     
    + [E] +
    + [X] +
    + + +zScore($_GET['key'], $value); + $display_value = $redis->exists($value) ? ''.nl2br(format_html($value)).'' : nl2br(format_html($value)); +?> + > + + + +
    Score
    Value
     
     
    + [E] + [X] +
    + +

    + Add another value +

    +