Coverage Report

Created: 2023-11-19 07:36

/src/fluent-bit/src/flb_record_accessor.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*  Fluent Bit
4
 *  ==========
5
 *  Copyright (C) 2015-2022 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_mem.h>
22
#include <fluent-bit/flb_env.h>
23
#include <fluent-bit/flb_log.h>
24
#include <fluent-bit/flb_pack.h>
25
#include <fluent-bit/flb_sds.h>
26
#include <fluent-bit/flb_sds_list.h>
27
#include <fluent-bit/flb_record_accessor.h>
28
#include <fluent-bit/flb_ra_key.h>
29
#include <fluent-bit/record_accessor/flb_ra_parser.h>
30
#include <monkey/mk_core.h>
31
#include <msgpack.h>
32
33
#include <ctype.h>
34
35
static struct flb_ra_parser *ra_parse_string(struct flb_record_accessor *ra,
36
                                             flb_sds_t buf, int start, int end)
37
163k
{
38
163k
    int len;
39
163k
    struct flb_ra_parser *rp;
40
41
163k
    len = end - start;
42
163k
    rp = flb_ra_parser_string_create(buf + start, len);
43
163k
    if (!rp) {
44
9
        return NULL;
45
9
    }
46
47
163k
    return rp;
48
163k
}
49
50
/* Create a parser context for a key map or function definition */
51
static struct flb_ra_parser *ra_parse_meta(struct flb_record_accessor *ra,
52
                                           flb_sds_t buf, int start, int end)
53
161k
{
54
161k
    int len;
55
161k
    struct flb_ra_parser *rp;
56
57
161k
    len = end - start;
58
161k
    rp = flb_ra_parser_meta_create(buf + start, len);
59
161k
    if (!rp) {
60
221
        return NULL;
61
221
    }
62
63
161k
    return rp;
64
161k
}
65
66
/*
67
 * Supported data
68
 *
69
 * ${X}                               => environment variable
70
 * $key, $key['x'], $key['x'][N]['z'] => record key value or array index
71
 * $0, $1,..$9                        => regex id
72
 * $X()                               => built-in function
73
 */
