Example #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;
}
Example #2
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
}
Example #3
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++;
    }
}
Example #4
0
int thorium_worker_enqueue_message_for_triage(struct thorium_worker *worker, struct thorium_message *message)
{
#ifdef THORIUM_WORKER_DEBUG_INJECTION
    int worker_name;
#endif

    CORE_DEBUGGER_ASSERT(thorium_message_buffer(message) != NULL);

    if (!core_fast_ring_push_from_producer(&worker->clean_message_ring_for_triage, message)) {

#ifdef SHOW_FULL_RING_WARNINGS
        printf("thorium_worker: Warning: ring is full, clean_message_ring_for_triage action= %x\n",
                        thorium_message_action(message));
#endif

        core_fast_queue_enqueue(&worker->clean_message_queue_for_triage, message);

#ifdef THORIUM_WORKER_DEBUG_INJECTION
    } else {
        /*
         * Update software counters.
         */
        worker_name = thorium_message_worker(message);

        if (worker_name >= 0) {
            ++worker->counter_injected_outbound_buffers_other_local_workers;
        } else {
            ++worker->counter_injected_inbound_buffers_from_thorium_core;
        }
#endif
    }

    return 1;
}
Example #5
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);
}
Example #6
0
void systolic_receive(struct thorium_actor *actor, struct thorium_message *message)
{
    int tag;
    int name;
    void *buffer;
    struct systolic *systolic1;
    int i;

    systolic1 = (struct systolic *)thorium_actor_concrete_actor(actor);
    tag = thorium_message_action(message);
    name = thorium_actor_name(actor);
    buffer = thorium_message_buffer(message);

    if (tag == ACTION_START) {

        core_vector_unpack(&systolic1->initial_data, buffer);

        printf("Hello world ! my name is actor:%d and I have %d acquaintances:",
                        name, (int)core_vector_size(&systolic1->initial_data));

        for (i = 0; i < core_vector_size(&systolic1->initial_data); i++) {
            printf(" actor:%d", core_vector_at_as_int(&systolic1->initial_data, i));
        }
        printf("\n");

        thorium_actor_send_to_self_empty(actor, ACTION_STOP);
    }
}
Example #7
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;
}
Example #8
0
void thorium_actor_send_range_default(struct thorium_actor *actor, struct core_vector *actors,
                int first, int last,
                struct thorium_message *message)
{
    int use_binomial_tree;
    struct core_vector destinations;
    struct core_memory_pool *ephemeral_memory;
    int name;
    int action;

    action = thorium_message_action(message);
    use_binomial_tree = 0;

#ifdef USE_BINOMIAL_TREE

    /*
     * ACTION_ASK_TO_STOP basically kills actors (if they agree to).
     * It is a bad idea to use a binomial tree to send this death signal
     * since intermediate actors can die before acting as relays.
     */
    if (action != ACTION_ASK_TO_STOP)
        use_binomial_tree = 1;
#endif

    if (!use_binomial_tree) {
        thorium_actor_send_range_loop(actor, actors, first, last, message);
        return;
    }

    tracepoint(thorium_binomial_tree, send_range, message, (int)core_vector_size(actors));

    /*
     * Otherwise, use the binomial tree code path. This algorithm is better since it distributed
     * the sending operations intot a binomial tree where there are a lot of intermediate
     * actors (to be exact, the number of intermediate actors is close to log2(actors.size)).
     */
    ephemeral_memory = thorium_actor_get_ephemeral_memory(actor);
    core_vector_init(&destinations, sizeof(int));
    core_vector_set_memory_pool(&destinations, ephemeral_memory);

    CORE_DEBUGGER_ASSERT(core_vector_empty(&destinations));

    core_vector_copy_range(actors, first, last, &destinations);

    /*
     * Set the source now.
     */
    name = thorium_actor_name(actor);
    thorium_message_set_source(message, name);

    thorium_actor_send_range_binomial_tree(actor, &destinations, message);

