21f6273855d4a119be83a6840b8efbdef53d8668
[dbsrgits/DBM-Deep.git] / lib / DBM / Deep / Sector / File.pm
1 package DBM::Deep::Sector::File;
2
3 use 5.006_000;
4
5 use strict;
6 use warnings FATAL => 'all';
7
8 use base qw( DBM::Deep::Sector );
9
10 use DBM::Deep::Sector::File::Reference;
11 use DBM::Deep::Sector::File::BucketList;
12 use DBM::Deep::Sector::File::Index;
13 use DBM::Deep::Sector::File::Null;
14 use DBM::Deep::Sector::File::Scalar;
15
16 my $STALE_SIZE = 2;
17
18 sub base_size {
19     my $self = shift;
20     return $self->engine->SIG_SIZE + $STALE_SIZE;
21 }
22
23 sub free_meth { die "free_meth must be implemented in a child class" }
24
25 sub free {
26     my $self = shift;
27
28     my $e = $self->engine;
29
30     $e->storage->print_at( $self->offset, $e->SIG_FREE );
31     # Skip staleness counter
32     $e->storage->print_at( $self->offset + $self->base_size,
33         chr(0) x ($self->size - $self->base_size),
34     );
35
36     my $free_meth = $self->free_meth;
37     $e->$free_meth( $self->offset, $self->size );
38
39     return;
40 }
41
42 =head2 load( $offset )
43
44 This will instantiate and return the sector object that represents the data
45 found at $offset.
46
47 =cut
48
49 sub load {
50     my $self = shift;
51     my ($engine, $offset) = @_;
52
53     # Add a catch for offset of 0 or 1
54     return if !$offset || $offset <= 1;
55
56     my $type = $engine->storage->read_at( $offset, 1 );
57     return if $type eq chr(0);
58
59     if ( $type eq $engine->SIG_ARRAY || $type eq $engine->SIG_HASH ) {
60         return DBM::Deep::Sector::File::Reference->new({
61             engine => $engine,
62             type   => $type,
63             offset => $offset,
64         });
65     }
66     # XXX Don't we need key_md5 here?
67     elsif ( $type eq $engine->SIG_BLIST ) {
68         return DBM::Deep::Sector::File::BucketList->new({
69             engine => $engine,
70             type   => $type,
71             offset => $offset,
72         });
73     }
74     elsif ( $type eq $engine->SIG_INDEX ) {
75         return DBM::Deep::Sector::File::Index->new({
76             engine => $engine,
77             type   => $type,
78             offset => $offset,
79         });
80     }
81     elsif ( $type eq $engine->SIG_NULL ) {
82         return DBM::Deep::Sector::File::Null->new({
83             engine => $engine,
84             type   => $type,
85             offset => $offset,
86         });
87     }
88     elsif ( $type eq $engine->SIG_DATA ) {
89         return DBM::Deep::Sector::File::Scalar->new({
90             engine => $engine,
91             type   => $type,
92             offset => $offset,
93         });
94     }
95     # This was deleted from under us, so just return and let the caller figure it out.
96     elsif ( $type eq $engine->SIG_FREE ) {
97         return;
98     }
99
100     DBM::Deep->_throw_error( "'$offset': Don't know what to do with type '$type'" );
101 }
102
103 1;
104 __END__