]> granicus.if.org Git - apache/blob - modules/proxy/balancers/mod_lbmethod_bybusyness.c
Move useful and shared balancer stuff to the shm slot...
[apache] / modules / proxy / balancers / mod_lbmethod_bybusyness.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "mod_proxy.h"
18 #include "scoreboard.h"
19 #include "ap_mpm.h"
20 #include "apr_version.h"
21 #include "ap_hooks.h"
22
23 module AP_MODULE_DECLARE_DATA lbmethod_bybusyness_module;
24
25 static proxy_worker *find_best_bybusyness(proxy_balancer *balancer,
26                                 request_rec *r)
27 {
28
29     int i;
30     proxy_worker **worker;
31     proxy_worker *mycandidate = NULL;
32     int cur_lbset = 0;
33     int max_lbset = 0;
34     int checking_standby;
35     int checked_standby;
36
37     int total_factor = 0;
38
39     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
40                  "proxy: Entering bybusyness for BALANCER (%s)",
41                  balancer->s->name);
42
43     /* First try to see if we have available candidate */
44     do {
45
46         checking_standby = checked_standby = 0;
47         while (!mycandidate && !checked_standby) {
48
49             worker = (proxy_worker **)balancer->workers->elts;
50             for (i = 0; i < balancer->workers->nelts; i++, worker++) {
51                 if  (!checking_standby) {    /* first time through */
52                     if ((*worker)->s->lbset > max_lbset)
53                         max_lbset = (*worker)->s->lbset;
54                 }
55                 if (
56                     ((*worker)->s->lbset != cur_lbset) ||
57                     (checking_standby ? !PROXY_WORKER_IS_STANDBY(*worker) : PROXY_WORKER_IS_STANDBY(*worker)) ||
58                     (PROXY_WORKER_IS_DRAINING(*worker))
59                     ) {
60                     continue;
61                 }
62
63                 /* If the worker is in error state run
64                  * retry on that worker. It will be marked as
65                  * operational if the retry timeout is elapsed.
66                  * The worker might still be unusable, but we try
67                  * anyway.
68                  */
69                 if (!PROXY_WORKER_IS_USABLE(*worker))
70                     ap_proxy_retry_worker("BALANCER", *worker, r->server);
71
72                 /* Take into calculation only the workers that are
73                  * not in error state or not disabled.
74                  */
75                 if (PROXY_WORKER_IS_USABLE(*worker)) {
76
77                     (*worker)->s->lbstatus += (*worker)->s->lbfactor;
78                     total_factor += (*worker)->s->lbfactor;
79
80                     if (!mycandidate
81                         || (*worker)->s->busy < mycandidate->s->busy
82                         || ((*worker)->s->busy == mycandidate->s->busy && (*worker)->s->lbstatus > mycandidate->s->lbstatus))
83                         mycandidate = *worker;
84
85                 }
86
87             }
88
89             checked_standby = checking_standby++;
90
91         }
92
93         cur_lbset++;
94
95     } while (cur_lbset <= max_lbset && !mycandidate);
96
97     if (mycandidate) {
98         mycandidate->s->lbstatus -= total_factor;
99         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
100                      "proxy: bybusyness selected worker \"%s\" : busy %" APR_SIZE_T_FMT " : lbstatus %d",
101                      mycandidate->s->name, mycandidate->s->busy, mycandidate->s->lbstatus);
102
103     }
104
105     return mycandidate;
106
107 }
108
109 /* assumed to be mutex protected by caller */
110 static apr_status_t reset(proxy_balancer *balancer, server_rec *s) {
111     int i;
112     proxy_worker **worker;
113     worker = (proxy_worker **)balancer->workers->elts;
114     for (i = 0; i < balancer->workers->nelts; i++, worker++) {
115         (*worker)->s->lbstatus = 0;
116         (*worker)->s->busy = 0;
117     }
118     return APR_SUCCESS;
119 }
120
121 static apr_status_t age(proxy_balancer *balancer, server_rec *s) {
122         return APR_SUCCESS;
123 }
124
125 static const proxy_balancer_method bybusyness =
126 {
127     "bybusyness",
128     &find_best_bybusyness,
129     NULL,
130     &reset,
131     &age
132 };
133
134
135 static void register_hook(apr_pool_t *p)
136 {
137     ap_register_provider(p, PROXY_LBMETHOD, "bybusyness", "0", &bybusyness);
138 }
139
140 AP_DECLARE_MODULE(lbmethod_bybusyness) = {
141     STANDARD20_MODULE_STUFF,
142     NULL,       /* create per-directory config structure */
143     NULL,       /* merge per-directory config structures */
144     NULL,       /* create per-server config structure */
145     NULL,       /* merge per-server config structures */
146     NULL,       /* command apr_table_t */
147     register_hook /* register hooks */
148 };