package Cache::Memcached::AnyEvent::Selector::Ketama; use strict; use base qw(Cache::Memcached::AnyEvent::Selector::Traditional); use Algorithm::ConsistentHash::Ketama; use Carp qw(croak); sub new { my $class = shift; my $self = bless{ @_, ketama => Algorithm::ConsistentHash::Ketama->new }, $class; my $servers = $self->{memcached}->{_active_servers}; foreach my $server (@$servers) { $self->add_server($server); } return $self; } sub add_server { my ($self, $server, $h) = @_; my $ketama = $self->{ketama}; my ($host_port, $weight) = (ref $server eq 'ARRAY') ? @$server : ( $server, 1 ) ; $ketama->add_bucket($host_port, $weight); } sub get_handle { my ($self, $key) = @_; my $count = $self->{memcached}->{_active_server_count}; if ($count > 0) { my $servers = $self->{memcached}->{_active_servers}; my $handles = $self->{memcached}->{_server_handles}; # short-circuit for when there's only one socket if ($count == 1) { return (values %$handles)[0]; } my $ketama = $self->{ketama}; my $handle = $handles->{ $ketama->hash( $key ) }; if ($handle) { return $handle; } } croak "Could not find a suitable handle for key $key"; } 1; __END__ =head1 NAME Cache::Memcached::AnyEvent::Selector::Ketama - Ketama Server Selection Algorithm =head1 SYNOPSIS use Cache::Memcached::AnyEvent; my $memd = Cache::Memcached::AnyEvent->new({ ... selector_class => 'Ketama', }); =head1 DESCRIPTION Implements the ketama server selection mechanism, =head1 METHODS =head2 $class->new( memcached => $memd ) Constructor. =head2 $selector->add_server( $server, $handle ) Called when a new server connection is made. =head2 $handle = $selector->get_handle( $key ) Returns the AnyEvent handle that is responsible for handling C<$key> =cut