74
static int ra_parse_buffer(struct flb_record_accessor *ra, flb_sds_t buf)
75
1.98k
{
76
1.98k
    int i;
77
1.98k
    int n;
78
1.98k
    int c;
79
1.98k
    int t;
80
1.98k
    int len;
81
1.98k
    int pre = 0;
82
1.98k
    int end = 0;
83
1.98k
    int quote_cnt;
84
1.98k
    struct flb_ra_parser *rp;
85
1.98k
    struct flb_ra_parser *rp_str = NULL;
86
87
1.98k
    len = flb_sds_len(buf);
88
89
573k
    for (i = 0; i < len; i++) {
90
571k
        if (buf[i] != '$') {
91
406k
            continue;
92
406k
        }
93
94
        /*
95
         * Before to add the number entry, add the previous text
96
         * before hitting this.
97
         */
98
164k
        if (i > pre) {
99
162k
            rp = ra_parse_string(ra, buf, pre, i);
100
162k
            if (!rp) {
101
6
                return -1;
102
6
            }
103
162k
            mk_list_add(&rp->_head, &ra->list);
104
162k
        }
105
164k
        pre = i;
106
107
108
164k
        n = i + 1;
109
164k
        if (n >= len) {
110
            /* Finalize, nothing to do */
111
69
            break;
112
69
        }
113
114
        /*
115
         * If the next character is a digit like $0,$1,$2..$9, means the user wants to use
116
         * the result of a regex capture.
117
         *
118
         * We support up to 10 regex ids [0-9]
119
         */
120
164k
        if (isdigit(buf[n])) {
121
            /* Add REGEX_ID entry */
122
1.84k
            c = atoi(buf + n);
123
1.84k
            rp = flb_ra_parser_regex_id_create(c);
124
1.84k
            if (!rp) {
125
1
                return -1;
126
1
            }
127
128
1.84k
            mk_list_add(&rp->_head, &ra->list);
129
1.84k
            i++;
130
1.84k
            pre = i + 1;
131
1.84k
            continue;
132
1.84k
        }
133
134
        /*
135
         * If the next 3 character are 'TAG', the user might want to include the tag or
136
         * part of it (e.g: TAG[n]).
137
         */
138
163k
        if (n + 2 < len && strncmp(buf + n, "TAG", 3) == 0) {
139
            /* Check if some [] was added */
140
1.63k
            if (n + 4 < len) {
141
1.60k
                end = -1;
142
1.60k
                if (buf[n + 3] == '[') {
143
1.18k
                    t = n + 3;
144
145
                    /* Look for the ending ']' */
146
1.18k
                    end = mk_string_char_search(buf + t, ']', len - t);
147
1.18k
                    if (end == 0) {
148
0
                        end = -1;
149
0
                    }
150
151
                    /* continue processsing */
152
1.18k
                    c = atoi(buf + t + 1);
153
154
1.18k
                    rp = flb_ra_parser_tag_part_create(c);
155
1.18k
                    if (!rp) {
156
1
                        return -1;
157
1
                    }
158
1.18k
                    mk_list_add(&rp->_head, &ra->list);
159
160
1.18k
                    i = t + end + 1;
161
1.18k
                    pre = i;
162
1.18k
                    continue;
163
1.18k
                }
164
1.60k
            }
165
166
            /* Append full tag */
167
451
            rp = flb_ra_parser_tag_create();
168
451
            if (!rp) {
169
1
                return -1;
170
1
            }
171
450
            mk_list_add(&rp->_head, &ra->list);
172
450
            i = n + 3;
173
450
            pre = n + 3;
174
450
            continue;
175
451
        }
176
177
161k
        quote_cnt = 0;
178
1.28M
        for (end = i + 1; end < len; end++) {
179
1.28M
            if (buf[end] == '\'') {
180
14.7k
              ++quote_cnt;
181
14.7k
            }
182
1.26M
            else if (buf[end] == '.' && (quote_cnt & 0x01)) {
183
                /* ignore '.' if it is inside a string/subkey */
184
1.72k
                continue;
185
1.72k
            }
186
1.26M
            else if (buf[end] == '.' || buf[end] == ' ' || buf[end] == ',' || buf[end] == '"') {
187
160k
                break;
188
160k
            }
189
1.28M
        }
190
161k
        if (end > len) {
191
0
            end = len;
192
0
        }
193
194
        /* Parse the content, we use 'end' as the separator position  */
195
161k
        rp = ra_parse_meta(ra, buf, i, end);
196
161k
        if (!rp) {
197
221
            return -1;
198
221
        }
199
200
        /* Generate fixed length string */
201
161k
        if (pre < i) {
202
0
            rp_str = ra_parse_string(ra, buf, pre, i);
203
0
            if (!rp_str) {
204
0
                flb_ra_parser_destroy(rp);
205
0
                return -1;
206
0
            }
207
0
        }
208
161k
        else {
209
161k
            rp_str = NULL;
210
161k
        }
211
212
161k
        if (rp_str) {
213
0
            mk_list_add(&rp_str->_head, &ra->list);
214
0
        }
215
161k
        mk_list_add(&rp->_head, &ra->list);
216
161k
        pre = end;
217
161k
        i = end;
218
161k
    }
219
220
    /* Append remaining string */
221
1.75k
    if ((i - 1 > end && pre < i) || i == 1 /*allow single character*/) {
222
702
        end = flb_sds_len(buf);
223
702
        rp_str = ra_parse_string(ra, buf, pre, end);
224
702
        if (rp_str) {
225
699
            mk_list_add(&rp_str->_head, &ra->list);
226
699
        }
227
702
    }
228
229
1.75k
    return 0;
230
1.98k
}
231
232
void flb_ra_destroy(struct flb_record_accessor *ra)
233
1.98k
{
234
1.98k
    struct mk_list *tmp;
235
1.98k
    struct mk_list *head;
236
1.98k
    struct flb_ra_parser *rp;
237
238
328k
    mk_list_foreach_safe(head, tmp, &ra->list) {
239
328k
        rp = mk_list_entry(head, struct flb_ra_parser, _head);
240
328k
        mk_list_del(&rp->_head);
241
328k
        flb_ra_parser_destroy(rp);
242
328k
    }
243
244
1.98k
    if (ra->pattern) {
245
1.98k
        flb_sds_destroy(ra->pattern);
246
1.98k
    }
247
1.98k
    flb_free(ra);
248
1.98k
}
249
250
int flb_ra_subkey_count(struct flb_record_accessor *ra)
251
0
{
252
0
    struct mk_list *head;
253
0
    struct flb_ra_parser *rp;
254
0
    int ret = -1;
255
0
    int tmp;
256
257
0
    if (ra == NULL) {
258
0
        return -1;
259
0
    }
260
0
    mk_list_foreach(head, &ra->list) {
261
0
        rp = mk_list_entry(head, struct flb_ra_parser, _head);
262
0
        tmp = flb_ra_parser_subkey_count(rp);
263
0
        if (tmp > ret) {
264
0
            ret = tmp;
265
0
        }
266
0
    }
267
268
0
    return ret;
269
0
}
270
271
struct flb_record_accessor *flb_ra_create(char *str, int translate_env)
272
1.99k
{
273
1.99k
    int ret;
274
1.99k
    size_t hint = 0;
275
1.99k
    char *p;
276
1.99k
    flb_sds_t buf = NULL;
277
1.99k
    struct flb_env *env;
278
1.99k
    struct mk_list *head;
279
1.99k
    struct flb_ra_parser *rp;
280
1.99k
    struct flb_record_accessor *ra;
281
282
1.99k
    p = str;
283
1.99k
    if (translate_env == FLB_TRUE) {
284
        /*
285
         * Check if some environment variable has been created as part of the
286
         * string. Upon running the environment variable will be pre-set in the
287
         * string.
288
         */
289
0
        env = flb_env_create();
290
0
        if (!env) {
291
0
            flb_error("[record accessor] cannot create environment context");
292
0
            return NULL;
293
0
        }
294
295
        /* Translate string */
296
0
        buf = flb_env_var_translate(env, str);
297
0
        if (!buf) {
298
0
            flb_error("[record accessor] cannot translate string");
299
0
            flb_env_destroy(env);
300
0
            return NULL;
301
0
        }
302
0
        flb_env_destroy(env);
303
0
        p = buf;
304
0
    }
305
306
    /* Allocate context */
307
1.99k
    ra = flb_calloc(1, sizeof(struct flb_record_accessor));
308
1.99k
    if (!ra) {
309
4
        flb_errno();
310
4
        flb_error("[record accessor] cannot create context");
311
4
        if (buf) {
312
0
            flb_sds_destroy(buf);
313
0
        }
314
4
        return NULL;
315
4
    }
316
1.98k
    ra->pattern = flb_sds_create(str);
317
1.98k
    if (!ra->pattern) {
318
2
        flb_error("[record accessor] could not allocate pattern");
319
2
        flb_free(ra);
320
2
        if (buf) {
321
0
            flb_sds_destroy(buf);
322
0
        }
323
2
        return NULL;
324
2
    }
325
326
1.98k
    mk_list_init(&ra->list);
327
328
    /*
329
     * The buffer needs to processed where we create a list of parts, basically
330
     * a linked list of sds using 'slist' api.
331
     */
332
1.98k
    ret = ra_parse_buffer(ra, p);
333
1.98k
    if (buf) {
334
0
        flb_sds_destroy(buf);
335
0
    }
336
1.98k
    if (ret == -1) {
337
230
        flb_ra_destroy(ra);
338
230
        return NULL;
339
230
    }
340
341
    /* Calculate a hint of an outgoing size buffer */
342
297k
    mk_list_foreach(head, &ra->list) {
343
297k
        rp = mk_list_entry(head, struct flb_ra_parser, _head);
344
297k
        if (rp->key) {
345
292k
            if (rp->type == FLB_RA_PARSER_REGEX_ID) {
346
0
                hint += 32;
347
0
            }
348
292k
            else {
349
292k
                hint += flb_sds_len(rp->key->name);
350
292k
            }
351
292k
        }
352
297k
    }
353
1.75k
    ra->size_hint = hint + 128;
354
1.75k
    return ra;
355
1.98k
}
356
357
/*
358
    flb_ra_create_str_from_list returns record accessor string from string list.
359
     e.g. {"aa", "bb", "cc", NULL} -> "$aa['bb']['cc']"
360
    Return value should be freed using flb_sds_destroy after using.
361
 */
