Coverage Report

Created: 2026-03-22 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fluent-bit/src/flb_routes_mask.c
Line
Count
Source
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*  Fluent Bit
4
 *  ==========
5
 *  Copyright (C) 2015-2026 The Fluent Bit Authors
6
 *
7
 *  Licensed under the Apache License, Version 2.0 (the "License");
8
 *  you may not use this file except in compliance with the License.
9
 *  You may obtain a copy of the License at
10
 *
11
 *      http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 *  Unless required by applicable law or agreed to in writing, software
14
 *  distributed under the License is distributed on an "AS IS" BASIS,
15
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 *  See the License for the specific language governing permissions and
17
 *  limitations under the License.
18
 */
19
20
#include <fluent-bit/flb_info.h>
21
#include <fluent-bit/flb_log.h>
22
#include <fluent-bit/flb_input.h>
23
#include <fluent-bit/flb_router.h>
24
#include <fluent-bit/flb_routes_mask.h>
25
26
27
size_t flb_routes_mask_get_size(struct flb_router *router)
28
2
{
29
2
    if (router == NULL) {
30
0
        return 0;
31
0
    }
32
33
2
    return router->route_mask_size;
34
2
}
35
36
size_t flb_routes_mask_get_slots(struct flb_router *router)
37
46
{
38
46
    if (router == NULL) {
39
0
        return 0;
40
0
    }
41
42
46
    return router->route_mask_slots;
43
46
}
44
45
/*
46
 * Set the routes_mask for input chunk with a router_match on tag, return a
47
 * non-zero value if any routes matched
48
 */
49
int flb_routes_mask_set_by_tag(flb_route_mask_element *routes_mask,
50
                               const char *tag,
51
                               int tag_len,
52
                               struct flb_input_instance *in)
53
1
{
54
1
    int has_routes = 0;
55
1
    size_t size;
56
1
    struct mk_list *o_head;
57
1
    struct flb_output_instance *o_ins;
58
1
    if (!in) {
59
0
        return 0;
60
0
    }
61
62
1
    if (in->config == NULL || in->config->router == NULL) {
63
0
        return 0;
64
0
    }
65
66
    /* Clear the bit field */
67
1
    size = flb_routes_mask_get_size(in->config->router);
68
1
    memset(routes_mask, 0, sizeof(flb_route_mask_element) * size);
69
70
    /* Find all matching routes for the given tag */
71
1
    mk_list_foreach(o_head, &in->config->outputs) {
72
1
        o_ins = mk_list_entry(o_head,
73
1
                              struct flb_output_instance, _head);
74
75
1
        if (flb_router_match(tag, tag_len, o_ins->match
76
1
#ifdef FLB_HAVE_REGEX
77
1
                             , o_ins->match_regex
78
#else
79
                             , NULL
80
#endif
81
1
                             )) {
82
1
            flb_routes_mask_set_bit(routes_mask, o_ins->id, o_ins->config->router);
83
1
            has_routes = 1;
84
1
        }
85
1
    }
86
87
1
    return has_routes;
88
1
}
89
90
/*
91
 * Sets a single bit in an array of bitfields
92
 *
93
 * For example: Given a value of 35 this routine will set the
94
 * 4th bit in the 2nd value of the bitfield array.
95
 *
96
 */
97
void flb_routes_mask_set_bit(flb_route_mask_element *routes_mask, int value,
98
                             struct flb_router *router)
99
1
{
100
1
    int index;
101
1
    uint64_t bit;
102
103
1
    if (router == NULL) {
104
0
        return;
105
0
    }
106
107
1
    if (value < 0 || value >= router->route_mask_slots) {
108
0
        flb_warn("[routes_mask] Can't clear bit (%d) past limits of bitfield",
109
0
                 value);
110
0
        return;
111
0
    }
112
113
1
    index = value / FLB_ROUTES_MASK_ELEMENT_BITS;
114
1
    bit = 1ULL << (value % FLB_ROUTES_MASK_ELEMENT_BITS);
115
1
    routes_mask[index] |= bit;
116
1
}
117
118
/*
119
 * Clears a single bit in an array of bitfields
120
 *
121
 * For example: Given a value of 68 this routine will clear the
122
 * 4th bit in the 2nd value of the bitfield array.
123
 *
124
 */
