<commit_before>/*
 * Copyright 2014-2020 Real Logic Limited.
 *
 * 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
 *
 * https://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 <string.h>
#include <math.h>
#include <errno.h>

#include "aeron_alloc.h"
#include "concurrent/aeron_counters_manager.h"
#include "util/aeron_error.h"

int aeron_counters_manager_init(
    aeron_counters_manager_t *manager,
    uint8_t *metadata_buffer,
    size_t metadata_length,
    uint8_t *values_buffer,
    size_t values_length,
    aeron_clock_cache_t *cached_clock,
    int64_t free_to_reuse_timeout_ms)
{
    int result = -1;

    if (AERON_COUNTERS_MANAGER_IS_BUFFER_LENGTHS_VALID(metadata_length, values_length))
    {
        manager->metadata = metadata_buffer;
        manager->metadata_length = metadata_length;
        manager->values = values_buffer;
        manager->values_length = values_length;
        manager->max_counter_id = (int32_t)((values_length / AERON_COUNTERS_MANAGER_VALUE_LENGTH) - 1);
        manager->id_high_water_mark = -1;
        manager->free_list_index = -1;
        manager->free_list_length = 2;
        manager->cached_clock = cached_clock;
        manager->free_to_reuse_timeout_ms = free_to_reuse_timeout_ms;
        result = aeron_alloc((void **)&manager->free_list, sizeof(int32_t) * manager->free_list_length);
    }
    else
    {
        aeron_set_err(EINVAL, "%s:%d: %s", __FILE__, __LINE__, strerror(EINVAL));
    }

    return result;
}

void aeron_counters_manager_close(aeron_counters_manager_t *manager)
{
    aeron_free(manager->free_list);
}

int32_t aeron_counters_manager_allocate(
    aeron_counters_manager_t *manager,
    int32_t type_id,
    const uint8_t *key,
    size_t key_length,
    const char *label,
    size_t label_length)
{
    const int32_t counter_id = aeron_counters_manager_next_counter_id(manager);
    if (counter_id < 0)
    {
        aeron_set_err(EINVAL, "%s:%d: %s", __FILE__, __LINE__, strerror(EINVAL));
        return -1;
    }

    aeron_counter_metadata_descriptor_t *metadata = (aeron_counter_metadata_descriptor_t *)
        (manager->metadata + (counter_id * AERON_COUNTERS_MANAGER_METADATA_LENGTH));

    metadata->type_id = type_id;
    metadata->free_for_reuse_deadline_ms = AERON_COUNTER_NOT_FREE_TO_REUSE;

    if (NULL != key && key_length > 0)
    {
        memcpy(metadata->key, key, (size_t)fmin((double)sizeof(metadata->key), (double)key_length));
    }

    size_t length = (size_t)fmin((double)sizeof(metadata->label), (double)label_length);

    memcpy(metadata->label, label, length);
    metadata->label_length = (int32_t)length;
    AERON_PUT_ORDERED(metadata->state, AERON_COUNTER_RECORD_ALLOCATED);

    return counter_id;
}

int aeron_counters_reader_get_buffers(aeron_counters_reader_t *reader, aeron_counters_reader_buffers_t *buffers)
{
    buffers->values = reader->values;
    buffers->metadata = reader->metadata;
    buffers->values_length = reader->values_length;
    buffers->metadata_length = reader->metadata_length;

    return 0;
}

int32_t aeron_counters_reader_max_counter_id(aeron_counters_reader_t *reader)
{
    return reader->max_counter_id;
}

void aeron_counters_manager_counter_registration_id(
    aeron_counters_manager_t *manager, int32_t counter_id, int64_t registration_id)
{
    aeron_counter_value_descriptor_t *value_descriptor = (aeron_counter_value_descriptor_t *)(
        manager->values + AERON_COUNTER_OFFSET(counter_id));

    AERON_PUT_ORDERED(value_descriptor->registration_id, registration_id);
}

void aeron_counters_manager_counter_owner_id(
    aeron_counters_manager_t *manager, int32_t counter_id, int64_t owner_id)
{
    aeron_counter_value_descriptor_t *value_descriptor = (aeron_counter_value_descriptor_t *)(
        manager->values + AERON_COUNTER_OFFSET(counter_id));

    value_descriptor->owner_id = owner_id;
}

void aeron_counters_manager_update_label(
    aeron_counters_manager_t *manager, int32_t counter_id, size_t label_length, const char *label)
{
    aeron_counter_metadata_descriptor_t *metadata = (aeron_counter_metadata_descriptor_t *)
        (manager->metadata + (counter_id * AERON_COUNTERS_MANAGER_METADATA_LENGTH));

    size_t length = (size_t)fmin((double)sizeof(metadata->label), (double)label_length);

    memcpy(metadata->label, label, length);
    AERON_PUT_ORDERED(metadata->label_length, (int32_t)length);
}

void aeron_counters_manager_append_to_label(
    aeron_counters_manager_t *manager, int32_t counter_id, size_t length, const char *value)
{
    aeron_counter_metadata_descriptor_t *metadata = (aeron_counter_metadata_descriptor_t *)
        (manager->metadata + (counter_id * AERON_COUNTERS_MANAGER_METADATA_LENGTH));

    size_t current_length = metadata->label_length;
    size_t available_length = sizeof(metadata->label) - current_length;
    size_t copy_length = length > available_length ? available_length : length;

    memcpy(metadata->label, value, copy_length);
    AERON_PUT_ORDERED(metadata->label_length, ((int32_t)(current_length + copy_length)));
}

void aeron_counters_manager_remove_free_list_index(aeron_counters_manager_t *manager, int index)
{
    for (int i = index; i < manager->free_list_index; i++)
    {<commit_msg>[C] Fix copy destination for counters manager append to label.<commit_after>/*
 * Copyright 2014-2020 Real Logic Limited.
 *
 * 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
 *
 * https://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 <string.h>
#include <math.h>
#include <errno.h>

#include "aeron_alloc.h"
#include "concurrent/aeron_counters_manager.h"
#include "util/aeron_error.h"

int aeron_counters_manager_init(
    aeron_counters_manager_t *manager,
    uint8_t *metadata_buffer,
    size_t metadata_length,
    uint8_t *values_buffer,
    size_t values_length,
    aeron_clock_cache_t *cached_clock,
    int64_t free_to_reuse_timeout_ms)
{
    int result = -1;

    if (AERON_COUNTERS_MANAGER_IS_BUFFER_LENGTHS_VALID(metadata_length, values_length))
    {
        manager->metadata = metadata_buffer;
        manager->metadata_length = metadata_length;
        manager->values = values_buffer;
        manager->values_length = values_length;
        manager->max_counter_id = (int32_t)((values_length / AERON_COUNTERS_MANAGER_VALUE_LENGTH) - 1);
        manager->id_high_water_mark = -1;
        manager->free_list_index = -1;
        manager->free_list_length = 2;
        manager->cached_clock = cached_clock;
        manager->free_to_reuse_timeout_ms = free_to_reuse_timeout_ms;
        result = aeron_alloc((void **)&manager->free_list, sizeof(int32_t) * manager->free_list_length);
    }
    else
    {
        aeron_set_err(EINVAL, "%s:%d: %s", __FILE__, __LINE__, strerror(EINVAL));
    }

    return result;
}

void aeron_counters_manager_close(aeron_counters_manager_t *manager)
{
    aeron_free(manager->free_list);
}

int32_t aeron_counters_manager_allocate(
    aeron_counters_manager_t *manager,
    int32_t type_id,
    const uint8_t *key,
    size_t key_length,
    const char *label,
    size_t label_length)
{
    const int32_t counter_id = aeron_counters_manager_next_counter_id(manager);
    if (counter_id < 0)
    {
        aeron_set_err(EINVAL, "%s:%d: %s", __FILE__, __LINE__, strerror(EINVAL));
        return -1;
    }

    aeron_counter_metadata_descriptor_t *metadata = (aeron_counter_metadata_descriptor_t *)
        (manager->metadata + (counter_id * AERON_COUNTERS_MANAGER_METADATA_LENGTH));

    metadata->type_id = type_id;
    metadata->free_for_reuse_deadline_ms = AERON_COUNTER_NOT_FREE_TO_REUSE;

    if (NULL != key && key_length > 0)
    {
        memcpy(metadata->key, key, (size_t)fmin((double)sizeof(metadata->key), (double)key_length));
    }

    size_t length = (size_t)fmin((double)sizeof(metadata->label), (double)label_length);

    memcpy(metadata->label, label, length);
    metadata->label_length = (int32_t)length;
    AERON_PUT_ORDERED(metadata->state, AERON_COUNTER_RECORD_ALLOCATED);

    return counter_id;
}

int aeron_counters_reader_get_buffers(aeron_counters_reader_t *reader, aeron_counters_reader_buffers_t *buffers)
{
    buffers->values = reader->values;
    buffers->metadata = reader->metadata;
    buffers->values_length = reader->values_length;
    buffers->metadata_length = reader->metadata_length;

    return 0;
}

int32_t aeron_counters_reader_max_counter_id(aeron_counters_reader_t *reader)
{
    return reader->max_counter_id;
}

void aeron_counters_manager_counter_registration_id(
    aeron_counters_manager_t *manager, int32_t counter_id, int64_t registration_id)
{
    aeron_counter_value_descriptor_t *value_descriptor = (aeron_counter_value_descriptor_t *)(
        manager->values + AERON_COUNTER_OFFSET(counter_id));

    AERON_PUT_ORDERED(value_descriptor->registration_id, registration_id);
}

void aeron_counters_manager_counter_owner_id(
    aeron_counters_manager_t *manager, int32_t counter_id, int64_t owner_id)
{
    aeron_counter_value_descriptor_t *value_descriptor = (aeron_counter_value_descriptor_t *)(
        manager->values + AERON_COUNTER_OFFSET(counter_id));

    value_descriptor->owner_id = owner_id;
}

void aeron_counters_manager_update_label(
    aeron_counters_manager_t *manager, int32_t counter_id, size_t label_length, const char *label)
{
    aeron_counter_metadata_descriptor_t *metadata = (aeron_counter_metadata_descriptor_t *)
        (manager->metadata + (counter_id * AERON_COUNTERS_MANAGER_METADATA_LENGTH));

    size_t length = (size_t)fmin((double)sizeof(metadata->label), (double)label_length);

    memcpy(metadata->label, label, length);
    AERON_PUT_ORDERED(metadata->label_length, (int32_t)length);
}

void aeron_counters_manager_append_to_label(
    aeron_counters_manager_t *manager, int32_t counter_id, size_t length, const char *value)
{
    aeron_counter_metadata_descriptor_t *metadata = (aeron_counter_metadata_descriptor_t *)
        (manager->metadata + (counter_id * AERON_COUNTERS_MANAGER_METADATA_LENGTH));

    size_t current_length = metadata->label_length;
    size_t available_length = sizeof(metadata->label) - current_length;
    size_t copy_length = length > available_length ? available_length : length;

    memcpy(metadata->label + current_length, value, copy_length);
    AERON_PUT_ORDERED(metadata->label_length, ((int32_t)(current_length + copy_length)));
}

void aeron_counters_manager_remove_free_list_index(aeron_counters_manager_t *manager, int index)
{
    for (int i = index; i < manager->free_list_index; i++)
    {
{'fraction_non_alphanumeric': 0.09411146161934805, 'fraction_numerical': 0.00981423063441991, 'mean_word_length': 4.825931597753956, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 103, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2766458', 'n_tokens_mistral': 3909, 'n_tokens_neox': 3814, 'n_words': 700}