File Coverage

blib/lib/BeePack.pm
Criterion Covered Total %
statement 8 10 80.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 12 14 85.7


line stmt bran cond sub pod time code
1             package BeePack;
2             BEGIN {
3 3     3   71028 $BeePack::AUTHORITY = 'cpan:GETTY';
4             }
5             # ABSTRACT: Primitive MsgPack based key value storage
6             $BeePack::VERSION = '0.101';
7 3     3   1606 use Moo;
  3         39533  
  3         15  
8 3     3   4884 use bytes;
  3         23  
  3         14  
9 3     3   2195 use CDB::TinyCDB;
  0            
  0            
10             use Data::MessagePack;
11             use Carp qw( croak );
12              
13             sub true { Data::MessagePack::true() }
14             sub false { Data::MessagePack::false() }
15              
16             # currently workaround to be reset
17             has cdb => (
18             is => 'rw',
19             lazy => 1,
20             builder => 1,
21             init_arg => undef,
22             handles => [qw(
23             keys
24             )],
25             );
26              
27             sub _build_cdb {
28             my ( $self ) = @_;
29             return -f $self->filename
30             ? CDB::TinyCDB->open($self->filename, $self->has_tempfile ? (
31             for_update => $self->tempfile
32             ) : ())
33             : $self->readonly
34             ? croak("Can't open non-existing readonly database ".$self->filename)
35             : CDB::TinyCDB->create($self->filename,$self->tempfile);
36             }
37              
38             has filename => (
39             is => 'ro',
40             required => 1,
41             );
42              
43             has tempfile => (
44             is => 'ro',
45             predicate => 1,
46             );
47              
48             has nil_exists => (
49             is => 'lazy',
50             );
51              
52             sub _build_nil_exists { 1 }
53              
54             has readonly => (
55             is => 'lazy',
56             );
57              
58             sub _build_readonly {
59             my ( $self ) = @_;
60             return $self->has_tempfile ? 0 : 1;
61             }
62              
63             has data_messagepack => (
64             is => 'lazy',
65             init_arg => undef,
66             );
67              
68             sub _build_data_messagepack {
69             Data::MessagePack->new->canonical->utf8
70             }
71              
72             sub BUILD {
73             my ( $self ) = @_;
74             croak("Read/Write opening requires tempfile") if !$self->readonly && !$self->has_tempfile;
75             $self->cdb;
76             $self->data_messagepack;
77             }
78              
79             sub open {
80             my ( $class, $filename, $tempfile, %attr ) = @_;
81             return $class->new(
82             filename => $filename,
83             defined $tempfile ? ( tempfile => $tempfile ) : (),
84             %attr,
85             );
86             }
87              
88             sub set {
89             my ( $self, $key, $value ) = @_;
90             croak("Trying to set on readonly BeePack") if $self->readonly;
91             $self->cdb->put_replace($key,$self->data_messagepack->pack($value));
92             }
93              
94             sub set_type {
95             my ( $self, $key, $type, $value ) = @_;
96             croak("Trying to set on readonly BeePack") if $self->readonly;
97             my $t = defined $type ? substr($type,0,1) : '';
98             if ($t eq 'i') {
99             $self->set_integer($key,$value);
100             } elsif ($t eq 'b') {
101             $self->set_bool($key,$value);
102             } elsif ($t eq 's') {
103             $self->set_string($key,$value);
104             } elsif ($t eq 'n') {
105             $self->set_nil($key,$value);
106             } elsif ($t eq 'a') {
107             my @array = @{$value};
108             $self->set($key,\@array);
109             } elsif ($t eq 'h') {
110             my %hash = %{$value};
111             $self->set($key,\%hash);
112             } elsif ($t eq '') {
113             $self->set($key,$value);
114             }
115             }
116              
117             sub set_integer {
118             my ( $self, $key, $value ) = @_;
119             $self->set($key, 0 + $value);
120             }
121              
122             sub set_bool {
123             my ( $self, $key, $value ) = @_;
124             $self->set($key, $value
125             ? Data::MessagePack::true()
126             : Data::MessagePack::false()
127             );
128             }
129              
130             sub set_string {
131             my ( $self, $key, $value ) = @_;
132             $self->set($key, "$value");
133             }
134              
135             sub set_nil {
136             my ( $self, $key ) = @_;
137             $self->set($key, undef);
138             }
139              
140             sub exists {
141             my ( $self, $key ) = @_;
142             return 0 unless $self->cdb->exists($key);
143             my $msgpack = $self->cdb->get($key);
144             my $value = $self->data_messagepack->unpack($msgpack);
145             return defined $value ? 1 : 0;
146             }
147              
148             sub get {
149             my ( $self, $key ) = @_;
150             return undef unless $self->exists($key);
151             return $self->data_messagepack->unpack(scalar $self->cdb->get($key));
152             }
153              
154             sub get_raw {
155             my ( $self, $key ) = @_;
156             return scalar $self->cdb->get($key);
157             }
158              
159             sub save {
160             my ( $self ) = @_;
161             croak("Trying to save readonly CDB ".$self->filename) if $self->readonly;
162             $self->cdb->finish( save_changes => 1, reopen => 0 );
163             # Bug in CDB::TinyCDB? reopen => 1 is not reopening
164             $self->cdb(undef);
165             $self->cdb($self->_build_cdb);
166             return 1;
167             }
168              
169             1;
170              
171             __END__