Ejemplo n.º 1
0
int thorium_transport_receive(struct thorium_transport *self, struct thorium_message *message)
{
    int value;

    if (self->transport_interface == NULL) {
        return 0;
    }

    value = self->transport_interface->receive(self, message);

    if (value) {
#ifdef THORIUM_TRANSPORT_DEBUG
        printf("TRANSPORT RECEIVE Source %d Destination %d Tag %d Count %d\n",
                        thorium_message_source_node(message),
                        thorium_message_destination_node(message),
                        thorium_message_action(message),
                        thorium_message_count(message));
#endif

        if (core_bitmap_get_bit_uint32_t(&self->flags, FLAG_PRINT_TRANSPORT_EVENTS)) {
            thorium_transport_print_event(self, EVENT_TYPE_RECEIVE, message);
        }
    }

    return value;
}
Ejemplo n.º 2
0
void process_ping(struct thorium_actor *self, struct thorium_message *message)
{
    int count;
    char *buffer;
    int buffer_size;
    uint64_t *bucket;
    uint64_t expected_checksum;
    uint64_t actual_checksum;
    struct process *concrete_self;

    concrete_self = (struct process *)thorium_actor_concrete_actor(self);
    buffer = thorium_message_buffer(message);
    count = thorium_message_count(message);
    buffer_size = count - sizeof(expected_checksum);
    bucket = (uint64_t *)(buffer + buffer_size);
    expected_checksum = *bucket;
    actual_checksum = core_hash_data_uint64_t(buffer, buffer_size, SEED);

    if (expected_checksum != actual_checksum) {
        printf("TRANSPORT FAILED source: %d (%d) destination: %d (%d) tag: ACTION_PING count: %d"
                        " expected_checksum: %" PRIu64 " actual_checksum: %" PRIu64 "\n",
                        thorium_message_source(message),
                        thorium_message_source_node(message),
                        thorium_message_destination(message),
                        thorium_message_destination_node(message),
                        count,
                        expected_checksum, actual_checksum);

        ++concrete_self->failed;
    } else {
        ++concrete_self->passed;
    }

    thorium_actor_send_reply_empty(self, ACTION_PING_REPLY);
}
Ejemplo n.º 3
0
void thorium_actor_pack_proxy_message(struct thorium_actor *self, struct thorium_message *message,
                int real_source)
{
    int real_tag;
    int count;
    int new_count;
    void *buffer;
    void *new_buffer;
    int offset;
    struct core_memory_pool *ephemeral_memory;

    /*
     * pack data in this order:
     *
     * - data (count bytes)
     * - real_source
     * - real_tag
     */
    ephemeral_memory = thorium_actor_get_ephemeral_memory(self);
    real_tag = thorium_message_action(message);
    buffer = thorium_message_buffer(message);
    count = thorium_message_count(message);

#ifdef DEBUG_BINOMIAL_TREE
    printf("DEBUG_BINOMIAL_TREE pack_proxy_message count %d source %d action %x\n", count,
                    thorium_actor_name(self),
                    real_tag);
    thorium_message_print(message);

#endif

    new_count = count + sizeof(real_source) + sizeof(real_tag);

    /* use slab allocator */
    new_buffer = core_memory_pool_allocate(ephemeral_memory, new_count);

#ifdef THORIUM_ACTOR_DEBUG
    printf("DEBUG12 core_memory_pool_allocate %p (pack proxy message)\n",
                    new_buffer);
#endif

    if (count > 0)
        core_memory_copy(new_buffer, buffer, count);

    offset = count;
    core_memory_copy((char *)new_buffer + offset, &real_source, sizeof(real_source));
    offset += sizeof(real_source);
    core_memory_copy((char *)new_buffer + offset, &real_tag, sizeof(real_tag));
    offset += sizeof(real_tag);

    thorium_message_init(message, ACTION_PROXY_MESSAGE, new_count, new_buffer);
    thorium_message_set_source(message, real_source);

#if 0
    /* free the old buffer
     */
    core_memory_free(buffer);
    buffer = NULL;
#endif
}
Ejemplo n.º 4
0
void thorium_message_get_all(struct thorium_message *message, int *tag, int *count, void **buffer, int *source)
{
    *tag = thorium_message_action(message);
    *count = thorium_message_count(message);
    *buffer = thorium_message_buffer(message);
    *source = thorium_message_source(message);
}
Ejemplo n.º 5
0
int thorium_transport_send(struct thorium_transport *self, struct thorium_message *message)
{
    int value;

    if (self->transport_interface == NULL) {
        return 0;
    }

    /*
     * Send the message through the mock transport which is
     * a transport profiler.
     */
    if (core_bitmap_get_bit_uint32_t(&self->flags, FLAG_PROFILE)) {
        thorium_transport_profiler_send_mock(&self->transport_profiler, message);
    }

    value = self->transport_interface->send(self, message);

    if (value) {
#ifdef THORIUM_TRANSPORT_DEBUG
        printf("TRANSPORT SEND Source %d Destination %d Tag %d Count %d\n",
                        thorium_message_source_node(message),
                        thorium_message_destination_node(message),
                        thorium_message_action(message),
                        thorium_message_count(message));
#endif
        ++self->active_request_count;

        if (core_bitmap_get_bit_uint32_t(&self->flags, FLAG_PRINT_TRANSPORT_EVENTS)) {
            thorium_transport_print_event(self, EVENT_TYPE_SEND, message);
        }
    }

    return value;
}
Ejemplo n.º 6
0
void thorium_message_remove_metadata(struct thorium_message *self)
{
    int count;
    int metadata_size;
    int all;

    count = thorium_message_count(self);
    metadata_size = thorium_message_metadata_size(self);
    all = count - metadata_size;
    thorium_message_set_count(self, all);
}
Ejemplo n.º 7
0
void thorium_message_init_copy(struct thorium_message *self, struct thorium_message *old_message)
{
    thorium_message_init(self,
                    thorium_message_action(old_message),
                    thorium_message_count(old_message),
                    thorium_message_buffer(old_message));

    thorium_message_set_source(self,
                    thorium_message_source(old_message));
    thorium_message_set_destination(self,
                    thorium_message_destination(old_message));
}
Ejemplo n.º 8
0
int thorium_message_multiplexer_message_should_be_multiplexed(struct thorium_message_multiplexer *self,
                struct thorium_message *message)
{
    int buffer_size;
    int threshold;

    if (thorium_message_multiplexer_is_disabled(self))
        return 0;

    buffer_size = thorium_message_count(message);
    threshold = self->buffer_size_in_bytes / 2;

    return buffer_size <= threshold;
}
Ejemplo n.º 9
0
void thorium_actor_unpack_proxy_message(struct thorium_actor *self,
                struct thorium_message *message)
{
    int new_count;
    int tag;
    int source;
    void *buffer;
    int offset;

    buffer = thorium_message_buffer(message);
    new_count = thorium_message_count(message);
    new_count -= sizeof(source);
    new_count -= sizeof(tag);

    offset = new_count;

    source = *(int *)((char *)buffer + offset);
    offset += sizeof(source);
    tag = *(int *)((char *)buffer + offset);

#ifdef DEBUG_BINOMIAL_TREE
    printf("DEBUG_BINOMIAL_TREE unpack_proxy_message real_count %d real_source %d real_action %x\n",
                    new_count, source, tag);
#endif

    /*
     * The action can not be ACTION_INVALID because it is invalid
     * by convention.
     */
    CORE_DEBUGGER_ASSERT(tag != ACTION_INVALID);

    offset += sizeof(tag);

    /*thorium_message_init(message, tag, new_count, buffer);*/

