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_actor_send_range_loop(struct thorium_actor *actor, struct core_vector *actors, int first, int last, struct thorium_message *message) { int i; int the_actor; #ifdef THORIUM_ACTOR_DEBUG1 printf("DEBUG thorium_actor_send_range_default%i-%i\n", first, last); #endif i = first; while (i <= last) { #ifdef THORIUM_ACTOR_DEBUG_20140601_1 printf("DEBUG sending %d to %d\n", thorium_message_action(message), i); #endif the_actor = *(int *)core_vector_at(actors, i); #ifdef DEBUG_BINOMIAL_TREE printf("send_range_loop, sending to %d\n", the_actor); thorium_message_print(message); #endif thorium_actor_send(actor, the_actor, message); i++; } }
/* 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); } }
void biosal_input_controller_receive(struct thorium_actor *actor, struct thorium_message *message) { int tag; int count; char *file; void *buffer; struct biosal_input_controller *controller; struct biosal_input_controller *concrete_actor; int destination; int script; int stream; char *local_file; int i; int name; int source; int destination_index; struct thorium_message new_message; int error; int stream_index; int64_t entries; int64_t *bucket; int *int_bucket; int spawner; int command_name; int stream_name; int consumer; int consumer_index; int *bucket_for_requests; char *new_buffer; int new_count; int file_index; struct core_vector mega_blocks; struct core_vector_iterator vector_iterator; struct biosal_mega_block *mega_block; struct core_vector *vector_bucket; struct core_vector block_counts; uint64_t block_entries; int mega_block_index; uint64_t offset; struct biosal_mega_block *block; int acquaintance_index; if (thorium_actor_take_action(actor, message)) { return; } thorium_message_get_all(message, &tag, &count, &buffer, &source); name = thorium_actor_name(actor); controller = (struct biosal_input_controller *)thorium_actor_concrete_actor(actor); concrete_actor = controller; if (tag == ACTION_START) { core_vector_init(&concrete_actor->spawners, 0); core_vector_unpack(&concrete_actor->spawners, buffer); core_vector_resize(&concrete_actor->stores_per_spawner, core_vector_size(&concrete_actor->spawners)); for (i = 0; i < core_vector_size(&concrete_actor->spawners); i++) { int_bucket = (int *)core_vector_at(&concrete_actor->stores_per_spawner, i); *int_bucket = 0; spawner = core_vector_at_as_int(&concrete_actor->spawners, i); core_queue_enqueue(&concrete_actor->unprepared_spawners, &spawner); } concrete_actor->state = BIOSAL_INPUT_CONTROLLER_STATE_PREPARE_SPAWNERS; #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL printf("DEBUG preparing first spawner\n"); #endif thorium_actor_send_to_self_empty(actor, ACTION_INPUT_CONTROLLER_PREPARE_SPAWNERS); /* thorium_dispatcher_print(thorium_actor_dispatcher(actor)); */ } else if (tag == ACTION_ADD_FILE) { file = (char *)buffer; local_file = core_memory_allocate(strlen(file) + 1, MEMORY_CONTROLLER); strcpy(local_file, file); printf("controller %d ACTION_ADD_FILE %s\n", thorium_actor_name(actor), local_file); core_vector_push_back(&concrete_actor->files, &local_file); bucket = core_vector_at(&concrete_actor->files, core_vector_size(&concrete_actor->files) - 1); local_file = *(char **)bucket; #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2 printf("DEBUG11 ACTION_ADD_FILE %s %p bucket %p index %d\n", local_file, local_file, (void *)bucket, core_vector_size(&concrete_actor->files) - 1); #endif thorium_actor_send_reply_empty(actor, ACTION_ADD_FILE_REPLY); } else if (tag == ACTION_SPAWN_REPLY) { if (concrete_actor->state == BIOSAL_INPUT_CONTROLLER_STATE_SPAWN_STORES) { biosal_input_controller_add_store(actor, message); return; } else if (concrete_actor->state == BIOSAL_INPUT_CONTROLLER_STATE_PREPARE_SPAWNERS) { concrete_actor->ready_spawners++; thorium_message_unpack_int(message, 0, &name); thorium_actor_send_empty(actor, name, ACTION_ASK_TO_STOP); thorium_actor_send_to_self_empty(actor, ACTION_INPUT_CONTROLLER_PREPARE_SPAWNERS); if (concrete_actor->ready_spawners == (int)core_vector_size(&concrete_actor->spawners)) { #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG printf("DEBUG all spawners are prepared\n"); #endif thorium_actor_send_to_supervisor_empty(actor, ACTION_START_REPLY); } return; } else if (concrete_actor->state == BIOSAL_INPUT_CONTROLLER_STATE_SPAWN_PARTITIONER) { #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG printf("DEBUG received spawn reply, state is spawn_partitioner\n"); #endif thorium_message_unpack_int(message, 0, &concrete_actor->partitioner); /* configure the partitioner */ destination = concrete_actor->partitioner; thorium_actor_send_int(actor, destination, ACTION_SEQUENCE_PARTITIONER_SET_BLOCK_SIZE, concrete_actor->block_size); thorium_actor_send_int(actor, destination, ACTION_SEQUENCE_PARTITIONER_SET_ACTOR_COUNT, core_vector_size(&concrete_actor->consumers)); core_vector_init(&block_counts, sizeof(uint64_t)); for (i = 0; i < core_vector_size(&concrete_actor->mega_block_vector); i++) { block = (struct biosal_mega_block *)core_vector_at(&concrete_actor->mega_block_vector, i); block_entries = biosal_mega_block_get_entries(block); core_vector_push_back_uint64_t(&block_counts, block_entries); } new_count = core_vector_pack_size(&block_counts); new_buffer = thorium_actor_allocate(actor, new_count); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG printf("DEBUG packed counts, %d bytes\n", count); #endif core_vector_pack(&block_counts, new_buffer); thorium_message_init(&new_message, ACTION_SEQUENCE_PARTITIONER_SET_ENTRY_VECTOR, new_count, new_buffer); thorium_actor_send(actor, destination, &new_message); core_vector_destroy(&block_counts); return; } else if (concrete_actor->state == BIOSAL_INPUT_CONTROLLER_STATE_SPAWN_READING_STREAMS) { thorium_message_unpack_int(message, 0, &stream); stream_index = stream; mega_block_index = core_vector_size(&concrete_actor->reading_streams); core_vector_push_back_int(&concrete_actor->reading_streams, stream_index); core_vector_push_back_int(&concrete_actor->partition_commands, -1); core_vector_push_back_int(&concrete_actor->stream_consumers, -1); stream_index = core_vector_size(&concrete_actor->reading_streams) - 1; mega_block = (struct biosal_mega_block *)core_vector_at(&concrete_actor->mega_block_vector, mega_block_index); offset = biosal_mega_block_get_offset(mega_block); core_map_add_value(&concrete_actor->assigned_blocks, &stream_index, &mega_block_index); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_READING_STREAMS printf("DEBUG setting offset to %" PRIu64 " for stream/%d\n", offset, stream); #endif thorium_actor_send_uint64_t(actor, stream, ACTION_INPUT_STREAM_SET_START_OFFSET, offset); return; } stream = *(int *)buffer; file_index = core_vector_size(&concrete_actor->counting_streams); local_file = *(char **)core_vector_at(&concrete_actor->files, file_index); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_READING_STREAMS printf("DEBUG actor %d receives stream %d from spawner %d for file %s\n", name, stream, source, local_file); #endif core_vector_push_back(&concrete_actor->counting_streams, &stream); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_READING_STREAMS printf("asking stream/%d to open %s\n", stream, local_file); #endif thorium_message_init(&new_message, ACTION_INPUT_OPEN, strlen(local_file) + 1, local_file); #ifdef DEBUG_ISSUE_594 thorium_message_print(&new_message); printf("SEND Buffer %s\n", local_file); #endif thorium_actor_send(actor, stream, &new_message); thorium_message_destroy(&new_message); if (core_vector_size(&concrete_actor->counting_streams) != core_vector_size(&concrete_actor->files)) { thorium_actor_send_to_self_empty(actor, ACTION_INPUT_SPAWN); } #ifdef DEBUG_ISSUE_594 printf("EXIT Buffer %s\n", local_file); #endif } else if (tag == ACTION_INPUT_OPEN_REPLY) { if (concrete_actor->state == BIOSAL_INPUT_CONTROLLER_STATE_SPAWN_READING_STREAMS) { #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_READING_STREAMS printf("DEBUG receives open.reply for reading stream/%d\n", source); #endif concrete_actor->opened_streams++; if (concrete_actor->opened_streams == core_vector_size(&concrete_actor->mega_block_vector)) { thorium_actor_send_to_self_empty(actor, ACTION_INPUT_CONTROLLER_CREATE_STORES); } return; } concrete_actor->opened_streams++; stream = source; thorium_message_unpack_int(message, 0, &error); if (error == BIOSAL_INPUT_ERROR_NO_ERROR) { #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2 printf("DEBUG actor %d asks %d ACTION_INPUT_COUNT_IN_PARALLEL\n", name, stream); #endif thorium_actor_send_vector(actor, stream, ACTION_INPUT_COUNT_IN_PARALLEL, &concrete_actor->spawners); } else { #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2 printf("DEBUG actor %d received error %d from %d\n", name, error, stream); #endif concrete_actor->counted++; } /* if all streams failed, notice supervisor */ if (concrete_actor->counted == core_vector_size(&concrete_actor->files)) { #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2 #endif printf("DEBUG %d: Error all streams failed.\n", thorium_actor_name(actor)); thorium_actor_send_to_supervisor_empty(actor, ACTION_INPUT_DISTRIBUTE_REPLY); } /* if (concrete_actor->opened_streams == core_vector_size(&concrete_actor->files)) { #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG printf("DEBUG controller %d sends ACTION_INPUT_DISTRIBUTE_REPLY to supervisor %d [%d/%d]\n", name, thorium_actor_supervisor(actor), concrete_actor->opened_streams, core_vector_size(&concrete_actor->files)); #endif } */ } else if (tag == ACTION_INPUT_COUNT_PROGRESS) { stream_index = core_vector_index_of(&concrete_actor->counting_streams, &source); local_file = core_vector_at_as_char_pointer(&concrete_actor->files, stream_index); thorium_message_unpack_int64_t(message, 0, &entries); bucket = (int64_t *)core_vector_at(&concrete_actor->counts, stream_index); printf("controller/%d receives progress from stream/%d file %s %" PRIu64 " entries so far\n", name, source, local_file, entries); *bucket = entries; } else if (tag == ACTION_INPUT_COUNT_IN_PARALLEL_REPLY) { stream_index = core_vector_index_of(&concrete_actor->counting_streams, &source); local_file = core_vector_at_as_char_pointer(&concrete_actor->files, stream_index); core_vector_init(&mega_blocks, 0); core_vector_unpack(&mega_blocks, buffer); printf("DEBUG receive mega blocks from %d\n", source); /* * Update the file index for every mega block. */ core_vector_iterator_init(&vector_iterator, &mega_blocks); bucket = (int64_t*)core_vector_at(&concrete_actor->counts, stream_index); (*bucket) = 0; while (core_vector_iterator_has_next(&vector_iterator)) { core_vector_iterator_next(&vector_iterator, (void **)&mega_block); printf("SETTING setting file to %d for mega block\n", stream_index); biosal_mega_block_set_file(mega_block, stream_index); entries = biosal_mega_block_get_entries_from_start(mega_block); printf("Cataloging %d ENTRIES\n", (int)entries); (*bucket) = entries; biosal_mega_block_print(mega_block); } core_vector_iterator_destroy(&vector_iterator); vector_bucket = (struct core_vector *)core_map_add(&concrete_actor->mega_blocks, &stream_index); core_vector_init_copy(vector_bucket, &mega_blocks); core_vector_destroy(&mega_blocks); concrete_actor->counted++; printf("controller/%d received from stream/%d for file %s %" PRIu64 " entries (final) %d/%d\n", name, source, local_file, entries, concrete_actor->counted, (int)core_vector_size(&concrete_actor->files)); thorium_actor_send_reply_empty(actor, ACTION_INPUT_CLOSE); /* continue work here, tell supervisor about it */ if (concrete_actor->counted == core_vector_size(&concrete_actor->files)) { thorium_actor_send_to_self_empty(actor, ACTION_INPUT_CONTROLLER_SPAWN_READING_STREAMS); } } else if (tag == ACTION_INPUT_DISTRIBUTE) { core_timer_start(&concrete_actor->input_timer); core_timer_start(&concrete_actor->counting_timer); /* for each file, spawn a stream to count */ /* no files, return immediately */ if (core_vector_size(&concrete_actor->files) == 0) { printf("Error: no file to distribute...\n"); thorium_actor_send_reply_empty(actor, ACTION_INPUT_DISTRIBUTE_REPLY); return; } #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2 printf("DEBUG actor %d receives ACTION_INPUT_DISTRIBUTE\n", name); #endif #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2 printf("DEBUG send ACTION_INPUT_SPAWN to self\n"); #endif thorium_actor_send_to_self_empty(actor, ACTION_INPUT_SPAWN); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2 printf("DEBUG resizing counts to %d\n", core_vector_size(&concrete_actor->files)); #endif core_vector_resize(&concrete_actor->counts, core_vector_size(&concrete_actor->files)); for (i = 0; i < core_vector_size(&concrete_actor->counts); i++) { bucket = (int64_t*)core_vector_at(&concrete_actor->counts, i); *bucket = 0; } } else if (tag == ACTION_INPUT_SPAWN && source == name) { #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2 printf("DEBUG ACTION_INPUT_SPAWN\n"); #endif script = SCRIPT_INPUT_STREAM; concrete_actor->state = BIOSAL_INPUT_CONTROLLER_STATE_SPAWN_STREAMS; /* the next file name to send is the current number of streams */ i = core_vector_size(&concrete_actor->counting_streams); destination_index = i % core_vector_size(&concrete_actor->spawners); destination = *(int *)core_vector_at(&concrete_actor->spawners, destination_index); thorium_message_init(message, ACTION_SPAWN, sizeof(script), &script); thorium_actor_send(actor, destination, message); bucket = core_vector_at(&concrete_actor->files, i); local_file = *(char **)core_vector_at(&concrete_actor->files, i); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2 printf("DEBUG890 local_file %p bucket %p index %d\n", local_file, (void *)bucket, i); #endif #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG printf("DEBUG actor %d spawns a stream for file %d/%d via spawner %d\n", name, i, core_vector_size(&concrete_actor->files), destination); #endif /* also, spawn 4 stores on each node */ } else if (tag == ACTION_ASK_TO_STOP && ( source == thorium_actor_supervisor(actor) || source == thorium_actor_name(actor))) { #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_LEVEL_2 #endif /* stop streams */ for (i = 0; i < core_vector_size(&concrete_actor->counting_streams); i++) { stream = *(int *)core_vector_at(&concrete_actor->counting_streams, i); thorium_actor_send_empty(actor, stream, ACTION_ASK_TO_STOP); } for (i = 0; i < core_vector_size(&concrete_actor->reading_streams); i++) { stream = *(int *)core_vector_at(&concrete_actor->reading_streams, i); thorium_actor_send_empty(actor, stream, ACTION_ASK_TO_STOP); } #if 0 /* stop data stores */ for (i = 0; i < core_vector_size(&concrete_actor->consumers); i++) { store = core_vector_at_as_int(&concrete_actor->consumers, i); thorium_actor_send_empty(actor, store, ACTION_ASK_TO_STOP); } #endif /* stop partitioner */ if (concrete_actor->partitioner != THORIUM_ACTOR_NOBODY) { thorium_actor_send_empty(actor, concrete_actor->partitioner, ACTION_ASK_TO_STOP); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG printf("DEBUG controller %d sends ACTION_ASK_TO_STOP_REPLY to %d\n", thorium_actor_name(actor), thorium_message_source(message)); #endif } thorium_actor_send_reply_empty(actor, ACTION_ASK_TO_STOP_REPLY); /* stop self */ thorium_actor_send_to_self_empty(actor, ACTION_STOP); thorium_actor_ask_to_stop(actor, message); printf("DEBUG controller %d dies\n", name); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG #endif } else if (tag == ACTION_INPUT_CONTROLLER_CREATE_PARTITION && source == name) { spawner = *(int *)core_vector_at(&concrete_actor->spawners, core_vector_size(&concrete_actor->spawners) / 2); thorium_actor_send_int(actor, spawner, ACTION_SPAWN, SCRIPT_SEQUENCE_PARTITIONER); concrete_actor->state = BIOSAL_INPUT_CONTROLLER_STATE_SPAWN_PARTITIONER; #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG printf("DEBUG input controller %d spawns a partitioner via spawner %d\n", name, spawner); #endif } else if (tag == ACTION_SEQUENCE_PARTITIONER_COMMAND_IS_READY) { #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG printf("DEBUG controller receives ACTION_SEQUENCE_PARTITIONER_COMMAND_IS_READY, asks for command\n"); #endif thorium_actor_send_reply_empty(actor, ACTION_SEQUENCE_PARTITIONER_GET_COMMAND); } else if (tag == ACTION_SEQUENCE_PARTITIONER_GET_COMMAND_REPLY) { biosal_input_controller_receive_command(actor, message); } else if (tag == ACTION_SEQUENCE_PARTITIONER_FINISHED) { thorium_actor_send_empty(actor, concrete_actor->partitioner, ACTION_ASK_TO_STOP); biosal_input_controller_verify_requests(actor, message); } else if (tag == ACTION_SEQUENCE_PARTITIONER_PROVIDE_STORE_ENTRY_COUNTS) { biosal_input_controller_receive_store_entry_counts(actor, message); } else if (tag == ACTION_RESERVE_REPLY) { concrete_actor->ready_consumers++; printf("DEBUG marker ACTION_RESERVE_REPLY %d/%d\n", concrete_actor->ready_consumers, (int)core_vector_size(&concrete_actor->consumers)); if (concrete_actor->ready_consumers == core_vector_size(&concrete_actor->consumers)) { concrete_actor->ready_consumers = 0; printf("DEBUG all consumers are ready\n"); thorium_actor_send_empty(actor, concrete_actor->partitioner, ACTION_SEQUENCE_PARTITIONER_PROVIDE_STORE_ENTRY_COUNTS_REPLY); } } else if (tag == ACTION_INPUT_PUSH_SEQUENCES_READY) { #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG printf("DEBUG biosal_input_controller_receive received ACTION_INPUT_PUSH_SEQUENCES_READY\n"); #endif stream_name = source; acquaintance_index = stream_name; stream_index = core_vector_index_of(&concrete_actor->reading_streams, &acquaintance_index); command_name = *(int *)core_vector_at(&concrete_actor->partition_commands, stream_index); thorium_actor_send_int(actor, concrete_actor->partitioner, ACTION_SEQUENCE_PARTITIONER_GET_COMMAND_REPLY_REPLY, command_name); } else if (tag == ACTION_INPUT_PUSH_SEQUENCES_REPLY) { stream_name = source; thorium_message_unpack_int(message, 0, &consumer); consumer_index = core_vector_index_of(&concrete_actor->consumers, &consumer); bucket_for_requests = (int *)core_vector_at(&concrete_actor->consumer_active_requests, consumer_index); (*bucket_for_requests)--; biosal_input_controller_verify_requests(actor, message); #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG_CONSUMERS printf("DEBUG consumer # %d has %d active requests\n", consumer_index, *bucket_for_requests); #endif } else if (tag == ACTION_SET_CONSUMERS) { core_vector_init(&concrete_actor->consumers, 0); core_vector_unpack(&concrete_actor->consumers, buffer); printf("controller %d receives %d consumers\n", thorium_actor_name(actor), (int)core_vector_size(&concrete_actor->consumers)); for (i = 0; i < core_vector_size(&concrete_actor->consumers); i++) { core_vector_push_back_int(&concrete_actor->consumer_active_requests, 0); } #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG core_vector_print_int(&concrete_actor->consumers); printf("\n"); #endif thorium_actor_send_reply_empty(actor, ACTION_SET_CONSUMERS_REPLY); } else if (tag == ACTION_SET_BLOCK_SIZE) { thorium_message_unpack_int(message, 0, &concrete_actor->block_size); thorium_actor_send_reply_empty(actor, ACTION_SET_BLOCK_SIZE_REPLY); } else if (tag == ACTION_SEQUENCE_STORE_READY) { concrete_actor->filled_consumers++; #ifdef BIOSAL_INPUT_CONTROLLER_DEBUG printf("DEBUG ACTION_SEQUENCE_STORE_READY %d/%d\n", concrete_actor->filled_consumers, (int)core_vector_size(&concrete_actor->consumers)); #endif if (concrete_actor->filled_consumers == core_vector_size(&concrete_actor->consumers)) { concrete_actor->filled_consumers = 0; printf("DEBUG: all consumers are filled, sending ACTION_INPUT_DISTRIBUTE_REPLY\n"); core_timer_stop(&concrete_actor->input_timer); core_timer_stop(&concrete_actor->distribution_timer); core_timer_print_with_description(&concrete_actor->distribution_timer, "Load input / Distribute input data"); core_timer_print_with_description(&concrete_actor->input_timer, "Load input"); thorium_actor_send_to_supervisor_empty(actor, ACTION_INPUT_DISTRIBUTE_REPLY); } } }
void biosal_input_stream_receive(struct thorium_actor *actor, struct thorium_message *message) { int tag; int source; uint64_t count; struct biosal_input_stream *concrete_self; int i; int has_sequence; int sequences; int sequence_index; int buffer_size; char *buffer; char *read_buffer; struct biosal_mega_block mega_block; char *file_name_in_buffer; if (thorium_actor_take_action(actor, message)) { return; } concrete_self = thorium_actor_concrete_actor(actor); tag = thorium_message_action(message); source = thorium_message_source(message); buffer = (char *)thorium_message_buffer(message); /* Do nothing if there is an error. * has_error returns the error to the source. */ /* if (biosal_input_stream_has_error(actor, message)) { return; } */ if (tag == ACTION_INPUT_OPEN) { #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG ACTION_INPUT_OPEN\n"); #endif if (concrete_self->open) { concrete_self->error = BIOSAL_INPUT_ERROR_ALREADY_OPEN; thorium_actor_send_reply_int(actor, ACTION_INPUT_OPEN_REPLY, concrete_self->error); thorium_actor_send_to_self_empty(actor, ACTION_ASK_TO_STOP); return; } concrete_self->open = 1; /* TODO: find out the maximum read length in some way */ concrete_self->maximum_sequence_length = BIOSAL_INPUT_MAXIMUM_SEQUENCE_LENGTH; concrete_self->buffer_for_sequence = (char *)core_memory_allocate(concrete_self->maximum_sequence_length, MEMORY_INPUT_STREAM); /*biosal_input_stream_init(actor);*/ #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG biosal_input_stream_receive open %s\n", buffer); #endif /*core_memory_copy(&concrete_self->file_index, buffer, sizeof(concrete_self->file_index));*/ file_name_in_buffer = buffer; printf("stream/%d (node/%d) opens file %s offset %" PRIu64 "\n", thorium_actor_name(actor), thorium_actor_node_name(actor), file_name_in_buffer, concrete_self->starting_offset); #ifdef DEBUG_ISSUE_594 thorium_message_print(message); printf("Buffer %s\n", buffer); #endif concrete_self->file_name = core_memory_allocate(strlen(file_name_in_buffer) + 1, MEMORY_INPUT_STREAM); strcpy(concrete_self->file_name, file_name_in_buffer); biosal_input_proxy_init(&concrete_self->proxy, concrete_self->file_name, concrete_self->starting_offset, concrete_self->ending_offset); concrete_self->proxy_ready = 1; /* Die if there is an error... */ if (biosal_input_stream_has_error(actor, message)) { #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG has error\n"); #endif thorium_actor_send_reply_int(actor, ACTION_INPUT_OPEN_REPLY, concrete_self->error); thorium_actor_send_to_self_empty(actor, ACTION_ASK_TO_STOP); return; } concrete_self->controller = source; /* no error here... */ thorium_actor_send_reply_int(actor, ACTION_INPUT_OPEN_REPLY, concrete_self->error); } else if (tag == ACTION_INPUT_COUNT) { /* count a little bit and yield the worker */ if (concrete_self->count_customer == THORIUM_ACTOR_NOBODY) { concrete_self->count_customer = source; } if (biosal_input_stream_check_open_error(actor, message)) { thorium_actor_send_reply_int64_t(actor, ACTION_INPUT_COUNT_REPLY, concrete_self->error); thorium_actor_send_to_self_empty(actor, ACTION_ASK_TO_STOP); return; } #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG ACTION_INPUT_COUNT received...\n"); #endif i = 0; /* continue counting ... */ has_sequence = 1; while (i < concrete_self->granularity && has_sequence) { has_sequence = biosal_input_proxy_get_sequence(&concrete_self->proxy, concrete_self->buffer_for_sequence); #if 0 printf("Sequence= %s\n", concrete_self->buffer_for_sequence); #endif i++; } sequences = biosal_input_proxy_size(&concrete_self->proxy); #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG ACTION_INPUT_COUNT sequences %d...\n", sequences); #endif if (!has_sequence || sequences % concrete_self->mega_block_size == 0) { biosal_mega_block_init(&mega_block, -1, concrete_self->last_offset, sequences - concrete_self->last_entries, sequences); core_vector_push_back(&concrete_self->mega_blocks, &mega_block); concrete_self->last_entries = sequences; concrete_self->last_offset = biosal_input_proxy_offset(&concrete_self->proxy); thorium_actor_send_int64_t(actor, concrete_self->controller, ACTION_INPUT_COUNT_PROGRESS, sequences); } if (has_sequence) { /*printf("DEBUG yield\n");*/ thorium_actor_send_to_self_empty(actor, ACTION_YIELD); /* notify the controller of our progress... */ } else { thorium_actor_send_to_self_empty(actor, ACTION_INPUT_COUNT_READY); } } else if (tag == ACTION_YIELD_REPLY) { if (biosal_input_stream_check_open_error(actor, message)) { /* * it is not clear that there can be an error when receiving YIELD. error = concrete_self->error; thorium_actor_send_reply_int(actor, ACTION_INPUT_COUNT_REPLY, error); thorium_actor_send_to_self(actor, ACTION_ASK_TO_STOP); */ return; } thorium_actor_send_to_self_empty(actor, ACTION_INPUT_COUNT); } else if (tag == ACTION_INPUT_COUNT_READY) { if (biosal_input_stream_check_open_error(actor, message)) { return; } count = biosal_input_proxy_size(&concrete_self->proxy); thorium_actor_send_vector(actor, concrete_self->count_customer, ACTION_INPUT_COUNT_REPLY, &concrete_self->mega_blocks); printf("input_stream/%d on node/%d counted entries in %s, %" PRIu64 "\n", thorium_actor_name(actor), thorium_actor_node_name(actor), concrete_self->file_name, count); } else if (tag == ACTION_INPUT_CLOSE) { #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG destroy proxy\n"); #endif concrete_self->error = BIOSAL_INPUT_ERROR_NO_ERROR; if (biosal_input_stream_check_open_error(actor, message)) { concrete_self->error = BIOSAL_INPUT_ERROR_FILE_NOT_OPEN; thorium_message_init(message, ACTION_INPUT_CLOSE_REPLY, sizeof(concrete_self->error), &concrete_self->error); thorium_actor_send(actor, source, message); thorium_actor_send_to_self_empty(actor, ACTION_ASK_TO_STOP); return; } thorium_message_init(message, ACTION_INPUT_CLOSE_REPLY, sizeof(concrete_self->error), &concrete_self->error); thorium_actor_send(actor, source, message); thorium_actor_send_to_self_empty(actor, ACTION_ASK_TO_STOP); #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("actor %d sending ACTION_INPUT_CLOSE_REPLY to %d\n", thorium_actor_name(actor), source); #endif } else if (tag == ACTION_INPUT_GET_SEQUENCE) { if (biosal_input_stream_check_open_error(actor, message)) { /* the error management could be better. */ concrete_self->error = BIOSAL_INPUT_ERROR_FILE_NOT_OPEN; thorium_message_init(message, ACTION_INPUT_GET_SEQUENCE_REPLY, sizeof(concrete_self->error), &concrete_self->error); thorium_actor_send(actor, source, message); return; } sequence_index = biosal_input_proxy_size(&concrete_self->proxy); /* TODO it would be clearer to use a struct to pack a int and a char [] * then to use the code below. */ read_buffer = concrete_self->buffer_for_sequence + sizeof(sequence_index); has_sequence = biosal_input_proxy_get_sequence(&concrete_self->proxy, read_buffer); if (!has_sequence) { thorium_message_init(message, ACTION_INPUT_GET_SEQUENCE_END, 0, NULL); thorium_actor_send(actor, source, message); return; } buffer_size = sizeof(sequence_index) + strlen(read_buffer) + 1; core_memory_copy(concrete_self->buffer_for_sequence, &sequence_index, sizeof(sequence_index)); thorium_message_init(message, ACTION_INPUT_GET_SEQUENCE_REPLY, buffer_size, concrete_self->buffer_for_sequence); thorium_actor_send(actor, source, message); } else if (tag == ACTION_INPUT_PUSH_SEQUENCES) { biosal_input_stream_push_sequences(actor, message); } else if (tag == ACTION_ASK_TO_STOP) { thorium_actor_send_to_self_empty(actor, ACTION_STOP); thorium_actor_send_range_empty(actor, &concrete_self->parallel_streams, ACTION_ASK_TO_STOP); thorium_actor_send_reply_empty(actor, ACTION_ASK_TO_STOP_REPLY); } else if (tag == ACTION_INPUT_STREAM_RESET) { /* fail silently */ if (!concrete_self->open) { thorium_actor_send_reply_empty(actor, ACTION_INPUT_STREAM_RESET_REPLY); return; } #ifdef BIOSAL_INPUT_STREAM_DEBUG printf("DEBUG ACTION_INPUT_STREAM_RESET\n"); #endif biosal_input_proxy_destroy(&concrete_self->proxy); biosal_input_proxy_init(&concrete_self->proxy, concrete_self->file_name, concrete_self->starting_offset, concrete_self->ending_offset); thorium_actor_send_reply_empty(actor, ACTION_INPUT_STREAM_RESET_REPLY); } else if (tag == ACTION_PUSH_SEQUENCE_DATA_BLOCK_REPLY) { thorium_actor_send_to_supervisor_int(actor, ACTION_INPUT_PUSH_SEQUENCES_REPLY, source); } }
void thorium_message_multiplexer_flush(struct thorium_message_multiplexer *self, int index, int force) { char *buffer; struct thorium_message message; int tag; int count; int current_size; int maximum_size; struct thorium_multiplexed_buffer *multiplexed_buffer; int destination_node; /* int elapsed; int message_count; */ if (CORE_BITMAP_GET_FLAG(self->flags, FLAG_DISABLED)) { return; } #ifdef THORIUM_MULTIPLEXER_TRACK_BUFFERS_WITH_CONTENT #ifdef CORE_DEBUGGER_ASSERT_ENABLED if (!(core_set_find(&self->buffers_with_content, &index))) { multiplexed_buffer = core_vector_at(&self->buffers, index); thorium_printf("index %d has no content\n", index); thorium_multiplexed_buffer_print(multiplexed_buffer); } #endif CORE_DEBUGGER_ASSERT(core_set_find(&self->buffers_with_content, &index)); #endif multiplexed_buffer = core_vector_at(&self->buffers, index); current_size = thorium_multiplexed_buffer_current_size(multiplexed_buffer); maximum_size = thorium_multiplexed_buffer_maximum_size(multiplexed_buffer); /* * The buffer was still in the timeline, but it was flushed elsewhere. */ if (current_size == 0) { return; /* if (force == FORCE_NO && current_size < maximum_size) { return; } else if (force == FORCE_YES_TIME) { elapsed = core_timer_get_nanoseconds(&self->timer) - multiplexed_buffer->timestamp_; if (elapsed < self->timeout_in_nanoseconds) { return; } } else if (force == FORCE_YES_DOA) { message_count = multiplexed_buffer->message_count_; if (message_count < self->degree_of_aggregation_limit) { return; } */ } #ifdef CORE_DEBUGGER_ASSERT_ENABLED if (current_size <= 0) thorium_printf("current_size %d maximum_size %d\n", current_size, maximum_size); #endif CORE_DEBUGGER_ASSERT(current_size > 0); buffer = thorium_multiplexed_buffer_buffer(multiplexed_buffer); count = current_size + THORIUM_MESSAGE_METADATA_SIZE; tag = ACTION_MULTIPLEXER_MESSAGE; /* * This count does not include metadata for the final big message. * * Avoid this copy by using an array of pointers in the first place. */ destination_node = index; thorium_message_init(&message, tag, count, buffer); thorium_message_set_destination(&message, destination_node); thorium_message_set_source(&message, thorium_node_name(self->node)); /* * Mark the message so that the buffer is eventually sent back here * for recycling. */ thorium_message_set_worker(&message, thorium_worker_name(self->worker)); thorium_message_write_metadata(&message); #ifdef DEBUG_MULTIPLEXER_FLUSH thorium_printf("DEBUG_MULTIPLEXER thorium_message_multiplexer_flush index %d buffer %p force %d current_size %d maximum_size %d" " destination_node %d\n", index, buffer, force, current_size, maximum_size, thorium_message_destination_node(&message)); thorium_printf("message in flush\n"); thorium_multiplexed_buffer_print(multiplexed_buffer); thorium_message_print(&message); #endif CORE_DEBUGGER_ASSERT_NOT_NULL(self->worker); /* * Make a copy of the buffer because the multiplexer does not have communication buffers. */ thorium_worker_enqueue_outbound_message(self->worker, &message); /* thorium_printf("MULTIPLEXER FLUSH\n"); */ ++self->real_message_count; thorium_message_destroy(&message); thorium_multiplexed_buffer_reset(multiplexed_buffer); #ifdef THORIUM_MULTIPLEXER_TRACK_BUFFERS_WITH_CONTENT core_set_delete(&self->buffers_with_content, &index); #endif }
/* * 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; }
/* * 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 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; }