AnyEvent-Memcached

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

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" ]);

README  view on Meta::CPAN

        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 {

t/check.pl  view on Meta::CPAN

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 0.622 second using v1.01-cache-2.11-cpan-49f99fa48dc )