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};
+}
+