ernie 2.2.1 → 2.3.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,7 @@
1
+ = 2.3.0 / 2010-05-17
2
+ * Minor Additions
3
+ * Add 'halt' command for gracefully shutting down
4
+
1
5
  = 2.2.1 / 2010-05-13
2
6
  * Minor Changes
3
7
  * Increase TCP backlog from 5 to 128
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- :minor: 2
2
+ :minor: 3
3
3
  :build:
4
- :patch: 1
4
+ :patch: 0
5
5
  :major: 2
data/bin/ernie CHANGED
@@ -33,6 +33,8 @@ Commands:
33
33
  <none> Start an Ernie server.
34
34
  reload-handlers Gracefully reload all of the the ruby handlers
35
35
  and use the new code for all subsequent requests.
36
+ stats Print usage statistics.
37
+ halt Gracefully halt the server.
36
38
 
37
39
  Options:
38
40
  HELP
@@ -68,10 +70,11 @@ OptionParser.new do |opts|
68
70
  end.parse!
69
71
 
70
72
  if command = ARGV[0]
71
- if !%w{reload-handlers stats}.include?(command)
73
+ if !%w{reload-handlers stats halt}.include?(command)
72
74
  puts "Invlalid command. Valid commands are:"
73
75
  puts " reload-handlers"
74
76
  puts " stats"
77
+ puts " halt"
75
78
  exit(1)
76
79
  end
77
80
 
data/elib/asset_pool.erl CHANGED
@@ -9,6 +9,7 @@
9
9
  terminate/2, code_change/3]).
10
10
 
11
11
  -record(state, {assets = undefined,
12
+ count = undefined,
12
13
  handler = undefined,
13
14
  token = undefined}).
14
15
 
@@ -48,7 +49,7 @@ init([Handler, Count]) ->
48
49
  Token = make_ref(),
49
50
  Assets = start_handlers(Count, Handler, Token),
50
51
  logger:debug("Assets = ~p~n", [Assets]),
