Ejemplo n.º 1
0
bool aeron_mpsc_rb_unblock(volatile aeron_mpsc_rb_t *ring_buffer)
{
    const size_t mask = ring_buffer->capacity - 1;
    int64_t head;
    int64_t tail;
    size_t consumer_index;
    size_t producer_index;
    bool unblocked = false;

    AERON_GET_VOLATILE(head, ring_buffer->descriptor->head_position);
    AERON_GET_VOLATILE(tail, ring_buffer->descriptor->tail_position);

    consumer_index = (int32_t)head & mask;
    producer_index = (int32_t)tail & mask;

    if (producer_index == consumer_index)
    {
        return false;
    }

    int32_t length;
    aeron_rb_record_descriptor_t *record = (aeron_rb_record_descriptor_t *)(ring_buffer->buffer + consumer_index);

    AERON_GET_VOLATILE(length, record->length);
    if (length < 0)
    {
        record->msg_type_id = AERON_RB_PADDING_MSG_TYPE_ID;
        AERON_PUT_ORDERED(record->length, -length);
        unblocked = true;
    }
    else if (0 == length)
    {
        const size_t limit = producer_index > consumer_index ? producer_index : ring_buffer->capacity;
        size_t i = consumer_index + AERON_RB_ALIGNMENT;

        do
        {
            record = (aeron_rb_record_descriptor_t *)(ring_buffer->buffer + i);
            AERON_GET_VOLATILE(length, record->length);
            if (0 != length)
            {
                if (scan_back_to_confirm_still_zeroed(ring_buffer->buffer, i, consumer_index))
                {
                    record = (aeron_rb_record_descriptor_t *)(ring_buffer->buffer + consumer_index);
                    record->msg_type_id = AERON_RB_PADDING_MSG_TYPE_ID;
                    AERON_PUT_ORDERED(record->length, i - consumer_index);
                    unblocked = true;
                }

                break;
            }

            i += AERON_RB_ALIGNMENT;
        }
        while (i < limit);
    }

    return unblocked;
}
Ejemplo n.º 2
0
void aeron_publication_image_on_time_event(
    aeron_driver_conductor_t *conductor, aeron_publication_image_t *image, int64_t now_ns, int64_t now_ms)
{
    switch (image->conductor_fields.status)
    {
        case AERON_PUBLICATION_IMAGE_STATUS_ACTIVE:
        {
            int64_t last_packet_timestamp_ns;
            AERON_GET_VOLATILE(last_packet_timestamp_ns, image->last_packet_timestamp_ns);
            bool is_end_of_stream;
            AERON_GET_VOLATILE(is_end_of_stream, image->is_end_of_stream);

            if (0 == image->conductor_fields.subscribable.length ||
                now_ns > (last_packet_timestamp_ns + image->conductor_fields.liveness_timeout_ns) ||
                (is_end_of_stream &&
                 aeron_counter_get(image->rcv_pos_position.value_addr) >=
                 aeron_counter_get_volatile(image->rcv_hwm_position.value_addr)))
            {
                image->conductor_fields.status = AERON_PUBLICATION_IMAGE_STATUS_INACTIVE;
                image->conductor_fields.time_of_last_status_change_ns = now_ns;

                aeron_driver_receiver_proxy_on_remove_publication_image(
                    conductor->context->receiver_proxy, image->endpoint, image);
            }
            break;
        }

        case AERON_PUBLICATION_IMAGE_STATUS_INACTIVE:
        {
            if (aeron_publication_image_is_drained(image))
            {
                image->conductor_fields.status = AERON_PUBLICATION_IMAGE_STATUS_LINGER;
                image->conductor_fields.time_of_last_status_change_ns = now_ns;

                aeron_driver_conductor_image_transition_to_linger(conductor, image);
            }
            break;
        }

        case AERON_PUBLICATION_IMAGE_STATUS_LINGER:
        {
            if (now_ns >
                (image->conductor_fields.time_of_last_status_change_ns + image->conductor_fields.liveness_timeout_ns))
            {
                image->conductor_fields.status = AERON_PUBLICATION_IMAGE_STATUS_DONE;
            }
            break;
        }

        default:
            break;
    }
}
Ejemplo n.º 3
0
int32_t aeron_counters_manager_next_counter_id(volatile aeron_counters_manager_t *manager)
{
    int64_t now_ms = manager->clock_func();

    for (int i = 0; i <= manager->free_list_index; i++)
    {
        int32_t counter_id = manager->free_list[i];
        aeron_counter_metadata_descriptor_t *metadata =
            (aeron_counter_metadata_descriptor_t *)(manager->metadata + (counter_id * AERON_COUNTERS_MANAGER_METADATA_LENGTH));

        int64_t deadline;
        AERON_GET_VOLATILE(deadline, metadata->free_to_reuse_deadline);

        if (now_ms >= deadline)
        {
            aeron_counters_manager_remove_free_list_index(manager, i);
            aeron_counter_value_descriptor_t *value =
                (aeron_counter_value_descriptor_t *)(manager->values + (counter_id * AERON_COUNTERS_MANAGER_VALUE_LENGTH));
            AERON_PUT_ORDERED(value->counter_value, 0L);
            return counter_id;
        }
    }

    return ++manager->id_high_water_mark;
}
Ejemplo n.º 4
0
bool aeron_error_log_exists(const uint8_t *buffer, size_t buffer_size)
{
    aeron_error_log_entry_t *entry = (aeron_error_log_entry_t *)buffer;
    int32_t length = 0;

    AERON_GET_VOLATILE(length, entry->length);
    return (0 != length);
}
Ejemplo n.º 5
0
bool aeron_max_flow_control_strategy_should_linger(void *state, int64_t now_ns)
{
    aeron_max_flow_control_strategy_state_t *strategy_state = (aeron_max_flow_control_strategy_state_t *)state;

    bool should_linger;
    AERON_GET_VOLATILE(should_linger, strategy_state->should_linger);

    return should_linger;
}
Ejemplo n.º 6
0
size_t aeron_error_log_read(
    const uint8_t *buffer,
    size_t buffer_size,
    aeron_error_log_reader_func_t reader,
    void *clientd,
    int64_t since_timestamp)
{
    size_t entries = 0;
    size_t offset = 0;

    while (offset < buffer_size)
    {
        aeron_error_log_entry_t *entry = (aeron_error_log_entry_t *)(buffer + offset);
        int32_t length = 0;

        AERON_GET_VOLATILE(length, entry->length);

        if (0 == length)
        {
            break;
        }

        int64_t last_observation_timestamp = 0;
        AERON_GET_VOLATILE(last_observation_timestamp, entry->last_observation_timestamp);

        if (last_observation_timestamp >= since_timestamp)
        {
            ++entries;

            reader(
                entry->observation_count,
                entry->first_observation_timestamp,
                last_observation_timestamp,
                (const char *)(buffer + offset + AERON_ERROR_LOG_HEADER_LENGTH),
                length - AERON_ERROR_LOG_HEADER_LENGTH,
                clientd);
        }

        offset += AERON_ALIGN(length, AERON_ERROR_LOG_RECORD_ALIGNMENT);
    }

    return entries;
}
Ejemplo n.º 7
0
int aeron_publication_image_send_pending_loss(aeron_publication_image_t *image)
{
    int work_count = 0;

    if (NULL != image->endpoint && AERON_PUBLICATION_IMAGE_STATUS_ACTIVE == image->conductor_fields.status)
    {
        int64_t change_number;
        AERON_GET_VOLATILE(change_number, image->end_loss_change);

        if (change_number != image->last_loss_change_number)
        {
            const int32_t term_id = image->loss_term_id;
            const int32_t term_offset = image->loss_term_offset;
            const int32_t length = (int32_t)image->loss_length;

            aeron_acquire();

            if (change_number == image->begin_loss_change)
            {
                if (image->conductor_fields.is_reliable)
                {
                    int send_nak_result = aeron_receive_channel_endpoint_send_nak(
                        image->endpoint,
                        &image->control_address,
                        image->stream_id,
                        image->session_id,
                        term_id,
                        term_offset,
                        length);

                    aeron_counter_ordered_increment(image->nak_messages_sent_counter, 1);
                    work_count = send_nak_result < 0 ? send_nak_result : 1;
                }
                else
                {
                    const size_t index = aeron_logbuffer_index_by_term(image->initial_term_id, term_id);
                    uint8_t *buffer = image->mapped_raw_log.term_buffers[index].addr;

                    if (aeron_term_gap_filler_try_fill_gap(image->log_meta_data, buffer, term_id, term_offset, length))
                    {
                        aeron_counter_ordered_increment(image->loss_gap_fills_counter, 1);
                    }

                    work_count = 1;
                }

                image->last_loss_change_number = change_number;
            }
        }
    }

    return work_count;
}
Ejemplo n.º 8
0
size_t aeron_mpsc_rb_read(
    volatile aeron_mpsc_rb_t *ring_buffer,
    aeron_rb_handler_t handler,
    void *clientd,
    size_t message_count_limit)
{
    const int64_t head = ring_buffer->descriptor->head_position;
    const size_t head_index = (int32_t)head & (ring_buffer->capacity - 1);
    const size_t contiguous_block_length = ring_buffer->capacity - head_index;
    size_t messages_read = 0;
    size_t bytes_read = 0;

    while ((bytes_read < contiguous_block_length) && (messages_read < message_count_limit))
    {
        aeron_rb_record_descriptor_t *header = NULL;
        const size_t record_index = head_index + bytes_read;
        int32_t record_length = 0;
        int32_t msg_type_id = 0;

        header = (aeron_rb_record_descriptor_t *)(ring_buffer->buffer + record_index);
        AERON_GET_VOLATILE(record_length, header->length);

        if (record_length <= 0)
        {
            break;
        }

        bytes_read += AERON_ALIGN(record_length, AERON_RB_ALIGNMENT);
        msg_type_id = header->msg_type_id;

        if (AERON_RB_PADDING_MSG_TYPE_ID == msg_type_id)
        {
            continue;
        }

        ++messages_read;
        handler(
            msg_type_id,
            ring_buffer->buffer + AERON_RB_MESSAGE_OFFSET(record_index),
            record_length - AERON_RB_RECORD_HEADER_LENGTH,
            clientd);

    }

    if (0 != bytes_read)
    {
        memset(ring_buffer->buffer + head_index, 0, bytes_read);
        AERON_PUT_ORDERED(ring_buffer->descriptor->head_position, head + bytes_read);
    }

    return messages_read;
}
Ejemplo n.º 9
0
int aeron_publication_image_send_pending_status_message(aeron_publication_image_t *image)
{
    int work_count = 0;

    if (NULL != image->endpoint && AERON_PUBLICATION_IMAGE_STATUS_ACTIVE == image->conductor_fields.status)
    {
        int64_t change_number;
        AERON_GET_VOLATILE(change_number, image->end_sm_change);

        if (change_number != image->last_sm_change_number)
        {
            const int64_t sm_position = image->next_sm_position;
            const int32_t receiver_window_length = image->next_sm_receiver_window_length;

            aeron_acquire();

            if (change_number == image->begin_sm_change)
            {
                const int32_t term_id = aeron_logbuffer_compute_term_id_from_position(
                    sm_position, image->position_bits_to_shift, image->initial_term_id);
                const int32_t term_offset = (int32_t)(sm_position & image->term_length_mask);

                int send_sm_result = aeron_receive_channel_endpoint_send_sm(
                    image->endpoint,
                    &image->control_address,
                    image->stream_id,
                    image->session_id,
                    term_id,
                    term_offset,
                    receiver_window_length,
                    0);

                aeron_counter_ordered_increment(image->status_messages_sent_counter, 1);

                image->last_sm_change_number = change_number;
                image->last_sm_position = sm_position;
                image->last_sm_position_window_limit = sm_position + receiver_window_length;
                work_count = send_sm_result < 0 ? send_sm_result : 1;
            }
        }
    }

    return work_count;
}
Ejemplo n.º 10
0
inline static bool scan_back_to_confirm_still_zeroed(uint8_t *buffer, size_t from, size_t limit)
{
    size_t i = from - AERON_RB_ALIGNMENT;
    bool all_zeroes = true;

    while (i >= limit)
    {
        const aeron_rb_record_descriptor_t *record = (aeron_rb_record_descriptor_t *)(buffer + i);
        int32_t length;
        AERON_GET_VOLATILE(length, record->length);
        if (0 != length)
        {
            all_zeroes = false;
            break;
        }

        i -= AERON_RB_ALIGNMENT;
    }

    return all_zeroes;
}
Ejemplo n.º 11
0
inline static int32_t aeron_mpsc_rb_claim_capacity(volatile aeron_mpsc_rb_t *ring_buffer, size_t required_capacity)
{
    const size_t mask = ring_buffer->capacity - 1;
    int64_t head = 0;
    int64_t tail = 0;
    size_t tail_index = 0;
    size_t padding = 0;
    size_t to_buffer_end_length = 0;

    AERON_GET_VOLATILE(head, ring_buffer->descriptor->head_cache_position);

    do
    {
        int32_t available_capacity = 0;
        AERON_GET_VOLATILE(tail, ring_buffer->descriptor->tail_position);

        available_capacity = (int32_t )ring_buffer->capacity - (int32_t)(tail - head);

        if ((int32_t)required_capacity > available_capacity)
        {
            AERON_GET_VOLATILE(head, ring_buffer->descriptor->head_position);

            if (required_capacity > (ring_buffer->capacity - (int32_t)(tail - head)))
            {
                return -1;
            }

            AERON_PUT_ORDERED(ring_buffer->descriptor->head_cache_position, head);
        }

        tail_index = (int32_t)tail & mask;
        to_buffer_end_length = ring_buffer->capacity - tail_index;

        if (required_capacity > to_buffer_end_length)
        {
            size_t head_index = (int32_t)head & mask;

            if (required_capacity > head_index)
            {
                AERON_GET_VOLATILE(head, ring_buffer->descriptor->head_position);
                head_index = (int32_t)head & mask;

                if (required_capacity > head_index)
                {
                    return -1;
                }

                AERON_PUT_ORDERED(ring_buffer->descriptor->head_cache_position, head);
            }

            padding = to_buffer_end_length;
        }
    }
    while (!aeron_cmpxchg64(
        &(ring_buffer->descriptor->tail_position),
        tail,
        tail + (int32_t)required_capacity + (int32_t)padding));

    if (0 != padding)
    {
        aeron_rb_record_descriptor_t *record_header = (aeron_rb_record_descriptor_t *)(ring_buffer->buffer + tail_index);

        record_header->msg_type_id = AERON_RB_PADDING_MSG_TYPE_ID;
        AERON_PUT_ORDERED(record_header->length, padding);
        tail_index = 0;
    }

    return (int32_t)tail_index;
}
Ejemplo n.º 12
0
int64_t aeron_mpsc_rb_consumer_heartbeat_time_value(volatile aeron_mpsc_rb_t *ring_buffer)
{
    int64_t value = 0;
    AERON_GET_VOLATILE(value, ring_buffer->descriptor->consumer_heartbeat);
    return value;
}