2 Unix SMB/Netbios implementation.
4 Copyright (C) Simo Sorce <idra@samba.org> 2011
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "lib/server_prefork.h"
22 #include "lib/server_prefork_util.h"
24 void pfh_daemon_config(const char *daemon_name
,
25 struct pf_daemon_config
*cfg
,
26 struct pf_daemon_config
*default_cfg
)
28 int min
, max
, rate
, allow
, life
;
30 min
= lp_parm_int(GLOBAL_SECTION_SNUM
,
32 "prefork_min_children",
33 default_cfg
->min_children
);
34 max
= lp_parm_int(GLOBAL_SECTION_SNUM
,
36 "prefork_max_children",
37 default_cfg
->max_children
);
38 rate
= lp_parm_int(GLOBAL_SECTION_SNUM
,
41 default_cfg
->spawn_rate
);
42 allow
= lp_parm_int(GLOBAL_SECTION_SNUM
,
44 "prefork_max_allowed_clients",
45 default_cfg
->max_allowed_clients
);
46 life
= lp_parm_int(GLOBAL_SECTION_SNUM
,
48 "prefork_child_min_life",
49 default_cfg
->child_min_life
);
51 if (max
> cfg
->max_children
&& cfg
->max_children
!= 0) {
52 cfg
->prefork_status
|= PFH_NEW_MAX
;
55 cfg
->min_children
= min
;
56 cfg
->max_children
= max
;
57 cfg
->spawn_rate
= rate
;
58 cfg
->max_allowed_clients
= allow
;
59 cfg
->child_min_life
= life
;
62 void pfh_manage_pool(struct tevent_context
*ev_ctx
,
63 struct messaging_context
*msg_ctx
,
64 struct pf_daemon_config
*cfg
,
65 struct prefork_pool
*pool
)
67 time_t now
= time(NULL
);
72 if ((cfg
->prefork_status
& PFH_NEW_MAX
) &&
73 !(cfg
->prefork_status
& PFH_ENOSPC
)) {
74 ret
= prefork_expand_pool(pool
, cfg
->max_children
);
76 cfg
->prefork_status
|= PFH_ENOSPC
;
78 cfg
->prefork_status
&= ~PFH_NEW_MAX
;
81 total
= prefork_count_children(pool
, NULL
);
82 avail
= prefork_count_allowed_connections(pool
);
83 DEBUG(10, ("(Pre)Stats: children: %d, allowed connections: %d\n",
86 if ((total
< cfg
->max_children
) && (avail
< cfg
->spawn_rate
)) {
87 n
= prefork_add_children(ev_ctx
, msg_ctx
,
88 pool
, cfg
->spawn_rate
);
89 if (n
< cfg
->spawn_rate
) {
90 DEBUG(10, ("Attempted to add %d children but only "
91 "%d were actually added!\n",
94 } else if ((avail
- cfg
->min_children
) >= cfg
->spawn_rate
) {
95 /* be a little slower in retiring children, to allow for
96 * double spikes of traffic to be handled more gracefully */
97 n
= (cfg
->spawn_rate
/ 2) + 1;
98 if (n
> cfg
->spawn_rate
) {
101 if ((total
- n
) < cfg
->min_children
) {
102 n
= total
- cfg
->min_children
;
105 prefork_retire_children(msg_ctx
, pool
, n
,
106 now
- cfg
->child_min_life
);
110 /* total/avail may have just been changed in the above if/else */
111 total
= prefork_count_children(pool
, NULL
);
112 avail
= prefork_count_allowed_connections(pool
);
113 if ((total
== cfg
->max_children
) && (avail
< cfg
->spawn_rate
)) {
115 while (avail
< cfg
->spawn_rate
) {
116 prefork_increase_allowed_clients(pool
,
117 cfg
->max_allowed_clients
);
118 avail
= prefork_count_allowed_connections(pool
);
119 /* if avail didn't change do not loop forever */
120 if (n
== avail
) break;
124 } else if (avail
> total
+ cfg
->spawn_rate
) {
126 while (avail
> total
+ cfg
->spawn_rate
) {
127 prefork_decrease_allowed_clients(pool
);
128 avail
= prefork_count_allowed_connections(pool
);
129 /* if avail didn't change do not loop forever */
130 if (n
== avail
) break;
135 /* send message to all children when we change maximum allowed
136 * connections, so that they can decide to start again to listen to
137 * sockets if they were already topping the number of allowed
138 * clients. Useful only when we increase allowed clients */
140 prefork_warn_active_children(msg_ctx
, pool
);
143 DEBUG(10, ("Stats: children: %d, allowed connections: %d\n",
144 prefork_count_children(pool
, NULL
),
145 prefork_count_allowed_connections(pool
)));
148 void pfh_client_terminated(struct pf_worker_data
*pf
)
150 if (pf
->num_clients
>= 0) {
153 if (pf
->status
!= PF_WORKER_EXITING
) {
154 DEBUG(1, ("Invalid num clients, stopping!\n"));
156 pf
->status
= PF_WORKER_EXITING
;
157 pf
->num_clients
= -1;
161 bool pfh_child_allowed_to_accept(struct pf_worker_data
*pf
)
163 if (pf
->status
== PF_WORKER_EXITING
||
164 pf
->status
== PF_WORKER_ACCEPTING
) {
168 return (pf
->num_clients
< pf
->allowed_clients
);