File Coverage

blib/lib/Cache/BaseCache.pm
Criterion Covered Total %
statement 189 198 95.4
branch 35 44 79.5
condition 5 15 33.3
subroutine 53 54 98.1
pod 12 25 48.0
total 294 336 87.5


line stmt bran cond sub pod time code
1             ######################################################################
2             # $Id: BaseCache.pm,v 1.25 2003/04/15 14:46:14 dclinton Exp $
3             # Copyright (C) 2001-2003 DeWitt Clinton All Rights Reserved
4             #
5             # Software distributed under the License is distributed on an "AS
6             # IS" basis, WITHOUT WARRANTY OF ANY KIND, either expressed or
7             # implied. See the License for the specific language governing
8             # rights and limitations under the License.
9             ######################################################################
10              
11              
12             package Cache::BaseCache;
13              
14              
15 4     4   20 use strict;
  4         6  
  4         119  
16 4     4   16 use vars qw( @ISA );
  4         6  
  4         136  
17 4     4   20 use Cache::Cache qw( $EXPIRES_NEVER $EXPIRES_NOW );
  4         7  
  4         434  
18 4     4   1010 use Cache::CacheUtils qw( Assert_Defined Clone_Data );
  4         8  
  4         267  
19 4     4   2308 use Cache::Object;
  4         12  
  4         120  
20 4     4   28 use Error;
  4         9  
  4         31  
