use strict;
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