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