ernie 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ = 2.5.0 / 2010-11-19
2
+ * Major Enhancements
3
+ * Enable multi-node mode (#11)
4
+ * Bug Fixes
5
+ * Properly determine whether function or module is missing.
6
+ * Spawn a process for receive_term to keep acceptor non-blocking.
7
+
1
8
  = 2.4.0 / 2010-05-21
2
9
  * Minor Additions
3
10
  * Add -E cli option for setting extra Erlang VM options
data/README.md CHANGED
@@ -59,6 +59,8 @@ Running
59
59
  -a, --access-log LOGFILE Access log file.
60
60
  -d, --detached Run as a daemon.
61
61
  -P, --pidfile PIDFILE Location to write pid file.
62
+ --name NAME Erlang process name.
63
+ --sname SNAME Erlang short process name.
62
64
  -E, --erlang ERLANG_OPTIONS Options passed to Erlang VM.
63
65
 
64
66
  Commands:
data/Rakefile CHANGED
@@ -1,67 +1,155 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
+ require 'date'
3
4
 
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "ernie"
8
- gem.rubyforge_project = "ernie"
9
- gem.summary = %Q{Ernie is a BERT-RPC server implementation.}
10
- gem.description = %Q{Ernie is an Erlang/Ruby hybrid BERT-RPC server implementation packaged as a gem.}
11
- gem.email = "tom@mojombo.com"
12
- gem.homepage = "http://github.com/mojombo/ernie"
13
- gem.authors = ["Tom Preston-Werner"]
14
- gem.files.include(["ext"])
15
- gem.extensions << 'ext/extconf.rb'
16
- gem.add_dependency('bert', '>= 1.1.0')
17
- gem.add_dependency('bertrpc', '>= 1.0.0')
18
-
19
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
- end
21
- rescue LoadError
22
- puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
5
+ #############################################################################
6
+ #
7
+ # Helper functions
8
+ #
9
+ #############################################################################
10
+
11
+ def name
12
+ @name ||= Dir['*.gemspec'].first.split('.').first
13
+ end
14
+
15
+ def version
16
+ line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
17
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
18
+ end
19
+
20
+ def date
21
+ Date.today.to_s
22
+ end
23
+
24
+ def rubyforge_project
25
+ name
26
+ end
27
+
28
+ def gemspec_file
29
+ "#{name}.gemspec"
23
30
  end
24
31
 
32
+ def gem_file
33
+ "#{name}-#{version}.gem"
34
+ end
35
+
36
+ def replace_header(head, header_name)
37
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
38
+ end
39
+
40
+ #############################################################################
41
+ #
42
+ # Standard tasks
43
+ #
44
+ #############################################################################
45
+
46
+ task :default => :test
47
+
25
48
  require 'rake/testtask'
26
49
  Rake::TestTask.new(:test) do |test|
27
50
  test.libs << 'lib' << 'test'
28
- test.pattern = 'test/**/*_test.rb'
51
+ test.pattern = 'test/**/test_*.rb'
29
52
  test.verbose = true
30
53
  end
31
54
 
32
- begin
33
- require 'rcov/rcovtask'
34
- Rcov::RcovTask.new do |test|
35
- test.libs << 'test'
36
- test.pattern = 'test/**/*_test.rb'
37
- test.verbose = true
38
- end
39
- rescue LoadError
40
- task :rcov do
41
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
42
- end
55
+ desc "Generate RCov test coverage and open in your browser"
56
+ task :coverage do
57
+ require 'rcov'
58
+ sh "rm -fr coverage"
59
+ sh "rcov test/test_*.rb"
60
+ sh "open coverage/index.html"
43
61
  end
44
62
 
45
- task :default => :test
63
+ require 'rake/rdoctask'
64
+ Rake::RDocTask.new do |rdoc|
65
+ rdoc.rdoc_dir = 'rdoc'
66
+ rdoc.title = "#{name} #{version}"
67
+ rdoc.rdoc_files.include('README*')
68
+ rdoc.rdoc_files.include('lib/**/*.rb')
69
+ end
70
+
71
+ desc "Open an irb session preloaded with this library"
72
+ task :console do
73
+ sh "irb -rubygems -r ./lib/#{name}.rb"
74
+ end
46
75
 
47
- # require 'rake/rdoctask'
48
- # Rake::RDocTask.new do |rdoc|
49
- # if File.exist?('VERSION.yml')
50
- # config = YAML.load(File.read('VERSION.yml'))
51
- # version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
52
- # else
53
- # version = ""
54
- # end
55
- #
56
- # rdoc.rdoc_dir = 'rdoc'
57
- # rdoc.title = "ernie #{version}"
58
- # rdoc.rdoc_files.include('README*')
59
- # rdoc.rdoc_files.include('lib/**/*.rb')
60
- # end
76
+ #############################################################################
77
+ #
78
+ # Custom tasks (add your own tasks here)
79
+ #
80
+ #############################################################################
61
81
 
62
82
  task :ebuild do
63
83
  ERLC_TEST_FLAGS = ""
64
84
  ERLC_FLAGS = "-o ../ebin"
65
85
  cd "elib"
66
86
  sh "erlc #{ERLC_FLAGS} #{ERLC_TEST_FLAGS} #{Dir["**/*.erl"].join(" ")}"
67
- end
87
+ end
88
+
89
+ #############################################################################
90
+ #
91
+ # Packaging tasks
92
+ #
93
+ #############################################################################
94
+
95
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
96
+ task :release => :build do
97
+ unless `git branch` =~ /^\* master$/
98
+ puts "You must be on the master branch to release!"
99
+ exit!
100
+ end
101
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
102
+ sh "git tag v#{version}"
103
+ sh "git push origin master"
104
+ sh "git push origin v#{version}"
105
+ sh "gem push pkg/#{name}-#{version}.gem"
106
+ end
107
+
108
+ desc "Build #{gem_file} into the pkg directory"
109
+ task :build => :gemspec do
110
+ sh "mkdir -p pkg"
111
+ sh "gem build #{gemspec_file}"
112
+ sh "mv #{gem_file} pkg"
113
+ end
114
+
115
+ desc "Generate #{gemspec_file}"
116
+ task :gemspec => :validate do
117
+ # read spec file and split out manifest section
118
+ spec = File.read(gemspec_file)
119
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
120
+
121
+ # replace name version and date
122
+ replace_header(head, :name)
123
+ replace_header(head, :version)
124
+ replace_header(head, :date)
125
+ #comment this out if your rubyforge_project has a different name
126
+ replace_header(head, :rubyforge_project)
127
+
128
+ # determine file list from git ls-files
129
+ files = `git ls-files`.
130
+ split("\n").
131
+ sort.
132
+ reject { |file| file =~ /^\./ }.
133
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
134
+ map { |file| " #{file}" }.
135
+ join("\n")
136
+
137
+ # piece file back together and write
138
+ manifest = " s.files = %w[\n#{files}\n ]\n"
139
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
140
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
141
+ puts "Updated #{gemspec_file}"
142
+ end
143
+
144
+ desc "Validate #{gemspec_file}"
145
+ task :validate do
146
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
147
+ unless libfiles.empty?
148
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
149
+ exit!
150
+ end
151
+ unless Dir['VERSION*'].empty?
152
+ puts "A `VERSION` file at root level violates Gem best practices."
153
+ exit!
154
+ end
155
+ end
data/bin/ernie CHANGED
@@ -14,14 +14,10 @@ def code_paths
14
14
  DEFAULT_ERLANG_CODEPATHS.map {|n| "-pz #{rel(n)}" }.join(" ") + " \\"
15
15
  end
16
16
 
17
- def version
18
- yml = YAML.load(File.read(File.join(File.dirname(__FILE__), *%w[.. VERSION.yml])))
19
- "#{yml[:major]}.#{yml[:minor]}.#{yml[:patch]}"
20
- end
21
-
22
17
  require 'optparse'
23
18
  require 'pp'
24
19
  require 'yaml'
20
+ require 'ernie'
25
21
 
26
22
  help = <<HELP
27
23
  Ernie is an Erlang/Ruby BERT-RPC Server.
@@ -42,7 +38,7 @@ HELP
42
38
  options = {}
43
39
  OptionParser.new do |opts|
44
40
  opts.banner = help
45
- opts.version = version
41
+ opts.version = Ernie::VERSION
46
42
 
47
43
  opts.on("-c CONFIG", "--config CONFIG", "Config file") do |x|
48
44
  options[:config] = x
@@ -64,6 +60,14 @@ OptionParser.new do |opts|
64
60
  options[:detached] = true
65
61
  end
66
62
 
63
+ opts.on("--name NAME", "Erlang proccess name") do |x|
64
+ options[:name] = x
65
+ end
66
+
67
+ opts.on("--sname NAME", "Erlang short proccess name") do |x|
68
+ options[:sname] = x
69
+ end
70
+
67
71
  opts.on("-P", "--pidfile PIDFILE", "Location to write pid file.") do |x|
68
72
  options[:pidfile] = x
69
73
  end
@@ -99,9 +103,13 @@ else
99
103
  pidfile = options[:pidfile] ? "-ernie_server_app pidfile \"'#{options[:pidfile]}'\"" : ''
100
104
  detached = options[:detached] ? '-detached' : ''
101
105
  access_log = options[:access_log] ? "-ernie_server_app access_log '\"#{options[:access_log]}\"'" : ''
106
+ name = options[:name] ? "-name #{options[:name]}" : ''
107
+ sname = options[:sname] ? "-sname #{options[:sname]}" : ''
102
108
  erl_options = options[:erl_options]
103
109
 
104
110
  cmd = %Q{erl -boot start_sasl \
111
+ #{name} \
112
+ #{sname} \
105
113
  #{detached} \
106
114
  +Bc \
107
115
  +K true \
@@ -115,5 +123,6 @@ else
115
123
  -run ernie_server_app boot \
116
124
  #{erl_options}}.squeeze(' ')
117
125
  puts cmd
126
+ STDOUT.flush
118
127
  exec(cmd)
119
128
  end
@@ -18,19 +18,19 @@
18
18
  %%====================================================================
19
19
 
20
20
  start_link(Args) ->
21
- gen_server:start_link({global, ?MODULE}, ?MODULE, Args, []).
21
+ gen_server:start_link({local, ?MODULE}, ?MODULE, Args, []).
22
22
 
23
23
  start(Args) ->
24
24
  gen_server:start({global, ?MODULE}, ?MODULE, Args, []).
25
25
 
26
26
  acc(Request) ->
27
- gen_server:cast({global, ?MODULE}, {acc, Request}).
27
+ gen_server:cast(?MODULE, {acc, Request}).
28
28
 
29
29
  err(Request, Msg, Args) ->
30
- gen_server:cast({global, ?MODULE}, {err, Request, Msg, Args}).
30
+ gen_server:cast(?MODULE, {err, Request, Msg, Args}).
31
31
 
32
32
  reopen() ->
33
- gen_server:cast({global, ?MODULE}, reopen).
33
+ gen_server:cast(?MODULE, reopen).
34
34
 
35
35
  %%====================================================================
36
36
  %% gen_server callbacks
@@ -3,7 +3,7 @@
3
3
  -include_lib("ernie.hrl").
4
4
 
5
5
  %% api
6
- -export([start_link/1, start/1, process/1, kick/0, fin/0]).
6
+ -export([start_link/1, start/1, process/1, enqueue_request/1, kick/0, fin/0]).
7
7
 
8
8
  %% gen_server callbacks
9
9
  -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -14,19 +14,22 @@
14
14
  %%====================================================================
15
15
 
16
16
  start_link(Args) ->
17
- gen_server:start_link({global, ?MODULE}, ?MODULE, Args, []).
17
+ gen_server:start_link({local, ?MODULE}, ?MODULE, Args, []).
18
18
 
19
19
  start(Args) ->
20
- gen_server:start({global, ?MODULE}, ?MODULE, Args, []).
20
+ gen_server:start({local, ?MODULE}, ?MODULE, Args, []).
21
21
 
22
22
  process(Sock) ->
23
- gen_server:cast({global, ?MODULE}, {process, Sock}).
23
+ gen_server:cast(?MODULE, {process, Sock}).
24
+
25
+ enqueue_request(Request) ->
26
+ gen_server:call(?MODULE, {enqueue_request, Request}).
24
27
 
25
28
  kick() ->
26
- gen_server:cast({global, ?MODULE}, kick).
29
+ gen_server:cast(?MODULE, kick).
27
30
 
28
31
  fin() ->
29
- gen_server:cast({global, ?MODULE}, fin).
32
+ gen_server:cast(?MODULE, fin).
30
33
 
31
34
  %%====================================================================
32
35
  %% gen_server callbacks
@@ -57,6 +60,16 @@ init([Port, Configs]) ->
57
60
  %% {stop, Reason, State}
58
61
  %% Description: Handling call messages
59
62
  %%--------------------------------------------------------------------
63
+ handle_call({enqueue_request, Request}, _From, State) ->
64
+ case Request#request.priority of
65
+ high ->
66
+ Hq2 = queue:in(Request, State#state.hq),
67
+ Lq2 = State#state.lq;
68
+ low ->
69
+ Hq2 = State#state.hq,
70
+ Lq2 = queue:in(Request, State#state.lq)
71
+ end,
72
+ {reply, ok, State#state{hq = Hq2, lq = Lq2}};
60
73
  handle_call(_Request, _From, State) ->
61
74
  {reply, ok, State}.
62
75
 
@@ -71,8 +84,9 @@ handle_cast({process, Sock}, State) ->
71
84
  lq = queue:len(State#state.lq),
72
85
  taccept = erlang:now()},
73
86
  Request = #request{sock = Sock, log = Log},
74
- State2 = receive_term(Request, State),
75
- {noreply, State2};
87
+ spawn(fun() -> receive_term(Request, State) end),
88
+ logger:debug("Spawned receiver~n", []),
89
+ {noreply, State};
76
90
  handle_cast(kick, State) ->
77
91
  case queue:out(State#state.hq) of
78
92
  {{value, Request}, Hq2} ->
@@ -175,20 +189,11 @@ receive_term(Request, State) ->
175
189
  _Any ->
176
190
  Request2 = Request#request{action = BinaryTerm},
177
191
  close_if_cast(Term, Request2),
178
- case Request2#request.priority of
179
- high ->
180
- Hq2 = queue:in(Request2, State#state.hq),
181
- Lq2 = State#state.lq;
182
- low ->
183
- Hq2 = State#state.hq,
184
- Lq2 = queue:in(Request2, State#state.lq)
185
- end,
186
- ernie_server:kick(),
187
- State#state{hq = Hq2, lq = Lq2}
192
+ ernie_server:enqueue_request(Request2),
193
+ ernie_server:kick()
188
194
  end;
189
195
  {error, closed} ->
190
- ok = gen_tcp:close(Sock),
191
- State
196
+ ok = gen_tcp:close(Sock)
192
197
  end.
193
198
 
194
199
  process_info(Request, priority, [Priority]) ->
@@ -200,16 +205,28 @@ process_request(Request, Priority, Q2, State) ->
200
205
  ActionTerm = bert:decode(Request#request.action),
201
206
  {_Type, Mod, _Fun, _Args} = ActionTerm,
202
207
  Specs = lists:filter(fun({X, _Id}) -> Mod =:= X end, State#state.map),
203
- process_module(ActionTerm, Specs, Request, Priority, Q2, State).
208
+ case Specs of
209
+ [] -> no_module(Mod, Request, Priority, Q2, State);
210
+ _Else -> process_module(ActionTerm, Specs, Request, Priority, Q2, State)
211
+ end.
204
212
 
205
- process_module(ActionTerm, [], Request, Priority, Q2, State) ->
206
- {_Type, Mod, _Fun, _Args} = ActionTerm,
213
+ no_module(Mod, Request, Priority, Q2, State) ->
207
214
  logger:debug("No such module ~p~n", [Mod]),
208
215
  Sock = Request#request.sock,
209
216
  Class = <<"ServerError">>,
210
217
  Message = list_to_binary(io_lib:format("No such module '~p'", [Mod])),
211
218
  gen_tcp:send(Sock, term_to_binary({error, [server, 0, Class, Message, []]})),
212
219
  ok = gen_tcp:close(Sock),
220
+ finish(Priority, Q2, State).
221
+
222
+ process_module(ActionTerm, [], Request, Priority, Q2, State) ->
223
+ {_Type, Mod, Fun, _Args} = ActionTerm,
224
+ logger:debug("No such function ~p:~p~n", [Mod, Fun]),
225
+ Sock = Request#request.sock,
226
+ Class = <<"ServerError">>,
227
+ Message = list_to_binary(io_lib:format("No such function '~p:~p'", [Mod, Fun])),
228
+ gen_tcp:send(Sock, term_to_binary({error, [server, 0, Class, Message, []]})),
229
+ ok = gen_tcp:close(Sock),
213
230
  finish(Priority, Q2, State);
214
231
  process_module(ActionTerm, Specs, Request, Priority, Q2, State) ->
215
232
  [{_Mod, Id} | OtherSpecs] = Specs,
data/elib/logger.erl CHANGED
@@ -15,28 +15,28 @@
15
15
  %%====================================================================
16
16
 
17
17
  start_link(Args) ->
18
- gen_server:start_link({global, ?MODULE}, ?MODULE, Args, []).
18
+ gen_server:start_link({local, ?MODULE}, ?MODULE, Args, []).
19
19
 
20
20
  start(Args) ->
21
- gen_server:start({global, ?MODULE}, ?MODULE, Args, []).
21
+ gen_server:start({local, ?MODULE}, ?MODULE, Args, []).
22
22
 
23
23
  set_log_level(Level) ->
24
- gen_server:call({global, ?MODULE}, {set_log_level, Level}).
24
+ gen_server:call(?MODULE, {set_log_level, Level}).
25
25
 
26
26
  debug(Msg, Args) ->
27
- gen_server:cast({global, ?MODULE}, {debug, Msg, Args}).
27
+ gen_server:cast(?MODULE, {debug, Msg, Args}).
28
28
 
29
29
  info(Msg, Args) ->
30
- gen_server:cast({global, ?MODULE}, {info, Msg, Args}).
30
+ gen_server:cast(?MODULE, {info, Msg, Args}).
31
31
 
32
32
  warn(Msg, Args) ->
33
- gen_server:cast({global, ?MODULE}, {warn, Msg, Args}).
33
+ gen_server:cast(?MODULE, {warn, Msg, Args}).
34
34
 
35
35
  error(Msg, Args) ->
36
- gen_server:cast({global, ?MODULE}, {error, Msg, Args}).
36
+ gen_server:cast(?MODULE, {error, Msg, Args}).
37
37
 
38
38
  fatal(Msg, Args) ->
39
- gen_server:cast({global, ?MODULE}, {fatal, Msg, Args}).
39
+ gen_server:cast(?MODULE, {fatal, Msg, Args}).
40
40
 
41
41
  %%====================================================================
42
42
  %% gen_server callbacks
data/ernie.gemspec CHANGED
@@ -1,95 +1,77 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
4
- # -*- encoding: utf-8 -*-
5
-
6
1
  Gem::Specification.new do |s|
7
- s.name = %q{ernie}
8
- s.version = "2.4.0"
9
-
2
+ s.specification_version = 2 if s.respond_to? :specification_version=
10
3
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Tom Preston-Werner"]
12
- s.date = %q{2010-05-21}
13
- s.default_executable = %q{ernie}
14
- s.description = %q{Ernie is an Erlang/Ruby hybrid BERT-RPC server implementation packaged as a gem.}
15
- s.email = %q{tom@mojombo.com}
16
- s.executables = ["ernie"]
4
+ s.rubygems_version = '1.3.6'
5
+
6
+ s.name = 'ernie'
7
+ s.version = '2.5.0'
8
+ s.date = '2010-11-19'
9
+ s.rubyforge_project = 'ernie'
10
+
11
+ s.summary = "Ernie is a BERT-RPC server implementation."
12
+ s.description = "Ernie is an Erlang/Ruby hybrid BERT-RPC server implementation packaged as a gem."
13
+
14
+ s.authors = ["Tom Preston-Werner"]
15
+ s.email = 'tom@mojombo.com'
16
+ s.homepage = 'http://github.com/mojombo/ernie'
17
+
18
+ s.require_paths = %w[lib]
19
+
17
20
  s.extensions = ["ext/extconf.rb", "ext/extconf.rb"]
18
- s.extra_rdoc_files = [
19
- "LICENSE",
20
- "README.md"
21
- ]
22
- s.files = [
23
- ".document",
24
- ".gitignore",
25
- "History.txt",
26
- "LICENSE",
27
- "README.md",
28
- "Rakefile",
29
- "VERSION.yml",
30
- "bin/ernie",
31
- "contrib/ebench.erl",
32
- "ebin/ernie_server_app.app",
33
- "elib/asset_pool.erl",
34
- "elib/asset_pool_sup.erl",
35
- "elib/bert.erl",
36
- "elib/ernie.hrl",
37
- "elib/ernie_access_logger.erl",
38
- "elib/ernie_access_logger_sup.erl",
39
- "elib/ernie_admin.erl",
40
- "elib/ernie_config.erl",
41
- "elib/ernie_native.erl",
42
- "elib/ernie_server.erl",
43
- "elib/ernie_server_app.erl",
44
- "elib/ernie_server_sup.erl",
45
- "elib/logger.erl",
46
- "elib/logger_sup.erl",
47
- "elib/port_wrapper.erl",
48
- "ernie.gemspec",
49
- "examples/example.cfg",
50
- "examples/example.config",
51
- "examples/ext.erl",
52
- "examples/ext.rb",
53
- "examples/nat.erl",
54
- "ext/Makefile",
55
- "ext/extconf.rb",
56
- "lib/ernie.rb",
57
- "test/ernie_server_test.rb",
58
- "test/ernie_test.rb",
59
- "test/helper.rb",
60
- "test/load.rb",
61
- "test/sample/ext.rb",
62
- "test/sample/sample.cfg"
63
- ]
64
- s.homepage = %q{http://github.com/mojombo/ernie}
21
+
22
+ s.executables = ["ernie"]
23
+ s.default_executable = 'ernie'
24
+
65
25
  s.rdoc_options = ["--charset=UTF-8"]
66
- s.require_paths = ["lib"]
67
- s.rubyforge_project = %q{ernie}
68
- s.rubygems_version = %q{1.3.6}
69
- s.summary = %q{Ernie is a BERT-RPC server implementation.}
70
- s.test_files = [
71
- "test/ernie_server_test.rb",
72
- "test/ernie_test.rb",
73
- "test/helper.rb",
74
- "test/load.rb",
75
- "test/sample/ext.rb",
76
- "examples/ext.rb"
77
- ]
26
+ s.extra_rdoc_files = %w[LICENSE README.md]
78
27
 
79
- if s.respond_to? :specification_version then
80
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
81
- s.specification_version = 3
28
+ s.add_dependency('bert', [">= 1.1.0"])
29
+ s.add_dependency('bertrpc', [">= 1.0.0"])
82
30
 
83
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
84
- s.add_runtime_dependency(%q<bert>, [">= 1.1.0"])
85
- s.add_runtime_dependency(%q<bertrpc>, [">= 1.0.0"])
86
- else
87
- s.add_dependency(%q<bert>, [">= 1.1.0"])
88
- s.add_dependency(%q<bertrpc>, [">= 1.0.0"])
89
- end
90
- else
91
- s.add_dependency(%q<bert>, [">= 1.1.0"])
92
- s.add_dependency(%q<bertrpc>, [">= 1.0.0"])
93
- end
94
- end
31
+ s.add_development_dependency('shoulda', [">= 2.11.3", "< 3.0.0"])
32
+
33
+ # = MANIFEST =
34
+ s.files = %w[
35
+ History.txt
36
+ LICENSE
37
+ README.md
38
+ Rakefile
39
+ bin/ernie
40
+ contrib/ebench.erl
41
+ ebin/ernie_server_app.app
42
+ elib/asset_pool.erl
43
+ elib/asset_pool_sup.erl
44
+ elib/bert.erl
45
+ elib/ernie.hrl
46
+ elib/ernie_access_logger.erl
47
+ elib/ernie_access_logger_sup.erl
48
+ elib/ernie_admin.erl
49
+ elib/ernie_config.erl
50
+ elib/ernie_native.erl
51
+ elib/ernie_server.erl
52
+ elib/ernie_server_app.erl
53
+ elib/ernie_server_sup.erl
54
+ elib/logger.erl
55
+ elib/logger_sup.erl
56
+ elib/port_wrapper.erl
57
+ ernie.gemspec
58
+ examples/example.cfg
59
+ examples/example.config
60
+ examples/ext.erl
61
+ examples/ext.rb
62
+ examples/nat.erl
63
+ ext/Makefile
64
+ ext/extconf.rb
65
+ lib/ernie.rb
66
+ test/helper.rb
67
+ test/load.rb
68
+ test/sample/ext.rb
69
+ test/sample/intTest.erl
70
+ test/sample/sample.cfg
71
+ test/test_ernie.rb
72
+ test/test_ernie_server.rb
73
+ ]
74
+ # = MANIFEST =
95
75
 
76
+ s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
77
+ end
data/lib/ernie.rb CHANGED
@@ -3,6 +3,8 @@ require 'bert'
3
3
  require 'logger'
4
4
 
5
5
  class Ernie
6
+ VERSION = '2.5.0'
7
+
6
8
  class << self
7
9
  attr_accessor :mods, :current_mod, :log
8
10
  attr_accessor :auto_start
@@ -185,13 +187,8 @@ class Ernie
185
187
  end
186
188
 
187
189
  def self.version
188
- yml = YAML.load(File.read(File.join(File.dirname(__FILE__), *%w[.. VERSION.yml])))
189
- "#{yml[:major]}.#{yml[:minor]}.#{yml[:patch]}"
190
- rescue
191
- 'unknown'
190
+ VERSION
192
191
  end
193
-
194
- VERSION = self.version
195
192
  end
196
193
 
197
194
  class Ernie::ServerError < StandardError; end
data/test/helper.rb CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  require 'test/unit'
3
3
  require 'shoulda'
4
4
 
5
- ERNIE_ROOT = File.join(File.dirname(__FILE__), *%w[..])
5
+ ERNIE_ROOT = File.expand_path(File.join(File.dirname(__FILE__), *%w[..]))
6
6
 
7
7
  $:.unshift(File.join(ERNIE_ROOT, 'lib'))
8
8
 
@@ -0,0 +1,60 @@
1
+ -module(intTest).
2
+
3
+ -export([zeronary/0, unary/1, binary/2, ternary/3, big/1, set_state/1, get_state/0, connect_nodes/0, sleep/1]).
4
+
5
+ connect_nodes() ->
6
+ net_adm:ping('ernie0@127.0.0.1').
7
+
8
+ zeronary() ->
9
+ foo.
10
+
11
+ unary(A) ->
12
+ A.
13
+
14
+ binary(A,B) ->
15
+ A + B.
16
+
17
+ ternary(A,B,C) ->
18
+ A + B + C.
19
+
20
+ big(A) ->
21
+ string:copies("a", A).
22
+
23
+ sleep(Time) ->
24
+ receive after Time ->
25
+ ok
26
+ end.
27
+
28
+ get_state() ->
29
+ case catch global:send(test_saved_state, {get_state, self()}) of
30
+ {'EXIT',{badarg, _}} ->
31
+ {error, no_record};
32
+ _ ->
33
+ receive
34
+ {ok, State} ->
35
+ State
36
+ after 1000 ->
37
+ {error, timeout}
38
+ end
39
+ end.
40
+
41
+ set_state(State) ->
42
+ spawn(fun() -> wrapper(State) end),
43
+ ok.
44
+
45
+ wrapper(State) ->
46
+ case global:register_name(test_saved_state, self()) of
47
+ no ->
48
+ global:send(test_saved_state, {set_state, State});
49
+ yes ->
50
+ recv(State)
51
+ end.
52
+
53
+ recv(State) ->
54
+ receive
55
+ {set_state, NewState} ->
56
+ recv(NewState);
57
+ {get_state, Pid} ->
58
+ Pid ! {ok, State},
59
+ recv(State)
60
+ end.
@@ -1,4 +1,8 @@
1
1
  [{module, ext},
2
2
  {type, external},
3
- {command, "ruby /Users/tom/dev/mojombo/ernie/test/sample/ext.rb"},
4
- {count, 1}].
3
+ {command, "ruby test/sample/ext.rb"},
4
+ {count, 1}].
5
+ [{module, intTest},
6
+ {type, native},
7
+ {codepaths, ["test/sample"]}
8
+ ].
File without changes
@@ -0,0 +1,221 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ PORT = 27118
4
+
5
+ class ErnieServerTest < Test::Unit::TestCase
6
+
7
+ # global setup
8
+ def setup
9
+ @servers ||= []
10
+ Dir.chdir(ERNIE_ROOT)
11
+ `erlc -o test/sample #{ERNIE_ROOT}/test/sample/intTest.erl`
12
+ Signal.trap("INT") do
13
+ puts "Shutting Down"
14
+ shutdown_servers
15
+ teardown
16
+ exit
17
+ end
18
+ end
19
+
20
+ def teardown
21
+ `rm test/sample/intTest.beam`
22
+ end
23
+
24
+ context "An Ernie Server" do
25
+ setup do
26
+ start_server
27
+ end
28
+
29
+ context "call" do
30
+ should "handle zeronary" do
31
+ assert_equal :foo, svc.call.ext.zeronary
32
+ assert_equal :foo, svc.call.intTest.zeronary
33
+ end
34
+
35
+ should "handle unary" do
36
+ assert_equal 5, svc.call.ext.unary(5)
37
+ assert_equal 5, svc.call.intTest.unary(5)
38
+ end
39
+
40
+ should "handle binary" do
41
+ assert_equal 7, svc.call.ext.binary(5, 2)
42
+ assert_equal 7, svc.call.intTest.binary(5, 2)
43
+ end
44
+
45
+ should "handle ternary" do
46
+ assert_equal 10, svc.call.ext.ternary(5, 2, 3)
47
+ assert_equal 10, svc.call.intTest.ternary(5, 2, 3)
48
+ end
49
+
50
+ should "handle massive binaries" do
51
+ assert_equal 8 * 1024 * 1024, svc.call.ext.big(8 * 1024 * 1024).size
52
+ assert_equal 8 * 1024 * 1024, svc.call.intTest.big(8 * 1024 * 1024).size
53
+ end
54
+
55
+ should "not block on internal modules" do
56
+ time = Time.now
57
+ svc.call.intTest.sleep(1000)
58
+ assert(Time.now >= time + 1)
59
+
60
+ time = Time.now
61
+ svc.cast.intTest.sleep(1000)
62
+ svc.cast.intTest.sleep(1000)
63
+ svc.cast.intTest.sleep(1000)
64
+ svc.call.intTest.zeronary
65
+ assert(Time.now < time + 1)
66
+ end
67
+
68
+ should "get an error on missing module" do
69
+ begin
70
+ svc.call.failboat.mcfail(:fail)
71
+ fail "Expected a BERTRPC::ServerError"
72
+ rescue BERTRPC::ServerError => e
73
+ assert_equal "No such module 'failboat'", e.message
74
+ else
75
+ assert false, 'failed to raise on missing module'
76
+ end
77
+ end
78
+
79
+ should "get an error on missing function" do
80
+ begin
81
+ svc.call.ext.mcfail(:fail)
82
+ fail "Expected a BERTRPC::ServerError"
83
+ rescue BERTRPC::ServerError => e
84
+ assert_equal "No such function 'ext:mcfail'", e.message
85
+ else
86
+ assert false, 'failed to raise on missing function'
87
+ end
88
+
89
+ begin
90
+ svc.call.intTest.mcfail(:fail)
91
+ fail "Expected a BERTRPC::ServerError"
92
+ rescue BERTRPC::ServerError => e
93
+ assert_equal "No such function 'intTest:mcfail'", e.message
94
+ else
95
+ assert false, 'failed to raise on missing function'
96
+ end
97
+ end
98
+ end
99
+
100
+ context "cast" do
101
+ should "be received and return immediately" do
102
+ t0 = Time.now
103
+ assert_equal nil, svc.cast.ext.set_state(7)
104
+ assert Time.now - t0 < 1
105
+ assert_equal 7, svc.call.ext.get_state
106
+
107
+ t0 = Time.now
108
+ assert_equal nil, svc.cast.intTest.set_state(7)
109
+ assert Time.now - t0 < 1
110
+ sleep 0.25
111
+ assert_equal 7, svc.call.intTest.get_state
112
+ end
113
+ end
114
+
115
+ teardown do
116
+ shutdown_server
117
+ end
118
+ end
119
+
120
+ context "Two Ernie Servers" do
121
+ setup do
122
+ start_servers(2)
123
+ @servers.each do |svc|
124
+ svc.cast.intTest.connect_nodes
125
+ end
126
+ end
127
+
128
+ context "call" do
129
+
130
+ should "handle zeronary" do
131
+ @servers.each do |svc|
132
+ assert_equal :foo, svc.call.ext.zeronary
133
+ assert_equal :foo, svc.call.intTest.zeronary
134
+ end
135
+ end
136
+
137
+ should "handle unary" do
138
+ @servers.each do |svc|
139
+ assert_equal 5, svc.call.ext.unary(5)
140
+ assert_equal 5, svc.call.intTest.unary(5)
141
+ end
142
+ end
143
+
144
+ should "handle binary" do
145
+ @servers.each do |svc|
146
+ assert_equal 7, svc.call.ext.binary(5, 2)
147
+ assert_equal 7, svc.call.intTest.binary(5, 2)
148
+ end
149
+ end
150
+
151
+ should "handle ternary" do
152
+ @servers.each do |svc|
153
+ assert_equal 10, svc.call.ext.ternary(5, 2, 3)
154
+ assert_equal 10, svc.call.intTest.ternary(5, 2, 3)
155
+ end
156
+ end
157
+
158
+ should "handle massive binaries" do
159
+ @servers.each do |svc|
160
+ assert_equal 8 * 1024 * 1024, svc.call.ext.big(8 * 1024 * 1024).size
161
+ assert_equal 8 * 1024 * 1024, svc.call.intTest.big(8 * 1024 * 1024).size
162
+ end
163
+ end
164
+
165
+ should "make joined erlang nodes possible" do
166
+ assert_equal nil, @servers.first.cast.intTest.set_state(7)
167
+ sleep 0.25
168
+ assert_equal 7, @servers.last.call.intTest.get_state
169
+ end
170
+
171
+ end
172
+
173
+ teardown do
174
+ shutdown_servers(2)
175
+ end
176
+ end
177
+
178
+ protected
179
+
180
+ def svc
181
+ @servers[rand(@servers.size-1)]
182
+ end
183
+
184
+ def start_server
185
+ start_servers(1)
186
+ end
187
+
188
+ def shutdown_server
189
+ shutdown_servers(1)
190
+ end
191
+
192
+ def start_servers(n = 1)
193
+ n.times do
194
+ `#{ERNIE_ROOT}/bin/ernie -c #{ERNIE_ROOT}/test/sample/sample.cfg \
195
+ -P /tmp/ernie#{@servers.size}.pid \
196
+ -p #{PORT + @servers.size} \
197
+ --name ernie#{@servers.size}@127.0.0.1 \
198
+ -d`
199
+
200
+ @servers << BERTRPC::Service.new('localhost', PORT + @servers.size)
201
+ loop do
202
+ begin
203
+ @servers.last.call.ext.zeronary
204
+ break
205
+ rescue Object => e
206
+ sleep 0.1
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ def shutdown_servers(n = nil)
213
+ start = @servers.size - 1
214
+ last = start - (n || start)
215
+ (start).downto(last >= 0 ? last : 0) do |i|
216
+ pid = File.read("/tmp/ernie#{i}.pid")
217
+ `kill -9 #{pid}`
218
+ end
219
+ end
220
+
221
+ end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ernie
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 27
4
5
  prerelease: false
5
6
  segments:
6
7
  - 2
7
- - 4
8
+ - 5
8
9
  - 0
9
- version: 2.4.0
10
+ version: 2.5.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - Tom Preston-Werner
@@ -14,16 +15,18 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-05-21 00:00:00 -07:00
18
+ date: 2010-11-19 00:00:00 -06:00
18
19
  default_executable: ernie
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: bert
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 19
27
30
  segments:
28
31
  - 1
29
32
  - 1
@@ -35,9 +38,11 @@ dependencies:
35
38
  name: bertrpc
36
39
  prerelease: false
37
40
  requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
38
42
  requirements:
39
43
  - - ">="
40
44
  - !ruby/object:Gem::Version
45
+ hash: 23
41
46
  segments:
42
47
  - 1
43
48
  - 0
@@ -45,6 +50,30 @@ dependencies:
45
50
  version: 1.0.0
46
51
  type: :runtime
47
52
  version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: shoulda
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 37
62
+ segments:
63
+ - 2
64
+ - 11
65
+ - 3
66
+ version: 2.11.3
67
+ - - <
68
+ - !ruby/object:Gem::Version
69
+ hash: 7
70
+ segments:
71
+ - 3
72
+ - 0
73
+ - 0
74
+ version: 3.0.0
75
+ type: :development
76
+ version_requirements: *id003
48
77
  description: Ernie is an Erlang/Ruby hybrid BERT-RPC server implementation packaged as a gem.
49
78
  email: tom@mojombo.com
50
79
  executables:
@@ -56,13 +85,10 @@ extra_rdoc_files:
56
85
  - LICENSE
57
86
  - README.md
58
87
  files:
59
- - .document
60
- - .gitignore
61
88
  - History.txt
62
89
  - LICENSE
63
90
  - README.md
64
91
  - Rakefile
65
- - VERSION.yml
66
92
  - bin/ernie
67
93
  - contrib/ebench.erl
68
94
  - ebin/ernie_server_app.app
@@ -90,12 +116,13 @@ files:
90
116
  - ext/Makefile
91
117
  - ext/extconf.rb
92
118
  - lib/ernie.rb
93
- - test/ernie_server_test.rb
94
- - test/ernie_test.rb
95
119
  - test/helper.rb
96
120
  - test/load.rb
97
121
  - test/sample/ext.rb
122
+ - test/sample/intTest.erl
98
123
  - test/sample/sample.cfg
124
+ - test/test_ernie.rb
125
+ - test/test_ernie_server.rb
99
126
  has_rdoc: true
100
127
  homepage: http://github.com/mojombo/ernie
101
128
  licenses: []
@@ -106,30 +133,30 @@ rdoc_options:
106
133
  require_paths:
107
134
  - lib
108
135
  required_ruby_version: !ruby/object:Gem::Requirement
136
+ none: false
109
137
  requirements:
110
138
  - - ">="
111
139
  - !ruby/object:Gem::Version
140
+ hash: 3
112
141
  segments:
113
142
  - 0
114
143
  version: "0"
115
144
  required_rubygems_version: !ruby/object:Gem::Requirement
145
+ none: false
116
146
  requirements:
117
147
  - - ">="
118
148
  - !ruby/object:Gem::Version
149
+ hash: 3
119
150
  segments:
120
151
  - 0
121
152
  version: "0"
122
153
  requirements: []
123
154
 
124
155
  rubyforge_project: ernie
125
- rubygems_version: 1.3.6
156
+ rubygems_version: 1.3.7
126
157
  signing_key:
127
- specification_version: 3
158
+ specification_version: 2
128
159
  summary: Ernie is a BERT-RPC server implementation.
129
160
  test_files:
130
- - test/ernie_server_test.rb
131
- - test/ernie_test.rb
132
- - test/helper.rb
133
- - test/load.rb
134
- - test/sample/ext.rb
135
- - examples/ext.rb
161
+ - test/test_ernie.rb
162
+ - test/test_ernie_server.rb
data/.document DELETED
@@ -1,5 +0,0 @@
1
- README.md
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
data/.gitignore DELETED
@@ -1,2 +0,0 @@
1
- *.beam
2
- pkg
data/VERSION.yml DELETED
@@ -1,5 +0,0 @@
1
- ---
2
- :minor: 4
3
- :build:
4
- :patch: 0
5
- :major: 2
@@ -1,77 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- PORT = 27118
4
-
5
- class ErnieServerTest < Test::Unit::TestCase
6
- context "An Ernie Server" do
7
- setup do
8
- `#{ERNIE_ROOT}/bin/ernie -c #{ERNIE_ROOT}/test/sample/sample.cfg \
9
- -P /tmp/ernie.pid \
10
- -p #{PORT} \
11
- -d`
12
- @svc = BERTRPC::Service.new('localhost', PORT)
13
- loop do
14
- begin
15
- @svc.call.ext.zeronary
16
- break
17
- rescue Object => e
18
- sleep 0.1
19
- end
20
- end
21
- end
22
-
23
- context "call" do
24
- should "handle zeronary" do
25
- assert_equal :foo, @svc.call.ext.zeronary
26
- end
27
-
28
- should "handle unary" do
29
- assert_equal 5, @svc.call.ext.unary(5)
30
- end
31
-
32
- should "handle binary" do
33
- assert_equal 7, @svc.call.ext.binary(5, 2)
34
- end
35
-
36
- should "handle ternary" do
37
- assert_equal 10, @svc.call.ext.ternary(5, 2, 3)
38
- end
39
-
40
- should "handle massive binaries" do
41
- assert_equal 8 * 1024 * 1024, @svc.call.ext.big(8 * 1024 * 1024).size
42
- end
43
-
44
- should "get an error on missing module" do
45
- begin
46
- @svc.call.failboat.mcfail(:fail)
47
- fail "Expected a BERTRPC::ServerError"
48
- rescue BERTRPC::ServerError => e
49
- assert_equal "No such module 'failboat'", e.message
50
- end
51
- end
52
-
53
- should "get an error on missing function" do
54
- begin
55
- @svc.call.ext.mcfail(:fail)
56
- fail "Expected a BERTRPC::ServerError"
57
- rescue BERTRPC::ServerError => e
58
- assert_equal "No such function 'ext:mcfail'", e.message
59
- end
60
- end
61
- end
62
-
63
- context "cast" do
64
- should "be received and return immediately" do
65
- t0 = Time.now
66
- assert_equal nil, @svc.cast.ext.set_state(7)
67
- assert Time.now - t0 < 1
68
- assert_equal 7, @svc.call.ext.get_state
69
- end
70
- end
71
-
72
- teardown do
73
- pid = File.read('/tmp/ernie.pid')
74
- `kill -9 #{pid}`
75
- end
76
- end
77
- end