/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Fluent Bit * ========== * Copyright (C) 2015-2022 The Fluent Bit Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include struct flb_log_event_encoder_dynamic_field_scope * flb_log_event_encoder_dynamic_field_scope_current( struct flb_log_event_encoder_dynamic_field *field) { if (cfl_list_is_empty(&field->scopes)) { return NULL; } return cfl_list_entry_first( &field->scopes, struct flb_log_event_encoder_dynamic_field_scope, _head); } int flb_log_event_encoder_dynamic_field_scope_enter( struct flb_log_event_encoder_dynamic_field *field, int type) { int result; struct flb_log_event_encoder_dynamic_field_scope *scope; if (type != MSGPACK_OBJECT_MAP && type != MSGPACK_OBJECT_ARRAY) { return FLB_EVENT_ENCODER_ERROR_INVALID_ARGUMENT; } result = flb_log_event_encoder_dynamic_field_append(field); if (result != FLB_EVENT_ENCODER_SUCCESS) { return result; } scope = flb_calloc(1, sizeof(struct flb_log_event_encoder_dynamic_field_scope)); if (scope == NULL) { return FLB_EVENT_ENCODER_ERROR_ALLOCATION_ERROR; } cfl_list_entry_init(&scope->_head); scope->type = type; scope->offset = field->buffer.size; cfl_list_prepend(&scope->_head, &field->scopes); if (type == MSGPACK_OBJECT_MAP) { flb_mp_map_header_init(&scope->header, &field->packer); } else if (type == MSGPACK_OBJECT_ARRAY) { flb_mp_array_header_init(&scope->header, &field->packer); } return FLB_EVENT_ENCODER_SUCCESS; } int flb_log_event_encoder_dynamic_field_scope_leave( struct flb_log_event_encoder_dynamic_field *field, struct flb_log_event_encoder_dynamic_field_scope *scope, int commit) { if (scope == NULL) { return FLB_EVENT_ENCODER_ERROR_INVALID_ARGUMENT; } if (commit) { /* We increment the entry count on each append because * we don't discriminate based on the scope type so * we need to divide the entry count by two for maps * to ensure the entry count matches the kv pair count */ if (scope->type == MSGPACK_OBJECT_MAP) { scope->header.entries /= 2; flb_mp_map_header_end(&scope->header); } else { flb_mp_array_header_end(&scope->header); } } else { field->buffer.size = scope->offset; } cfl_list_del(&scope->_head); flb_free(scope); return FLB_EVENT_ENCODER_SUCCESS; } int flb_log_event_encoder_dynamic_field_begin_map( struct flb_log_event_encoder_dynamic_field *field) { return flb_log_event_encoder_dynamic_field_scope_enter(field, MSGPACK_OBJECT_MAP); } int flb_log_event_encoder_dynamic_field_begin_array( struct flb_log_event_encoder_dynamic_field *field) { return flb_log_event_encoder_dynamic_field_scope_enter(field, MSGPACK_OBJECT_ARRAY); } int flb_log_event_encoder_dynamic_field_commit_map( struct flb_log_event_encoder_dynamic_field *field) { struct flb_log_event_encoder_dynamic_field_scope *scope; scope = flb_log_event_encoder_dynamic_field_scope_current(field); return flb_log_event_encoder_dynamic_field_scope_leave(field, scope, FLB_TRUE); } int flb_log_event_encoder_dynamic_field_commit_array( struct flb_log_event_encoder_dynamic_field *field) { struct flb_log_event_encoder_dynamic_field_scope *scope; scope = flb_log_event_encoder_dynamic_field_scope_current(field); return flb_log_event_encoder_dynamic_field_scope_leave(field, scope, FLB_TRUE); } int flb_log_event_encoder_dynamic_field_rollback_map( struct flb_log_event_encoder_dynamic_field *field) { struct flb_log_event_encoder_dynamic_field_scope *scope; scope = flb_log_event_encoder_dynamic_field_scope_current(field); return flb_log_event_encoder_dynamic_field_scope_leave(field, scope, FLB_FALSE); } int flb_log_event_encoder_dynamic_field_rollback_array( struct flb_log_event_encoder_dynamic_field *field) { struct flb_log_event_encoder_dynamic_field_scope *scope; scope = flb_log_event_encoder_dynamic_field_scope_current(field); return flb_log_event_encoder_dynamic_field_scope_leave(field, scope, FLB_TRUE); } int flb_log_event_encoder_dynamic_field_append( struct flb_log_event_encoder_dynamic_field *field) { struct flb_log_event_encoder_dynamic_field_scope *scope; scope = flb_log_event_encoder_dynamic_field_scope_current(field); if (scope == NULL) { if (cfl_list_is_empty(&field->scopes)) { return FLB_EVENT_ENCODER_SUCCESS; } return FLB_EVENT_ENCODER_ERROR_INVALID_ARGUMENT; } flb_mp_map_header_append(&scope->header); return FLB_EVENT_ENCODER_SUCCESS; } static int flb_log_event_encoder_dynamic_field_flush_scopes( struct flb_log_event_encoder_dynamic_field *field, int commit) { int result; struct flb_log_event_encoder_dynamic_field_scope *scope; result = FLB_EVENT_ENCODER_SUCCESS; do { scope = flb_log_event_encoder_dynamic_field_scope_current(field); if (scope != NULL) { result = flb_log_event_encoder_dynamic_field_scope_leave(field, scope, commit); } } while (scope != NULL && result == FLB_EVENT_ENCODER_SUCCESS); return result; } int flb_log_event_encoder_dynamic_field_flush( struct flb_log_event_encoder_dynamic_field *field) { int result; result = flb_log_event_encoder_dynamic_field_flush_scopes(field, FLB_TRUE); if (result == FLB_EVENT_ENCODER_SUCCESS) { field->data = field->buffer.data; field->size = field->buffer.size; } return result; } int flb_log_event_encoder_dynamic_field_reset( struct flb_log_event_encoder_dynamic_field *field) { msgpack_sbuffer_clear(&field->buffer); flb_log_event_encoder_dynamic_field_flush_scopes(field, FLB_FALSE); field->data = NULL; field->size = 0; return FLB_EVENT_ENCODER_SUCCESS; } int flb_log_event_encoder_dynamic_field_init( struct flb_log_event_encoder_dynamic_field *field, int type) { msgpack_sbuffer_init(&field->buffer); msgpack_packer_init(&field->packer, &field->buffer, msgpack_sbuffer_write); field->initialized = FLB_TRUE; field->type = type; cfl_list_init(&field->scopes); flb_log_event_encoder_dynamic_field_reset(field); return FLB_EVENT_ENCODER_SUCCESS; } void flb_log_event_encoder_dynamic_field_destroy( struct flb_log_event_encoder_dynamic_field *field) { msgpack_sbuffer_destroy(&field->buffer); field->initialized = FLB_FALSE; }