    core_vector_destroy(&destinations);
}
Example #9
0
void biosal_assembly_arc_classifier_receive(struct thorium_actor *self, struct thorium_message *message)
{
    int tag;
    void *buffer;
    struct biosal_assembly_arc_classifier *concrete_self;
    int size;
    int i;
    int *bucket;
    int source;
    int source_index;

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

    concrete_self = (struct biosal_assembly_arc_classifier *)thorium_actor_concrete_actor(self);
    tag = thorium_message_action(message);
    buffer = thorium_message_buffer(message);
    source = thorium_message_source(message);

    if (tag == ACTION_SET_CONSUMERS) {

        core_vector_unpack(&concrete_self->consumers, buffer);

        size = core_vector_size(&concrete_self->consumers);
        core_vector_resize(&concrete_self->pending_requests, size);

        for (i = 0; i < size; i++) {
            core_vector_set_int(&concrete_self->pending_requests, i, 0);
        }

        thorium_actor_send_reply_empty(self, ACTION_SET_CONSUMERS_REPLY);

    } else if (tag == ACTION_ASSEMBLY_PUSH_ARC_BLOCK_REPLY){

        /*
         * Decrease counter now.
         */
        source_index = core_vector_index_of(&concrete_self->consumers, &source);
        bucket = core_vector_at(&concrete_self->pending_requests, source_index);
        --(*bucket);
        --concrete_self->active_requests;

        /*
         * The previous value was maximum_pending_request_count + 1
         */
        if (*bucket == concrete_self->maximum_pending_request_count) {

            --concrete_self->consumer_count_above_threshold;
        }

        biosal_assembly_arc_classifier_verify_counters(self);
    }
}
Example #10
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));
}
Example #11
0
void buddy_receive(struct thorium_actor *actor, struct thorium_message *message)
{
    int tag;
    int source;
    int name;

    name = thorium_actor_name(actor);
    source = thorium_message_source(message);
    tag = thorium_message_action(message);

    if (tag == ACTION_BUDDY_BOOT) {

        printf("ACTION_BUDDY_BOOT\n");
        thorium_actor_print(actor);

        thorium_message_init(message, ACTION_BUDDY_BOOT_REPLY, 0, NULL);
        thorium_actor_send(actor, source, message);

    } else if (tag == ACTION_BUDDY_HELLO) {

        printf("ACTION_BUDDY_HELLO\n");

        /* pin the actor to the worker for no reason !
         */

        /*
        thorium_actor_send_to_self_empty(actor, ACTION_PIN_TO_WORKER);
        */

        thorium_message_init(message, ACTION_BUDDY_HELLO_REPLY, 0, NULL);
        thorium_actor_send(actor, source, message);

    } else if (tag == ACTION_ASK_TO_STOP) {

        printf("BUDDY_DIE\n");

        printf("buddy_receive Actor %i received a message (%i BUDDY_DIE) from actor %i\n",
                        name, tag, source);

        /*
        thorium_actor_send_to_self_empty(actor, ACTION_UNPIN_FROM_WORKER);
        */

        thorium_message_init(message, ACTION_STOP, 0, NULL);
        thorium_actor_send(actor, name, message);
    }
}
Example #12
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);
    }
}
Example #13
0
File: ring.c Project: huyba/biosal
void ring_receive(struct thorium_actor *actor, struct thorium_message *message)
{
    int tag;
    int new_actor;
    int previous;
    int name;
    struct ring *concrete_actor;
    int messages;
    int previous_actor;
    char *buffer;
    int destination;

    concrete_actor = (struct ring *)thorium_actor_concrete_actor(actor);
    tag = thorium_message_action(message);
    buffer = thorium_message_buffer(message);
    name = thorium_actor_name(actor);

    if (tag == ACTION_START) {

        core_vector_init(&concrete_actor->spawners, 0);
        core_vector_unpack(&concrete_actor->spawners, buffer);
        printf("actor %d ACTION_START, %d spawners\n", name,
                        (int)core_vector_size(&concrete_actor->spawners));

        destination = *(int *)core_vector_at(&concrete_actor->spawners, 0);
        thorium_actor_send_empty(actor, destination, ACTION_RING_READY);

    } else if (tag == ACTION_RING_READY && concrete_actor->step == RING_STEP_RECEIVE_SPAWNERS) {

        concrete_actor->ready_rings++;

        if (concrete_actor->ready_rings == (int)core_vector_size(&concrete_actor->spawners)) {
            thorium_actor_send_range_empty(actor, &concrete_actor->spawners, ACTION_RING_SPAWN);
            concrete_actor->step = RING_STEP_SPAWN;
            concrete_actor->ready_rings = 0;
        }

    } else if (tag == ACTION_RING_SPAWN) {

        printf("actor/%d is spawning %d senders\n",
                        thorium_actor_name(actor), concrete_actor->senders);

        concrete_actor->step = RING_STEP_SPAWN;

        new_actor = thorium_actor_spawn(actor, SCRIPT_SENDER);
        concrete_actor->first = new_actor;
        previous = new_actor;
        new_actor = thorium_actor_spawn(actor, SCRIPT_SENDER);
        concrete_actor->previous = new_actor;

        thorium_message_init(message, ACTION_SENDER_SET_NEXT, sizeof(new_actor), &new_actor);
        thorium_actor_send(actor, previous, message);

        ++concrete_actor->spawned_senders;
        ++concrete_actor->spawned_senders;

    } else if (tag == ACTION_RING_READY && concrete_actor->step == RING_STEP_SPAWN) {
        concrete_actor->ready_rings++;

#if 0
        printf("READY: %d/%d\n", concrete_actor->ready_rings, (int)core_vector_size(&concrete_actor->spawners));
#endif

        if (concrete_actor->ready_rings == core_vector_size(&concrete_actor->spawners)) {

            thorium_actor_send_range_empty(actor, &concrete_actor->spawners, ACTION_RING_PUSH_NEXT);
            concrete_actor->ready_rings = 0;
            concrete_actor->step = RING_STEP_PUSH_NEXT;
        }
    } else if (tag == ACTION_RING_PUSH_NEXT) {

        previous_actor = core_vector_index_of(&concrete_actor->spawners, &name) - 1;
        if (previous_actor < 0) {
            previous_actor = core_vector_size(&concrete_actor->spawners)- 1;
        }

        printf("%d received ACTION_RING_PUSH_NEXT\n", name);
        thorium_message_init(message, ACTION_RING_SET_NEXT, sizeof(concrete_actor->first), &concrete_actor->first);
        thorium_actor_send(actor, *(int *)core_vector_at(&concrete_actor->spawners, previous_actor),
                       message);

    } else if (tag == ACTION_RING_SET_NEXT) {

        concrete_actor->step = RING_STEP_PUSH_NEXT;
        thorium_message_set_action(message, ACTION_SENDER_SET_NEXT);
        thorium_actor_send(actor, concrete_actor->last, message);

    } else if (tag == ACTION_SENDER_SET_NEXT_REPLY
                    && concrete_actor->step == RING_STEP_SPAWN) {


#if 0
        printf("ready senders %d/%d\n", concrete_actor->ready_senders, concrete_actor->senders);
#endif

        if (concrete_actor->spawned_senders % 10000 == 0) {
            printf("spawned %d/%d\n",
                        concrete_actor->spawned_senders,
                        concrete_actor->senders);
        }

        if (concrete_actor->spawned_senders == concrete_actor->senders) {

            printf("RING_STEP_SPAWN completed.\n");
            thorium_actor_send_empty(actor, *(int *)core_vector_at(&concrete_actor->spawners, 0), ACTION_RING_READY);
            concrete_actor->ready_senders = 0;

            concrete_actor->last = concrete_actor->previous;
        } else {
            new_actor = thorium_actor_spawn(actor, SCRIPT_SENDER);
            ++concrete_actor->spawned_senders;
            previous = concrete_actor->previous;

            thorium_message_init(message, ACTION_SENDER_SET_NEXT, sizeof(new_actor), &new_actor);
            thorium_actor_send(actor, previous, message);

            concrete_actor->previous = new_actor;
        }
    } else if (tag == ACTION_SENDER_SET_NEXT_REPLY
                    && concrete_actor->step == RING_STEP_PUSH_NEXT) {

        concrete_actor->ready_senders++;

        printf("ACTION_SENDER_SET_NEXT_REPLY %d/%d\n",
                        concrete_actor->ready_senders,
                        1);

        if (concrete_actor->ready_senders == 1) {
            thorium_actor_send_empty(actor, *(int *)core_vector_at(&concrete_actor->spawners, 0), ACTION_RING_READY);
            printf("RING_STEP_PUSH_NEXT completed.\n");
            concrete_actor->ready_senders = 0;
        }


    } else if (tag == ACTION_RING_READY && concrete_actor->step == RING_STEP_PUSH_NEXT) {
        concrete_actor->ready_rings++;

        if (concrete_actor->ready_rings == core_vector_size(&concrete_actor->spawners)) {

            printf("system is ready...\n");
            messages = 2000007;
            thorium_message_init(message, ACTION_SENDER_HELLO, sizeof(messages), &messages);
            thorium_actor_send(actor, concrete_actor->first, message);

            concrete_actor->ready_rings = 0;
        }
    } else if (tag == ACTION_SENDER_HELLO_REPLY) {

        thorium_actor_send_range_empty(actor, &concrete_actor->spawners, ACTION_RING_KILL);
        thorium_actor_send_empty(actor, concrete_actor->first, ACTION_SENDER_KILL);

    } else if (tag == ACTION_RING_KILL) {

        thorium_actor_send_to_self_empty(actor, ACTION_STOP);
    }
}
Example #14
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);
        }
    }
}
Example #15
0
void table_receive(struct thorium_actor *actor, struct thorium_message *message)
{
    int tag;
    int source;
    int name;
    int remote;
    struct thorium_message spawn_message;
    int script;
    int new_actor;
    void *buffer;
    struct table *table1;

    table1 = (struct table *)thorium_actor_concrete_actor(actor);
    source = thorium_message_source(message);
    tag = thorium_message_action(message);
    name = thorium_actor_name(actor);
    buffer = thorium_message_buffer(message);

    if (tag == ACTION_START) {
        printf("Actor %i receives ACTION_START from actor %i\n",
               name,  source);

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

        remote = core_vector_index_of(&table1->spawners, &name) + 1;
        remote %= core_vector_size(&table1->spawners);

        script = SCRIPT_TABLE;
        thorium_message_init(&spawn_message, ACTION_SPAWN, sizeof(script), &script);
        thorium_actor_send(actor, *(int *)core_vector_at(&table1->spawners, remote), &spawn_message);

        /*
        printf("sending notification\n");
        thorium_message_init(message, ACTION_TABLE_NOTIFY, 0, NULL);
        thorium_actor_send(actor, 0, message);
        */
    } else if (tag == ACTION_SPAWN_REPLY) {

        new_actor= *(int *)buffer;

        printf("Actor %i receives ACTION_SPAWN_REPLY from actor %i,"
               " new actor is %d\n",
               name,  source, new_actor);

        thorium_message_init(message, ACTION_TABLE_DIE2, 0, NULL);
        thorium_actor_send(actor, new_actor, message);

        thorium_message_init(message, ACTION_TABLE_NOTIFY, 0, NULL);
        thorium_actor_send(actor, core_vector_at_as_int(&table1->spawners, 0), message);

    } else if (tag == ACTION_TABLE_DIE2) {

        printf("Actor %i receives ACTION_TABLE_DIE2 from actor %i\n",
               name,  source);

        if (name < core_vector_size(&table1->spawners)) {
            return;
        }

        thorium_message_init(message, ACTION_STOP, 0, NULL);
        thorium_actor_send(actor, name, message);

    } else if (tag == ACTION_TABLE_DIE) {

        printf("Actor %i receives ACTION_TABLE_DIE from actor %i\n",
               name,  source);

        thorium_message_init(message, ACTION_STOP, 0, NULL);
        thorium_actor_send(actor, name, message);

    } else if (tag == ACTION_TABLE_NOTIFY) {

        printf("Actor %i receives ACTION_TABLE_NOTIFY from actor %i\n",
               name,  source);

        table1->done++;

        if (table1->done == core_vector_size(&table1->spawners)) {
            printf("actor %d kills %d to %d\n",
                   name, 0, (int)core_vector_size(&table1->spawners) - 1);
            thorium_message_init(message, ACTION_TABLE_DIE, 0, NULL);
            thorium_actor_send_range(actor, &table1->spawners, message);
        }
    }
}
Example #16
0
File: frame.c Project: huyba/biosal
void frame_receive(struct thorium_actor *actor, struct thorium_message *message)
{
    int tag;
    int name;
    void *buffer;
    struct frame *concrete_actor;
    int other;
    struct core_vector initial_actors;
    struct core_vector *acquaintance_vector;
    int source;

    source = thorium_message_source(message);
    concrete_actor = (struct frame *)thorium_actor_concrete_actor(actor);
    tag = thorium_message_action(message);
    name = thorium_actor_name(actor);
    buffer = thorium_message_buffer(message);
    acquaintance_vector = &concrete_actor->acquaintance_vector;


    if (tag == ACTION_START) {

        core_vector_init(&initial_actors, sizeof(int));
        core_vector_unpack(&initial_actors, buffer);
        core_vector_push_back_vector(acquaintance_vector, &initial_actors);
        core_vector_destroy(&initial_actors);

        other = thorium_actor_spawn(actor, thorium_actor_script(actor));
        core_vector_push_back_int(acquaintance_vector, other);

        thorium_actor_send_empty(actor, other, ACTION_PING);

        printf("actor %d sends ACTION_PING to new actor %d\n",
                        name, other);

    } else if (tag == ACTION_PING) {

        /* new acquaintance
         */
        core_vector_push_back(acquaintance_vector, &source);

        printf("actor %d (value %d) receives ACTION_PING from actor %d\n",
                        name, concrete_actor->value, source);
        printf("Acquaintances of actor %d: ", name);
        core_vector_print_int(acquaintance_vector);
        printf("\n");

        thorium_actor_send_reply_empty(actor, ACTION_PING_REPLY);

    } else if (tag == ACTION_PING_REPLY) {

        concrete_actor->pings++;

        printf("actor %d receives ACTION_PING_REPLY from actor %d\n",
                        name, source);

        /* kill the system
         */
        if (concrete_actor->migrated_other && concrete_actor->pings == 2) {

            thorium_actor_send_reply_empty(actor, ACTION_ASK_TO_STOP);
            thorium_actor_send_to_self_empty(actor, ACTION_ASK_TO_STOP);

            return;
        }

        /* migrate other actor
         */

        printf("actor %d asks actor %d to migrate using actor %d as spawner\n",
                        name, source, name);

        printf("Acquaintances of actor %d: ", name);
        core_vector_print_int(acquaintance_vector);
        printf("\n");

        thorium_actor_send_reply_int(actor, ACTION_MIGRATE, name);

        /* send a message to other while it is migrating.
         * this is supposed to work !
         */
        printf("actor %d sends ACTION_PING to %d while it is migrating\n",
                        name, source);
        thorium_actor_send_reply_empty(actor, ACTION_PING);

        concrete_actor->migrated_other = 1;

    } else if (tag == ACTION_MIGRATE_REPLY) {

        thorium_message_unpack_int(message, 0, &other);
        printf("actor %d received migrated actor %d\n", name, other);
        printf("Acquaintances of actor %d: ", name);
        core_vector_print_int(acquaintance_vector);
        printf("\n");

        /* it is possible that the ACTION_PING went through
         * before the migration
         */
        if (concrete_actor->pings == 2) {
            thorium_actor_send_reply_empty(actor, ACTION_ASK_TO_STOP);
            thorium_actor_send_to_self_empty(actor, ACTION_ASK_TO_STOP);
        }

    } else if (tag == ACTION_PACK) {

        thorium_actor_send_reply_int(actor, ACTION_PACK_REPLY, concrete_actor->value);

    } else if (tag == ACTION_UNPACK) {

        thorium_message_unpack_int(message, 0, &concrete_actor->value);
        thorium_actor_send_reply_empty(actor, ACTION_UNPACK_REPLY);

    } else if (tag == ACTION_ASK_TO_STOP) {

        printf("actor %d received ACTION_ASK_TO_STOP, value: %d ",
                        name, concrete_actor->value);
        printf("acquaintance vector: ");
        core_vector_print_int(acquaintance_vector);
        printf("\n");

        thorium_actor_send_to_self_empty(actor, ACTION_STOP);
    }
}
Example #17
0
void reader_receive(struct thorium_actor *actor, struct thorium_message *message)
{
    int tag;
    int argc;
    char **argv;
    /*int i;*/
    int name;
    struct reader *reader1;
    int source;
    uint64_t count;
    void *buffer;
    int sequences;
    int script;
    int sequence_index;
    char *received_sequence;
    int error;

    reader1 = (struct reader *)thorium_actor_concrete_actor(actor);
    tag = thorium_message_action(message);
    source = thorium_message_source(message);
    buffer = thorium_message_buffer(message);
    name = thorium_actor_name(actor);

    if (tag == ACTION_START) {

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

        argc = thorium_actor_argc(actor);
        argv = thorium_actor_argv(actor);
        name = thorium_actor_name(actor);
        reader1->last_report = 0;

        /*
        printf("actor %i received %i arguments\n", name, argc);

        for (i = 0; i < argc ;i++) {
            printf("   argument %i : %s\n", i, argv[i]);
        }
        */

        if (core_vector_index_of(&reader1->spawners, &name) != 0) {
            thorium_message_init(message, ACTION_STOP, 0, NULL);
            thorium_actor_send(actor, name, message);

            return;
        }

        if (argc == 1) {
            thorium_message_init(message, ACTION_STOP, 0, NULL);
            thorium_actor_send(actor, name, message);

            return;
        }

        reader1->sequence_reader = thorium_actor_spawn(actor, SCRIPT_INPUT_STREAM);

        reader1->file = argv[argc - 1];

        thorium_message_init(message, ACTION_INPUT_OPEN, strlen(reader1->file) + 1,
                        reader1->file);

        printf("actor %i: asking actor %i to count entries in %s\n",
                        name, reader1->sequence_reader, reader1->file);

        thorium_actor_send(actor, reader1->sequence_reader, message);

    } else if (tag == ACTION_INPUT_COUNT_PROGRESS) {

        sequences = *(int64_t *)buffer;

        if (sequences < reader1->last_report + 10000000) {

            return;
        }

        printf("Actor %i received a progress report from actor %i: %i\n",
                        name, source, sequences);
        reader1->last_report = sequences;

    } else if (tag == ACTION_INPUT_OPEN_REPLY && !reader1->counted) {

        thorium_message_unpack_int(message, 0, &error);

        if (error == BIOSAL_INPUT_ERROR_NO_ERROR) {
            printf("Successfully opened file.\n");
            thorium_actor_send_reply_empty(actor, ACTION_INPUT_COUNT);

        } else if (error == BIOSAL_INPUT_ERROR_FILE_NOT_FOUND) {

            printf("Error, file not found! \n");
            thorium_actor_send_to_self_empty(actor, ACTION_STOP);

        } else if (error == BIOSAL_INPUT_ERROR_FORMAT_NOT_SUPPORTED) {

            printf("Error, format not supported! \n");
            thorium_actor_send_to_self_empty(actor, ACTION_STOP);

        }
    } else if (tag == ACTION_INPUT_COUNT_REPLY) {

        count = *(int64_t*)thorium_message_buffer(message);
        printf("actor %i: file has %" PRIu64 " items\n", name, count);

        thorium_message_init(message, ACTION_INPUT_CLOSE, 0, NULL);
        thorium_actor_send(actor, source, message);

        reader1->counted = 1;

    } else if (tag == ACTION_INPUT_CLOSE_REPLY && !reader1->pulled) {

        /* not necessary, it is already dead. */
        thorium_actor_send_reply_empty(actor, ACTION_ASK_TO_STOP);

        printf("actor %d received ACTION_INPUT_CLOSE_REPLY from actor %d, asking it to stop"
                        " with ACTION_ASK_TO_STOP\n", name, source);
            /*
        thorium_message_init(message, ACTION_STOP, 0, NULL);
        thorium_actor_send(actor, name, message);

        return;
        */

        script = SCRIPT_INPUT_STREAM;

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

    } else if (tag == ACTION_INPUT_CLOSE_REPLY && reader1->pulled) {

        thorium_actor_send_reply_empty(actor, ACTION_ASK_TO_STOP);

        thorium_actor_send_to_self_empty(actor, ACTION_STOP);

    } else if (tag == ACTION_ASK_TO_STOP_REPLY && reader1->pulled) {

        /* this tag will never arrive here */
        thorium_message_init(message, ACTION_STOP, 0, NULL);
        thorium_actor_send(actor, name, message);

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

        reader1->sequence_reader = *(int *)buffer;

        printf("actor %d tells actor %d to open %s to pull sequences from the file\n",
                        name, reader1->sequence_reader, reader1->file);

        thorium_message_init(message, ACTION_INPUT_OPEN,
                        strlen(reader1->file) + 1, reader1->file);
        thorium_actor_send(actor, reader1->sequence_reader, message);

    } else if (tag == ACTION_INPUT_OPEN_REPLY && reader1->counted) {

        thorium_message_init(message, ACTION_INPUT_GET_SEQUENCE, 0, NULL);
        thorium_actor_send(actor, source, message);

    } else if (tag == ACTION_INPUT_GET_SEQUENCE_REPLY) {

        sequence_index = *(int *)buffer;
        received_sequence = (char*)buffer + sizeof(sequence_index);

        /*
        printf("DEBUG %d %s\n", sequence_index, received_sequence);
*/
        if (sequence_index == 123456) {
            printf("actor %d says that sequence %d is %s.\n",
                            name, sequence_index, received_sequence);
        } else if (sequence_index % 100000 == 0) {
            printf("actor %d is pulling sequences from fellow local actor %d,"
                            " %d sequences pulled so far !\n",
                            name, reader1->sequence_reader, sequence_index);
        }

        if (sequence_index < 1000000) {
            thorium_message_init(message, ACTION_INPUT_GET_SEQUENCE, 0, NULL);
            thorium_actor_send(actor, source, message);
        } else {
            thorium_message_init(message, ACTION_INPUT_CLOSE, 0, NULL);
            thorium_actor_send(actor, source, message);
            reader1->pulled = 1;
        }

    } else if (tag == ACTION_INPUT_GET_SEQUENCE_END) {
        printf("actor %d: reached the end...\n", name);

        thorium_message_init(message, ACTION_INPUT_CLOSE, 0, NULL);
        thorium_actor_send(actor, source, message);

        reader1->pulled = 1;
    }
}
Example #18
0
void thorium_worker_run(struct thorium_worker *worker)
{
    struct thorium_actor *actor;
    struct thorium_message other_message;

#ifdef THORIUM_NODE_INJECT_CLEAN_WORKER_BUFFERS
    void *buffer;
#endif

#ifdef THORIUM_NODE_ENABLE_INSTRUMENTATION
    time_t current_time;
    int elapsed;
    int period;
    uint64_t current_nanoseconds;
    uint64_t elapsed_nanoseconds;
#endif

#ifdef THORIUM_WORKER_DEBUG
    int tag;
    int destination;
    struct thorium_message *message;
#endif

#ifdef THORIUM_WORKER_ENABLE_LOCK
    thorium_worker_lock(worker);
#endif

#ifdef THORIUM_NODE_ENABLE_INSTRUMENTATION
    period = THORIUM_NODE_LOAD_PERIOD;
    current_time = time(NULL);

    elapsed = current_time - worker->last_report;

    if (elapsed >= period) {

        current_nanoseconds = core_timer_get_nanoseconds(&worker->timer);

#ifdef THORIUM_WORKER_DEBUG_LOAD
        printf("DEBUG Updating load report\n");
#endif
        elapsed_nanoseconds = current_nanoseconds - worker->epoch_start_in_nanoseconds;

        if (elapsed_nanoseconds > 0) {
            worker->epoch_load = (0.0 + worker->epoch_used_nanoseconds) / elapsed_nanoseconds;
            worker->epoch_used_nanoseconds = 0;
            worker->last_wake_up_count = core_thread_get_wake_up_count(&worker->thread);

            /* \see http://stackoverflow.com/questions/9657993/negative-zero-in-c
             */
            if (worker->epoch_load == 0) {
                worker->epoch_load = 0;
            }

            worker->epoch_start_in_nanoseconds = current_nanoseconds;
            worker->last_report = current_time;
        }

#ifdef THORIUM_WORKER_PRINT_SCHEDULING_QUEUE

        /*
        if (thorium_node_name(worker->node) == 0
                        && worker->name == 0) {
                        */

        thorium_scheduler_print(&worker->scheduler,
                        thorium_node_name(worker->node),
                        worker->name);
            /*
        }
        */
#endif

        if (core_bitmap_get_bit_uint32_t(&worker->flags, FLAG_DEBUG_ACTORS)) {
            thorium_worker_print_actors(worker, NULL);
        }
    }
#endif

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

    /* check for messages in inbound FIFO */
    if (thorium_worker_dequeue_actor(worker, &actor)) {

#ifdef THORIUM_WORKER_DEBUG
        message = biosal_work_message(&work);
        tag = thorium_message_action(message);
        destination = thorium_message_destination(message);

        if (tag == ACTION_ASK_TO_STOP) {
            printf("DEBUG pulled ACTION_ASK_TO_STOP for %d\n",
                            destination);
        }
#endif

        /*
         * Update the priority of the actor
         * before starting the timer because this is part of the
         * runtime system (RTS).
         */

#ifdef THORIUM_UPDATE_SCHEDULING_PRIORITIES
        thorium_priority_assigner_update(&worker->scheduler, actor);
#endif

#ifdef THORIUM_NODE_ENABLE_INSTRUMENTATION
        core_timer_start(&worker->timer);
#endif

        core_bitmap_set_bit_uint32_t(&worker->flags, FLAG_BUSY);

        /*
         * Dispatch message to a worker
         */
        thorium_worker_work(worker, actor);

        core_bitmap_clear_bit_uint32_t(&worker->flags, FLAG_BUSY);

#ifdef THORIUM_NODE_ENABLE_INSTRUMENTATION
        core_timer_stop(&worker->timer);

        elapsed_nanoseconds = core_timer_get_elapsed_nanoseconds(&worker->timer);

        if (elapsed_nanoseconds >= THORIUM_GRANULARITY_WARNING_THRESHOLD) {
        }

        worker->epoch_used_nanoseconds += elapsed_nanoseconds;
        worker->loop_used_nanoseconds += elapsed_nanoseconds;
        worker->scheduling_epoch_used_nanoseconds += elapsed_nanoseconds;

        worker->last_elapsed_nanoseconds = elapsed_nanoseconds;
#endif
    }

    /* queue buffered message
     */
    if (core_fast_queue_dequeue(&worker->outbound_message_queue_buffer, &other_message)) {

        if (!core_fast_ring_push_from_producer(&worker->outbound_message_queue, &other_message)) {

#ifdef SHOW_FULL_RING_WARNINGS
            printf("thorium_worker: Warning: ring is full => outbound_message_queue\n");
#endif

            core_fast_queue_enqueue(&worker->outbound_message_queue_buffer, &other_message);
        }
    }

#ifdef THORIUM_NODE_INJECT_CLEAN_WORKER_BUFFERS
    /*
     * Free outbound buffers, if any
     */

    if (thorium_worker_fetch_clean_outbound_buffer(worker, &buffer)) {
        core_memory_pool_free(&worker->outbound_message_memory_pool, buffer);

#ifdef THORIUM_WORKER_DEBUG_INJECTION
        ++worker->counter_freed_outbound_buffers_from_other_workers;
#endif
    }
#endif

    /*
     * Transfer messages for triage
     */

    if (core_fast_queue_dequeue(&worker->clean_message_queue_for_triage, &other_message)) {

        CORE_DEBUGGER_ASSERT(thorium_message_buffer(&other_message) != NULL);
        thorium_worker_enqueue_message_for_triage(worker, &other_message);
    }

#ifdef THORIUM_WORKER_ENABLE_LOCK
    thorium_worker_unlock(worker);
#endif
}
Example #19
0
int thorium_balancer_select_worker_least_busy(
                struct thorium_balancer *self, int *worker_score)
{
    int to_check;
    int score;
    int best_score;
    struct thorium_worker *worker;
    struct thorium_worker *best_worker;
    int selected_worker;

#if 0
    int last_worker_score;
#endif

#ifdef THORIUM_WORKER_DEBUG
    int tag;
    int destination;
    struct thorium_message *message;
#endif