362
flb_sds_t flb_ra_create_str_from_list(struct flb_sds_list *str_list)
363
0
{
364
0
    int i = 0;
365
0
    int ret_i = 0;
366
0
    int offset = 0;
367
368
0
    char *fmt = NULL;
369
0
    char **strs = NULL;
370
0
    flb_sds_t str;
371
0
    flb_sds_t tmp_sds;
372
373
0
    if (str_list == NULL || flb_sds_list_size(str_list) == 0) {
374
0
        return NULL;
375
0
    }
376
377
0
    str = flb_sds_create_size(256);
378
0
    if (str == NULL) {
379
0
        flb_errno();
380
0
        return NULL;
381
0
    }
382
383
0
    strs = flb_sds_list_create_str_array(str_list);
384
0
    if (strs == NULL) {
385
0
        flb_error("%s flb_sds_list_create_str_array failed", __FUNCTION__);
386
0
        return NULL;
387
0
    }
388
389
0
    while(strs[i] != NULL) {
390
0
        if (i == 0) {
391
0
            fmt = "$%s";
392
0
        }
393
0
        else {
394
0
            fmt = "['%s']";
395
0
        }
396
397
0
        ret_i = snprintf(str+offset, flb_sds_alloc(str)-offset-1, fmt, strs[i]);
398
0
        if (ret_i > flb_sds_alloc(str)-offset-1) {
399
0
            tmp_sds = flb_sds_increase(str, ret_i);
400
0
            if (tmp_sds == NULL) {
401
0
                flb_errno();
402
0
                flb_sds_list_destroy_str_array(strs);
403
0
                flb_sds_destroy(str);
404
0
                return NULL;
405
0
            }
406
0
            str = tmp_sds;
407
0
            ret_i = snprintf(str+offset, flb_sds_alloc(str)-offset-1, fmt, strs[i]);
408
0
            if (ret_i > flb_sds_alloc(str)-offset-1) {
409
0
                flb_errno();
410
0
                flb_sds_list_destroy_str_array(strs);
411
0
                flb_sds_destroy(str);
412
0
                return NULL;
413
0
            }
414
0
        }
415
0
        offset += ret_i;
416
0
        i++;
417
0
    }
418
0
    flb_sds_list_destroy_str_array(strs);
419
420
0
    return str;
421
0
}
422
423
struct flb_record_accessor *flb_ra_create_from_list(struct flb_sds_list *str_list, int translate_env)
424
0
{
425
0
    flb_sds_t tmp = NULL;
426
0
    struct flb_record_accessor *ret = NULL;
427
428
0
    tmp = flb_ra_create_str_from_list(str_list);
429
0
    if (tmp == NULL) {
430
0
        flb_errno();
431
0
        return NULL;
432
0
    }
433
434
0
    ret = flb_ra_create(tmp, translate_env);
435
0
    flb_sds_destroy(tmp);
436
437
0
    return ret;
438
0
}
439
440
void flb_ra_dump(struct flb_record_accessor *ra)
441
1.69k
{
442
1.69k
    struct mk_list *head;
443
1.69k
    struct flb_ra_parser *rp;
444
445
294k
    mk_list_foreach(head, &ra->list) {
446
294k
        rp = mk_list_entry(head, struct flb_ra_parser, _head);
447
294k
        printf("\n");
448
294k
        flb_ra_parser_dump(rp);
449
294k
    }
450
1.69k
}
451
452
static flb_sds_t ra_translate_regex_id(struct flb_ra_parser *rp,
453
                                       struct flb_regex_search *result,
454
                                       flb_sds_t buf)
