File Coverage

blib/lib/Cache/Entry.pm
Criterion Covered Total %
statement 70 76 92.1
branch 22 30 73.3
condition 5 6 83.3
subroutine 14 17 82.3
pod 8 11 72.7
total 119 140 85.0


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Cache::Entry - interface for a cache entry
4              
5             =head1 SYNOPSIS
6              
7             my Cache::Entry $entry = $cache->entry( $key )
8             my $data;
9             if ($entry->exists()) {
10             $data = $entry->get();
11             }
12             else {
13             $data = get_some_data($key);
14             $entry->set($data, '10 minutes');
15             }
16              
17             =head1 DESCRIPTION
18              
19             Objects derived from Cache::Entry represent an entry in a Cache. Methods are
20             provided that act upon the data in the entry, and allow you to set things like
21             the expiry time.
22              
23             Users should not create instances of Cache::Entry directly, but instead use
24             the entry($key) method of a Cache instance.
25              
26             =head1 METHODS
27              
28             =over
29              
30             =cut
31             package Cache::Entry;
32              
33             require 5.006;
34 7     7   874 use strict;
  7         9  
  7         242  
35 7     7   28 use warnings;
  7         7  
  7         172  
36 7     7   2419 use Cache;
  7         17  
  7         201  
37 7     7   1224 use Storable;
  7         5206  
  7         436  
38 7     7   32 use Carp;
  7         33  
  7         306  
39              
40 7     7   29 use fields qw(cache key);
  7         6  
  7         40  
