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   16 use strict;
  4         5  
  4         124  
16 4     4   15 use vars qw( @ISA );
  4         5  
  4         152  
17 4     4   15 use Cache::Cache qw( $EXPIRES_NEVER $EXPIRES_NOW );
  4         4  
  4         506  
18 4     4   650 use Cache::CacheUtils qw( Assert_Defined Clone_Data );
  4         6  
  4         208  
19 4     4   1662 use Cache::Object;
  4         10  
  4         110  
20 4     4   23 use Error;
  4         5  
  4         26  
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 135     135 0 196 my ( $p_created_at, $p_default_expires_in, $p_explicit_expires_in ) = @_;
57              
58 135 100       335 my $expires_in = defined $p_explicit_expires_in ?
59             $p_explicit_expires_in : $p_default_expires_in;
60              
61 135         346 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 135     135 0 217 my ( $p_key, $p_data, $p_default_expires_in, $p_expires_in ) = @_;
70              
71 135         294 Assert_Defined( $p_key );
72 135         286 Assert_Defined( $p_default_expires_in );
73              
74 135         191 my $now = time( );
75              
76 135         710 my $object = new Cache::Object( );
77              
78 135         406 $object->set_key( $p_key );
79 135         355 $object->set_data( $p_data );
80 135         350 $object->set_created_at( $now );
81 135         314 $object->set_accessed_at( $now );
82 135         309 $object->set_expires_at( Build_Expires_At( $now,
83             $p_default_expires_in,
84             $p_expires_in ) );
85 135         450 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 123     123 0 205 my ( $p_object, $p_time ) = @_;
95              
96 123 100       285 if ( not defined $p_object )
97             {
98 6         33 return 1;
99             }
100              
101 117   33     504 $p_time = $p_time || time( );
102              
103 117 50       353 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         69 return 0;
110             }
111             elsif ( $p_time >= $p_object->get_expires_at( ) )
112             {
113 42         222 return 1;
114             }
115             else
116             {
117 51         233 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 135     135 0 215 my ( $p_created_at, $p_expires_in ) = @_;
129              
130 135         292 Assert_Defined( $p_created_at );
131 135         270 Assert_Defined( $p_expires_in );
132              
133 135 100       534 if ( $p_expires_in eq $EXPIRES_NEVER )
134             {
135 72         282 return $EXPIRES_NEVER;
136             }
137             else
138             {
139 63         180 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 63     63 0 111 my ( $p_expires_in ) = @_;
150              
151 63         140 Assert_Defined( $p_expires_in );
152              
153 63         70 my $secs;
154              
155 63 50 0     900 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 63         109 $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 63         346 return $secs;
178             }
179              
180              
181              
182             sub clear
183             {
184 34     34 1 55 my ( $self ) = @_;
185              
186 34         93 $self->_get_backend( )->delete_namespace( $self->get_namespace( ) );
187             }
188              
189              
190             sub get
191             {
192 111     111 1 206 my ( $self, $p_key ) = @_;
193              
194 111         306 Assert_Defined( $p_key );
195              
196 111 100       245 $self->_conditionally_auto_purge_on_get( ) unless
197             $self->get_namespace( ) eq $AUTO_PURGE_NAMESPACE;
198              
199 111 100       333 my $object = $self->get_object( $p_key ) or
200             return undef;
201              
202 83 100       205 if ( Object_Has_Expired( $object ) )
203             {
204 33         128 $self->remove( $p_key );
205 33         288 return undef;
206             }
207              
208 50         165 return $object->get_data( );
209             }
210              
211              
212             sub get_keys
213             {
214 95     95 1 141 my ( $self ) = @_;
215              
216 95         392 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 246     246 1 322 my ( $self, $p_key ) = @_;
233              
234 246         553 Assert_Defined( $p_key );
235              
236 246 100       545 my $object =
237             $self->_get_backend( )->restore( $self->get_namespace( ), $p_key ) or
238             return undef;
239              
240 184         655 $object->set_size( $self->_get_backend( )->
241             get_size( $self->get_namespace( ), $p_key ) );
242              
243 184         657 $object->set_key( $p_key );
244              
245 184         550 return $object;
246             }
247              
248              
249             sub purge
250             {
251 27     27 1 56 my ( $self ) = @_;
252              
253 27         98 foreach my $key ( $self->get_keys( ) )
254             {
255 28         117 $self->get( $key );
256             }
257             }
258              
259              
260             sub remove
261             {
262 55     55 1 93 my ( $self, $p_key ) = @_;
263              
264 55         143 Assert_Defined( $p_key );
265              
266 55         130 $self->_get_backend( )->delete_key( $self->get_namespace( ), $p_key );
267             }
268              
269              
270             sub set
271             {
272 112     112 1 216 my ( $self, $p_key, $p_data, $p_expires_in ) = @_;
273              
274 112         354 Assert_Defined( $p_key );
275              
276 112         315 $self->_conditionally_auto_purge_on_set( );
277              
278 112         390 $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 182     182 1 285 my ( $self, $p_key, $p_object ) = @_;
289              
290 182         483 my $object = Clone_Data( $p_object );
291              
292 182         600 $object->set_size( undef );
293 182         362 $object->set_key( undef );
294              
295 182         367 $self->_get_backend( )->store( $self->get_namespace( ), $p_key, $object );
296             }
297              
298              
299             sub size
300             {
301 58     58 1 87 my ( $self ) = @_;
302              
303 58         77 my $size = 0;
304              
305 58         156 foreach my $key ( $self->get_keys( ) )
306             {
307 56         145 $size += $self->_get_backend( )->get_size( $self->get_namespace( ), $key );
308             }
309              
310 58         211 return $size;
311             }
312              
313              
314             sub get_namespaces
315             {
316 4     4 1 11 my ( $self ) = @_;
317              
318 4         16 return grep {!/$AUTO_PURGE_NAMESPACE/} $self->_get_backend( )->get_namespaces( );
  12         171  
319             }
320              
321              
322             sub _new
323             {
324 52     52   87 my ( $proto, $p_options_hash_ref ) = @_;
325 52   33     223 my $class = ref( $proto ) || $proto;
326 52         87 my $self = {};
327 52         120 bless( $self, $class );
328 52         180 $self->_initialize_base_cache( $p_options_hash_ref );
329 52         128 return $self;
330             }
331              
332              
333             sub _complete_initialization
334             {
335 52     52   103 my ( $self ) = @_;
336 52         137 $self->_initialize_auto_purge_interval( );
337             }
338              
339              
340             sub _initialize_base_cache
341             {
342 52     52   85 my ( $self, $p_options_hash_ref ) = @_;
343              
344 52         148 $self->_initialize_options_hash_ref( $p_options_hash_ref );
345 52         163 $self->_initialize_namespace( );
346 52         135 $self->_initialize_default_expires_in( );
347 52         134 $self->_initialize_auto_purge_on_set( );
348 52         140 $self->_initialize_auto_purge_on_get( );
349             }
350              
351              
352             sub _initialize_options_hash_ref
353             {
354 52     52   80 my ( $self, $p_options_hash_ref ) = @_;
355              
356 52 100       299 $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   65 my ( $self ) = @_;
365              
366 52         175 my $namespace = $self->_read_option( 'namespace', $DEFAULT_NAMESPACE );
367              
368 52         184 $self->set_namespace( $namespace );
369             }
370              
371              
372             sub _initialize_default_expires_in
373             {
374 52     52   68 my ( $self ) = @_;
375              
376 52         132 my $default_expires_in =
377             $self->_read_option( 'default_expires_in', $DEFAULT_EXPIRES_IN );
378              
379 52         164 $self->_set_default_expires_in( $default_expires_in );
380             }
381              
382              
383             sub _initialize_auto_purge_interval
384             {
385 52     52   62 my ( $self ) = @_;
386              
387 52         99 my $auto_purge_interval = $self->_read_option( 'auto_purge_interval' );
388              
389 52 100       173 if ( defined $auto_purge_interval )
390             {
391 4         19 $self->set_auto_purge_interval( $auto_purge_interval );
392 4         17 $self->_auto_purge( );
393             }
394             }
395              
396              
397             sub _initialize_auto_purge_on_set
398             {
399 52     52   67 my ( $self ) = @_;
400              
401 52         141 my $auto_purge_on_set =
402             $self->_read_option( 'auto_purge_on_set', $DEFAULT_AUTO_PURGE_ON_SET );
403              
404 52         163 $self->set_auto_purge_on_set( $auto_purge_on_set );
405             }
406              
407              
408             sub _initialize_auto_purge_on_get
409             {
410 52     52   68 my ( $self ) = @_;
411              
412 52         109 my $auto_purge_on_get =
413             $self->_read_option( 'auto_purge_on_get', $DEFAULT_AUTO_PURGE_ON_GET );
414              
415 52         174 $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   418 my ( $self, $p_option_name, $p_default_value ) = @_;
427              
428 374         604 my $options_hash_ref = $self->_get_options_hash_ref( );
429              
430 374 100       688 if ( defined $options_hash_ref->{ $p_option_name } )
431             {
432 44         117 return $options_hash_ref->{ $p_option_name };
433             }
434             else
435             {
436 330         762 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 23     23   42 my ( $self ) = @_;
450              
451 23 50       74 return if not $self->_should_auto_purge( );
452              
453 23         79 my $real_namespace = $self->get_namespace( );
454              
455 23         63 $self->set_namespace( $AUTO_PURGE_NAMESPACE );
456              
457 23 50       69 if ( not defined $self->get( $real_namespace ) )
458             {
459 23         95 $self->_insert_auto_purge_object( $real_namespace );
460             }
461              
462 23         141 $self->set_namespace( $real_namespace );
463             }
464              
465              
466             sub _should_auto_purge
467             {
468 63     63   90 my ( $self ) = @_;
469              
470 63   33     184 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 23     23   41 my ( $self, $p_real_namespace ) = @_;
477              
478 23         57 my $object = Build_Object( $p_real_namespace,
479             1,
480             $self->get_auto_purge_interval( ),
481             undef );
482              
483 23         72 $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   59 my ( $self ) = @_;
497              
498 40 100       143 if ( $self->_needs_auto_purge( ) )
499             {
500 15         53 $self->purge( );
501 15         66 $self->_reset_auto_purge_interval( );
502             }
503             }
504              
505              
506             sub _get_auto_purge_object
507             {
508 40     40   55 my ( $self ) = @_;
509              
510 40         111 my $real_namespace = $self->get_namespace( );
511 40         139 $self->set_namespace( $AUTO_PURGE_NAMESPACE );
512 40         126 my $auto_purge_object = $self->get_object( $real_namespace );
513 40         128 $self->set_namespace( $real_namespace );
514 40         111 return $auto_purge_object;
515             }
516              
517              
518             sub _needs_auto_purge
519             {
520 40     40   57 my ( $self ) = @_;
521              
522 40   66     118 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   151 my ( $self ) = @_;
532              
533 112 100       345 if ( $self->get_auto_purge_on_set( ) )
534             {
535 36         147 $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   116 my ( $self ) = @_;
545              
546 88 50       273 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   327 my ( $self ) = @_;
556              
557 374         521 return $self->{_Options_Hash_Ref};
558             }
559              
560              
561             sub _set_options_hash_ref
562             {
563 52     52   80 my ( $self, $options_hash_ref ) = @_;
564              
565 52         204 $self->{_Options_Hash_Ref} = $options_hash_ref;
566             }
567              
568              
569             sub get_namespace
570             {
571 1026     1026 0 1060 my ( $self ) = @_;
572              
573 1026         3789 return $self->{_Namespace};
574             }
575              
576              
577             sub set_namespace
578             {
579 182     182 0 272 my ( $self, $namespace ) = @_;
580              
581 182         396 $self->{_Namespace} = $namespace;
582             }
583              
584              
585             sub get_default_expires_in
586             {
587 112     112 1 158 my ( $self ) = @_;
588              
589 112         422 return $self->{_Default_Expires_In};
590             }
591              
592              
593             sub _set_default_expires_in
594             {
595 52     52   72 my ( $self, $default_expires_in ) = @_;
596              
597 52         116 $self->{_Default_Expires_In} = $default_expires_in;
598             }
599              
600              
601             sub get_auto_purge_interval
602             {
603 149     149 0 190 my ( $self ) = @_;
604              
605 149         882 return $self->{_Auto_Purge_Interval};
606             }
607              
608              
609             sub set_auto_purge_interval
610             {
611 8     8 0 17 my ( $self, $auto_purge_interval ) = @_;
612              
613 8         29 $self->{_Auto_Purge_Interval} = $auto_purge_interval;
614              
615 8         40 $self->_reset_auto_purge_interval( );
616             }
617              
618              
619             sub get_auto_purge_on_set
620             {
621 112     112 0 202 my ( $self ) = @_;
622              
623 112         479 return $self->{_Auto_Purge_On_Set};
624             }
625              
626              
627             sub set_auto_purge_on_set
628             {
629 56     56 0 83 my ( $self, $auto_purge_on_set ) = @_;
630              
631 56         127 $self->{_Auto_Purge_On_Set} = $auto_purge_on_set;
632             }
633              
634              
635             sub get_auto_purge_on_get
636             {
637 88     88 0 110 my ( $self ) = @_;
638              
639 88         276 return $self->{_Auto_Purge_On_Get};
640             }
641              
642              
643             sub set_auto_purge_on_get
644             {
645 52     52 0 66 my ( $self, $auto_purge_on_get ) = @_;
646              
647 52         139 $self->{_Auto_Purge_On_Get} = $auto_purge_on_get;
648             }
649              
650              
651             sub _get_backend
652             {
653 856     856   937 my ( $self ) = @_;
654              
655 856         1988 return $self->{ _Backend };
656             }
657              
658              
659             sub _set_backend
660             {
661 52     52   66 my ( $self, $p_backend ) = @_;
662              
663 52         163 $self->{ _Backend } = $p_backend;
664             }
665              
666              
667              
668             1;
669              
670              
671             __END__