Coverage Report

Created: 2024-02-25 06:15

/src/h2o/lib/common/balancer/least_conn.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2017 Justin Zhu
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
5
 * of this software and associated documentation files (the "Software"), to
6
 * deal in the Software without restriction, including without limitation the
7
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8
 * sell copies of the Software, and to permit persons to whom the Software is
9
 * furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in
12
 * all copies or substantial portions of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
 * IN THE SOFTWARE.
21
 */
22
#include "h2o/balancer.h"
23
24
struct least_conn_t {
25
    h2o_balancer_t super;
26
    pthread_mutex_t mutex;
27
};
28
29
static size_t selector(h2o_balancer_t *_self, h2o_socketpool_target_vector_t *targets, char *tried)
30
0
{
31
0
    struct least_conn_t *self = (void *)_self;
32
0
    size_t i;
33
0
    size_t result_index = -1;
34
0
    size_t result_weight = 0;
35
0
    size_t result_leased = 1;
36
0
    uint64_t leftprod, rightprod;
37
38
0
    assert(targets->size != 0);
39
0
    pthread_mutex_lock(&self->mutex);
40
0
    for (i = 0; i < targets->size; i++) {
41
0
        leftprod = targets->entries[i]->_shared.leased_count;
42
0
        leftprod *= result_weight;
43
0
        rightprod = result_leased;
44
0
        rightprod *= ((unsigned)targets->entries[i]->conf.weight_m1) + 1;
45
0
        if (!tried[i] && leftprod < rightprod) {
46
0
            result_index = i;
47
0
            result_leased = targets->entries[i]->_shared.leased_count;
48
0
            result_weight = ((unsigned)targets->entries[i]->conf.weight_m1) + 1;
49
0
        }
50
0
    }
51
0
    pthread_mutex_unlock(&self->mutex);
52
53
0
    assert(result_index < targets->size);
54
0
    return result_index;
55
0
}
56
57
static void destroy(h2o_balancer_t *_self)
58
0
{
59
0
    struct least_conn_t *self = (void *)_self;
60
0
    pthread_mutex_destroy(&self->mutex);
61
0
    free(self);
62
0
}
63
64
h2o_balancer_t *h2o_balancer_create_lc(void)
65
0
{
66
0
    static const h2o_balancer_callbacks_t lc_callbacks = {selector, destroy};
67
0
    struct least_conn_t *self = h2o_mem_alloc(sizeof(*self));
68
0
    self->super.callbacks = &lc_callbacks;
69
0
    pthread_mutex_init(&self->mutex, NULL);
70
0
    return &self->super;
71
0
}