File Coverage

lib/AnyEvent/Memcached/Buckets.pm
Criterion Covered Total %
statement 64 76 84.2
branch 15 26 57.6
condition 5 10 50.0
subroutine 7 9 77.7
pod 0 6 0.0
total 91 127 71.6


line stmt bran cond sub pod time code
1             package #hide
2             AnyEvent::Memcached::Buckets;
3              
4 6     6   782 use common::sense 2;m{
  6         104  
  6         35  
5             use strict;
6             use warnings;
7             }x;
8 6     6   376 use Carp;
  6         62  
  6         5620  
9              
10             sub new {
11 2     2 0 29 my $self = bless {}, shift;
12 2         7 my %args = @_;
13 2         10 $self->set_servers(delete $args{servers});
14 2         5 $self;
15             }
16              
17             sub set_servers {
18 2     2 0 3 my $self = shift;
19 2 50       33 my $list = shift or return;
20 2 50       8 $list = [$list] unless ref $list eq 'ARRAY';
21 2   50     50 $self->{servers} = $list || [];
22 2         8 $self->_init_buckets;
23 2         3 return $self;
24             }
25              
26             sub peers {
27 0     0 0 0 my $self = shift;
28 0 0       0 @{$self->{servers}} or croak "servers not set during peers";
  0         0  
29 0         0 $self->{peers};
30             }
31              
32             sub _init_buckets {
33 2     2   4 my $self = shift;
34 2 50       2 @{$self->{servers}} or croak "servers not set during _init_buckets";
  2         8  
35 2 50       6 if ($self->{buckets}) {
36 0         0 @{ $self->{buckets} } = ();
  0         0  
37             } else {
38 2         6 $self->{buckets} = [];
39             }
40 2         3 my $bu = $self->{buckets};
41 2         4 my $i = 0;
42 2         2 foreach my $v (@{$self->{servers}}) {
  2         7  
43 10         10 my $peer;
44 10         14 my $buck = [ 0+@$bu ];
45 10 100       15 if (ref $v eq "ARRAY") {
46 2         4 $peer = $v->[0];
47 2         21 for (1..$v->[1]) {
48 6         10 push @$bu, $v->[0];
49             }
50 2         7 push @$buck, $buck->[0]+1 .. $#$bu;
51             } else {
52 8         11 push @$bu, $peer = $v;
53             }
54 10         39 my ($host,$port) = $peer =~ /^(.+?)(?:|:(\d+))$/;
55 10 100       20 if ( exists $self->{peers}{$peer} ) {
56 2         4 push @{ $self->{peers}{$peer}{bucks} }, @$buck;
  2         9  
57             } else {
58 8   100     5 push @{ $self->{srv} ||= [] }, $peer;
  8         28  
59             $self->{peers}{$peer} = {
60 8         9 index => $#{ $self->{srv} },
  8         30  
61             bucks => $buck,
62             host => $host,
63             port => $port,
64             };
65             }
66             }
67 2         3 return;
68             }
69              
70              
71             sub peer {
72 82     82 0 63 my $self = shift;
73 82         68 my $hash = shift;
74 82 50       68 @{$self->{servers}} or croak "servers not set during peer";
  82         168  
75 82         91 return $self->{buckets}[ $hash % @{ $self->{buckets} } ];
  82         191  
76             }
77              
78             sub next {
79 41     41 0 34 my $self = shift;
80 41         40 my $srv = shift;
81 41 50       32 @{$self->{servers}} or croak "servers not set during next";
  41         72  
82 41 50       71 my $peer = $self->{peers}{$srv} or croak "No such server in buckets: $srv";
83 41         58 my %args = @_;
84 41   50     127 my $by = $args{by} || 1;
85 41         45 my $next = ( $peer->{index} + $by ) % @{$self->{srv}};
  41         45  
86 41 50       77 my $nsrv = $self->{srv}[$next] or die "Cant find next server by index $next";
87 41 50       64 $nsrv = $nsrv->[0] if ref $nsrv;
88             #warn R::Dump($nsrv);
89 41 100       30 if ( ( my @bucks = @{ $self->{peers}{$nsrv}{bucks} } ) > 1 ) {
  41         106  
90 5   50     18 my $which = $bucks[ ( $args{hash} || 0 ) % @bucks ];
91             #warn "many buckets (@bucks) for $nsrv. using $which ($self->{buckets}[ $which ])";
92 5         14 return $self->{buckets}[ $which ];
93             } else {
94 36         85 return $nsrv;
95             }
96             }
97             sub prev {
98 0     0 0   my $self = shift;
99 0           my $srv = shift;
100 0           my %args = @_;
101 0   0       my $by = $args{by} || 1;
102 0           $self->next( $srv, %args, by => @{$self->{srv}}-$by );
  0            
103             }
104              
105             1;