DBM-Deep
view release on metacpan or search on metacpan
utils/lib/DBM/Deep/09830.pm view on Meta::CPAN
seek($fh, $subloc + SIG_SIZE + $self->_root->{file_offset}, SEEK_SET);
##
# Skip over value to get to plain key
##
my $size;
read( $fh, $size, $DATA_LENGTH_SIZE); $size = unpack($DATA_LENGTH_PACK, $size);
if ($size) { seek($fh, $size, SEEK_CUR); }
##
# Read in plain key and return as scalar
##
my $plain_key;
read( $fh, $size, $DATA_LENGTH_SIZE); $size = unpack($DATA_LENGTH_PACK, $size);
if ($size) { read( $fh, $plain_key, $size); }
return $plain_key;
}
} # bucket loop
$self->{return_next} = 1;
} # tag is a bucket list
return;
}
sub _get_next_key {
##
# Locate next key, given digested previous one
##
my $self = $_[0]->_get_self;
$self->{prev_md5} = $_[1] ? $_[1] : undef;
$self->{return_next} = 0;
##
# If the previous key was not specifed, start at the top and
# return the first one found.
##
if (!$self->{prev_md5}) {
$self->{prev_md5} = chr(0) x $HASH_SIZE;
$self->{return_next} = 1;
}
return $self->_traverse_index( $self->_base_offset, 0 );
}
sub lock {
##
# If db locking is set, flock() the db file. If called multiple
# times before unlock(), then the same number of unlocks() must
# be called before the lock is released.
##
my $self = $_[0]->_get_self;
my $type = $_[1];
$type = LOCK_EX unless defined $type;
if (!defined($self->_fh)) { return; }
if ($self->_root->{locking}) {
if (!$self->_root->{locked}) {
flock($self->_fh, $type);
# refresh end counter in case file has changed size
my @stats = stat($self->_root->{file});
$self->_root->{end} = $stats[7];
# double-check file inode, in case another process
# has optimize()d our file while we were waiting.
if ($stats[1] != $self->_root->{inode}) {
$self->_open(); # re-open
flock($self->_fh, $type); # re-lock
$self->_root->{end} = (stat($self->_fh))[7]; # re-end
}
}
$self->_root->{locked}++;
return 1;
}
return;
}
sub unlock {
##
# If db locking is set, unlock the db file. See note in lock()
# regarding calling lock() multiple times.
##
my $self = $_[0]->_get_self;
if (!defined($self->_fh)) { return; }
if ($self->_root->{locking} && $self->_root->{locked} > 0) {
$self->_root->{locked}--;
if (!$self->_root->{locked}) { flock($self->_fh, LOCK_UN); }
return 1;
}
return;
}
sub _copy_value {
my $self = shift->_get_self;
my ($spot, $value) = @_;
if ( !ref $value ) {
${$spot} = $value;
}
elsif ( eval { local $SIG{__DIE__}; $value->isa( 'DBM::Deep::09830' ) } ) {
my $type = $value->_type;
${$spot} = $type eq TYPE_HASH ? {} : [];
$value->_copy_node( ${$spot} );
}
else {
my $r = Scalar::Util::reftype( $value );
my $c = Scalar::Util::blessed( $value );
if ( $r eq 'ARRAY' ) {
${$spot} = [ @{$value} ];
}
else {
${$spot} = { %{$value} };
}
${$spot} = bless ${$spot}, $c
if defined $c;
}
return 1;
}
sub _copy_node {
##
# Copy single level of keys or elements to new DB handle.
# Recurse for nested structures
##
my $self = shift->_get_self;
my ($db_temp) = @_;
if ($self->_type eq TYPE_HASH) {
my $key = $self->first_key();
while ($key) {
my $value = $self->get($key);
$self->_copy_value( \$db_temp->{$key}, $value );
$key = $self->next_key($key);
}
}
else {
my $length = $self->length();
for (my $index = 0; $index < $length; $index++) {
my $value = $self->get($index);
$self->_copy_value( \$db_temp->[$index], $value );
}
}
return 1;
utils/lib/DBM/Deep/09830.pm view on Meta::CPAN
##
# Clear all keys from hash, or all elements from array.
##
my $self = $_[0]->_get_self;
##
# Make sure file is open
##
if (!defined($self->_fh)) { $self->_open(); }
##
# Request exclusive lock for writing
##
$self->lock( LOCK_EX );
my $fh = $self->_fh;
seek($fh, $self->_base_offset + $self->_root->{file_offset}, SEEK_SET);
if (eof $fh) {
$self->unlock();
return;
}
$self->_create_tag($self->_base_offset, $self->_type, chr(0) x $INDEX_SIZE);
$self->unlock();
return 1;
}
##
# Public method aliases
##
sub put { (shift)->STORE( @_ ) }
sub store { (shift)->STORE( @_ ) }
sub get { (shift)->FETCH( @_ ) }
sub fetch { (shift)->FETCH( @_ ) }
sub delete { (shift)->DELETE( @_ ) }
sub exists { (shift)->EXISTS( @_ ) }
sub clear { (shift)->CLEAR( @_ ) }
package DBM::Deep::09830::_::Root;
sub new {
my $class = shift;
my ($args) = @_;
my $self = bless {
file => undef,
fh => undef,
file_offset => 0,
end => 0,
autoflush => undef,
locking => undef,
debug => undef,
filter_store_key => undef,
filter_store_value => undef,
filter_fetch_key => undef,
filter_fetch_value => undef,
autobless => undef,
locked => 0,
%$args,
}, $class;
if ( $self->{fh} && !$self->{file_offset} ) {
$self->{file_offset} = tell( $self->{fh} );
}
return $self;
}
sub DESTROY {
my $self = shift;
return unless $self;
close $self->{fh} if $self->{fh};
return;
}
package DBM::Deep::09830::Array;
use strict;
# This is to allow DBM::Deep::Array to handle negative indices on
# its own. Otherwise, Perl would intercept the call to negative
# indices for us. This was causing bugs for negative index handling.
use vars qw( $NEGATIVE_INDICES );
$NEGATIVE_INDICES = 1;
use base 'DBM::Deep::09830';
use Scalar::Util ();
sub _get_self {
eval { local $SIG{'__DIE__'}; tied( @{$_[0]} ) } || $_[0]
}
sub TIEARRAY {
##
# Tied array constructor method, called by Perl's tie() function.
##
my $class = shift;
my $args = $class->_get_args( @_ );
$args->{type} = $class->TYPE_ARRAY;
return $class->_init($args);
}
sub FETCH {
my $self = $_[0]->_get_self;
my $key = $_[1];
$self->lock( $self->LOCK_SH );
if ( $key =~ /^-?\d+$/ ) {
if ( $key < 0 ) {
$key += $self->FETCHSIZE;
unless ( $key >= 0 ) {
$self->unlock;
( run in 1.310 second using v1.01-cache-2.11-cpan-39bf76dae61 )