455
0
{
456
0
    int ret;
457
0
    ptrdiff_t start;
458
0
    ptrdiff_t end;
459
0
    flb_sds_t tmp;
460
461
0
    ret = flb_regex_results_get(result, rp->id, &start, &end);
462
0
    if (ret == -1) {
463
0
        return buf;
464
0
    }
465
466
0
    tmp = flb_sds_cat(buf, result->str + start, end - start);
467
0
    return tmp;
468
0
}
469
470
static flb_sds_t ra_translate_tag(struct flb_ra_parser *rp, flb_sds_t buf,
471
                                  char *tag, int tag_len)
472
0
{
473
0
    flb_sds_t tmp;
474
475
0
    tmp = flb_sds_cat(buf, tag, tag_len);
476
0
    return tmp;
477
0
}
478
479
static flb_sds_t ra_translate_tag_part(struct flb_ra_parser *rp, flb_sds_t buf,
480
                                       char *tag, int tag_len)
481
0
{
482
0
    int i = 0;
483
0
    int id = -1;
484
0
    int end;
485
0
    flb_sds_t tmp = buf;
486
487
0
    while (i < tag_len) {
488
0
        end = mk_string_char_search(tag + i, '.', tag_len - i);
489
0
        if (end == -1) {
490
0
            if (i == 0) {
491
0
                break;
492
0
            }
493
0
            end = tag_len - i;
494
0
        }
495
0
        id++;
496
0
        if (rp->id == id) {
497
0
            tmp = flb_sds_cat(buf, tag + i, end);
498
0
            break;
499
0
        }
500
501
0
        i += end + 1;
502
0
    }
503
504
    /* No dots in the tag */
505
0
    if (rp->id == 0 && id == -1 && i < tag_len) {
506
0
        tmp = flb_sds_cat(buf, tag, tag_len);
507
0
        return tmp;
508
0
    }
509
510
0
    return tmp;
511
0
}
512
513
static flb_sds_t ra_translate_string(struct flb_ra_parser *rp, flb_sds_t buf)
514
146k
{
515
146k
    flb_sds_t tmp;
516
517
146k
    tmp = flb_sds_cat(buf, rp->key->name, flb_sds_len(rp->key->name));
518
146k
    return tmp;
519
146k
}
520
521
static flb_sds_t ra_translate_keymap(struct flb_ra_parser *rp, flb_sds_t buf,
522
                                     msgpack_object map, int *found)
