Exemple #1
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
}
Exemple #2
0
void thorium_actor_send_range_loop(struct thorium_actor *actor, struct core_vector *actors,
                int first, int last,
                struct thorium_message *message)
{
    int i;
    int the_actor;

#ifdef THORIUM_ACTOR_DEBUG1
    printf("DEBUG thorium_actor_send_range_default%i-%i\n",
                    first, last);
#endif

    i = first;

    while (i <= last) {

#ifdef THORIUM_ACTOR_DEBUG_20140601_1
        printf("DEBUG sending %d to %d\n",
                       thorium_message_action(message), i);
#endif
        the_actor = *(int *)core_vector_at(actors, i);

#ifdef DEBUG_BINOMIAL_TREE
        printf("send_range_loop, sending to %d\n", the_actor);
        thorium_message_print(message);
#endif

        thorium_actor_send(actor, the_actor, message);
        i++;
    }
}
Exemple #3
0
/* hello-hello_receive */
void hello_receive(struct thorium_actor *self, struct thorium_message *message)
{
    int tag;
    int name;
    void *buffer;
    struct hello *concrete_self;
    struct core_vector data_vector;
    int i;
    int action = thorium_message_action(message);

    concrete_self = thorium_actor_concrete_actor(self);
    name = thorium_actor_name(self);
    buffer = thorium_message_buffer(message);

    thorium_actor_log(self, "received action %d\n",
                    action);

    if (action == ACTION_START) {
        
        thorium_message_print(message);
        printf("\n");

        /*
         * Send a ping message to self.
         */
        thorium_actor_send_reply_empty(self, ACTION_MY_PING);

    }

    if (action == ACTION_MY_PING) {
        thorium_actor_send_reply_empty(self, ACTION_MY_PONG);

    }
    
    if (action == ACTION_MY_PONG) {

        thorium_actor_send_reply_empty(self, ACTION_ASK_TO_STOP);
    }

    if (action == ACTION_ASK_TO_STOP) {

        thorium_actor_send_reply_empty(self, ACTION_STOP);
    }
}
Exemple #4
0
void biosal_input_controller_receive(struct thorium_actor *actor, struct thorium_message *message)
{
    int tag;
    int count;
    char *file;
    void *buffer;
    struct biosal_input_controller *controller;
    struct biosal_input_controller *concrete_actor;
    int destination;
    int script;
    int stream;
    char *local_file;
    int i;
    int name;
    int source;
    int destination_index;
    struct thorium_message new_message;
    int error;
    int stream_index;
    int64_t entries;
    int64_t *bucket;
    int *int_bucket;
    int spawner;
    int command_name;
    int stream_name;
    int consumer;
    int consumer_index;
    int *bucket_for_requests;
    char *new_buffer;
    int new_count;
    int file_index;
    struct core_vector mega_blocks;
    struct core_vector_iterator vector_iterator;
    struct biosal_mega_block *mega_block;
    struct core_vector *vector_bucket;
    struct core_vector block_counts;
    uint64_t block_entries;
    int mega_block_index;
    uint64_t offset;
    struct biosal_mega_block *block;
    int acquaintance_index;

    if (thorium_actor_take_action(actor, message)) {
        return;
    }

    thorium_message_get_all(message, &tag, &count, &buffer, &source);

    name = thorium_actor_name(actor);
    controller = (struct biosal_input_controller *)thorium_actor_concrete_actor(actor);
    concrete_actor = controller;

    if (tag == ACTION_START) {

        core_vector_init(&concrete_actor->spawners, 0);
        core_vector_unpack(&concrete_actor->spawners, buffer);

        core_vector_resize(&concrete_actor->stores_per_spawner,
                        core_vector_size(&concrete_actor->spawners));

        for (i = 0; i < core_vector_size(&concrete_actor->spawners); i++) {
            int_bucket = (int *)core_vector_at(&concrete_actor->stores_per_spawner, i);
            *int_bucket = 0;

            spawner = core_vector_at_as_int(&concrete_actor->spawners, i);

            core_queue_enqueue(&concrete_actor->unprepared_spawners, &spawner);
        }

        concrete_actor->state = BIOSAL_INPUT_CONTROLLER_STATE_PREPARE_SPAWNERS;

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL
        printf("DEBUG preparing first spawner\n");
#endif

        thorium_actor_send_to_self_empty(actor, ACTION_INPUT_CONTROLLER_PREPARE_SPAWNERS);

        /*
        thorium_dispatcher_print(thorium_actor_dispatcher(actor));
        */

    } else if (tag == ACTION_ADD_FILE) {

        file = (char *)buffer;

        local_file = core_memory_allocate(strlen(file) + 1, MEMORY_CONTROLLER);
        strcpy(local_file, file);

        printf("controller %d ACTION_ADD_FILE %s\n",
                        thorium_actor_name(actor),
                        local_file);

        core_vector_push_back(&concrete_actor->files, &local_file);

        bucket = core_vector_at(&concrete_actor->files, core_vector_size(&concrete_actor->files) - 1);
        local_file = *(char **)bucket;

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2
        printf("DEBUG11 ACTION_ADD_FILE %s %p bucket %p index %d\n",
                        local_file, local_file, (void *)bucket, core_vector_size(&concrete_actor->files) - 1);
#endif

        thorium_actor_send_reply_empty(actor, ACTION_ADD_FILE_REPLY);

    } else if (tag == ACTION_SPAWN_REPLY) {

        if (concrete_actor->state == BIOSAL_INPUT_CONTROLLER_STATE_SPAWN_STORES) {

            biosal_input_controller_add_store(actor, message);
            return;

        } else if (concrete_actor->state == BIOSAL_INPUT_CONTROLLER_STATE_PREPARE_SPAWNERS) {

            concrete_actor->ready_spawners++;
            thorium_message_unpack_int(message, 0, &name);
            thorium_actor_send_empty(actor, name, ACTION_ASK_TO_STOP);
            thorium_actor_send_to_self_empty(actor, ACTION_INPUT_CONTROLLER_PREPARE_SPAWNERS);

            if (concrete_actor->ready_spawners == (int)core_vector_size(&concrete_actor->spawners)) {

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG
                printf("DEBUG all spawners are prepared\n");
#endif
                thorium_actor_send_to_supervisor_empty(actor, ACTION_START_REPLY);
            }

            return;

        } else if (concrete_actor->state == BIOSAL_INPUT_CONTROLLER_STATE_SPAWN_PARTITIONER) {

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG
            printf("DEBUG received spawn reply, state is spawn_partitioner\n");
#endif

            thorium_message_unpack_int(message, 0, &concrete_actor->partitioner);

            /* configure the partitioner
             */
            destination = concrete_actor->partitioner;
            thorium_actor_send_int(actor, destination,
                            ACTION_SEQUENCE_PARTITIONER_SET_BLOCK_SIZE,
                            concrete_actor->block_size);
            thorium_actor_send_int(actor, destination,
                            ACTION_SEQUENCE_PARTITIONER_SET_ACTOR_COUNT,
                            core_vector_size(&concrete_actor->consumers));

            core_vector_init(&block_counts, sizeof(uint64_t));

            for (i = 0; i < core_vector_size(&concrete_actor->mega_block_vector); i++) {

                block = (struct biosal_mega_block *)core_vector_at(&concrete_actor->mega_block_vector, i);
                block_entries = biosal_mega_block_get_entries(block);

                core_vector_push_back_uint64_t(&block_counts, block_entries);
            }

            new_count = core_vector_pack_size(&block_counts);
            new_buffer = thorium_actor_allocate(actor, new_count);

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG
            printf("DEBUG packed counts, %d bytes\n", count);
#endif

            core_vector_pack(&block_counts, new_buffer);
            thorium_message_init(&new_message, ACTION_SEQUENCE_PARTITIONER_SET_ENTRY_VECTOR,
                            new_count, new_buffer);
            thorium_actor_send(actor, destination, &new_message);
            core_vector_destroy(&block_counts);

            return;

        } else if (concrete_actor->state == BIOSAL_INPUT_CONTROLLER_STATE_SPAWN_READING_STREAMS) {

            thorium_message_unpack_int(message, 0, &stream);

            stream_index = stream;

            mega_block_index = core_vector_size(&concrete_actor->reading_streams);

            core_vector_push_back_int(&concrete_actor->reading_streams, stream_index);
            core_vector_push_back_int(&concrete_actor->partition_commands, -1);
            core_vector_push_back_int(&concrete_actor->stream_consumers, -1);

            stream_index = core_vector_size(&concrete_actor->reading_streams) - 1;
            mega_block = (struct biosal_mega_block *)core_vector_at(&concrete_actor->mega_block_vector,
                            mega_block_index);

            offset = biosal_mega_block_get_offset(mega_block);

            core_map_add_value(&concrete_actor->assigned_blocks,
                            &stream_index, &mega_block_index);

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_READING_STREAMS
            printf("DEBUG setting offset to %" PRIu64 " for stream/%d\n",
                            offset, stream);
#endif

            thorium_actor_send_uint64_t(actor, stream, ACTION_INPUT_STREAM_SET_START_OFFSET, offset);

            return;
        }

        stream = *(int *)buffer;

        file_index = core_vector_size(&concrete_actor->counting_streams);
        local_file = *(char **)core_vector_at(&concrete_actor->files, file_index);

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_READING_STREAMS
        printf("DEBUG actor %d receives stream %d from spawner %d for file %s\n",
                        name, stream, source,
                        local_file);
#endif

        core_vector_push_back(&concrete_actor->counting_streams, &stream);

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_READING_STREAMS
        printf("asking stream/%d to open %s\n", stream, local_file);
#endif
        thorium_message_init(&new_message, ACTION_INPUT_OPEN, strlen(local_file) + 1, local_file);

#ifdef DEBUG_ISSUE_594
        thorium_message_print(&new_message);
        printf("SEND Buffer %s\n", local_file);
#endif

        thorium_actor_send(actor, stream, &new_message);
        thorium_message_destroy(&new_message);

        if (core_vector_size(&concrete_actor->counting_streams) != core_vector_size(&concrete_actor->files)) {

            thorium_actor_send_to_self_empty(actor, ACTION_INPUT_SPAWN);

        }

#ifdef DEBUG_ISSUE_594
        printf("EXIT Buffer %s\n", local_file);
#endif

    } else if (tag == ACTION_INPUT_OPEN_REPLY) {

        if (concrete_actor->state == BIOSAL_INPUT_CONTROLLER_STATE_SPAWN_READING_STREAMS) {

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_READING_STREAMS
            printf("DEBUG receives open.reply for reading stream/%d\n", source);
#endif
            concrete_actor->opened_streams++;

            if (concrete_actor->opened_streams == core_vector_size(&concrete_actor->mega_block_vector)) {
                thorium_actor_send_to_self_empty(actor, ACTION_INPUT_CONTROLLER_CREATE_STORES);
            }

            return;
        }

        concrete_actor->opened_streams++;

        stream = source;
        thorium_message_unpack_int(message, 0, &error);

        if (error == BIOSAL_INPUT_ERROR_NO_ERROR) {

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2
            printf("DEBUG actor %d asks %d ACTION_INPUT_COUNT_IN_PARALLEL\n", name, stream);
#endif

            thorium_actor_send_vector(actor, stream, ACTION_INPUT_COUNT_IN_PARALLEL,
                            &concrete_actor->spawners);
        } else {

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2
            printf("DEBUG actor %d received error %d from %d\n", name, error, stream);
#endif
            concrete_actor->counted++;
        }

	/* if all streams failed, notice supervisor */
        if (concrete_actor->counted == core_vector_size(&concrete_actor->files)) {

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2
#endif
            printf("DEBUG %d: Error all streams failed.\n",
                            thorium_actor_name(actor));
            thorium_actor_send_to_supervisor_empty(actor, ACTION_INPUT_DISTRIBUTE_REPLY);
        }

/*
        if (concrete_actor->opened_streams == core_vector_size(&concrete_actor->files)) {

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG
            printf("DEBUG controller %d sends ACTION_INPUT_DISTRIBUTE_REPLY to supervisor %d [%d/%d]\n",
                            name, thorium_actor_supervisor(actor),
                            concrete_actor->opened_streams, core_vector_size(&concrete_actor->files));
#endif

        }
*/

    } else if (tag == ACTION_INPUT_COUNT_PROGRESS) {

        stream_index = core_vector_index_of(&concrete_actor->counting_streams, &source);
        local_file = core_vector_at_as_char_pointer(&concrete_actor->files, stream_index);
        thorium_message_unpack_int64_t(message, 0, &entries);

        bucket = (int64_t *)core_vector_at(&concrete_actor->counts, stream_index);

        printf("controller/%d receives progress from stream/%d file %s %" PRIu64 " entries so far\n",
                        name, source, local_file, entries);
        *bucket = entries;

    } else if (tag == ACTION_INPUT_COUNT_IN_PARALLEL_REPLY) {

        stream_index = core_vector_index_of(&concrete_actor->counting_streams, &source);
        local_file = core_vector_at_as_char_pointer(&concrete_actor->files, stream_index);

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

        printf("DEBUG receive mega blocks from %d\n", source);
        /*
         * Update the file index for every mega block.
         */
        core_vector_iterator_init(&vector_iterator, &mega_blocks);

        bucket = (int64_t*)core_vector_at(&concrete_actor->counts, stream_index);
        (*bucket) = 0;

        while (core_vector_iterator_has_next(&vector_iterator)) {
            core_vector_iterator_next(&vector_iterator, (void **)&mega_block);

            printf("SETTING setting file to %d for mega block\n", stream_index);
            biosal_mega_block_set_file(mega_block, stream_index);

            entries = biosal_mega_block_get_entries_from_start(mega_block);

            printf("Cataloging %d ENTRIES\n", (int)entries);

            (*bucket) = entries;

            biosal_mega_block_print(mega_block);
        }

        core_vector_iterator_destroy(&vector_iterator);

        vector_bucket = (struct core_vector *)core_map_add(&concrete_actor->mega_blocks, &stream_index);
        core_vector_init_copy(vector_bucket, &mega_blocks);

        core_vector_destroy(&mega_blocks);

        concrete_actor->counted++;

        printf("controller/%d received from stream/%d for file %s %" PRIu64 " entries (final) %d/%d\n",
                        name, source, local_file, entries,
                        concrete_actor->counted, (int)core_vector_size(&concrete_actor->files));

        thorium_actor_send_reply_empty(actor, ACTION_INPUT_CLOSE);

        /* continue work here, tell supervisor about it */
        if (concrete_actor->counted == core_vector_size(&concrete_actor->files)) {
            thorium_actor_send_to_self_empty(actor, ACTION_INPUT_CONTROLLER_SPAWN_READING_STREAMS);
        }


    } else if (tag == ACTION_INPUT_DISTRIBUTE) {

        core_timer_start(&concrete_actor->input_timer);
        core_timer_start(&concrete_actor->counting_timer);

        /* for each file, spawn a stream to count */

        /* no files, return immediately
         */
        if (core_vector_size(&concrete_actor->files) == 0) {

            printf("Error: no file to distribute...\n");
            thorium_actor_send_reply_empty(actor, ACTION_INPUT_DISTRIBUTE_REPLY);
            return;
        }

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2
        printf("DEBUG actor %d receives ACTION_INPUT_DISTRIBUTE\n", name);
#endif

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2
        printf("DEBUG send ACTION_INPUT_SPAWN to self\n");
#endif

        thorium_actor_send_to_self_empty(actor, ACTION_INPUT_SPAWN);

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2
        printf("DEBUG resizing counts to %d\n", core_vector_size(&concrete_actor->files));
#endif

        core_vector_resize(&concrete_actor->counts, core_vector_size(&concrete_actor->files));

        for (i = 0; i < core_vector_size(&concrete_actor->counts); i++) {
            bucket = (int64_t*)core_vector_at(&concrete_actor->counts, i);
            *bucket = 0;
        }

    } else if (tag == ACTION_INPUT_SPAWN && source == name) {

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2
        printf("DEBUG ACTION_INPUT_SPAWN\n");
#endif

        script = SCRIPT_INPUT_STREAM;

        concrete_actor->state = BIOSAL_INPUT_CONTROLLER_STATE_SPAWN_STREAMS;

        /* the next file name to send is the current number of streams */
        i = core_vector_size(&concrete_actor->counting_streams);

        destination_index = i % core_vector_size(&concrete_actor->spawners);
        destination = *(int *)core_vector_at(&concrete_actor->spawners, destination_index);

        thorium_message_init(message, ACTION_SPAWN, sizeof(script), &script);
        thorium_actor_send(actor, destination, message);

        bucket = core_vector_at(&concrete_actor->files, i);
        local_file = *(char **)core_vector_at(&concrete_actor->files, i);

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2
        printf("DEBUG890 local_file %p bucket %p index %d\n", local_file, (void *)bucket,
                        i);
#endif

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG
        printf("DEBUG actor %d spawns a stream for file %d/%d via spawner %d\n",
                        name, i, core_vector_size(&concrete_actor->files), destination);
#endif

        /* also, spawn 4 stores on each node */

    } else if (tag == ACTION_ASK_TO_STOP && ( source == thorium_actor_supervisor(actor)
                            || source == thorium_actor_name(actor))) {

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2
#endif

        /* stop streams
         */
        for (i = 0; i < core_vector_size(&concrete_actor->counting_streams); i++) {
            stream = *(int *)core_vector_at(&concrete_actor->counting_streams, i);

            thorium_actor_send_empty(actor, stream, ACTION_ASK_TO_STOP);
        }
        for (i = 0; i < core_vector_size(&concrete_actor->reading_streams); i++) {
            stream = *(int *)core_vector_at(&concrete_actor->reading_streams, i);

            thorium_actor_send_empty(actor, stream, ACTION_ASK_TO_STOP);
        }



#if 0
        /* stop data stores
         */
        for (i = 0; i < core_vector_size(&concrete_actor->consumers); i++) {
            store = core_vector_at_as_int(&concrete_actor->consumers, i);

            thorium_actor_send_empty(actor, store, ACTION_ASK_TO_STOP);
        }
#endif
        /* stop partitioner
         */

        if (concrete_actor->partitioner != THORIUM_ACTOR_NOBODY) {
            thorium_actor_send_empty(actor,
                                concrete_actor->partitioner,
                        ACTION_ASK_TO_STOP);

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG
            printf("DEBUG controller %d sends ACTION_ASK_TO_STOP_REPLY to %d\n",
                        thorium_actor_name(actor),
                        thorium_message_source(message));
#endif

        }

        thorium_actor_send_reply_empty(actor, ACTION_ASK_TO_STOP_REPLY);

        /* stop self
         */
        thorium_actor_send_to_self_empty(actor, ACTION_STOP);

        thorium_actor_ask_to_stop(actor, message);

        printf("DEBUG controller %d dies\n", name);
#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG
#endif

    } else if (tag == ACTION_INPUT_CONTROLLER_CREATE_PARTITION && source == name) {

        spawner = *(int *)core_vector_at(&concrete_actor->spawners,
                        core_vector_size(&concrete_actor->spawners) / 2);

        thorium_actor_send_int(actor, spawner, ACTION_SPAWN,
                        SCRIPT_SEQUENCE_PARTITIONER);
        concrete_actor->state = BIOSAL_INPUT_CONTROLLER_STATE_SPAWN_PARTITIONER;

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG
        printf("DEBUG input controller %d spawns a partitioner via spawner %d\n",
                        name,  spawner);
#endif

    } else if (tag == ACTION_SEQUENCE_PARTITIONER_COMMAND_IS_READY) {

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG
        printf("DEBUG controller receives ACTION_SEQUENCE_PARTITIONER_COMMAND_IS_READY, asks for command\n");
#endif

        thorium_actor_send_reply_empty(actor, ACTION_SEQUENCE_PARTITIONER_GET_COMMAND);

    } else if (tag == ACTION_SEQUENCE_PARTITIONER_GET_COMMAND_REPLY) {

        biosal_input_controller_receive_command(actor, message);

    } else if (tag == ACTION_SEQUENCE_PARTITIONER_FINISHED) {

        thorium_actor_send_empty(actor,
                                concrete_actor->partitioner,
                        ACTION_ASK_TO_STOP);

        biosal_input_controller_verify_requests(actor, message);

    } else if (tag == ACTION_SEQUENCE_PARTITIONER_PROVIDE_STORE_ENTRY_COUNTS) {

        biosal_input_controller_receive_store_entry_counts(actor, message);

    } else if (tag == ACTION_RESERVE_REPLY) {

        concrete_actor->ready_consumers++;

        printf("DEBUG marker ACTION_RESERVE_REPLY %d/%d\n",
                        concrete_actor->ready_consumers,
                        (int)core_vector_size(&concrete_actor->consumers));

        if (concrete_actor->ready_consumers == core_vector_size(&concrete_actor->consumers)) {

            concrete_actor->ready_consumers = 0;
            printf("DEBUG all consumers are ready\n");
            thorium_actor_send_empty(actor,
                            concrete_actor->partitioner,
                            ACTION_SEQUENCE_PARTITIONER_PROVIDE_STORE_ENTRY_COUNTS_REPLY);
        }

    } else if (tag == ACTION_INPUT_PUSH_SEQUENCES_READY) {

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG
        printf("DEBUG biosal_input_controller_receive received ACTION_INPUT_PUSH_SEQUENCES_READY\n");
#endif

        stream_name = source;

        acquaintance_index = stream_name;
        stream_index = core_vector_index_of(&concrete_actor->reading_streams, &acquaintance_index);
        command_name = *(int *)core_vector_at(&concrete_actor->partition_commands,
                        stream_index);

        thorium_actor_send_int(actor,
                                concrete_actor->partitioner,
                        ACTION_SEQUENCE_PARTITIONER_GET_COMMAND_REPLY_REPLY,
                        command_name);

    } else if (tag == ACTION_INPUT_PUSH_SEQUENCES_REPLY) {

        stream_name = source;

        thorium_message_unpack_int(message, 0, &consumer);

        consumer_index = core_vector_index_of(&concrete_actor->consumers,
                        &consumer);

        bucket_for_requests = (int *)core_vector_at(&concrete_actor->consumer_active_requests, consumer_index);

        (*bucket_for_requests)--;

        biosal_input_controller_verify_requests(actor, message);

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_CONSUMERS
        printf("DEBUG consumer # %d has %d active requests\n",
                        consumer_index, *bucket_for_requests);
#endif


    } else if (tag == ACTION_SET_CONSUMERS) {

        core_vector_init(&concrete_actor->consumers, 0);
        core_vector_unpack(&concrete_actor->consumers, buffer);

        printf("controller %d receives %d consumers\n",
                        thorium_actor_name(actor),
                        (int)core_vector_size(&concrete_actor->consumers));

        for (i = 0; i < core_vector_size(&concrete_actor->consumers); i++) {
            core_vector_push_back_int(&concrete_actor->consumer_active_requests, 0);
        }

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG
        core_vector_print_int(&concrete_actor->consumers);
        printf("\n");
#endif
        thorium_actor_send_reply_empty(actor, ACTION_SET_CONSUMERS_REPLY);

    } else if (tag == ACTION_SET_BLOCK_SIZE) {

        thorium_message_unpack_int(message, 0, &concrete_actor->block_size);
        thorium_actor_send_reply_empty(actor, ACTION_SET_BLOCK_SIZE_REPLY);

    } else if (tag == ACTION_SEQUENCE_STORE_READY) {

        concrete_actor->filled_consumers++;

#ifdef BIOSAL_INPUT_CONTROLLER_DEBUG
        printf("DEBUG ACTION_SEQUENCE_STORE_READY %d/%d\n", concrete_actor->filled_consumers,
                        (int)core_vector_size(&concrete_actor->consumers));
#endif

        if (concrete_actor->filled_consumers == core_vector_size(&concrete_actor->consumers)) {
            concrete_actor->filled_consumers = 0;

            printf("DEBUG: all consumers are filled,  sending ACTION_INPUT_DISTRIBUTE_REPLY\n");

            core_timer_stop(&concrete_actor->input_timer);
            core_timer_stop(&concrete_actor->distribution_timer);

            core_timer_print_with_description(&concrete_actor->distribution_timer,
                            "Load input / Distribute input data");

            core_timer_print_with_description(&concrete_actor->input_timer,
                            "Load input");

            thorium_actor_send_to_supervisor_empty(actor, ACTION_INPUT_DISTRIBUTE_REPLY);
        }
    }
}
Exemple #5
0
void biosal_input_stream_receive(struct thorium_actor *actor, struct thorium_message *message)
{
    int tag;
    int source;
    uint64_t count;
    struct biosal_input_stream *concrete_self;
    int i;
    int has_sequence;
    int sequences;
    int sequence_index;
    int buffer_size;
    char *buffer;
    char *read_buffer;
    struct biosal_mega_block mega_block;
    char *file_name_in_buffer;

    if (thorium_actor_take_action(actor, message)) {
        return;
    }

    concrete_self = thorium_actor_concrete_actor(actor);
    tag = thorium_message_action(message);
    source = thorium_message_source(message);
    buffer = (char *)thorium_message_buffer(message);

    /* Do nothing if there is an error.
     * has_error returns the error to the source.
     */
    /*
    if (biosal_input_stream_has_error(actor, message)) {
        return;
    }

    */

    if (tag == ACTION_INPUT_OPEN) {

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

        if (concrete_self->open) {

            concrete_self->error = BIOSAL_INPUT_ERROR_ALREADY_OPEN;
            thorium_actor_send_reply_int(actor, ACTION_INPUT_OPEN_REPLY, concrete_self->error);
            thorium_actor_send_to_self_empty(actor, ACTION_ASK_TO_STOP);

            return;
        }

        concrete_self->open = 1;

        /* TODO: find out the maximum read length in some way */
        concrete_self->maximum_sequence_length = BIOSAL_INPUT_MAXIMUM_SEQUENCE_LENGTH;

        concrete_self->buffer_for_sequence = (char *)core_memory_allocate(concrete_self->maximum_sequence_length, MEMORY_INPUT_STREAM);

        /*biosal_input_stream_init(actor);*/

#ifdef BIOSAL_INPUT_STREAM_DEBUG
        printf("DEBUG biosal_input_stream_receive open %s\n",
                        buffer);
#endif

        /*core_memory_copy(&concrete_self->file_index, buffer, sizeof(concrete_self->file_index));*/
        file_name_in_buffer = buffer;

        printf("stream/%d (node/%d) opens file %s offset %" PRIu64 "\n", thorium_actor_name(actor),
                        thorium_actor_node_name(actor), file_name_in_buffer,
                        concrete_self->starting_offset);

#ifdef DEBUG_ISSUE_594
        thorium_message_print(message);

        printf("Buffer %s\n", buffer);
#endif

        concrete_self->file_name = core_memory_allocate(strlen(file_name_in_buffer) + 1, MEMORY_INPUT_STREAM);
        strcpy(concrete_self->file_name, file_name_in_buffer);

        biosal_input_proxy_init(&concrete_self->proxy, concrete_self->file_name,
                        concrete_self->starting_offset, concrete_self->ending_offset);

        concrete_self->proxy_ready = 1;

        /* Die if there is an error...
         */
        if (biosal_input_stream_has_error(actor, message)) {

#ifdef BIOSAL_INPUT_STREAM_DEBUG
            printf("DEBUG has error\n");
#endif

            thorium_actor_send_reply_int(actor, ACTION_INPUT_OPEN_REPLY, concrete_self->error);
            thorium_actor_send_to_self_empty(actor, ACTION_ASK_TO_STOP);

            return;
        }

        concrete_self->controller = source;

        /* no error here... */
        thorium_actor_send_reply_int(actor, ACTION_INPUT_OPEN_REPLY, concrete_self->error);

    } else if (tag == ACTION_INPUT_COUNT) {
        /* count a little bit and yield the worker */

        if (concrete_self->count_customer == THORIUM_ACTOR_NOBODY) {
            concrete_self->count_customer = source;
        }

        if (biosal_input_stream_check_open_error(actor, message)) {

            thorium_actor_send_reply_int64_t(actor, ACTION_INPUT_COUNT_REPLY, concrete_self->error);
            thorium_actor_send_to_self_empty(actor, ACTION_ASK_TO_STOP);

            return;
        }

#ifdef BIOSAL_INPUT_STREAM_DEBUG
        printf("DEBUG ACTION_INPUT_COUNT received...\n");
#endif

        i = 0;
        /* continue counting ... */
        has_sequence = 1;

        while (i < concrete_self->granularity && has_sequence) {
            has_sequence = biosal_input_proxy_get_sequence(&concrete_self->proxy,
                            concrete_self->buffer_for_sequence);

#if 0
            printf("Sequence= %s\n", concrete_self->buffer_for_sequence);
#endif
            i++;
        }

        sequences = biosal_input_proxy_size(&concrete_self->proxy);

#ifdef BIOSAL_INPUT_STREAM_DEBUG
        printf("DEBUG ACTION_INPUT_COUNT sequences %d...\n", sequences);
#endif

        if (!has_sequence || sequences % concrete_self->mega_block_size == 0) {

            biosal_mega_block_init(&mega_block, -1, concrete_self->last_offset,
                            sequences - concrete_self->last_entries, sequences);

            core_vector_push_back(&concrete_self->mega_blocks, &mega_block);

            concrete_self->last_entries = sequences;
            concrete_self->last_offset = biosal_input_proxy_offset(&concrete_self->proxy);

            thorium_actor_send_int64_t(actor, concrete_self->controller, ACTION_INPUT_COUNT_PROGRESS, sequences);
        }

        if (has_sequence) {

            /*printf("DEBUG yield\n");*/

            thorium_actor_send_to_self_empty(actor, ACTION_YIELD);

            /* notify the controller of our progress...
             */

        } else {

            thorium_actor_send_to_self_empty(actor, ACTION_INPUT_COUNT_READY);
        }

    } else if (tag == ACTION_YIELD_REPLY) {

        if (biosal_input_stream_check_open_error(actor, message)) {
                /*
                 * it is not clear that there can be an error when receiving YIELD.
            error = concrete_self->error;
            thorium_actor_send_reply_int(actor, ACTION_INPUT_COUNT_REPLY, error);
            thorium_actor_send_to_self(actor, ACTION_ASK_TO_STOP);

                 */
            return;
        }

        thorium_actor_send_to_self_empty(actor, ACTION_INPUT_COUNT);

    } else if (tag == ACTION_INPUT_COUNT_READY) {

        if (biosal_input_stream_check_open_error(actor, message)) {
            return;
        }

        count = biosal_input_proxy_size(&concrete_self->proxy);

        thorium_actor_send_vector(actor, concrete_self->count_customer, ACTION_INPUT_COUNT_REPLY,
                        &concrete_self->mega_blocks);

        printf("input_stream/%d on node/%d counted entries in %s, %" PRIu64 "\n",
                        thorium_actor_name(actor), thorium_actor_node_name(actor),
                        concrete_self->file_name, count);

    } else if (tag == ACTION_INPUT_CLOSE) {

#ifdef BIOSAL_INPUT_STREAM_DEBUG
        printf("DEBUG destroy proxy\n");
#endif
        concrete_self->error = BIOSAL_INPUT_ERROR_NO_ERROR;

        if (biosal_input_stream_check_open_error(actor, message)) {
            concrete_self->error = BIOSAL_INPUT_ERROR_FILE_NOT_OPEN;

            thorium_message_init(message, ACTION_INPUT_CLOSE_REPLY, sizeof(concrete_self->error),
                &concrete_self->error);
            thorium_actor_send(actor, source, message);

            thorium_actor_send_to_self_empty(actor, ACTION_ASK_TO_STOP);
            return;
        }

        thorium_message_init(message, ACTION_INPUT_CLOSE_REPLY, sizeof(concrete_self->error),
                &concrete_self->error);
        thorium_actor_send(actor, source, message);

        thorium_actor_send_to_self_empty(actor, ACTION_ASK_TO_STOP);

#ifdef BIOSAL_INPUT_STREAM_DEBUG
        printf("actor %d sending ACTION_INPUT_CLOSE_REPLY to %d\n",
                        thorium_actor_name(actor), source);
#endif

    } else if (tag == ACTION_INPUT_GET_SEQUENCE) {

        if (biosal_input_stream_check_open_error(actor, message)) {

            /* the error management could be better. */
            concrete_self->error = BIOSAL_INPUT_ERROR_FILE_NOT_OPEN;
            thorium_message_init(message, ACTION_INPUT_GET_SEQUENCE_REPLY, sizeof(concrete_self->error),
                            &concrete_self->error);
            thorium_actor_send(actor, source, message);

            return;
        }

        sequence_index = biosal_input_proxy_size(&concrete_self->proxy);

        /* TODO it would be clearer to use a struct to pack a int and a char []
         * then to use the code below.
         */
        read_buffer = concrete_self->buffer_for_sequence + sizeof(sequence_index);
        has_sequence = biosal_input_proxy_get_sequence(&concrete_self->proxy,
                            read_buffer);

        if (!has_sequence) {
            thorium_message_init(message, ACTION_INPUT_GET_SEQUENCE_END, 0, NULL);
            thorium_actor_send(actor, source, message);

            return;
        }

        buffer_size = sizeof(sequence_index) + strlen(read_buffer) + 1;

        core_memory_copy(concrete_self->buffer_for_sequence, &sequence_index, sizeof(sequence_index));

        thorium_message_init(message, ACTION_INPUT_GET_SEQUENCE_REPLY,
                        buffer_size, concrete_self->buffer_for_sequence);
        thorium_actor_send(actor, source, message);

    } else if (tag == ACTION_INPUT_PUSH_SEQUENCES) {

        biosal_input_stream_push_sequences(actor, message);

    } else if (tag == ACTION_ASK_TO_STOP) {

        thorium_actor_send_to_self_empty(actor, ACTION_STOP);

        thorium_actor_send_range_empty(actor, &concrete_self->parallel_streams,
                        ACTION_ASK_TO_STOP);

        thorium_actor_send_reply_empty(actor, ACTION_ASK_TO_STOP_REPLY);

    } else if (tag == ACTION_INPUT_STREAM_RESET) {

        /* fail silently
         */
        if (!concrete_self->open) {
            thorium_actor_send_reply_empty(actor, ACTION_INPUT_STREAM_RESET_REPLY);
            return;
        }

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

        biosal_input_proxy_destroy(&concrete_self->proxy);
        biosal_input_proxy_init(&concrete_self->proxy, concrete_self->file_name,
                        concrete_self->starting_offset,
                        concrete_self->ending_offset);

        thorium_actor_send_reply_empty(actor, ACTION_INPUT_STREAM_RESET_REPLY);

    } else if (tag == ACTION_PUSH_SEQUENCE_DATA_BLOCK_REPLY) {

        thorium_actor_send_to_supervisor_int(actor, ACTION_INPUT_PUSH_SEQUENCES_REPLY,
                        source);
    }
}
Exemple #6
0
void thorium_message_multiplexer_flush(struct thorium_message_multiplexer *self, int index, int force)
{
    char *buffer;
    struct thorium_message message;
    int tag;
    int count;
    int current_size;
    int maximum_size;
    struct thorium_multiplexed_buffer *multiplexed_buffer;
    int destination_node;
    /*
    int elapsed;
    int message_count;
    */

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

#ifdef THORIUM_MULTIPLEXER_TRACK_BUFFERS_WITH_CONTENT
#ifdef CORE_DEBUGGER_ASSERT_ENABLED
    if (!(core_set_find(&self->buffers_with_content, &index))) {
        multiplexed_buffer = core_vector_at(&self->buffers, index);
        thorium_printf("index %d has no content\n", index);

        thorium_multiplexed_buffer_print(multiplexed_buffer);
    }
#endif

    CORE_DEBUGGER_ASSERT(core_set_find(&self->buffers_with_content, &index));
#endif

    multiplexed_buffer = core_vector_at(&self->buffers, index);
    current_size = thorium_multiplexed_buffer_current_size(multiplexed_buffer);
    maximum_size = thorium_multiplexed_buffer_maximum_size(multiplexed_buffer);

    /*
     * The buffer was still in the timeline, but it was flushed elsewhere.
     */
    if (current_size == 0) {
        return;

        /*
    if (force == FORCE_NO && current_size < maximum_size) {
        return;

    } else if (force == FORCE_YES_TIME) {
        elapsed = core_timer_get_nanoseconds(&self->timer) - multiplexed_buffer->timestamp_;

        if (elapsed < self->timeout_in_nanoseconds) {
            return;
        }
    } else if (force == FORCE_YES_DOA) {
        message_count = multiplexed_buffer->message_count_;

        if (message_count < self->degree_of_aggregation_limit) {
            return;
        }
        */
    }

#ifdef CORE_DEBUGGER_ASSERT_ENABLED
    if (current_size <= 0)
        thorium_printf("current_size %d maximum_size %d\n", current_size, maximum_size);
#endif

    CORE_DEBUGGER_ASSERT(current_size > 0);

    buffer = thorium_multiplexed_buffer_buffer(multiplexed_buffer);

    count = current_size + THORIUM_MESSAGE_METADATA_SIZE;

    tag = ACTION_MULTIPLEXER_MESSAGE;

    /*
     * This count does not include metadata for the final big message.
     *
     * Avoid this copy by using an array of pointers in the first place.
     */

    destination_node = index;

    thorium_message_init(&message, tag, count, buffer);
    thorium_message_set_destination(&message,
                    destination_node);
    thorium_message_set_source(&message,
            thorium_node_name(self->node));
    /*
     * Mark the message so that the buffer is eventually sent back here
     * for recycling.
     */
    thorium_message_set_worker(&message, thorium_worker_name(self->worker));

    thorium_message_write_metadata(&message);

#ifdef DEBUG_MULTIPLEXER_FLUSH
    thorium_printf("DEBUG_MULTIPLEXER thorium_message_multiplexer_flush index %d buffer %p force %d current_size %d maximum_size %d"
                    " destination_node %d\n",
                    index, buffer, force,
                    current_size, maximum_size,
                    thorium_message_destination_node(&message));

    thorium_printf("message in flush\n");
    thorium_multiplexed_buffer_print(multiplexed_buffer);
    thorium_message_print(&message);
#endif

    CORE_DEBUGGER_ASSERT_NOT_NULL(self->worker);

    /*
     * Make a copy of the buffer because the multiplexer does not have communication buffers.
     */
    thorium_worker_enqueue_outbound_message(self->worker, &message);

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

    ++self->real_message_count;
    thorium_message_destroy(&message);

    thorium_multiplexed_buffer_reset(multiplexed_buffer);

#ifdef THORIUM_MULTIPLEXER_TRACK_BUFFERS_WITH_CONTENT
    core_set_delete(&self->buffers_with_content, &index);
#endif
}
Exemple #7
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;
}
Exemple #8
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;
}
Exemple #9
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;
}