/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 | } |