    /*
     * Change the tag, source, and count.
     */
    thorium_message_set_source(message, source);
    thorium_message_set_action(message, tag);
    thorium_message_set_count(message, new_count);

#if 0
    printf("DEBUG unpack_proxy_message... source %d tag %d count %d\n",
                    source, tag, new_count);
#endif
}
Ejemplo n.º 10
0
void biosal_assembly_graph_store_set_vertex_flag(struct thorium_actor *self,
                struct thorium_message *message)
{
    char *buffer;
    int count;
    int flag;
    struct biosal_dna_kmer transport_kmer;
    struct biosal_assembly_vertex *vertex;
    struct biosal_assembly_graph_store *concrete_self;
    struct core_memory_pool *ephemeral_memory;
    int position;

    concrete_self = thorium_actor_concrete_actor(self);
    ephemeral_memory = thorium_actor_get_ephemeral_memory(self);
    biosal_dna_kmer_init_empty(&transport_kmer);
    buffer = thorium_message_buffer(message);
    count = thorium_message_count(message);

    position = 0;
    position += biosal_dna_kmer_unpack(&transport_kmer, buffer, concrete_self->kmer_length,
                    ephemeral_memory, &concrete_self->transport_codec);
    core_memory_copy(&flag, buffer + position, sizeof(flag));
    position += sizeof(flag);
    CORE_DEBUGGER_ASSERT_IS_EQUAL_INT(position, count);

    CORE_DEBUGGER_ASSERT(flag >= BIOSAL_VERTEX_FLAG_START_VALUE);
    CORE_DEBUGGER_ASSERT(flag <= BIOSAL_VERTEX_FLAG_END_VALUE);

    if (flag == BIOSAL_VERTEX_FLAG_UNITIG) {
        ++concrete_self->unitig_vertex_count;
    }

#if 0
    printf("DEBUG ACTION_SET_VERTEX_FLAG %d\n", flag);
#endif
    vertex = biosal_assembly_graph_store_find_vertex(self, &transport_kmer);

    CORE_DEBUGGER_ASSERT_NOT_NULL(vertex);

    biosal_dna_kmer_destroy(&transport_kmer, ephemeral_memory);

    biosal_assembly_vertex_set_flag(vertex, flag);

    thorium_actor_send_reply_empty(self, ACTION_SET_VERTEX_FLAG_REPLY);
}
Ejemplo n.º 11
0
/* \see http://www.mpich.org/static/docs/v3.1/www3/MPI_Isend.html */
int thorium_mpi1_pt2pt_transport_send(struct thorium_transport *self, struct thorium_message *message)
{
    struct thorium_mpi1_pt2pt_transport *concrete_self;
    char *buffer;
    int count;
    int destination;
    int tag;
    MPI_Request *request;
    struct thorium_mpi1_pt2pt_active_request active_request;
    int worker;
    int result;

    concrete_self = thorium_transport_get_concrete_transport(self);

    worker = thorium_message_worker(message);
    buffer = thorium_message_buffer(message);
    count = thorium_message_count(message);
    destination = thorium_message_destination_node(message);
    tag = DUMMY_TAG;

    thorium_mpi1_pt2pt_active_request_init(&active_request, buffer, worker);
    request = thorium_mpi1_pt2pt_active_request_request(&active_request);

    CORE_DEBUGGER_ASSERT(buffer == NULL || count > 0);

    /* get return value */
    result = MPI_Isend(buffer, count, concrete_self->datatype, destination, tag,
                    concrete_self->comm, request);

    if (result != MPI_SUCCESS) {
        return 0;
    }

    /* store the MPI_Request to test it later to know when
     * the buffer can be reused
     */
    /* \see http://blogs.cisco.com/performance/mpi_request_free-is-evil/
     */
    /*MPI_Request_free(&request);*/

    core_fast_queue_enqueue(&concrete_self->active_requests, &active_request);

    return 1;
}
Ejemplo n.º 12
0
int thorium_message_unpack_double(struct thorium_message *message, int offset, double *value)
{
    int bytes;
    void *buffer;
    double *pointer;

    if (offset >= thorium_message_count(message)) {
        return -1;
    }

    bytes = sizeof(double);
    buffer = thorium_message_buffer(message);

    pointer = (double *)((char *)buffer + offset);

    *value = *pointer;

    return bytes;
}
Ejemplo n.º 13
0
int thorium_message_unpack_int64_t(struct thorium_message *message, int offset, int64_t *value)
{
    int bytes;
    void *buffer;
    int64_t *pointer;

    if (offset >= thorium_message_count(message)) {
        return -1;
    }

    bytes = sizeof(int64_t);
    buffer = thorium_message_buffer(message);

    pointer = (int64_t *)((char *)buffer + offset);

    *value = *pointer;

    return bytes;
}
Ejemplo n.º 14
0
int thorium_message_unpack_2_int(struct thorium_message *message, int *value1, int *value2)
{
    int offset;
    int count;
    int required;

    count = thorium_message_count(message);

    required = sizeof(*value1) + sizeof(*value2);

    if (required > count) {
        return -1;
    }

    offset = 0;
    offset += thorium_message_unpack_int(message, offset, value1);
    offset += thorium_message_unpack_int(message, offset, value2);

    return offset;
}
Ejemplo n.º 15
0
void biosal_input_stream_count_reply_mock(struct thorium_actor *self, struct thorium_message *message)
{
    struct biosal_input_stream *concrete_self;
    void *buffer;
    int count;
    struct core_vector mega_blocks;
    char *file;
    struct core_memory_pool *ephemeral_memory;
    uint64_t result;
    struct biosal_mega_block *block;

    concrete_self = (struct biosal_input_stream *)thorium_actor_concrete_actor(self);
    buffer = thorium_message_buffer(message);
    count = thorium_message_count(message);
    ephemeral_memory = thorium_actor_get_ephemeral_memory(self);

    core_vector_init(&mega_blocks, 0);
    core_vector_set_memory_pool(&mega_blocks, ephemeral_memory);
    core_vector_unpack(&mega_blocks, buffer);

    block = core_vector_at_last(&mega_blocks);

    result = biosal_mega_block_get_entries(block);

#if 0
    file = core_string_get(&concrete_self->file_for_parallel_counting);
#endif

    file = concrete_self->file_name;

    printf("%s/%d COUNT_IN_PARALLEL result for %s is %" PRIu64 "\n",
                    thorium_actor_script_name(self),
                    thorium_actor_name(self),
                    file,
                    result);

    core_vector_destroy(&mega_blocks);

    thorium_actor_send_buffer(self, concrete_self->controller,
                    ACTION_INPUT_COUNT_IN_PARALLEL_REPLY, count, buffer);
}
Ejemplo n.º 16
0
void biosal_input_stream_count_in_parallel_mock(struct thorium_actor *self, struct thorium_message *message)
{
    struct biosal_input_stream *concrete_self;
    void *buffer;
    int count;
    char *file;

    concrete_self = (struct biosal_input_stream *)thorium_actor_concrete_actor(self);

    buffer = thorium_message_buffer(message);
    count = thorium_message_count(message);

    file = concrete_self->file_name;

    printf("%s/%d receives ACTION_INPUT_COUNT_IN_PARALLEL file %s\n",
                    thorium_actor_script_name(self),
                    thorium_actor_name(self),
                    file);

    thorium_actor_send_to_self_buffer(self, ACTION_INPUT_COUNT, count, buffer);
}
Ejemplo n.º 17
0
void thorium_transport_print_event(struct thorium_transport *self, int type, struct thorium_message *message)
{
    char *description;
    int count;
    int source_rank;
    int destination_rank;
    uint64_t time;

    description = EVENT_STRING_SEND;

    if (type == EVENT_TYPE_RECEIVE)
        description = EVENT_STRING_RECEIVE;

    count = thorium_message_count(message);
    source_rank = thorium_message_source_node(message);
    destination_rank = thorium_message_destination_node(message);

    time = core_timer_get_nanoseconds(&self->timer);
    time -= self->start_time;
    printf("thorium_transport print_event time_nanoseconds= %" PRIu64 " type= %s source= %d destination= %d count= %d\n",
                    time, description,
                    source_rank, destination_rank, count);
}
Ejemplo n.º 18
0
void biosal_input_stream_push_sequences(struct thorium_actor *actor,
                struct thorium_message *message)
{
    struct biosal_input_command command;
    void *buffer;
    int store_name;
    uint64_t store_first;
    uint64_t store_last;
    int sequences_to_read;
    void *new_buffer;
    int new_count;
    struct thorium_message new_message;
    void *buffer_for_sequence;
    struct biosal_dna_sequence dna_sequence;
    /*struct core_vector *command_entries;*/
    int has_sequence;
    int i;
    struct biosal_input_stream *concrete_self;

#ifdef BIOSAL_INPUT_STREAM_DEBUG
    int count;
    int actual_count;
#endif

