line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package KiokuDB::Linker; |
4
|
18
|
|
|
18
|
|
6543
|
use Moose; |
|
18
|
|
|
|
|
31
|
|
|
18
|
|
|
|
|
125
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
# perf improvements: |
7
|
|
|
|
|
|
|
# use a queue of required objects, queue up references, and bulk fetch |
8
|
|
|
|
|
|
|
# bulk fetch arrays |
9
|
|
|
|
|
|
|
# could support a Backend::Queueing which allows queuing of IDs for fetching, |
10
|
|
|
|
|
|
|
# to help clump or start a request and only read it when it's actually needed |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
|
13
|
18
|
|
|
18
|
|
80547
|
use Carp qw(croak); |
|
18
|
|
|
|
|
55
|
|
|
18
|
|
|
|
|
1149
|
|
14
|
18
|
|
|
18
|
|
88
|
use Scalar::Util qw(reftype weaken); |
|
18
|
|
|
|
|
27
|
|
|
18
|
|
|
|
|
859
|
|
15
|
18
|
|
|
18
|
|
91
|
use Symbol qw(gensym); |
|
18
|
|
|
|
|
26
|
|
|
18
|
|
|
|
|
1008
|
|
16
|
18
|
|
|
18
|
|
90
|
use Tie::ToObject; |
|
18
|
|
|
|
|
27
|
|
|
18
|
|
|
|
|
1379
|
|
17
|
|
|
|
|
|
|
|
18
|
18
|
|
|
18
|
|
6813
|
use KiokuDB::Error::MissingObjects; |
|
18
|
|
|
|
|
45
|
|
|
18
|
|
|
|
|
742
|
|
19
|
|
|
|
|
|
|
|
20
|
18
|
|
|
18
|
|
137
|
use namespace::clean -except => 'meta'; |
|
18
|
|
|
|
|
29
|
|
|
18
|
|
|
|
|
156
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
has live_objects => ( |
23
|
|
|
|
|
|
|
isa => "KiokuDB::LiveObjects", |
24
|
|
|
|
|
|
|
is => "ro", |
25
|
|
|
|
|
|
|
required => 1, |
26
|
|
|
|
|
|
|
handles => [qw(id_to_object ids_to_objects object_to_id objects_to_ids id_to_entry ids_to_entries)], |
27
|
|
|
|
|
|
|
); |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
has backend => ( |
30
|
|
|
|
|
|
|
does => "KiokuDB::Backend", |
31
|
|
|
|
|
|
|
is => "ro", |
32
|
|
|
|
|
|
|
required => 1, |
33
|
|
|
|
|
|
|
); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
has typemap_resolver => ( |
36
|
|
|
|
|
|
|
isa => "KiokuDB::TypeMap::Resolver", |
37
|
|
|
|
|
|
|
is => "ro", |
38
|
|
|
|
|
|
|
handles => [qw(expand_method refresh_method)], |
39
|
|
|
|
|
|
|
required => 1, |
40
|
|
|
|
|
|
|
); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
has queue => ( |
43
|
|
|
|
|
|
|
isa => "Bool", |
44
|
|
|
|
|
|
|
is => "ro", |
45
|
|
|
|
|
|
|
default => 1, |
46
|
|
|
|
|
|
|
); |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
has _queue => ( |
49
|
|
|
|
|
|
|
isa => "ArrayRef", |
50
|
|
|
|
|
|
|
is => "ro", |
51
|
|
|
|
|
|
|
default => sub { [] }, |
52
|
|
|
|
|
|
|
); |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
has _deferred => ( |
55
|
|
|
|
|
|
|
isa => "ArrayRef", |
56
|
|
|
|
|
|
|
is => "ro", |
57
|
|
|
|
|
|
|
default => sub { [] }, |
58
|
|
|
|
|
|
|
); |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
sub register_object { |
61
|
5673
|
|
|
5673
|
0
|
8658
|
my ( $self, $entry, $object, @args ) = @_; |
62
|
|
|
|
|
|
|
|
63
|
5673
|
100
|
|
|
|
136160
|
if ( my $id = $entry->id ) { |
64
|
5571
|
|
|
|
|
132895
|
my $l = $self->live_objects; |
65
|
|
|
|
|
|
|
|
66
|
5571
|
|
|
|
|
16891
|
$l->register_entry( $id => $entry ); |
67
|
5571
|
|
|
|
|
16585
|
$l->register_object( $id => $object, @args ); |
68
|
|
|
|
|
|
|
|
69
|
18
|
|
|
18
|
|
7249
|
use Scalar::Util qw(refaddr); |
|
18
|
|
|
|
|
30
|
|
|
18
|
|
|
|
|
28633
|
|
70
|
|
|
|
|
|
|
# break cycle for passthrough objects |
71
|
5571
|
100
|
100
|
|
|
127170
|
if ( ref($entry->data) and refaddr($object) == refaddr($entry->data) ) { |
72
|
1
|
|
|
|
|
5
|
weaken($entry->{data}); # FIXME there should be a MOP way to do this |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub expand_objects { |
78
|
1167
|
|
|
1167
|
0
|
2574
|
my ( $self, @entries ) = @_; |
79
|
|
|
|
|
|
|
|
80
|
1167
|
|
|
|
|
29481
|
my $l = $self->live_objects; |
81
|
|
|
|
|
|
|
|
82
|
1167
|
|
|
|
|
1602
|
my @objects; |
83
|
|
|
|
|
|
|
|
84
|
1167
|
|
|
|
|
2278
|
foreach my $entry ( @entries ) { |
85
|
|
|
|
|
|
|
# if the object was referred to in some other entry in @entries, it may |
86
|
|
|
|
|
|
|
# have already been loaded. |
87
|
2932
|
100
|
|
|
|
65179
|
if ( defined ( my $obj = $l->id_to_object($entry->id) ) ) { |
88
|
213
|
|
|
|
|
581
|
push @objects, $obj; |
89
|
|
|
|
|
|
|
} else { |
90
|
2719
|
|
|
|
|
8500
|
$self->inflate_data( $entry, \($objects[@objects]) ); |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
1167
|
|
|
|
|
3690
|
$self->load_queue; |
95
|
|
|
|
|
|
|
|
96
|
1167
|
|
|
|
|
19337
|
return @objects; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub expand_object { |
100
|
2903
|
|
|
2903
|
0
|
4749
|
my ( $self, $entry ) = @_; |
101
|
|
|
|
|
|
|
|
102
|
2903
|
|
|
|
|
9303
|
$self->inflate_data( $entry, \(my $obj) ); |
103
|
|
|
|
|
|
|
|
104
|
2899
|
|
|
|
|
7103
|
$self->load_queue; |
105
|
|
|
|
|
|
|
|
106
|
2899
|
|
|
|
|
33751
|
return $obj; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub queue_ref { |
110
|
6339
|
|
|
6339
|
0
|
7385
|
my ( $self, $ref, $into ) = @_; |
111
|
|
|
|
|
|
|
|
112
|
6339
|
100
|
|
|
|
156500
|
if ( $self->queue ) { |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
#my $b = $self->backend; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
#if ( $b->can("prefetch") ) { |
117
|
|
|
|
|
|
|
# $b->prefetch($ref->id); |
118
|
|
|
|
|
|
|
#} |
119
|
|
|
|
|
|
|
|
120
|
3731
|
|
|
|
|
3359
|
push @{ $self->_queue }, [ $ref, $into ]; |
|
3731
|
|
|
|
|
81727
|
|
121
|
|
|
|
|
|
|
} else { |
122
|
2608
|
50
|
|
|
|
5050
|
if ( ref $ref ) { |
123
|
2608
|
|
|
|
|
60012
|
$$into = $self->get_or_load_object($ref->id); |
124
|
2608
|
100
|
|
|
|
66687
|
weaken($$into) if $ref->is_weak; |
125
|
|
|
|
|
|
|
} else { |
126
|
0
|
|
|
|
|
0
|
$$into = $self->get_or_load_object($ref); |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
sub queue_finalizer { |
132
|
5368
|
|
|
5368
|
0
|
8704
|
my ( $self, @hooks ) = @_; |
133
|
|
|
|
|
|
|
|
134
|
5368
|
100
|
|
|
|
143919
|
if ( $self->queue ) { |
135
|
2984
|
|
|
|
|
3455
|
push @{ $self->_deferred }, @hooks; |
|
2984
|
|
|
|
|
70127
|
|
136
|
|
|
|
|
|
|
} else { |
137
|
2384
|
|
|
|
|
5358
|
foreach my $hook ( @hooks ) { |
138
|
2384
|
|
|
|
|
6095
|
$self->$hook(); |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub load_queue { |
144
|
4370
|
|
|
4370
|
0
|
5985
|
my $self = shift; |
145
|
|
|
|
|
|
|
|
146
|
4370
|
100
|
|
|
|
100547
|
return unless $self->queue; |
147
|
|
|
|
|
|
|
|
148
|
2138
|
|
|
|
|
48853
|
my $queue = $self->_queue; |
149
|
2138
|
|
|
|
|
47819
|
my $deferred = $self->_deferred; |
150
|
|
|
|
|
|
|
|
151
|
2138
|
|
|
|
|
5160
|
my @queue = @$queue; |
152
|
2138
|
|
|
|
|
3641
|
my @deferred = @$deferred; |
153
|
|
|
|
|
|
|
|
154
|
2138
|
|
|
|
|
2922
|
@$queue = (); |
155
|
2138
|
|
|
|
|
2985
|
@$deferred = (); |
156
|
|
|
|
|
|
|
|
157
|
2138
|
100
|
|
|
|
5235
|
if ( @queue ) { |
158
|
906
|
|
|
|
|
1241
|
my @ids; |
159
|
|
|
|
|
|
|
|
160
|
906
|
|
|
|
|
1617
|
foreach my $entry ( @queue ) { |
161
|
3731
|
|
|
|
|
3819
|
my $ref = $entry->[0]; |
162
|
3731
|
50
|
|
|
|
86807
|
push @ids, ref($ref) ? $ref->id : $ref; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
906
|
|
|
|
|
3095
|
my @objects = $self->get_or_load_objects(@ids); |
166
|
|
|
|
|
|
|
|
167
|
906
|
|
|
|
|
2071
|
foreach my $item ( @queue ) { |
168
|
3731
|
|
|
|
|
5252
|
my ( $data, $into ) = @$item; |
169
|
3731
|
|
|
|
|
5033
|
my $obj = shift @objects; |
170
|
|
|
|
|
|
|
|
171
|
3731
|
|
|
|
|
4387
|
$$into = $obj; |
172
|
|
|
|
|
|
|
|
173
|
3731
|
100
|
66
|
|
|
93654
|
weaken $$into if ref $data and $data->is_weak; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
2138
|
100
|
|
|
|
5586
|
if ( @deferred ) { |
178
|
1662
|
|
|
|
|
2925
|
foreach my $item ( @deferred ) { |
179
|
2984
|
|
|
|
|
15085
|
$self->$item; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
sub inflate_data { |
185
|
26856
|
|
|
26856
|
0
|
30876
|
my ( $self, $data, $into, $entry ) = @_; |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
# Kinda ugly... inflates $data into the scalar ref in $into |
188
|
|
|
|
|
|
|
# but this allows us to handle weakening properly. |
189
|
|
|
|
|
|
|
# god I hate perl's reftypes, why couldn't they be a little more consistent |
190
|
|
|
|
|
|
|
|
191
|
26856
|
100
|
|
|
|
91659
|
unless ( ref $data ) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
192
|
273
|
|
|
|
|
686
|
$$into = $data; |
193
|
|
|
|
|
|
|
} elsif ( ref $data eq 'KiokuDB::Reference' ) { |
194
|
6339
|
|
|
|
|
11954
|
$self->queue_ref( $data, $into ); |
195
|
|
|
|
|
|
|
} elsif ( ref $data eq 'KiokuDB::Entry' ) { |
196
|
5727
|
100
|
|
|
|
139547
|
if ( my $class = $data->class ) { |
197
|
5464
|
|
|
|
|
17038
|
my $expand_method = $self->expand_method($class); |
198
|
5464
|
|
|
|
|
20178
|
$$into = $self->$expand_method($data); |
199
|
|
|
|
|
|
|
} else { |
200
|
263
|
|
|
|
|
491
|
my $obj; |
201
|
|
|
|
|
|
|
|
202
|
263
|
|
|
|
|
6223
|
$self->inflate_data($data->data, \$obj, $data); |
203
|
|
|
|
|
|
|
|
204
|
263
|
|
|
|
|
973
|
$self->load_queue; # force vivification of $obj |
205
|
|
|
|
|
|
|
|
206
|
263
|
100
|
|
|
|
6820
|
if ( my $tie = $data->tied ) { |
207
|
35
|
50
|
|
|
|
126
|
if ( $tie eq 'H' ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
208
|
35
|
|
|
|
|
388
|
tie my %h, "Tie::ToObject" => $obj; |
209
|
35
|
|
|
|
|
687
|
$obj = \%h; |
210
|
|
|
|
|
|
|
} elsif ( $tie eq 'A' ) { |
211
|
0
|
|
|
|
|
0
|
tie my @a, "Tie::ToObject" => $obj; |
212
|
0
|
|
|
|
|
0
|
$obj = \@a; |
213
|
|
|
|
|
|
|
} elsif ( $tie eq 'G' ) { |
214
|
0
|
|
|
|
|
0
|
my $glob = gensym(); |
215
|
0
|
|
|
|
|
0
|
tie *$glob, "Tie::ToObject" => $obj, |
216
|
|
|
|
|
|
|
$obj = $glob; |
217
|
|
|
|
|
|
|
} elsif ( $tie eq 'S' ) { |
218
|
0
|
|
|
|
|
0
|
my $scalar; |
219
|
0
|
|
|
|
|
0
|
tie $scalar, "Tie::ToObject" => $obj; |
220
|
0
|
|
|
|
|
0
|
$obj = \$scalar; |
221
|
|
|
|
|
|
|
} else { |
222
|
0
|
|
|
|
|
0
|
die "Don't know how to tie $tie"; |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
263
|
|
|
|
|
542
|
$$into = $obj; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
5723
|
|
|
|
|
140433
|
$data->object($$into); |
230
|
|
|
|
|
|
|
} elsif ( ref($data) eq 'HASH' ) { |
231
|
294
|
|
|
|
|
404
|
my %targ; |
232
|
294
|
100
|
|
|
|
1033
|
$self->register_object( $entry => \%targ ) if $entry; |
233
|
294
|
|
|
|
|
1060
|
foreach my $key ( keys %$data ) { |
234
|
297
|
|
|
|
|
1124
|
$self->inflate_data( $data->{$key}, \$targ{$key} ); |
235
|
|
|
|
|
|
|
} |
236
|
294
|
|
|
|
|
835
|
$$into = \%targ; |
237
|
|
|
|
|
|
|
} elsif ( ref($data) eq 'ARRAY' ) { |
238
|
14103
|
|
|
|
|
12874
|
my @targ; |
239
|
14103
|
100
|
|
|
|
22384
|
$self->register_object( $entry => \@targ ) if $entry; |
240
|
14103
|
|
|
|
|
20845
|
for (@$data ) { |
241
|
5319
|
|
|
|
|
7902
|
push @targ, undef; |
242
|
5319
|
|
|
|
|
10973
|
$self->inflate_data( $_, \$targ[-1] ); |
243
|
|
|
|
|
|
|
} |
244
|
14103
|
|
|
|
|
30382
|
$$into = \@targ; |
245
|
|
|
|
|
|
|
} elsif ( ref($data) eq 'SCALAR' ) { |
246
|
37
|
|
|
|
|
84
|
my $targ = $$data; |
247
|
37
|
100
|
|
|
|
177
|
$self->register_object( $entry => \$targ ) if $entry; |
248
|
37
|
|
|
|
|
106
|
$$into = \$targ; |
249
|
|
|
|
|
|
|
} elsif ( ref($data) eq 'REF' ) { |
250
|
6
|
|
|
|
|
8
|
my $targ; |
251
|
6
|
50
|
|
|
|
11
|
$self->register_object( $entry => \$targ ) if $entry; |
252
|
6
|
|
|
|
|
18
|
$self->inflate_data( $$data, \$targ ); |
253
|
6
|
|
|
|
|
9
|
$$into = \$targ; |
254
|
|
|
|
|
|
|
} else { |
255
|
77
|
50
|
|
|
|
306
|
if ( blessed($data) ) { |
256
|
|
|
|
|
|
|
# this branch is for passthrough intrinsic values |
257
|
77
|
100
|
|
|
|
183
|
$self->register_object( $entry => $data ) if $entry; |
258
|
77
|
|
|
|
|
250
|
$$into = $data; |
259
|
|
|
|
|
|
|
} else { |
260
|
0
|
|
|
|
|
0
|
die "unsupported reftype: " . ref $data; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
sub get_or_load_objects { |
266
|
2444
|
|
|
2444
|
0
|
5362
|
my ( $self, @ids ) = @_; |
267
|
|
|
|
|
|
|
|
268
|
2444
|
100
|
|
|
|
11261
|
return $self->get_or_load_object($ids[0]) if @ids == 1; |
269
|
|
|
|
|
|
|
|
270
|
620
|
|
|
|
|
1200
|
my %objects; |
271
|
620
|
|
|
|
|
16315
|
@objects{@ids} = $self->live_objects->ids_to_objects(@ids); |
272
|
|
|
|
|
|
|
|
273
|
620
|
|
|
|
|
1919
|
my @missing = grep { not defined $objects{$_} } keys %objects; # @ids may contain duplicates |
|
2639
|
|
|
|
|
5041
|
|
274
|
|
|
|
|
|
|
|
275
|
620
|
|
|
|
|
2033
|
@objects{@missing} = $self->load_objects(@missing); |
276
|
|
|
|
|
|
|
|
277
|
620
|
|
|
|
|
6016
|
return @objects{@ids}; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
sub load_objects { |
281
|
620
|
|
|
620
|
0
|
1238
|
my ( $self, @ids ) = @_; |
282
|
|
|
|
|
|
|
|
283
|
620
|
|
|
|
|
1655
|
return $self->expand_objects( $self->get_or_load_entries(@ids) ); |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
sub get_or_load_entries { |
287
|
620
|
|
|
620
|
0
|
1234
|
my ( $self, @ids ) = @_; |
288
|
|
|
|
|
|
|
|
289
|
620
|
|
|
|
|
647
|
my %entries; |
290
|
620
|
|
|
|
|
2575
|
@entries{@ids} = $self->ids_to_entries(@ids); |
291
|
|
|
|
|
|
|
|
292
|
620
|
100
|
|
|
|
1426
|
if ( my @load = grep { !$entries{$_} } @ids ) { |
|
1522
|
|
|
|
|
3564
|
|
293
|
524
|
|
|
|
|
1978
|
@entries{@load} = $self->load_entries(@load); |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
620
|
|
|
|
|
3020
|
return @entries{@ids}; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
sub load_entries { |
300
|
524
|
|
|
524
|
0
|
1080
|
my ( $self, @ids ) = @_; |
301
|
|
|
|
|
|
|
|
302
|
524
|
|
|
|
|
13650
|
my @entries = $self->backend->get(@ids); |
303
|
|
|
|
|
|
|
|
304
|
524
|
50
|
33
|
|
|
2339
|
if ( @entries != @ids or grep { !$_ } @entries ) { |
|
1522
|
|
|
|
|
3800
|
|
305
|
0
|
|
|
|
|
0
|
my %entries; |
306
|
0
|
|
|
|
|
0
|
@entries{@ids} = @entries; |
307
|
0
|
|
|
|
|
0
|
my @missing = grep { !$entries{$_} } @ids; |
|
0
|
|
|
|
|
0
|
|
308
|
|
|
|
|
|
|
|
309
|
0
|
|
|
|
|
0
|
KiokuDB::Error::MissingObjects->throw( ids => \@missing ); |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
|
312
|
524
|
|
|
|
|
15503
|
my $l = $self->live_objects; |
313
|
524
|
|
|
|
|
1163
|
foreach my $entry ( @entries ) { |
314
|
1522
|
|
|
|
|
33684
|
$l->register_entry( $entry->id, $entry, in_storage => 1 ); |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
524
|
|
|
|
|
2271
|
return @entries; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
sub register_and_expand_entries { |
321
|
547
|
|
|
547
|
0
|
1240
|
my ( $self, @entries ) = @_; |
322
|
|
|
|
|
|
|
|
323
|
547
|
|
|
|
|
15273
|
my $l = $self->live_objects; |
324
|
547
|
|
|
|
|
1165
|
foreach my $entry ( @entries ) { |
325
|
1410
|
|
|
|
|
31852
|
$l->register_entry( $entry->id, $entry, in_storage => 1 ); |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
|
328
|
547
|
|
|
|
|
2200
|
$self->expand_objects(@entries); |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
sub get_or_load_object { |
332
|
4437
|
|
|
4437
|
0
|
6793
|
my ( $self, $id ) = @_; |
333
|
|
|
|
|
|
|
|
334
|
4437
|
100
|
|
|
|
114008
|
if ( defined( my $obj = $self->live_objects->id_to_object($id) ) ) { |
335
|
1488
|
|
|
|
|
2751
|
return $obj; |
336
|
|
|
|
|
|
|
} else { |
337
|
2949
|
|
|
|
|
8999
|
return $self->load_object($id); |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
sub refresh_objects { |
342
|
33
|
|
|
33
|
0
|
69
|
my ( $self, @objects ) = @_; |
343
|
|
|
|
|
|
|
|
344
|
33
|
|
|
|
|
202
|
$self->refresh_object($_) for @objects; |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
sub refresh_object { |
348
|
35
|
|
|
35
|
0
|
1102
|
my ( $self, $object ) = @_; |
349
|
|
|
|
|
|
|
|
350
|
35
|
|
|
|
|
178
|
my $id = $self->object_to_id($object); |
351
|
|
|
|
|
|
|
|
352
|
35
|
|
|
|
|
128
|
my $entry = $self->load_entry($id); |
353
|
|
|
|
|
|
|
|
354
|
35
|
|
|
|
|
909
|
my $refresh = $self->refresh_method( $entry->class ); |
355
|
|
|
|
|
|
|
|
356
|
35
|
|
|
|
|
183
|
$self->$refresh($object, $entry); |
357
|
35
|
|
|
|
|
108
|
$self->load_queue; |
358
|
|
|
|
|
|
|
|
359
|
35
|
|
|
|
|
383
|
return $object; |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
sub get_or_load_entry { |
363
|
2949
|
|
|
2949
|
0
|
3661
|
my ( $self, $id ) = @_; |
364
|
|
|
|
|
|
|
|
365
|
2949
|
|
66
|
|
|
10854
|
return $self->id_to_entry($id) || $self->load_entry($id); |
366
|
|
|
|
|
|
|
} |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
sub load_entry { |
369
|
2959
|
|
|
2959
|
0
|
4359
|
my ( $self, $id ) = @_; |
370
|
|
|
|
|
|
|
|
371
|
2959
|
100
|
|
|
|
72065
|
my $entry = ( $self->backend->get($id) )[0] |
372
|
|
|
|
|
|
|
or KiokuDB::Error::MissingObjects->throw( ids => [ $id ] ); |
373
|
|
|
|
|
|
|
|
374
|
2890
|
|
|
|
|
83510
|
$self->live_objects->register_entry( $id => $entry, in_storage => 1 ); |
375
|
|
|
|
|
|
|
|
376
|
2890
|
|
|
|
|
10569
|
return $entry; |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
sub load_object { |
380
|
2949
|
|
|
2949
|
0
|
5705
|
my ( $self, $id ) = @_; |
381
|
|
|
|
|
|
|
|
382
|
2949
|
|
|
|
|
6836
|
my $entry = $self->get_or_load_entry($id); |
383
|
|
|
|
|
|
|
|
384
|
2880
|
|
|
|
|
8604
|
return $self->expand_object($entry); |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
__PACKAGE__ |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
__END__ |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
=pod |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
=head1 NAME |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
KiokuDB::Linker - Relinks live objects from storage entries |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=head1 SYNOPSIS |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
# mostly internal |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
=head1 DESCRIPTION |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
The linker reconnects entry data, recreating the connected object graph in |
406
|
|
|
|
|
|
|
memory. |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
The linkage process starts with a an ID (or several IDs) to be loaded passed to |
409
|
|
|
|
|
|
|
the C<get_or_load_objects> method. |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
This ID will first be searched for in the live object set |
412
|
|
|
|
|
|
|
(L<KiokuDB::LiveObjects>). If the object is already live, then it will be |
413
|
|
|
|
|
|
|
returned as is. |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
If the object is not live, then the corresponding entry is fetched from the |
416
|
|
|
|
|
|
|
backend, and expanded into an actual instance. |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
Expansion consults the L<KiokuDB::TypeMap> using L<KiokuDB::TypeMap::Resolver>, |
419
|
|
|
|
|
|
|
to find the correct typemap entry (see |
420
|
|
|
|
|
|
|
L<KiokuDB::Collapser/"COLLAPSING STRATEGIES"> and L<KiokuDB::TypeMap>), and |
421
|
|
|
|
|
|
|
that is used for the actual expansion. |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
Most of the grunt work is delegated by the entries back to the linker using the |
424
|
|
|
|
|
|
|
C<inflate_data> method, which handles circular structures, retrying of tied |
425
|
|
|
|
|
|
|
structures, etc. |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
Inflated objects are registered with L<KiokuDB::LiveObjects>, and get inserted |
428
|
|
|
|
|
|
|
into the current live object scope (L<KiokuDB::LiveObjects::Scope>). The |
429
|
|
|
|
|
|
|
scope's job is to maintain a reference count of at least 1 for any loaded |
430
|
|
|
|
|
|
|
object, until it is destroyed itself. This ensures that weak references are not |
431
|
|
|
|
|
|
|
destroyed prematurely, but allows their use in order to avoid memory leaks. |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
=cut |
434
|
|
|
|
|
|
|
|