Before the clear() bug was fixed, t/03_bighash.t took 45 sec., for me
at least. It was using a ‘first_key next_key*’ approach, which ended
up skipping keys, since they were being deleted during iteration. When
clear() was fixed, a ‘first_key+’ approach was used, which was *much*
slower, since it created a new iterator object for each key. That test
script ended up taking 2 hours!
I found that a compromise, using ‘first_key next_key*’ repeatedly
until first_key stopped returning a key, would reduce the time to 65
seconds. Then I found that pushing the functionality further inside
the engine and freeing the index or bucket list reduces it to 25 sec-
onds. Transactions make things a little more complicated, so I fall
back to the compromise in the presence of transactions.
my $self = shift->_get_self;
warn "CLEAR($self)\n" if DEBUG;
- unless ( $self->_engine->storage->is_writable ) {
+ my $engine = $self->_engine;
+ unless ( $engine->storage->is_writable ) {
$self->_throw_error( 'Cannot write to a readonly filehandle' );
}
$self->lock_exclusive;
# Dispatch to the specific clearing functionality.
- $self->_clear;
+ $engine->clear($self);
$self->unlock;
=item * get_next_key
+=item * clear
+
=item * setup_fh
=item * begin_work
return $obj->{iterator}->get_next_key( $obj );
}
+=head2 clear( $obj )
+
+This takes an object that provides _base_offset() and deletes all its
+elements, returning nothing.
+
+=cut
+
+sub clear {
+ my $self = shift;
+ my $obj = shift;
+
+ my $sector = $self->_load_sector( $obj->_base_offset )
+ or return;
+
+ if ( $sector->staleness != $obj->_staleness ) {
+ return;
+ }
+
+ $sector->clear;
+ return;
+}
+
=head2 setup_fh( $obj )
This takes an object that provides _base_offset(). It will do everything needed
return $data;
}
+sub clear {
+ my $self = shift;
+
+ my $blist_loc = $self->get_blist_loc or return;
+
+ my $engine = $self->engine;
+
+ if($engine->get_running_txn_ids) {
+ # ~~~ Temporary; the code below this block needs to be modified to
+ # take transactions into account.
+ $self->data->_clear;
+ return;
+ }
+
+ my $sector = $engine->_load_sector( $blist_loc )
+ or DBM::Deep->_throw_error(
+ "Cannot read sector at $blist_loc in clear()"
+ );
+
+ # Set blist offset to 0
+ $engine->storage->print_at( $self->offset + $self->base_size,
+ pack( $StP{$engine->byte_size}, 0 ),
+ );
+
+ # Free the blist
+ $sector->free;
+
+ return;
+}
+
sub get_blist_loc {
my $self = shift;
my $self = shift;
while ( defined(my $key = $self->first_key) ) {
+ do {
$self->_engine->delete_key( $self, $key, $key );
+ } while defined($key = $self->next_key($key));
}
return;