    /* answer immediately
     */
    thorium_actor_send_reply_empty(actor, ACTION_INPUT_PUSH_SEQUENCES_READY);
    has_sequence = 1;

#ifdef BIOSAL_INPUT_STREAM_DEBUG
    printf("DEBUG stream/%d biosal_input_stream_push_sequences entering...\n",
                    thorium_actor_name(actor));
#endif


    buffer = thorium_message_buffer(message);

    concrete_self = (struct biosal_input_stream *)thorium_actor_concrete_actor(actor);

    biosal_input_command_init_empty(&command);
    biosal_input_command_unpack(&command, buffer, thorium_actor_get_ephemeral_memory(actor),
                    &concrete_self->codec);

#ifdef BIOSAL_INPUT_STREAM_DEBUG
    count = thorium_message_count(message);
    printf("DEBUG biosal_input_stream_push_sequences after unpack, count %d:\n",
                    count);

    biosal_input_command_print(&command);
#endif

    store_name = biosal_input_command_store_name(&command);
    store_first = biosal_input_command_store_first(&command);
    store_last = biosal_input_command_store_last(&command);

    sequences_to_read = store_last - store_first + 1;

#ifdef BIOSAL_INPUT_STREAM_DEBUG
    printf("DEBUG biosal_input_stream_push_sequences received ACTION_INPUT_PUSH_SEQUENCES\n");
    printf("DEBUG Command before sending it\n");

    biosal_input_command_print(&command);
#endif

    /*
     * add sequences to the input command
     */

    buffer_for_sequence = concrete_self->buffer_for_sequence;
    /*command_entries = biosal_input_command_entries(&command);*/

    i = 0;
    /* TODO: actually load something
     */
    while (sequences_to_read-- && has_sequence) {
        has_sequence = biosal_input_proxy_get_sequence(&concrete_self->proxy,
                            buffer_for_sequence);

        biosal_dna_sequence_init(&dna_sequence, buffer_for_sequence,
                        &concrete_self->codec, thorium_actor_get_ephemeral_memory(actor));

        biosal_input_command_add_entry(&command, &dna_sequence, &concrete_self->codec,
                        thorium_actor_get_ephemeral_memory(actor));

        biosal_dna_sequence_destroy(&dna_sequence, thorium_actor_get_ephemeral_memory(actor));

        i++;
    }

#ifdef BIOSAL_INPUT_STREAM_DEBUG
    printf("DEBUG prepared %d sequences for command\n",
                    i);
    biosal_input_command_print(&command);
#endif

    new_count = biosal_input_command_pack_size(&command,
                    &concrete_self->codec);

    new_buffer = thorium_actor_allocate(actor, new_count);

    biosal_input_command_pack(&command, new_buffer, &concrete_self->codec);

#ifdef BIOSAL_INPUT_STREAM_DEBUG
    actual_count = biosal_input_command_pack(&command, new_buffer);
    printf("DEBUG123 new_count %d actual_count %d\n", new_count,
                    actual_count);
#endif

    thorium_message_init(&new_message, ACTION_PUSH_SEQUENCE_DATA_BLOCK,
                    new_count, new_buffer);

#ifdef BIOSAL_INPUT_STREAM_DEBUG
    printf("DEBUG biosal_input_stream_push_sequences sending ACTION_PUSH_SEQUENCE_DATA_BLOCK to %d\n",
                    store_name);
#endif

    thorium_actor_send(actor, store_name, &new_message);

    /*
     * send sequences to store.
     * The required information is the input command
     */
    /*
    thorium_actor_send_reply_empty(actor, ACTION_INPUT_PUSH_SEQUENCES_REPLY);
    */

    /* free memory
     */

#ifdef BIOSAL_INPUT_STREAM_DEBUG
    printf("DEBUG freeing %d entries\n",
                    (int)core_vector_size(command_entries));
#endif

    biosal_input_command_destroy(&command, thorium_actor_get_ephemeral_memory(actor));

#if 0
    for (i = 0; i < core_vector_size(command_entries); i++) {
        a_sequence = (struct biosal_dna_sequence *)core_vector_at(command_entries, i);

        biosal_dna_sequence_destroy(a_sequence, thorium_actor_get_ephemeral_memory(actor));
    }

    core_vector_destroy(command_entries);
#endif

#ifdef BIOSAL_INPUT_STREAM_DEBUG
    printf("DEBUG biosal_input_stream_push_sequences EXIT\n");
#endif

}
Ejemplo n.º 19
0
/*
 * Returns 1 if the message was multiplexed.
 *
 * This is O(1) in regard to the number of thorium nodes.
 */
int thorium_message_multiplexer_multiplex(struct thorium_message_multiplexer *self,
                struct thorium_message *message)
{
    /*
     * If buffer is full, use thorium_node_send_with_transport
     *
     * get count
     *
     * if count is below or equal to the threshold
     *      multiplex the message.
     *      return 1
     *
     * return 0
     */

    int count;
    int current_size;
    int maximum_size;
    int action;
    struct core_memory_pool *pool;
    void *new_buffer;
    int new_count;
    void *buffer;
    int destination_node;
    int destination_actor;
    int new_size;
    int required_size;
    struct thorium_multiplexed_buffer *real_multiplexed_buffer;
    uint64_t time;
    int next_node_in_route;
    int source_node;
    int current_node;

#ifdef DEBUG_MULTIPLEXER
    thorium_printf("multiplex\n");
    thorium_message_print(message);
#endif

    if (CORE_BITMAP_GET_FLAG(self->flags, FLAG_DISABLED)) {
        return 0;
    }

    action = thorium_message_action(message);

    CORE_DEBUGGER_ASSERT(action != ACTION_INVALID);

#ifdef THORIUM_MULTIPLEXER_USE_ACTIONS_TO_SKIP
    /*
     * Don't multiplex already-multiplexed messages.
     */
    if (thorium_multiplexer_policy_is_action_to_skip(self->policy, action)) {
        return 0;
    }
#endif

#ifdef CONFIG_MULTIPLEXER_USE_DECISION_MAKER
    thorium_message_multiplexer_update_timeout(self);
#endif

    ++self->original_message_count;

    count = thorium_message_count(message);

    destination_node = thorium_message_destination_node(message);

    source_node = message->routing_source;
    current_node = self->node->name;
    next_node_in_route = thorium_router_get_next_rank_in_route(&self->router,
                    source_node, current_node, destination_node);

    /*
    thorium_message_print(message);
    thorium_printf("router: source_node %d current_node %d next_node_in_route %d"
                    " destination_node %d\n",
                    source_node, current_node,
                    next_node_in_route, destination_node);
                    */

#ifdef CONFIG_USE_TOPOLOGY_AWARE_AGGREGATION
    /*
     * The next node in the route for this message is
     * next_node_in_route.
     */
    destination_node = next_node_in_route;
#endif

    CORE_DEBUGGER_ASSERT(source_node >= 0);

    real_multiplexed_buffer = core_vector_at(&self->buffers, destination_node);

    CORE_DEBUGGER_ASSERT(real_multiplexed_buffer != NULL);

    required_size = thorium_multiplexed_buffer_required_size(real_multiplexed_buffer, count);

    buffer = thorium_message_buffer(message);
    destination_actor = thorium_message_destination(message);

#ifdef DEBUG_MULTIPLEXER
    thorium_printf("DEBUG multiplex count %d required_size %d action %x\n",
                    count, required_size, action);
#endif