    best_worker = NULL;
    best_score = 99;

    to_check = THORIUM_SCHEDULER_WORK_SCHEDULING_WINDOW;

    while (to_check--) {

        /*
         * get the worker to test for this iteration.
         */
        worker = thorium_worker_pool_get_worker(self->pool, self->worker_for_work);

        score = thorium_worker_get_epoch_load(worker);

#ifdef THORIUM_WORKER_POOL_DEBUG_ISSUE_334
        if (score >= THORIUM_WORKER_WARNING_THRESHOLD
                        && (self->last_scheduling_warning == 0
                             || score >= self->last_scheduling_warning + THORIUM_WORKER_WARNING_THRESHOLD_STRIDE)) {
            printf("Warning: node %d worker %d has a scheduling score of %d\n",
                            thorium_node_name(thorium_worker_pool_get_node(self->pool)),
                            self->worker_for_work, score);

            self->last_scheduling_warning = score;
        }
#endif

        /* if the worker is not busy and it has no work to do,
         * select it right away...
         */
        if (score == 0) {
            best_worker = worker;
            best_score = 0;
            break;
        }

        /* Otherwise, test the worker
         */
        if (best_worker == NULL || score < best_score) {
            best_worker = worker;
            best_score = score;
        }

        /*
         * assign the next worker
         */
        self->worker_for_work = thorium_worker_pool_next_worker(self->pool, self->worker_for_work);
    }

#ifdef THORIUM_WORKER_POOL_DEBUG
    message = biosal_work_message(work);
    tag = thorium_message_action(message);
    destination = thorium_message_destination(message);

