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; }
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); }
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 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); }
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; }
void thorium_message_remove_metadata(struct thorium_message *self) { int count; int metadata_size; int all; count = thorium_message_count(self); metadata_size = thorium_message_metadata_size(self); all = count - metadata_size; thorium_message_set_count(self, all); }
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_message_multiplexer_message_should_be_multiplexed(struct thorium_message_multiplexer *self, struct thorium_message *message) { int buffer_size; int threshold; if (thorium_message_multiplexer_is_disabled(self)) return 0; buffer_size = thorium_message_count(message); threshold = self->buffer_size_in_bytes / 2; return buffer_size <= threshold; }
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); }
/* \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; }
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; }
int thorium_message_unpack_2_int(struct thorium_message *message, int *value1, int *value2) { int offset; int count; int required; count = thorium_message_count(message); required = sizeof(*value1) + sizeof(*value2); if (required > count) { return -1; } offset = 0; offset += thorium_message_unpack_int(message, offset, value1); offset += thorium_message_unpack_int(message, offset, value2); return offset; }
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 thorium_transport_print_event(struct thorium_transport *self, int type, struct thorium_message *message) { char *description; int count; int source_rank; int destination_rank; uint64_t time; description = EVENT_STRING_SEND; if (type == EVENT_TYPE_RECEIVE) description = EVENT_STRING_RECEIVE; count = thorium_message_count(message); source_rank = thorium_message_source_node(message); destination_rank = thorium_message_destination_node(message); time = core_timer_get_nanoseconds(&self->timer); time -= self->start_time; printf("thorium_transport print_event time_nanoseconds= %" PRIu64 " type= %s source= %d destination= %d count= %d\n", time, description, source_rank, destination_rank, count); }
void biosal_input_stream_push_sequences(struct thorium_actor *actor, struct thorium_message *message) { struct biosal_input_command command; void *buffer; int store_name; uint64_t store_first; uint64_t store_last; int sequences_to_read; void *new_buffer; int new_count; struct thorium_message new_message; void *buffer_for_sequence; struct biosal_dna_sequence dna_sequence; /*struct core_vector *command_entries;*/ int has_sequence; int i; struct biosal_input_stream *concrete_self; #ifdef BIOSAL_INPUT_STREAM_DEBUG int count; int actual_count; #endif /* answer immediately */ thorium_actor_send_reply_empty(actor, ACTION_INPUT_PUSH_SEQUENCES_READY); has_sequence = 1; #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG stream/%d biosal_input_stream_push_sequences entering...\n", thorium_actor_name(actor)); #endif buffer = thorium_message_buffer(message); concrete_self = (struct biosal_input_stream *)thorium_actor_concrete_actor(actor); biosal_input_command_init_empty(&command); biosal_input_command_unpack(&command, buffer, thorium_actor_get_ephemeral_memory(actor), &concrete_self->codec); #ifdef BIOSAL_INPUT_STREAM_DEBUG count = thorium_message_count(message); printf("DEBUG biosal_input_stream_push_sequences after unpack, count %d:\n", count); biosal_input_command_print(&command); #endif store_name = biosal_input_command_store_name(&command); store_first = biosal_input_command_store_first(&command); store_last = biosal_input_command_store_last(&command); sequences_to_read = store_last - store_first + 1; #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG biosal_input_stream_push_sequences received ACTION_INPUT_PUSH_SEQUENCES\n"); printf("DEBUG Command before sending it\n"); biosal_input_command_print(&command); #endif /* * add sequences to the input command */ buffer_for_sequence = concrete_self->buffer_for_sequence; /*command_entries = biosal_input_command_entries(&command);*/ i = 0; /* TODO: actually load something */ while (sequences_to_read-- && has_sequence) { has_sequence = biosal_input_proxy_get_sequence(&concrete_self->proxy, buffer_for_sequence); biosal_dna_sequence_init(&dna_sequence, buffer_for_sequence, &concrete_self->codec, thorium_actor_get_ephemeral_memory(actor)); biosal_input_command_add_entry(&command, &dna_sequence, &concrete_self->codec, thorium_actor_get_ephemeral_memory(actor)); biosal_dna_sequence_destroy(&dna_sequence, thorium_actor_get_ephemeral_memory(actor)); i++; } #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG prepared %d sequences for command\n", i); biosal_input_command_print(&command); #endif new_count = biosal_input_command_pack_size(&command, &concrete_self->codec); new_buffer = thorium_actor_allocate(actor, new_count); biosal_input_command_pack(&command, new_buffer, &concrete_self->codec); #ifdef BIOSAL_INPUT_STREAM_DEBUG actual_count = biosal_input_command_pack(&command, new_buffer); printf("DEBUG123 new_count %d actual_count %d\n", new_count, actual_count); #endif thorium_message_init(&new_message, ACTION_PUSH_SEQUENCE_DATA_BLOCK, new_count, new_buffer); #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG biosal_input_stream_push_sequences sending ACTION_PUSH_SEQUENCE_DATA_BLOCK to %d\n", store_name); #endif thorium_actor_send(actor, store_name, &new_message); /* * send sequences to store. * The required information is the input command */ /* thorium_actor_send_reply_empty(actor, ACTION_INPUT_PUSH_SEQUENCES_REPLY); */ /* free memory */ #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG freeing %d entries\n", (int)core_vector_size(command_entries)); #endif biosal_input_command_destroy(&command, thorium_actor_get_ephemeral_memory(actor)); #if 0 for (i = 0; i < core_vector_size(command_entries); i++) { a_sequence = (struct biosal_dna_sequence *)core_vector_at(command_entries, i); biosal_dna_sequence_destroy(a_sequence, thorium_actor_get_ephemeral_memory(actor)); } core_vector_destroy(command_entries); #endif #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG biosal_input_stream_push_sequences EXIT\n"); #endif }
/* * 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; }
void biosal_assembly_graph_store_get_vertex(struct thorium_actor *self, struct thorium_message *message) { struct biosal_assembly_vertex vertex; struct biosal_dna_kmer kmer; void *buffer; struct biosal_assembly_graph_store *concrete_self; struct core_memory_pool *ephemeral_memory; struct thorium_message new_message; int new_count; void *new_buffer; struct biosal_assembly_vertex *canonical_vertex; int is_canonical; int path; int position; int count; path = -1; ephemeral_memory = thorium_actor_get_ephemeral_memory(self); concrete_self = thorium_actor_concrete_actor(self); buffer = thorium_message_buffer(message); count = thorium_message_count(message); biosal_dna_kmer_init_empty(&kmer); position = 0; position += biosal_dna_kmer_unpack(&kmer, buffer, concrete_self->kmer_length, ephemeral_memory, &concrete_self->transport_codec); /* * Check if a path index was provided too. */ if (position < count) { position += thorium_message_unpack_int(message, position, &path); } CORE_DEBUGGER_ASSERT_IS_EQUAL_INT(position, count); CORE_DEBUGGER_ASSERT(position == count); canonical_vertex = biosal_assembly_graph_store_find_vertex(self, &kmer); biosal_assembly_vertex_init_copy(&vertex, canonical_vertex); is_canonical = biosal_dna_kmer_is_canonical(&kmer, concrete_self->kmer_length, &concrete_self->transport_codec); if (!is_canonical) { biosal_assembly_vertex_invert_arcs(&vertex); } biosal_dna_kmer_destroy(&kmer, ephemeral_memory); new_count = biosal_assembly_vertex_pack_size(&vertex); new_buffer = thorium_actor_allocate(self, new_count); biosal_assembly_vertex_pack(&vertex, new_buffer); thorium_message_init(&new_message, ACTION_ASSEMBLY_GET_VERTEX_REPLY, new_count, new_buffer); thorium_actor_send_reply(self, &new_message); thorium_message_destroy(&new_message); }
void biosal_assembly_graph_store_push_arc_block(struct thorium_actor *self, struct thorium_message *message) { struct biosal_assembly_graph_store *concrete_self; int size; int i; void *buffer; int count; struct biosal_assembly_arc_block input_block; struct biosal_assembly_arc *arc; struct core_memory_pool *ephemeral_memory; struct core_vector *input_arcs; char *sequence; void *key; #if 0 /* * Don't do anything to rule out that this is the problem. */ thorium_actor_send_reply_empty(self, ACTION_ASSEMBLY_PUSH_ARC_BLOCK_REPLY); return; #endif concrete_self = thorium_actor_concrete_actor(self); ephemeral_memory = thorium_actor_get_ephemeral_memory(self); sequence = core_memory_pool_allocate(ephemeral_memory, concrete_self->kmer_length + 1); ++concrete_self->received_arc_block_count; count = thorium_message_count(message); buffer = thorium_message_buffer(message); biosal_assembly_arc_block_init(&input_block, ephemeral_memory, concrete_self->kmer_length, &concrete_self->transport_codec); biosal_assembly_arc_block_unpack(&input_block, buffer, concrete_self->kmer_length, &concrete_self->transport_codec, ephemeral_memory); input_arcs = biosal_assembly_arc_block_get_arcs(&input_block); size = core_vector_size(input_arcs); if (!concrete_self->printed_arc_size) { printf("DEBUG ARC DELIVERY %d bytes, %d arcs\n", count, size); concrete_self->printed_arc_size = 1; } key = core_memory_pool_allocate(ephemeral_memory, concrete_self->key_length_in_bytes); for (i = 0; i < size; i++) { arc = core_vector_at(input_arcs, i); #ifdef BIOSAL_ASSEMBLY_ADD_ARCS biosal_assembly_graph_store_add_arc(self, arc, sequence, key); #endif ++concrete_self->received_arc_count; } core_memory_pool_free(ephemeral_memory, key); biosal_assembly_arc_block_destroy(&input_block, ephemeral_memory); /* * * Add the arcs to the graph */ thorium_actor_send_reply_empty(self, ACTION_ASSEMBLY_PUSH_ARC_BLOCK_REPLY); core_memory_pool_free(ephemeral_memory, sequence); }
void biosal_assembly_graph_store_push_kmer_block(struct thorium_actor *self, struct thorium_message *message) { struct core_memory_pool *ephemeral_memory; struct biosal_dna_kmer_frequency_block block; struct biosal_assembly_vertex *bucket; void *packed_kmer; struct core_map_iterator iterator; struct biosal_assembly_graph_store *concrete_self; /*int tag;*/ void *key; struct core_map *kmers; struct biosal_dna_kmer kmer; void *buffer; int count; struct biosal_dna_kmer encoded_kmer; char *raw_kmer; int period; struct biosal_dna_kmer *kmer_pointer; int *frequency; ephemeral_memory = thorium_actor_get_ephemeral_memory(self); concrete_self = thorium_actor_concrete_actor(self); /*tag = thorium_message_action(message);*/ buffer = thorium_message_buffer(message); count = thorium_message_count(message); /* * Handler for PUSH_DATA */ biosal_dna_kmer_frequency_block_init(&block, concrete_self->kmer_length, ephemeral_memory, &concrete_self->transport_codec, 0); biosal_dna_kmer_frequency_block_unpack(&block, buffer, ephemeral_memory, &concrete_self->transport_codec); key = core_memory_pool_allocate(ephemeral_memory, concrete_self->key_length_in_bytes); kmers = biosal_dna_kmer_frequency_block_kmers(&block); core_map_iterator_init(&iterator, kmers); period = 2500000; raw_kmer = core_memory_pool_allocate(thorium_actor_get_ephemeral_memory(self), concrete_self->kmer_length + 1); if (!concrete_self->printed_vertex_size) { printf("DEBUG VERTEX DELIVERY %d bytes\n", count); concrete_self->printed_vertex_size = 1; } while (core_map_iterator_has_next(&iterator)) { /* * add kmers to store */ core_map_iterator_next(&iterator, (void **)&packed_kmer, (void **)&frequency); /* Store the kmer in 2 bit encoding */ biosal_dna_kmer_init_empty(&kmer); biosal_dna_kmer_unpack(&kmer, packed_kmer, concrete_self->kmer_length, ephemeral_memory, &concrete_self->transport_codec); kmer_pointer = &kmer; if (concrete_self->codec_are_different) { /* * Get a copy of the sequence */ biosal_dna_kmer_get_sequence(kmer_pointer, raw_kmer, concrete_self->kmer_length, &concrete_self->transport_codec); biosal_dna_kmer_init(&encoded_kmer, raw_kmer, &concrete_self->storage_codec, thorium_actor_get_ephemeral_memory(self)); kmer_pointer = &encoded_kmer; } biosal_dna_kmer_pack_store_key(kmer_pointer, key, concrete_self->kmer_length, &concrete_self->storage_codec, thorium_actor_get_ephemeral_memory(self)); #ifdef BIOSAL_DEBUG_ISSUE_540 if (strcmp(raw_kmer, "AGCTGGTAGTCATCACCAGACTGGAACAG") == 0 || strcmp(raw_kmer, "CGCGATCTGTTGCTGGGCCTAACGTGGTA") == 0 || strcmp(raw_kmer, "TACCACGTTAGGCCCAGCAACAGATCGCG") == 0) { printf("Examine store key for %s\n", raw_kmer); core_debugger_examine(key, concrete_self->key_length_in_bytes); } #endif bucket = core_map_get(&concrete_self->table, key); if (bucket == NULL) { /* This is the first time that this kmer is seen. */ bucket = core_map_add(&concrete_self->table, key); biosal_assembly_vertex_init(bucket); #if 0 printf("DEBUG303 ADD_KEY"); biosal_dna_kmer_print(&encoded_kmer, concrete_self->kmer_length, &concrete_self->storage_codec, ephemeral_memory); #endif } if (concrete_self->codec_are_different) { biosal_dna_kmer_destroy(&encoded_kmer, thorium_actor_get_ephemeral_memory(self)); } biosal_dna_kmer_destroy(&kmer, ephemeral_memory); biosal_assembly_vertex_increase_coverage_depth(bucket, *frequency); if (concrete_self->received >= concrete_self->last_received + period) { printf("%s/%d received %" PRIu64 " kmers so far," " store has %" PRIu64 " canonical kmers, %" PRIu64 " kmers\n", thorium_actor_script_name(self), thorium_actor_name(self), concrete_self->received, core_map_size(&concrete_self->table), 2 * core_map_size(&concrete_self->table)); concrete_self->last_received = concrete_self->received; } concrete_self->received += *frequency; } core_memory_pool_free(ephemeral_memory, key); core_memory_pool_free(ephemeral_memory, raw_kmer); core_map_iterator_destroy(&iterator); biosal_dna_kmer_frequency_block_destroy(&block, thorium_actor_get_ephemeral_memory(self)); thorium_actor_send_reply_empty(self, ACTION_PUSH_KMER_BLOCK_REPLY); }
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); } }
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); } }
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); }
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); } } }
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(©) == 30202) { printf("DEBUG-594 thorium_worker_send\n"); thorium_message_print(©); } #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; }
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 }
/* * 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; }