    /*
     * Don't multiplex non-actor messages.
     */
    if (destination_actor == THORIUM_ACTOR_NOBODY) {
        return 0;
    }

#ifdef CORE_DEBUGGER_ASSERT
    if (real_multiplexed_buffer == NULL) {
        thorium_printf("Error action %d destination_node %d destination_actor %d\n", action, destination_node,
                        destination_actor);
    }
#endif

    current_size = thorium_multiplexed_buffer_current_size(real_multiplexed_buffer);
    maximum_size = thorium_multiplexed_buffer_maximum_size(real_multiplexed_buffer);

    /*
     * Don't multiplex large messages.
     */
    if (required_size > maximum_size) {

#ifdef DEBUG_MULTIPLEXER
        thorium_printf("too large required_size %d maximum_size %d\n", required_size, maximum_size);
#endif
        return 0;
    }

    /*
    thorium_printf("MULTIPLEX_MESSAGE\n");
    */

    new_size = current_size + required_size;

    /*
     * Flush now if there is no space left for the <required_size> bytes
     */
    if (new_size > maximum_size) {

#ifdef DEBUG_MULTIPLEXER
        thorium_printf("thorium_message_multiplexer: must FLUSH thorium_message_multiplexer_multiplex required_size %d new_size %d maximum_size %d\n",
                    required_size, new_size, maximum_size);
#endif

        thorium_message_multiplexer_flush(self, destination_node, FORCE_YES_SIZE);
        current_size = thorium_multiplexed_buffer_current_size(real_multiplexed_buffer);

        CORE_DEBUGGER_ASSERT(current_size == 0);
    }

    time = core_timer_get_nanoseconds(&self->timer);

    /*
     * If the buffer is empty before adding the data, it means that it is not
     * in the list of buffers with content and it must be added.
     */
    if (current_size == 0) {

        thorium_multiplexed_buffer_set_time(real_multiplexed_buffer, time);

#ifdef THORIUM_MULTIPLEXER_TRACK_BUFFERS_WITH_CONTENT
        core_set_add(&self->buffers_with_content, &destination_node);
#endif

        /*
         * Add it to the timeline.
         */

#ifdef THORIUM_MULTIPLEXER_USE_TREE
        core_red_black_tree_add_key_and_value(&self->timeline, &time, &destination_node);

#elif defined(THORIUM_MULTIPLEXER_USE_HEAP)
        core_binary_heap_insert(&self->timeline, &time, &destination_node);
#elif defined(THORIUM_MULTIPLEXER_USE_QUEUE)
        core_queue_enqueue(&self->timeline, &destination_node);
#endif

    }

    /*
     * The allocation of buffer is lazy.
     * The current worker is an exporter of small message for the destination
     * "destination_node".
     */
    if (thorium_multiplexed_buffer_buffer(real_multiplexed_buffer) == NULL) {
        pool = thorium_worker_get_outbound_message_memory_pool(self->worker);

        new_count = self->buffer_size_in_bytes + THORIUM_MESSAGE_METADATA_SIZE;
        new_buffer = core_memory_pool_allocate(pool, new_count);

        thorium_multiplexed_buffer_set_buffer(real_multiplexed_buffer, new_buffer);
    }

    /*
    thorium_printf("DEBUG worker_latency %d ns\n",
                    thorium_worker_latency(self->worker));
                    */

    thorium_multiplexed_buffer_append(real_multiplexed_buffer, count, buffer, time);

    /*
     * Try to flush. This only flushes something if the buffer is full.
     */

    if (thorium_message_multiplexer_buffer_is_ready(self, real_multiplexed_buffer)) {

        /*
         * Try to flush here too. This is required in order to satisfy the
         * technical requirement of a DOA limit.
         *
         * Obviously, don't flush if there is some outbound traffic congestion.
         * Otherwise, there will be too many messages on the network.
         */
        if (!thorium_worker_has_outbound_traffic_congestion(self->worker)) {
            thorium_message_multiplexer_flush(self, destination_node, FORCE_YES_SIZE);
        }
    }

    /*
     * Verify invariant.
     */
    CORE_DEBUGGER_ASSERT(thorium_multiplexed_buffer_current_size(real_multiplexed_buffer)<= maximum_size);

