File Coverage

blib/lib/CHI/CacheObject.pm
Criterion Covered Total %
statement 116 116 100.0
branch 23 24 95.8
condition 7 9 77.7
subroutine 32 32 100.0
pod 5 13 38.4
total 183 194 94.3


line stmt bran cond sub pod time code
1             package CHI::CacheObject;
2             $CHI::CacheObject::VERSION = '0.61';
3 20     20   153 use CHI::Constants qw(CHI_Max_Time);
  20         42  
  20         1068  
4 20     20   13566 use Encode;
  20         205911  
  20         1790  
5 20     20   534 use strict;
  20         45  
  20         423  
6 20     20   139 use warnings;
  20         39  
  20         522  
7              
8 20     20   112 use constant f_key => 0;
  20         41  
  20         1246  
9 20     20   113 use constant f_raw_value => 1;
  20         43  
  20         861  
10 20     20   109 use constant f_serializer => 2;
  20         41  
  20         838  
11 20     20   107 use constant f_created_at => 3;
  20         40  
  20         826  
12 20     20   104 use constant f_early_expires_at => 4;
  20         39  
  20         814  
13 20     20   109 use constant f_expires_at => 5;
  20         39  
  20         958  
14 20     20   129 use constant f_is_transformed => 6;
  20         42  
  20         891  
15 20     20   112 use constant f_cache_version => 7;
  20         58  
  20         900  
16 20     20   122 use constant f_value => 8;
  20         47  
  20         1039  
17 20     20   160 use constant f_packed_data => 9;
  20         52  
  20         1052  
18 20     20   137 use constant f_size => 10;
  20         43  
  20         1228  
19              
20 20     20   163 use constant T_SERIALIZED => 1;
  20         49  
  20         1063  
21 20     20   123 use constant T_UTF8_ENCODED => 2;
  20         46  
  20         1007  
22 20     20   131 use constant T_COMPRESSED => 4;
  20         40  
  20         21278  
