| Cache-Memcached-Indexable documentation | Contained in the Cache-Memcached-Indexable distribution. |
Cache::Memcached::Indexable - A key indexable Cache::Memcached wrapper
use Cache::Memcached::Indexable;
$memd = new Cache::Memcached::Indexable {
'servers' => [ "10.0.0.15:11211", "10.0.0.15:11212",
"10.0.0.17:11211", [ "10.0.0.17:11211", 3 ] ],
'debug' => 0,
'compress_threshold' => 10_000,
};
$memd->set_servers($array_ref);
$memd->set_compress_threshold(10_000);
$memd->enable_compress(0);
$memd->set("my_key", "Some value");
$memd->set("object_key", { 'complex' => [ "object", 2, 4 ]});
$val = $memd->get("my_key");
$val = $memd->get("object_key");
if ($val) { print $val->{'complex'}->[2]; }
$memd->incr("key");
$memd->decr("key");
$memd->incr("key", 2);
@all_keys = $memd->keys;
THIS IS ALPHA SOFTWARE
Cache::Memcached::Indexable is a key indexable memcached interface.
It is a simple wrapper class of Cache::Memcached.
Usually, we can't get any key information of stored data with using memcached.
This module provides keys() method (likes CORE::keys()) for getting
all of stored key information.
In fact, this module uses only a few patterns of knowable key, and it stores the key with the value of large hash-ref. It controls the large hash-ref when you call set, get or delete methods.
It was implantated some functions of Cache::Memcached. But the implanted functions are only documented functions. Note that some undocumented functions weren't implanted to this module.
newTakes one parameter, a hashref of options. Almost same as Cache::Memcached's constructor. But it has some additional parameter.
The parameter of logic is the name of your chosen logic class or
the entity of the logic class instance.
$memd = Cache::Memcached::Indexable->new({
logic => 'Cache::Memcached::Indexable::Logic::DigestSHA1',
logic_args => { set_max_power => 0xFF },
%memcached_args,
})
and the following code is same as above:
use Cache::Memcached::Indexable::Logic::DigestSHA1;
$logic = Cache::Memcached::Indexable::Logic::DigestSHA1->new({
set_max_power => 0xFF,
});
$memd = Cache::Memcached::Indexable->new({
logic => $logic,
%memcached_args,
});
The arguments of your specified logic class (see above.)
You may specify your favorite memcached interface class. But it must have Cache::Memcached compatibility (e.g. Cache::Memcached::XS).
You can get all of stored keys with calling this method.
And the usage of following methods. See Cache::Memcached document.
set_serversset_debugset_readonlyset_norehashset_compress_thresholdenable_compressgetget_multisetaddreplacedeleteincrdecrstatsdisconnect_allflush_allTHIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Koichi Taniguchi <taniguchi@livedoor.jp>
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Cache-Memcached-Indexable documentation | Contained in the Cache-Memcached-Indexable distribution. |
package Cache::Memcached::Indexable; use strict; use warnings; use UNIVERSAL::require; use Carp; our $VERSION = '0.03'; our $DEFAULT_LOGIC = 'Cache::Memcached::Indexable::Logic::Default'; sub new { my($class, $args) = @_; my $self = bless $args, $class; if (exists $self->{logic}) { my $logic = delete $self->{logic}; my $logic_args = delete $self->{logic_args}; $self->set_logic($logic, $logic_args); } my $memd; if (exists $self->{memd}) { $memd = delete $self->{memd}; } my %memd_args = map { $_ => $self->{$_} } keys %$self; $self->{_memd_args} = \%memd_args; if ($memd) { $self->set_memd($memd, $self->{_memd_args}); } return $self; } sub logic { my $self = shift; if (my $logic = $self->{_logic}) { return $logic; } $self->set_logic($DEFAULT_LOGIC); } sub set_logic { my $self = shift; my $class = shift; if (ref($class)) { $self->{_logic} = $class; } else { $class->use or croak $@; my $logic = $class->new(@_); $self->{_logic} = $logic; } return $self->{_logic}; } sub memd { my $self = shift; if (my $memd = $self->{_memd}) { return $memd; } $self->set_memd('Cache::Memcached', $self->{_memd_args}); } sub set_memd { my $self = shift; my $class = shift; if (ref($class)) { $self->{_memd} = $class; } else { $class->use or croak $@; my $memd = $class->new(@_); $self->{_memd} = $memd; } return $self->{_memd}; } sub set_servers { shift->memd->set_servers(@_) } sub set_debug { shift->memd->set_debug(@_) } sub set_readonly { shift->memd->set_readonly(@_) } sub set_norehash { shift->memd->set_norehash(@_) } sub set_compress_threshold { shift->memd->set_compress_threshold(@_) } sub enable_compress { shift->memd->enable_compress(@_) } sub get { my($self, $key) = @_; my $r = $self->get_multi($key); my $kval = ref($key) ? $key->[1] : $key; return $r->{$kval}; } sub get_multi { my $self = shift; my %val = (); my $logic = $self->logic; my $memd = $self->memd; for my $key (@_) { my $branch_key = $logic->branch_key($key); my $stored = $memd->get($branch_key); unless ($stored && ref($stored) eq 'HASH') { $val{$key} = (); next; } my $value = $stored->{$key}; next unless defined $value; if (ref($value) eq 'ARRAY') { my $expires = $value->[1]; if ($expires && time() > $expires) { $self->delete($key); $val{$key} = (); next; } $val{$key} = $value->[0]; next; } $val{$key} = $value; } if ($memd->{'debug'}) { while (my($k, $v) = each %val) { print STDERR "MemCache-Indexable: got $k = $v\n"; } } return \%val; } sub _exists { my($self, $key) = @_; my $logic = $self->logic; my $memd = $self->memd; my $branch_key = $logic->branch_key($key); my $stored = $memd->get($branch_key); return unless $stored && ref($stored) eq 'HASH'; my $value = $stored->{$key}; return unless defined $value; return defined $value unless ref($value) eq 'ARRAY'; my $expires = $value->[1]; if ($expires && time() > $expires) { $self->delete($key); return; } return defined $value->[0]; } sub set { my($self, $key, $value, $exptime) = @_; my $check = $self->__deleted_keys_as_hashref; if ($check->{$key}) { $self->delete($key); return; } my $set_value = $exptime ? [ $value, (time() + $exptime) ] : $value; my $memd = $self->memd; my $logic = $self->logic; my $branch_key = $logic->branch_key($key); my $stored = $memd->get($branch_key); unless ($stored && ref($stored) eq 'HASH') { $stored = {}; } $stored->{$key} = $set_value; return $memd->set($branch_key => $stored); } sub add { my $self = shift; my($key) = @_; return if $self->_exists($key); return $self->set(@_); } sub replace { my $self = shift; my($key) = @_; return unless $self->_exists($key); return $self->set(@_); } sub delete { my($self, $key, $exptime) = @_; my $memd = $self->memd; my $logic = $self->logic; my $branch_key = $logic->branch_key($key); my $stored = $memd->get($branch_key); my $result; if ($stored && ref($stored) eq 'HASH') { my $deleted = delete $stored->{$key}; $result = defined $deleted; $memd->set($branch_key => $stored) if $result; } else { $memd->set($branch_key => {}); } if ($exptime) { $self->_set_delete_expires($key => $exptime); } return $result ? $result : (); } sub incr { my($self, $key, $value) = @_; # XXX a simple emulation of original incr() $value = 1 unless defined $value; $self->replace($key => $self->get($key) + $value); } sub decr { my($self, $key, $value) = @_; # XXX a simple emulation of original decr() $value = 1 unless defined $value; $self->replace($key => $self->get($key) - $value); } sub stats { shift->memd->stats(@_) } sub disconnect_all { shift->memd->disconnect_all(@_) } sub flush_all { shift->memd->flush_all(@_) } sub keys { my $self = shift; my $memd = $self->memd; my $logic = $self->logic; my $deleted = $self->__deleted_keys_as_hashref; my @keys = (); for my $trunk_key ($logic->trunk_keys) { my $stored = $memd->get($trunk_key); if ($stored && ref($stored) eq 'HASH') { push(@keys, (grep { ! $deleted->{$_} } keys %$stored)); } } return @keys; } sub _set_delete_expires { my($self, $key, $exptime) = @_; my $memd = $self->memd; my $deleted_key = $self->logic->_deleted_key; my $deleted = $self->memd->get($deleted_key); unless ($deleted && ref($deleted) eq 'HASH') { $deleted = {}; } $deleted->{$key} = time() + $exptime; $memd->set($deleted_key => $deleted); } sub _deleted_keys { my $self = shift; my $memd = $self->memd; my $deleted_key = $self->logic->_deleted_key; my $deleted = $self->memd->get($deleted_key); return unless $deleted && ref($deleted) eq 'HASH'; my %new = (); my @deleted_keys = (); for my $key (CORE::keys %$deleted) { next if $deleted->{$key} < time(); push @deleted_keys, $key; $new{$key} = $deleted->{$key}; } $memd->set($deleted_key => \%new); return @deleted_keys; } sub __deleted_keys_as_hashref { my $self = shift; return +{ map { $_ => 1 } $self->_deleted_keys }; } 1; __END__