    /*
     * Inject the buffer into the worker too.
     */
    return 1;
}
Ejemplo n.º 20
0
void biosal_assembly_graph_store_get_vertex(struct thorium_actor *self, struct thorium_message *message)
{
    struct biosal_assembly_vertex vertex;
    struct biosal_dna_kmer kmer;
    void *buffer;
    struct biosal_assembly_graph_store *concrete_self;
    struct core_memory_pool *ephemeral_memory;
    struct thorium_message new_message;
    int new_count;
    void *new_buffer;
    struct biosal_assembly_vertex *canonical_vertex;
    int is_canonical;
    int path;
    int position;
    int count;

    path = -1;
    ephemeral_memory = thorium_actor_get_ephemeral_memory(self);
    concrete_self = thorium_actor_concrete_actor(self);

    buffer = thorium_message_buffer(message);
    count = thorium_message_count(message);

    biosal_dna_kmer_init_empty(&kmer);

    position = 0;
    position += biosal_dna_kmer_unpack(&kmer, buffer, concrete_self->kmer_length,
                ephemeral_memory,
                &concrete_self->transport_codec);

    /*
     * Check if a path index was provided too.
     */
    if (position < count) {
        position += thorium_message_unpack_int(message, position, &path);
    }

    CORE_DEBUGGER_ASSERT_IS_EQUAL_INT(position, count);
    CORE_DEBUGGER_ASSERT(position == count);

    canonical_vertex = biosal_assembly_graph_store_find_vertex(self, &kmer);

    biosal_assembly_vertex_init_copy(&vertex, canonical_vertex);

    is_canonical = biosal_dna_kmer_is_canonical(&kmer, concrete_self->kmer_length,
                    &concrete_self->transport_codec);

    if (!is_canonical) {

        biosal_assembly_vertex_invert_arcs(&vertex);
    }

    biosal_dna_kmer_destroy(&kmer, ephemeral_memory);

    new_count = biosal_assembly_vertex_pack_size(&vertex);
    new_buffer = thorium_actor_allocate(self, new_count);

    biosal_assembly_vertex_pack(&vertex, new_buffer);

    thorium_message_init(&new_message, ACTION_ASSEMBLY_GET_VERTEX_REPLY,
                    new_count, new_buffer);

    thorium_actor_send_reply(self, &new_message);

    thorium_message_destroy(&new_message);
}
Ejemplo n.º 21
0
void biosal_assembly_graph_store_push_arc_block(struct thorium_actor *self, struct thorium_message *message)
{
    struct biosal_assembly_graph_store *concrete_self;
    int size;
    int i;
    void *buffer;
    int count;
    struct biosal_assembly_arc_block input_block;
    struct biosal_assembly_arc *arc;
    struct core_memory_pool *ephemeral_memory;
    struct core_vector *input_arcs;
    char *sequence;
    void *key;

#if 0
    /*
     * Don't do anything to rule out that this is the problem.
     */
    thorium_actor_send_reply_empty(self, ACTION_ASSEMBLY_PUSH_ARC_BLOCK_REPLY);
    return;
#endif

    concrete_self = thorium_actor_concrete_actor(self);
    ephemeral_memory = thorium_actor_get_ephemeral_memory(self);

    sequence = core_memory_pool_allocate(ephemeral_memory, concrete_self->kmer_length + 1);

    ++concrete_self->received_arc_block_count;

    count = thorium_message_count(message);
    buffer = thorium_message_buffer(message);

    biosal_assembly_arc_block_init(&input_block, ephemeral_memory, concrete_self->kmer_length,
                    &concrete_self->transport_codec);

    biosal_assembly_arc_block_unpack(&input_block, buffer, concrete_self->kmer_length,
                    &concrete_self->transport_codec, ephemeral_memory);

    input_arcs = biosal_assembly_arc_block_get_arcs(&input_block);
    size = core_vector_size(input_arcs);

    if (!concrete_self->printed_arc_size) {
        printf("DEBUG ARC DELIVERY %d bytes, %d arcs\n",
                    count, size);

        concrete_self->printed_arc_size = 1;
    }

    key = core_memory_pool_allocate(ephemeral_memory, concrete_self->key_length_in_bytes);

    for (i = 0; i < size; i++) {

        arc = core_vector_at(input_arcs, i);

#ifdef BIOSAL_ASSEMBLY_ADD_ARCS
        biosal_assembly_graph_store_add_arc(self, arc, sequence, key);
#endif

        ++concrete_self->received_arc_count;
    }

    core_memory_pool_free(ephemeral_memory, key);

    biosal_assembly_arc_block_destroy(&input_block, ephemeral_memory);

    /*
     *
     * Add the arcs to the graph
     */

    thorium_actor_send_reply_empty(self, ACTION_ASSEMBLY_PUSH_ARC_BLOCK_REPLY);

    core_memory_pool_free(ephemeral_memory, sequence);
}
Ejemplo n.º 22
0
void biosal_assembly_graph_store_push_kmer_block(struct thorium_actor *self, struct thorium_message *message)
{
    struct core_memory_pool *ephemeral_memory;
    struct biosal_dna_kmer_frequency_block block;
    struct biosal_assembly_vertex *bucket;
    void *packed_kmer;
    struct core_map_iterator iterator;
    struct biosal_assembly_graph_store *concrete_self;
    /*int tag;*/
    void *key;
    struct core_map *kmers;
    struct biosal_dna_kmer kmer;
    void *buffer;
    int count;
    struct biosal_dna_kmer encoded_kmer;
    char *raw_kmer;
    int period;
    struct biosal_dna_kmer *kmer_pointer;
    int *frequency;

    ephemeral_memory = thorium_actor_get_ephemeral_memory(self);
    concrete_self = thorium_actor_concrete_actor(self);
    /*tag = thorium_message_action(message);*/
    buffer = thorium_message_buffer(message);
    count = thorium_message_count(message);

    /*
     * Handler for PUSH_DATA
     */

    biosal_dna_kmer_frequency_block_init(&block, concrete_self->kmer_length,
                    ephemeral_memory, &concrete_self->transport_codec, 0);

    biosal_dna_kmer_frequency_block_unpack(&block, buffer, ephemeral_memory,
                    &concrete_self->transport_codec);

    key = core_memory_pool_allocate(ephemeral_memory, concrete_self->key_length_in_bytes);

    kmers = biosal_dna_kmer_frequency_block_kmers(&block);
    core_map_iterator_init(&iterator, kmers);

    period = 2500000;

    raw_kmer = core_memory_pool_allocate(thorium_actor_get_ephemeral_memory(self),
                    concrete_self->kmer_length + 1);

    if (!concrete_self->printed_vertex_size) {

        printf("DEBUG VERTEX DELIVERY %d bytes\n", count);

        concrete_self->printed_vertex_size = 1;
    }

    while (core_map_iterator_has_next(&iterator)) {

        /*
         * add kmers to store
         */
        core_map_iterator_next(&iterator, (void **)&packed_kmer, (void **)&frequency);

        /* Store the kmer in 2 bit encoding
         */

        biosal_dna_kmer_init_empty(&kmer);
        biosal_dna_kmer_unpack(&kmer, packed_kmer, concrete_self->kmer_length,
                    ephemeral_memory,
                    &concrete_self->transport_codec);

        kmer_pointer = &kmer;

        if (concrete_self->codec_are_different) {
            /*
             * Get a copy of the sequence
             */
            biosal_dna_kmer_get_sequence(kmer_pointer, raw_kmer, concrete_self->kmer_length,
                        &concrete_self->transport_codec);


            biosal_dna_kmer_init(&encoded_kmer, raw_kmer, &concrete_self->storage_codec,
                        thorium_actor_get_ephemeral_memory(self));
            kmer_pointer = &encoded_kmer;
        }

        biosal_dna_kmer_pack_store_key(kmer_pointer, key,
                        concrete_self->kmer_length, &concrete_self->storage_codec,
                        thorium_actor_get_ephemeral_memory(self));

#ifdef BIOSAL_DEBUG_ISSUE_540
        if (strcmp(raw_kmer, "AGCTGGTAGTCATCACCAGACTGGAACAG") == 0
                        || strcmp(raw_kmer, "CGCGATCTGTTGCTGGGCCTAACGTGGTA") == 0
                        || strcmp(raw_kmer, "TACCACGTTAGGCCCAGCAACAGATCGCG") == 0) {
            printf("Examine store key for %s\n", raw_kmer);

            core_debugger_examine(key, concrete_self->key_length_in_bytes);
        }
#endif

        bucket = core_map_get(&concrete_self->table, key);

        if (bucket == NULL) {
            /* This is the first time that this kmer is seen.
             */
            bucket = core_map_add(&concrete_self->table, key);

            biosal_assembly_vertex_init(bucket);

#if 0
            printf("DEBUG303 ADD_KEY");
            biosal_dna_kmer_print(&encoded_kmer, concrete_self->kmer_length,
                            &concrete_self->storage_codec, ephemeral_memory);
#endif
        }

        if (concrete_self->codec_are_different) {
            biosal_dna_kmer_destroy(&encoded_kmer,
                        thorium_actor_get_ephemeral_memory(self));
        }

        biosal_dna_kmer_destroy(&kmer, ephemeral_memory);

        biosal_assembly_vertex_increase_coverage_depth(bucket, *frequency);

        if (concrete_self->received >= concrete_self->last_received + period) {
            printf("%s/%d received %" PRIu64 " kmers so far,"
                            " store has %" PRIu64 " canonical kmers, %" PRIu64 " kmers\n",
                        thorium_actor_script_name(self),
                            thorium_actor_name(self), concrete_self->received,
                            core_map_size(&concrete_self->table),
                            2 * core_map_size(&concrete_self->table));

            concrete_self->last_received = concrete_self->received;
        }

        concrete_self->received += *frequency;
    }

    core_memory_pool_free(ephemeral_memory, key);
    core_memory_pool_free(ephemeral_memory, raw_kmer);

    core_map_iterator_destroy(&iterator);
    biosal_dna_kmer_frequency_block_destroy(&block, thorium_actor_get_ephemeral_memory(self));

    thorium_actor_send_reply_empty(self, ACTION_PUSH_KMER_BLOCK_REPLY);
}
Ejemplo n.º 23
0
void biosal_coverage_distribution_receive(struct thorium_actor *self, struct thorium_message *message)
{
    int tag;
    struct core_map map;
    struct core_map_iterator iterator;
    int *coverage_from_message;
    uint64_t *count_from_message;
    uint64_t *frequency;
    int count;
    void *buffer;
    struct biosal_coverage_distribution *concrete_actor;
    int name;
    int source;
    struct core_memory_pool *ephemeral_memory;

    ephemeral_memory = thorium_actor_get_ephemeral_memory(self);
    name = thorium_actor_name(self);
    source = thorium_message_source(message);
    concrete_actor = (struct biosal_coverage_distribution *)thorium_actor_concrete_actor(self);
    tag = thorium_message_action(message);
    count = thorium_message_count(message);
    buffer = thorium_message_buffer(message);

    if (tag == ACTION_PUSH_DATA) {

        core_map_init(&map, 0, 0);
        core_map_set_memory_pool(&map, ephemeral_memory);
        core_map_unpack(&map, buffer);

        core_map_iterator_init(&iterator, &map);


        while (core_map_iterator_has_next(&iterator)) {

            core_map_iterator_next(&iterator, (void **)&coverage_from_message,
                            (void **)&count_from_message);

#ifdef BIOSAL_COVERAGE_DISTRIBUTION_DEBUG
            thorium_actor_log(self, "DEBUG DATA %d %d\n", (int)*coverage_from_message, (int)*count_from_message);
#endif

            frequency = core_map_get(&concrete_actor->distribution, coverage_from_message);

            if (frequency == NULL) {

                frequency = core_map_add(&concrete_actor->distribution, coverage_from_message);

                (*frequency) = 0;
            }

            (*frequency) += (*count_from_message);
        }

        core_map_iterator_destroy(&iterator);

        thorium_actor_send_reply_empty(self, ACTION_PUSH_DATA_REPLY);

        concrete_actor->actual++;

        thorium_actor_log(self, "distribution/%d receives coverage data from producer/%d, %d entries / %d bytes %d/%d\n",
                        name, source, (int)core_map_size(&map), count,
                        concrete_actor->actual, concrete_actor->expected);

        if (concrete_actor->expected != 0 && concrete_actor->expected == concrete_actor->actual) {

            thorium_actor_log(self, "received everything %d/%d\n", concrete_actor->actual, concrete_actor->expected);

            biosal_coverage_distribution_write_distribution(self);

            thorium_actor_send_empty(self, concrete_actor->source,
                            ACTION_NOTIFY);
        }

        core_map_destroy(&map);

    } else if (tag == ACTION_ASK_TO_STOP) {

        biosal_coverage_distribution_ask_to_stop(self, message);

    } else if (tag == ACTION_SET_EXPECTED_MESSAGE_COUNT) {

        concrete_actor->source = source;
        thorium_message_unpack_int(message, 0, &concrete_actor->expected);

        thorium_actor_log(self, "distribution %d expects %d messages\n",
                        thorium_actor_name(self),
                        concrete_actor->expected);

        thorium_actor_send_reply_empty(self, ACTION_SET_EXPECTED_MESSAGE_COUNT_REPLY);
    }
}
Ejemplo n.º 24
0
void core_writer_process_receive(struct thorium_actor *self, struct thorium_message *message)
{
    int action;
    int count;
    int source;
    char *buffer;
    char *file_name;
    struct core_writer_process *concrete_self;

    concrete_self = thorium_actor_concrete_actor(self);

    action = thorium_message_action(message);
    count = thorium_message_count(message);
    buffer = thorium_message_buffer(message);
    source = thorium_message_source(message);

    if (action == ACTION_OPEN) {

        if (concrete_self->has_file) {
            thorium_actor_log(self, "actor error, already open, can not open\n");
            return;
        }

        file_name = buffer;

        core_buffered_file_writer_init(&concrete_self->writer, file_name);

        concrete_self->has_file = 1;

        thorium_actor_send_reply_empty(self, ACTION_OPEN_REPLY);

    } else if (action == ACTION_WRITE) {

        core_buffered_file_writer_write(&concrete_self->writer, buffer, count);

        thorium_actor_send_reply_empty(self, ACTION_WRITE_REPLY);

    } else if (action == ACTION_CLOSE) {

        if (!concrete_self->has_file) {
            thorium_actor_log(self, "Error, can not close a file that is not open\n");
            return;
        }

        core_buffered_file_writer_destroy(&concrete_self->writer);
        concrete_self->has_file = 0;

        thorium_actor_send_reply_empty(self, ACTION_CLOSE_REPLY);

    } else if (action == ACTION_ASK_TO_STOP
                    && source == thorium_actor_supervisor(self)) {

        /*
         * Close the file if it is open
         * right now.
         */
        if (concrete_self->has_file) {

            core_buffered_file_writer_destroy(&concrete_self->writer);
            concrete_self->has_file = 0;
        }

        thorium_actor_send_to_self_empty(self, ACTION_STOP);

        thorium_actor_send_reply_empty(self, ACTION_ASK_TO_STOP_REPLY);
    }
}
Ejemplo n.º 25
0
void biosal_assembly_arc_classifier_push_arc_block(struct thorium_actor *self, struct thorium_message *message)
{
    struct biosal_assembly_arc_classifier *concrete_self;
    int source;
    struct biosal_assembly_arc_block input_block;
    struct biosal_assembly_arc_block *output_block;
    struct core_vector output_blocks;
    struct core_memory_pool *ephemeral_memory;
    int consumer_count;
    struct core_vector *input_arcs;
    struct core_vector *output_arcs;
    int size;
    int i;
    struct biosal_assembly_arc *arc;
    void *buffer;
    int count;
    struct biosal_dna_kmer *kmer;
    int consumer_index;
    int arc_count;
    int consumer;
    struct thorium_message new_message;
    int new_count;
    void *new_buffer;
    int *bucket;
    int maximum_pending_requests;
    int maximum_buffer_length;
    int reservation;

    count = thorium_message_count(message);
    buffer = thorium_message_buffer(message);

    if (count == 0) {
        printf("Error, count is 0 (classifier_push_arc_block)\n");
        return;
    }

    concrete_self = (struct biosal_assembly_arc_classifier *)thorium_actor_concrete_actor(self);
    source = thorium_message_source(message);
    consumer_count = core_vector_size(&concrete_self->consumers);
    ephemeral_memory = thorium_actor_get_ephemeral_memory(self);

    CORE_DEBUGGER_LEAK_DETECTION_BEGIN(ephemeral_memory, classify_arcs);

    core_vector_init(&output_blocks, sizeof(struct biosal_assembly_arc_block));
    core_vector_set_memory_pool(&output_blocks, ephemeral_memory);

    biosal_assembly_arc_block_init(&input_block, ephemeral_memory, concrete_self->kmer_length,
                    &concrete_self->codec);

#ifdef BIOSAL_ASSEMBLY_ARC_CLASSIFIER_DEBUG
    printf("UNPACKING\n");
#endif

    biosal_assembly_arc_block_unpack(&input_block, buffer, concrete_self->kmer_length,
                    &concrete_self->codec, ephemeral_memory);

#ifdef BIOSAL_ASSEMBLY_ARC_CLASSIFIER_DEBUG
    printf("OK\n");
#endif

    input_arcs = biosal_assembly_arc_block_get_arcs(&input_block);

    /*
     * Configure the ephemeral memory reservation.
     */
    arc_count = core_vector_size(input_arcs);
    reservation = (arc_count / consumer_count) * 2;

    core_vector_resize(&output_blocks, consumer_count);

    CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory));

    /*
     * Initialize output blocks.
     * There is one for each destination.
     */
    for (i = 0; i < consumer_count; i++) {

        output_block = core_vector_at(&output_blocks, i);

        biosal_assembly_arc_block_init(output_block, ephemeral_memory, concrete_self->kmer_length,
                        &concrete_self->codec);

        biosal_assembly_arc_block_reserve(output_block, reservation);
    }

    size = core_vector_size(input_arcs);

    /*
     * Classify every arc in the input block
     * and put them in output blocks.
     */

