Acme-RPC
view release on metacpan or search on metacpan
lib/Acme/RPC.pm view on Meta::CPAN
* Should switch to our own recurse logic from Data::Dumper to support these other things.
* action=dump on anything; in the case of a coderef, find its source on disc or else deparse it
* action=call on coderefs and blessed objects, with an args parameter, or arg1, arg2, arg3, etc, and a method parameter for blessed objs.
* json will croak if a reference contains objects in side it somewhere. Should handle this gracefully.
* Offer JSON output! Not just Data::Dumper. Do this for action=dump, action=call, and the default tree view.
* If Devel::Leak won't give us refs... have to do an Acme::State style crawl from main::,
but crawling into each sub and looking at its lexicals with PadWalker.
Could make for a nice tree view.
Would also make it easy to filter out the variables that hold refs.
* Maybe this should be called Acme::RPC.
* Actually crawl into code refs when recursing the output!
* Devel pointer is too much work also. Maybe we should just cache $tree and then
walk it again when passed an oid. *sigh* Magic isn't working for me today.
Bleah.
EOF
# our $lt;
our $continuity; # don't lose this reference
our @keepalive; # stuff instances of objects created over RPC in there so they don't get garbage collected before the other end can use them
our $tree; # cached tree
our %registry; # oid=>objectrefs
sub import {
Devel::Trace::trace('off') if exists $INC{'Devel/Trace.pm'};
$continuity = Continuity->new(port => 7777, callback => sub {
my $request = shift;
while(1) {
$SIG{PIPE} = 'IGNORE';
my $action = $request->param('action') || 'dump';
my $output = $request->param('output');
my $ob;
$tree = tree('main::') unless $tree and $request->param('lazy');
#
# if they're referencing a specific object, find it
#
if($request->param('oid')) {
my $oid = $request->param('oid');
$ob = $registry{$oid};
$ob or do { $request->print("no object with that oid"); next; };
} elsif($request->param('path')) {
my @path = split m{/}, $request->param('path');
my $node = $tree;
while(@path) {
my $step = shift @path;
$node = $node->{$step} or do {
$step =~ s{[^a-z0-9:_-]}{}g;
$request->print("step ``$step'' not found in path");
$node = undef;
last;
};
}
$node or next;
$ob = $node->{chr(0)} or do {
$request->print("tried to look up a path that has no object associated");
};
}
#
# default view -- index of everything, up to a certain point
#
if( ! $ob ) {
my $htmlout = sub {
my $node = shift;
no strict 'refs';
# each node now possibily contains named refs to other nodes (recurse into those),
# and a possible single chr(0), a ref to something in the running program.
$request->print("<ul>\n");
for my $k (sort { $a cmp $b } keys %$node) {
next if $k eq chr(0); # doesn't exist in root node and our calling instance needs to have handled it otherwise
next if $k eq chr(1);
if(exists $node->{$k}{chr(0)}) {
my $addy = 0+($node->{$k}{chr(0)});
my $comment = $node->{$k}{chr(1)} || '';
$request->print(qq{<li><a href="?oid=$addy">$k</a> $comment</li>\n});
} else {
$request->print(qq{<li>$k</li>\n});
}
caller_cv(0)->($node->{$k}); # caller_cv(0)->($node->{$k});
}
$request->print("</ul>\n");
};
my $jsonout = sub {
my $node = shift;
my $outnode = { };
no strict 'refs';
for my $k (sort { $a cmp $b } keys %$node) {
next if $k eq chr(0) or $k eq chr(1);
$outnode->{$k} = caller_cv(0)->($node->{$k});
if(exists $node->{$k}{chr(0)}) {
my $addy = 0+($node->{$k}{chr(0)});
$outnode->{$k}{oid} = $addy;
}
}
return $outnode;
};
# XXX json support here too... feed to_json a pruned $tree?
# if($output and $output eq 'json')
( run in 0.617 second using v1.01-cache-2.11-cpan-71847e10f99 )