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   73403 $BeePack::AUTHORITY = 'cpan:GETTY';
4             }
5             # ABSTRACT: Primitive MsgPack based key value storage
6             $BeePack::VERSION = '0.102';
7 3     3   1529 use Moo;
  3         37769  
  3         15  
8 3     3   4463 use bytes;
  3         24  
  3         16  
9 3     3   2262 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 { 0 }
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 { Data::MessagePack->new->canonical->utf8 }
69              
70             sub BUILD {
71             my ( $self ) = @_;
72             croak("Read/Write opening requires tempfile") if !$self->readonly && !$self->has_tempfile;
73             $self->cdb;
74             $self->data_messagepack;
75             }
76              
77             sub open {
78             my ( $class, $filename, $tempfile, %attr ) = @_;
79             return $class->new(
80             filename => $filename,
81             defined $tempfile ? ( tempfile => $tempfile ) : (),
82             %attr,
83             );
84             }
85              
86             sub set {
87             my ( $self, $key, $value ) = @_;
88             $self->readonly_check;
89             $self->cdb->put_replace($key,$self->data_messagepack->pack($value));
90             }
91              
92             sub readonly_check {
93             my ( $self ) = @_;
94             croak("Trying to set on readonly BeePack") if $self->readonly;
95             }
96              
97             sub set_type {
98             my ( $self, $key, $type, $value ) = @_;
99             $self->readonly_check;
100             my $t = defined $type ? substr($type,0,1) : '';
101             if ($t eq 'i') {
102             $self->set_integer($key,$value);
103             } elsif ($t eq 'b') {
104             $self->set_bool($key,$value);
105             } elsif ($t eq 's') {
106             $self->set_string($key,$value);
107             } elsif ($t eq 'n') {
108             $self->set_nil($key,$value);
109             } elsif ($t eq 'a') {
110             my @array = @{$value};
111             $self->set($key,\@array);
112             } elsif ($t eq 'h') {
113             my %hash = %{$value};
114             $self->set($key,\%hash);
115             } elsif ($t eq '') {
116             $self->set($key,$value);
117             }
118             }
119              
120             sub set_integer {
121             my ( $self, $key, $value ) = @_;
122             $self->set($key, 0 + $value);
123             }
124              
125             sub set_bool {
126             my ( $self, $key, $value ) = @_;
127             $self->set($key, $value
128             ? Data::MessagePack::true()
129             : Data::MessagePack::false()
130             );
131             }
132              
133             sub set_string {
134             my ( $self, $key, $value ) = @_;
135             $self->set($key, "$value");
136             }
137              
138             sub set_nil {
139             my ( $self, $key ) = @_;
140             $self->set($key, undef);
141             }
142              
143             sub exists {
144             my ( $self, $key ) = @_;
145             return 0 unless $self->cdb->exists($key);
146             return $self->cdb->exists($key) if $self->nil_exists;
147             my $msgpack = $self->cdb->get($key);
148             my $value = $self->data_messagepack->unpack($msgpack);
149             return defined $value ? 1 : 0;
150             }
151              
152             sub get {
153             my ( $self, $key ) = @_;
154             return undef unless $self->exists($key);
155             return $self->data_messagepack->unpack(scalar $self->cdb->get($key));
156             }
157              
158             sub get_raw {
159             my ( $self, $key ) = @_;
160             return scalar $self->cdb->get($key);
161             }
162              
163             sub save {
164             my ( $self ) = @_;
165             croak("Trying to save readonly CDB ".$self->filename) if $self->readonly;
166             $self->cdb->finish( save_changes => 1, reopen => 0 );
167             # Bug in CDB::TinyCDB? reopen => 1 is not reopening
168             $self->cdb(undef);
169             $self->cdb($self->_build_cdb);
170             return 1;
171             }
172              
173             1;
174              
175             __END__