| 9616 | |
| 9617 | |
| 9618 | Future<ResourceUsage> Slave::usage() |
| 9619 | { |
| 9620 | // NOTE: We use 'Owned' here trying to avoid the expensive copy. |
| 9621 | // C++11 lambda only supports capturing variables that have copy |
| 9622 | // constructors. Revisit once we remove the copy constructor for |
| 9623 | // Owned (or C++14 lambda generalized capture is supported). |
| 9624 | Owned<ResourceUsage> usage(new ResourceUsage()); |
| 9625 | vector<Future<ResourceStatistics>> futures; |
| 9626 | |
| 9627 | foreachvalue (const Framework* framework, frameworks) { |
| 9628 | foreachvalue (const Executor* executor, framework->executors) { |
| 9629 | // No need to get statistics and status if we know that the |
| 9630 | // executor has already terminated. |
| 9631 | if (executor->state == Executor::TERMINATED) { |
| 9632 | continue; |
| 9633 | } |
| 9634 | |
| 9635 | ResourceUsage::Executor* entry = usage->add_executors(); |
| 9636 | entry->mutable_executor_info()->CopyFrom(executor->info); |
| 9637 | entry->mutable_allocated()->CopyFrom(executor->allocatedResources()); |
| 9638 | entry->mutable_container_id()->CopyFrom(executor->containerId); |
| 9639 | |
| 9640 | // We include non-terminal tasks in ResourceUsage. |
| 9641 | foreachvalue (const Task* task, executor->launchedTasks) { |
| 9642 | ResourceUsage::Executor::Task* t = entry->add_tasks(); |
| 9643 | t->set_name(task->name()); |
| 9644 | t->mutable_id()->CopyFrom(task->task_id()); |
| 9645 | t->mutable_resources()->CopyFrom(task->resources()); |
| 9646 | |
| 9647 | if (task->has_labels()) { |
| 9648 | t->mutable_labels()->CopyFrom(task->labels()); |
| 9649 | } |
| 9650 | } |
| 9651 | |
| 9652 | futures.push_back(containerizer->usage(executor->containerId)); |
| 9653 | } |
| 9654 | } |
| 9655 | |
| 9656 | usage->mutable_total()->CopyFrom(totalResources); |
| 9657 | |
| 9658 | return await(futures).then( |
| 9659 | [usage](const vector<Future<ResourceStatistics>>& futures) { |
| 9660 | // NOTE: We add ResourceUsage::Executor to 'usage' the same |
| 9661 | // order as we push future to 'futures'. So the variables |
| 9662 | // 'future' and 'executor' below should be in sync. |
| 9663 | CHECK_EQ(futures.size(), (size_t) usage->executors_size()); |
| 9664 | |
| 9665 | int i = 0; |
| 9666 | foreach (const Future<ResourceStatistics>& future, futures) { |
| 9667 | ResourceUsage::Executor* executor = usage->mutable_executors(i++); |
| 9668 | |
| 9669 | if (future.isReady()) { |
| 9670 | executor->mutable_statistics()->CopyFrom(future.get()); |
| 9671 | } else { |
| 9672 | LOG(WARNING) << "Failed to get resource statistics for executor '" |
| 9673 | << executor->executor_info().executor_id() << "'" |
| 9674 | << " of framework " |
| 9675 | << executor->executor_info().framework_id() << ": " |