523
145k
{
524
145k
    int len;
525
145k
    char *js;
526
145k
    char str[32];
527
145k
    flb_sds_t tmp = NULL;
528
145k
    struct flb_ra_value *v;
529
530
    /* Lookup key or subkey value */
531
145k
    if (rp->key == NULL) {
532
751
      *found = FLB_FALSE;
533
751
      return buf;
534
751
    }
535
536
144k
    v = flb_ra_key_to_value(rp->key->name, map, rp->key->subkeys);
537
144k
    if (!v) {
538
16.1k
        *found = FLB_FALSE;
539
16.1k
        return buf;
540
16.1k
    }
541
128k
    else {
542
128k
        *found = FLB_TRUE;
543
128k
    }
544
545
    /* Based on data type, convert to it string representation */
546
128k
    if (v->type == FLB_RA_BOOL) {
547
        /* Check if is a map or a real bool */
548
47.1k
        if (v->o.type == MSGPACK_OBJECT_MAP) {
549
            /* Convert msgpack map to JSON string */
550
46.4k
            js = flb_msgpack_to_json_str(1024, &v->o);
551
46.4k
            if (js) {
552
46.4k
                len = strlen(js);
553
46.4k
                tmp = flb_sds_cat(buf, js, len);
554
46.4k
                flb_free(js);
555
46.4k
            }
556
46.4k
        }
557
686
        else if (v->o.type == MSGPACK_OBJECT_BOOLEAN) {
558
686
            if (v->val.boolean) {
559
250
                tmp = flb_sds_cat(buf, "true", 4);
560
250
            }
561
436
            else {
562
436
                tmp = flb_sds_cat(buf, "false", 5);
563
436
            }
564
686
        }
565
47.1k
    }
566
81.2k
    else if (v->type == FLB_RA_INT) {
567
13.3k
        len = snprintf(str, sizeof(str) - 1, "%" PRId64, v->val.i64);
568
13.3k
        tmp = flb_sds_cat(buf, str, len);
569
13.3k
    }
570
67.9k
    else if (v->type == FLB_RA_FLOAT) {
571
1.75k
        len = snprintf(str, sizeof(str) - 1, "%f", v->val.f64);
572
1.75k
        if (len >= sizeof(str)) {
573
194
            tmp = flb_sds_cat(buf, str, sizeof(str)-1);
574
194
        }
575
1.56k
        else {
576
1.56k
            tmp = flb_sds_cat(buf, str, len);
577
1.56k
        }
578
1.75k
    }
579
66.1k
    else if (v->type == FLB_RA_STRING) {
580
65.1k
        tmp = flb_sds_cat(buf, v->val.string, flb_sds_len(v->val.string));
581
65.1k
    }
582
985
    else if (v->type == FLB_RA_NULL) {
583
985
        tmp = flb_sds_cat(buf, "null", 4);
584
985
    }
585
586
128k
    flb_ra_key_value_destroy(v);
587
128k
    return tmp;
588
144k
}
589
590
/*
591
 * Translate a record accessor buffer, tag and records are optional
592
 * parameters.
593
 *
594
 * For safety, the function returns a newly created string that needs
595
 * to be destroyed by the caller.
596
 */
