From: Rob Kinyon Date: Fri, 25 Dec 2009 22:55:05 +0000 (-0500) Subject: Started refactoring of Iterator hierarchy X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits%2FDBM-Deep.git;a=commitdiff_plain;h=19b913ce4f25ce69bd69b4bf4a95ca99d4aa007e Started refactoring of Iterator hierarchy --- diff --git a/lib/DBM/Deep/Engine.pm b/lib/DBM/Deep/Engine.pm index 6e6147e..999a65c 100644 --- a/lib/DBM/Deep/Engine.pm +++ b/lib/DBM/Deep/Engine.pm @@ -243,7 +243,7 @@ sub get_next_key { # XXX Need to add logic about resetting the iterator if any key in the # reference has changed unless ( $prev_key ) { - $obj->{iterator} = DBM::Deep::Iterator->new({ + $obj->{iterator} = $self->iterator_class->new({ base_offset => $obj->_base_offset, engine => $self, }); diff --git a/lib/DBM/Deep/Engine/DBI.pm b/lib/DBM/Deep/Engine/DBI.pm index 39e7246..7d28615 100644 --- a/lib/DBM/Deep/Engine/DBI.pm +++ b/lib/DBM/Deep/Engine/DBI.pm @@ -11,6 +11,7 @@ use DBM::Deep::Sector::DBI (); use DBM::Deep::Storage::DBI (); sub sector_type { 'DBM::Deep::Sector::DBI' } +sub iterator_class { 'DBM::Deep::Iterator::DBI' } sub new { my $class = shift; diff --git a/lib/DBM/Deep/Engine/File.pm b/lib/DBM/Deep/Engine/File.pm index d40b51e..cda6128 100644 --- a/lib/DBM/Deep/Engine/File.pm +++ b/lib/DBM/Deep/Engine/File.pm @@ -14,6 +14,7 @@ use DBM::Deep::Sector::File (); use DBM::Deep::Storage::File (); sub sector_type { 'DBM::Deep::Sector::File' } +sub iterator_class { 'DBM::Deep::Iterator::File' } my $STALE_SIZE = 2; diff --git a/lib/DBM/Deep/Iterator.pm b/lib/DBM/Deep/Iterator.pm index 26e81a2..4dfe3e0 100644 --- a/lib/DBM/Deep/Iterator.pm +++ b/lib/DBM/Deep/Iterator.pm @@ -5,8 +5,8 @@ use 5.006_000; use strict; use warnings FATAL => 'all'; -use DBM::Deep::Iterator::BucketList (); -use DBM::Deep::Iterator::Index (); +use DBM::Deep::Iterator::DBI (); +use DBM::Deep::Iterator::File (); =head1 NAME @@ -63,110 +63,24 @@ This method returns nothing. =cut -sub reset { $_[0]{breadcrumbs} = [] } +sub reset { $_[0]{breadcrumbs} = []; return } =head2 get_sector_iterator( $loc ) -This takes a location. It will load the sector for $loc, then instantiate the right -iteartor type for it. +This takes a location. It will load the sector for $loc, then instantiate the +right iteartor type for it. This returns the sector iterator. =cut -sub get_sector_iterator { - my $self = shift; - my ($loc) = @_; - - my $sector = $self->{engine}->load_sector( $loc ) - or return; - - if ( $sector->isa( 'DBM::Deep::Sector::File::Index' ) ) { - return DBM::Deep::Iterator::Index->new({ - iterator => $self, - sector => $sector, - }); - } - elsif ( $sector->isa( 'DBM::Deep::Sector::File::BucketList' ) ) { - return DBM::Deep::Iterator::BucketList->new({ - iterator => $self, - sector => $sector, - }); - } - - DBM::Deep->_throw_error( "get_sector_iterator(): Why did $loc make a $sector?" ); -} +sub get_sector_iterator { die "get_sector_iterator must be implemented in a child class" } =head2 get_next_key( $obj ) =cut -sub get_next_key { - my $self = shift; - my ($obj) = @_; - - my $crumbs = $self->{breadcrumbs}; - my $e = $self->{engine}; - - unless ( @$crumbs ) { - # This will be a Reference sector - my $sector = $e->load_sector( $self->{base_offset} ) - # If no sector is found, this must have been deleted from under us. - or return; - - if ( $sector->staleness != $obj->_staleness ) { - return; - } - - my $loc = $sector->get_blist_loc - or return; - - push @$crumbs, $self->get_sector_iterator( $loc ); - } - - FIND_NEXT_KEY: { - # We're at the end. - unless ( @$crumbs ) { - $self->reset; - return; - } - - my $iterator = $crumbs->[-1]; - - # This level is done. - if ( $iterator->at_end ) { - pop @$crumbs; - redo FIND_NEXT_KEY; - } - - if ( $iterator->isa( 'DBM::Deep::Iterator::Index' ) ) { - # If we don't have any more, it will be caught at the - # prior check. - if ( my $next = $iterator->get_next_iterator ) { - push @$crumbs, $next; - } - redo FIND_NEXT_KEY; - } - - unless ( $iterator->isa( 'DBM::Deep::Iterator::BucketList' ) ) { - DBM::Deep->_throw_error( - "Should have a bucketlist iterator here - instead have $iterator" - ); - } - - # At this point, we have a BucketList iterator - my $key = $iterator->get_next_key; - if ( defined $key ) { - return $key; - } - #XXX else { $iterator->set_to_end() } ? - - # We hit the end of the bucketlist iterator, so redo - redo FIND_NEXT_KEY; - } - - DBM::Deep->_throw_error( "get_next_key(): How did we get here?" ); -} +sub get_next_key { die "get_next_key must be implemented in a child class" } 1; __END__ diff --git a/lib/DBM/Deep/Iterator/DBI.pm b/lib/DBM/Deep/Iterator/DBI.pm new file mode 100644 index 0000000..3b8f1c8 --- /dev/null +++ b/lib/DBM/Deep/Iterator/DBI.pm @@ -0,0 +1,9 @@ +package DBM::Deep::Iterator::DBI; + +use strict; +use warnings FATAL => 'all'; + +use base qw( DBM::Deep::Iterator ); + +1; +__END__ diff --git a/lib/DBM/Deep/Iterator/File.pm b/lib/DBM/Deep/Iterator/File.pm new file mode 100644 index 0000000..d2d5437 --- /dev/null +++ b/lib/DBM/Deep/Iterator/File.pm @@ -0,0 +1,102 @@ +package DBM::Deep::Iterator::File; + +use strict; +use warnings FATAL => 'all'; + +use base qw( DBM::Deep::Iterator ); + +use DBM::Deep::Iterator::File::BucketList (); +use DBM::Deep::Iterator::File::Index (); + +sub get_sector_iterator { + my $self = shift; + my ($loc) = @_; + + my $sector = $self->{engine}->load_sector( $loc ) + or return; + + if ( $sector->isa( 'DBM::Deep::Sector::File::Index' ) ) { + return DBM::Deep::Iterator::Index->new({ + iterator => $self, + sector => $sector, + }); + } + elsif ( $sector->isa( 'DBM::Deep::Sector::File::BucketList' ) ) { + return DBM::Deep::Iterator::BucketList->new({ + iterator => $self, + sector => $sector, + }); + } + + DBM::Deep->_throw_error( "get_sector_iterator(): Why did $loc make a $sector?" ); +} + +sub get_next_key { + my $self = shift; + my ($obj) = @_; + + my $crumbs = $self->{breadcrumbs}; + my $e = $self->{engine}; + + unless ( @$crumbs ) { + # This will be a Reference sector + my $sector = $e->load_sector( $self->{base_offset} ) + # If no sector is found, this must have been deleted from under us. + or return; + + if ( $sector->staleness != $obj->_staleness ) { + return; + } + + my $loc = $sector->get_blist_loc + or return; + + push @$crumbs, $self->get_sector_iterator( $loc ); + } + + FIND_NEXT_KEY: { + # We're at the end. + unless ( @$crumbs ) { + $self->reset; + return; + } + + my $iterator = $crumbs->[-1]; + + # This level is done. + if ( $iterator->at_end ) { + pop @$crumbs; + redo FIND_NEXT_KEY; + } + + if ( $iterator->isa( 'DBM::Deep::Iterator::Index' ) ) { + # If we don't have any more, it will be caught at the + # prior check. + if ( my $next = $iterator->get_next_iterator ) { + push @$crumbs, $next; + } + redo FIND_NEXT_KEY; + } + + unless ( $iterator->isa( 'DBM::Deep::Iterator::BucketList' ) ) { + DBM::Deep->_throw_error( + "Should have a bucketlist iterator here - instead have $iterator" + ); + } + + # At this point, we have a BucketList iterator + my $key = $iterator->get_next_key; + if ( defined $key ) { + return $key; + } + #XXX else { $iterator->set_to_end() } ? + + # We hit the end of the bucketlist iterator, so redo + redo FIND_NEXT_KEY; + } + + DBM::Deep->_throw_error( "get_next_key(): How did we get here?" ); +} + +1; +__END__ diff --git a/lib/DBM/Deep/Iterator/BucketList.pm b/lib/DBM/Deep/Iterator/File/BucketList.pm similarity index 97% rename from lib/DBM/Deep/Iterator/BucketList.pm rename to lib/DBM/Deep/Iterator/File/BucketList.pm index 577b5c2..d23a8ca 100644 --- a/lib/DBM/Deep/Iterator/BucketList.pm +++ b/lib/DBM/Deep/Iterator/File/BucketList.pm @@ -1,4 +1,4 @@ -package DBM::Deep::Iterator::BucketList; +package DBM::Deep::Iterator::File::BucketList; use 5.006_000; diff --git a/lib/DBM/Deep/Iterator/Index.pm b/lib/DBM/Deep/Iterator/File/Index.pm similarity index 97% rename from lib/DBM/Deep/Iterator/Index.pm rename to lib/DBM/Deep/Iterator/File/Index.pm index cdc28df..6c7f815 100644 --- a/lib/DBM/Deep/Iterator/Index.pm +++ b/lib/DBM/Deep/Iterator/File/Index.pm @@ -1,4 +1,4 @@ -package DBM::Deep::Iterator::Index; +package DBM::Deep::Iterator::File::Index; use 5.006_000;