X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBM%2FDeep%2FArray.pm;h=247d7307c3998c747cde8262928e830e6c1afde4;hb=2ba14e04118fbfa4f41947ac9273b97ca1cb78e2;hp=e60c152bcbc43dd86c662a59a2cfa749b4309078;hpb=151e00777a6e5ff803b5456075042d257dbcd4fc;p=dbsrgits%2FDBM-Deep.git diff --git a/lib/DBM/Deep/Array.pm b/lib/DBM/Deep/Array.pm index e60c152..247d730 100644 --- a/lib/DBM/Deep/Array.pm +++ b/lib/DBM/Deep/Array.pm @@ -3,9 +3,9 @@ package DBM::Deep::Array; use 5.006_000; use strict; -use warnings; +use warnings FATAL => 'all'; -our $VERSION = q(1.0001); +our $VERSION = $DBM::Deep::VERSION; # This is to allow DBM::Deep::Array to handle negative indices on # its own. Otherwise, Perl would intercept the call to negative @@ -20,16 +20,7 @@ sub _get_self { eval { local $SIG{'__DIE__'}; tied( @{$_[0]} ) } || $_[0] } -sub _repr { shift;[ @_ ] } - -sub _import { - my $self = shift; - my ($struct) = @_; - - $self->push( @$struct ); - - return 1; -} +sub _repr { [] } sub TIEARRAY { my $class = shift; @@ -44,9 +35,10 @@ sub FETCH { my $self = shift->_get_self; my ($key) = @_; - $self->lock( $self->LOCK_SH ); + $self->lock_shared; if ( !defined $key ) { + $self->unlock; DBM::Deep->_throw_error( "Cannot use an undefined array index." ); } elsif ( $key =~ /^-?\d+$/ ) { @@ -74,11 +66,12 @@ sub STORE { my $self = shift->_get_self; my ($key, $value) = @_; - $self->lock( $self->LOCK_EX ); + $self->lock_exclusive; my $size; my $idx_is_numeric; if ( !defined $key ) { + $self->unlock; DBM::Deep->_throw_error( "Cannot use an undefined array index." ); } elsif ( $key =~ /^-?\d+$/ ) { @@ -114,9 +107,10 @@ sub EXISTS { my $self = shift->_get_self; my ($key) = @_; - $self->lock( $self->LOCK_SH ); + $self->lock_shared; if ( !defined $key ) { + $self->unlock; DBM::Deep->_throw_error( "Cannot use an undefined array index." ); } elsif ( $key =~ /^-?\d+$/ ) { @@ -143,11 +137,13 @@ sub EXISTS { sub DELETE { my $self = shift->_get_self; my ($key) = @_; + warn "ARRAY::DELETE($self,$key)\n" if DBM::Deep::DEBUG; - $self->lock( $self->LOCK_EX ); + $self->lock_exclusive; my $size = $self->FETCHSIZE; if ( !defined $key ) { + $self->unlock; DBM::Deep->_throw_error( "Cannot use an undefined array index." ); } elsif ( $key =~ /^-?\d+$/ ) { @@ -175,20 +171,20 @@ sub DELETE { return $rv; } -# Now that we have a real Reference sector, we should store arrayzize there. However, -# arraysize needs to be transactionally-aware, so a simple location to store it isn't -# going to work. +# Now that we have a real Reference sector, we should store arrayzize there. +# However, arraysize needs to be transactionally-aware, so a simple location to +# store it isn't going to work. sub FETCHSIZE { my $self = shift->_get_self; - $self->lock( $self->LOCK_SH ); + $self->lock_shared; - my $SAVE_FILTER = $self->_storage->{filter_fetch_value}; - $self->_storage->{filter_fetch_value} = undef; + my $SAVE_FILTER = $self->_engine->storage->{filter_fetch_value}; + $self->_engine->storage->{filter_fetch_value} = undef; my $size = $self->FETCH('length') || 0; - $self->_storage->{filter_fetch_value} = $SAVE_FILTER; + $self->_engine->storage->{filter_fetch_value} = $SAVE_FILTER; $self->unlock; @@ -199,14 +195,14 @@ sub STORESIZE { my $self = shift->_get_self; my ($new_length) = @_; - $self->lock( $self->LOCK_EX ); + $self->lock_exclusive; - my $SAVE_FILTER = $self->_storage->{filter_store_value}; - $self->_storage->{filter_store_value} = undef; + my $SAVE_FILTER = $self->_engine->storage->{filter_store_value}; + $self->_engine->storage->{filter_store_value} = undef; my $result = $self->STORE('length', $new_length, 'length'); - $self->_storage->{filter_store_value} = $SAVE_FILTER; + $self->_engine->storage->{filter_store_value} = $SAVE_FILTER; $self->unlock; @@ -216,7 +212,7 @@ sub STORESIZE { sub POP { my $self = shift->_get_self; - $self->lock( $self->LOCK_EX ); + $self->lock_exclusive; my $length = $self->FETCHSIZE(); @@ -237,7 +233,7 @@ sub POP { sub PUSH { my $self = shift->_get_self; - $self->lock( $self->LOCK_EX ); + $self->lock_exclusive; my $length = $self->FETCHSIZE(); @@ -251,44 +247,59 @@ sub PUSH { return $length; } +# XXX This really needs to be something more direct within the file, not a +# fetch and re-store. -RobK, 2007-09-20 +sub _move_value { + my $self = shift; + my ($old_key, $new_key) = @_; + + return $self->_engine->make_reference( $self, $old_key, $new_key ); +} + sub SHIFT { my $self = shift->_get_self; + warn "SHIFT($self)\n" if DBM::Deep::DEBUG; - $self->lock( $self->LOCK_EX ); + $self->lock_exclusive; my $length = $self->FETCHSIZE(); - if ($length) { - my $content = $self->FETCH( 0 ); + if ( !$length ) { + $self->unlock; + return; + } + my $content = $self->DELETE( 0 ); + + # Unless the deletion above has cleared the array ... + if ( $length > 1 ) { for (my $i = 0; $i < $length - 1; $i++) { - $self->STORE( $i, $self->FETCH($i + 1) ); + $self->_move_value( $i+1, $i ); } + $self->DELETE( $length - 1 ); + } - $self->unlock; + $self->unlock; - return $content; - } - else { - $self->unlock; - return; - } + return $content; } sub UNSHIFT { my $self = shift->_get_self; my @new_elements = @_; - $self->lock( $self->LOCK_EX ); + $self->lock_exclusive; my $length = $self->FETCHSIZE(); my $new_size = scalar @new_elements; if ($length) { for (my $i = $length - 1; $i >= 0; $i--) { - $self->STORE( $i + $new_size, $self->FETCH($i) ); + $self->_move_value( $i, $i+$new_size ); } + + $self->STORESIZE( $length + $new_size ); } for (my $i = 0; $i < $new_size; $i++) { @@ -303,7 +314,7 @@ sub UNSHIFT { sub SPLICE { my $self = shift->_get_self; - $self->lock( $self->LOCK_EX ); + $self->lock_exclusive; my $length = $self->FETCHSIZE(); @@ -335,12 +346,13 @@ sub SPLICE { if ( $new_size != $splice_length ) { if ($new_size > $splice_length) { for (my $i = $length - 1; $i >= $offset + $splice_length; $i--) { - $self->STORE( $i + ($new_size - $splice_length), $self->FETCH($i) ); + $self->_move_value( $i, $i + ($new_size - $splice_length) ); } + $self->STORESIZE( $length + $new_size - $splice_length ); } else { for (my $i = $offset + $splice_length; $i < $length; $i++) { - $self->STORE( $i + ($new_size - $splice_length), $self->FETCH($i) ); + $self->_move_value( $i, $i + ($new_size - $splice_length) ); } for (my $i = 0; $i < $splice_length - $new_size; $i++) { $self->DELETE( $length - 1 ); @@ -366,12 +378,9 @@ sub SPLICE { # We don't need to populate it, yet. # It will be useful, though, when we split out HASH and ARRAY -sub EXTEND { - ## - # Perl will call EXTEND() when the array is likely to grow. - # We don't care, but include it because it gets called at times. - ## -} +# Perl will call EXTEND() when the array is likely to grow. +# We don't care, but include it because it gets called at times. +sub EXTEND {} sub _copy_node { my $self = shift; @@ -379,21 +388,29 @@ sub _copy_node { my $length = $self->length(); for (my $index = 0; $index < $length; $index++) { - my $value = $self->get($index); - $self->_copy_value( \$db_temp->[$index], $value ); + $self->_copy_value( \$db_temp->[$index], $self->get($index) ); } return 1; } -## -# Public method aliases -## -sub length { (shift)->FETCHSIZE(@_) } -sub pop { (shift)->POP(@_) } -sub push { (shift)->PUSH(@_) } -sub unshift { (shift)->UNSHIFT(@_) } -sub splice { (shift)->SPLICE(@_) } +sub _clear { + my $self = shift; + + my $size = $self->FETCHSIZE; + for my $key ( 0 .. $size - 1 ) { + $self->_engine->delete_key( $self, $key, $key ); + } + $self->STORESIZE( 0 ); + + return; +} + +sub length { (shift)->FETCHSIZE(@_) } +sub pop { (shift)->POP(@_) } +sub push { (shift)->PUSH(@_) } +sub unshift { (shift)->UNSHIFT(@_) } +sub splice { (shift)->SPLICE(@_) } # This must be last otherwise we have to qualify all other calls to shift # as calls to CORE::shift