File Coverage

blib/lib/RMI/ProxyReference.pm
Criterion Covered Total %
statement 34 35 97.1
branch 5 8 62.5
condition 5 6 83.3
subroutine 8 8 100.0
pod 0 1 0.0
total 52 58 89.6


line stmt bran cond sub pod time code
1             package RMI::ProxyReference;
2              
3 24     24   136 use strict;
  24         42  
  24         855  
4 24     24   129 use warnings;
  24         40  
  24         754  
5 24     24   122 use version;
  24         37  
  24         157  
6             our $VERSION = $RMI::VERSION;
7              
8 24     24   1896 use RMI;
  24         39  
  24         3300  
9              
10              
11             # When references are "passed" to a remote client/server, the proxy is tied using this package to proxy back all data access.
12             # NOTE: if the reference is blessed, the proxy will also be blessed into RMI::ProxyObject, in addition to being _tied_ to this package.
13              
14             *TIEARRAY = \&TIE;
15             *TIEHASH = \&TIE;
16             *TIESCALAR = \&TIE;
17             *TIEHANDLE = \&TIE;
18              
19             # CODE references are handled specially, using an anonymous sub on the proxy side, without tie, since tie does not support them
20              
21             sub TIE {
22 32     32 0 309 my $obj = bless [@_], $_[0];
23 32         180 return $obj;
24             }
25              
26             sub AUTOLOAD {
27 24     24   163 no strict 'refs';
  24         35  
  24         17455  
28 65     65   13049 my $method = $RMI::ProxyReference::AUTOLOAD;
29 65         644 $method =~ s/^.*:://g;
30 65         156 my $o = $_[0];
31 65         180 my ($c,$n,$v,$t,$delegate_class) = @$o;
32 65   66     301 my $node = $RMI::Node::node_for_object{$t} || $n;
33 65 50       166 print "$RMI::DEBUG_MSG_PREFIX R: $$ reference calling $method in $delegate_class from $o ($n,$v,$t) through node $node with " . join(",", @_) . "\n" if $RMI::DEBUG;
34 65 50       145 unless ($node) {
35 0         0 die "no node for reference $o: method $method for @_ (@$o)?" . Data::Dumper::Dumper(\%RMI::Node::node_for_object);
36             }
37             # inheritance doesn't work this one method
38             # TODO: make a custom sub-class for these instead of using Tie::StdX directly
39 65 100 100     374 if ($delegate_class eq 'Tie::StdArray' and $method eq 'EXTEND') {
40 2         4 $delegate_class = 'Tie::Array';
41             }
42 65         588 $node->send_request_and_receive_response('call_function', $delegate_class . '::' . $method, @_);
43             }
44              
45             sub DESTROY {
46 27     27   1292 my $self = $_[0];
47 27         89 my ($c,$node,$remote_id,$t) = @$self;
48 27         262 $node = delete $RMI::Node::node_for_object{$t};
49 27 50       128 print "$RMI::DEBUG_MSG_PREFIX R: $$ DESTROYING $self wrapping $remote_id from $node with $t\n" if $RMI::DEBUG;
50 27         100 delete $node->{_received_objects}{$remote_id};
51 27         48 push @{ $node->{_received_and_destroyed_ids} }, $remote_id;
  27         1413  
52             }
53              
54             # NOTE: this module uses Tie::Std* modules in non-standard ways
55             #
56             # AUTOLOAD makes a remote function call for every operation to one of the Tie::Std*
57             # family of modules. The code for these modules works by beautiful coincidence
58             # on the side which originated the reference, even though that reference is not
59             # actually tied to that package in that process (nor in the remote process, b/c
60             # there it is tied to _this_ package).
61             #
62             # It is not known yet whether this has unseen limitations, and we will eventually
63             # need custom packages to manage remote operations on references.
64              
65             1;
66              
67             =pod
68              
69             =head1 NAME
70              
71             RMI::ProxyReference - used internally by RMI to tie references
72            
73             =head1 VERSION
74              
75             This document describes RMI::ProxyReference v0.10.
76              
77             =head1 DESCRIPTION
78              
79             When an refrerence is detected in the params or return value for an RMI
80             call, the sending RMI::Node (client sending params or server sending
81             results) captures a reference to the item internally, generates an "id"
82             for that object, and sends the "id" across the handle instead.
83              
84             When the remote side recieves the "id", it also recieves an indication
85             that this is the id of a proxied reference, an indication of what Perl
86             base type it is (SCALAR,ARRAY,HASH,CODE,GLOB/IO), and what class it is
87             blessed-into, if any. The remote side constructs a reference of
88             the appropriate type, and uses "tie" to bind it to this package.
89              
90             All subsequent attempst to use the reference fire AUTOLOAD,
91             and result in a request across the "wire" to the other side.
92              
93             Note: if the reference is blessed, it also blesses the object as an
94             B. Because bless and tie are independent, a
95             single reference can (and will) be blessed and tied to two different
96             packages, one for method call resolution, and one for usage of
97             the reference as a HASH ref, ARRAY ref, CODE ref, etc.
98              
99             Details of Perl tie are somewhat esoteric, but it is worth mentioning
100             that tying a reference $o results in an additional, separate object
101             being created, which is the invocant above whenever activity on the
102             reference occurs. That second object is managed internally by Perl,
103             though we are able to use it to store the identify of $o on the "real" side,
104             along with information about the RMI::Node through which to proxy
105             calls.
106              
107             Note: CODE references are not tied, and do not use this class. A
108             proxy for a code reference is generated as an anonymous subrotine
109             which makes a remote call via its RMI::Node upon execute.
110              
111             =head1 METHODS
112              
113             The RMI::ProxyReference implements TIEHASH TIEARRAY TIESCALAR and
114             TIEHANDLE with a single implementation. All other methods are
115             implemented by proxying back to the original side via AUTOLOAD.
116              
117             On the local side, all attempts to access the real reference go through
118             Tie::StdArray, Tie::StdHash, Tie::StdScalar and Tie::StdHandle. Note
119             that we do not _actually_ "tie" the real reference on the original side
120             before sending it. These methods work just fine with the
121              
122             =head1 BUGS AND CAVEATS
123              
124             See general bugs in B for general system limitations
125              
126             =head1 SEE ALSO
127              
128             B B B B B
129              
130             B B B B
131              
132             =head1 AUTHORS
133              
134             Scott Smith
135              
136             =head1 COPYRIGHT
137              
138             Copyright (c) 2008 - 2009 Scott Smith All rights reserved.
139              
140             =head1 LICENSE
141              
142             This program is free software; you can redistribute it and/or modify it under
143             the same terms as Perl itself.
144              
145             The full text of the license can be found in the LICENSE file included with this
146             module.
147              
148             =cut
149