Cache-BDB
view release on metacpan or search on metacpan
lib/Cache/BDB.pm view on Meta::CPAN
__set_time => $now,
__last_access_time => $now,
__version => $Cache::BDB::VERSION,
__data => $value};
$rv = $db->db_put($key, $data);
return $rv ? 0 : 1;
}
sub add {
my ($self, $key, $value, $ttl) = @_;
return $self->get($key) ? 0 : $self->set($key, $value, $ttl);
}
sub replace {
my ($self, $key, $value, $ttl) = @_;
return $self->get($key) ? $self->set($key, $value, $ttl) : 0;
}
sub get {
my ($self, $key) = @_;
return undef unless $key;
my $db = $self->{__db};
my $t = time();
my $data;
if($self->{auto_purge_on_get}) {
my $interval = $self->{auto_purge_interval};
if($t > ($self->{__last_purge_time} + $interval)) {
$self->purge();
$self->{__last_purge_time} = $t;
}
}
my $rv = $db->db_get($key, $data);
return undef if $rv == DB_NOTFOUND;
return undef unless $data->{__data};
if($self->__is_expired($data, $t)) {
$self->remove($key) unless $self->{disable_auto_purge};
return undef;
}
# this is pretty slow, leaving it out for now. if i start supporting
# access time related stuff i'll need to work on it.
# $self->_update_access_time($key, $data, $t);
return $data->{__data};
}
sub get_bulk {
my $self = shift;
my $t = time();
my $count = 0;
my $db = $self->{__db};
my $cursor = $db->db_cursor();
my %ret;
my ($k, $v) = ('','');
while($cursor->c_get($k, $v, DB_NEXT) == 0) {
my $d = $self->get($k);
$ret{$k} = $d if $d;
}
$cursor->c_close();
return \%ret;
}
sub _update_access_time {
my ($self, $key, $data, $t) = @_;
my $db = $self->{__db};
$t ||= time();
$data->{__last_access_time} = $t;
my $rv = $db->db_put($key, $data);
return $rv;
}
###########################
# Cache meta information. #
###########################
sub count {
my $self = shift;
my $total = 0;
my $db = $self->{__db};
my $stats = $db->db_stat;
my $type = $db->type;
$total = ($type == DB_HASH) ?
$stats->{hash_ndata} : $stats->{bt_ndata};
return $total;
}
sub size {
my $self = shift;
my $db = $self->{__db};
eval { require Devel::Size };
if($@) {
warn "size() currently requires Devel::Size";
return 0;
}
else {
import Devel::Size qw(total_size);
}
my ($k, $v) = ('','');
my $size = 0;
my $cursor = $self->{__db}->db_cursor();
while($cursor->c_get($k, $v, DB_NEXT) == 0) {
$size += total_size($v->{__data});
}
$cursor->c_close();
return $size;
}
##############################################
# Methods for removing items from the cache. #
##############################################
sub remove {
my ($self, $key) = @_;
my $rv;
my $v = '';
my $db = $self->{__db};
$rv = $db->db_del($key);
warn "compaction failed!" if $self->_compact();
return $rv ? 0 : 1;
}
*delete = \&remove;
sub clear {
my $self = shift;
my $rv;
my $count = 0;
my $db = $self->{__db};
$rv = $db->truncate($count);
warn "compaction failed!" if $self->_compact();
return $count;
}
sub purge {
my $self = shift;
my $t = time();
my $count = 0;
my $db = $self->{__db};
my $cursor = $db->db_cursor(DB_WRITECURSOR);
my ($k, $v) = ('','');
while($cursor->c_get($k, $v, DB_NEXT) == 0) {
if($self->__is_expired($v, $t)) {
$cursor->c_del();
$count++;
}
}
$cursor->c_close();
warn "compaction failed!" if $self->_compact();
return $count;
}
sub __is_expired {
my ($self, $data, $t) = @_;
$t ||= time();
return 1 if($data->{__expires} && $data->{__expires} < $t);
return 0;
}
sub is_expired {
my ($self, $key) = @_;
my $data;
my $t = time();
return 0 unless $key;
my $db = $self->{__db};
my $rv = $db->db_get($key, $data);
return 0 unless $data;
return $self->__is_expired($data, $t);
}
sub _compact {
my $self = shift;
my $rv = 0; # assume success, if compact isn't available pretend its cool
my $db = $self->{__db};
if($db->can('compact') &&
$db->type == DB_BTREE &&
!$self->{disable_compact}) {
$rv = $db->compact(undef, undef, undef, DB_FREE_SPACE, undef);
}
return $rv;
}
1;
( run in 1.814 second using v1.01-cache-2.11-cpan-39bf76dae61 )