#ifdef BIOSAL_ASSEMBLY_ARC_CLASSIFIER_DEBUG
    printf("ClassifyArcs arc_count= %d\n", size);

#endif

    CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory));

    for (i = 0; i < size; i++) {

        arc = core_vector_at(input_arcs, i);

        kmer = biosal_assembly_arc_source(arc);

        consumer_index = biosal_dna_kmer_store_index(kmer, consumer_count,
                        concrete_self->kmer_length, &concrete_self->codec,
                        ephemeral_memory);

        output_block = core_vector_at(&output_blocks, consumer_index);

        /*
         * Make a copy of the arc and copy it.
         * It will be freed
         */

        biosal_assembly_arc_block_add_arc_copy(output_block, arc,
                        concrete_self->kmer_length, &concrete_self->codec,
                        ephemeral_memory);
    }

    /*
     * Input arcs are not needed anymore.
     */
    biosal_assembly_arc_block_destroy(&input_block, ephemeral_memory);

    CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory));

    /*
     * Finally, send these output blocks to consumers.
     */

    maximum_pending_requests = 0;
    maximum_buffer_length = 0;

    /*
     * Figure out the maximum buffer length tor
     * messages.
     */
    for (i = 0; i < consumer_count; i++) {

        output_block = core_vector_at(&output_blocks, i);
        new_count = biosal_assembly_arc_block_pack_size(output_block, concrete_self->kmer_length,
                    &concrete_self->codec);

        if (new_count > maximum_buffer_length) {
            maximum_buffer_length = new_count;
        }
    }