23              
24             my $Metadata_Format = "LLLCC";
25             my $Metadata_Length = 14;
26              
27             # Eschewing Moose and hash-based objects for this class to get the extra speed.
28             # Eventually will probably write in C anyway.
29              
30 4295     4295 1 12406 sub key { $_[0]->[f_key] }
31 306     306 1 1508 sub created_at { $_[0]->[f_created_at] }
32 211     211 0 1203 sub early_expires_at { $_[0]->[f_early_expires_at] }
33 4861     4861 1 15867 sub expires_at { $_[0]->[f_expires_at] }
34 4696     4696 0 12634 sub serializer { $_[0]->[f_serializer] }
35 91     91   436 sub _is_transformed { $_[0]->[f_is_transformed] }
36 6595     6595 0 102697 sub size { $_[0]->[f_size] }
37              
38             sub set_early_expires_at {
39 210     210 0 380 $_[0]->[f_early_expires_at] = $_[1];
40 210         446 undef $_[0]->[f_packed_data];
41             }
42              
43             sub set_expires_at {
44 210     210 0 394 $_[0]->[f_expires_at] = $_[1];
45 210         375 undef $_[0]->[f_packed_data];
46             }
47              
48             ## no critic (ProhibitManyArgs)
49             sub new {
50 4253     4253 0 11648 my ( $class, $key, $value, $created_at, $early_expires_at, $expires_at,
51             $serializer, $compress_threshold )
52             = @_;
53              
54             # Serialize/encode value if necessary - does this belong here, or in
55             # Driver.pm?
56             #
57 4253         6535 my $is_transformed = 0;
58 4253         6237 my $raw_value = $value;
59 4253         5691 my $size;
60 4253 100       8308 if ($serializer) {
61 3994 100       14835 if ( ref($raw_value) ) {
    100          
62 211         957 $raw_value = $serializer->serialize($raw_value);
63 211         13706 $is_transformed |= T_SERIALIZED;
64             }
65             elsif ( Encode::is_utf8($raw_value) ) {
66 98         346 $raw_value = Encode::encode( utf8 => $raw_value );
67 98         3219 $is_transformed |= T_UTF8_ENCODED;
68             }
69 3994 100 100     9808 if ( defined($compress_threshold)
70             && length($raw_value) > $compress_threshold )
71             {
72 7         5365 require Compress::Zlib;
73 7         419247 $raw_value = Compress::Zlib::memGzip($raw_value);
74 7         3223 $is_transformed |= T_COMPRESSED;
75             }
76 3994         6564 $size = length($raw_value) + $Metadata_Length;
77             }
78             else {
79 259         388 $size = 1;
80             }
81              
82             # Not sure where this should be set and checked
83             #
84 4253         6436 my $cache_version = 1;
85              
86 4253         18159 return bless [
87             $key, $raw_value, $serializer, $created_at,
88             $early_expires_at, $expires_at, $is_transformed, $cache_version,
89             $value, undef, $size
90             ], $class;
91             }
92              
93             sub unpack_from_data {
94 11831     11831 0 24461 my ( $class, $key, $data, $serializer ) = @_;
95              
96 11831 100       25932 return $data if !$serializer;
97 10603         21926 my $metadata = substr( $data, 0, $Metadata_Length );
98 10603         18888 my $raw_value = substr( $data, $Metadata_Length );
99 10603         48217 my $obj = bless [
100             $key, $raw_value,
101             $serializer, unpack( $Metadata_Format, $metadata )
102             ],
103             $class;
104 10603         29656 $obj->[f_packed_data] = $data;
105 10603         16337 $obj->[f_size] = length($data);
106 10603         24324 return $obj;
107             }
108              
109             sub pack_to_data {
110 4463     4463 0 7879 my ($self) = @_;
111              
112 4463 100       9564 return $self if !$self->serializer;
113 4186 50       10177 if ( !defined( $self->[f_packed_data] ) ) {
114             my $data = pack( $Metadata_Format,
115 4186         7630 ( @{$self} )[ f_created_at .. f_cache_version ] )
  4186         22248  
116             . $self->[f_raw_value];
117 4186         8895 $self->[f_packed_data] = $data;
118             }
119 4186         8599 return $self->[f_packed_data];
120             }
121              
122             sub is_expired {
123 10303     10303 1 17825 my ($self) = @_;
124              
125 10303         15719 my $expires_at = $self->[f_expires_at];
126 10303 100       26134 return undef if $expires_at == CHI_Max_Time;
127              
128 8178   66     16135 my $time = $CHI::Driver::Test_Time || time();
129 8178         10969 my $early_expires_at = $self->[f_early_expires_at];
130              
131 8178   66     49611 return $time >= $early_expires_at
132             && (
133             $time >= $expires_at
134             || (
135             rand() < (
136             ( $time - $early_expires_at ) /
137             ( $expires_at - $early_expires_at )
138             )
139             )
140             );
141             }
142              
143             sub value {
144 6439     6439 1 11753 my ($self) = @_;
145              
146 6439 100       15757 if ( !defined $self->[f_value] ) {
147 5505         8934 my $value = $self->[f_raw_value];
148 5505         7470 my $is_transformed = $self->[f_is_transformed];
149 5505 100       12081 if ( $is_transformed & T_COMPRESSED ) {
150 6         52 require Compress::Zlib;
151 6         32 $value = Compress::Zlib::memGunzip($value);
152             }
153 5505 100       14508 if ( $is_transformed & T_SERIALIZED ) {
    100          
154 233         613 $value = $self->serializer->deserialize($value);
155             }
156             elsif ( $is_transformed & T_UTF8_ENCODED ) {
157 77         371 $value = Encode::decode( utf8 => $value );
158             }
159 5505         18793 $self->[f_value] = $value;
160             }
161 6439         36609 return $self->[f_value];
162             }
163              
164             # get_* aliases for backward compatibility with Cache::Cache
165             #
166             *get_created_at = \&created_at;
167             *get_expires_at = \&expires_at;
168              
169             1;
170              
171             __END__