File Coverage

blib/lib/Method/Cached/Manager.pm
Criterion Covered Total %
statement 85 94 90.4
branch 35 44 79.5
condition 18 29 62.0
subroutine 17 19 89.4
pod 2 10 20.0
total 157 196 80.1


line stmt bran cond sub pod time code
1             package Method::Cached::Manager;
2              
3 6     6   2005 use strict;
  6         11  
  6         687  
4 6     6   69 use warnings;
  6         10  
  6         217  
5 6     6   33 use Carp qw/croak confess/;
  6         19  
  6         542  
6 6     6   5985 use UNIVERSAL::require;
  6         30047  
  6         89  
7              
8             my %DOMAIN;
9             my %METHOD;
10             my $DEFAULT_DOMAIN = { class => 'Cache::FastMmap' };
11             my %ATTR_PARSER = ( Cached => \&_parse_attr_args );
12              
13             {
14 6     6   459 no warnings 'once';
  6         20  
  6         15686  
15             *set_domain = \&set_domain_setting;
16             *get_domain = \&get_domain_setting;
17             }
18              
19             sub import {
20 13     13   193 my ($class, %args) = @_;
21 13 100 66     116 if (exists $args{-domains} && defined $args{-domains}) {
22 2         6 my $domains = $args{-domains};
23 2 100       309 ref $domains eq 'HASH'
24             || confess '-domains option should be a hash reference';
25 1         2 $class->set_domain(%{ $domains });
  1         16  
26             }
27 12 100 66     80 if (exists $args{-default} && defined $args{-default}) {
28 3         7 my $default = $args{-default};
29 3 100       489 ref $default eq 'HASH'
30             || confess '-default option should be a hash reference';
31 2         211 $class->default_domain($default);
32             }
33             else {
34 9         38 _inspect_storage_class($DEFAULT_DOMAIN->{class});
35             }
36             }
37              
38             sub set_method_setting {
39 24     24 0 59 my ($class, $name, $attr, @args) = @_;
40 24         55 my $parser_sub = _get_attr_parser($attr);
41 24         54 my ($domain, $expires, $key_rule, %extend) = $parser_sub->(@args);
42 24         204 $METHOD{$name} = {
43             domain => $domain,
44             expires => $expires,
45             key_rule => $key_rule,
46             %extend,
47             };
48             }
49              
50             sub get_method_setting {
51 103     103 0 180 my ($class, $name) = @_;
52 103         643 return $METHOD{$name};
53             }
54              
55             sub exists_method_setting {
56 2     2 0 5 my ($class, $name) = @_;
57 2         11 return exists $METHOD{$name};
58             }
59              
60             sub set_domain_setting {
61 1     1 0 3 my ($class, %args) = @_;
62 1         6 for my $name (keys %args) {
63 2         4 my $args = $args{$name};
64 2 50       8 if (exists $DOMAIN{$name}) {
65 0         0 warn 'This domain has already been defined: ' . $name;
66 0         0 next;
67             }
68 2         4 $DOMAIN{$name} = $args;
69 2         8 _inspect_storage_class($DOMAIN{$name}->{class});
70             }
71             }
72              
73             sub get_domain_setting {
74 105     105 0 205 my ($class, $domain) = @_;
75 105 100       556 return exists $DOMAIN{$domain} ? $DOMAIN{$domain} : $class->default_domain;
76             }
77              
78             sub exists_domain {
79 0     0 0 0 my ($class, $domain) = @_;
80 0         0 return exists $DOMAIN{$domain};
81             }
82              
83             sub default_domain {
84 107     107 1 213 my ($class, $args) = @_;
85 107 100       284 if ($args) {
86 3 50       12 exists $args->{key_rule} && delete $args->{key_rule};
87 3         13 $DEFAULT_DOMAIN = {
88 3         13 %{ $DEFAULT_DOMAIN },
89 3         674 %{ $args },
90             };
91 3         19 _inspect_storage_class($DEFAULT_DOMAIN->{class});
92             }
93 105         596 return $DEFAULT_DOMAIN;
94             }
95              
96             sub get_instance {
97 103     103 0 173 my ($class, $domain) = @_;
98 103 100       494 $domain->{instance} && return $domain->{instance};
99 4   33     46 my $st_class = $domain->{class} || croak 'class is necessary';
100 4   100     38 my $st_args = $domain->{args} || undef;
101 4 100       10 $domain->{instance} = $st_class->new(@{ $st_args || [] });
  4         87  
102             }
103              
104             sub delete {
105 1     1 1 7 my ($class, $name) = splice @_, 0, 2;
106 1 50       6 unless ($class->exists_method_setting($name)) {
107 0 0       0 if ($name =~ /^(.*)::[^:]*$/) {
108 0         0 my $package = $1;
109 0 0       0 $package->require || confess "Can't load module: $package";
110             }
111             }
112 1 50       4 if ($class->exists_method_setting($name)) {
113 1         4 my $method = $class->get_method_setting($name);
114 1         4 my $domain = $class->get_domain_setting($method->{domain});
115 1   33     6 my $rule = $method->{key_rule} || $domain->{key_rule};
116 1         6 my $key = Method::Cached::KeyRule::regularize($rule, $name, [ @_ ]);
117 1         7 my $cache = $class->get_instance($domain);
118 1   33     27 my $del_sub = $cache->can('delete') || $cache->can('clear');
119 1         8 $del_sub->($cache, $key . $_) for qw/ :l :s /;
120             }
121             }
122              
123             sub set_attr_parser {
124 0     0 0 0 my ($class, $attr, $parser) = @_;
125 0         0 $ATTR_PARSER{$attr} = $parser;
126             }
127              
128             sub _get_attr_parser {
129 24     24   32 my $attr = shift;
130 24   50     93 return $ATTR_PARSER{$attr} || \&_parse_attr_args;
131             }
132              
133             sub _parse_attr_args {
134 24     24   31 my $domain = q{};
135 24         29 my $expires = 0;
136 24         32 my $key_rule = undef;
137 24 100       64 if (0 < @_) {
138 23 100 66     222 if (! defined $_[0] || $_[0] !~ /^?\d+$/) {
139 12         18 $domain = shift;
140             }
141             }
142 24   100     91 $domain ||= q{};
143 24 100       55 if (0 < @_) {
144 23 50       109 $expires = ($_[0] =~ /^\d+$/) ? shift @_ : confess
145             'The first argument or the second argument should be a numeric value.';
146 23 100       66 $key_rule = shift if 0 < @_;
147             }
148 24         73 return ($domain, $expires, $key_rule);
149             }
150              
151             sub _inspect_storage_class {
152 14     14   29 my $any_class = shift;
153 14         22 my $invalid;
154 14 100       126 $any_class->require || confess "Can't load module: $any_class";
155 13   100     83379 $any_class->can($_) || $invalid++ for qw/new set get/;
156 13 100 66     266 $any_class->can('delete') || $any_class->can('remove') || $invalid++;
157 13 100       5120 $invalid &&
158             croak 'storage-class needs the following methods: new, set, get, delete or remove';
159             }
160              
161             1;
162              
163             __END__