597
flb_sds_t flb_ra_translate(struct flb_record_accessor *ra,
598
                           char *tag, int tag_len,
599
                           msgpack_object map, struct flb_regex_search *result)
600
1.75k
{
601
1.75k
    return flb_ra_translate_check(ra, tag, tag_len, map, result, FLB_FALSE);
602
1.75k
}
603
604
/*
605
 * Translate a record accessor buffer, tag and records are optional
606
 * parameters.
607
 *
608
 * For safety, the function returns a newly created string that needs
609
 * to be destroyed by the caller.
610
 * 
611
 * Returns NULL if `check` is FLB_TRUE and any key lookup in the record failed
612
 */
613
flb_sds_t flb_ra_translate_check(struct flb_record_accessor *ra,
614
                                 char *tag, int tag_len,
615
                                 msgpack_object map, struct flb_regex_search *result,
616
                                 int check)
617
1.75k
{
618
1.75k
    flb_sds_t tmp = NULL;
619
1.75k
    flb_sds_t buf;
620
1.75k
    struct mk_list *head;
621
1.75k
    struct flb_ra_parser *rp;
622
1.75k
    int found = FLB_FALSE;
623
624
1.75k
    buf = flb_sds_create_size(ra->size_hint);
625
1.75k
    if (!buf) {
626
5
        flb_error("[record accessor] cannot create outgoing buffer");
627
5
        return NULL;
628
5
    }
629
630
294k
    mk_list_foreach(head, &ra->list) {
631
294k
        rp = mk_list_entry(head, struct flb_ra_parser, _head);
632
294k
        if (rp->type == FLB_RA_PARSER_STRING) {
633
146k
            tmp = ra_translate_string(rp, buf);
634
146k
        }
635
147k
        else if (rp->type == FLB_RA_PARSER_KEYMAP) {
636
145k
            tmp = ra_translate_keymap(rp, buf, map, &found);
637
145k
            if (check == FLB_TRUE && found == FLB_FALSE) {
638
0
                flb_warn("[record accessor] translation failed, root key=%s", rp->key->name);
639
0
                flb_sds_destroy(buf);
640
0
                return NULL;
641
0
            }
642
145k
        }
643
2.48k
        else if (rp->type == FLB_RA_PARSER_REGEX_ID && result) {
644
0
            tmp = ra_translate_regex_id(rp, result, buf);
645
0
        }
646
2.48k
        else if (rp->type == FLB_RA_PARSER_TAG && tag) {
647
0
            tmp = ra_translate_tag(rp, buf, tag, tag_len);
648
0
        }
649
2.48k
        else if (rp->type == FLB_RA_PARSER_TAG_PART && tag) {
650
0
            tmp = ra_translate_tag_part(rp, buf, tag, tag_len);
651
0
        }
652
653
        //else if (rp->type == FLB_RA_PARSER_FUNC) {
654
            //tmp = ra_translate_func(rp, buf, tag, tag_len);
655
        //}
656
657
294k
        if (!tmp) {
658
52
            flb_error("[record accessor] translation failed");
659
52
            flb_sds_destroy(buf);
660
52
            return NULL;
661
52
        }
662
294k
        if (tmp != buf) {
663
271
            buf = tmp;
664
271
        }
665
294k
    }
666
667
1.69k
    return buf;
668
1.75k
}
669
670
/*
671
 * If the record accessor rules do not generate content based on a keymap or
672
 * regex, it's considered to be 'static', so the value returned will always be
673
 * the same.
674
 *
675
 * If the 'ra' is static, return FLB_TRUE, otherwise FLB_FALSE.
676
 */
677
int flb_ra_is_static(struct flb_record_accessor *ra)
678
1.75k
{
679
1.75k
    struct mk_list *head;
680
1.75k
    struct flb_ra_parser *rp;
681
682
5.35k
    mk_list_foreach(head, &ra->list) {
683
5.35k
        rp = mk_list_entry(head, struct flb_ra_parser, _head);
684
5.35k
        if (rp->type == FLB_RA_PARSER_STRING) {
685
2.66k
            continue;
686
2.66k
        }
687
2.68k
        else if (rp->type == FLB_RA_PARSER_KEYMAP) {
688
1.17k
            return FLB_FALSE;
689
1.17k
        }
690
1.51k
        else if (rp->type == FLB_RA_PARSER_REGEX_ID) {
691
29
            return FLB_FALSE;
692
29
        }
693
1.48k
        else if (rp->type == FLB_RA_PARSER_TAG) {
694
398
            continue;
695
398
        }
696
1.08k
        else if (rp->type == FLB_RA_PARSER_TAG_PART) {
697
1.08k
            continue;
698
1.08k
        }
699
5.35k
    }
700
701
552
    return FLB_TRUE;
702
1.75k
}
703
704
/*
705
 * Compare a string value against the first entry of a record accessor component, used
706
 * specifically when the record accessor refers to a single key name.
707
 */
