File Coverage

lib/App/SharedDatastore.pm
Criterion Covered Total %
statement 80 84 95.2
branch 37 56 66.0
condition 2 3 66.6
subroutine 13 13 100.0
pod 7 7 100.0
total 139 163 85.2


line stmt bran cond sub pod time code
1              
2             #############################################################################
3             ## $Id: SharedDatastore.pm 10851 2008-02-28 19:50:01Z spadkins $
4             #############################################################################
5              
6             package App::SharedDatastore;
7             $VERSION = (q$Revision: 10851 $ =~ /(\d[\d\.]*)/)[0]; # VERSION numbers generated by svn
8              
9 1     1   7 use App;
  1         2  
  1         25  
10 1     1   595 use App::Service;
  1         3  
  1         31  
11             @ISA = ( "App::Service" );
12              
13 1     1   5 use strict;
  1         2  
  1         24  
14              
15 1     1   1058 use Storable qw(nfreeze thaw);
  1         3365  
  1         75  
16 1     1   2181 use Digest::SHA qw(sha1_hex);
  1         3898  
  1         909  
17              
18             $Storable::canonical = 1; # this will cause hashes to be serialized the same way every time
19              
20             =head1 NAME
21              
22             App::SharedDatastore - Interface for sharing data between processes
23              
24             =head1 SYNOPSIS
25              
26             use App;
27              
28             $context = App->context();
29             $sds = $context->service("SharedDatastore");
30             $sds = $context->shared_datastore();
31              
32             =head1 DESCRIPTION
33              
34             A SharedDatastore service represents a single hash in which scalars or
35             deep references may be stored (basically an MLDBM).
36              
37             =cut
38              
39             #############################################################################
40             # CLASS GROUP
41             #############################################################################
42              
43             =head1 Class Group: SharedDatastore
44              
45             The following classes might be a part of the SharedDatastore Class Group.
46              
47             =over
48              
49             =item * Class: App::SharedDatastore
50              
51             =item * Class: App::SharedDatastore::Repository
52              
53             =item * Class: App::SharedDatastore::IPCMM
54              
55             =item * Class: App::SharedDatastore::DBI
56              
57             =item * Class: App::SharedDatastore::MLDBM
58              
59             =item * Class: App::SharedDatastore::ApacheSession
60              
61             =item * Class: App::SharedDatastore::IPCShareLite
62              
63             =item * Class: App::SharedDatastore::IPCShareable
64              
65             =back
66              
67             =cut
68              
69             #############################################################################
70             # CLASS
71             #############################################################################
72              
73             =head1 Class: App::SharedDatastore
74              
75             A SharedDatastore service represents a single hash in which scalars or
76             deep references may be stored. (They are automatically serialized
77             for storage.)
78              
79             It is essentially identical to an MLDBM, but it supports more
80             implementations than an MLDBM (MLDBM is one of the implementations).
81             It also does not support the "tie" interface.
82              
83             =cut
84              
85             #############################################################################
86             # CONSTRUCTOR METHODS
87             #############################################################################
88              
89             =head1 Constructor Methods:
90              
91             =cut
92              
93             #############################################################################
94             # new()
95             #############################################################################
96              
97             =head2 new()
98              
99             The constructor is inherited from
100             L|App::Service/"new()">.
101              
102             =cut
103              
104             #############################################################################
105             # _init()
106             #############################################################################
107              
108             =head2 _init()
109              
110             =cut
111              
112             sub _init {
113 4 50   4   14 &App::sub_entry if ($App::trace);
114 4         6 my ($self) = @_;
115 4         13 $self->{data} = {};
116 4 100       13 if ($self->{compress}) {
117 1         1102 require Compress::Zlib;
118             }
119 4 100       72753 if ($self->{base64}) {
120 1         8 App->use("MIME::Base64");
121             }
122 4 50       19 &App::sub_exit() if ($App::trace);
123             }
124              
125             #############################################################################
126             # PUBLIC METHODS
127             #############################################################################
128              
129             =head1 Public Methods:
130              
131             =cut
132              
133             #############################################################################
134             # set()
135             #############################################################################
136              
137             =head2 set()
138              
139             * Signature: $sds->set($key, $value);
140             * Signature: $sds->set($key, $value, $options);
141             * Param: $key scalar
142             * Param: $value scalar
143             * Param: $options HASH (optional)
144             * Return: void
145              
146             $sds->set($key,$value);
147             $options = {
148             info_columns => [ "col1", "col2" ],
149             info_values => [ "value1", "value2" ],
150             };
151             $sds->set($key, $value, $options);
152              
153             =cut
154              
155             sub set {
156 10 50   10 1 2094 &App::sub_entry if ($App::trace);
157 10         21 my ($self, $key, $value, $options) = @_;
158 10         22 $self->{data}{$key} = $value;
159 10 50       26 &App::sub_exit() if ($App::trace);
160             }
161              
162             #############################################################################
163             # get()
164             #############################################################################
165              
166             =head2 get()
167              
168             * Signature: $value = $sds->get($key);
169             * Param: $key scalar
170             * Return: $value scalar
171              
172             $value = $sds->get($key);
173              
174             =cut
175              
176             sub get {
177 22 50   22 1 5367 &App::sub_entry if ($App::trace);
178 22         29 my ($self, $key) = @_;
179 22         45 my $value = $self->{data}{$key};
180 22 50       34 &App::sub_exit($value) if ($App::trace);
181 22         45 return($value);
182             }
183              
184             #############################################################################
185             # set_ref()
186             #############################################################################
187              
188             =head2 set_ref()
189              
190             * Signature: $sds->set_ref($keyref,$valueref);
191             * Signature: $sds->set_ref($keyref,$valueref,$options);
192             * Param: $keyref anything (ref or scalar)
193             * Param: $valueref anything (ref or scalar)
194             * Param: $options HASH (optional)
195             * Return: void
196              
197             $sds->set_ref($keyref, $valueref);
198             $options = {
199             info_columns => [ "col1", "col2" ],
200             info_values => [ "value1", "value2" ],
201             };
202             $sds->set_ref($keyref, $valueref, $options);
203              
204             =cut
205              
206             sub set_ref {
207 7 50   7 1 3084 &App::sub_entry if ($App::trace);
208 7         16 my ($self, $keyref, $valueref, $options) = @_;
209 7         17 my $hashkey = $self->hashkey($keyref);
210 7         20 my $blob = $self->serialize($valueref);
211 6         17 $self->set($hashkey, $blob, $options);
212 6 50       18 &App::sub_exit() if ($App::trace);
213             }
214              
215             #############################################################################
216             # get_ref()
217             #############################################################################
218              
219             =head2 get_ref()
220              
221             * Signature: $valueref = $sds->get_ref($keyref);
222             * Param: $keyref anything (ref or scalar)
223             * Return: $valueref anything (ref or scalar)
224              
225             $valueref = $sds->get_ref($keyref);
226              
227             =cut
228              
229             sub get_ref {
230 12 50   12 1 1235 &App::sub_entry if ($App::trace);
231 12         19 my ($self, $keyref) = @_;
232 12         24 my $hashkey = $self->hashkey($keyref);
233 12         28 my $blob = $self->get($hashkey);
234 12         13 my ($valueref);
235 12 100       20 if (defined $blob) {
236 6         51 eval {
237 6         15 $valueref = $self->deserialize($blob);
238             };
239             # we want to catch errors in derialization which may occur due to version mismatches in the Storable module
240             # (see "man Storable" in section on "FORWARD COMPATIBILITY")
241 6 50       13 if ($@) {
242 0         0 my $context = $self->{context};
243 0         0 $context->log("WARNING: DataStore($self->{name})->get_ref($hashkey): $@");
244             }
245             }
246 12 50       25 &App::sub_exit($valueref) if ($App::trace);
247 12         31 return($valueref);
248             }
249              
250             #############################################################################
251             # serialize()
252             #############################################################################
253              
254             =head2 serialize()
255              
256             * Signature: $blob = $sds->serialize($ref);
257             * Return: $ref any (ref)
258             * Return: $blob scalar (binary)
259              
260             $blob = $sds->serialize($ref);
261              
262             =cut
263              
264             sub serialize {
265 10 50   10 1 4831 &App::sub_entry if ($App::trace);
266 10         17 my ($self, $ref) = @_;
267 10         12 my ($blob);
268 10 100       13 if (defined $ref) {
269 7         19 $blob = nfreeze($ref);
270 7 100       204 if ($self->{compress}) {
271 2         9 $blob = Compress::Zlib::memGzip($blob);
272             }
273 7 100       989 if ($self->{base64}) {
274 1         220 $blob = MIME::Base64::encode($blob);
275             }
276             }
277             else {
278 3         5 $blob = undef;
279             }
280 9 50       19 &App::sub_exit("") if ($App::trace);
281 9         19 return($blob);
282             }
283              
284             #############################################################################
285             # deserialize()
286             #############################################################################
287              
288             =head2 deserialize()
289              
290             * Signature: $ref = $sds->deserialize($blob);
291             * Param: $blob scalar (binary)
292             * Return: $ref any (ref)
293              
294              
295             $ref = $sds->deserialize($blob);
296              
297             =cut
298              
299             sub deserialize {
300 9 50   9 1 1584 &App::sub_entry if ($App::trace);
301 9         11 my ($self, $blob) = @_;
302 9         10 my ($ref);
303 9 50       16 if (defined $blob) {
304 9 50       21 if ($self->{base64}) {
305 0         0 $blob = MIME::Base64::decode($blob);
306             }
307 9 100       23 if ($self->{compress}) {
308 3         12 $blob = Compress::Zlib::memGunzip($blob);
309             }
310 9         311 $ref = thaw($blob);
311             }
312             else {
313 0         0 $ref = undef;
314             }
315 9 50       240 &App::sub_exit($ref) if ($App::trace);
316 9         19 return($ref);
317             }
318              
319             #############################################################################
320             # hashkey()
321             #############################################################################
322              
323             =head2 hashkey()
324              
325             * Signature: $hashkey = $sds->hashkey($keyref);
326             * Return: $keyref any (ref or scalar)
327             * Return: $hashkey scalar
328              
329             $hashkey = $sds->hashkey($keyref);
330              
331             =cut
332              
333             sub hashkey {
334 22 50   22 1 5179 &App::sub_entry if ($App::trace);
335 22         27 my ($self, $keyref) = @_;
336 22         21 my ($hashkey);
337 22 100 66     83 if (ref($keyref)) {
    100          
338 10         32 $hashkey = sha1_hex(nfreeze($keyref));
339             }
340             elsif (length($keyref) == 40 && $keyref =~ /^[a-f0-9]+$/) {
341 3         4 $hashkey = $keyref;
342             }
343             else {
344 9         62 $hashkey = sha1_hex($keyref);
345             }
346 22 50       812 &App::sub_exit($hashkey) if ($App::trace);
347 22         42 return($hashkey);
348             }
349              
350             #############################################################################
351             # PROTECTED METHODS
352             #############################################################################
353              
354             =head1 Protected Methods:
355              
356             =cut
357              
358             #############################################################################
359             # Method: service_type()
360             #############################################################################
361              
362             =head2 service_type()
363              
364             Returns "SharedDatastore";
365              
366             * Signature: $service_type = App::SharedDatastore->service_type();
367             * Param: void
368             * Return: $service_type string
369              
370             $service_type = $sds->service_type();
371              
372             =cut
373              
374             sub service_type () { "SharedDatastore"; }
375              
376             =head1 ACKNOWLEDGEMENTS
377              
378             * Author: Stephen Adkins
379             * License: This is free software. It is licensed under the same terms as Perl itself.
380              
381             =head1 SEE ALSO
382              
383             L|App::Context>,
384             L|App::Service>
385              
386             =cut
387              
388             1;
389