AnyEvent-Memcached
view release on metacpan or search on metacpan
NAME
AnyEvent::Memcached - AnyEvent memcached client
SYNOPSIS
use AnyEvent::Memcached;
my $memd = AnyEvent::Memcached->new(
servers => [ "10.0.0.15:11211", "10.0.0.15:11212" ], # same as in Cache::Memcached
debug => 1,
compress_threshold => 10000,
namespace => 'my-namespace:',
# May use another hashing algo:
hasher => 'AnyEvent::Memcached::Hash::WithNext',
cv => $cv, # AnyEvent->condvar: group callback
);
$memd->set_servers([ "10.0.0.15:11211", "10.0.0.15:11212" ]);
There is a note, that get_multi is not implementeted. In fact, it
was implemented by method "get", but the documentation was wrong.
In general, this module follows the spirit of AnyEvent rather than
correspondence to Cache::Memcached interface.
METHODS
new %args
Currently supported options:
servers =item namespace =item debug =item cv =item compress_threshold
=item compress_enable =item timeout =item hasher
If set, will use instance of this class for hashing instead of
default. For implementing your own hashing, see sources of
AnyEvent::Memcached::Hash and AnyEvent::Memcached::Hash::With::Next
noreply
If true, additional connection will established for noreply
commands.
cas If true, will enable cas/gets commands (since they are not suppotred
examples/test.pl view on Meta::CPAN
use lib::abs '../lib';
use AnyEvent;
use AnyEvent::Memcached;
my $cv = AnyEvent->condvar;
$cv->begin(sub { $cv->send });
my $memd = AnyEvent::Memcached->new(
servers => [ '127.0.0.1:11211' ],
cv => $cv,
# debug => 1,
namespace => "test:",
);
$memd->set("key1", "val1", cb => sub {
shift or warn "Set key1 failed: @_";
warn "Set ok";
$memd->get("key1", cb => sub {
my ($v,$e) = @_;
$e and return warn "Get failed: $e";
warn "Got value for key1: $v";
lib/AnyEvent/Memcached.pm view on Meta::CPAN
=cut
our $VERSION = '0.08';
=head1 SYNOPSIS
use AnyEvent::Memcached;
my $memd = AnyEvent::Memcached->new(
servers => [ "10.0.0.15:11211", "10.0.0.15:11212" ], # same as in Cache::Memcached
debug => 1,
compress_threshold => 10000,
namespace => 'my-namespace:',
# May use another hashing algo:
hasher => 'AnyEvent::Memcached::Hash::WithNext',
cv => $cv, # AnyEvent->condvar: group callback
);
$memd->set_servers([ "10.0.0.15:11211", "10.0.0.15:11212" ]);
lib/AnyEvent/Memcached.pm view on Meta::CPAN
=head1 METHODS
=head2 new %args
Currently supported options:
=over 4
=item servers
=item namespace
=item debug
=item cv
=item compress_threshold
=item compress_enable
=item timeout
=item hasher
If set, will use instance of this class for hashing instead of default.
For implementing your own hashing, see sources of L<AnyEvent::Memcached::Hash> and L<AnyEvent::Memcached::Hash::With::Next>
=item noreply
lib/AnyEvent/Memcached.pm view on Meta::CPAN
If true, will enable cas/gets commands (since they are not suppotred in memcachedb)
=back
=cut
sub new {
my $self = bless {}, shift;
my %args = @_;
$self->{namespace} = exists $args{namespace} ? delete $args{namespace} : '';
for (qw( debug cv compress_threshold compress_enable timeout noreply cas)) {
$self->{$_} = exists $args{$_} ? delete $args{$_} : 0;
}
$self->{timeout} ||= 3;
$self->{_bucker} = $args{bucker} || 'AnyEvent::Memcached::Buckets';
$self->{_hasher} = $args{hasher} || 'AnyEvent::Memcached::Hash';
$self->set_servers(delete $args{servers});
$self->{compress_enable} and !$HAVE_ZLIB and carp("Have no Compress::Zlib installed, but have compress_enable option");
carp "@{[ keys %args ]} options are not supported yet" if %args;
Carp::confess "Invalid characters in 'namespace' option: '$self->{namespace}'" if $self->{namespace} =~ /[\x00-\x20\x7F]/;
lib/AnyEvent/Memcached.pm view on Meta::CPAN
my $buckets = $self->{_bucker}->new(servers => $list);
#warn R::Dump($list, $buckets);
$self->{hash} = $self->{_hasher}->new(buckets => $buckets);
$self->{peers} =
my $peers = $buckets->peers;
for my $peer ( values %{ $peers } ) {
$peer->{con} = AnyEvent::Memcached::Peer->new(
port => $peer->{port},
host => $peer->{host},
timeout => $self->{timeout},
debug => $self->{debug},
);
# Noreply connection
if ($self->{noreply}) {
$peer->{nrc} = AnyEvent::Memcached::Peer->new(
port => $peer->{port},
host => $peer->{host},
timeout => $self->{timeout},
debug => $self->{debug},# || 1,
);
}
}
return $self;
}
=head2 connect
Establish connection to all servers and invoke event C<connected>, when ready
lib/AnyEvent/Memcached.pm view on Meta::CPAN
sub AnyEvent::Memcached::destroyed::AUTOLOAD {}
sub destroy {
my $self = shift;
$self->DESTROY;
bless $self, "AnyEvent::Memcached::destroyed";
}
sub DESTROY {
my $self = shift;
warn "(".int($self).") Destroying AE:MC" if $self->{debug};
for (values %{$self->{peers}}) {
$_->{con} and $_->{con}->destroy;
}
%$self = ();
}
=head1 BUGS
Feature requests are welcome
lib/AnyEvent/Memcached/Conn.pm view on Meta::CPAN
sub reader {
my ($self,%args) = @_;
$args{cb} or return $self->event( error => "no cb for command at @{[ (caller)[1,2] ]}" );
$self->{h} or return $args{cb}->(undef,"Not connected");
my $result = $args{res} || {};
my $ar = ref $result eq 'ARRAY' ? 1 : 0;
my $cut = exists $args{namespace} ? length $args{namespace} : 0;
my $reader;$reader = sub {
shift;
defined( local $_ = shift ) or return $args{cb}(undef,@_);
warn "<<$args{id} $_" if $self->{debug};
if ($_ eq "END") {
undef $reader;
$args{cb}( $result );
}
elsif (substr($_,0,5) eq 'ERROR') {
undef $reader;
$args{cb}( undef, $_ );
}
elsif (!length) {
warn "Skip empty line";
lib/AnyEvent/Memcached/Conn.pm view on Meta::CPAN
}
elsif( /^VALUE (\S+) (\d+) (\d+)(?:| (.+))$/ ) {
my ($key,$flags,$len,$cas) = ($1,$2,$3,$4);
#warn "have to read $1 $2 $3 $4";
$self->recv( $3+2 => cb => sub {
#shift;
my $data = shift;
substr($data,$len) = ''; # trim out data outside length
#$data = substr($data,0,length($data)-2);
$key = substr($key, $cut) if substr($key, 0, $cut) eq $args{namespace};
warn "+ received data $key: $data" if $self->{debug};
my $v = {
data => $data,
flags => $flags,
defined $cas ? (cas => $cas) : (),
};
if ($ar) {
push @$result, $key, $v;
} else {
$result->{$key} = $v;#{ data => $data, $cas ? (cas => $cas) : () };
}
lib/AnyEvent/Memcached/Peer.pm view on Meta::CPAN
}
sub connect {
my $self = shift;
$self->{connecting} and return;
$self->{grd}{con} = $self->reg_cb( connected => sub { $self->{failed} = 0; } );
$self->{grd}{cfl} = $self->reg_cb( connfail => sub { $self->{failed} = 1; } );
$self->{grd}{dis} = $self->reg_cb( disconnect => sub {
shift;shift;
%$self or return;
warn "Peer $self->{host}:$self->{port} disconnected".(@_ ? ": @_" : '')."\n" if $self->{debug};
my $e = @_ ? "@_" : "disconnected";
for ( keys %{$self->{waitingcb}} ) {
if ($self->{waitingcb}{$_}) {
#warn "Cleanup: ",::sub_fullname( $self->{waitingcb}{$_} );
$self->{waitingcb}{$_}(undef,$e);
}
delete $self->{waitingcb}{$_};
}
} );
$self->SUPER::connect(@_);
t/03-storable.t view on Meta::CPAN
runtest {
my ($host,$port) = @_;
diag "testing $host : $port";
require Test::NoWarnings;Test::NoWarnings->import;
plan tests => 5 + 1;
my $cv = AE::cv;
my $memd = AnyEvent::Memcached->new(
servers => "$host:$port",
cv => $cv,
debug => 0,
namespace => "AE::Memd::t/$$/" . (time() % 100) . "/",
compress_enable => 1,
compress_threshold => 1, # Almost everything is greater than 1
);
isa_ok($memd, 'AnyEvent::Memcached');
# Repeated structures will be compressed
$memd->set(key1 => { some => 'struct'x10, "\0" => "\1" }, cb => sub {
ok(shift,"set key1") or diag " Error: @_";
$memd->get("key1", cb => sub {
runtest {
my ($host,$port,%args) = @_;
my $cv;$cv = AE::cv;
diag "testing $host:$port";
require Test::NoWarnings;Test::NoWarnings->import;
plan tests => 52+1;
my $memd = AnyEvent::Memcached->new(
servers => [ "$host:$port" ],
cv => $cv,
debug => 0,
%args,
namespace => "AE::Memd::t/$$/" . (time() % 100) . "/",
);
isa_ok($memd, 'AnyEvent::Memcached');
$cv->begin;
$memd->set('cas2','val2',cb => sub { ok(shift,"set cas2 as val1") or diag " Error: @_"; });
$memd->set('cas1','val1',cb => sub {
ok(shift,"set cas as val1") or diag " Error: @_";
$memd->gets('cas1',cb => sub {
( run in 1.334 second using v1.01-cache-2.11-cpan-49f99fa48dc )