    if (tag == ACTION_ASK_TO_STOP) {
        printf("DEBUG dispatching ACTION_ASK_TO_STOP for actor %d to worker %d\n",
                        destination, *start);
    }


#endif

    selected_worker = self->worker_for_work;

    /*
     * assign the next worker
     */
    self->worker_for_work = thorium_worker_pool_next_worker(self->pool, self->worker_for_work);

    *worker_score = best_score;
    /* This is a best effort algorithm
     */
    return selected_worker;
}
Example #20
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);
    }
}
Example #21
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
}
Example #22
0
/*
 * Basically, this actor does this:
 * - spawn visitors
 * - let them visit stuff
 * - kill them.
 * - spawn walkers
 * - let them walk
 * - kill the walkers
 * - return OK
 */
void biosal_unitig_manager_receive(struct thorium_actor *self, struct thorium_message *message)
{
    struct biosal_unitig_manager *concrete_self;
    int tag;
    void *buffer;
    int spawner;
    int expected;
    int script;
    int actor_count;
    int source;
    struct core_string file_name;
    char *directory;
    int argc;
    char **argv;
    char *path;

    tag = thorium_message_action(message);
    source = thorium_message_source(message);
    buffer = thorium_message_buffer(message);

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

    if (tag == ACTION_START) {

        core_vector_unpack(&concrete_self->spawners, buffer);

        spawner = thorium_actor_get_random_spawner(self, &concrete_self->spawners);

        concrete_self->state = STATE_SPAWN_WRITER;

        thorium_actor_send_int(self, spawner, ACTION_SPAWN, SCRIPT_WRITER_PROCESS);

    } else if (tag == ACTION_SPAWN_REPLY
                    && concrete_self->state == STATE_SPAWN_WRITER) {

        thorium_message_unpack_int(message, 0, &concrete_self->writer_process);

        /*
         * open the file now.
         */

        argc = thorium_actor_argc(self);
        argv = thorium_actor_argv(self);
        directory = core_command_get_output_directory(argc, argv);
        core_string_init(&file_name, directory);
        core_string_append(&file_name, "/");
        core_string_append(&file_name, "unitigs.fasta");
        path = core_string_get(&file_name);

        thorium_actor_send_buffer(self, concrete_self->writer_process,
                        ACTION_OPEN, strlen(path) + 1, path);

        core_string_destroy(&file_name);

    } else if (tag == ACTION_OPEN_REPLY
                    && source == concrete_self->writer_process) {
        /*
         * Spawn visitors.
         */
        concrete_self->state = STATE_VISITORS;
        thorium_actor_send_to_self_empty(self, ACTION_PING);

    } else if (tag == ACTION_PING) {
        spawner = thorium_actor_get_random_spawner(self, &concrete_self->spawners);
        thorium_actor_send_int(self, spawner, ACTION_SPAWN, SCRIPT_MANAGER);

    } else if (tag == ACTION_SPAWN_REPLY) {

        thorium_message_unpack_int(message, 0, &concrete_self->manager);

        script = SCRIPT_UNITIG_VISITOR;

        if (concrete_self->state == STATE_WALKERS) {
            script = SCRIPT_UNITIG_WALKER;
        }
        thorium_actor_send_int(self, concrete_self->manager, ACTION_MANAGER_SET_SCRIPT,
                        script);

    } else if (tag == ACTION_ASK_TO_STOP) {

        thorium_actor_send_empty(self, concrete_self->writer_process,
                        ACTION_ASK_TO_STOP);

        thorium_actor_send_empty(self, concrete_self->manager,
                        ACTION_ASK_TO_STOP);

        thorium_actor_send_to_self_empty(self, ACTION_STOP);

        thorium_actor_send_reply_empty(self, ACTION_ASK_TO_STOP_REPLY);

    } else if (tag == ACTION_MANAGER_SET_SCRIPT_REPLY) {

        actor_count = UNITIG_VISITOR_COUNT_PER_WORKER;

        if (concrete_self->state == STATE_WALKERS)
            actor_count = UNITIG_WALKER_COUNT_PER_WORKER;

        thorium_actor_send_reply_int(self, ACTION_MANAGER_SET_ACTORS_PER_WORKER,
                        actor_count);

    } else if (tag == ACTION_MANAGER_SET_ACTORS_PER_WORKER_REPLY) {

        thorium_actor_send_reply_vector(self, ACTION_START,
                        &concrete_self->spawners);

    } else if (tag == ACTION_START_REPLY
                    && concrete_self->state == STATE_VISITORS
                    && core_vector_size(&concrete_self->visitors) == 0) {

        core_vector_unpack(&concrete_self->visitors, buffer);

        printf("DEBUG the system has %d visitors\n",
                        (int)core_vector_size(&concrete_self->visitors));

        thorium_actor_send_to_supervisor_empty(self, ACTION_START_REPLY);

    } else if (tag == ACTION_START_REPLY
                    && concrete_self->state == STATE_WALKERS
                    && core_vector_size(&concrete_self->walkers) == 0) {

        core_vector_unpack(&concrete_self->walkers, buffer);

        printf("DEBUG the system has %d walkers\n",
                        (int)core_vector_size(&concrete_self->walkers));

        core_timer_start(&concrete_self->timer);
        concrete_self->completed = 0;

        thorium_actor_send_range_int(self, &concrete_self->walkers,
                        ACTION_SET_CONSUMER, concrete_self->writer_process);
        thorium_actor_send_range_vector(self, &concrete_self->walkers,
                        ACTION_START, &concrete_self->graph_stores);

    } else if (tag == ACTION_SET_PRODUCERS) {

        core_vector_unpack(&concrete_self->graph_stores, buffer);

        core_timer_start(&concrete_self->timer);

        concrete_self->completed = 0;
        thorium_actor_send_range_vector(self, &concrete_self->visitors,
                        ACTION_START, &concrete_self->graph_stores);

    } else if (tag == ACTION_START_REPLY && concrete_self->state == STATE_VISITORS) {

        ++concrete_self->completed;
        expected = core_vector_size(&concrete_self->visitors);

        if (concrete_self->completed % UNITIG_VISITOR_COUNT_PER_WORKER == 0
                        || concrete_self->completed == expected) {
            printf("PROGRESS unitig visitors %d/%d\n",
                        concrete_self->completed,
                        expected);
        }

        if (concrete_self->completed == expected) {

            core_timer_stop(&concrete_self->timer);
            core_timer_print_with_description(&concrete_self->timer, "Visit vertices for unitigs");

            /*
             * Stop the visitor manager and all visitors too.
             */
            thorium_actor_send_empty(self, concrete_self->manager, ACTION_ASK_TO_STOP);

            /*
             * Reset graph stores.
             */
            thorium_actor_send_range_empty(self, &concrete_self->graph_stores,
                            ACTION_RESET);
            concrete_self->completed = 0;
        }

    } else if (tag == ACTION_RESET_REPLY) {

        ++concrete_self->completed;
        expected = core_vector_size(&concrete_self->graph_stores);

        if (concrete_self->completed == expected) {
            concrete_self->completed = 0;
            concrete_self->state = STATE_WALKERS;

            /*
             * Go back at the beginning.
             */
            thorium_actor_send_to_self_empty(self, ACTION_PING);
        }
    } else if (tag == ACTION_START_REPLY && concrete_self->state == STATE_WALKERS) {

        ++concrete_self->completed;
        expected = core_vector_size(&concrete_self->walkers);

        if (concrete_self->completed % UNITIG_WALKER_COUNT_PER_WORKER == 0
                        || concrete_self->completed == expected) {
            printf("PROGRESS unitig walkers %d/%d\n",
                        concrete_self->completed,
                        expected);
        }

        if (concrete_self->completed == expected) {

            core_timer_stop(&concrete_self->timer);
            core_timer_print_with_description(&concrete_self->timer, "Walk for unitigs");

            thorium_actor_send_to_supervisor_empty(self, ACTION_SET_PRODUCERS_REPLY);
        }
    }
}
Example #23
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;
}
Example #24
0
void biosal_assembly_graph_store_receive(struct thorium_actor *self, struct thorium_message *message)
{
    int tag;
    /*void *buffer;*/
    struct biosal_assembly_graph_store *concrete_self;
    double value;
    struct biosal_dna_kmer kmer;
    /*struct core_memory_pool *ephemeral_memory;*/
    int customer;
    int big_key_size;
    int big_value_size;

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

    /*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);*/

    if (tag == ACTION_SET_KMER_LENGTH) {

        thorium_message_unpack_int(message, 0, &concrete_self->kmer_length);

        biosal_dna_kmer_init_mock(&kmer, concrete_self->kmer_length,
                        &concrete_self->storage_codec, thorium_actor_get_ephemeral_memory(self));
        concrete_self->key_length_in_bytes = biosal_dna_kmer_pack_size(&kmer,
                        concrete_self->kmer_length, &concrete_self->storage_codec);
        biosal_dna_kmer_destroy(&kmer, thorium_actor_get_ephemeral_memory(self));

        big_key_size = concrete_self->key_length_in_bytes;
        big_value_size = sizeof(struct biosal_assembly_vertex);

        core_map_init(&concrete_self->table, big_key_size,
                        big_value_size);
        core_map_set_memory_pool(&concrete_self->table,
                        &concrete_self->persistent_memory);

        printf("DEBUG big_key_size %d big_value_size %d\n", big_key_size, big_value_size);

        /*
         * Configure the map for better performance.
         */
        core_map_disable_deletion_support(&concrete_self->table);

        /*
         * The threshold of the map is not very important because
         * requests that hit the map have to first arrive as messages,
         * which are slow.
         */
        core_map_set_threshold(&concrete_self->table, 0.95);

        thorium_actor_send_reply_empty(self, ACTION_SET_KMER_LENGTH_REPLY);

    } else if (tag == ACTION_ASSEMBLY_GET_KMER_LENGTH) {

        thorium_actor_send_reply_int(self, ACTION_ASSEMBLY_GET_KMER_LENGTH_REPLY,
                        concrete_self->kmer_length);

    } else if (tag == ACTION_RESET) {

        /*
         * Reset the iterator.
         */
        core_map_iterator_init(&concrete_self->iterator, &concrete_self->table);

        printf("DEBUG unitig_vertex_count %d\n",
                        concrete_self->unitig_vertex_count);

        thorium_actor_send_reply_empty(self, ACTION_RESET_REPLY);

    } else if (tag == ACTION_SEQUENCE_STORE_REQUEST_PROGRESS_REPLY) {

        thorium_message_unpack_double(message, 0, &value);

        core_map_set_current_size_estimate(&concrete_self->table, value);

    } else if (tag == ACTION_ASK_TO_STOP) {

        printf("%s/%d received %d arc blocks\n",
                        thorium_actor_script_name(self),
                        thorium_actor_name(self),
                        concrete_self->received_arc_block_count);

        thorium_actor_ask_to_stop(self, message);

    } else if (tag == ACTION_SET_CONSUMER) {

        thorium_message_unpack_int(message, 0, &customer);

        printf("%s/%d will use coverage distribution %d\n",
                        thorium_actor_script_name(self),
                        thorium_actor_name(self), customer);

        concrete_self->customer = customer;

        thorium_actor_send_reply_empty(self, ACTION_SET_CONSUMER_REPLY);

    } else if (tag == ACTION_PUSH_DATA) {

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

        biosal_assembly_graph_store_push_data(self, message);

    } else if (tag == ACTION_STORE_GET_ENTRY_COUNT) {

        thorium_actor_send_reply_uint64_t(self, ACTION_STORE_GET_ENTRY_COUNT_REPLY,
                        concrete_self->received);

    } else if (tag == ACTION_GET_RECEIVED_ARC_COUNT) {

        thorium_actor_send_reply_uint64_t(self, ACTION_GET_RECEIVED_ARC_COUNT_REPLY,
                        concrete_self->received_arc_count);
    }
}
Example #25
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);
    }
}
Example #26
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);
    }
}
Example #27
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;
}
Example #28
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;
}