Mercurial > hg > memcached
diff scripts/memcached-tool @ 0:30782bb1fc04 MEMCACHED_1_2_3
memcached-1.2.3
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sun, 23 Sep 2007 03:58:34 +0400 |
parents | |
children |
line wrap: on
line diff
new file mode 100755 --- /dev/null +++ b/scripts/memcached-tool @@ -0,0 +1,160 @@ +#!/usr/bin/perl +# +# memcached-tool: +# stats/management tool for memcached. +# +# Author: +# Brad Fitzpatrick <brad@danga.com> +# +# License: +# public domain. I give up all rights to this +# tool. modify and copy at will. +# + +use strict; +use IO::Socket::INET; + +my $host = shift; +my $mode = shift || "display"; +my ($from, $to); + +if ($mode eq "display") { + undef $mode if @ARGV; +} elsif ($mode eq "move") { + $from = shift; + $to = shift; + undef $mode if $from < 6 || $from > 17; + undef $mode if $to < 6 || $to > 17; + print STDERR "ERROR: parameters out of range\n\n" unless $mode; +} elsif ($mode eq 'dump') { + ; +} else { + undef $mode; +} + +undef $mode if @ARGV; + +die +"Usage: memcached-tool <host[:port]> [mode]\n + memcached-tool 10.0.0.5:11211 display # shows slabs + memcached-tool 10.0.0.5:11211 # same. (default is display) + memcached-tool 10.0.0.5:11211 move 7 9 # takes 1MB slab from class #7 + # to class #9. + +You can only move slabs around once memory is totally allocated, and only +once the target class is full. (So you can't move from #6 to #9 and #7 +to #9 at the same itme, since you'd have to wait for #9 to fill from +the first reassigned page) +" unless $host && $mode; + +$host .= ":11211" unless $host =~ /:\d+/; + +my $sock = IO::Socket::INET->new(PeerAddr => $host, + Proto => 'tcp'); +die "Couldn't connect to $host\n" unless $sock; + + +if ($mode eq "move") { + my $tries = 0; + while (1) { + print $sock "slabs reassign $from $to\r\n"; + my $res = <$sock>; + $res =~ s/\s+//; + if ($res eq "DONE") { + print "Success.\n"; + exit 0; + } elsif ($res eq "CANT") { + print "Error: can't move from $from to $to. Destination not yet full? See usage docs.\n"; + exit; + } elsif ($res eq "BUSY") { + if (++$tries == 3) { + print "Failed to move after 3 tries. Try again later.\n"; + exit; + } + + print "Page busy, retrying...\n"; + sleep 1; + } + } + + exit; +} + +if ($mode eq 'dump') { + my %items; + my $totalitems; + + print $sock "stats items\r\n"; + + while (<$sock>) { + last if /^END/; + if (/^STAT items:(\d*):number (\d*)/) { + $items{$1} = $2; + $totalitems += $2; + } + } + print STDERR "Dumping memcache contents\n"; + print STDERR " Number of buckets: " . scalar(keys(%items)) . "\n"; + print STDERR " Number of items : $totalitems\n"; + + foreach my $bucket (sort(keys(%items))) { + print STDERR "Dumping bucket $bucket - " . $items{$bucket} . " total items\n"; + print $sock "stats cachedump $bucket $items{$bucket} 1\r\n"; + my %keyexp; + while (<$sock>) { + last if /^END/; + # return format looks like this + # ITEM foo [6 b; 1176415152 s] + if (/^ITEM (\w+) \[.* (\d+) s\]/) { + $keyexp{$1} = $2; + } + } + + foreach my $k (keys(%keyexp)) { + my $val; + print $sock "get $k\r\n"; + my $response = <$sock>; + $response =~ /VALUE (\w+) (\d+) (\d+)/; + my $flags = $2; + my $len = $3; + read $sock, $val , $len; + # get the END + $_ = <$sock>; + $_ = <$sock>; + print "add $k $flags $keyexp{$k} $len\r\n$val\r\n"; + } + } + exit; +} + +# display mode: + +my %items; # class -> { number, age, chunk_size, chunks_per_page, + # total_pages, total_chunks, used_chunks, + # free_chunks, free_chunks_end } + +print $sock "stats items\r\n"; +while (<$sock>) { + last if /^END/; + if (/^STAT items:(\d+):(\w+) (\d+)/) { + $items{$1}{$2} = $3; + } +} + +print $sock "stats slabs\r\n"; +while (<$sock>) { + last if /^END/; + if (/^STAT (\d+):(\w+) (\d+)/) { + $items{$1}{$2} = $3; + } +} + +print " # Item_Size Max_age 1MB_pages Full?\n"; +foreach my $n (6..17) { + my $it = $items{$n}; + my $size = $it->{chunk_size} < 1024 ? "$it->{chunk_size} B" : + sprintf("%d kB", $it->{chunk_size} / 1024); + my $full = $it->{free_chunks_end} == 0 ? "yes" : " no"; + printf "%3d %6s%7d s %7d $full\n", $n, $size, $it->{age}, $it->{total_pages}; +} +