1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
% Licensed under the Apache License, Version 2.0 (the "License"); you may not
% use this file except in compliance with the License. You may obtain a copy of
% the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
% License for the specific language governing permissions and limitations under
% the License.
-module(couch_views_server).
-behaviour(gen_server).
-export([
start_link/0
]).
-export([
init/1,
terminate/2,
handle_call/3,
handle_cast/2,
handle_info/2,
code_change/3
]).
-define(MAX_WORKERS, 100).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init(_) ->
process_flag(trap_exit, true),
couch_views_jobs:set_timeout(),
St = #{
workers => #{},
max_workers => max_workers()
},
{ok, spawn_workers(St)}.
terminate(_, _St) ->
ok.
handle_call(Msg, _From, St) ->
{stop, {bad_call, Msg}, {bad_call, Msg}, St}.
handle_cast(Msg, St) ->
{stop, {bad_cast, Msg}, St}.
handle_info({'EXIT', Pid, Reason}, St) ->
#{workers := Workers} = St,
case maps:is_key(Pid, Workers) of
true ->
if Reason == normal -> ok; true ->
LogMsg = "~p : indexer process ~p exited with ~p",
couch_log:error(LogMsg, [?MODULE, Pid, Reason])
end,
NewWorkers = maps:remove(Pid, Workers),
{noreply, spawn_workers(St#{workers := NewWorkers})};
false ->
LogMsg = "~p : unknown process ~p exited with ~p",
couch_log:error(LogMsg, [?MODULE, Pid, Reason]),
{stop, {unknown_pid_exit, Pid}, St}
end;
handle_info(Msg, St) ->
{stop, {bad_info, Msg}, St}.
code_change(_OldVsn, St, _Extra) ->
{ok, St}.
spawn_workers(St) ->
#{
workers := Workers,
max_workers := MaxWorkers
} = St,
case maps:size(Workers) < MaxWorkers of
true ->
Pid = couch_views_indexer:spawn_link(),
NewSt = St#{workers := Workers#{Pid => true}},
spawn_workers(NewSt);
false ->
St
end.
max_workers() ->
config:get_integer("couch_views", "max_workers", ?MAX_WORKERS).
|