LCOV - code coverage report
Current view: top level - source3/lib - server_prefork_util.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 46 78 59.0 %
Date: 2021-09-23 10:06:22 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/Netbios implementation.
       3             :    Prefork Helpers
       4             :    Copyright (C) Simo Sorce <idra@samba.org> 2011
       5             : 
       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.
      10             : 
      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.
      15             : 
      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/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "lib/server_prefork.h"
      22             : #include "lib/server_prefork_util.h"
      23             : 
      24          63 : void pfh_daemon_config(const char *daemon_name,
      25             :                         struct pf_daemon_config *cfg,
      26             :                         const struct pf_daemon_config *default_cfg)
      27             : {
      28             :         int min, max, rate, allow, life;
      29             : 
      30          63 :         min = lp_parm_int(GLOBAL_SECTION_SNUM,
      31             :                                 daemon_name,
      32             :                                 "prefork_min_children",
      33           0 :                                 default_cfg->min_children);
      34          63 :         max = lp_parm_int(GLOBAL_SECTION_SNUM,
      35             :                                 daemon_name,
      36             :                                 "prefork_max_children",
      37           0 :                                 default_cfg->max_children);
      38          63 :         rate = lp_parm_int(GLOBAL_SECTION_SNUM,
      39             :                                 daemon_name,
      40             :                                 "prefork_spawn_rate",
      41           0 :                                 default_cfg->spawn_rate);
      42          63 :         allow = lp_parm_int(GLOBAL_SECTION_SNUM,
      43             :                                 daemon_name,
      44             :                                 "prefork_max_allowed_clients",
      45           0 :                                 default_cfg->max_allowed_clients);
      46          63 :         life = lp_parm_int(GLOBAL_SECTION_SNUM,
      47             :                                 daemon_name,
      48             :                                 "prefork_child_min_life",
      49           0 :                                 default_cfg->child_min_life);
      50             : 
      51          63 :         if (max > cfg->max_children && cfg->max_children != 0) {
      52           0 :                 cfg->prefork_status |= PFH_NEW_MAX;
      53             :         }
      54             : 
      55          63 :         cfg->min_children = min;
      56          63 :         cfg->max_children = max;
      57          63 :         cfg->spawn_rate = rate;
      58          63 :         cfg->max_allowed_clients = allow;
      59          63 :         cfg->child_min_life = life;
      60          63 : }
      61             : 
      62        2900 : 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)
      66             : {
      67        2900 :         time_t now = time(NULL);
      68             :         int total, avail;
      69             :         int ret, n;
      70        2900 :         bool msg = false;
      71             : 
      72        2900 :         if ((cfg->prefork_status & PFH_NEW_MAX) &&
      73           0 :             !(cfg->prefork_status & PFH_ENOSPC)) {
      74           0 :                 ret = prefork_expand_pool(pool, cfg->max_children);
      75           0 :                 if (ret == ENOSPC) {
      76           0 :                         cfg->prefork_status |= PFH_ENOSPC;
      77             :                 }
      78           0 :                 cfg->prefork_status &= ~PFH_NEW_MAX;
      79             :         }
      80             : 
      81        2900 :         total = prefork_count_children(pool, NULL);
      82        2900 :         avail = prefork_count_allowed_connections(pool);
      83        2900 :         DEBUG(10, ("(Pre)Stats: children: %d, allowed connections: %d\n",
      84             :                    total, avail));
      85             : 
      86        2900 :         if ((total < cfg->max_children) && (avail < cfg->spawn_rate)) {
      87          21 :                 n = prefork_add_children(ev_ctx, msg_ctx,
      88             :                                          pool, cfg->spawn_rate);
      89          12 :                 if (n < cfg->spawn_rate) {
      90           0 :                         DEBUG(10, ("Attempted to add %d children but only "
      91             :                                    "%d were actually added!\n",
      92             :                                    cfg->spawn_rate, n));
      93             :                 }
      94        2879 :         } 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          72 :                 n = (cfg->spawn_rate / 2) + 1;
      98          72 :                 if (n > cfg->spawn_rate) {
      99           0 :                         n = cfg->spawn_rate;
     100             :                 }
     101          72 :                 if ((total - n) < cfg->min_children) {
     102           0 :                         n = total - cfg->min_children;
     103             :                 }
     104          72 :                 if (n >= 0) {
     105          72 :                         prefork_retire_children(msg_ctx, pool, n,
     106          72 :                                                 now - cfg->child_min_life);
     107             :                 }
     108             :         }
     109             : 
     110             :         /* total/avail may have just been changed in the above if/else */
     111        2885 :         total = prefork_count_children(pool, NULL);
     112        2885 :         avail = prefork_count_allowed_connections(pool);
     113        2885 :         if ((total == cfg->max_children) && (avail < cfg->spawn_rate)) {
     114           0 :                 n = avail;
     115           0 :                 while (avail < cfg->spawn_rate) {
     116           0 :                         prefork_increase_allowed_clients(pool,
     117             :                                                 cfg->max_allowed_clients);
     118           0 :                         avail = prefork_count_allowed_connections(pool);
     119             :                         /* if avail didn't change do not loop forever */
     120           0 :                         if (n == avail) break;
     121           0 :                         n = avail;
     122             :                 }
     123           0 :                 msg = true;
     124        2885 :         } else if (avail > total + cfg->spawn_rate) {
     125           0 :                 n = avail;
     126           0 :                 while (avail > total + cfg->spawn_rate) {
     127           0 :                         prefork_decrease_allowed_clients(pool);
     128           0 :                         avail = prefork_count_allowed_connections(pool);
     129             :                         /* if avail didn't change do not loop forever */
     130           0 :                         if (n == avail) break;
     131           0 :                         n = avail;
     132             :                 }
     133             :         }
     134             : 
     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 */
     139        2885 :         if (msg) {
     140           0 :                 prefork_warn_active_children(msg_ctx, pool);
     141             :         }
     142             : 
     143        2885 :         DEBUG(10, ("Stats: children: %d, allowed connections: %d\n",
     144             :                   prefork_count_children(pool, NULL),
     145             :                   prefork_count_allowed_connections(pool)));
     146        2885 : }
     147             : 
     148        1002 : void pfh_client_terminated(struct pf_worker_data *pf)
     149             : {
     150        1002 :         if (pf->num_clients >= 0) {
     151        1002 :                 pf->num_clients--;
     152             :         } else {
     153           0 :                 if (pf->status != PF_WORKER_EXITING) {
     154           0 :                         DEBUG(1, ("Invalid num clients, stopping!\n"));
     155             :                 }
     156           0 :                 pf->status = PF_WORKER_EXITING;
     157           0 :                 pf->num_clients = -1;
     158             :         }
     159        1002 : }
     160             : 
     161      168432 : bool pfh_child_allowed_to_accept(struct pf_worker_data *pf)
     162             : {
     163      336864 :         if (pf->status == PF_WORKER_EXITING ||
     164      168432 :             pf->status == PF_WORKER_ACCEPTING) {
     165       34377 :                 return false;
     166             :         }
     167             : 
     168      134055 :         return (pf->num_clients < pf->allowed_clients);
     169             : }

Generated by: LCOV version 1.13