Optimization: First broke out all the classes that were in Engine.pm so that I can...
[dbsrgits/DBM-Deep.git] / lib / DBM / Deep / Engine / Sector / Index.pm
1 #TODO: Convert this to a string
2 package DBM::Deep::Engine::Sector::Index;
3
4 use 5.006;
5
6 use strict;
7 use warnings FATAL => 'all';
8
9 use DBM::Deep::Engine::Sector;
10 our @ISA = qw( DBM::Deep::Engine::Sector );
11
12 sub _init {
13     my $self = shift;
14
15     my $engine = $self->engine;
16
17     unless ( $self->offset ) {
18         my $leftover = $self->size - $self->base_size;
19
20         $self->{offset} = $engine->_request_index_sector( $self->size );
21         $engine->storage->print_at( $self->offset, $engine->SIG_INDEX ); # Sector type
22         # Skip staleness counter
23         $engine->storage->print_at( $self->offset + $self->base_size,
24             chr(0) x $leftover, # Zero-fill the rest
25         );
26     }
27
28     return $self;
29 }
30
31 #XXX Change here
32 sub size {
33     my $self = shift;
34     unless ( $self->{size} ) {
35         my $e = $self->engine;
36         $self->{size} = $self->base_size + $e->byte_size * $e->hash_chars;
37     }
38     return $self->{size};
39 }
40
41 sub free_meth { return '_add_free_index_sector' }
42
43 sub free {
44     my $self = shift;
45     my $e = $self->engine;
46
47     for my $i ( 0 .. $e->hash_chars - 1 ) {
48         my $l = $self->get_entry( $i ) or next;
49         $e->_load_sector( $l )->free;
50     }
51
52     $self->SUPER::free();
53 }
54
55 sub _loc_for {
56     my $self = shift;
57     my ($idx) = @_;
58     return $self->offset + $self->base_size + $idx * $self->engine->byte_size;
59 }
60
61 sub get_entry {
62     my $self = shift;
63     my ($idx) = @_;
64
65     my $e = $self->engine;
66
67     DBM::Deep->_throw_error( "get_entry: Out of range ($idx)" )
68         if $idx < 0 || $idx >= $e->hash_chars;
69
70     return unpack(
71         $e->StP($e->byte_size),
72         $e->storage->read_at( $self->_loc_for( $idx ), $e->byte_size ),
73     );
74 }
75
76 sub set_entry {
77     my $self = shift;
78     my ($idx, $loc) = @_;
79
80     my $e = $self->engine;
81
82     DBM::Deep->_throw_error( "set_entry: Out of range ($idx)" )
83         if $idx < 0 || $idx >= $e->hash_chars;
84
85     $self->engine->storage->print_at(
86         $self->_loc_for( $idx ),
87         pack( $e->StP($e->byte_size), $loc ),
88     );
89 }
90
91 1;
92 __END__