line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Class::ReluctantORM::Registry; |
2
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
28
|
|
3
|
1
|
|
|
1
|
|
7
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
116
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 NAME |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
Class::ReluctantORM::Registry - Store CRO instances uniquely |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 SYNOPSIS |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
# Setup a CRO class to use a Hash-based registry |
13
|
|
|
|
|
|
|
package MyCRO; |
14
|
|
|
|
|
|
|
use base 'Class::ReluctantORM'; |
15
|
|
|
|
|
|
|
MyCRO->build_class( |
16
|
|
|
|
|
|
|
... |
17
|
|
|
|
|
|
|
registry => 'Class::ReluctantORM::Registry::Hash', |
18
|
|
|
|
|
|
|
); |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# Use the default registry class |
21
|
|
|
|
|
|
|
OtherCRO->build_class( ... ); # omit registry param |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# Change the default registry class |
24
|
|
|
|
|
|
|
Class::ReluctantORM::Registry->default_registry_class |
25
|
|
|
|
|
|
|
('Class::ReluctantORM::Registry::Custom'); |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# Disable registries |
28
|
|
|
|
|
|
|
Class::ReluctantORM::Registry->default_registry_class |
29
|
|
|
|
|
|
|
('Class::ReluctantORM::Registry::None'); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# Work with a class's registry |
32
|
|
|
|
|
|
|
my $reg = MyCRO->registry(); |
33
|
|
|
|
|
|
|
print "Have " . $reg->count() . " objects cached\n"; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
$reg->walk(sub { |
36
|
|
|
|
|
|
|
my $obj = shift; |
37
|
|
|
|
|
|
|
... |
38
|
|
|
|
|
|
|
}); |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
my $obj = $reg->fetch($id); |
41
|
|
|
|
|
|
|
$reg->store($obj); |
42
|
|
|
|
|
|
|
$reg->purge($id); |
43
|
|
|
|
|
|
|
$reg->purge_all(); |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=head1 DESCRIPTION |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
The Registry facility provides a way to ensure that objects loaded from the database are unique in memory. Upon initial fetch from the database, each CRO object is stored in its class's Registry. Subsequent fetches will result in the first object being returned. |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
This class provides a generalized interface for Registries. Specific subclasses provide specific implementations, each of which has strengths and weaknesses. A do-nothing Registry is provided as well, Registry::None . |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
Each CRO class may choose its registry implementation by naming a Registry subclass using the 'registry' parameter to build_class. If the parameter is not provided, the class named by Class::ReluctantORM::Registry->default_registry_class() will be used. You may change this default by passing a value. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=head1 NOTES ON IMPLEMENTING REGISTRIES |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
You may also write your own Registry classes. Simply subclass from this class, and implement the methods listed under METHODS FOR SUBCLASSES TO IMPLEMENT. |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
You are free to extend the Registry API (for example, with expirations or size or count limits). |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
You must use weak references to track objects. Otherwise this will leak memory badly. See Scalar::Util::weaken . |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=head1 METHODS PROVIDED BY THIS SUPERCLASS |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=cut |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
#our $DEFAULT_REGISTRY_CLASS = 'Class::ReluctantORM::Registry::None'; |
66
|
|
|
|
|
|
|
our $DEFAULT_REGISTRY_CLASS = 'Class::ReluctantORM::Registry::Hash'; |
67
|
1
|
|
|
1
|
|
7
|
use base 'Class::Accessor'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
103
|
|
68
|
1
|
|
|
1
|
|
6
|
use Class::ReluctantORM::Utilities qw(conditional_load_subdir); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
54
|
|
69
|
1
|
|
|
1
|
|
5
|
use Class::ReluctantORM::Exception; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
30
|
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
BEGIN { |
72
|
1
|
|
|
1
|
|
14
|
conditional_load_subdir(__PACKAGE__); |
73
|
|
|
|
|
|
|
}; |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=head2 $reg = RegClass->new($target_class); |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
A basic constructor is provided. It sets the target class and blesses a hashref. |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=cut |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub new { |
83
|
0
|
|
|
0
|
1
|
|
my $reg_class = shift; |
84
|
0
|
|
|
|
|
|
my $tgt_class = shift; |
85
|
0
|
|
|
|
|
|
my $self = bless {}, $reg_class; |
86
|
0
|
|
|
|
|
|
$self->set('target_class', $tgt_class); |
87
|
0
|
|
|
|
|
|
return $self; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=head2 $reg_class = Class::ReluctantORM::Registry->default_registry_class(); |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=head2 Class::ReluctantORM::Registry->default_registry_class($new_default); |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
Reads or sets the defualt Registry class used when no 'registry' param is passed to build_class(). |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
When setting, the class passed must be a subclass of Class::ReluctantORM::Registry. |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=cut |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub default_registry_class { |
101
|
0
|
|
|
0
|
1
|
|
my $inv = shift; # ignore |
102
|
0
|
0
|
|
|
|
|
if (@_) { |
103
|
|
|
|
|
|
|
# setting |
104
|
0
|
|
|
|
|
|
my $new_default = shift; |
105
|
0
|
0
|
|
|
|
|
unless ($new_default->isa('Class::ReluctantORM::Registry')) { |
106
|
0
|
|
|
|
|
|
Class::ReluctantORM::Exception::Param::BadValue->croak(param => 'default_registry', error => 'Registry class must inherit from Class::ReluctantORM::Registry', value => $new_default); |
107
|
|
|
|
|
|
|
} |
108
|
0
|
|
|
|
|
|
$DEFAULT_REGISTRY_CLASS = $new_default; |
109
|
|
|
|
|
|
|
} |
110
|
0
|
|
|
|
|
|
return $DEFAULT_REGISTRY_CLASS; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=head2 $class = $registry->target_class(); |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
Returns the CRO class for which this Registry is caching objects. |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=cut |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
__PACKAGE__->mk_ro_accessors('target_class'); |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=head1 METHODS FOR SUBCLASSES TO IMPLEMENT |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=cut |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=head2 $obj = $registry->fetch($id); |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
Looks for an object previously stored with composite ID $id, and if found, returns it. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
If not found, returns undef. |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=cut |
134
|
|
|
|
|
|
|
|
135
|
0
|
|
|
0
|
1
|
|
sub fetch { Class::ReluctantORM::Exception::Call::PureVirtual->croak(); } |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=head2 $registry->store($obj); |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
Stores an object in the registry, using its id() as the key. If the object already existed, it is replaced. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=cut |
143
|
|
|
|
|
|
|
|
144
|
0
|
|
|
0
|
1
|
|
sub store { Class::ReluctantORM::Exception::Call::PureVirtual->croak(); } |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=head2 $registry->purge($id); |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
Removes an object from the registry. This doesn't invalidate any other references to the object, but subsequent fetch()s will return undef until an objecvt with the same ID is stored again. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=cut |
152
|
|
|
|
|
|
|
|
153
|
0
|
|
|
0
|
1
|
|
sub purge { Class::ReluctantORM::Exception::Call::PureVirtual->croak(); } |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=head2 $registry->purge_all(); |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Removes all objects from the registry. |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=cut |
160
|
|
|
|
|
|
|
|
161
|
0
|
|
|
0
|
1
|
|
sub purge_all { Class::ReluctantORM::Exception::Call::PureVirtual->croak(); } |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=head2 $int = $registry->count(); |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
Returns an integer count of the number of objects currently tracked by the registry. |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=cut |
169
|
|
|
|
|
|
|
|
170
|
0
|
|
|
0
|
1
|
|
sub count { Class::ReluctantORM::Exception::Call::PureVirtual->croak(); } |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=head2 $registry->walk($coderef); |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
Fetches each stored object and calls the provided coderef, sending the object as the only argument. |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=cut |
178
|
|
|
|
|
|
|
|
179
|
0
|
|
|
0
|
1
|
|
sub walk { Class::ReluctantORM::Exception::Call::PureVirtual->croak(); } |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=head1 AUTHOR |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Clinton Wolfe clwolfe@cpan.org January 2010 |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=cut |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
1; |