51
- {ok, #state{assets = Assets, handler = Handler, token = Token}}.
52
+ {ok, #state{assets = Assets, count = Count, handler = Handler, token = Token}}.
52
53
 
53
54
  %%--------------------------------------------------------------------
54
55
  %% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
data/elib/ernie.hrl CHANGED
@@ -1,7 +1,9 @@
1
1
  -record(state, {lsock = undefined, % the listen socket
2
+ listen = true, % whether to listen for new connections
2
3
  hq = queue:new(), % high priority queue
3
4
  lq = queue:new(), % low priority queue
4
5
  count = 0, % total request count
6
+ zcount = 0, % total completed request count
5
7
  map = undefined}). % module map. tuples of {Mod, Id}
6
8
 
7
9
  -record(request, {sock = undefined, % connection socket
data/elib/ernie_admin.erl CHANGED
@@ -8,6 +8,9 @@
8
8
  process(Sock, reload_handlers, _Args, State) ->
9
9
  spawn(fun() -> process_reload_assets(Sock, State) end),
10
10
  State;
11
+ process(Sock, halt, _Args, State) ->
12
+ process_halt(Sock, State),
13
+ State#state{listen = false};
11
14
  process(Sock, stats, _Args, State) ->
12
15
  spawn(fun() -> process_stats(Sock, State) end),
13
16
  State;
@@ -29,14 +32,27 @@ reload({_Mod, native}) ->
29
32
  reload({_Mod, Pid}) ->
30
33
  asset_pool:reload_assets(Pid).
31
34
 
35
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36
+ % Halt
37
+
38
+ process_halt(Sock, State) ->
39
+ gen_tcp:send(Sock, term_to_binary({reply, <<"Halting.">>})),
40
+ ok = gen_tcp:close(Sock),
41
+ gen_tcp:close(State#state.lsock),
42
+ case State#state.count =:= State#state.zcount of
43
+ true -> halt();
44
+ false -> ok
45
+ end.
46
+
32
47
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33
48
  % Stats
34
49
 
35
50
  process_stats(Sock, State) ->
36
51
  CountString = stat(count, State),
52
+ ZCountString = stat(zcount, State),
37
53
  IdleWorkersString = stat(idle, State),
38
54
  QueueLengthString = stat(queue, State),
39
- StatString = list_to_binary([CountString, IdleWorkersString, QueueLengthString]),
55
+ StatString = list_to_binary([CountString, ZCountString, IdleWorkersString, QueueLengthString]),
40
56
  Data = term_to_binary({reply, StatString}),
41
57
  gen_tcp:send(Sock, Data),
42
58
  ok = gen_tcp:close(Sock).
@@ -44,6 +60,9 @@ process_stats(Sock, State) ->
44
60
  stat(count, State) ->
45
61
  Count = State#state.count,
46
62
  list_to_binary([<<"connections.total=">>, integer_to_list(Count), <<"\n">>]);
63
+ stat(zcount, State) ->
64
+ ZCount = State#state.zcount,
65
+ list_to_binary([<<"connections.completed=">>, integer_to_list(ZCount), <<"\n">>]);
47
66
  stat(idle, State) ->
48
67
  IdleMap = lists:map((fun idle/1), State#state.map),
49
68
  list_to_binary(IdleMap);
@@ -20,6 +20,7 @@ process(ActionTerm, Request) ->
20
20
  gen_tcp:send(Sock, Data)
21
21
  end,
22
22
  ok = gen_tcp:close(Sock),
23
+ ernie_server:fin(),
23
24
  Log = Request#request.log,
24
25
  Log2 = Log#log{tdone = erlang:now()},
25
26
  Request2 = Request#request{log = Log2},
@@ -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]).
6
+ -export([start_link/1, start/1, process/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,
@@ -25,6 +25,9 @@ process(Sock) ->
25
25
  kick() ->
26
26
  gen_server:cast({global, ?MODULE}, kick).
27
27
 
28
+ fin() ->
29
+ gen_server:cast({global, ?MODULE}, fin).
30
+
28
31
  %%====================================================================
29
32
  %% gen_server callbacks
30
33
  %%====================================================================
@@ -84,6 +87,15 @@ handle_cast(kick, State) ->
84
87
  {noreply, State}
85
88
  end
86
89
  end;
90
+ handle_cast(fin, State) ->
91
+ Listen = State#state.listen,
92
+ Count = State#state.count,
93
+ ZCount = State#state.zcount + 1,
94
+ logger:debug("Fin; Listen = ~p (~p/~p)~n", [Listen, Count, ZCount]),
95
+ case Listen =:= false andalso ZCount =:= Count of
96
+ true -> halt();
97
+ false -> {noreply, State#state{zcount = ZCount}}
98
+ end;
87
99
  handle_cast(_Msg, State) -> {noreply, State}.
88
100
 
89
101
  handle_info(Msg, State) ->
@@ -119,6 +131,7 @@ try_listen(Port, Times) ->
119
131
  case Res of
120
132
  {ok, LSock} ->
121
133
  error_logger:info_msg("Listening on port ~p~n", [Port]),
134
+ % gen_tcp:controlling_process(LSock, ernie_server),
122
135
  {ok, LSock};
123
136
  {error, Reason} ->
124
137
  error_logger:info_msg("Could not listen on port ~p: ~p~n", [Port, Reason]),
@@ -127,10 +140,18 @@ try_listen(Port, Times) ->
127
140
  end.
128
141
 
129
142
  loop(LSock) ->
130
- {ok, Sock} = gen_tcp:accept(LSock),
131
- logger:debug("Accepted socket: ~p~n", [Sock]),
132
- ernie_server:process(Sock),
133
- loop(LSock).
143
+ case gen_tcp:accept(LSock) of
144
+ {error, closed} ->
145
+ logger:debug("Listen socket closed~n", []),
146
+ timer:sleep(infinity);
147
+ {error, Error} ->
148
+ logger:debug("Connection accept error: ~p~n", [Error]),
149
+ loop(LSock);
150
+ {ok, Sock} ->
151
+ logger:debug("Accepted socket: ~p~n", [Sock]),
152
+ ernie_server:process(Sock),
153
+ loop(LSock)
154
+ end.
134
155
 
135
156
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136
157
  % Receive and process
@@ -287,6 +308,7 @@ process_now(Pid, Request, Asset) ->
287
308
  ernie_access_logger:err(Request2, "External process error ~w: ~w", [AnyClass, AnyError])
288
309
  after
289
310
  asset_pool:return(Pid, Asset),
311
+ ernie_server:fin(),
290
312
  ernie_server:kick(),
291
313
  logger:debug("Returned asset ~p~n", [Asset]),
292
314
  gen_tcp:close(Request#request.sock),
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 = "2.2.1"
8
+ s.version = "2.3.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{2010-05-13}
12
+ s.date = %q{2010-05-17}
13
13
  s.default_executable = %q{ernie}
14
14
  s.description = %q{Ernie is an Erlang/Ruby hybrid BERT-RPC server implementation packaged as a gem.}
15
15
  s.email = %q{tom@mojombo.com}
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 2
7
- - 2
8
- - 1
9
- version: 2.2.1
7
+ - 3
8
+ - 0
9
+ version: 2.3.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Tom Preston-Werner
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-13 00:00:00 -07:00
17
+ date: 2010-05-17 00:00:00 -07:00
18
18
  default_executable: ernie
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency