void Worker::executeWorkOrderHelper(const TaggedMessage &tagged_message, CompletionMessageProtoT *proto) { std::chrono::time_point<std::chrono::steady_clock> start, end; WorkerMessage worker_message( *static_cast<const WorkerMessage *>(tagged_message.message())); DCHECK(worker_message.getWorkOrder() != nullptr); const size_t query_id_for_workorder = worker_message.getWorkOrder()->getQueryID(); // Start measuring the execution time. start = std::chrono::steady_clock::now(); worker_message.getWorkOrder()->execute(); end = std::chrono::steady_clock::now(); delete worker_message.getWorkOrder(); const uint64_t execution_time_microseconds = std::chrono::duration_cast<std::chrono::microseconds>(end - start) .count(); // Construct the proto message. proto->set_operator_index(worker_message.getRelationalOpIndex()); proto->set_query_id(query_id_for_workorder); proto->set_worker_thread_index(worker_thread_index_); proto->set_execution_time_in_microseconds(execution_time_microseconds); }
QueryManager::QueryStatusCode QueryManager::processMessage( const TaggedMessage &tagged_message) { dag_node_index op_index; switch (tagged_message.message_type()) { case kWorkOrderCompleteMessage: { serialization::WorkOrderCompletionMessage proto; CHECK(proto.ParseFromArray(tagged_message.message(), tagged_message.message_bytes())); op_index = proto.operator_index(); processWorkOrderCompleteMessage(proto.operator_index()); break; } case kRebuildWorkOrderCompleteMessage: { serialization::WorkOrderCompletionMessage proto; CHECK(proto.ParseFromArray(tagged_message.message(), tagged_message.message_bytes())); op_index = proto.operator_index(); processRebuildWorkOrderCompleteMessage(proto.operator_index()); break; } case kCatalogRelationNewBlockMessage: { serialization::CatalogRelationNewBlockMessage proto; CHECK(proto.ParseFromArray(tagged_message.message(), tagged_message.message_bytes())); const block_id block = proto.block_id(); CatalogRelation *relation = static_cast<CatalogDatabase*>(catalog_database_)->getRelationByIdMutable(proto.relation_id()); relation->addBlock(block); if (proto.has_partition_id()) { relation->getPartitionSchemeMutable()->addBlockToPartition( proto.partition_id(), block); } return QueryStatusCode::kNone; } case kDataPipelineMessage: { // Possible message senders include InsertDestinations and some // operators which modify existing blocks. serialization::DataPipelineMessage proto; CHECK(proto.ParseFromArray(tagged_message.message(), tagged_message.message_bytes())); op_index = proto.operator_index(); processDataPipelineMessage(proto.operator_index(), proto.block_id(), proto.relation_id()); break; } case kWorkOrdersAvailableMessage: { serialization::WorkOrdersAvailableMessage proto; CHECK(proto.ParseFromArray(tagged_message.message(), tagged_message.message_bytes())); op_index = proto.operator_index(); // Check if new work orders are available. fetchNormalWorkOrders(op_index); // Dispatch the WorkerMessages to the workers. We prefer to start the search // for the schedulable WorkOrders beginning from 'op_index'. The first // candidate worker to receive the next WorkOrder is the one that sent the // response message to Foreman. // TODO(zuyu): Improve the data locality for the next WorkOrder. break; } case kWorkOrderFeedbackMessage: { WorkOrder::FeedbackMessage msg( const_cast<void *>(tagged_message.message()), tagged_message.message_bytes()); op_index = msg.header().rel_op_index; processFeedbackMessage(msg); break; } default: LOG(FATAL) << "Unknown message type found in QueryManager"; } if (query_exec_state_->hasExecutionFinished(op_index)) { return QueryStatusCode::kOperatorExecuted; } // As kQueryExecuted takes precedence over kOperatorExecuted, we check again. if (query_exec_state_->hasQueryExecutionFinished()) { return QueryStatusCode::kQueryExecuted; } return QueryStatusCode::kNone; }