Added description to a test
[dbsrgits/DBM-Deep.git] / lib / DBM / Deep / Iterator.pm
CommitLineData
065b45be 1package DBM::Deep::Iterator;
2
9c7d9738 3use 5.006_000;
065b45be 4
5use strict;
6use warnings FATAL => 'all';
7
8use Scalar::Util ();
9
10use DBM::Deep::Iterator::Index;
11use DBM::Deep::Iterator::BucketList;
12
13sub new {
14 my $class = shift;
15 my ($args) = @_;
16
17 my $self = bless {
18 breadcrumbs => [],
19 engine => $args->{engine},
20 base_offset => $args->{base_offset},
21 }, $class;
22
23 Scalar::Util::weaken( $self->{engine} );
24
25 return $self;
26}
27
28sub reset { $_[0]{breadcrumbs} = [] }
29
30sub get_sector_iterator {
31 my $self = shift;
32 my ($loc) = @_;
33
34 my $sector = $self->{engine}->_load_sector( $loc )
35 or return;
36
37 if ( $sector->isa( 'DBM::Deep::Engine::Sector::Index' ) ) {
38 return DBM::Deep::Iterator::Index->new({
39 iterator => $self,
40 sector => $sector,
41 });
42 }
43 elsif ( $sector->isa( 'DBM::Deep::Engine::Sector::BucketList' ) ) {
44 return DBM::Deep::Iterator::BucketList->new({
45 iterator => $self,
46 sector => $sector,
47 });
48 }
49
50 DBM::Deep->_throw_error( "get_sector_iterator(): Why did $loc make a $sector?" );
51}
52
53sub get_next_key {
54 my $self = shift;
55 my ($obj) = @_;
56
57 my $crumbs = $self->{breadcrumbs};
58 my $e = $self->{engine};
59
9c87a079 60 warn "1\n";
065b45be 61 unless ( @$crumbs ) {
62 # This will be a Reference sector
63 my $sector = $e->_load_sector( $self->{base_offset} )
64 # If no sector is found, thist must have been deleted from under us.
65 or return;
66
67 if ( $sector->staleness != $obj->_staleness ) {
68 return;
69 }
70
71 my $loc = $sector->get_blist_loc
72 or return;
73
74 push @$crumbs, $self->get_sector_iterator( $loc );
75 }
76
9c87a079 77 warn "2: " . $obj->_dump_file;
065b45be 78 FIND_NEXT_KEY: {
79 # We're at the end.
80 unless ( @$crumbs ) {
81 $self->reset;
82 return;
83 }
84
85 my $iterator = $crumbs->[-1];
86
87 # This level is done.
88 if ( $iterator->at_end ) {
89 pop @$crumbs;
90 redo FIND_NEXT_KEY;
91 }
92
93 if ( $iterator->isa( 'DBM::Deep::Iterator::Index' ) ) {
94 # If we don't have any more, it will be caught at the
95 # prior check.
96 if ( my $next = $iterator->get_next_iterator ) {
97 push @$crumbs, $next;
98 }
99 redo FIND_NEXT_KEY;
100 }
101
102 unless ( $iterator->isa( 'DBM::Deep::Iterator::BucketList' ) ) {
103 DBM::Deep->_throw_error(
104 "Should have a bucketlist iterator here - instead have $iterator"
105 );
106 }
107
108 # At this point, we have a BucketList iterator
109 my $key = $iterator->get_next_key;
110 if ( defined $key ) {
111 return $key;
112 }
113 #XXX else { $iterator->set_to_end() } ?
114
115 # We hit the end of the bucketlist iterator, so redo
116 redo FIND_NEXT_KEY;
117 }
118
119 DBM::Deep->_throw_error( "get_next_key(): How did we get here?" );
120}
121
1221;
123__END__