990d357380e8b7fe72a28a37b4a78bf3d091ebfa
[dbsrgits/DBM-Deep.git] / lib / DBM / Deep / Engine / Sector.pm
1 package DBM::Deep::Engine::Sector;
2
3 use 5.006_000;
4
5 use strict;
6 use warnings FATAL => 'all';
7
8 use Scalar::Util ();
9
10 sub new {
11     my $self = bless $_[1], $_[0];
12     Scalar::Util::weaken( $self->{engine} );
13
14     if ( $self->offset ) {
15         $self->{string} = $self->engine->storage->read_at(
16             $self->offset, $self->size,
17         );
18     }
19     else {
20         $self->{string} = chr(0) x $self->size;
21     }
22
23     $self->_init;
24
25     return $self;
26 }
27
28 #sub _init {}
29 #sub clone { DBM::Deep->_throw_error( "Must be implemented in the child class" ); }
30
31 sub engine { $_[0]{engine} }
32 sub offset { $_[0]{offset} }
33 sub type   { $_[0]{type}   }
34
35 sub base_size {
36    my $self = shift;
37    no warnings 'once';
38    return $self->engine->SIG_SIZE + $DBM::Deep::Engine::STALE_SIZE;
39 }
40
41 sub free {
42     my $self = shift;
43
44     my $e = $self->engine;
45
46     $self->write( 0, $e->SIG_FREE );
47     $self->write( $self->base_size, chr(0) x ($self->size - $self->base_size) );
48
49     $e->flush;
50
51 #    $e->storage->print_at( $self->offset, $e->SIG_FREE );
52 #    # Skip staleness counter
53 #    $e->storage->print_at( $self->offset + $self->base_size,
54 #        chr(0) x ($self->size - $self->base_size),
55 #    );
56
57     #TODO When freeing two sectors, we cannot flush them right away! This means the following:
58     # 1) The header has to understand about unflushed items.
59     # 2) Loading a sector has to go through a cache to make sure we see what's already been loaded.
60     # 3) The header should be cached.
61
62     my $free_meth = $self->free_meth;
63     $e->$free_meth( $self->offset, $self->size );
64
65     return;
66 }
67
68 sub read {
69     my $self = shift;
70     my ($start, $length) = @_;
71     if ( $length ) {
72         return substr( $self->{string}, $start, $length );
73     }
74     else {
75         return substr( $self->{string}, $start );
76     }
77 }
78
79 sub write {
80     my $self = shift;
81     my ($start, $text) = @_;
82
83     substr( $self->{string}, $start, length($text) ) = $text;
84
85     $self->mark_dirty;
86 }
87
88 sub mark_dirty {
89     my $self = shift;
90     $self->engine->add_dirty_sector( $self );
91 }
92
93 sub flush {
94     my $self = shift;
95     $self->engine->storage->print_at( $self->offset, $self->{string} );
96 }
97
98 1;
99 __END__