#if 0
    printf("POOL_BALANCE %d\n",
                    core_memory_pool_profile_balance_count(ephemeral_memory));
#endif

    for (i = 0; i < consumer_count; i++) {

        output_block = core_vector_at(&output_blocks, i);
        output_arcs = biosal_assembly_arc_block_get_arcs(output_block);
        arc_count = core_vector_size(output_arcs);

        /*
         * Don't send an empty message.
         */
        if (arc_count > 0) {

            /*
             * Allocation is not required because new_count <= maximum_buffer_length
             */
            new_count = biosal_assembly_arc_block_pack_size(output_block, concrete_self->kmer_length,
                    &concrete_self->codec);

            new_buffer = thorium_actor_allocate(self, maximum_buffer_length);

            CORE_DEBUGGER_ASSERT(new_count <= maximum_buffer_length);

            biosal_assembly_arc_block_pack(output_block, new_buffer, concrete_self->kmer_length,
                    &concrete_self->codec);

            thorium_message_init(&new_message, ACTION_ASSEMBLY_PUSH_ARC_BLOCK,
                    new_count, new_buffer);

            consumer = core_vector_at_as_int(&concrete_self->consumers, i);

            /*
             * Send the message.
             */
            thorium_actor_send(self, consumer, &new_message);
            thorium_message_destroy(&new_message);

            /* update event counters for control.
             */
            bucket = core_vector_at(&concrete_self->pending_requests, i);
            ++(*bucket);
            ++concrete_self->active_requests;

            if (*bucket > maximum_pending_requests) {
                maximum_pending_requests = *bucket;
            }

            if (*bucket > concrete_self->maximum_pending_request_count) {
                ++concrete_self->consumer_count_above_threshold;
            }
        }

        CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory));

#if 0
        printf("i = %d\n", i);
#endif

        /*
         * Destroy output block.
         */
        biosal_assembly_arc_block_destroy(output_block,
                    ephemeral_memory);

        CORE_DEBUGGER_LEAK_CHECK_DOUBLE_FREE(ephemeral_memory);
        CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory));
    }

    core_vector_destroy(&output_blocks);

    CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory));

    CORE_DEBUGGER_LEAK_CHECK_DOUBLE_FREE(ephemeral_memory);

    /*
     * Check if a response must be sent now.
     */

    ++concrete_self->received_blocks;
    concrete_self->source = source;

    /*
     * Only send a direct reply if there is enough memory.
     *
     * As long as maximum_pending_requests is lower than maximum_pending_request_count,
     * there is still space for at least one additional request.
     */
    if (maximum_pending_requests < concrete_self->maximum_pending_request_count
            && core_memory_has_enough_bytes()) {

        thorium_actor_send_empty(self, concrete_self->source,
                    ACTION_ASSEMBLY_PUSH_ARC_BLOCK_REPLY);
    } else {

        concrete_self->producer_is_waiting = 1;
    }

    CORE_DEBUGGER_LEAK_DETECTION_END(ephemeral_memory, classify_arcs);
}
Ejemplo n.º 26
0
static void source_receive(struct thorium_actor *self, struct thorium_message *message)
{
    int action;
    void *buffer;
    int leader;
    int source;
    int count;
    struct source *concrete_self;
    int name;

    concrete_self = (struct source *)thorium_actor_concrete_actor(self);
    action = thorium_message_action(message);
    buffer = thorium_message_buffer(message);
    source = thorium_message_source(message);
    name = thorium_actor_name(self);
    count = thorium_message_count(message);

    if (action == ACTION_ASK_TO_STOP) {

        thorium_actor_log(self, "sent %d ACTION_PING messages\n",
                        concrete_self->message_count);

        thorium_actor_send_to_self_empty(self, ACTION_STOP);

    } else if (action == ACTION_NOTIFY) {

#ifdef LATENCY_PROBE_USE_MULTIPLEXER
        thorium_actor_send_to_self_empty(self, ACTION_ENABLE_MULTIPLEXER);
#endif

        CORE_DEBUGGER_ASSERT(core_vector_empty(&concrete_self->targets));

        core_vector_unpack(&concrete_self->targets, buffer);

        if (source_is_important(self)) {
            printf("%d (node %d worker %d) has %d targets\n", thorium_actor_name(self),
                            thorium_actor_node_name(self),
                            thorium_actor_worker_name(self),
                        (int)core_vector_size(&concrete_self->targets));
        }

        concrete_self->leader = source;
        source_send_ping(self);

    } else if (action == ACTION_PING_REPLY) {

        CORE_DEBUGGER_ASSERT(count == 0);

        ++concrete_self->message_count;

        CORE_DEBUGGER_ASSERT_IS_EQUAL_INT(count, 0);
        CORE_DEBUGGER_ASSERT_IS_NULL(buffer);

        if (concrete_self->message_count % PERIOD == 0 || concrete_self->event_count < 500) {
            if (source_is_important(self)) {
                printf("progress %d %d/%d\n",
                            name, concrete_self->message_count, concrete_self->event_count);
            }
        }

        if (concrete_self->message_count == concrete_self->event_count) {

            leader = concrete_self->leader;
            thorium_actor_send_empty(self, leader, ACTION_NOTIFY_REPLY);

            if (source_is_important(self))
                printf("%d (ACTION_PING sent: %d)"
                            " sends ACTION_NOTIFY_REPLY to %d\n", thorium_actor_name(self),
                            concrete_self->message_count,
                            leader);
        } else {

            source_send_ping(self);
        }
    }
}
Ejemplo n.º 27
0
void thorium_worker_send(struct thorium_worker *worker, struct thorium_message *message)
{
    void *buffer;
    int count;
    void *old_buffer;

    old_buffer = thorium_message_buffer(message);

    /*
     * Allocate a buffer if the actor provided a NULL buffer or if it
     * provided its own buffer.
     */
    if (old_buffer == NULL
                    || old_buffer != worker->zero_copy_buffer) {

        count = thorium_message_count(message);
        /* use slab allocator */
        buffer = thorium_worker_allocate(worker, count);

        /* according to
         * http://stackoverflow.com/questions/3751797/can-i-call-core_memory_copy-and-core_memory_move-with-number-of-bytes-set-to-zero
         * memcpy works with a count of 0, but the addresses must be valid
         * nonetheless
         *
         * Copy the message data.
         */
        if (count > 0) {

#ifdef DISPLAY_COPY_WARNING
            printf("thorium_worker: Warning, not using zero-copy path, action %x count %d source %d destination %d\n",
                            thorium_message_action(message), count, thorium_message_source(message),
                            thorium_message_destination(message));
#endif
            core_memory_copy(buffer, old_buffer, count);
        }

        thorium_message_set_buffer(message, buffer);
    }

    /*
     * Always write metadata.
     */
    thorium_message_write_metadata(message);

#ifdef THORIUM_WORKER_DEBUG_INJECTION
    ++worker->counter_allocated_outbound_buffers;
#endif

#ifdef THORIUM_WORKER_DEBUG_MEMORY
    printf("ALLOCATE %p\n", buffer);
#endif

#ifdef THORIUM_WORKER_DEBUG
    printf("[thorium_worker_send] allocated %i bytes (%i + %i) for buffer %p\n",
                    all, count, metadata_size, buffer);

    printf("thorium_worker_send old buffer: %p\n",
                    thorium_message_buffer(message));
#endif

#ifdef THORIUM_BUG_594
    if (thorium_message_action(&copy) == 30202) {
        printf("DEBUG-594 thorium_worker_send\n");
        thorium_message_print(&copy);
    }
#endif

#ifdef THORIUM_WORKER_DEBUG_20140601
    if (thorium_message_action(message) == 1100) {
        printf("DEBUG thorium_worker_send 1100\n");
    }
#endif

    /* if the destination is on the same node,
     * handle that directly here to avoid locking things
     * with the node.
     */

    thorium_worker_enqueue_message(worker, message);
    worker->zero_copy_buffer = NULL;
}
Ejemplo n.º 28
0
void thorium_worker_work(struct thorium_worker *worker, struct thorium_actor *actor)
{
    int dead;
    int actor_name;

#ifdef THORIUM_WORKER_DEBUG
    int tag;
    int destination;
#endif

    actor_name = thorium_actor_name(actor);

#ifdef THORIUM_WORKER_DEBUG_SCHEDULER
    printf("WORK actor %d\n", actor_name);
#endif

    /* the actor died while the work was queued.
     */
    if (thorium_actor_dead(actor)) {

        printf("NOTICE actor is dead already (thorium_worker_work)\n");

        return;
    }

#ifdef THORIUM_DISABLE_LOCKLESS_ACTORS
    /* lock the actor to prevent another worker from making work
     * on the same actor at the same time
     */
    if (thorium_actor_trylock(actor) != CORE_LOCK_SUCCESS) {

#ifdef SHOW_FULL_RING_WARNINGS
        printf("Warning: CONTENTION worker %d could not lock actor %d, returning the message...\n",
                        thorium_worker_name(worker),
                        actor_name);
#endif

        return;
    }
#endif

    /* the actor died while this worker was waiting for the lock
     */
    if (thorium_actor_dead(actor)) {

        printf("DEBUG thorium_worker_work actor died while the worker was waiting for the lock.\n");
#ifdef THORIUM_WORKER_DEBUG
#endif
        /*thorium_actor_unlock(actor);*/
        return;
    }

    /* call the actor receive code
     */
    thorium_actor_set_worker(actor, worker);

    thorium_actor_work(actor);

    /* Free ephemeral memory
     */
    core_memory_pool_free_all(&worker->ephemeral_memory);

    dead = thorium_actor_dead(actor);

    if (dead) {

        core_map_delete(&worker->actors, &actor_name);

        if (core_bitmap_get_bit_uint32_t(&worker->flags,
                                FLAG_ENABLE_ACTOR_LOAD_PROFILER)) {
            thorium_actor_write_profile(actor, &worker->load_profile_writer);
        }
        thorium_node_notify_death(worker->node, actor);
    }

    thorium_actor_set_worker(actor, NULL);

#ifdef THORIUM_WORKER_DEBUG_20140601
    if (core_bitmap_get_bit_uint32_t(&worker->flags, FLAG_DEBUG)) {
        printf("DEBUG worker/%d after dead call\n",
                        thorium_worker_name(worker));
    }
#endif

#ifdef THORIUM_DISABLE_LOCKLESS_ACTORS
    /* Unlock the actor.
     * This does not do anything if a death notification
     * was sent to the node
     */
    thorium_actor_unlock(actor);
#endif

#ifdef THORIUM_WORKER_DEBUG
    printf("thorium_worker_work Freeing buffer %p %i tag %i\n",
                    buffer, thorium_message_count(message),
                    thorium_message_action(message));
#endif

#ifdef THORIUM_WORKER_DEBUG_20140601
    if (core_bitmap_get_bit_uint32_t(&worker->flags, FLAG_DEBUG)) {
        printf("DEBUG worker/%d exiting thorium_worker_work\n",
                        thorium_worker_name(worker));
    }
#endif
}
Ejemplo n.º 29
0
/*
 * Returns 1 if the message was demultiplexed.
 *
 * This is O(1) in regard to the number of thorium nodes.
 */