708
int flb_ra_strcmp(struct flb_record_accessor *ra, msgpack_object map,
709
                  char *str, int len)
710
0
{
711
0
    struct flb_ra_parser *rp;
712
713
0
    rp = mk_list_entry_first(&ra->list, struct flb_ra_parser, _head);
714
0
    return flb_ra_key_strcmp(rp->key->name, map, rp->key->subkeys,
715
0
                             rp->key->name, flb_sds_len(rp->key->name));
716
0
}
717
718
/*
719
 * Check if a regular expression matches a record accessor key in the
720
 * given map
721
 */
722
int flb_ra_regex_match(struct flb_record_accessor *ra, msgpack_object map,
723
                       struct flb_regex *regex, struct flb_regex_search *result)
724
0
{
725
0
    struct flb_ra_parser *rp;
726
727
0
    rp = mk_list_entry_first(&ra->list, struct flb_ra_parser, _head);
728
0
    if (rp == NULL || rp->key == NULL) {
729
0
        return -1;
730
0
    }
731
0
    return flb_ra_key_regex_match(rp->key->name, map, rp->key->subkeys,
732
0
                                  regex, result);
733
0
}
734
735
736
static struct flb_ra_parser* get_ra_parser(struct flb_record_accessor *ra)
737
0
{
738
0
    struct flb_ra_parser *rp = NULL;
739
740
0
    if (mk_list_size(&ra->list) == 0) {
741
0
        return NULL;
742
0
    }
743
0
    rp = mk_list_entry_first(&ra->list, struct flb_ra_parser, _head);
744
0
    if (!rp->key) {
745
0
        return NULL;
746
0
    }
747
0
    return rp;
748
0
}
749
750
/*
751
 * If 'record accessor' pattern matches an entry in the 'map', set the
752
 * reference in 'out_key' and 'out_val' for the entries in question.
753
 *
754
 * Returns FLB_TRUE if the pattern matched a kv pair, otherwise it returns
755
 * FLB_FALSE.
756
 */
757
int flb_ra_get_kv_pair(struct flb_record_accessor *ra, msgpack_object map,
758
                       msgpack_object **start_key,
759
                       msgpack_object **out_key, msgpack_object **out_val)
760
0
{
761
0
    struct flb_ra_parser *rp;
762
763
0
    rp = get_ra_parser(ra);
764
0
    if (rp == NULL) {
765
0
        return FLB_FALSE;
766
0
    }
767
768
0
    return flb_ra_key_value_get(rp->key->name, map, rp->key->subkeys,
769
0
                                start_key, out_key, out_val);
770
0
}
771
772
struct flb_ra_value *flb_ra_get_value_object(struct flb_record_accessor *ra,
773
                                             msgpack_object map)
774
0
{
775
0
    struct flb_ra_parser *rp;
776
777
0
    rp = get_ra_parser(ra);
778
0
    if (rp == NULL) {
779
0
        return NULL;
780
0
    }
781
782
0
    return flb_ra_key_to_value(rp->key->name, map, rp->key->subkeys);
783
0
}
784
785
/**
786
 *  Update key and/or value of the map using record accessor.
787
 *
788
 *  @param ra   the record accessor to specify key/value pair
789
 *  @param map  the original map.
790
 *  @param in_key   the pointer to overwrite key. If NULL, key will not be updated.
791
 *  @param in_val   the pointer to overwrite val. If NULL, val will not be updated.
792
 *  @param out_map  the updated map. If the API fails, out_map will be NULL.
793
 *
794
 *  @return result of the API. 0:success, -1:fail
795
 */
796
797
int flb_ra_update_kv_pair(struct flb_record_accessor *ra, msgpack_object map,
798
                          void **out_map, size_t *out_size,
799
                          msgpack_object *in_key, msgpack_object *in_val)
