Commit | Line | Data |
19b913ce |
1 | package DBM::Deep::Iterator::File; |
2 | |
3 | use strict; |
4 | use warnings FATAL => 'all'; |
5 | |
6 | use base qw( DBM::Deep::Iterator ); |
7 | |
8 | use DBM::Deep::Iterator::File::BucketList (); |
9 | use DBM::Deep::Iterator::File::Index (); |
10 | |
11 | sub get_sector_iterator { |
12 | my $self = shift; |
13 | my ($loc) = @_; |
14 | |
15 | my $sector = $self->{engine}->load_sector( $loc ) |
16 | or return; |
17 | |
18 | if ( $sector->isa( 'DBM::Deep::Sector::File::Index' ) ) { |
19 | return DBM::Deep::Iterator::Index->new({ |
20 | iterator => $self, |
21 | sector => $sector, |
22 | }); |
23 | } |
24 | elsif ( $sector->isa( 'DBM::Deep::Sector::File::BucketList' ) ) { |
25 | return DBM::Deep::Iterator::BucketList->new({ |
26 | iterator => $self, |
27 | sector => $sector, |
28 | }); |
29 | } |
30 | |
31 | DBM::Deep->_throw_error( "get_sector_iterator(): Why did $loc make a $sector?" ); |
32 | } |
33 | |
34 | sub get_next_key { |
35 | my $self = shift; |
36 | my ($obj) = @_; |
37 | |
38 | my $crumbs = $self->{breadcrumbs}; |
39 | my $e = $self->{engine}; |
40 | |
41 | unless ( @$crumbs ) { |
42 | # This will be a Reference sector |
43 | my $sector = $e->load_sector( $self->{base_offset} ) |
44 | # If no sector is found, this must have been deleted from under us. |
45 | or return; |
46 | |
47 | if ( $sector->staleness != $obj->_staleness ) { |
48 | return; |
49 | } |
50 | |
51 | my $loc = $sector->get_blist_loc |
52 | or return; |
53 | |
54 | push @$crumbs, $self->get_sector_iterator( $loc ); |
55 | } |
56 | |
57 | FIND_NEXT_KEY: { |
58 | # We're at the end. |
59 | unless ( @$crumbs ) { |
60 | $self->reset; |
61 | return; |
62 | } |
63 | |
64 | my $iterator = $crumbs->[-1]; |
65 | |
66 | # This level is done. |
67 | if ( $iterator->at_end ) { |
68 | pop @$crumbs; |
69 | redo FIND_NEXT_KEY; |
70 | } |
71 | |
72 | if ( $iterator->isa( 'DBM::Deep::Iterator::Index' ) ) { |
73 | # If we don't have any more, it will be caught at the |
74 | # prior check. |
75 | if ( my $next = $iterator->get_next_iterator ) { |
76 | push @$crumbs, $next; |
77 | } |
78 | redo FIND_NEXT_KEY; |
79 | } |
80 | |
81 | unless ( $iterator->isa( 'DBM::Deep::Iterator::BucketList' ) ) { |
82 | DBM::Deep->_throw_error( |
83 | "Should have a bucketlist iterator here - instead have $iterator" |
84 | ); |
85 | } |
86 | |
87 | # At this point, we have a BucketList iterator |
88 | my $key = $iterator->get_next_key; |
89 | if ( defined $key ) { |
90 | return $key; |
91 | } |
92 | #XXX else { $iterator->set_to_end() } ? |
93 | |
94 | # We hit the end of the bucketlist iterator, so redo |
95 | redo FIND_NEXT_KEY; |
96 | } |
97 | |
98 | DBM::Deep->_throw_error( "get_next_key(): How did we get here?" ); |
99 | } |
100 | |
101 | 1; |
102 | __END__ |