int thorium_message_multiplexer_demultiplex(struct thorium_message_multiplexer *self,
                struct thorium_message *message)
{
    /*
     * Algorithm:
     *
     * get tag.
     * if tag is ACTION_MULTIPLEXER_MESSAGE
     *     for every enclosed message
     *         call thorium_node_prepare_received_message
     *         call thorium_node_dispatch_message()
     *     return 1
     *
     * return 0
     */

    int count;
    char *buffer;
    struct thorium_message new_message;
    int new_count;
    void *new_buffer;
    int position;
    struct core_memory_pool *pool;
    int messages;
    int tag;
    int source_node;
    int destination_node;
    int current_node;
    int routing_destination;

#ifdef DEBUG_MULTIPLEXER
    thorium_printf("demultiplex message\n");
    thorium_message_print(message);
#endif

    if (CORE_BITMAP_GET_FLAG(self->flags, FLAG_DISABLED)) {
        return 0;
    }

    tag = thorium_message_action(message);

    if (tag != ACTION_MULTIPLEXER_MESSAGE) {
        return 0;
    }

    /*
    thorium_printf("MULTIPLEXER demultiplex\n");
    */

    messages = 0;
    tracepoint(thorium_node, demultiplex_enter, self->node->name,
                    self->node->tick, messages);

    source_node = thorium_message_source_node(message);
    destination_node = thorium_message_destination_node(message);

    /*
     * Remove the metadata from the count.
     */
    thorium_message_remove_metadata_from_count(message);

    count = thorium_message_count(message);

    buffer = thorium_message_buffer(message);

    pool = thorium_worker_get_outbound_message_memory_pool(self->worker);

    position = 0;

    /*
     * Inject a message for each enclosed message.
     */
    while (position < count) {
        core_memory_copy(&new_count, buffer + position, sizeof(new_count));
        position += sizeof(new_count);

        new_buffer = core_memory_pool_allocate(pool, new_count);
        core_memory_copy(new_buffer, buffer + position, new_count);

        thorium_message_init_with_nodes(&new_message, new_count, new_buffer,
                        source_node, destination_node);

        thorium_node_prepare_received_message(self->node, &new_message);

        /*
         * For these demultiplexed messages, there are 2 outcomes:
         *
         * 1) the message must be delivered locally;
         * 2) the message must be forward because this is a middle node in
         *    the route.
         */
        /*
        thorium_printf("demultiplex: \n");
        thorium_message_print(&new_message);
        thorium_printf("\n");
*/
        /*
         * Mark the message for recycling.
         */
        thorium_message_set_worker(&new_message, thorium_worker_name(self->worker));

#ifdef CORE_DEBUGGER_ASSERT_ENABLED
        if (thorium_message_action(&new_message) == ACTION_INVALID) {
            thorium_printf("Error invalid action DEMUL Multiplexer position %d count %d new_count %d\n",
                            position, count, new_count);
            thorium_message_print(&new_message);
        }
#endif

        CORE_DEBUGGER_ASSERT(thorium_message_action(&new_message) != ACTION_INVALID);

        /*
        thorium_printf("DEMULTIPLEX_MESSAGE\n");
        */

        /*
        thorium_printf("demultiplex, local delivery: \n");
        thorium_message_print(&new_message);
        */

        current_node = self->node->name;
        routing_destination = new_message.routing_destination;

        CORE_DEBUGGER_ASSERT(routing_destination >= 0);

        /*
         * This is a local delivery, nothing to see here.
         */
        if (routing_destination == current_node) {

            thorium_worker_send_local_delivery(self->worker, &new_message);

        /*
         * Otherwise, get the next node in the route and send the
         * payload there since we can not do anything with it here.
         */
        } else {

            /*
             * Export the message to another node.
             * To do this, use an exporter worker.
             */
            thorium_worker_send_for_multiplexer(self->worker,
                            &new_message);
        }

        /*
        thorium_message_destroy(&new_message);
        */

        position += new_count;
        ++messages;
    }

    CORE_DEBUGGER_ASSERT(messages > 0);

#ifdef DEBUG_MULTIPLEXER
    thorium_printf("thorium_message_multiplexer_demultiplex %d messages\n",
                    messages);
#endif

    tracepoint(thorium_node, demultiplex_exit, self->node->name,
                    self->node->tick, messages);

    return 1;
}