ernie 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,8 @@
1
+ = 1.1.0 / 2009-10-28
2
+ * Major changes
3
+ * Remove dependency on Erlectricity
4
+ * Simplify processing loop
5
+
1
6
  = 1.0.0 / 2009-10-19
2
7
  * No Changes. Production ready!
3
8
 
data/Rakefile CHANGED
@@ -11,8 +11,7 @@ begin
11
11
  gem.authors = ["Tom Preston-Werner"]
12
12
  gem.files.include(["ext"])
13
13
  gem.extensions << 'ext/extconf.rb'
14
- gem.add_dependency('erlectricity', '>= 1.1.0')
15
- gem.add_dependency('bert', '>= 1.0.0')
14
+ gem.add_dependency('bert', '>= 1.1.0')
16
15
  gem.add_dependency('bertrpc', '>= 1.0.0')
17
16
 
18
17
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
+ :minor: 1
2
3
  :patch: 0
3
4
  :major: 1
4
- :minor: 0
data/ernie.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ernie}
8
- s.version = "1.0.0"
8
+ s.version = "1.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tom Preston-Werner"]
12
- s.date = %q{2009-10-19}
12
+ s.date = %q{2009-10-28}
13
13
  s.default_executable = %q{ernie}
14
14
  s.email = %q{tom@mojombo.com}
15
15
  s.executables = ["ernie"]
@@ -66,17 +66,14 @@ Gem::Specification.new do |s|
66
66
  s.specification_version = 3
67
67
 
68
68
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
69
- s.add_runtime_dependency(%q<erlectricity>, [">= 1.1.0"])
70
- s.add_runtime_dependency(%q<bert>, [">= 1.0.0"])
69
+ s.add_runtime_dependency(%q<bert>, [">= 1.1.0"])
71
70
  s.add_runtime_dependency(%q<bertrpc>, [">= 1.0.0"])
72
71
  else
73
- s.add_dependency(%q<erlectricity>, [">= 1.1.0"])
74
- s.add_dependency(%q<bert>, [">= 1.0.0"])
72
+ s.add_dependency(%q<bert>, [">= 1.1.0"])
75
73
  s.add_dependency(%q<bertrpc>, [">= 1.0.0"])
76
74
  end
77
75
  else
78
- s.add_dependency(%q<erlectricity>, [">= 1.1.0"])
79
- s.add_dependency(%q<bert>, [">= 1.0.0"])
76
+ s.add_dependency(%q<bert>, [">= 1.1.0"])
80
77
  s.add_dependency(%q<bertrpc>, [">= 1.0.0"])
81
78
  end
82
79
  end
data/examples/calc.rb CHANGED
@@ -14,6 +14,10 @@ mod(:slowcalc) do
14
14
  sleep(rand * 2)
15
15
  a + b
16
16
  end
17
+
18
+ fun(:superslow) do
19
+ sleep 10
20
+ end
17
21
  end
18
22
 
19
23
  # Throw an error
data/lib/ernie.rb CHANGED
@@ -11,6 +11,11 @@ class Ernie
11
11
  self.current_mod = nil
12
12
  self.logger = nil
13
13
 
14
+ # Record a module.
15
+ # +name+ is the module Symbol
16
+ # +block+ is the Block containing function definitions
17
+ #
18
+ # Returns nothing
14
19
  def self.mod(name, block)
15
20
  m = Mod.new(name)
16
21
  self.current_mod = m
@@ -18,69 +23,129 @@ class Ernie
18
23
  block.call
19
24
  end
20
25
 
26
+ # Record a function.
27
+ # +name+ is the function Symbol
28
+ # +block+ is the Block to associate
29
+ #
30
+ # Returns nothing
21
31
  def self.fun(name, block)
22
32
  self.current_mod.fun(name, block)
23
33
  end
24
34
 
35
+ # Set the logfile to given path.
36
+ # +file+ is the String path to the logfile
37
+ #
38
+ # Returns nothing
25
39
  def self.logfile(file)
26
40
  self.logger = Logger.new(file)
27
41
  end
28
42
 
43
+ # If logging is enabled, log the given text.
44
+ # +text+ is the String to log
45
+ #
46
+ # Returns nothing
29
47
  def self.log(text)
30
48
  self.logger.info(text) if self.logger
31
49
  end
32
50
 
51
+ # Dispatch the request to the proper mod:fun.
52
+ # +mod+ is the module Symbol
53
+ # +fun+ is the function Symbol
54
+ # +args+ is the Array of arguments
55
+ #
56
+ # Returns the Ruby object response
33
57
  def self.dispatch(mod, fun, args)
34
- xargs = BERT::Decoder.convert(args)
35
- self.log("-- " + [mod, fun, xargs].inspect)
36
58
  self.mods[mod] || raise(ServerError.new("No such module '#{mod}'"))
37
59
  self.mods[mod].funs[fun] || raise(ServerError.new("No such function '#{mod}:#{fun}'"))
38
- res = self.mods[mod].funs[fun].call(*xargs)
39
- BERT::Encoder.convert(res)
60
+ self.mods[mod].funs[fun].call(*args)
40
61
  end
41
62
 
