~ubuntu-branches/ubuntu/trusty/haproxy/trusty-updates

« back to all changes in this revision

Viewing changes to src/backend.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Cornet
  • Date: 2009-10-19 22:31:45 UTC
  • mfrom: (1.2.5 upstream)
  • mto: This revision was merged to the branch mainline in revision 10.
  • Revision ID: james.westby@ubuntu.com-20091019223145-rymupk5njs544bvp
ImportĀ upstreamĀ versionĀ 1.3.22

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#include <proto/fd.h>
34
34
#include <proto/httperr.h>
35
35
#include <proto/log.h>
 
36
#include <proto/port_range.h>
36
37
#include <proto/proto_http.h>
37
38
#include <proto/proto_tcp.h>
38
39
#include <proto/queue.h>
200
201
                int max = 0;
201
202
                best = NULL;
202
203
                for (cur = px->srv; cur; cur = cur->next) {
203
 
                        if (flag == (cur->state &
 
204
                        if (cur->eweight &&
 
205
                            flag == (cur->state &
204
206
                                     (SRV_RUNNING | SRV_GOINGDOWN | SRV_BACKUP))) {
205
207
                                int v;
206
208
 
247
249
                return;
248
250
 
249
251
        /* We will factor the weights to reduce the table,
250
 
         * using Euclide's largest common divisor algorithm
 
252
         * using Euclide's largest common divisor algorithm.
 
253
         * Since we may have zero weights, we have to first
 
254
         * find a non-zero weight server.
251
255
         */
252
 
        pgcd = p->srv->uweight;
253
 
        for (srv = p->srv->next; srv && pgcd > 1; srv = srv->next) {
254
 
                int w = srv->uweight;
255
 
                while (w) {
256
 
                        int t = pgcd % w;
257
 
                        pgcd = w;
258
 
                        w = t;
 
256
        pgcd = 1;
 
257
        srv = p->srv;
 
258
        while (srv && !srv->uweight)
 
259
                srv = srv->next;
 
260
 
 
261
        if (srv) {
 
262
                pgcd = srv->uweight; /* note: cannot be zero */
 
263
                while (pgcd > 1 && (srv = srv->next)) {
 
264
                        int w = srv->uweight;
 
265
                        while (w) {
 
266
                                int t = pgcd % w;
 
267
                                pgcd = w;
 
268
                                w = t;
 
269
                        }
259
270
                }
260
271
        }
261
272
 
280
291
        if (act < bck)
281
292
                act = bck;
282
293
 
 
294
        if (!act)
 
295
                act = 1;
 
296
 
283
297
        p->lbprm.map.srv = (struct server **)calloc(act, sizeof(struct server *));
284
298
        /* recounts servers and their weights */
285
299
        p->lbprm.map.state = PR_MAP_RECALC;
1812
1826
                if (s->srv->iface_name)
1813
1827
                        setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, s->srv->iface_name, s->srv->iface_len + 1);
1814
1828
#endif
1815
 
                ret = tcpv4_bind_socket(fd, flags, &s->srv->source_addr, remote);
 
1829
 
 
1830
                if (s->srv->sport_range) {
 
1831
                        int attempts = 10; /* should be more than enough to find a spare port */
 
1832
                        struct sockaddr_in src;
 
1833
 
 
1834
                        ret = 1;
 
1835
                        src = s->srv->source_addr;
 
1836
 
 
1837
                        do {
 
1838
                                /* note: in case of retry, we may have to release a previously
 
1839
                                 * allocated port, hence this loop's construct.
 
1840
                                 */
 
1841
                                port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
 
1842
                                fdtab[fd].port_range = NULL;
 
1843
 
 
1844
                                if (!attempts)
 
1845
                                        break;
 
1846
                                attempts--;
 
1847
 
 
1848
                                fdtab[fd].local_port = port_range_alloc_port(s->srv->sport_range);
 
1849
                                if (!fdtab[fd].local_port)
 
1850
                                        break;
 
1851
 
 
1852
                                fdtab[fd].port_range = s->srv->sport_range;
 
1853
                                src.sin_port = htons(fdtab[fd].local_port);
 
1854
 
 
1855
                                ret = tcpv4_bind_socket(fd, flags, &src, remote);
 
1856
                        } while (ret != 0); /* binding NOK */
 
1857
                }
 
1858
                else {
 
1859
                        ret = tcpv4_bind_socket(fd, flags, &s->srv->source_addr, remote);
 
1860
                }
 
1861
 
1816
1862
                if (ret) {
 
1863
                        port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
 
1864
                        fdtab[fd].port_range = NULL;
1817
1865
                        close(fd);
 
1866
 
1818
1867
                        if (ret == 1) {
1819
1868
                                Alert("Cannot bind to source address before connect() for server %s/%s. Aborting.\n",
1820
1869
                                      s->be->id, s->srv->id);
1887
1936
                                msg = "local address already in use";
1888
1937
 
1889
1938
                        qfprintf(stderr,"Cannot connect: %s.\n",msg);
 
1939
                        port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
 
1940
                        fdtab[fd].port_range = NULL;
1890
1941
                        close(fd);
1891
1942
                        send_log(s->be, LOG_EMERG,
1892
1943
                                 "Connect() failed for server %s/%s: %s.\n",
1894
1945
                        return SN_ERR_RESOURCE;
1895
1946
                } else if (errno == ETIMEDOUT) {
1896
1947
                        //qfprintf(stderr,"Connect(): ETIMEDOUT");
 
1948
                        port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
 
1949
                        fdtab[fd].port_range = NULL;
1897
1950
                        close(fd);
1898
1951
                        return SN_ERR_SRVTO;
1899
1952
                } else {
1900
1953
                        // (errno == ECONNREFUSED || errno == ENETUNREACH || errno == EACCES || errno == EPERM)
1901
1954
                        //qfprintf(stderr,"Connect(): %d", errno);
 
1955
                        port_range_release_port(fdtab[fd].port_range, fdtab[fd].local_port);
 
1956
                        fdtab[fd].port_range = NULL;
1902
1957
                        close(fd);
1903
1958
                        return SN_ERR_SRVCL;
1904
1959
                }
2194
2249
        test->i = 0;
2195
2250
        iterator = px->srv;
2196
2251
        while (iterator) {
2197
 
                if ((iterator->state & 1) == 0) {
 
2252
                if ((iterator->state & SRV_RUNNING) == 0) {
2198
2253
                        iterator = iterator->next;
2199
2254
                        continue;
2200
2255
                }
2249
2304
        return 1;
2250
2305
}
2251
2306
 
 
2307
/* set test->i to the number of concurrent connections on the frontend */
 
2308
static int
 
2309
acl_fetch_fe_conn(struct proxy *px, struct session *l4, void *l7, int dir,
 
2310
                  struct acl_expr *expr, struct acl_test *test)
 
2311
{
 
2312
        test->flags = ACL_TEST_F_VOL_TEST;
 
2313
        if (expr->arg_len) {
 
2314
                /* another proxy was designated, we must look for it */
 
2315
                for (px = proxy; px; px = px->next)
 
2316
                        if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->arg.str))
 
2317
                                break;
 
2318
        }
 
2319
        if (!px)
 
2320
                return 0;
 
2321
 
 
2322
        test->i = px->feconn;
 
2323
        return 1;
 
2324
}
 
2325
 
 
2326
/* set test->i to the number of concurrent connections on the backend */
 
2327
static int
 
2328
acl_fetch_be_conn(struct proxy *px, struct session *l4, void *l7, int dir,
 
2329
                  struct acl_expr *expr, struct acl_test *test)
 
2330
{
 
2331
        test->flags = ACL_TEST_F_VOL_TEST;
 
2332
        if (expr->arg_len) {
 
2333
                /* another proxy was designated, we must look for it */
 
2334
                for (px = proxy; px; px = px->next)
 
2335
                        if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
 
2336
                                break;
 
2337
        }
 
2338
        if (!px)
 
2339
                return 0;
 
2340
 
 
2341
        test->i = px->beconn;
 
2342
        return 1;
 
2343
}
 
2344
 
 
2345
/* set test->i to the total number of queued connections on the backend */
 
2346
static int
 
2347
acl_fetch_queue_size(struct proxy *px, struct session *l4, void *l7, int dir,
 
2348
                   struct acl_expr *expr, struct acl_test *test)
 
2349
{
 
2350
        test->flags = ACL_TEST_F_VOL_TEST;
 
2351
        if (expr->arg_len) {
 
2352
                /* another proxy was designated, we must look for it */
 
2353
                for (px = proxy; px; px = px->next)
 
2354
                        if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
 
2355
                                break;
 
2356
        }
 
2357
        if (!px)
 
2358
                return 0;
 
2359
 
 
2360
        test->i = px->totpend;
 
2361
        return 1;
 
2362
}
 
2363
 
 
2364
/* set test->i to the total number of queued connections on the backend divided
 
2365
 * by the number of running servers and rounded up. If there is no running
 
2366
 * server, we return twice the total, just as if we had half a running server.
 
2367
 * This is more or less correct anyway, since we expect the last server to come
 
2368
 * back soon.
 
2369
 */
 
2370
static int
 
2371
acl_fetch_avg_queue_size(struct proxy *px, struct session *l4, void *l7, int dir,
 
2372
                   struct acl_expr *expr, struct acl_test *test)
 
2373
{
 
2374
        int nbsrv;
 
2375
 
 
2376
        test->flags = ACL_TEST_F_VOL_TEST;
 
2377
        if (expr->arg_len) {
 
2378
                /* another proxy was designated, we must look for it */
 
2379
                for (px = proxy; px; px = px->next)
 
2380
                        if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
 
2381
                                break;
 
2382
        }
 
2383
        if (!px)
 
2384
                return 0;
 
2385
 
 
2386
        if (px->srv_act)
 
2387
                nbsrv = px->srv_act;
 
2388
        else if (px->lbprm.fbck)
 
2389
                nbsrv = 1;
 
2390
        else
 
2391
                nbsrv = px->srv_bck;
 
2392
 
 
2393
        if (nbsrv > 0)
 
2394
                test->i = (px->totpend + nbsrv - 1) / nbsrv;
 
2395
        else
 
2396
                test->i = px->totpend * 2;
 
2397
 
 
2398
        return 1;
 
2399
}
2252
2400
 
2253
2401
/* Note: must not be declared <const> as its list will be overwritten */
2254
2402
static struct acl_kw_list acl_kws = {{ },{
2256
2404
        { "connslots", acl_parse_int,   acl_fetch_connslots, acl_match_int, ACL_USE_NOTHING },
2257
2405
        { "fe_sess_rate", acl_parse_int, acl_fetch_fe_sess_rate, acl_match_int, ACL_USE_NOTHING },
2258
2406
        { "be_sess_rate", acl_parse_int, acl_fetch_be_sess_rate, acl_match_int, ACL_USE_NOTHING },
 
2407
        { "fe_conn", acl_parse_int, acl_fetch_fe_conn, acl_match_int, ACL_USE_NOTHING },
 
2408
        { "be_conn", acl_parse_int, acl_fetch_be_conn, acl_match_int, ACL_USE_NOTHING },
 
2409
        { "queue", acl_parse_int, acl_fetch_queue_size, acl_match_int, ACL_USE_NOTHING },
 
2410
        { "avg_queue", acl_parse_int, acl_fetch_avg_queue_size, acl_match_int, ACL_USE_NOTHING },
2259
2411
        { NULL, NULL, NULL, NULL },
2260
2412
}};
2261
2413