125
void flb_routes_mask_clear_bit(flb_route_mask_element *routes_mask, int value,
126
                               struct flb_router *router)
127
0
{
128
0
    int index;
129
0
    uint64_t bit;
130
131
0
    if (router == NULL) {
132
0
        return;
133
0
    }
134
135
0
    if (value < 0 || value >= router->route_mask_slots) {
136
0
        flb_warn("[routes_mask] Can't set bit (%d) past limits of bitfield",
137
0
                 value);
138
0
        return;
139
0
    }
140
141
0
    index = value / FLB_ROUTES_MASK_ELEMENT_BITS;
142
0
    bit = 1ULL << (value % FLB_ROUTES_MASK_ELEMENT_BITS);
143
0
    routes_mask[index] &= ~(bit);
144
0
}
145
146
/*
147
 * Checks the value of a single bit in an array of bitfields and returns a
148
 * non-zero value if that bit is set.
149
 *
150
 * For example: Given a value of 68 this routine will return a non-zero value
151
 * if the 4th bit in the 2nd value of the bitfield array is set.
152
 *
153
 */
154
int flb_routes_mask_get_bit(flb_route_mask_element *routes_mask, int value,
155
                            struct flb_router *router)
156
4
{
157
4
    int index;
158
4
    uint64_t bit;
159
160
4
    if (router == NULL) {
161
0
        return 0;
162
0
    }
163
164
4
    if (value < 0 || value >= router->route_mask_slots) {
165
0
        flb_warn("[routes_mask] Can't get bit (%d) past limits of bitfield",
166
0
                 value);
167
0
        return 0;
168
0
    }
169
170
4
    index = value / FLB_ROUTES_MASK_ELEMENT_BITS;
171
4
    bit = 1ULL << (value % FLB_ROUTES_MASK_ELEMENT_BITS);
172
4
    return (routes_mask[index] & bit) != 0ULL;
173
4
}
174
175
int flb_routes_mask_is_empty(flb_route_mask_element *routes_mask,
176
                             struct flb_router *router)
177
2
{
178
2
    if (router == NULL || router->route_empty_mask == NULL) {
179
0
        return 0;
180
0
    }
181
182
2
    return memcmp(routes_mask,
183
2
                  router->route_empty_mask,
184
2
                  router->route_mask_size * sizeof(flb_route_mask_element)) == 0;
185
2
}
186
187
int flb_routes_empty_mask_create(struct flb_router *router)
188
89.7k
{
189
89.7k
    if (router == NULL) {
190
0
        return -1;
191
0
    }
192
193
89.7k
    flb_routes_empty_mask_destroy(router);
194
195
89.7k
    router->route_empty_mask = flb_calloc(router->route_mask_size,
196
89.7k
                                          sizeof(flb_route_mask_element));
197
198
89.7k
    if (router->route_empty_mask == NULL) {
199
13
        return -1;
200
13
    }
201
202
89.7k
    return 0;
203
89.7k
}
204
205
void flb_routes_empty_mask_destroy(struct flb_router *router)
206
177k
{
207
177k
    if (router == NULL) {
208
0
        return;
209
0
    }
210
211
177k
    if (router->route_empty_mask != NULL) {
212
89.7k
        flb_free(router->route_empty_mask);
213
214
89.7k
        router->route_empty_mask = NULL;
215
89.7k
    }
216
177k
}
217
218
int flb_routes_mask_set_size(size_t mask_size, struct flb_router *router)
219
89.7k
{
220
89.7k
    if (router == NULL) {
221
0
        return -1;
222
0
    }
223
224
89.7k
    if (mask_size < 1) {
225
0
        mask_size = 1;
226
0
    }
227
228
89.7k
    mask_size = (mask_size + FLB_ROUTES_MASK_ELEMENT_BITS - 1) /
229
89.7k
                FLB_ROUTES_MASK_ELEMENT_BITS;
230
231
89.7k
    router->route_mask_size = mask_size;
232
89.7k
    router->route_mask_slots = mask_size * FLB_ROUTES_MASK_ELEMENT_BITS;
233
234
89.7k
    return flb_routes_empty_mask_create(router);
235
89.7k
}