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