tiamat 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.rdoc +7 -0
- data/MANIFEST +42 -0
- data/README.rdoc +194 -0
- data/Rakefile +19 -0
- data/bin/tiamat-server +31 -0
- data/devel/jumpstart.rb +987 -0
- data/install.rb +2 -0
- data/lib/tiamat.rb +43 -0
- data/lib/tiamat/autoconfig.rb +8 -0
- data/lib/tiamat/child_server.rb +21 -0
- data/lib/tiamat/config/ruby_parser.rb +6 -0
- data/lib/tiamat/connector.rb +23 -0
- data/lib/tiamat/error.rb +24 -0
- data/lib/tiamat/farm.rb +32 -0
- data/lib/tiamat/local_child_farm.rb +23 -0
- data/lib/tiamat/local_child_server.rb +25 -0
- data/lib/tiamat/local_child_worker.rb +11 -0
- data/lib/tiamat/remote_farm.rb +11 -0
- data/lib/tiamat/remote_worker.rb +10 -0
- data/lib/tiamat/server.rb +42 -0
- data/lib/tiamat/tiamat.rb +49 -0
- data/lib/tiamat/tiamat_server.rb +48 -0
- data/lib/tiamat/util.rb +37 -0
- data/lib/tiamat/version.rb +4 -0
- data/lib/tiamat/worker.rb +61 -0
- data/spec/connector_spec.rb +11 -0
- data/spec/drb_connection_spec.rb +18 -0
- data/spec/local_child_farm_spec.rb +29 -0
- data/spec/local_child_server_path_spec.rb +37 -0
- data/spec/local_child_server_spec.rb +24 -0
- data/spec/local_child_worker_spec.rb +140 -0
- data/spec/pure_spec.rb +59 -0
- data/spec/readme_spec.rb +29 -0
- data/spec/remote_farm_spec.rb +36 -0
- data/spec/remote_worker_spec.rb +59 -0
- data/spec/server_spec.rb +48 -0
- data/spec/tiamat_open_local_spec.rb +77 -0
- data/spec/tiamat_open_remote_spec.rb +67 -0
- data/spec/tiamat_server_spec.rb +51 -0
- data/spec/tiamat_spec_base.rb +36 -0
- data/spec/util_spec.rb +29 -0
- data/spec/worker_spec.rb +19 -0
- metadata +209 -0
data/install.rb
ADDED
data/lib/tiamat.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009 James M. Lawrence. All rights reserved.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person
|
5
|
+
# obtaining a copy of this software and associated documentation files
|
6
|
+
# (the "Software"), to deal in the Software without restriction,
|
7
|
+
# including without limitation the rights to use, copy, modify, merge,
|
8
|
+
# publish, distribute, sublicense, and/or sell copies of the Software,
|
9
|
+
# and to permit persons to whom the Software is furnished to do so,
|
10
|
+
# subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
19
|
+
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
20
|
+
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
21
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
#
|
24
|
+
|
25
|
+
require 'rbconfig'
|
26
|
+
require 'drb'
|
27
|
+
|
28
|
+
require 'pure'
|
29
|
+
|
30
|
+
require 'tiamat/error'
|
31
|
+
require 'tiamat/version'
|
32
|
+
require 'tiamat/util'
|
33
|
+
require 'tiamat/connector'
|
34
|
+
require 'tiamat/server'
|
35
|
+
require 'tiamat/farm'
|
36
|
+
require 'tiamat/worker'
|
37
|
+
require 'tiamat/remote_farm'
|
38
|
+
require 'tiamat/remote_worker'
|
39
|
+
require 'tiamat/child_server'
|
40
|
+
require 'tiamat/local_child_server'
|
41
|
+
require 'tiamat/local_child_farm'
|
42
|
+
require 'tiamat/local_child_worker'
|
43
|
+
require 'tiamat/tiamat'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
module Tiamat
|
3
|
+
class ChildServer < Server
|
4
|
+
def initialize(uri, *args)
|
5
|
+
@thread = Thread.new {
|
6
|
+
launch(uri, *args)
|
7
|
+
}
|
8
|
+
super(uri)
|
9
|
+
end
|
10
|
+
|
11
|
+
def close
|
12
|
+
begin
|
13
|
+
@drb_object.close
|
14
|
+
rescue DRb::DRbConnError
|
15
|
+
nil # rcov workaround
|
16
|
+
end
|
17
|
+
super
|
18
|
+
@thread.join
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module Tiamat
|
3
|
+
module Connector
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def connect(wait_interval, timeout)
|
7
|
+
begin
|
8
|
+
yield
|
9
|
+
rescue DRb::DRbConnError
|
10
|
+
start = Time.now
|
11
|
+
begin
|
12
|
+
Kernel.sleep(wait_interval)
|
13
|
+
yield
|
14
|
+
rescue DRb::DRbConnError
|
15
|
+
if Time.now - start > timeout
|
16
|
+
raise
|
17
|
+
end
|
18
|
+
retry
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/tiamat/error.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
module Tiamat
|
3
|
+
class Error < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
class AlreadyOpenError < Error
|
7
|
+
def initialize(object)
|
8
|
+
@object = object
|
9
|
+
super("open called on object which is already open: #{@object.inspect}")
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :object
|
13
|
+
end
|
14
|
+
|
15
|
+
class RunRubyError < Error
|
16
|
+
def initialize(command, status)
|
17
|
+
@command, @status = command, status
|
18
|
+
command_str = command.map { |a| "'#{a}'" }.join(", ")
|
19
|
+
super("system(#{command_str}) failed with status #{@status}")
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :command, :status
|
23
|
+
end
|
24
|
+
end
|
data/lib/tiamat/farm.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
module Tiamat
|
3
|
+
class Farm
|
4
|
+
def initialize(servers)
|
5
|
+
@servers = servers
|
6
|
+
@available = Queue.new
|
7
|
+
|
8
|
+
@servers.each { |server|
|
9
|
+
@available.push(server)
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def num_servers
|
14
|
+
@servers.size
|
15
|
+
end
|
16
|
+
|
17
|
+
def lend_server
|
18
|
+
server = @available.pop
|
19
|
+
begin
|
20
|
+
yield server
|
21
|
+
ensure
|
22
|
+
@available.push(server)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def close
|
27
|
+
@servers.each { |server|
|
28
|
+
server.close
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module Tiamat
|
3
|
+
class LocalChildFarm < Farm
|
4
|
+
def initialize(num_servers, *args)
|
5
|
+
base_uri = self.class.base_uri
|
6
|
+
port_begin = self.class.port_begin
|
7
|
+
servers = (0...num_servers).map { |n|
|
8
|
+
LocalChildServer.new("#{base_uri}:#{port_begin + n}", *args)
|
9
|
+
}
|
10
|
+
super(servers)
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def base_uri
|
15
|
+
"druby://localhost"
|
16
|
+
end
|
17
|
+
|
18
|
+
def port_begin
|
19
|
+
48727
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
module Tiamat
|
3
|
+
class LocalChildServer < ChildServer
|
4
|
+
def launch(uri, compiler_name, *requires)
|
5
|
+
args = [compiler_name] + requires
|
6
|
+
Util.run_ruby(self.class.server_path, uri, *args)
|
7
|
+
end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def server_basename
|
11
|
+
"tiamat-server"
|
12
|
+
end
|
13
|
+
|
14
|
+
def server_path
|
15
|
+
if server = Util.find_executable(server_basename)
|
16
|
+
server
|
17
|
+
else
|
18
|
+
File.expand_path(
|
19
|
+
File.dirname(__FILE__) + "/../../bin/" + server_basename
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
module Tiamat
|
3
|
+
class Server
|
4
|
+
include Connector
|
5
|
+
|
6
|
+
def initialize(uri)
|
7
|
+
@uri = uri
|
8
|
+
@drb_object = DRbObject.new_with_uri(uri)
|
9
|
+
connect {
|
10
|
+
@drb_object.ping
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :uri
|
15
|
+
|
16
|
+
def close
|
17
|
+
end
|
18
|
+
|
19
|
+
def evaluate_function(*args)
|
20
|
+
@drb_object.evaluate_function(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def connect(&block)
|
26
|
+
super(self.class.wait_interval, self.class.timeout, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
attr_writer :wait_interval
|
31
|
+
attr_writer :timeout
|
32
|
+
|
33
|
+
def wait_interval
|
34
|
+
@wait_interval ||= 0.02
|
35
|
+
end
|
36
|
+
|
37
|
+
def timeout
|
38
|
+
@timeout ||= 3
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
module Tiamat
|
3
|
+
class << self
|
4
|
+
#
|
5
|
+
# Launch _num_parallel_ local Ruby interpreters.
|
6
|
+
#
|
7
|
+
# If a block is given:
|
8
|
+
# * Pure.worker is replaced for the duration of the block.
|
9
|
+
# * The return value is the block result.
|
10
|
+
# * The interpreters are stopped when the block finishes.
|
11
|
+
#
|
12
|
+
# If no block is given, an opened worker is returned. You are
|
13
|
+
# responsible for closing it.
|
14
|
+
#
|
15
|
+
def open_local(num_parallel, *requires, &block)
|
16
|
+
args = [num_parallel] + Tiamat.compiler.reverse + requires
|
17
|
+
open_worker(LocalChildWorker, *args, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Connect to the already-running tiamat servers given by the URIs,
|
22
|
+
# e.g. druby://192.168.4.1:27272.
|
23
|
+
#
|
24
|
+
# If a block is given:
|
25
|
+
# * Pure.worker is replaced for the duration of the block.
|
26
|
+
# * The return value is the block result.
|
27
|
+
#
|
28
|
+
# If no block is given, an opened worker is returned. You are
|
29
|
+
# responsible for closing it.
|
30
|
+
#
|
31
|
+
def open_remote(*uris, &block)
|
32
|
+
open_worker(RemoteWorker, *uris, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_accessor :compiler
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def open_worker(worker, *args, &block)
|
40
|
+
result = worker.open(*args, &block)
|
41
|
+
if block
|
42
|
+
result
|
43
|
+
else
|
44
|
+
worker
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
@compiler = nil
|
49
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#
|
2
|
+
# This is the core of bin/tiamat-server, the code which runs on the
|
3
|
+
# remote Ruby interpreter.
|
4
|
+
#
|
5
|
+
# This file is not required by the top-level tiamat.rb.
|
6
|
+
#
|
7
|
+
|
8
|
+
module Tiamat
|
9
|
+
class TiamatServer
|
10
|
+
FINISH = Queue.new
|
11
|
+
|
12
|
+
def initialize(compiler_name, *requires)
|
13
|
+
@compiler_name = compiler_name
|
14
|
+
|
15
|
+
requires.each { |path| require path }
|
16
|
+
|
17
|
+
@compiler = compiler_name.split("::").inject(Object) { |acc, name|
|
18
|
+
acc.const_get(name)
|
19
|
+
}.new
|
20
|
+
|
21
|
+
nil # rcov workaround
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :compiler_name
|
25
|
+
|
26
|
+
def evaluate_function(spec, *args)
|
27
|
+
@compiler.evaluate_function(spec, *args)
|
28
|
+
end
|
29
|
+
|
30
|
+
def ping
|
31
|
+
end
|
32
|
+
|
33
|
+
def close
|
34
|
+
FINISH.push nil
|
35
|
+
end
|
36
|
+
|
37
|
+
class << self
|
38
|
+
def run(uri, *args)
|
39
|
+
DRb.start_service(uri, new(*args))
|
40
|
+
begin
|
41
|
+
FINISH.pop
|
42
|
+
ensure
|
43
|
+
DRb.stop_service
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/tiamat/util.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
module Tiamat
|
3
|
+
module Util
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def ruby_executable
|
7
|
+
require 'rbconfig'
|
8
|
+
name = File.join(
|
9
|
+
Config::CONFIG["bindir"],
|
10
|
+
Config::CONFIG["RUBY_INSTALL_NAME"]
|
11
|
+
)
|
12
|
+
if Config::CONFIG["host"] =~ %r!(mswin|cygwin|mingw)! and
|
13
|
+
File.basename(name) !~ %r!\.(exe|com|bat|cmd)\Z!i
|
14
|
+
name + Config::CONFIG["EXEEXT"]
|
15
|
+
else
|
16
|
+
name
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def run_ruby(*args)
|
21
|
+
cmd = [ruby_executable, *args]
|
22
|
+
unless system(*cmd)
|
23
|
+
raise RunRubyError.new(cmd, $?.exitstatus)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def find_executable(basename)
|
28
|
+
ENV["PATH"].split(File::PATH_SEPARATOR).each { |path|
|
29
|
+
candidate = path + "/" + basename
|
30
|
+
if File.exist?(candidate)
|
31
|
+
return candidate
|
32
|
+
end
|
33
|
+
}
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|