21              
22              
23             @ISA = qw( Cache::Cache );
24              
25              
26             my $DEFAULT_EXPIRES_IN = $EXPIRES_NEVER;
27             my $DEFAULT_NAMESPACE = "Default";
28             my $DEFAULT_AUTO_PURGE_ON_SET = 0;
29             my $DEFAULT_AUTO_PURGE_ON_GET = 0;
30              
31              
32             # namespace that stores the keys used for the auto purge functionality
33              
34             my $AUTO_PURGE_NAMESPACE = "__AUTO_PURGE__";
35              
36              
37             # map of expiration formats to their respective time in seconds
38              
39             my %_Expiration_Units = ( map(($_, 1), qw(s second seconds sec)),
40             map(($_, 60), qw(m minute minutes min)),
41             map(($_, 60*60), qw(h hour hours)),
42             map(($_, 60*60*24), qw(d day days)),
43             map(($_, 60*60*24*7), qw(w week weeks)),
44             map(($_, 60*60*24*30), qw(M month months)),
45             map(($_, 60*60*24*365), qw(y year years)) );
46              
47              
48              
49             # Takes the time the object was created, the default_expires_in and
50             # optionally the explicitly set expires_in and returns the time the
51             # object will expire. Calls _canonicalize_expiration to convert
52             # strings like "5m" into second values.
53              
54             sub Build_Expires_At
55             {
56 134     134 0 224 my ( $p_created_at, $p_default_expires_in, $p_explicit_expires_in ) = @_;
57              
58 134 100       354 my $expires_in = defined $p_explicit_expires_in ?
59             $p_explicit_expires_in : $p_default_expires_in;
60              
61 134         342 return Sum_Expiration_Time( $p_created_at, $expires_in );
62             }
63              
64              
65             # Return a Cache::Object object
66              
67             sub Build_Object
68             {
69 134     134 0 286 my ( $p_key, $p_data, $p_default_expires_in, $p_expires_in ) = @_;
70              
71 134         363 Assert_Defined( $p_key );
72 134         333 Assert_Defined( $p_default_expires_in );
73              
74 134         612 my $now = time( );
75              
76 134         1693 my $object = new Cache::Object( );
77              
78 134         752 $object->set_key( $p_key );
79 134         453 $object->set_data( $p_data );
80 134         423 $object->set_created_at( $now );
81 134         419 $object->set_accessed_at( $now );
82 134         384 $object->set_expires_at( Build_Expires_At( $now,
83             $p_default_expires_in,
84             $p_expires_in ) );
85 134         658 return $object;
86             }
87              
88              
89             # Compare the expires_at to the current time to determine whether or
90             # not an object has expired (the time parameter is optional)
91              
92             sub Object_Has_Expired
93             {
94 122     122 0 294 my ( $p_object, $p_time ) = @_;
95              
96 122 100       345 if ( not defined $p_object )
97             {
98 6         35 return 1;
99             }
100              
101 116   33     647 $p_time = $p_time || time( );
102              
103 116 50       487 if ( $p_object->get_expires_at( ) eq $EXPIRES_NOW )
    100          
    100          
104             {
105 0         0 return 1;
106             }
107             elsif ( $p_object->get_expires_at( ) eq $EXPIRES_NEVER )
108             {
109 24         77 return 0;
110             }
111             elsif ( $p_time >= $p_object->get_expires_at( ) )
112             {
113 40         171 return 1;
114             }
115             else
116             {
117 52         250 return 0;
118             }
119             }
120              
121              
122             # Returns the sum of the base created_at time (in seconds since the epoch)
123             # and the canonical form of the expires_at string
124              
125              
126             sub Sum_Expiration_Time
127             {
128 134     134 0 223 my ( $p_created_at, $p_expires_in ) = @_;
129              
130 134         481 Assert_Defined( $p_created_at );
131 134         526 Assert_Defined( $p_expires_in );
132              
133 134 100       476 if ( $p_expires_in eq $EXPIRES_NEVER )
134             {
135 72         319 return $EXPIRES_NEVER;
136             }
137             else
138             {
139 62         202 return $p_created_at + Canonicalize_Expiration_Time( $p_expires_in );
140             }
141             }
142              
143              
144             # turn a string in the form "[number] [unit]" into an explicit number
145             # of seconds from the present. E.g, "10 minutes" returns "600"
146              
147             sub Canonicalize_Expiration_Time
148             {
149 62     62 0 125 my ( $p_expires_in ) = @_;
150              
151 62         162 Assert_Defined( $p_expires_in );
152              
153 62         80 my $secs;
154              
155 62 50 0     682 if ( uc( $p_expires_in ) eq uc( $EXPIRES_NOW ) )
    50          
    50          
    0          
156             {
157 0         0 $secs = 0;
158             }
159             elsif ( uc( $p_expires_in ) eq uc( $EXPIRES_NEVER ) )
160             {
161 0         0 throw Error::Simple( "Internal error. expires_in eq $EXPIRES_NEVER" );
162             }
163             elsif ( $p_expires_in =~ /^\s*([+-]?(?:\d+|\d*\.\d*))\s*$/ )
164             {
165 62         1082 $secs = $p_expires_in;
166             }
167             elsif ( $p_expires_in =~ /^\s*([+-]?(?:\d+|\d*\.\d*))\s*(\w*)\s*$/
168             and exists( $_Expiration_Units{ $2 } ))
169             {
170 0         0 $secs = ( $_Expiration_Units{ $2 } ) * $1;
171             }
172             else
173             {
174 0         0 throw Error::Simple( "invalid expiration time '$p_expires_in'" );
175             }
176              
177 62         350 return $secs;
178             }
179              
180              
181              
182             sub clear
183             {
184 34     34 1 66 my ( $self ) = @_;
185              
186 34         237 $self->_get_backend( )->delete_namespace( $self->get_namespace( ) );
187             }
188              
189              
190             sub get
191             {
192 110     110 1 298 my ( $self, $p_key ) = @_;
193              
194 110         360 Assert_Defined( $p_key );
195              
196 110 100       288 $self->_conditionally_auto_purge_on_get( ) unless
197             $self->get_namespace( ) eq $AUTO_PURGE_NAMESPACE;
198              
199 110 100       330 my $object = $self->get_object( $p_key ) or
200             return undef;
201              
202 82 100       397 if ( Object_Has_Expired( $object ) )
203             {
204 32         139 $self->remove( $p_key );
205 32         342 return undef;
206             }
207              
208 50         267 return $object->get_data( );
209             }
210              
211              
212             sub get_keys
213             {
214 94     94 1 154 my ( $self ) = @_;
215              
216 94         282 return $self->_get_backend( )->get_keys( $self->get_namespace( ) );
217             }
218              
219              
220             sub get_identifiers
221             {
222 0     0 1 0 my ( $self ) = @_;
223              
224 0         0 warn( "get_identifiers has been marked deprepricated. use get_keys" );
225              
226 0         0 return $self->get_keys( );
227             }
228              
229              
230             sub get_object
231             {
232 244     244 1 733 my ( $self, $p_key ) = @_;
233              
234 244         664 Assert_Defined( $p_key );
235              
236 244 100       958 my $object =
237             $self->_get_backend( )->restore( $self->get_namespace( ), $p_key ) or
238             return undef;
239              
240 182         864 $object->set_size( $self->_get_backend( )->
241             get_size( $self->get_namespace( ), $p_key ) );
242              
243 182         1031 $object->set_key( $p_key );
244              
245 182         528 return $object;
246             }
247              
248              
249             sub purge
250             {
251 26     26 1 66 my ( $self ) = @_;
252              
253 26         120 foreach my $key ( $self->get_keys( ) )
254             {
255 28         223 $self->get( $key );
256             }
257             }
258              
259              
260             sub remove
261             {
262 54     54 1 112 my ( $self, $p_key ) = @_;
263              
264 54         165 Assert_Defined( $p_key );
265              
266 54         131 $self->_get_backend( )->delete_key( $self->get_namespace( ), $p_key );
267             }
268              
269              
270             sub set
271             {
272 112     112 1 284 my ( $self, $p_key, $p_data, $p_expires_in ) = @_;
273              
274 112         432 Assert_Defined( $p_key );
275              
276 112         387 $self->_conditionally_auto_purge_on_set( );
277              
278 112         464 $self->set_object( $p_key,
279             Build_Object( $p_key,
280             $p_data,
281             $self->get_default_expires_in( ),
282             $p_expires_in ) );
283             }
284              
285              
286             sub set_object
287             {
288 180     180 1 315 my ( $self, $p_key, $p_object ) = @_;
289              
290 180         620 my $object = Clone_Data( $p_object );
291              
292 180         635 $object->set_size( undef );
293 180         475 $object->set_key( undef );
294              
295 180         461 $self->_get_backend( )->store( $self->get_namespace( ), $p_key, $object );
296             }
297              
298              
299             sub size
300             {
301 58     58 1 111 my ( $self ) = @_;
302              
303 58         96 my $size = 0;
304              
305 58         229 foreach my $key ( $self->get_keys( ) )
306             {
307 56         162 $size += $self->_get_backend( )->get_size( $self->get_namespace( ), $key );
308             }
309              
310 58         345 return $size;
311             }
312              
313              
314             sub get_namespaces
315             {
316 4     4 1 13 my ( $self ) = @_;
317              
318 4         18 return grep {!/$AUTO_PURGE_NAMESPACE/} $self->_get_backend( )->get_namespaces( );
  12         150  
319             }
320              
321              
322             sub _new
323             {
324 52     52   117 my ( $proto, $p_options_hash_ref ) = @_;
325 52   33     249 my $class = ref( $proto ) || $proto;
326 52         105 my $self = {};
327 52         128 bless( $self, $class );
328 52         715 $self->_initialize_base_cache( $p_options_hash_ref );
329 52         149 return $self;
330             }
331              
332              
333             sub _complete_initialization
334             {
335 52     52   295 my ( $self ) = @_;
336 52         173 $self->_initialize_auto_purge_interval( );
337             }
338              
339              
340             sub _initialize_base_cache
341             {
342 52     52   94 my ( $self, $p_options_hash_ref ) = @_;
343              
344 52         271 $self->_initialize_options_hash_ref( $p_options_hash_ref );
345 52         275 $self->_initialize_namespace( );
346 52         183 $self->_initialize_default_expires_in( );
347 52         173 $self->_initialize_auto_purge_on_set( );
348 52         177 $self->_initialize_auto_purge_on_get( );
349             }
350              
351              
352             sub _initialize_options_hash_ref
353             {
354 52     52   89 my ( $self, $p_options_hash_ref ) = @_;
355              
356 52 100       300 $self->_set_options_hash_ref( defined $p_options_hash_ref ?
357             $p_options_hash_ref :
358             { } );
359             }
360              
361              
362             sub _initialize_namespace
363             {
364 52     52   90 my ( $self ) = @_;
365              
366 52         218 my $namespace = $self->_read_option( 'namespace', $DEFAULT_NAMESPACE );
367              
368 52         198 $self->set_namespace( $namespace );
369             }
370              
371              
372             sub _initialize_default_expires_in
373             {
374 52     52   172 my ( $self ) = @_;
375              
376 52         137 my $default_expires_in =
377             $self->_read_option( 'default_expires_in', $DEFAULT_EXPIRES_IN );
378              
379 52         206 $self->_set_default_expires_in( $default_expires_in );
380             }
381              
382              
383             sub _initialize_auto_purge_interval
384             {
385 52     52   91 my ( $self ) = @_;
386              
387 52         119 my $auto_purge_interval = $self->_read_option( 'auto_purge_interval' );
388              
389 52 100       208 if ( defined $auto_purge_interval )
390             {
391 4         16 $self->set_auto_purge_interval( $auto_purge_interval );
392 4         16 $self->_auto_purge( );
393             }
394             }
395              
396              
397             sub _initialize_auto_purge_on_set
398             {
399 52     52   92 my ( $self ) = @_;
400              
401 52         281 my $auto_purge_on_set =
402             $self->_read_option( 'auto_purge_on_set', $DEFAULT_AUTO_PURGE_ON_SET );
403              
404 52         210 $self->set_auto_purge_on_set( $auto_purge_on_set );
405             }
406              
407              
408             sub _initialize_auto_purge_on_get
409             {
410 52     52   93 my ( $self ) = @_;
411              
412 52         122 my $auto_purge_on_get =
413             $self->_read_option( 'auto_purge_on_get', $DEFAULT_AUTO_PURGE_ON_GET );
414              
415 52         312 $self->set_auto_purge_on_get( $auto_purge_on_get );
416             }
417              
418              
419              
420             # _read_option looks for an option named 'option_name' in the
421             # option_hash associated with this instance. If it is not found, then
422             # 'default_value' will be returned instead
423              
424             sub _read_option
425             {
426 374     374   572 my ( $self, $p_option_name, $p_default_value ) = @_;
427              
428 374         762 my $options_hash_ref = $self->_get_options_hash_ref( );
429              
430 374 100       1287 if ( defined $options_hash_ref->{ $p_option_name } )
431             {
432 44         139 return $options_hash_ref->{ $p_option_name };
433             }
434             else
435             {
436 330         1167 return $p_default_value;
437             }
438             }
439              
440              
441              
442             # this method checks to see if the auto_purge property is set for a
443             # particular cache. If it is, then it switches the cache to the
444             # $AUTO_PURGE_NAMESPACE and stores that value under the name of the
445             # current cache namespace
446              
447             sub _reset_auto_purge_interval
448             {
449 22     22   45 my ( $self ) = @_;
450              
451 22 50       74 return if not $self->_should_auto_purge( );
452              
453 22         71 my $real_namespace = $self->get_namespace( );
454              
455 22         63 $self->set_namespace( $AUTO_PURGE_NAMESPACE );
456              
457 22 50       87 if ( not defined $self->get( $real_namespace ) )
458             {
459 22         96 $self->_insert_auto_purge_object( $real_namespace );
460             }
461              
462 22         136 $self->set_namespace( $real_namespace );
463             }
464              
465              
466             sub _should_auto_purge
467             {
468 62     62   108 my ( $self ) = @_;
469              
470 62   33     196 return ( defined $self->get_auto_purge_interval( ) &&
471             $self->get_auto_purge_interval( ) ne $EXPIRES_NEVER );
472             }
473              
474             sub _insert_auto_purge_object
475             {
476 22     22   45 my ( $self, $p_real_namespace ) = @_;
477              
478 22         67 my $object = Build_Object( $p_real_namespace,
479             1,
480             $self->get_auto_purge_interval( ),
481             undef );
482              
483 22         75 $self->set_object( $p_real_namespace, $object );
484             }
485              
486              
487              
488             # this method checks to see if the auto_purge property is set, and if
489             # it is, switches to the $AUTO_PURGE_NAMESPACE and sees if a value
490             # exists at the location specified by a key named for the current
491             # namespace. If that key doesn't exist, then the purge method is
492             # called on the cache
493              
494             sub _auto_purge
495             {
496 40     40   73 my ( $self ) = @_;
497              
498 40 100       135 if ( $self->_needs_auto_purge( ) )
499             {
500 14         53 $self->purge( );
501 14         65 $self->_reset_auto_purge_interval( );
502             }
503             }
504              
505              
506             sub _get_auto_purge_object
507             {
508 40     40   62 my ( $self ) = @_;
509              
510 40         184 my $real_namespace = $self->get_namespace( );
511 40         140 $self->set_namespace( $AUTO_PURGE_NAMESPACE );
512 40         197 my $auto_purge_object = $self->get_object( $real_namespace );
513 40         121 $self->set_namespace( $real_namespace );
514 40         129 return $auto_purge_object;
515             }
516              
517              
518             sub _needs_auto_purge
519             {
520 40     40   79 my ( $self ) = @_;
521              
522 40   66     128 return ( $self->_should_auto_purge( ) &&
523             Object_Has_Expired( $self->_get_auto_purge_object( ) ) );
524             }
525              
526              
527             # call auto_purge if the auto_purge_on_set option is true
528              
529             sub _conditionally_auto_purge_on_set
530             {
531 112     112   373 my ( $self ) = @_;
532              
533 112 100       365 if ( $self->get_auto_purge_on_set( ) )
534             {
535 36         159 $self->_auto_purge( );
536             }
537             }
538              
539              
540             # call auto_purge if the auto_purge_on_get option is true
541              
542             sub _conditionally_auto_purge_on_get
543             {
544 88     88   141 my ( $self ) = @_;
545              
546 88 50       327 if ( $self->get_auto_purge_on_get( ) )
547             {
548 0         0 $self->_auto_purge( );
549             }
550             }
551              
552              
553             sub _get_options_hash_ref
554             {
555 374     374   599 my ( $self ) = @_;
556              
557 374         839 return $self->{_Options_Hash_Ref};
558             }
559              
560              
561             sub _set_options_hash_ref
562             {
563 52     52   93 my ( $self, $options_hash_ref ) = @_;
564              
565 52         259 $self->{_Options_Hash_Ref} = $options_hash_ref;
566             }
567              
568              
569             sub get_namespace
570             {
571 1016     1016 0 1259 my ( $self ) = @_;
572              
573 1016         5187 return $self->{_Namespace};
574             }
575              
576              
577             sub set_namespace
578             {
579 180     180 0 298 my ( $self, $namespace ) = @_;
580              
581 180         450 $self->{_Namespace} = $namespace;
582             }
583              
584              
585             sub get_default_expires_in
586             {
587 112     112 1 261 my ( $self ) = @_;
588              
589 112         1362 return $self->{_Default_Expires_In};
590             }
591              
592              
593             sub _set_default_expires_in
594             {
595 52     52   88 my ( $self, $default_expires_in ) = @_;
596              
597 52         369 $self->{_Default_Expires_In} = $default_expires_in;
598             }
599              
600              
601             sub get_auto_purge_interval
602             {
603 146     146 0 201 my ( $self ) = @_;
604              
605 146         975 return $self->{_Auto_Purge_Interval};
606             }
607              
608              
609             sub set_auto_purge_interval
610             {
611 8     8 0 20 my ( $self, $auto_purge_interval ) = @_;
612              
613 8         29 $self->{_Auto_Purge_Interval} = $auto_purge_interval;
614              
615 8         60 $self->_reset_auto_purge_interval( );
616             }
617              
618              
619             sub get_auto_purge_on_set
620             {
621 112     112 0 184 my ( $self ) = @_;
622              
623 112         558 return $self->{_Auto_Purge_On_Set};
624             }
625              
626              
627             sub set_auto_purge_on_set
628             {
629 56     56 0 104 my ( $self, $auto_purge_on_set ) = @_;
630              
631 56         176 $self->{_Auto_Purge_On_Set} = $auto_purge_on_set;
632             }
633              
634              
635             sub get_auto_purge_on_get
636             {
637 88     88 0 119 my ( $self ) = @_;
638              
639 88         353 return $self->{_Auto_Purge_On_Get};
640             }
641              
642              
643             sub set_auto_purge_on_get
644             {
645 52     52 0 96 my ( $self, $auto_purge_on_get ) = @_;
646              
647 52         160 $self->{_Auto_Purge_On_Get} = $auto_purge_on_get;
648             }
649              
650              
651             sub _get_backend
652             {
653 848     848   16642 my ( $self ) = @_;
654              
655 848         2440 return $self->{ _Backend };
656             }
657              
658              
659             sub _set_backend
660             {
661 52     52   88 my ( $self, $p_backend ) = @_;
662              
663 52         168 $self->{ _Backend } = $p_backend;
664             }
665              
666              
667              
668             1;
669              
670              
671             __END__