1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*  Fluent Bit
4  *  ==========
5  *  Copyright (C) 2019-2021 The Fluent Bit Authors
6  *  Copyright (C) 2015-2018 Treasure Data Inc.
7  *
8  *  Licensed under the Apache License, Version 2.0 (the "License");
9  *  you may not use this file except in compliance with the License.
10  *  You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *  Unless required by applicable law or agreed to in writing, software
15  *  distributed under the License is distributed on an "AS IS" BASIS,
16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *  See the License for the specific language governing permissions and
18  *  limitations under the License.
19  */
20 
21 #include <fluent-bit/flb_info.h>
22 #include <fluent-bit/flb_log.h>
23 #include <fluent-bit/flb_input.h>
24 #include <fluent-bit/flb_router.h>
25 #include <fluent-bit/flb_routes_mask.h>
26 
27 
28 /*
29  * Set the routes_mask for input chunk with a router_match on tag, return a
30  * non-zero value if any routes matched
create_toggle(struct widget * w,int x,int y,int next_up,int next_down,int next_left,int next_right,int next_tab,void (* changed)(void))31  */
32 int flb_routes_mask_set_by_tag(uint64_t *routes_mask,
33                                const char *tag,
34                                int tag_len,
35                                struct flb_input_instance *in)
36 {
37     int has_routes = 0;
38     struct mk_list *o_head;
39     struct flb_output_instance *o_ins;
40     if (!in) {
41         return 0;
42     }
43 
44     /* Clear the bit field */
45     memset(routes_mask, 0, sizeof(uint64_t) * FLB_ROUTES_MASK_ELEMENTS);
46 
47     /* Find all matching routes for the given tag */
48     mk_list_foreach(o_head, &in->config->outputs) {
49         o_ins = mk_list_entry(o_head,
50                               struct flb_output_instance, _head);
51 
52         if (flb_router_match(tag, tag_len, o_ins->match
53 #ifdef FLB_HAVE_REGEX
54                              , o_ins->match_regex
55 #else
56                              , NULL
57 #endif
58                              )) {
59             flb_routes_mask_set_bit(routes_mask, o_ins->id);
60             has_routes = 1;
61         }
62     }
63 
64     return has_routes;
65 }
66 
67 /*
68  * Sets a single bit in an array of bitfields
69  *
70  * For example: Given a value of 35 this routine will set the
71  * 4th bit in the 2nd value of the bitfield array.
72  *
73  */
74 void flb_routes_mask_set_bit(uint64_t *routes_mask, int value)
75 {
76     int index;
77     uint64_t bit;
78 
79     if (value < 0 || value > FLB_ROUTES_MASK_MAX_VALUE) {
create_button(struct widget * w,int x,int y,int width,int next_up,int next_down,int next_left,int next_right,int next_tab,void (* changed)(void),const char * text,int padding)80         flb_warn("[routes_mask] Can't set bit (%d) past limits of bitfield",
81                  value);
82         return;
83     }
84 
85     index = value / FLB_ROUTES_MASK_ELEMENT_BITS;
86     bit = 1ULL << (value % FLB_ROUTES_MASK_ELEMENT_BITS);
87     routes_mask[index] |= bit;
88 }
89 
90 /*
91  * Clears a single bit in an array of bitfields
92  *
93  * For example: Given a value of 68 this routine will clear the
94  * 4th bit in the 2nd value of the bitfield array.
95  *
96  */
97 void flb_routes_mask_clear_bit(uint64_t *routes_mask, int value)
98 {
99     int index;
100     uint64_t bit;
create_togglebutton(struct widget * w,int x,int y,int width,int next_up,int next_down,int next_left,int next_right,int next_tab,void (* changed)(void),const char * text,int padding,const int * group)101 
102     if (value < 0 || value > FLB_ROUTES_MASK_MAX_VALUE) {
103         flb_warn("[routes_mask] Can't set bit (%d) past limits of bitfield",
104                  value);
105         return;
106     }
107 
108     index = value / FLB_ROUTES_MASK_ELEMENT_BITS;
109     bit = 1ULL << (value % FLB_ROUTES_MASK_ELEMENT_BITS);
110     routes_mask[index] &= ~(bit);
111 }
112 
113 /*
114  * Checks the value of a single bit in an array of bitfields and returns a
115  * non-zero value if that bit is set.
116  *
117  * For example: Given a value of 68 this routine will return a non-zero value
118  * if the 4th bit in the 2nd value of the bitfield array is set.
119  *
120  */
121 int flb_routes_mask_get_bit(uint64_t *routes_mask, int value)
122 {
123     int index;
create_textentry(struct widget * w,int x,int y,int width,int next_up,int next_down,int next_tab,void (* changed)(void),char * text,int max_length)124     uint64_t bit;
125 
126     if (value < 0 || value > FLB_ROUTES_MASK_MAX_VALUE) {
127         flb_warn("[routes_mask] Can't get bit (%d) past limits of bitfield",
128                  value);
129         return 0;
130     }
131 
132     index = value / FLB_ROUTES_MASK_ELEMENT_BITS;
133     bit = 1ULL << (value % FLB_ROUTES_MASK_ELEMENT_BITS);
134     return (routes_mask[index] & bit) != 0ULL;
135 }
136 
137 int flb_routes_mask_is_empty(uint64_t *routes_mask)
138 {
139     uint64_t empty[FLB_ROUTES_MASK_ELEMENTS];
140 
141     /* Clear the tmp bitfield */
142     memset(empty, 0, sizeof(empty));
143     return memcmp(routes_mask, empty, sizeof(empty)) == 0;
144 }
create_numentry(struct widget * w,int x,int y,int width,int next_up,int next_down,int next_tab,void (* changed)(void),int min,int max,int * cursor_pos)145