File Coverage

blib/lib/CDB/TinyCDB/Wrapper.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package CDB::TinyCDB::Wrapper;
2              
3 1     1   23879 use warnings;
  1         3  
  1         28  
4 1     1   5 use strict;
  1         1  
  1         25  
5 1     1   332 use CDB::TinyCDB;
  0            
  0            
6              
7             =head1 NAME
8              
9             CDB::TinyCDB::Wrapper - A wrapper around CDB::TinyCDB to try and make
10             updating its files a little more transparent
11              
12             =head1 VERSION
13              
14             Version 0.03
15              
16             =cut
17              
18             our $VERSION = '0.03';
19              
20             =head1 SYNOPSIS
21              
22             Quick summary of what the module does.
23              
24             Perhaps a little code snippet.
25              
26             use CDB::TinyCDB::Wrapper;
27             my $db = CDB::TinyCDB::Wrapper->new();
28             ...
29              
30             =head1 SUBROUTINES/METHODS
31              
32             =head2 new
33              
34             =cut
35              
36             sub new {
37             my ($class, $filename) = @_;
38             $class = ref($class) || $class;
39             my $self = {filename => $filename,
40             modified => {}};
41              
42             # If the file doesn't exist, dummy an empty file up. We can get away
43             # with this because the BayesStore checks for file existence itself
44             unless (-f $filename) {
45             my $tmp;
46             unless ($tmp = CDB::TinyCDB->create ($filename, "$filename.$$")) {
47             #warn("Couldn't open $filename: $!");
48             return 0;
49             }
50             $tmp->finish;
51             }
52              
53             unless ($self->{cdb} = CDB::TinyCDB->load ($filename)) {
54             #warn("Couldn't open $filename: $!");
55             return 0;
56             }
57              
58             bless ($self, $class);
59             $self;
60             }
61              
62             =head2 abandon
63              
64             Indicates that whatever alterations were made should be thrown away
65             when the file is closed.
66              
67             =cut
68              
69             sub abandon {
70             my ($self) = @_;
71             $self->{discard}++;
72             $self->close;
73             }
74              
75             =head2 close
76              
77             Closes the CDB file, rebuilding the file reflecting any changes that
78             were made.
79              
80             =cut
81              
82             sub close {
83             my ($self) = @_;
84              
85             # If keys were modified and we want to preserve the changes
86             if (CORE::keys %{$self->{modified}} and !$self->{discard}) {
87             #warn "Keys were modified\n";
88             $self->_reset_each;
89             # Start with the existing file
90             #warn "Creating new temp file\n";
91             my $tmp = CDB::TinyCDB->create ($self->{filename}, "$self->{filename}.$$");
92             #warn "Starting loop\n";
93             # Iterate over all values that were in the modified list
94             while (my ($key, $value) = CORE::each %{$self->{modified}}) {
95             # Skip undefined (deleted) values
96             next unless defined $value;
97             $tmp->put_add ($key, $value);
98             }
99             # Iterate over all keys, copying appropriate values to the new db
100             while (my ($key, $value) = $self->{cdb}->each) {
101             $tmp->put_add ($key, $value) unless exists $self->{modified}->{$key};
102             }
103             # Store our changes
104             $tmp->finish;
105             }
106              
107             delete $self->{cdb};
108              
109             return 1;
110             }
111              
112             =head2 del
113              
114             Delete the key from the DB.
115              
116             =cut
117              
118             sub del {
119             my ($self, $key) = @_;
120             $self->{modified}->{$key} = undef;
121             return 1;
122             }
123              
124             =head2 exists
125              
126             Checks whether the key exists in the db
127              
128             =cut
129              
130             sub exists {
131             my ($self, $key) = @_;
132             return defined $self->{modified}->{$key} || $self->{cdb}->exists ($key);
133             }
134              
135             =head2 each
136              
137             Iterates through the DB, returning tuples of ($key, $value) each time
138             it's called.
139              
140             =cut
141              
142             {
143             my @each = ();
144             my $eof = 0;
145              
146             sub each {
147             my ($self) = @_;
148             my @return = ();
149             if ($eof) {
150             #warn "At the end of the list, resetting\n";
151             $eof = 0;
152             return ();
153             } else {
154             unless (@each) {
155             #warn "Refilling the list\n";
156             @each = sort $self->keys;
157             #my $output = Dumper \@each;
158             #warn "List is " . substr ($output, 0, 1000);
159             }
160             if (defined (my $key = shift @each)) {
161             #warn "key is $key\n";
162             $eof = @each ? 0 : 1;
163             #warn "EOF is $eof\n";
164             return ($key, exists $self->{modified}->{$key} ? $self->{modified}->{$key} : $self->{cdb}->get ($key));
165             } else {
166             # If the list is empty the first time through, we'll end up
167             # here
168             return ();
169             }
170             }
171             }
172              
173             =head2 _reset_each
174              
175             Iterates through the DB, returning tuples of ($key, $value) each time
176             it's called.
177              
178             =cut
179              
180             sub _reset_each {
181             @each = ();
182             $eof = 0;
183             }
184             }
185              
186             =head2 get
187              
188             Retrieves the specified key from the DB. Returns 'undef' if the key
189             doesn't exist.
190              
191             =cut
192              
193             sub get {
194             my ($self, $key) = @_;
195             return exists $self->{modified}->{$key} ? $self->{modified}->{$key} : $self->{cdb}->get ($key);
196             }
197              
198             =head2 keys
199              
200             Retrieves the list of keys from the DB.
201              
202             =cut
203              
204             sub keys {
205             my ($self) = @_;
206             # Hold our list of keys
207             my %keys;
208             # Get the keys on disk
209             map {$keys{$_}++} $self->{cdb}->keys;
210             # Iterate over the keys in memory
211             for my $key (CORE::keys %{$self->{modified}}) {
212             # If the key has a value in memory, make sure it's includee
213             if (defined $self->{modified}->{$key}) {
214             $keys{$key}++
215             } else {
216             # This has been deleted in memory, delete from list of keys
217             delete $keys{$key};
218             }
219             }
220             return CORE::keys %keys;
221             }
222              
223             =head2 set
224              
225             Sets the specified key to the specified value in the DB.
226              
227             =cut
228              
229             sub set {
230             my ($self, $key, $value) = @_;
231             $self->{modified}->{$key} = $value;
232             }
233              
234             =head2 DESTROY
235              
236             Called when the object is deleted or goes out of scope, it closes the
237             file. This is just here for compatibility with versions < 0.3---all
238             new development should explicitly call close, or risk potential issues
239             if the data doesn't get GC'd immediately.
240              
241             =cut
242              
243             sub DESTROY {
244             my ($self) = @_;
245             $self->close if ($self->{cdb});
246             }
247              
248             =head1 AUTHOR
249              
250             Michael Alan Dorman, C<< >>
251              
252             =head1 BUGS
253              
254             Please report any bugs or feature requests to
255             C, or through the web
256             interface at
257             L.
258             I will be notified, and then you'll automatically be notified of
259             progress on your bug as I make changes.
260              
261             =head1 SUPPORT
262              
263             You can find documentation for this module with the perldoc command.
264              
265             perldoc CDB::TinyCDB::Wrapper
266              
267             You can also look for information at:
268              
269             =over 4
270              
271             =item * RT: CPAN's request tracker
272              
273             L
274              
275             =item * AnnoCPAN: Annotated CPAN documentation
276              
277             L
278              
279             =item * CPAN Ratings
280              
281             L
282              
283             =item * Search CPAN
284              
285             L
286              
287             =back
288              
289             =head1 ACKNOWLEDGEMENTS
290              
291             CDB::TinyCDB, without which this module would have no reason to exist
292              
293             =head1 LICENSE AND COPYRIGHT
294              
295             Copyright 2010 Michael Alan Dorman.
296              
297             This program is free software; you can redistribute it and/or modify it
298             under the terms of either: the GNU General Public License as published
299             by the Free Software Foundation; or the Artistic License.
300              
301             See http://dev.perl.org/licenses/ for more information.
302              
303             =cut
304              
305             1; # End of CDB::TinyCDB::Wrapper