Permalink
Browse files

Add ruby dispatch support to the agent

  • Loading branch information...
1 parent 31deab3 commit 3f2cf0a296bdc310676ea8ff49eca046c450d759 Evan Phoenix committed Mar 9, 2011
Showing with 208 additions and 25 deletions.
  1. +1 −0 kernel/delta/load_order.txt
  2. +9 −0 kernel/loader.rb
  3. +37 −0 lib/bin/console.rb
  4. +1 −0 lib/rubinius/agent.rb
  5. +94 −2 vm/agent.cpp
  6. +22 −0 vm/agent.hpp
  7. +31 −20 vm/agent_components.cpp
  8. +2 −2 vm/agent_components.hpp
  9. +3 −1 vm/capi/thread.cpp
  10. +8 −0 vm/util/bert.hpp
@@ -1,3 +1,4 @@
+agent.rbc
ctype.rbc
class.rbc
exception.rbc
View
@@ -520,6 +520,14 @@ def debugger
end
end
+ def agent
+ @stage = "starting agent ruby thread"
+
+ if Rubinius::Config['agent.start']
+ Rubinius::AgentRegistry.spawn_thread
+ end
+ end
+
# Require any -r arguments
def requires
@stage = "requiring command line files"
@@ -696,6 +704,7 @@ def main
options
load_paths
debugger
+ agent
requires
evals
script
View
@@ -79,6 +79,11 @@ def quit
end
def set_config(args)
+ unless args
+ puts "Error: Specify a variable to access"
+ return
+ end
+
var, val = args.split(/\s+/, 2)
response = @agent.request :set_config, var, val
@@ -90,10 +95,17 @@ def set_config(args)
puts "Unknown var '#{var}'."
when :error
puts "Error setting variable."
+ else
+ p response
end
end
def get_config(args)
+ unless args
+ puts "Error: Specify a variable to access"
+ return
+ end
+
var = args.strip
begin
@@ -224,6 +236,26 @@ def self.find_all
Agent.new(pid.to_i, port.to_i, cmd.strip, exec.strip)
end
end
+
+ def self.cleanup
+ unless dir = ENV['TMPDIR']
+ dir = "/tmp"
+ return [] unless File.directory?(dir) and File.readable?(dir)
+ end
+
+ agents = Dir["#{dir}/rubinius-agent.*"]
+
+ return [] unless agents
+
+ agents.map do |path|
+ pid, port, cmd, exec = File.readlines(path)
+ `kill -0 #{pid}`
+ if $?.exitstatus != 0
+ puts "Removing #{path}"
+ File.unlink path
+ end
+ end
+ end
end
end
@@ -239,6 +271,11 @@ def self.find_all
exit 0
end
+ o.on "-c", "--cleanup", "Test and cleanup agent id files" do
+ Console::Agent.cleanup
+ exit 0
+ end
+
o.on "-v", "--vm NUM" do |val|
options.vm = val.to_i
end
@@ -9,6 +9,7 @@ def self.connect(host, port)
end
def self.loopback
+ Rubinius::AgentRegistry.spawn_thread
new Rubinius.agent_io
end
View
@@ -21,6 +21,7 @@
#include "environment.hpp"
#include "builtin/nativemethod.hpp"
+#include "builtin/io.hpp"
#include <ostream>
#include <sstream>
@@ -56,6 +57,29 @@ namespace rubinius {
loopback_[0] = -1;
loopback_[1] = -1;
+
+ if(pipe(a2r_) != 0) {
+ perror("pipe");
+ rubinius::abort();
+ }
+
+ if(pipe(r2a_) != 0) {
+ perror("pipe");
+ rubinius::abort();
+ }
+
+ add_fd(r2a_agent());
+
+ // This class is always created with the GIL locked, so it's ok
+ // to access ruby stuff here.
+ IO* from = IO::create(state_, a2r_ruby());
+ from->sync(state, Qtrue);
+
+ IO* to = IO::create(state_, r2a_ruby());
+ to->sync(state, Qtrue);
+
+ shared_.globals.rubinius.get()->set_const(state_, "FROM_AGENT", from);
+ shared_.globals.rubinius.get()->set_const(state_, "TO_AGENT", to);
}
bool QueryAgent::setup_local() {
@@ -119,6 +143,68 @@ namespace rubinius {
return true;
}
+ namespace {
+ bool get_ruby(QueryAgent* agent, int client, const char* k) {
+ bert::IOWriter writer(agent->a2r_agent());
+ bert::Encoder<bert::IOWriter> e(writer);
+
+ e.write_tuple(3);
+ e.write_integer(client);
+ e.write_atom("get");
+ e.write_binary(k);
+
+ return true;
+ }
+
+ bool set_ruby(QueryAgent* agent, int client, const char* k,
+ bert::Value* val)
+ {
+ bert::IOWriter writer(agent->a2r_agent());
+ bert::Encoder<bert::IOWriter> e(writer);
+
+ e.write_tuple(4);
+ e.write_integer(client);
+ e.write_atom("set");
+ e.write_binary(k);
+ e.write_value(val);
+
+ return true;
+ }
+
+ void respond_from_ruby(QueryAgent* agent) {
+ bert::IOReader reader(agent->r2a_agent());
+ bert::Decoder<bert::IOReader> d(reader);
+
+ bert::Value* val = d.next_value();
+
+ if(val->type() == bert::Tuple && val->total_elements() == 3) {
+ bert::Value* who = val->get_element(0);
+ bert::Value* code = val->get_element(1);
+
+ if(code->type() == bert::Atom && who->integer_p()) {
+ int client = who->integer();
+
+ bert::IOWriter writer(client);
+ bert::Encoder<bert::IOWriter> e(writer);
+
+ if(code->equal_atom("ok")) {
+ e.write_tuple(3);
+ e.write_atom("ok");
+ e.write_atom("value");
+ e.write_value(val->get_element(2));
+ } else {
+ e.write_tuple(2);
+ e.write_value(code);
+ e.write_value(val->get_element(2));
+ }
+ }
+ }
+
+ delete val;
+ }
+ }
+
+
bool QueryAgent::process_commands(int client) {
bert::IOReader reader(client);
bert::Decoder<bert::IOReader> decoder(reader);
@@ -148,7 +234,9 @@ namespace rubinius {
if(key->type() == bert::Binary) {
agent::Output output(writer);
- vars_->set_path(output, key->string(), value);
+ if(!vars_->set_path(output, key->string(), value)) {
+ set_ruby(this, client, key->string(), value);
+ }
delete val;
return true;
}
@@ -163,7 +251,9 @@ namespace rubinius {
if(key->type() == bert::Binary) {
agent::Output output(writer);
- vars_->read_path(output, key->string());
+ if(!vars_->read_path(output, key->string())) {
+ get_ruby(this, client, key->string());
+ }
delete val;
return true;
@@ -244,6 +334,8 @@ namespace rubinius {
if(read(read_control(), &buf, 1) < 0) {
std::cerr << "[QA: Read error: " << strerror(errno) << "]\n";
}
+ } else if(FD_ISSET(r2a_agent(), &read_fds)) {
+ respond_from_ruby(this);
} else if(server_fd_ > 0 && FD_ISSET(server_fd_, &read_fds)) {
// now accept an incoming connection
struct sockaddr_in sin;
View
@@ -8,8 +8,11 @@ namespace rubinius {
namespace agent {
class VariableAccess;
+ class Output;
}
+ class Thread;
+
class QueryAgent : public thread::Thread {
SharedState& shared_;
VM* state_;
@@ -24,6 +27,9 @@ namespace rubinius {
int control_[2];
int loopback_[2];
+ int a2r_[2];
+ int r2a_[2];
+
std::vector<int> sockets_;
agent::VariableAccess* vars_;
@@ -66,6 +72,22 @@ namespace rubinius {
return control_[1];
}
+ int a2r_agent() {
+ return a2r_[1];
+ }
+
+ int a2r_ruby() {
+ return a2r_[0];
+ }
+
+ int r2a_agent() {
+ return r2a_[0];
+ }
+
+ int r2a_ruby() {
+ return r2a_[1];
+ }
+
void wakeup();
bool setup_local();
Oops, something went wrong.

0 comments on commit 3f2cf0a

Please sign in to comment.