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 }
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; }