41              
42             our $VERSION = '2.11';
43              
44              
45             sub new {
46 242     242 0 269 my Cache::Entry $self = shift;
47 242         234 my ($cache, $key) = @_;
48              
49 242 50       425 ref $self or croak 'Must use a subclass of Cache::Entry';
50              
51 242         334 $self->{cache} = $cache;
52 242         279 $self->{key} = $key;
53              
54 242         364 return $self;
55             }
56              
57             =item my $cache = $e->cache()
58              
59             Returns a reference to the cache object this entry is from.
60              
61             =cut
62              
63             sub cache {
64 0     0 1 0 my Cache::Entry $self = shift;
65 0         0 return $self->{cache};
66             }
67              
68             =item my $key = $e->key()
69              
70             Returns the cache key this entry is associated with.
71              
72             =cut
73              
74             sub key {
75 5     5 1 210 my Cache::Entry $self = shift;
76 5         24 return $self->{key};
77             }
78              
79             =item my $bool = $e->exists()
80              
81             Returns a boolean value (1 or 0) to indicate whether there is any data
82             present in the cache for this entry.
83              
84             =cut
85              
86             sub exists;
87              
88             =item $e->set( $data, [ $expiry ] )
89              
90             Stores the data into the cache. The data must be a scalar (if you want to
91             store more complex data types, see freeze and thaw below).
92              
93             The expiry time may be provided as an optional 2nd argument and is in the same
94             form as for 'set_expiry($time)'.
95              
96             =cut
97              
98             # ensure expiry is normalized then call _set
99             sub set {
100 247     247 1 320 my Cache::Entry $self = shift;
101 247         255 my ($data, $expiry) = @_;
102              
103 247 50       418 unless (defined $data) {
104 0         0 return $self->remove();
105             }
106              
107 247 50       352 ref($data) and warnings::warnif('Cache','Reference passed to set');
108              
109 247 100       456 if ($#_ < 1) {
110 244         619 $expiry = $self->{cache}->default_expires();
111             }
112             else {
113 3         10 $expiry = Cache::Canonicalize_Expiration_Time($expiry);
114             }
115              
116 247 100 100     509 if (defined $expiry and $expiry == 0) {
117 1         4 return $self->remove();
118             }
119              
120 246         485 return $self->_set($data, $expiry);
121             }
122              
123             # Implement this method instead of set
124             sub _set;
125              
126             =item my $data = $e->get()
127              
128             Returns the data from the cache, or undef if the entry doesn't exist.
129              
130             =cut
131              
132             # ensure load_callback and validity callback is issued
133             sub get {
134 17     17 1 30 my Cache::Entry $self = shift;
135 17         27 my Cache $cache = $self->{cache};
136              
137 17         64 my $result = $self->_get(@_);
138              
139 17 100       41 if (defined $result) {
140 14         24 my $validate_callback = $cache->{validate_callback};
141 14 100       62 $validate_callback or return $result;
142 1 50       4 $validate_callback->($self) and return $result;
143             }
144              
145 3 100       13 my $load_callback = $cache->{load_callback}
146             or return undef;
147 2         3 my @options;
148 2         7 ($result, @options) = $load_callback->($self);
149 2 50       9 $self->set($result, @options) if defined $result;
150              
151 2         20 return $result;
152             }
153              
154             # Implement this method instead of get
155             sub _get;
156              
157             =item my $size = $e->size()
158              
159             Returns the size of the entry data, or undef if the entry doesn't exist.
160              
161             =cut
162              
163             sub size;
164              
165             =item $e->remove()
166              
167             Clear the data for this entry from the cache.
168              
169             =cut
170              
171             sub remove;
172              
173             =item my $expiry = $e->expiry()
174              
175             Returns the expiry time of the entry, in seconds since the epoch.
176              
177             =cut
178              
179             sub expiry;
180 0     0 0 0 sub get_expiry { shift->expiry(@_); }
181              
182             =item $e->set_expiry( $time )
183              
184             Set the expiry time in seconds since the epoch, or alternatively using a
185             string like '10 minutes'. Valid units are s, second, seconds, sec, m, minute,
186             minutes, min, h, hour, hours, w, week, weeks, M, month, months, y, year and
187             years. You can also specify an absolute time, such as '16 Nov 94 22:28:20' or
188             any other time that Date::Parse can understand. Finally, the strings 'now'
189             and 'never' may also be used.
190              
191             =cut
192              
193             # ensure time is normalized then call _set_expiry
194             sub set_expiry {
195 2     2 1 12 my Cache::Entry $self = shift;
196 2         3 my ($time) = @_;
197              
198 2         8 my $expiry = Cache::Canonicalize_Expiration_Time($time);
199              
200 2 100 66     15 if (defined $expiry and $expiry == 0) {
201 1         7 return $self->remove();
202             }
203              
204 1         3 $self->_set_expiry($expiry);
205             }
206              
207             # Implement this method instead of set_expiry
208             sub _set_expiry;
209              
210             =item my $fh = $e->handle( [$mode, [$expiry] ] )
211              
212             Returns an IO::Handle by which data can be read, or written, to the cache.
213             This is useful if you are caching a large amount of data - although it should
214             be noted that only some cache implementations (such as Cache::File) provide an
215             efficient mechanism for implementing this.
216              
217             The optional mode argument can be any of the perl mode strings as used for the
218             open function '<', '+<', '>', '+>', '>>' and '+>>'. Alternatively it can be
219             the corresponding fopen(3) modes of 'r', 'r+', 'w', 'w+', 'a' and 'a+'. The
220             default mode is '+<' (or 'r+') indicating reading and writing.
221              
222             The second argument is used to set the expiry time for the entry if it doesn't
223             exist already and the handle is opened for writing. It is also used to reset
224             the expiry time if the entry is truncated by opening in the '>' or '+>' modes.
225             If the expiry is not provided in these situations then the default expiry time
226             for the cache is applied.
227              
228             Cache implementations will typically provide locking around cache entries, so
229             that writers will have have an exclusive lock and readers a shared one. Thus
230             the method get() (or obtaining another handle) should be avoided whilst a
231             write handle is held. Using set() or remove(), however, should be supported.
232             These clear the current entry and whilst they do not invalidate open handles,
233             those handle will from then on refer to old data and any changes to the data
234             will be discarded.
235              
236             =cut
237              
238             # ensure mode and expiry are normalized then call _handle
239             sub handle {
240 11     11 1 17 my Cache::Entry $self = shift;
241 11         15 my ($mode, $expiry) = @_;
242              
243             # normalize mode
244 11 100       24 if ($mode) {
245 8         1409 require IO::Handle;
246 8         11140 $mode = IO::Handle::_open_mode_string($mode);
247             }
248             else {
249 3         5 $mode = '+<';
250             }
251              
252 11 50       100 if ($#_ < 1) {
253 11         47 $self->_handle($mode, $self->{cache}->default_expires());
254             }
255             else {
256 0         0 $self->_handle($mode, Cache::Canonicalize_Expiration_Time($expiry));
257             }
258             }
259              
260             # Implement this method instead of handle
261             sub _handle;
262              
263              
264             =back
265              
266             =head1 STORING VALIDITY OBJECTS
267              
268             There are two additional set & get methods that can be used to store a
269             validity object that is associated with the data in question. Typically this
270             is useful in conjunction with a validate_callback, and may be used to store a
271             timestamp or similar to validate against. The validity data stored may be any
272             complex data that can be serialized via Storable.
273              
274             =over
275              
276             =item $e->validity()
277              
278             =cut
279              
280             sub validity;
281 0     0 0 0 sub get_validity { shift->validity(@_); }
282              
283             =item $e->set_validity( $data )
284              
285             =cut
286              
287             sub set_validity;
288              
289              
290             =back
291              
292             =head1 STORING COMPLEX OBJECTS
293              
294             The set and get methods only allow for working with simple scalar types, but
295             if you want to store more complex types they need to be serialized first. To
296             assist with this, the freeze and thaw methods are provided. They are simple
297             wrappers to get & set that use Storable to do the serialization and
298             de-serialization of the data.
299              
300             Note, however, that you must be careful to ONLY use 'thaw' on data that was
301             stored via 'freeze'. Otherwise the stored data wont actually be in Storable
302             format and it will complain loudly.
303              
304             =over
305              
306             =item $e->freeze( $data, [ $expiry ] )
307              
308             Identical to 'set', except that data may be any complex data type that can be
309             serialized via Storable.
310              
311             =cut
312              
313             sub freeze {
314 1     1 1 1 my Cache::Entry $self = shift;
315 1         2 my ($data, @args) = @_;
316 1 50       3 ref($data) or warnings::warnif('Cache','Non-reference passed to freeze');
317 1         4 return $self->set(Storable::nfreeze($data), @args);
318             }
319              
320             =item $e->thaw()
321              
322             Identical to 'get', except that it will return a complex data type that was
323             set via 'freeze'.
324              
325             =cut
326              
327             sub thaw {
328 1     1 1 2 my Cache::Entry $self = shift;
329 1         3 my $data = $self->get(@_);
330 1 50       6 defined $data or return undef;
331 1         5 return Storable::thaw($data);
332             }
333              
334             =back
335              
336             =cut
337              
338              
339             1;
340             __END__