/* *This is called from within the actor running inside this worker. */ void thorium_worker_free_message(struct thorium_worker *worker, struct thorium_message *message) { int source_worker; void *buffer; buffer = thorium_message_buffer(message); source_worker = thorium_message_worker(message); if (source_worker == worker->name) { /* This is from the current worker */ core_memory_pool_free(&worker->outbound_message_memory_pool, buffer); #ifdef THORIUM_WORKER_DEBUG_INJECTION ++worker->counter_freed_outbound_buffers_from_self; #endif } else { /* This is from another fellow local worker * or from another BIOSAL node altogether. */ CORE_DEBUGGER_ASSERT(thorium_message_buffer(message) != NULL); thorium_worker_enqueue_message_for_triage(worker, message); } }
void spate_start_reply_builder(struct thorium_actor *self, struct thorium_message *message) { void *buffer; int spawner; struct spate *concrete_self; concrete_self = (struct spate *)thorium_actor_concrete_actor(self); buffer = thorium_message_buffer(message); core_vector_unpack(&concrete_self->graph_stores, buffer); thorium_actor_log(self, "%s/%d has %d graph stores", thorium_actor_script_name(self), thorium_actor_name(self), (int)core_vector_size(&concrete_self->graph_stores)); spawner = thorium_actor_get_spawner(self, &concrete_self->initial_actors); concrete_self->unitig_manager = THORIUM_ACTOR_SPAWNING_IN_PROGRESS; thorium_actor_add_action_with_condition(self, ACTION_SPAWN_REPLY, spate_spawn_reply_unitig_manager, &concrete_self->unitig_manager, THORIUM_ACTOR_SPAWNING_IN_PROGRESS); thorium_actor_send_int(self, spawner, ACTION_SPAWN, SCRIPT_UNITIG_MANAGER); }
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); }
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); } }
void process_ping(struct thorium_actor *self, struct thorium_message *message) { int count; char *buffer; int buffer_size; uint64_t *bucket; uint64_t expected_checksum; uint64_t actual_checksum; struct process *concrete_self; concrete_self = (struct process *)thorium_actor_concrete_actor(self); buffer = thorium_message_buffer(message); count = thorium_message_count(message); buffer_size = count - sizeof(expected_checksum); bucket = (uint64_t *)(buffer + buffer_size); expected_checksum = *bucket; actual_checksum = core_hash_data_uint64_t(buffer, buffer_size, SEED); if (expected_checksum != actual_checksum) { printf("TRANSPORT FAILED source: %d (%d) destination: %d (%d) tag: ACTION_PING count: %d" " expected_checksum: %" PRIu64 " actual_checksum: %" PRIu64 "\n", thorium_message_source(message), thorium_message_source_node(message), thorium_message_destination(message), thorium_message_destination_node(message), count, expected_checksum, actual_checksum); ++concrete_self->failed; } else { ++concrete_self->passed; } thorium_actor_send_reply_empty(self, ACTION_PING_REPLY); }
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; }
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 }
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); } }
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)); }
int thorium_worker_dequeue_message_for_triage(struct thorium_worker *worker, struct thorium_message *message) { int value; value = core_fast_ring_pop_from_consumer(&worker->clean_message_ring_for_triage, message); #ifdef CORE_DEBUGGER_ENABLE_ASSERT if (value) { CORE_DEBUGGER_ASSERT(thorium_message_buffer(message) != NULL); } #endif return value; }
void process_start(struct thorium_actor *self, struct thorium_message *message) { void *buffer; struct process *concrete_self; concrete_self = (struct process *)thorium_actor_concrete_actor(self); buffer = thorium_message_buffer(message); core_vector_unpack(&concrete_self->actors, buffer); concrete_self->ready = 0; while (concrete_self->active_messages < concrete_self->concurrent_event_count) { process_send_ping(self); } }
void thorium_actor_unpack_proxy_message(struct thorium_actor *self, struct thorium_message *message) { int new_count; int tag; int source; void *buffer; int offset; buffer = thorium_message_buffer(message); new_count = thorium_message_count(message); new_count -= sizeof(source); new_count -= sizeof(tag); offset = new_count; source = *(int *)((char *)buffer + offset); offset += sizeof(source); tag = *(int *)((char *)buffer + offset); #ifdef DEBUG_BINOMIAL_TREE printf("DEBUG_BINOMIAL_TREE unpack_proxy_message real_count %d real_source %d real_action %x\n", new_count, source, tag); #endif /* * The action can not be ACTION_INVALID because it is invalid * by convention. */ CORE_DEBUGGER_ASSERT(tag != ACTION_INVALID); offset += sizeof(tag); /*thorium_message_init(message, tag, new_count, buffer);*/ /* * Change the tag, source, and count. */ thorium_message_set_source(message, source); thorium_message_set_action(message, tag); thorium_message_set_count(message, new_count); #if 0 printf("DEBUG unpack_proxy_message... source %d tag %d count %d\n", source, tag, new_count); #endif }
void biosal_assembly_graph_store_set_vertex_flag(struct thorium_actor *self, struct thorium_message *message) { char *buffer; int count; int flag; struct biosal_dna_kmer transport_kmer; struct biosal_assembly_vertex *vertex; struct biosal_assembly_graph_store *concrete_self; struct core_memory_pool *ephemeral_memory; int position; concrete_self = thorium_actor_concrete_actor(self); ephemeral_memory = thorium_actor_get_ephemeral_memory(self); biosal_dna_kmer_init_empty(&transport_kmer); buffer = thorium_message_buffer(message); count = thorium_message_count(message); position = 0; position += biosal_dna_kmer_unpack(&transport_kmer, buffer, concrete_self->kmer_length, ephemeral_memory, &concrete_self->transport_codec); core_memory_copy(&flag, buffer + position, sizeof(flag)); position += sizeof(flag); CORE_DEBUGGER_ASSERT_IS_EQUAL_INT(position, count); CORE_DEBUGGER_ASSERT(flag >= BIOSAL_VERTEX_FLAG_START_VALUE); CORE_DEBUGGER_ASSERT(flag <= BIOSAL_VERTEX_FLAG_END_VALUE); if (flag == BIOSAL_VERTEX_FLAG_UNITIG) { ++concrete_self->unitig_vertex_count; } #if 0 printf("DEBUG ACTION_SET_VERTEX_FLAG %d\n", flag); #endif vertex = biosal_assembly_graph_store_find_vertex(self, &transport_kmer); CORE_DEBUGGER_ASSERT_NOT_NULL(vertex); biosal_dna_kmer_destroy(&transport_kmer, ephemeral_memory); biosal_assembly_vertex_set_flag(vertex, flag); thorium_actor_send_reply_empty(self, ACTION_SET_VERTEX_FLAG_REPLY); }
/* 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); } }
/* \see http://www.mpich.org/static/docs/v3.1/www3/MPI_Isend.html */ int thorium_mpi1_pt2pt_transport_send(struct thorium_transport *self, struct thorium_message *message) { struct thorium_mpi1_pt2pt_transport *concrete_self; char *buffer; int count; int destination; int tag; MPI_Request *request; struct thorium_mpi1_pt2pt_active_request active_request; int worker; int result; concrete_self = thorium_transport_get_concrete_transport(self); worker = thorium_message_worker(message); buffer = thorium_message_buffer(message); count = thorium_message_count(message); destination = thorium_message_destination_node(message); tag = DUMMY_TAG; thorium_mpi1_pt2pt_active_request_init(&active_request, buffer, worker); request = thorium_mpi1_pt2pt_active_request_request(&active_request); CORE_DEBUGGER_ASSERT(buffer == NULL || count > 0); /* get return value */ result = MPI_Isend(buffer, count, concrete_self->datatype, destination, tag, concrete_self->comm, request); if (result != MPI_SUCCESS) { return 0; } /* store the MPI_Request to test it later to know when * the buffer can be reused */ /* \see http://blogs.cisco.com/performance/mpi_request_free-is-evil/ */ /*MPI_Request_free(&request);*/ core_fast_queue_enqueue(&concrete_self->active_requests, &active_request); return 1; }
void biosal_input_controller_receive_store_entry_counts(struct thorium_actor *actor, struct thorium_message *message) { struct biosal_input_controller *concrete_actor; struct core_vector store_entries; void *buffer; int i; int store; uint64_t entries; struct thorium_message new_message; int name; core_vector_init(&store_entries, sizeof(uint64_t)); concrete_actor = (struct biosal_input_controller *)thorium_actor_concrete_actor(actor); buffer = thorium_message_buffer(message); name = thorium_actor_name(actor); concrete_actor->ready_consumers = 0; #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG printf("DEBUG biosal_input_controller_receive_store_entry_counts unpacking entries\n"); #endif core_vector_init(&store_entries, 0); core_vector_unpack(&store_entries, buffer); for (i = 0; i < core_vector_size(&store_entries); i++) { store = *(int *)core_vector_at(&concrete_actor->consumers, i); entries = *(uint64_t *)core_vector_at(&store_entries, i); printf("DEBUG controller/%d tells consumer/%d to reserve %" PRIu64 " buckets\n", name, store, entries); thorium_message_init(&new_message, ACTION_RESERVE, sizeof(entries), &entries); thorium_actor_send(actor, store, &new_message); } #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG printf("DEBUG biosal_input_controller_receive_store_entry_counts will wait for replies\n"); #endif core_vector_destroy(&store_entries); }
int thorium_message_unpack_double(struct thorium_message *message, int offset, double *value) { int bytes; void *buffer; double *pointer; if (offset >= thorium_message_count(message)) { return -1; } bytes = sizeof(double); buffer = thorium_message_buffer(message); pointer = (double *)((char *)buffer + offset); *value = *pointer; return bytes; }
int thorium_message_unpack_int64_t(struct thorium_message *message, int offset, int64_t *value) { int bytes; void *buffer; int64_t *pointer; if (offset >= thorium_message_count(message)) { return -1; } bytes = sizeof(int64_t); buffer = thorium_message_buffer(message); pointer = (int64_t *)((char *)buffer + offset); *value = *pointer; return bytes; }
void biosal_input_stream_count_reply_mock(struct thorium_actor *self, struct thorium_message *message) { struct biosal_input_stream *concrete_self; void *buffer; int count; struct core_vector mega_blocks; char *file; struct core_memory_pool *ephemeral_memory; uint64_t result; struct biosal_mega_block *block; concrete_self = (struct biosal_input_stream *)thorium_actor_concrete_actor(self); buffer = thorium_message_buffer(message); count = thorium_message_count(message); ephemeral_memory = thorium_actor_get_ephemeral_memory(self); core_vector_init(&mega_blocks, 0); core_vector_set_memory_pool(&mega_blocks, ephemeral_memory); core_vector_unpack(&mega_blocks, buffer); block = core_vector_at_last(&mega_blocks); result = biosal_mega_block_get_entries(block); #if 0 file = core_string_get(&concrete_self->file_for_parallel_counting); #endif file = concrete_self->file_name; printf("%s/%d COUNT_IN_PARALLEL result for %s is %" PRIu64 "\n", thorium_actor_script_name(self), thorium_actor_name(self), file, result); core_vector_destroy(&mega_blocks); thorium_actor_send_buffer(self, concrete_self->controller, ACTION_INPUT_COUNT_IN_PARALLEL_REPLY, count, buffer); }
void biosal_input_stream_count_in_parallel_mock(struct thorium_actor *self, struct thorium_message *message) { struct biosal_input_stream *concrete_self; void *buffer; int count; char *file; concrete_self = (struct biosal_input_stream *)thorium_actor_concrete_actor(self); buffer = thorium_message_buffer(message); count = thorium_message_count(message); file = concrete_self->file_name; printf("%s/%d receives ACTION_INPUT_COUNT_IN_PARALLEL file %s\n", thorium_actor_script_name(self), thorium_actor_name(self), file); thorium_actor_send_to_self_buffer(self, ACTION_INPUT_COUNT, count, buffer); }
void framr_start(actor_t *actor, message_t *message) { int name; int rank; int size; int neighbor_rank; int neighbor_name; void * buffer; framr_t *self; struct core_vector *spawners; framr_process_args(actor); self = thorium_actor_concrete_actor(actor); name = thorium_actor_name(actor); buffer = thorium_message_buffer(message); spawners = &self->spawners; size = core_vector_size(spawners); pm("received ACTION_START\n"); core_vector_unpack(spawners, buffer); size = core_vector_size(spawners); rank = core_vector_index_of(spawners, &name); neighbor_rank = (rank + 1) % size; neighbor_name = core_vector_at_as_int(spawners, neighbor_rank); pm("Spawner world size = %d\n", size); pm("Spawner %d about to send hello to neighbor %d\n", rank, neighbor_rank); thorium_actor_send_empty(actor, neighbor_name, ACTION_FRAMR_HELLO); /* thorium_message_init(&new_message, ACTION_FRAMR_HELLO, 0, NULL); */ /* thorium_actor_send(actor, neighbor_name, &new_message); */ /* thorium_message_destroy(&new_message); */ }
void spate_start_reply_manager(struct thorium_actor *self, struct thorium_message *message) { struct core_vector consumers; struct spate *concrete_self; void *buffer; concrete_self = (struct spate *)thorium_actor_concrete_actor(self); core_vector_init(&consumers, sizeof(int)); buffer = thorium_message_buffer(message); core_vector_unpack(&consumers, buffer); thorium_actor_log(self, "spate %d sends the names of %d consumers to controller %d", thorium_actor_name(self), (int)core_vector_size(&consumers), concrete_self->input_controller); thorium_actor_send_vector(self, concrete_self->input_controller, ACTION_SET_CONSUMERS, &consumers); core_vector_push_back_vector(&concrete_self->sequence_stores, &consumers); core_vector_destroy(&consumers); }
void spate_start(struct thorium_actor *self, struct thorium_message *message) { void *buffer; int name; struct spate *concrete_self; int spawner; char *directory_name; int already_created; int argc; char **argv; #ifdef SPATE_VERBOSE thorium_actor_send_to_self_int(self, ACTION_ENABLE_LOG_LEVEL, LOG_LEVEL_DEFAULT); #endif concrete_self = (struct spate *)thorium_actor_concrete_actor(self); buffer = thorium_message_buffer(message); name = thorium_actor_name(self); /* * The buffer contains initial actors spawned by Thorium */ core_vector_unpack(&concrete_self->initial_actors, buffer); if (!spate_must_print_help(self)) { thorium_actor_log(self, "spate/%d starts", name); } if (core_vector_index_of(&concrete_self->initial_actors, &name) == 0) { concrete_self->is_leader = 1; } /* * Abort if the actor is not the leader of the tribe. */ if (!concrete_self->is_leader) { return; } if (spate_must_print_help(self)) { spate_help(self); spate_stop(self); return; } /* * Otherwise, the coverage distribution will take care of creating * the directory. */ core_timer_start(&concrete_self->timer); /* * Verify if the directory already exists. If it does, don't * do anything as it is not a good thing to overwrite previous science * results. */ argc = thorium_actor_argc(self); argv = thorium_actor_argv(self); directory_name = biosal_command_get_output_directory(argc, argv); already_created = core_directory_verify_existence(directory_name); if (already_created) { thorium_actor_log(self, "%s/%d Error: output directory \"%s\" already exists, please delete it or use a different output directory", thorium_actor_script_name(self), thorium_actor_name(self), directory_name); spate_stop(self); return; } spawner = thorium_actor_get_spawner(self, &concrete_self->initial_actors); thorium_actor_send_int(self, spawner, ACTION_SPAWN, SCRIPT_INPUT_CONTROLLER); }
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); } } }
void biosal_input_controller_receive_command(struct thorium_actor *actor, struct thorium_message *message) { struct biosal_partition_command command; void *buffer; int stream_index; int store_index; int store_name; uint64_t store_first; uint64_t store_last; int command_name; int stream_name; int *bucket_for_command_name; int bytes; struct biosal_input_command input_command; void *new_buffer; struct thorium_message new_message; struct biosal_input_controller *concrete_actor; int *bucket; int *bucket_for_consumer; int consumer_index; concrete_actor = (struct biosal_input_controller *)thorium_actor_concrete_actor(actor); buffer = thorium_message_buffer(message); biosal_partition_command_unpack(&command, buffer); stream_index = biosal_partition_command_stream_index(&command); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_COMMANDS printf("DEBUG biosal_input_controller_receive_command controller receives command for stream %d\n", stream_index); biosal_partition_command_print(&command); #endif store_index = biosal_partition_command_store_index(&command); bucket_for_command_name = (int *)core_vector_at(&concrete_actor->partition_commands, stream_index); bucket_for_consumer = (int *)core_vector_at(&concrete_actor->stream_consumers, stream_index); stream_name = core_vector_at_as_int(&concrete_actor->reading_streams, stream_index); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_COMMANDS printf("DEBUG stream_index %d stream_name %d\n", stream_index, stream_name); #endif store_name = *(int *)core_vector_at(&concrete_actor->consumers, store_index); store_first = biosal_partition_command_store_first(&command); store_last = biosal_partition_command_store_last(&command); biosal_input_command_init(&input_command, store_name, store_first, store_last); bytes = biosal_input_command_pack_size(&input_command, &concrete_actor->codec); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_COMMANDS printf("DEBUG input command\n"); biosal_input_command_print(&input_command); printf("DEBUG biosal_input_controller_receive_command bytes %d\n", bytes); #endif new_buffer = thorium_actor_allocate(actor, bytes); biosal_input_command_pack(&input_command, new_buffer, &concrete_actor->codec); thorium_message_init(&new_message, ACTION_INPUT_PUSH_SEQUENCES, bytes, new_buffer); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_COMMANDS printf("DEBUG biosal_input_controller_receive_command sending ACTION_INPUT_PUSH_SEQUENCES to %d (index %d)\n", stream_name, stream_index); biosal_input_command_print(&input_command); printf("SENDING COMMAND TO stream/%d\n", stream_name); #endif thorium_actor_send(actor, stream_name, &new_message); command_name = biosal_partition_command_name(&command); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_COMMANDS printf("controller/%d processed input command %d %p\n", thorium_actor_name(actor), command_name, (void *)bucket_for_command_name); #endif *bucket_for_command_name = command_name; consumer_index = store_index; *bucket_for_consumer = consumer_index; bucket = (int *)core_vector_at(&concrete_actor->consumer_active_requests, consumer_index); (*bucket)++; #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_CONSUMERS printf("DEBUG consumer # %d has %d active requests\n", consumer_index, *bucket); #endif }
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; } }
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); } }
void biosal_assembly_arc_classifier_push_arc_block(struct thorium_actor *self, struct thorium_message *message) { struct biosal_assembly_arc_classifier *concrete_self; int source; struct biosal_assembly_arc_block input_block; struct biosal_assembly_arc_block *output_block; struct core_vector output_blocks; struct core_memory_pool *ephemeral_memory; int consumer_count; struct core_vector *input_arcs; struct core_vector *output_arcs; int size; int i; struct biosal_assembly_arc *arc; void *buffer; int count; struct biosal_dna_kmer *kmer; int consumer_index; int arc_count; int consumer; struct thorium_message new_message; int new_count; void *new_buffer; int *bucket; int maximum_pending_requests; int maximum_buffer_length; int reservation; count = thorium_message_count(message); buffer = thorium_message_buffer(message); if (count == 0) { printf("Error, count is 0 (classifier_push_arc_block)\n"); return; } concrete_self = (struct biosal_assembly_arc_classifier *)thorium_actor_concrete_actor(self); source = thorium_message_source(message); consumer_count = core_vector_size(&concrete_self->consumers); ephemeral_memory = thorium_actor_get_ephemeral_memory(self); CORE_DEBUGGER_LEAK_DETECTION_BEGIN(ephemeral_memory, classify_arcs); core_vector_init(&output_blocks, sizeof(struct biosal_assembly_arc_block)); core_vector_set_memory_pool(&output_blocks, ephemeral_memory); biosal_assembly_arc_block_init(&input_block, ephemeral_memory, concrete_self->kmer_length, &concrete_self->codec); #ifdef BIOSAL_ASSEMBLY_ARC_CLASSIFIER_DEBUG printf("UNPACKING\n"); #endif biosal_assembly_arc_block_unpack(&input_block, buffer, concrete_self->kmer_length, &concrete_self->codec, ephemeral_memory); #ifdef BIOSAL_ASSEMBLY_ARC_CLASSIFIER_DEBUG printf("OK\n"); #endif input_arcs = biosal_assembly_arc_block_get_arcs(&input_block); /* * Configure the ephemeral memory reservation. */ arc_count = core_vector_size(input_arcs); reservation = (arc_count / consumer_count) * 2; core_vector_resize(&output_blocks, consumer_count); CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory)); /* * Initialize output blocks. * There is one for each destination. */ for (i = 0; i < consumer_count; i++) { output_block = core_vector_at(&output_blocks, i); biosal_assembly_arc_block_init(output_block, ephemeral_memory, concrete_self->kmer_length, &concrete_self->codec); biosal_assembly_arc_block_reserve(output_block, reservation); } size = core_vector_size(input_arcs); /* * Classify every arc in the input block * and put them in output blocks. */ #ifdef BIOSAL_ASSEMBLY_ARC_CLASSIFIER_DEBUG printf("ClassifyArcs arc_count= %d\n", size); #endif CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory)); for (i = 0; i < size; i++) { arc = core_vector_at(input_arcs, i); kmer = biosal_assembly_arc_source(arc); consumer_index = biosal_dna_kmer_store_index(kmer, consumer_count, concrete_self->kmer_length, &concrete_self->codec, ephemeral_memory); output_block = core_vector_at(&output_blocks, consumer_index); /* * Make a copy of the arc and copy it. * It will be freed */ biosal_assembly_arc_block_add_arc_copy(output_block, arc, concrete_self->kmer_length, &concrete_self->codec, ephemeral_memory); } /* * Input arcs are not needed anymore. */ biosal_assembly_arc_block_destroy(&input_block, ephemeral_memory); CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory)); /* * Finally, send these output blocks to consumers. */ maximum_pending_requests = 0; maximum_buffer_length = 0; /* * Figure out the maximum buffer length tor * messages. */ for (i = 0; i < consumer_count; i++) { output_block = core_vector_at(&output_blocks, i); new_count = biosal_assembly_arc_block_pack_size(output_block, concrete_self->kmer_length, &concrete_self->codec); if (new_count > maximum_buffer_length) { maximum_buffer_length = new_count; } } #if 0 printf("POOL_BALANCE %d\n", core_memory_pool_profile_balance_count(ephemeral_memory)); #endif for (i = 0; i < consumer_count; i++) { output_block = core_vector_at(&output_blocks, i); output_arcs = biosal_assembly_arc_block_get_arcs(output_block); arc_count = core_vector_size(output_arcs); /* * Don't send an empty message. */ if (arc_count > 0) { /* * Allocation is not required because new_count <= maximum_buffer_length */ new_count = biosal_assembly_arc_block_pack_size(output_block, concrete_self->kmer_length, &concrete_self->codec); new_buffer = thorium_actor_allocate(self, maximum_buffer_length); CORE_DEBUGGER_ASSERT(new_count <= maximum_buffer_length); biosal_assembly_arc_block_pack(output_block, new_buffer, concrete_self->kmer_length, &concrete_self->codec); thorium_message_init(&new_message, ACTION_ASSEMBLY_PUSH_ARC_BLOCK, new_count, new_buffer); consumer = core_vector_at_as_int(&concrete_self->consumers, i); /* * Send the message. */ thorium_actor_send(self, consumer, &new_message); thorium_message_destroy(&new_message); /* update event counters for control. */ bucket = core_vector_at(&concrete_self->pending_requests, i); ++(*bucket); ++concrete_self->active_requests; if (*bucket > maximum_pending_requests) { maximum_pending_requests = *bucket; } if (*bucket > concrete_self->maximum_pending_request_count) { ++concrete_self->consumer_count_above_threshold; } } CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory)); #if 0 printf("i = %d\n", i); #endif /* * Destroy output block. */ biosal_assembly_arc_block_destroy(output_block, ephemeral_memory); CORE_DEBUGGER_LEAK_CHECK_DOUBLE_FREE(ephemeral_memory); CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory)); } core_vector_destroy(&output_blocks); CORE_DEBUGGER_ASSERT(!core_memory_pool_has_double_free(ephemeral_memory)); CORE_DEBUGGER_LEAK_CHECK_DOUBLE_FREE(ephemeral_memory); /* * Check if a response must be sent now. */ ++concrete_self->received_blocks; concrete_self->source = source; /* * Only send a direct reply if there is enough memory. * * As long as maximum_pending_requests is lower than maximum_pending_request_count, * there is still space for at least one additional request. */ if (maximum_pending_requests < concrete_self->maximum_pending_request_count && core_memory_has_enough_bytes()) { thorium_actor_send_empty(self, concrete_self->source, ACTION_ASSEMBLY_PUSH_ARC_BLOCK_REPLY); } else { concrete_self->producer_is_waiting = 1; } CORE_DEBUGGER_LEAK_DETECTION_END(ephemeral_memory, classify_arcs); }
void biosal_input_stream_count_in_parallel(struct thorium_actor *self, struct thorium_message *message) { struct biosal_input_stream *concrete_self; char *file; uint64_t file_size; uint64_t start_offset; uint64_t end_offset; void *buffer; int spawner; int i; int size; uint64_t parallel_block_size; /* * The block size for deciding when to spawn new actors for * I/O. */ parallel_block_size = 536870912; /* parallel_block_size = 0; --parallel_block_size; */ /* * Approach: * * 1. Check number of bytes. * 2. Determine the number of streams. * 3. Spawn streams using a manager. * 4. Set the offsets for each stream * 5. Set ask them to count */ concrete_self = (struct biosal_input_stream *)thorium_actor_concrete_actor(self); buffer = thorium_message_buffer(message); core_vector_unpack(&concrete_self->spawners, buffer); file = concrete_self->file_name; file_size = core_file_get_size(file); printf("COUNT_IN_PARALLEL %s %" PRIu64 "\n", file, file_size); start_offset = 0; i = 0; while (start_offset < file_size) { end_offset = start_offset + parallel_block_size - 1; if (end_offset > file_size - 1 || end_offset < start_offset) { end_offset = file_size - 1; } core_vector_push_back_uint64_t(&concrete_self->start_offsets, start_offset); core_vector_push_back_uint64_t(&concrete_self->end_offsets, end_offset); printf("DEBUG PARALLEL BLOCK %s %i %" PRIu64 " %" PRIu64 "\n", file, i, start_offset, end_offset); start_offset = end_offset + 1; ++i; } size = core_vector_size(&concrete_self->start_offsets); thorium_actor_add_action(self, ACTION_SPAWN_REPLY, biosal_input_stream_spawn_reply); printf("DEBUG stream/%d spawns %d streams for counting\n", thorium_actor_name(self), size); for (i = 0; i < size; i++) { spawner = thorium_actor_get_random_spawner(self, &concrete_self->spawners); thorium_actor_send_int(self, spawner, ACTION_SPAWN, SCRIPT_INPUT_STREAM); } }
void biosal_input_stream_count_reply(struct thorium_actor *self, struct thorium_message *message) { struct biosal_input_stream *concrete_self; void *buffer; uint64_t result; struct biosal_mega_block *block; int i; int size; struct core_vector *vector; int source_index; int source; int j; uint64_t total; concrete_self = (struct biosal_input_stream *)thorium_actor_concrete_actor(self); buffer = thorium_message_buffer(message); source = thorium_message_source(message); source_index = core_vector_index_of(&concrete_self->parallel_streams, &source); vector = core_vector_at(&concrete_self->parallel_mega_blocks, source_index); core_vector_unpack(vector, buffer); block = core_vector_at_last(vector); result = biosal_mega_block_get_entries(block); concrete_self->total_entries += result; ++concrete_self->finished_parallel_stream_count; printf("DEBUG count_reply %d/%d\n", concrete_self->finished_parallel_stream_count, (int)core_vector_size(&concrete_self->parallel_streams)); /* * Send back an array of mega blocks when it is done. */ if (concrete_self->finished_parallel_stream_count == core_vector_size(&concrete_self->parallel_streams)) { /* * Transfer mega blocks * to main vector. */ size = core_vector_size(&concrete_self->parallel_streams); for (i = 0; i < size; i++) { /* * This is easy to do because they are already sorted. * * With one parallel stream, there is nothing else to do. * * Otherwise, mega blocks with correct entries_from_start * need to be created (the entries fields are only for * the stuff between 2 offsets so they are already * correct. */ vector = core_vector_at(&concrete_self->parallel_mega_blocks, i); #if 0 printf("ParallelStream %d\n", i); #endif for (j = 0; j < core_vector_size(vector); j++) { block = core_vector_at(vector, j); biosal_mega_block_print(block); } core_vector_push_back_vector(&concrete_self->mega_blocks, vector); } /* * Update total */ total = 0; for (i = 0; i < core_vector_size(&concrete_self->mega_blocks); i++) { block = core_vector_at(&concrete_self->mega_blocks, i); total += biosal_mega_block_get_entries(block); biosal_mega_block_set_entries_from_start(block, total); } /* * Destroy mega block vectors. */ for (i = 0; i < size; i++) { vector = core_vector_at(&concrete_self->parallel_mega_blocks, i); core_vector_destroy(vector); } core_vector_resize(&concrete_self->parallel_mega_blocks, 0); printf("DEBUG send ACTION_INPUT_COUNT_IN_PARALLEL_REPLY to %d\n", concrete_self->controller); thorium_actor_send_vector(self, concrete_self->controller, ACTION_INPUT_COUNT_IN_PARALLEL_REPLY, &concrete_self->mega_blocks); } }