800
0
{
801
0
    struct flb_ra_parser *rp;
802
0
    msgpack_packer mp_pck;
803
0
    msgpack_sbuffer mp_sbuf;
804
0
    int ret;
805
806
0
    msgpack_object *s_key;
807
0
    msgpack_object *o_key;
808
0
    msgpack_object *o_val;
809
810
0
    if (in_key == NULL && in_val == NULL) {
811
        /* no key and value. nothing to do */
812
0
        flb_error("%s: no inputs", __FUNCTION__);
813
0
        return -1;
814
0
    }
815
0
    else if (ra == NULL || out_map == NULL || out_size == NULL) {
816
        /* invalid input */
817
0
        flb_error("%s: invalid input", __FUNCTION__);
818
0
        return -1;
819
0
    }
820
0
    else if ( flb_ra_get_kv_pair(ra, map, &s_key, &o_key, &o_val) != 0) {
821
        /* key and value are not found */
822
0
        flb_error("%s: no value", __FUNCTION__);
823
0
        return -1;
824
0
    }
825
826
0
    rp = get_ra_parser(ra);
827
0
    if (rp == NULL) {
828
0
        return -1;
829
0
    }
830
831
0
    msgpack_sbuffer_init(&mp_sbuf);
832
0
    msgpack_packer_init(&mp_pck, &mp_sbuf, msgpack_sbuffer_write);
833
834
0
    ret = flb_ra_key_value_update(rp, map, in_key, in_val, &mp_pck);
835
0
    if (ret < 0) {
836
0
        msgpack_sbuffer_destroy(&mp_sbuf);
837
0
        return -1;
838
0
    }
839
0
    *out_map  = mp_sbuf.data;
840
0
    *out_size = mp_sbuf.size;
841
842
0
    return 0;
843
0
}
844
845
/**
846
 *  Add key and/or value of the map using record accessor.
847
 *  If key already exists, the API fails.
848
 *
849
 *  @param ra   the record accessor to specify key.
850
 *  @param map  the original map.
851
 *  @param in_val   the pointer to add val.
852
 *  @param out_map  the updated map. If the API fails, out_map will be NULL.
853
 *
854
 *  @return result of the API. 0:success, -1:fail
855
 */
856
857
int flb_ra_append_kv_pair(struct flb_record_accessor *ra, msgpack_object map,
858
                          void **out_map, size_t *out_size,
859
                          msgpack_object *in_val)
860
0
{
861
0
    struct flb_ra_parser *rp;
862
0
    msgpack_packer mp_pck;
863
0
    msgpack_sbuffer mp_sbuf;
864
0
    int ret;
865
866
0
    msgpack_object *s_key = NULL;
867
0
    msgpack_object *o_key = NULL;
868
0
    msgpack_object *o_val = NULL;
869
870
0
    if (in_val == NULL) {
871
        /* no key and value. nothing to do */
872
0
        flb_error("%s: no value", __FUNCTION__);
873
0
        return -1;
874
0
    }
875
0
    else if (ra == NULL || out_map == NULL|| out_size == NULL) {
876
        /* invalid input */
877
0
        flb_error("%s: invalid input", __FUNCTION__);
878
0
        return -1;
879
0
    }
880
881
0
    flb_ra_get_kv_pair(ra, map, &s_key, &o_key, &o_val);
882
0
    if (o_key != NULL && o_val != NULL) {
883
        /* key and value already exist */
884
0
        flb_error("%s: already exist", __FUNCTION__);
885
0
        return -1;
886
0
    }
887
888
0
    rp = get_ra_parser(ra);
889
0
    if (rp == NULL || rp->key == NULL) {
890
0
        return -1;
891
0
    }
892
893
0
    msgpack_sbuffer_init(&mp_sbuf);
894
0
    msgpack_packer_init(&mp_pck, &mp_sbuf, msgpack_sbuffer_write);
895
896
0
    ret = flb_ra_key_value_append(rp, map, in_val, &mp_pck);
897
0
    if (ret < 0) {
898
0
        msgpack_sbuffer_destroy(&mp_sbuf);
899
0
        return -1;
900
0
    }
901
902
0
    *out_map  = mp_sbuf.data;
903
0
    *out_size = mp_sbuf.size;
904
905
0
    return 0;
906
0
}