63
+ # Read the length header from the wire.
64
+ # +input+ is the IO from which to read
65
+ #
66
+ # Returns the size Integer if one was read
67
+ # Returns nil otherwise
68
+ def self.read_4(input)
69
+ raw = input.read(4)
70
+ return nil unless raw
71
+ raw.unpack('N').first
72
+ end
73
+
74
+ # Read a BERP from the wire and decode it to a Ruby object.
75
+ # +input+ is the IO from which to read
76
+ #
77
+ # Returns a Ruby object if one could be read
78
+ # Returns nil otherwise
79
+ def self.read_berp(input)
80
+ packet_size = self.read_4(input)
81
+ return nil unless packet_size
82
+ bert = input.read(packet_size)
83
+ BERT.decode(bert)
84
+ end
85
+
86
+ # Write the given Ruby object to the wire as a BERP.
87
+ # +output+ is the IO on which to write
88
+ # +ruby+ is the Ruby object to encode
89
+ #
90
+ # Returns nothing
91
+ def self.write_berp(output, ruby)
92
+ data = BERT.encode(ruby)
93
+ output.write([data.length].pack("N"))
94
+ output.write(data)
95
+ end
96
+
97
+ # Start the processing loop.
98
+ #
99
+ # Loops forever
42
100
  def self.start
43
101
  self.log("Starting")
44
102
  self.log(self.mods.inspect)
45
- receive do |f|
46
- f.when([:call, Symbol, Symbol, Array]) do |mod, fun, args|
47
- self.log("-> " + [:call, mod, fun, args].inspect)
103
+
104
+ input = IO.new(3)
105
+ output = IO.new(4)
106
+ input.sync = true
107
+ output.sync = true
108
+
109
+ loop do
110
+ iruby = self.read_berp(input)
111
+ unless iruby
112
+ puts "Could not read BERP length header. Ernie server may have gone away. Exiting now."
113
+ exit!
114
+ end
115
+
116
+ if iruby.size == 4 && iruby[0] == :call
117
+ mod, fun, args = iruby[1..3]
118
+ self.log("-> " + iruby.inspect)
48
119
  begin
49
120
  res = self.dispatch(mod, fun, args)
50
- xres = [:reply, res]
51
- self.log("<- " + xres.inspect)
52
- f.send!(xres)
121
+ oruby = t[:reply, res]
122
+ self.log("<- " + oruby.inspect)
123
+ write_berp(output, oruby)
53
124
  rescue ServerError => e
54
- xres = [:error, [:server, 0, e.class.to_s, e.message, e.backtrace]]
55
- self.log("<- " + xres.inspect)
125
+ oruby = t[:error, t[:server, 0, e.class.to_s, e.message, e.backtrace]]
126
+ self.log("<- " + oruby.inspect)
56
127
  self.log(e.backtrace.join("\n"))
57
- f.send!(xres)
128
+ write_berp(output, oruby)
58
129
  rescue Object => e
59
- xres = [:error, [:user, 0, e.class.to_s, e.message, e.backtrace]]
60
- self.log("<- " + xres.inspect)
130
+ oruby = t[:error, t[:user, 0, e.class.to_s, e.message, e.backtrace]]
131
+ self.log("<- " + oruby.inspect)
61
132
  self.log(e.backtrace.join("\n"))
62
- f.send!(xres)
133
+ write_berp(output, oruby)
63
134
  end
64
- f.receive_loop
65
- end
66
-
67
- f.when([:cast, Symbol, Symbol, Array]) do |mod, fun, args|
135
+ elsif iruby.size == 4 && iruby[0] == :cast
136
+ mod, fun, args = iruby[1..3]
68
137
  self.log("-> " + [:cast, mod, fun, args].inspect)
69
138
  begin
70
139
  self.dispatch(mod, fun, args)
71
140
  rescue Object => e
72
141
  # ignore
73
142
  end
74
- f.send!([:noreply])
75
- f.receive_loop
76
- end
77
-
78
- f.when(Any) do |any|
79
- self.log("-> " + any.inspect)
80
- xres = [:error, [:server, 0, "Invalid request: #{any.inspect}"]]
81
- self.log("<- " + xres.inspect)
82
- f.send!(xres)
83
- f.receive_loop
143
+ write_berp(output, t[:noreply])
144
+ else
145
+ self.log("-> " + iruby.inspect)
146
+ oruby = t[:error, t[:server, 0, "Invalid request: #{iruby.inspect}"]]
147
+ self.log("<- " + oruby.inspect)
148
+ write_berp(output, oruby)
84
149
  end
85
150
  end
86
151
  end
@@ -37,6 +37,10 @@ class ErnieServerTest < Test::Unit::TestCase
37
37
  assert_equal 10, @svc.call.test.ternary(5, 2, 3)
38
38
  end
39
39
 
40
+ should "handle massive binaries" do
41
+ assert_equal 8 * 1024 * 1024, @svc.call.test.big(8 * 1024 * 1024).size
42
+ end
43
+
40
44
  should "get an error on missing module" do
41
45
  begin
42
46
  @svc.call.failboat.mcfail(:fail)
data/test/handler.rb CHANGED
@@ -31,6 +31,10 @@ mod(:test) do
31
31
  state
32
32
  end
33
33
 
34
+ fun(:big) do |x|
35
+ 'a' * x
36
+ end
37
+
34
38
  fun(:cry) do
35
39
  raise "abandon hope!"
36
40
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ernie
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Preston-Werner
@@ -9,19 +9,9 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-19 00:00:00 -07:00
12
+ date: 2009-10-28 00:00:00 -07:00
13
13
  default_executable: ernie
14
14
  dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: erlectricity
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 1.1.0
24
- version:
25
15
  - !ruby/object:Gem::Dependency
26
16
  name: bert
27
17
  type: :runtime
@@ -30,7 +20,7 @@ dependencies:
30
20
  requirements:
31
21
  - - ">="
32
22
  - !ruby/object:Gem::Version
33
- version: 1.0.0
23
+ version: 1.1.0
34
24
  version:
35
25
  - !ruby/object:Gem::Dependency
36
26
  name: bertrpc