File Coverage

blib/lib/RMI/Client.pm
Criterion Covered Total %
statement 40 46 86.9
branch 4 6 66.6
condition n/a
subroutine 12 14 85.7
pod 9 10 90.0
total 65 76 85.5


line stmt bran cond sub pod time code
1             package RMI::Client;
2              
3 24     24   156 use strict;
  24         108  
  24         773  
4 24     24   122 use warnings;
  24         40  
  24         1013  
5             our $VERSION = $RMI::VERSION;
6              
7 24     24   126 use base 'RMI::Node';
  24         59  
  24         20407  
8              
9             # all methods in this module are convenience wrappers for RMI::Node generic methods.
10              
11             *call_sub = \&call_function;
12              
13             sub call_function {
14 10     10 1 7469 my ($self,$fname,@params) = @_;
15 10         142 return $self->send_request_and_receive_response('call_function', $fname, @params);
16             }
17              
18             sub call_class_method {
19 7     7 1 9188 my ($self,$class,$method,@params) = @_;
20 7         183 return $self->send_request_and_receive_response('call_class_method', $class, $method, @params);
21             }
22              
23             sub call_object_method {
24 1     1 0 1071 my ($self,$object,$method,@params) = @_;
25 1         6 return $self->send_request_and_receive_response('call_object_method', $object, $method, @params);
26             }
27              
28             sub call_eval {
29 92     92 1 27322 my ($self,$src,@params) = @_;
30 92         1033 return $self->send_request_and_receive_response('call_eval', $src, @params);
31             }
32              
33             sub call_use {
34 7     7 1 22 my ($self,$class,$module,$use_args) = @_;
35              
36 7         14 my @exported;
37             my $path;
38            
39 7 100       137 ($class,$module,$path, @exported) =
40             $self->send_request_and_receive_response(
41             'call_use',
42             $class,
43             $module,
44             defined($use_args),
45             ($use_args ? @$use_args : ())
46             );
47            
48 7         62 return ($class,$module,$path,@exported);
49             }
50              
51             sub call_use_lib {
52 0     0 1 0 my ($self,$lib) = @_;
53 0         0 return $self->send_request_and_receive_response('call_use_lib', $lib);
54             }
55              
56             sub use_remote {
57 5     5 1 5867 my $self = shift;
58 5         13 my $class = shift;
59 5         100 $self->bind_local_class_to_remote($class, undef, @_);
60 4         43 $self->bind_local_var_to_remote('@' . $class . '::ISA');
61 4         23 return 1;
62             }
63              
64             sub use_lib_remote {
65 1     1 1 1763 my $self = shift;
66 1         34 unshift @INC, $self->virtual_lib;
67             }
68              
69             sub virtual_lib {
70 1     1 1 3 my $self = shift;
71             my $virtual_lib = sub {
72 2     2   1365 my $module = pop;
73 2         86 $self->bind_local_class_to_remote(undef,$module);
74 2         25 my $sym = Symbol::gensym();
75 2         68 my $done = 0;
76             return $sym, sub {
77 4 100       15 if (! $done) {
78 2         5 $_ = '1;';
79 2         4 $done++;
80 2         19 return 1;
81             }
82             else {
83 2         730 return 0;
84             }
85 2         222 };
86             }
87 1         33 }
88              
89             sub bind {
90 0     0 1   my $self = shift;
91 0 0         if (substr($_[0],0,1) =~ /\w/) {
92 0           $self->bind_local_class_to_remote(@_);
93             }
94             else {
95 0           $self->bind_local_var_to_remote(@_);
96             }
97             }
98              
99              
100             =pod
101              
102             =head1 NAME
103              
104             RMI::Client - connection to an RMI::Server
105              
106             =head1 VERSION
107              
108             This document describes RMI::Client v0.10.
109              
110             =head1 SYNOPSIS
111              
112             # simple
113             $c = RMI::Client::ForkedPipes->new();
114              
115             # typical
116             $c = RMI::Client::Tcp->new(host => 'server1', port => 1234);
117            
118             # roll-your-own...
119             $c = RMI::Client->new(reader => $fh1, writer => $fh2); # generic
120            
121             $c->call_use('IO::File');
122             $c->call_use('Sys::Hostname');
123              
124             $remote_obj = $c->call_class_method('IO::File','new','/tmp/myfile');
125             print $remote_obj->getline;
126             print <$remote_obj>;
127              
128             $host = $c->call_function('Sys::Hostname::hostname')
129             $host eq 'server1'; #!
130            
131             $remote_hashref = $c->call_eval('$main::h = { k1 => 111, k2 => 222, k3 => 333}');
132             $remote_hashref->{k4} = 444;
133             print sort keys %$remote_hashref;
134             print $c->call_eval('sort keys %$main::h'); # includes changes!
135              
136             $c->use_remote('Sys::Hostname'); # this whole package is on the other side
137             $host = Sys::Hostname::hostname(); # possibly not this hostname...
138              
139             our $c;
140             BEGIN {
141             $c = RMI::Client::Tcp->new(port => 1234);
142             $c->use_lib_remote;
143             }
144             use Some::Class; # remote!
145            
146             =head1 DESCRIPTION
147              
148             This is the base class for a standard RMI connection to an RMI::Server.
149              
150             In most cases, you will create a client of some subclass, typically
151             B for a network socket, or B
152             for a private out-of-process object server.
153              
154             =head1 METHODS
155            
156             =head2 call_use_lib($path);
157              
158             Calls "use lib '$path'" on the remote side.
159              
160             $c->call_use_lib('/some/path/on/the/server');
161              
162             =head2 call_use($class)
163              
164             Uses the Perl package specified on the remote side, making it available for later
165             calls to call_class_method() and call_function().
166              
167             $c->call_use('Some::Package');
168              
169             =head2 call_class_method($class, $method, @params)
170              
171             Does $class->$method(@params) on the remote side.
172              
173             Calling remote constructors is the primary way to make a remote object.
174              
175             $remote_obj = $client->call_class_method('Some::Class','new',@params);
176            
177             $possibly_another_remote_obj = $remote_obj->some_method(@p);
178            
179             =head2 call_function($fname, @params)
180              
181             A plain function call made by name to the remote side. The function name must be fully qualified.
182              
183             $c->call_use('Sys::Hostname');
184             my $server_hostname = $c->call_function('Sys::Hostname::hostname');
185              
186             =head2 call_sub($subname, @params)
187              
188             An alias for call_function();
189              
190             =head2 call_eval($src,@args)
191              
192             Calls eval $src on the remote side.
193              
194             Any additional arguments are set to @_ before eval on the remote side, after proxying.
195              
196             my $a = $c->call_eval('@main::x = (11,22,33); return \@main::x;'); # pass an arrayref back
197             push @$a, 44, 55; # changed on the server
198             scalar(@$a) == $c->call_eval('scalar(@main::x)'); # ...true!
199            
200             =head2 use_remote($class)
201              
202             Creases the effect of "use $class", but all calls of any kind for that
203             namespace are proxied through the client. This is the most transparent way to
204             get remote objects, since you can just call normal constructors and class methods
205             as though the module were local. It does means that ALL objects of the given
206             class must come from through this client.
207              
208             # NOTE: you probably shouldn't do this with IO::File unless you
209             # _really_ want all of its files to open on the server,
210             # while open() opens on the client...
211            
212             $c->use_remote('IO::File'); # never touches IO/File.pm on the client
213             $fh = IO::File->new('myfile'); # actually a remote call
214             print <$fh>; # printing rows from a remote file
215              
216             require IO::File; # does nothing, since we've already "used" IO::File
217            
218             The @ISA array is also bound to the remote @ISA, but all other variables
219             must be explicitly bound on the client to be accessible. This may be changed in a
220             future release.
221              
222             Exporting does work. To turn it off, use empty braces as you would empty parens.
223              
224             $c->use_remote('Sys::Hostname',[]);
225              
226             To get this effect (and prevent export of the hostame() function).
227              
228             use Sys::Hostname ();
229              
230             =head2 use_lib_remote($path)
231              
232             Installs a special handler into the local @INC which causes it to check the remote
233             side for a class. If available, it will do use_remote() on that class.
234              
235             use A;
236             use B;
237             BEGIN { $c->use_remote_lib; }; # do everything remotely from now on if possible...
238             use C; #remote!
239             use D; #remote!
240             use E; #local, b/c not found on the remote side
241              
242             =head2 bind($varname)
243              
244             Create a local transparent proxy for a package variable on the remote side.
245              
246             $c->bind('$Some::Package::somevar')
247             $Some::Package::somevar = 123; # changed remotely
248            
249             $c->bind('@main::foo');
250             push @main::foo, 11, 22 33; #changed remotely
251              
252             =head1 ADDITIONAL EXAMPLES
253              
254             =head2 create and use a remote hashref
255              
256             This makes a hashref on the server, and makes a proxy on the client:
257              
258             my $remote_hashref = $c->call_eval('{}');
259              
260             This seems to put a key in the hash, but actually sends a message to the server
261             to modify the hash.
262              
263             $remote_hashref->{key1} = 100;
264              
265             Lookups also result in a request to the server:
266              
267             print $remote_hashref->{key1};
268              
269             When we do this, the hashref on the server is destroyed, as since the ref-count
270             on both sides is now zero:
271              
272             $remote_hashref = undef;
273              
274             =head2 put remote objects from one server in a remote hash on another
275              
276             $c1 = RMI::Client::Tcp->new(host => 'host1', port => 1234);
277             $c2 = RMI::Client::Tcp->new(host => 'host2', port => 1234);
278             $c3 = RMI::Client::Tcp->new(host => 'host3', port => 1234);
279              
280             $o1 = $c1->call_class_method('IO::File','new','/etc/passwd');
281             $o2 = $c2->call_class_method('IO::File','new','/etc/passwd');
282              
283             $h = $c3->call_eval('{ handle1 => $_[0] }', $o1);
284              
285             $h->{handle2} = $o2;
286              
287             =head2 making a remote CODE ref, and using it with local and remote objects
288              
289             my $local_fh = IO::File->new('/etc/passwd');
290             my $remote_fh = $c->call_class_method('IO::File','new','/etc/passwd');
291             my $remote_coderef = $c->call_eval('
292             sub {
293             my $f1 = shift; my $f2 = shift;
294             my @lines = (<$f1>, <$f2>);
295             return scalar(@lines)
296             }
297             ');
298             my $total_line_count = $remote_coderef->($local_fh, $remote_fh);
299              
300             =head1 BUGS AND CAVEATS
301              
302             See general bugs in B for general system limitations
303              
304             =head1 SEE ALSO
305              
306             B, B, B, B
307              
308             B, B, B, B, B
309              
310             =head1 AUTHORS
311              
312             Scott Smith
313              
314             =head1 COPYRIGHT
315              
316             Copyright (c) 2008 - 2009 Scott Smith All rights reserved.
317              
318             =head1 LICENSE
319              
320             This program is free software; you can redistribute it and/or modify it under
321             the same terms as Perl itself.
322              
323             The full text of the license can be found in the LICENSE file included with this
324             module.
325              
326              
327             =cut
328              
329             1;
330