// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#include "master/master.hpp"

#include <string>
#include <vector>

#include <google/protobuf/descriptor.h>
#include <google/protobuf/wire_format_lite.h>

#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>

#include <mesos/mesos.hpp>

#include <mesos/authorizer/authorizer.hpp>

#include <process/http.hpp>
#include <process/owned.hpp>

#include <stout/foreach.hpp>
#include <stout/hashmap.hpp>
#include <stout/hashset.hpp>
#include <stout/jsonify.hpp>
#include <stout/option.hpp>
#include <stout/representation.hpp>

#include "common/build.hpp"
#include "common/http.hpp"

using google::protobuf::internal::WireFormatLite;

using process::Owned;

using process::http::NotAcceptable;
using process::http::OK;
using process::http::Response;

using mesos::authorization::VIEW_EXECUTOR;
using mesos::authorization::VIEW_FLAGS;
using mesos::authorization::VIEW_FRAMEWORK;
using mesos::authorization::VIEW_ROLE;
using mesos::authorization::VIEW_TASK;

using mesos::internal::protobuf::WireFormatLite2;

using std::function;
using std::pair;
using std::string;
using std::vector;

namespace mesos {
namespace internal {
namespace master {

// Pull in model overrides from common.
using mesos::internal::model;

// The summary representation of `T` to support the `/state-summary` endpoint.
// e.g., `Summary<Slave>`.
template <typename T>
struct Summary : Representation<T>
{
  using Representation<T>::Representation;
};


// The full representation of `T` to support the `/state` endpoint.
// e.g., `Full<Slave>`.
template <typename T>
struct Full : Representation<T>
{
  using Representation<T>::Representation;
};


// Filtered representation of Full<Framework>.
// Executors and Tasks are filtered based on whether the
// user is authorized to view them.
//
// TODO(bevers): Consider moving writers and other json-related
// code into a separate file.
struct FullFrameworkWriter {
  FullFrameworkWriter(
      const process::Owned<ObjectApprovers>& approvers,
      const Framework* framework);

  void operator()(JSON::ObjectWriter* writer) const;

  const process::Owned<ObjectApprovers>& approvers_;
  const Framework* framework_;
};


struct SlaveWriter
{
  SlaveWriter(
      const Slave& slave,
      const Option<DrainInfo>& drainInfo,
      bool deactivated,
      const process::Owned<ObjectApprovers>& approvers);

  void operator()(JSON::ObjectWriter* writer) const;

  const Slave& slave_;
  const Option<DrainInfo> drainInfo_;
  const bool deactivated_;
  const process::Owned<ObjectApprovers>& approvers_;
};


struct SlavesWriter
{
  SlavesWriter(
      const Master::Slaves& slaves,
      const process::Owned<ObjectApprovers>& approvers,
      const IDAcceptor<SlaveID>& selectSlaveId);

  void operator()(JSON::ObjectWriter* writer) const;

  void writeSlave(const Slave* slave, JSON::ObjectWriter* writer) const;

  const Master::Slaves& slaves_;
  const process::Owned<ObjectApprovers>& approvers_;
  const IDAcceptor<SlaveID>& selectSlaveId_;
};


void json(JSON::ObjectWriter* writer, const Summary<Framework>& summary);


FullFrameworkWriter::FullFrameworkWriter(
    const Owned<ObjectApprovers>& approvers,
    const Framework* framework)
  : approvers_(approvers),
    framework_(framework)
{}


void FullFrameworkWriter::operator()(JSON::ObjectWriter* writer) const
{
  json(writer, Summary<Framework>(*framework_));

  // Add additional fields to those generated by the
  // `Summary<Framework>` overload.
  writer->field("user", framework_->info.user());
  writer->field("failover_timeout", framework_->info.failover_timeout());
  writer->field("checkpoint", framework_->info.checkpoint());
  writer->field("registered_time", framework_->registeredTime.secs());
  writer->field("unregistered_time", framework_->unregisteredTime.secs());

  if (framework_->info.has_principal()) {
    writer->field("principal", framework_->info.principal());
  }

  // TODO(bmahler): Consider deprecating this in favor of the split
  // used and offered resources added in `Summary<Framework>`.
  writer->field(
      "resources",
      framework_->totalUsedResources + framework_->totalOfferedResources);

  // TODO(benh): Consider making reregisteredTime an Option.
  if (framework_->registeredTime != framework_->reregisteredTime) {
    writer->field("reregistered_time", framework_->reregisteredTime.secs());
  }

  // For multi-role frameworks the `role` field will be unset.
  // Note that we could set `roles` here for both cases, which
  // would make tooling simpler (only need to look for `roles`).
  // However, we opted to just mirror the protobuf akin to how
  // generic protobuf -> JSON translation works.
  if (framework_->capabilities.multiRole) {
    writer->field("roles", framework_->info.roles());
  } else {
    writer->field("role", framework_->info.role());
  }

  // Model all of the tasks associated with a framework.
  writer->field("tasks", [this](JSON::ArrayWriter* writer) {
    foreachvalue (Task* task, framework_->tasks) {
      // Skip unauthorized tasks.
      if (!approvers_->approved<VIEW_TASK>(*task, framework_->info)) {
        continue;
      }

      writer->element(*task);
    }
  });

  writer->field("unreachable_tasks", [this](JSON::ArrayWriter* writer) {
    foreachvalue (const Owned<Task>& task, framework_->unreachableTasks) {
      // Skip unauthorized tasks.
      if (!approvers_->approved<VIEW_TASK>(*task, framework_->info)) {
        continue;
      }

      writer->element(*task);
    }
  });

  writer->field("completed_tasks", [this](JSON::ArrayWriter* writer) {
    foreach (const Owned<Task>& task, framework_->completedTasks) {
      // Skip unauthorized tasks.
      if (!approvers_->approved<VIEW_TASK>(*task, framework_->info)) {
        continue;
      }

      writer->element(*task);
    }
  });

  // Model all of the offers associated with a framework.
  writer->field("offers", [this](JSON::ArrayWriter* writer) {
    foreach (Offer* offer, framework_->offers) {
      writer->element(*offer);
    }
  });

  // Model all of the executors of a framework.
  writer->field("executors", [this](JSON::ArrayWriter* writer) {
    foreachpair (
        const SlaveID& slaveId,
        const auto& executorsMap,
        framework_->executors) {
      foreachvalue (const ExecutorInfo& executor, executorsMap) {
        writer->element([this,
                         &executor,
                         &slaveId](JSON::ObjectWriter* writer) {
          // Skip unauthorized executors.
          if (!approvers_->approved<VIEW_EXECUTOR>(
                  executor, framework_->info)) {
            return;
          }

          json(writer, executor);
          writer->field("slave_id", slaveId.value());
        });
      }
    }
  });

  // Model all of the labels associated with a framework.
  if (framework_->info.has_labels()) {
    writer->field("labels", framework_->info.labels());
  }

  writer->field(
      "offer_constraints", JSON::Protobuf(framework_->offerConstraints()));
}


SlaveWriter::SlaveWriter(
    const Slave& slave,
    const Option<DrainInfo>& drainInfo,
    bool deactivated,
    const Owned<ObjectApprovers>& approvers)
  : slave_(slave),
    drainInfo_(drainInfo),
    deactivated_(deactivated),
    approvers_(approvers)
{}


void SlaveWriter::operator()(JSON::ObjectWriter* writer) const
{
  json(writer, slave_.info);

  writer->field("pid", string(slave_.pid));
  writer->field("registered_time", slave_.registeredTime.secs());

  if (slave_.reregisteredTime.isSome()) {
    writer->field("reregistered_time", slave_.reregisteredTime->secs());
  }

  const Resources& totalResources = slave_.totalResources;
  writer->field("resources", totalResources);
  writer->field("used_resources", Resources::sum(slave_.usedResources));
  writer->field("offered_resources", slave_.offeredResources);
  writer->field(
      "reserved_resources",
      [&totalResources, this](JSON::ObjectWriter* writer) {
        foreachpair (const string& role, const Resources& reservation,
                     totalResources.reservations()) {
          // TODO(arojas): Consider showing unapproved resources in an
          // aggregated special field, so that all resource values add up
          // MESOS-7779.
          if (approvers_->approved<VIEW_ROLE>(role)) {
            writer->field(role, reservation);
          }
        }
      });
  writer->field("unreserved_resources", totalResources.unreserved());

  writer->field("active", slave_.active);
  writer->field("deactivated", deactivated_);
  writer->field("version", slave_.version);
  writer->field("capabilities", slave_.capabilities.toRepeatedPtrField());

  if (drainInfo_.isSome()) {
    writer->field("drain_info", JSON::Protobuf(drainInfo_.get()));

    if (slave_.estimatedDrainStartTime.isSome()) {
      writer->field(
          "estimated_drain_start_time_seconds",
          slave_.estimatedDrainStartTime->secs());
    }
  }
}


SlavesWriter::SlavesWriter(
    const Master::Slaves& slaves,
    const Owned<ObjectApprovers>& approvers,
    const IDAcceptor<SlaveID>& selectSlaveId)
  : slaves_(slaves), approvers_(approvers), selectSlaveId_(selectSlaveId)
{}


void SlavesWriter::operator()(JSON::ObjectWriter* writer) const
{
  writer->field("slaves", [this](JSON::ArrayWriter* writer) {
    foreachvalue (const Slave* slave, slaves_.registered) {
      if (!selectSlaveId_.accept(slave->id)) {
        continue;
      }

      writer->element([this, &slave](JSON::ObjectWriter* writer) {
        writeSlave(slave, writer);
      });
    }
  });

  writer->field("recovered_slaves", [this](JSON::ArrayWriter* writer) {
    foreachvalue (const SlaveInfo& slaveInfo, slaves_.recovered) {
      if (!selectSlaveId_.accept(slaveInfo.id())) {
        continue;
      }

      writer->element([&slaveInfo](JSON::ObjectWriter* writer) {
        json(writer, slaveInfo);
      });
    }
  });
}


void SlavesWriter::writeSlave(
  const Slave* slave, JSON::ObjectWriter* writer) const
{
  SlaveWriter(
      *slave,
      slaves_.draining.get(slave->id),
      slaves_.deactivated.contains(slave->id),
      approvers_)(writer);

  // Add the complete protobuf->JSON for all used, reserved,
  // and offered resources. The other endpoints summarize
  // resource information, which omits the details of
  // reservations and persistent volumes. Full resource
  // information is necessary so that operators can use the
  // `/unreserve` and `/destroy-volumes` endpoints.

  hashmap<string, Resources> reserved = slave->totalResources.reservations();

  writer->field(
      "reserved_resources_full",
      [&reserved, this](JSON::ObjectWriter* writer) {
        foreachpair (const string& role,
                     const Resources& resources,
                     reserved) {
          if (approvers_->approved<VIEW_ROLE>(role)) {
            writer->field(role, [&resources, this](
                JSON::ArrayWriter* writer) {
              foreach (Resource resource, resources) {
                if (approvers_->approved<VIEW_ROLE>(resource)) {
                  convertResourceFormat(&resource, ENDPOINT);
                  writer->element(JSON::Protobuf(resource));
                }
              }
            });
          }
        }
      });

  Resources unreservedResources = slave->totalResources.unreserved();

  writer->field(
      "unreserved_resources_full",
      [&unreservedResources, this](JSON::ArrayWriter* writer) {
        foreach (Resource resource, unreservedResources) {
          if (approvers_->approved<VIEW_ROLE>(resource)) {
            convertResourceFormat(&resource, ENDPOINT);
            writer->element(JSON::Protobuf(resource));
          }
        }
      });

  Resources usedResources = Resources::sum(slave->usedResources);

  writer->field(
      "used_resources_full",
      [&usedResources, this](JSON::ArrayWriter* writer) {
        foreach (Resource resource, usedResources) {
          if (approvers_->approved<VIEW_ROLE>(resource)) {
            convertResourceFormat(&resource, ENDPOINT);
            writer->element(JSON::Protobuf(resource));
          }
        }
      });

  const Resources& offeredResources = slave->offeredResources;

  writer->field(
      "offered_resources_full",
      [&offeredResources, this](JSON::ArrayWriter* writer) {
        foreach (Resource resource, offeredResources) {
          if (approvers_->approved<VIEW_ROLE>(resource)) {
            convertResourceFormat(&resource, ENDPOINT);
            writer->element(JSON::Protobuf(resource));
          }
        }
      });
}


void json(JSON::ObjectWriter* writer, const Summary<Framework>& summary)
{
  const Framework& framework = summary;

  writer->field("id", framework.id().value());
  writer->field("name", framework.info.name());

  // Omit pid for http frameworks.
  if (framework.pid().isSome()) {
    writer->field("pid", string(framework.pid().get()));
  }

  // TODO(bmahler): Use these in the webui.
  writer->field("used_resources", framework.totalUsedResources);
  writer->field("offered_resources", framework.totalOfferedResources);
  writer->field("capabilities", framework.info.capabilities());
  writer->field("hostname", framework.info.hostname());
  writer->field("webui_url", framework.info.webui_url());
  writer->field("active", framework.active());
  writer->field("connected", framework.connected());
  writer->field("recovered", framework.recovered());
}


// This abstraction has no side-effects. It factors out computing the
// mapping from 'slaves' to 'frameworks' to answer the questions 'what
// frameworks are running on a given slave?' and 'what slaves are
// running the given framework?'.
class SlaveFrameworkMapping
{
public:
  SlaveFrameworkMapping(const hashmap<FrameworkID, Framework*>& frameworks)
  {
    foreachpair (const FrameworkID& frameworkId,
                 const Framework* framework,
                 frameworks) {
      foreachvalue (const Task* task, framework->tasks) {
        frameworksToSlaves[frameworkId].insert(task->slave_id());
        slavesToFrameworks[task->slave_id()].insert(frameworkId);
      }

      foreachvalue (const Owned<Task>& task, framework->unreachableTasks) {
        frameworksToSlaves[frameworkId].insert(task->slave_id());
        slavesToFrameworks[task->slave_id()].insert(frameworkId);
      }

      foreach (const Owned<Task>& task, framework->completedTasks) {
        frameworksToSlaves[frameworkId].insert(task->slave_id());
        slavesToFrameworks[task->slave_id()].insert(frameworkId);
      }
    }
  }

  const hashset<FrameworkID>& frameworks(const SlaveID& slaveId) const
  {
    const auto iterator = slavesToFrameworks.find(slaveId);
    return iterator != slavesToFrameworks.end() ?
      iterator->second : hashset<FrameworkID>::EMPTY;
  }

  const hashset<SlaveID>& slaves(const FrameworkID& frameworkId) const
  {
    const auto iterator = frameworksToSlaves.find(frameworkId);
    return iterator != frameworksToSlaves.end() ?
      iterator->second : hashset<SlaveID>::EMPTY;
  }

private:
  hashmap<SlaveID, hashset<FrameworkID>> slavesToFrameworks;
  hashmap<FrameworkID, hashset<SlaveID>> frameworksToSlaves;
};


// This abstraction has no side-effects. It factors out the accounting
// for a 'TaskState' summary. We use this to summarize 'TaskState's
// for both frameworks as well as slaves.
struct TaskStateSummary
{
  // TODO(jmlvanre): Possibly clean this up as per MESOS-2694.
  const static TaskStateSummary EMPTY;

  TaskStateSummary()
    : staging(0),
      starting(0),
      running(0),
      killing(0),
      finished(0),
      killed(0),
      failed(0),
      lost(0),
      error(0),
      dropped(0),
      unreachable(0),
      gone(0),
      gone_by_operator(0),
      unknown(0) {}

  // Account for the state of the given task.
  void count(const Task& task)
  {
    switch (task.state()) {
      case TASK_STAGING: { ++staging; break; }
      case TASK_STARTING: { ++starting; break; }
      case TASK_RUNNING: { ++running; break; }
      case TASK_KILLING: { ++killing; break; }
      case TASK_FINISHED: { ++finished; break; }
      case TASK_KILLED: { ++killed; break; }
      case TASK_FAILED: { ++failed; break; }
      case TASK_LOST: { ++lost; break; }
      case TASK_ERROR: { ++error; break; }
      case TASK_DROPPED: { ++dropped; break; }
      case TASK_UNREACHABLE: { ++unreachable; break; }
      case TASK_GONE: { ++gone; break; }
      case TASK_GONE_BY_OPERATOR: { ++gone_by_operator; break; }
      case TASK_UNKNOWN: { ++unknown; break; }
      // No default case allows for a helpful compiler error if we
      // introduce a new state.
    }
  }

  size_t staging;
  size_t starting;
  size_t running;
  size_t killing;
  size_t finished;
  size_t killed;
  size_t failed;
  size_t lost;
  size_t error;
  size_t dropped;
  size_t unreachable;
  size_t gone;
  size_t gone_by_operator;
  size_t unknown;
};


const TaskStateSummary TaskStateSummary::EMPTY;


// This abstraction has no side-effects. It factors out computing the
// 'TaskState' summaries for frameworks and slaves. This answers the
// questions 'How many tasks are in each state for a given framework?'
// and 'How many tasks are in each state for a given slave?'.
class TaskStateSummaries
{
public:
  TaskStateSummaries(const hashmap<FrameworkID, Framework*>& frameworks)
  {
    foreachpair (const FrameworkID& frameworkId,
                 const Framework* framework,
                 frameworks) {
      foreachvalue (const Task* task, framework->tasks) {
        frameworkTaskSummaries[frameworkId].count(*task);
        slaveTaskSummaries[task->slave_id()].count(*task);
      }

      foreachvalue (const Owned<Task>& task, framework->unreachableTasks) {
        frameworkTaskSummaries[frameworkId].count(*task);
        slaveTaskSummaries[task->slave_id()].count(*task);
      }

      foreach (const Owned<Task>& task, framework->completedTasks) {
        frameworkTaskSummaries[frameworkId].count(*task);
        slaveTaskSummaries[task->slave_id()].count(*task);
      }
    }
  }

  const TaskStateSummary& framework(const FrameworkID& frameworkId) const
  {
    const auto iterator = frameworkTaskSummaries.find(frameworkId);
    return iterator != frameworkTaskSummaries.end() ?
      iterator->second : TaskStateSummary::EMPTY;
  }

  const TaskStateSummary& slave(const SlaveID& slaveId) const
  {
    const auto iterator = slaveTaskSummaries.find(slaveId);
    return iterator != slaveTaskSummaries.end() ?
      iterator->second : TaskStateSummary::EMPTY;
  }

private:
  hashmap<FrameworkID, TaskStateSummary> frameworkTaskSummaries;
  hashmap<SlaveID, TaskStateSummary> slaveTaskSummaries;
};


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::frameworks(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  CHECK_EQ(outputContentType, ContentType::JSON);

  IDAcceptor<FrameworkID> selectFrameworkId(
      query.get("framework_id"));

  // This lambda is consumed before the outer lambda
  // returns, hence capture by reference is fine here.
  const Master* master = this->master;
  auto frameworks = [master, &approvers, &selectFrameworkId](
      JSON::ObjectWriter* writer) {
    // Model all of the frameworks.
    writer->field(
        "frameworks",
        [master, &approvers, &selectFrameworkId](
            JSON::ArrayWriter* writer) {
          foreachvalue (
              Framework* framework, master->frameworks.registered) {
            // Skip unauthorized frameworks or frameworks
            // without a matching ID.
            if (!selectFrameworkId.accept(framework->id()) ||
                !approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
              continue;
            }

            writer->element(FullFrameworkWriter(approvers, framework));
          }
        });

    // Model all of the completed frameworks.
    writer->field(
        "completed_frameworks",
        [master, &approvers, &selectFrameworkId](
            JSON::ArrayWriter* writer) {
          foreachvalue (const Owned<Framework>& framework,
                        master->frameworks.completed) {
            // Skip unauthorized frameworks or frameworks
            // without a matching ID.
            if (!selectFrameworkId.accept(framework->id()) ||
                !approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
              continue;
            }

            writer->element(
                FullFrameworkWriter(approvers, framework.get()));
          }
        });

    // Unregistered frameworks are no longer possible. We emit an
    // empty array for the sake of backward compatibility.
    writer->field("unregistered_frameworks", [](JSON::ArrayWriter*) {});
  };

  return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
      OK(jsonify(frameworks), query.get("jsonp")),
      None());
}


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::roles(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  CHECK_EQ(outputContentType, ContentType::JSON);

  const Master* master = this->master;

  const vector<string> knownRoles = master->knownRoles();

  auto roles = [&](JSON::ObjectWriter* writer) {
    writer->field(
        "roles",
        [&](JSON::ArrayWriter* writer) {
          foreach (const string& name, knownRoles) {
            if (!approvers->approved<VIEW_ROLE>(name)) {
              continue;
            }

            writer->element([&](JSON::ObjectWriter* writer) {
              writer->field("name", name);

              writer->field(
                  "weight",
                  master->weights.get(name).getOrElse(DEFAULT_WEIGHT));

              Option<Role*> role = master->roles.get(name);

              RoleResourceBreakdown resourceBreakdown(master, name);

              // Prior to Mesos 1.9, this field is filled based on
              // `QuotaInfo` which is now deprecated. For backward
              // compatibility reasons, we do not use any formatter
              // for the new struct but construct the response by hand.
              // Specifically:
              //
              //  - We keep the `role` field which was present in the
              //    `QuotaInfo`.
              //
              //  - We name the field using singular `guarantee` and `limit`
              //    which is different from the plural used in `QuotaConfig`.
              const Quota quota = master->quotas.get(name).getOrElse(Quota());

              writer->field("quota", [&](JSON::ObjectWriter* writer) {
                writer->field("role", name);

                writer->field("guarantee", quota.guarantees);
                writer->field("limit", quota.limits);
                writer->field("consumed", resourceBreakdown.consumedQuota());
              });

              ResourceQuantities allocated = resourceBreakdown.allocated();
              ResourceQuantities offered = resourceBreakdown.offered();

              // Deprecated by allocated, offered, reserved.
              writer->field("resources", allocated + offered);

              writer->field("allocated", allocated);
              writer->field("offered", offered);
              writer->field("reserved", resourceBreakdown.reserved());

              if (role.isNone()) {
                writer->field("frameworks", [](JSON::ArrayWriter*) {});
              } else {
                writer->field("frameworks", [&](JSON::ArrayWriter* writer) {
                  foreachkey (const FrameworkID& id, (*role)->frameworks) {
                    writer->element(id.value());
                  }
                });
              }
            });
          }
        });
  };

  return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
      OK(jsonify(roles), query.get("jsonp")),
      None());
}


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::slaves(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  CHECK_EQ(outputContentType, ContentType::JSON);

  IDAcceptor<SlaveID> selectSlaveId(query.get("slave_id"));

  return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
      OK(jsonify(SlavesWriter(master->slaves, approvers, selectSlaveId)),
         query.get("jsonp")),
      None());
}


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::state(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  CHECK_EQ(outputContentType, ContentType::JSON);

  const Master* master = this->master;
  auto calculateState = [master, &approvers](JSON::ObjectWriter* writer) {
    writer->field("version", MESOS_VERSION);

    if (build::GIT_SHA.isSome()) {
      writer->field("git_sha", build::GIT_SHA.get());
    }

    if (build::GIT_BRANCH.isSome()) {
      writer->field("git_branch", build::GIT_BRANCH.get());
    }

    if (build::GIT_TAG.isSome()) {
      writer->field("git_tag", build::GIT_TAG.get());
    }

    writer->field("build_date", build::DATE);
    writer->field("build_time", build::TIME);
    writer->field("build_user", build::USER);
    writer->field("start_time", master->startTime.secs());

    if (master->electedTime.isSome()) {
      writer->field("elected_time", master->electedTime->secs());
    }

    writer->field("id", master->info().id());
    writer->field("pid", string(master->self()));
    writer->field("hostname", master->info().hostname());
    writer->field("capabilities", master->info().capabilities());
    writer->field("activated_slaves", master->_const_slaves_active());
    writer->field("deactivated_slaves", master->_const_slaves_inactive());
    writer->field("unreachable_slaves", master->_const_slaves_unreachable());

    if (master->info().has_domain()) {
      writer->field("domain", master->info().domain());
    }

    // TODO(haosdent): Deprecated this in favor of `leader_info` below.
    if (master->leader.isSome()) {
      writer->field("leader", master->leader->pid());
    }

    if (master->leader.isSome()) {
      writer->field("leader_info", [master](JSON::ObjectWriter* writer) {
        json(writer, master->leader.get());
      });
    }

    if (approvers->approved<VIEW_FLAGS>()) {
      if (master->flags.cluster.isSome()) {
        writer->field("cluster", master->flags.cluster.get());
      }

      if (master->flags.log_dir.isSome()) {
        writer->field("log_dir", master->flags.log_dir.get());
      }

      if (master->flags.external_log_file.isSome()) {
        writer->field("external_log_file",
                      master->flags.external_log_file.get());
      }

      writer->field("flags", [master](JSON::ObjectWriter* writer) {
          foreachvalue (const flags::Flag& flag, master->flags) {
            Option<string> value = flag.stringify(master->flags);
            if (value.isSome()) {
              writer->field(flag.effective_name().value, value.get());
            }
          }
        });
    }

    // Model all of the registered slaves.
    writer->field(
        "slaves",
        [master, &approvers](JSON::ArrayWriter* writer) {
          foreachvalue (Slave* slave, master->slaves.registered) {
            writer->element(SlaveWriter(
                *slave,
                master->slaves.draining.get(slave->id),
                master->slaves.deactivated.contains(slave->id),
                approvers));
          }
        });

    // Model all of the recovered slaves.
    writer->field(
        "recovered_slaves",
        [master](JSON::ArrayWriter* writer) {
          foreachvalue (
              const SlaveInfo& slaveInfo, master->slaves.recovered) {
            writer->element([&slaveInfo](JSON::ObjectWriter* writer) {
              json(writer, slaveInfo);
            });
          }
        });

    // Model all of the frameworks.
    writer->field(
        "frameworks",
        [master, &approvers](JSON::ArrayWriter* writer) {
          foreachvalue (
              Framework* framework, master->frameworks.registered) {
            // Skip unauthorized frameworks.
            if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
              continue;
            }

            writer->element(FullFrameworkWriter(approvers, framework));
          }
        });

    // Model all of the completed frameworks.
    writer->field(
        "completed_frameworks",
        [master, &approvers](JSON::ArrayWriter* writer) {
          foreachvalue (
              const Owned<Framework>& framework,
              master->frameworks.completed) {
            // Skip unauthorized frameworks.
            if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
              continue;
            }

            writer->element(
                FullFrameworkWriter(approvers, framework.get()));
          }
        });

    // Orphan tasks are no longer possible. We emit an empty array
    // for the sake of backward compatibility.
    writer->field("orphan_tasks", [](JSON::ArrayWriter*) {});

    // Unregistered frameworks are no longer possible. We emit an
    // empty array for the sake of backward compatibility.
    writer->field("unregistered_frameworks", [](JSON::ArrayWriter*) {});
  };

  return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
      OK(jsonify(calculateState), query.get("jsonp")),
      None());
}


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::stateSummary(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  CHECK_EQ(outputContentType, ContentType::JSON);

  const Master* master = this->master;
  auto stateSummary = [master, &approvers](JSON::ObjectWriter* writer) {
    writer->field("hostname", master->info().hostname());

    if (master->flags.cluster.isSome()) {
      writer->field("cluster", master->flags.cluster.get());
    }

    // We use the tasks in the 'Frameworks' struct to compute summaries
    // for this endpoint. This is done 1) for consistency between the
    // 'slaves' and 'frameworks' subsections below 2) because we want to
    // provide summary information for frameworks that are currently
    // registered 3) the frameworks keep a circular buffer of completed
    // tasks that we can use to keep a limited view on the history of
    // recent completed / failed tasks.

    // Generate mappings from 'slave' to 'framework' and reverse.
    SlaveFrameworkMapping slaveFrameworkMapping(
        master->frameworks.registered);

    // Generate 'TaskState' summaries for all framework and slave ids.
    TaskStateSummaries taskStateSummaries(
        master->frameworks.registered);

    // Model all of the slaves.
    writer->field(
        "slaves",
        [master,
         &slaveFrameworkMapping,
         &taskStateSummaries,
         &approvers](JSON::ArrayWriter* writer) {
          foreachvalue (Slave* slave, master->slaves.registered) {
            writer->element(
                [&slave,
                 &master,
                 &slaveFrameworkMapping,
                 &taskStateSummaries,
                 &approvers](JSON::ObjectWriter* writer) {
                  SlaveWriter slaveWriter(
                      *slave,
                      master->slaves.draining.get(slave->id),
                      master->slaves.deactivated.contains(slave->id),
                      approvers);
                  slaveWriter(writer);

                  // Add the 'TaskState' summary for this slave.
                  const TaskStateSummary& summary =
                      taskStateSummaries.slave(slave->id);

                  // Certain per-agent status totals will always be zero
                  // (e.g., TASK_ERROR, TASK_UNREACHABLE). We report
                  // them here anyway, for completeness.
                  //
                  // TODO(neilc): Update for TASK_GONE and
                  // TASK_GONE_BY_OPERATOR.
                  writer->field("TASK_STAGING", summary.staging);
                  writer->field("TASK_STARTING", summary.starting);
                  writer->field("TASK_RUNNING", summary.running);
                  writer->field("TASK_KILLING", summary.killing);
                  writer->field("TASK_FINISHED", summary.finished);
                  writer->field("TASK_KILLED", summary.killed);
                  writer->field("TASK_FAILED", summary.failed);
                  writer->field("TASK_LOST", summary.lost);
                  writer->field("TASK_ERROR", summary.error);
                  writer->field(
                      "TASK_UNREACHABLE",
                      summary.unreachable);

                  // Add the ids of all the frameworks running on this
                  // slave.
                  const hashset<FrameworkID>& frameworks =
                      slaveFrameworkMapping.frameworks(slave->id);

                  writer->field(
                      "framework_ids",
                      [&frameworks](JSON::ArrayWriter* writer) {
                        foreach (
                            const FrameworkID& frameworkId,
                            frameworks) {
                          writer->element(frameworkId.value());
                        }
                      });
                });
          }
        });

    // Model all of the frameworks.
    writer->field(
        "frameworks",
        [master,
         &slaveFrameworkMapping,
         &taskStateSummaries,
         &approvers](JSON::ArrayWriter* writer) {
          foreachpair (const FrameworkID& frameworkId,
                       Framework* framework,
                       master->frameworks.registered) {
            // Skip unauthorized frameworks.
            if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
              continue;
            }

            writer->element(
                [&frameworkId,
                 &framework,
                 &slaveFrameworkMapping,
                 &taskStateSummaries](JSON::ObjectWriter* writer) {
                  json(writer, Summary<Framework>(*framework));

                  // Add the 'TaskState' summary for this framework.
                  const TaskStateSummary& summary =
                      taskStateSummaries.framework(frameworkId);

                  // TODO(neilc): Update for TASK_GONE and
                  // TASK_GONE_BY_OPERATOR.
                  writer->field("TASK_STAGING", summary.staging);
                  writer->field("TASK_STARTING", summary.starting);
                  writer->field("TASK_RUNNING", summary.running);
                  writer->field("TASK_KILLING", summary.killing);
                  writer->field("TASK_FINISHED", summary.finished);
                  writer->field("TASK_KILLED", summary.killed);
                  writer->field("TASK_FAILED", summary.failed);
                  writer->field("TASK_LOST", summary.lost);
                  writer->field("TASK_ERROR", summary.error);
                  writer->field(
                      "TASK_UNREACHABLE",
                      summary.unreachable);

                  // Add the ids of all the slaves running
                  // this framework.
                  const hashset<SlaveID>& slaves =
                      slaveFrameworkMapping.slaves(frameworkId);

                  writer->field(
                      "slave_ids",
                      [&slaves](JSON::ArrayWriter* writer) {
                        foreach (const SlaveID& slaveId, slaves) {
                          writer->element(slaveId.value());
                        }
                      });
                });
          }
        });
    };

  return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
      OK(jsonify(stateSummary), query.get("jsonp")),
      None());
}


struct TaskComparator
{
  static bool ascending(const Task* lhs, const Task* rhs)
  {
    size_t lhsSize = lhs->statuses().size();
    size_t rhsSize = rhs->statuses().size();

    if ((lhsSize == 0) && (rhsSize == 0)) {
      return false;
    }

    if (lhsSize == 0) {
      return true;
    }

    if (rhsSize == 0) {
      return false;
    }

    return (lhs->statuses(0).timestamp() < rhs->statuses(0).timestamp());
  }

  static bool descending(const Task* lhs, const Task* rhs)
  {
    size_t lhsSize = lhs->statuses().size();
    size_t rhsSize = rhs->statuses().size();

    if ((lhsSize == 0) && (rhsSize == 0)) {
      return false;
    }

    if (rhsSize == 0) {
      return true;
    }

    if (lhsSize == 0) {
      return false;
    }

    return (lhs->statuses(0).timestamp() > rhs->statuses(0).timestamp());
  }
};


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::tasks(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  CHECK_EQ(outputContentType, ContentType::JSON);

  // Get list options (limit and offset).
  Result<int> result = numify<int>(query.get("limit"));
  size_t limit = result.isSome() ? result.get() : TASK_LIMIT;

  result = numify<int>(query.get("offset"));
  size_t offset = result.isSome() ? result.get() : 0;

  Option<string> order = query.get("order");
  string _order = order.isSome() && (order.get() == "asc") ? "asc" : "des";

  Option<string> frameworkId = query.get("framework_id");
  Option<string> taskId = query.get("task_id");

  IDAcceptor<FrameworkID> selectFrameworkId(frameworkId);
  IDAcceptor<TaskID> selectTaskId(taskId);

  // Construct framework list with both active and completed frameworks.
  vector<const Framework*> frameworks;
  foreachvalue (const Framework* framework, master->frameworks.registered) {
    // Skip unauthorized frameworks or frameworks without matching
    // framework ID.
    if (!selectFrameworkId.accept(framework->id()) ||
        !approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
      continue;
    }

    frameworks.push_back(framework);
  }

  foreachvalue (const Owned<Framework>& framework,
                master->frameworks.completed) {
    // Skip unauthorized frameworks or frameworks without matching
    // framework ID.
    if (!selectFrameworkId.accept(framework->id()) ||
        !approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
     continue;
    }

    frameworks.push_back(framework.get());
  }

  // Construct task list with both running,
  // completed and unreachable tasks.
  vector<const Task*> tasks;
  foreach (const Framework* framework, frameworks) {
    foreachvalue (Task* task, framework->tasks) {
      // Skip unauthorized tasks or tasks without matching task ID.
      if (!selectTaskId.accept(task->task_id()) ||
          !approvers->approved<VIEW_TASK>(*task, framework->info)) {
        continue;
      }

      tasks.push_back(task);
    }

    foreachvalue (
        const Owned<Task>& task,
        framework->unreachableTasks) {
      // Skip unauthorized tasks or tasks without matching task ID.
      if (!selectTaskId.accept(task->task_id()) ||
          !approvers->approved<VIEW_TASK>(*task, framework->info)) {
        continue;
      }

      tasks.push_back(task.get());
    }

    foreach (const Owned<Task>& task, framework->completedTasks) {
      // Skip unauthorized tasks or tasks without matching task ID.
      if (!selectTaskId.accept(task->task_id()) ||
          !approvers->approved<VIEW_TASK>(*task, framework->info)) {
        continue;
      }

      tasks.push_back(task.get());
    }
  }

  // Sort tasks by task status timestamp. Default order is descending.
  // The earliest timestamp is chosen for comparison when
  // multiple are present.
  if (_order == "asc") {
    sort(tasks.begin(), tasks.end(), TaskComparator::ascending);
  } else {
    sort(tasks.begin(), tasks.end(), TaskComparator::descending);
  }

  auto tasksWriter =
    [&tasks, limit, offset](JSON::ObjectWriter* writer) {
      writer->field(
          "tasks",
          [&tasks, limit, offset](JSON::ArrayWriter* writer) {
            // Collect 'limit' number of tasks starting from 'offset'.
            size_t end = std::min(offset + limit, tasks.size());
            for (size_t i = offset; i < end; i++) {
              writer->element(*tasks[i]);
            }
          });
  };

  return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
      OK(jsonify(tasksWriter), query.get("jsonp")),
      None());
}


function<void(JSON::ObjectWriter*)> Master::ReadOnlyHandler::jsonifyGetAgents(
    const Owned<ObjectApprovers>& approvers) const
{
  // Serialize the following:
  //
  //   mesos::master::Response::GetAgents getAgents;
  //   for each registered agent:
  //     *getAgents.add_agents() = protobuf::master::event::createAgentResponse(
  //         agent,
  //         master->slaves.draining.get(slave->id),
  //         master->slaves.deactivated.contains(slave->id),
  //         approvers);
  //   for each recovered agent:
  //     SlaveInfo* agent = getAgents.add_recovered_agents();
  //     agent->CopyFrom(slaveInfo);
  //     agent->clear_resources();
  //     foreach (const Resource& resource, slaveInfo.resources()):
  //       if (approvers->approved<VIEW_ROLE>(resource)):
  //         *agent->add_resources() = resource;

  // TODO(bmahler): This copies the Owned object approvers.
  return [=](JSON::ObjectWriter* writer) {
    const google::protobuf::Descriptor* descriptor =
      v1::master::Response::GetAgents::descriptor();

    int field;

    field = v1::master::Response::GetAgents::kAgentsFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        [&](JSON::ArrayWriter* writer) {
      foreachvalue (const Slave* slave, master->slaves.registered) {
        // TODO(bmahler): Consider not constructing the temporary
        // agent object and instead serialize directly.
        mesos::master::Response::GetAgents::Agent agent =
            protobuf::master::event::createAgentResponse(
                *slave,
                master->slaves.draining.get(slave->id),
                master->slaves.deactivated.contains(slave->id),
                approvers);

        writer->element(asV1Protobuf(agent));
      }
    });

    field = v1::master::Response::GetAgents::kRecoveredAgentsFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        [&](JSON::ArrayWriter* writer) {
      foreachvalue (const SlaveInfo& slaveInfo, master->slaves.recovered) {
        // TODO(bmahler): Consider not constructing the temporary
        // SlaveInfo object and instead serialize directly.
        SlaveInfo agent = slaveInfo;
        agent.clear_resources();
        foreach (const Resource& resource, slaveInfo.resources()) {
          if (approvers->approved<VIEW_ROLE>(resource)) {
            *agent.add_resources() = resource;
          }
        }

        writer->element(asV1Protobuf(agent));
      }
    });
  };
}


string Master::ReadOnlyHandler::serializeGetAgents(
    const Owned<ObjectApprovers>& approvers) const
{
  // Serialize the following:
  //
  //   mesos::master::Response::GetAgents getAgents;
  //   for each registered agent:
  //     *getAgents.add_agents() = protobuf::master::event::createAgentResponse(
  //         agent,
  //         master->slaves.draining.get(slave->id),
  //         master->slaves.deactivated.contains(slave->id),
  //         approvers);
  //   for each recovered agent:
  //     SlaveInfo* agent = getAgents.add_recovered_agents();
  //     agent->CopyFrom(slaveInfo);
  //     agent->clear_resources();
  //     foreach (const Resource& resource, slaveInfo.resources()):
  //       if (approvers->approved<VIEW_ROLE>(resource)):
  //         *agent->add_resources() = resource;

  string output;
  google::protobuf::io::StringOutputStream stream(&output);
  google::protobuf::io::CodedOutputStream writer(&stream);

  foreachvalue (const Slave* slave, master->slaves.registered) {
    // TODO(bmahler): Consider not constructing the temporary
    // agent object and instead serialize directly.
    WireFormatLite2::WriteMessageWithoutCachedSizes(
        mesos::master::Response::GetAgents::kAgentsFieldNumber,
        protobuf::master::event::createAgentResponse(
            *slave,
            master->slaves.draining.get(slave->id),
            master->slaves.deactivated.contains(slave->id),
            approvers),
        &writer);
  }

  foreachvalue (const SlaveInfo& slaveInfo, master->slaves.recovered) {
    // TODO(bmahler): Consider not constructing the temporary
    // SlaveInfo object and instead serialize directly.
    SlaveInfo agent = slaveInfo;
    agent.clear_resources();
    foreach (const Resource& resource, slaveInfo.resources()) {
      if (approvers->approved<VIEW_ROLE>(resource)) {
        *agent.add_resources() = resource;
      }
    }

    WireFormatLite2::WriteMessageWithoutCachedSizes(
        mesos::master::Response::GetAgents::kRecoveredAgentsFieldNumber,
        agent,
        &writer);
  }

  // While an explicit Trim() isn't necessary (since the coded
  // output stream is destructed before the string is returned),
  // it's a quite tricky bug to diagnose if Trim() is missed, so
  // we always do it explicitly to signal the reader about this
  // subtlety.
  writer.Trim();

  return output;
}



pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::getAgents(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  // Serialize the following message:
  //
  //   mesos::master::Response response;
  //   response.set_type(mesos::master::Response::GET_AGENTS);
  //   *response.mutable_get_agents() = _getAgents(approvers);

  switch (outputContentType) {
    case ContentType::PROTOBUF: {
      string output;
      google::protobuf::io::StringOutputStream stream(&output);
      google::protobuf::io::CodedOutputStream writer(&stream);

      WireFormatLite::WriteEnum(
          mesos::v1::master::Response::kTypeFieldNumber,
          mesos::v1::master::Response::GET_AGENTS,
          &writer);

      WireFormatLite::WriteBytes(
          mesos::v1::master::Response::kGetAgentsFieldNumber,
          serializeGetAgents(approvers),
          &writer);

      // We must manually trim the unused buffer space since
      // we use the string before the coded output stream is
      // destructed.
      writer.Trim();

      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          OK(std::move(output), stringify(outputContentType)),
          None());
    }

    case ContentType::JSON: {
      string body = jsonify([&](JSON::ObjectWriter* writer) {
        const google::protobuf::Descriptor* descriptor =
          v1::master::Response::descriptor();

        int field;

        field = v1::master::Response::kTypeFieldNumber;
        writer->field(
            descriptor->FindFieldByNumber(field)->name(),
            v1::master::Response::Type_Name(
                v1::master::Response::GET_AGENTS));

        field = v1::master::Response::kGetAgentsFieldNumber;
        writer->field(
            descriptor->FindFieldByNumber(field)->name(),
            jsonifyGetAgents(approvers));
      });

      // TODO(bmahler): Pass jsonp query parameter through here.
      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          OK(std::move(body), stringify(outputContentType)),
          None());
    }

    default:
      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          NotAcceptable("Request must accept json or protobuf"), None());
  }
}


function<void(JSON::ObjectWriter*)>
  Master::ReadOnlyHandler::jsonifyGetFrameworks(
      const Owned<ObjectApprovers>& approvers) const
{
  // Serialize the following:
  //
  //   mesos::master::Response::GetFrameworks getFrameworks;
  //   for each framework:
  //     *getFrameworks.add_frameworks() = model(*framework);
  //   for each completed framework:
  //     *getFrameworks.add_completed_frameworks() = model(*framework);

  // TODO(bmahler): Consider not constructing the temporary framework
  // objects and instead serialize directly, but since we don't
  // expect a large number of pending tasks, we currently don't
  // bother with the more efficient approach.

  // TODO(bmahler): This copies the Owned object approvers.
  return [=](JSON::ObjectWriter* writer) {
    const google::protobuf::Descriptor* descriptor =
      v1::master::Response::GetFrameworks::descriptor();

    int field;

    field = v1::master::Response::GetFrameworks::kFrameworksFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        [&](JSON::ArrayWriter* writer) {
      foreachvalue (const Framework* framework,
                    master->frameworks.registered) {
        // Skip unauthorized frameworks.
        if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
          continue;
        }

        mesos::master::Response::GetFrameworks::Framework f = model(*framework);
        writer->element(asV1Protobuf(f));
      }
    });

    field =
      v1::master::Response::GetFrameworks::kCompletedFrameworksFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        [&](JSON::ArrayWriter* writer) {
      foreachvalue (const Owned<Framework>& framework,
                    master->frameworks.completed) {
        // Skip unauthorized frameworks.
        if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
          continue;
        }

        mesos::master::Response::GetFrameworks::Framework f = model(*framework);
        writer->element(asV1Protobuf(f));
      }
    });
  };
}


string Master::ReadOnlyHandler::serializeGetFrameworks(
    const Owned<ObjectApprovers>& approvers) const
{
  // Serialize the following:
  //
  //   mesos::master::Response::GetFrameworks getFrameworks;
  //   for each framework:
  //     *getFrameworks.add_frameworks() = model(*framework);
  //   for each completed framework:
  //     *getFrameworks.add_completed_frameworks() = model(*framework);

  string output;
  google::protobuf::io::StringOutputStream stream(&output);
  google::protobuf::io::CodedOutputStream writer(&stream);

  // TODO(bmahler): Consider not constructing the temporary framework
  // objects and instead serialize directly, but since we don't
  // expect a large number of pending tasks, we currently don't
  // bother with the more efficient approach.

  foreachvalue (const Framework* framework,
                master->frameworks.registered) {
    // Skip unauthorized frameworks.
    if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
      continue;
    }

    WireFormatLite2::WriteMessageWithoutCachedSizes(
        mesos::master::Response::GetFrameworks::kFrameworksFieldNumber,
        model(*framework),
        &writer);
  }

  foreachvalue (const Owned<Framework>& framework,
                master->frameworks.completed) {
    // Skip unauthorized frameworks.
    if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
      continue;
    }

    WireFormatLite2::WriteMessageWithoutCachedSizes(
        mesos::master::Response::GetFrameworks::kCompletedFrameworksFieldNumber,
        model(*framework),
        &writer);
  }

  // While an explicit Trim() isn't necessary (since the coded
  // output stream is destructed before the string is returned),
  // it's a quite tricky bug to diagnose if Trim() is missed, so
  // we always do it explicitly to signal the reader about this
  // subtlety.
  writer.Trim();

  return output;
}


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::getFrameworks(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  // Serialize the following message:
  //
  //   mesos::master::Response response;
  //   response.set_type(mesos::master::Response::GET_FRAMEWORKS);
  //   *response.mutable_get_frameworks() = _getFrameworks(approvers);

  switch (outputContentType) {
    case ContentType::PROTOBUF: {
      string output;
      google::protobuf::io::StringOutputStream stream(&output);
      google::protobuf::io::CodedOutputStream writer(&stream);

      WireFormatLite::WriteEnum(
          mesos::v1::master::Response::kTypeFieldNumber,
          mesos::v1::master::Response::GET_FRAMEWORKS,
          &writer);

      WireFormatLite::WriteBytes(
          mesos::v1::master::Response::kGetFrameworksFieldNumber,
          serializeGetFrameworks(approvers),
          &writer);

      // We must manually trim the unused buffer space since
      // we use the string before the coded output stream is
      // destructed.
      writer.Trim();

      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          OK(std::move(output), stringify(outputContentType)),
          None());
    }

    case ContentType::JSON: {
      string body = jsonify([&](JSON::ObjectWriter* writer) {
        const google::protobuf::Descriptor* descriptor =
          v1::master::Response::descriptor();

        int field;

        field = v1::master::Response::kTypeFieldNumber;
        writer->field(
            descriptor->FindFieldByNumber(field)->name(),
            v1::master::Response::Type_Name(
                v1::master::Response::GET_FRAMEWORKS));

        field = v1::master::Response::kGetFrameworksFieldNumber;
        writer->field(
            descriptor->FindFieldByNumber(field)->name(),
            jsonifyGetFrameworks(approvers));
      });

      // TODO(bmahler): Pass jsonp query parameter through here.
      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          OK(std::move(body), stringify(outputContentType)),
          None());
    }

    default:
      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          NotAcceptable("Request must accept json or protobuf"), None());
  }
}


function<void(JSON::ObjectWriter*)>
  Master::ReadOnlyHandler::jsonifyGetExecutors(
      const Owned<ObjectApprovers>& approvers) const
{
  // Serialize the following:
  //
  //   mesos::master::Response::GetExecutors getExecutors;
  //
  //   for each (executor, agent):
  //     mesos::master::Response::GetExecutors::Executor* executor =
  //       getExecutors.add_executors();
  //     *executor->mutable_executor_info() = executorInfo;
  //     *executor->mutable_slave_id() = slaveId;

  // TODO(bmahler): This copies the owned object approvers.
  return [=](JSON::ObjectWriter* writer) {
    // Construct framework list with both active and completed frameworks.
    vector<const Framework*> frameworks;
    foreachvalue (const Framework* framework, master->frameworks.registered) {
      // Skip unauthorized frameworks.
      if (approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
        frameworks.push_back(framework);
      }
    }
    foreachvalue (const Owned<Framework>& framework,
                  master->frameworks.completed) {
      // Skip unauthorized frameworks.
      if (approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
        frameworks.push_back(framework.get());
      }
    }

    const google::protobuf::Descriptor* descriptor =
      v1::master::Response::GetExecutors::descriptor();

    int field;

    field = v1::master::Response::GetExecutors::kExecutorsFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        [&](JSON::ArrayWriter* writer) {
      foreach (const Framework* framework, frameworks) {
        foreachpair (const SlaveID& slaveId,
                     const auto& executorsMap,
                     framework->executors) {
          foreachvalue (const ExecutorInfo& executorInfo, executorsMap) {
            // Skip unauthorized executors.
            if (!approvers->approved<VIEW_EXECUTOR>(
                    executorInfo, framework->info)) {
              continue;
            }

            writer->element([&](JSON::ObjectWriter* writer) {
              const google::protobuf::Descriptor* descriptor =
                v1::master::Response::GetExecutors::Executor::descriptor();

              // Serialize the following message:
              //
              //   mesos::master::Response::GetExecutors::Executor executor;
              //   *executor.mutable_executor_info() = executorInfo;
              //   *executor.mutable_slave_id() = slaveId;
              int field;

              field = v1::master::Response::GetExecutors::Executor
                ::kExecutorInfoFieldNumber;
              writer->field(
                  descriptor->FindFieldByNumber(field)->name(),
                  asV1Protobuf(executorInfo));

              field = v1::master::Response::GetExecutors::Executor
                ::kAgentIdFieldNumber;
              writer->field(
                  descriptor->FindFieldByNumber(field)->name(),
                  asV1Protobuf(slaveId));
            });
          }
        }
      }
    });
  };
}


string Master::ReadOnlyHandler::serializeGetExecutors(
    const Owned<ObjectApprovers>& approvers) const
{
  // Construct framework list with both active and completed frameworks.
  vector<const Framework*> frameworks;
  foreachvalue (const Framework* framework, master->frameworks.registered) {
    // Skip unauthorized frameworks.
    if (approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
      frameworks.push_back(framework);
    }
  }
  foreachvalue (const Owned<Framework>& framework,
                master->frameworks.completed) {
    // Skip unauthorized frameworks.
    if (approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
      frameworks.push_back(framework.get());
    }
  }

  // Lambda for serializing the following message:
  //
  //   mesos::master::Response::GetExecutors::Executor executor;
  //   *executor.mutable_executor_info() = executorInfo;
  //   *executor.mutable_slave_id() = slaveId;
  auto serializeExecutor = [](const ExecutorInfo& e, const SlaveID& s) {
    string output;
    google::protobuf::io::StringOutputStream stream(&output);
    google::protobuf::io::CodedOutputStream writer(&stream);

    WireFormatLite2::WriteMessageWithoutCachedSizes(
        mesos::v1::master::Response::GetExecutors::Executor
          ::kExecutorInfoFieldNumber,
        e,
        &writer);

    WireFormatLite2::WriteMessageWithoutCachedSizes(
        mesos::v1::master::Response::GetExecutors::Executor
          ::kAgentIdFieldNumber,
        s,
        &writer);

    // While an explicit Trim() isn't necessary (since the coded
    // output stream is destructed before the string is returned),
    // it's a quite tricky bug to diagnose if Trim() is missed, so
    // we always do it explicitly to signal the reader about this
    // subtlety.
    writer.Trim();

    return output;
  };

  string output;
  google::protobuf::io::StringOutputStream stream(&output);
  google::protobuf::io::CodedOutputStream writer(&stream);

  // Serialize the following:
  //
  //   mesos::master::Response::GetExecutors getExecutors;
  //
  //   for each (executor, agent):
  //     mesos::master::Response::GetExecutors::Executor* executor =
  //       getExecutors.add_executors();
  //     *executor->mutable_executor_info() = executorInfo;
  //     *executor->mutable_slave_id() = slaveId;

  foreach (const Framework* framework, frameworks) {
    foreachpair (const SlaveID& slaveId,
                 const auto& executorsMap,
                 framework->executors) {
      foreachvalue (const ExecutorInfo& executorInfo, executorsMap) {
        // Skip unauthorized executors.
        if (!approvers->approved<VIEW_EXECUTOR>(
                executorInfo, framework->info)) {
          continue;
        }

        WireFormatLite::WriteBytes(
            mesos::v1::master::Response::GetExecutors::kExecutorsFieldNumber,
            serializeExecutor(executorInfo, slaveId),
            &writer);
      }
    }
  }

  // While an explicit Trim() isn't necessary (since the coded
  // output stream is destructed before the string is returned),
  // it's a quite tricky bug to diagnose if Trim() is missed, so
  // we always do it explicitly to signal the reader about this
  // subtlety.
  writer.Trim();

  return output;
}


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::getExecutors(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  // Serialize the following message:
  //
  //   mesos::master::Response response;
  //   response.set_type(mesos::master::Response::GET_EXECUTORS);
  //   *response.mutable_get_executors() = _getExecutors(approvers);

  switch (outputContentType) {
    case ContentType::PROTOBUF: {
      string output;
      google::protobuf::io::StringOutputStream stream(&output);
      google::protobuf::io::CodedOutputStream writer(&stream);

      WireFormatLite::WriteEnum(
          mesos::v1::master::Response::kTypeFieldNumber,
          mesos::v1::master::Response::GET_EXECUTORS,
          &writer);

      WireFormatLite::WriteBytes(
          mesos::v1::master::Response::kGetExecutorsFieldNumber,
          serializeGetExecutors(approvers),
          &writer);

      // We must manually trim the unused buffer space since
      // we use the string before the coded output stream is
      // destructed.
      writer.Trim();

      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          OK(std::move(output), stringify(outputContentType)),
          None());
    }

    case ContentType::JSON: {
      string body = jsonify([&](JSON::ObjectWriter* writer) {
        const google::protobuf::Descriptor* descriptor =
          v1::master::Response::descriptor();

        int field;

        field = v1::master::Response::kTypeFieldNumber;
        writer->field(
            descriptor->FindFieldByNumber(field)->name(),
            v1::master::Response::Type_Name(
                v1::master::Response::GET_EXECUTORS));

        field = v1::master::Response::kGetExecutorsFieldNumber;
        writer->field(
            descriptor->FindFieldByNumber(field)->name(),
            jsonifyGetExecutors(approvers));
      });

      // TODO(bmahler): Pass jsonp query parameter through here.
      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          OK(std::move(body), stringify(outputContentType)),
          None());
    }

    default:
      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          NotAcceptable("Request must accept json or protobuf"), None());
  }
}


function<void(JSON::ObjectWriter*)> Master::ReadOnlyHandler::jsonifyGetTasks(
    const Owned<ObjectApprovers>& approvers) const
{
  // Jsonify the following message:
  //
  //  master::Response::GetTasks getTasks;
  //  for each pending task:
  //    *getTasks.add_pending_tasks() =
  //      protobuf::createTask(taskInfo, TASK_STAGING, framework->id());
  //  for each task:
  //    *getTasks.add_tasks() = *task;
  //  for each unreachable task:
  //    *getTasks.add_unreachable_tasks() = *task;
  //  for each completed task:
  //    *getTasks.add_completed_tasks() = *task;

  // TODO(bmahler): This copies the Owned object approvers.
  return [=](JSON::ObjectWriter* writer) {
    // Construct framework list with both active and completed frameworks.
    vector<const Framework*> frameworks;
    foreachvalue (const Framework* framework, master->frameworks.registered) {
      // Skip unauthorized frameworks.
      if (approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
        frameworks.push_back(framework);
      }
    }
    foreachvalue (const Owned<Framework>& framework,
                  master->frameworks.completed) {
      // Skip unauthorized frameworks.
      if (approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
        frameworks.push_back(framework.get());
      }
    }

    const google::protobuf::Descriptor* descriptor =
      v1::master::Response::GetTasks::descriptor();

    int field;

    // Active tasks.
    field = v1::master::Response::GetTasks::kTasksFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        [&](JSON::ArrayWriter* writer) {
          foreach (const Framework* framework, frameworks) {
            foreachvalue (const Task* task, framework->tasks) {
              // Skip unauthorized tasks.
              if (!approvers->approved<VIEW_TASK>(*task, framework->info)) {
                continue;
              }

              writer->element(asV1Protobuf(*task));
            }
          }
        });

    // Unreachable tasks.
    field = v1::master::Response::GetTasks::kUnreachableTasksFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        [&](JSON::ArrayWriter* writer) {
          foreach (const Framework* framework, frameworks) {
            foreachvalue (const Owned<Task>& task,
                          framework->unreachableTasks) {
              // Skip unauthorized tasks.
              if (!approvers->approved<VIEW_TASK>(*task, framework->info)) {
                continue;
              }

              writer->element(asV1Protobuf(*task));
            }
          }
        });

    // Completed tasks.
    field = v1::master::Response::GetTasks::kCompletedTasksFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        [&](JSON::ArrayWriter* writer) {
          foreach (const Framework* framework, frameworks) {
            foreach (const Owned<Task>& task, framework->completedTasks) {
              // Skip unauthorized tasks.
              if (!approvers->approved<VIEW_TASK>(*task, framework->info)) {
                continue;
              }

              writer->element(asV1Protobuf(*task));
            }
          }
        });
  };
}


string Master::ReadOnlyHandler::serializeGetTasks(
    const Owned<ObjectApprovers>& approvers) const
{
  // Construct framework list with both active and completed frameworks.
  vector<const Framework*> frameworks;
  foreachvalue (const Framework* framework, master->frameworks.registered) {
    // Skip unauthorized frameworks.
    if (approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
      frameworks.push_back(framework);
    }
  }
  foreachvalue (const Owned<Framework>& framework,
                master->frameworks.completed) {
    // Skip unauthorized frameworks.
    if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
      frameworks.push_back(framework.get());
    }
  }

  // Serialize the following message:
  //
  //  mesos::master::Response::GetTasks getTasks;
  //  for each pending task:
  //    *getTasks.add_pending_tasks() =
  //      protobuf::createTask(taskInfo, TASK_STAGING, framework->id());
  //  for each task:
  //    *getTasks.add_tasks() = *task;
  //  for each unreachable task:
  //    *getTasks.add_unreachable_tasks() = *task;
  //  for each completed task:
  //    *getTasks.add_completed_tasks() = *task;

  string output;
  google::protobuf::io::StringOutputStream stream(&output);
  google::protobuf::io::CodedOutputStream writer(&stream);

  foreach (const Framework* framework, frameworks) {
    // Active tasks.
    foreachvalue (const Task* task, framework->tasks) {
      // Skip unauthorized tasks.
      if (!approvers->approved<VIEW_TASK>(*task, framework->info)) {
        continue;
      }

      WireFormatLite2::WriteMessageWithoutCachedSizes(
          mesos::v1::master::Response::GetTasks::kTasksFieldNumber,
          *task,
          &writer);
    }

    // Unreachable tasks.
    foreachvalue (const Owned<Task>& task, framework->unreachableTasks) {
      // Skip unauthorized tasks.
      if (!approvers->approved<VIEW_TASK>(*task, framework->info)) {
        continue;
      }

      WireFormatLite2::WriteMessageWithoutCachedSizes(
          mesos::v1::master::Response::GetTasks::kUnreachableTasksFieldNumber,
          *task,
          &writer);
    }

    // Completed tasks.
    foreach (const Owned<Task>& task, framework->completedTasks) {
      // Skip unauthorized tasks.
      if (!approvers->approved<VIEW_TASK>(*task, framework->info)) {
        continue;
      }

      WireFormatLite2::WriteMessageWithoutCachedSizes(
          mesos::v1::master::Response::GetTasks::kCompletedTasksFieldNumber,
          *task,
          &writer);
    }
  }

  // While an explicit Trim() isn't necessary (since the coded
  // output stream is destructed before the string is returned),
  // it's a quite tricky bug to diagnose if Trim() is missed, so
  // we always do it explicitly to signal the reader about this
  // subtlety.
  writer.Trim();

  return output;
}


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::getTasks(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  // Serialize the following message:
  //
  //    mesos::master::Response response;
  //    response.set_type(mesos::master::Response::GET_TASKS);
  //    *response.mutable_get_tasks() = _getTasks(approvers);

  switch (outputContentType) {
    case ContentType::PROTOBUF: {
      string output;
      google::protobuf::io::StringOutputStream stream(&output);
      google::protobuf::io::CodedOutputStream writer(&stream);

      WireFormatLite::WriteEnum(
          mesos::v1::master::Response::kTypeFieldNumber,
          mesos::v1::master::Response::GET_TASKS,
          &writer);

      WireFormatLite::WriteBytes(
          mesos::v1::master::Response::kGetTasksFieldNumber,
          serializeGetTasks(approvers),
          &writer);

      // We must manually trim the unused buffer space since
      // we use the string before the coded output stream is
      // destructed.
      writer.Trim();

      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          OK(std::move(output), stringify(outputContentType)),
          None());
    }

    case ContentType::JSON: {
      string body = jsonify([&](JSON::ObjectWriter* writer) {
        const google::protobuf::Descriptor* descriptor =
          v1::master::Response::descriptor();

        int field;

        field = v1::master::Response::kTypeFieldNumber;
        writer->field(
            descriptor->FindFieldByNumber(field)->name(),
            v1::master::Response::Type_Name(
                v1::master::Response::GET_TASKS));

        field = v1::master::Response::kGetTasksFieldNumber;
        writer->field(
            descriptor->FindFieldByNumber(field)->name(),
            jsonifyGetTasks(approvers));
      });

      // TODO(bmahler): Pass jsonp query parameter through here.
      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          OK(std::move(body), stringify(outputContentType)),
          None());
    }

    default:
      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          NotAcceptable("Request must accept json or protobuf"), None());
  }
}


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::getOperations(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  // We consider a principal to be authorized to view an operation if it
  // is authorized to view the resources the operation is performed on.
  auto approved = [&approvers](const Operation& operation) {
    Try<Resources> consumedResources =
      protobuf::getConsumedResources(operation.info());

    if (consumedResources.isError()) {
      LOG(WARNING)
        << "Could not approve operation " << operation.uuid()
        << " since its consumed resources could not be determined:"
        << consumedResources.error();

      return false;
    }

    foreach (const Resource& resource, consumedResources.get()) {
      if (!approvers->approved<VIEW_ROLE>(resource)) {
        return false;
      }
    }

    return true;
  };

  mesos::master::Response response;
  response.set_type(mesos::master::Response::GET_OPERATIONS);

  mesos::master::Response::GetOperations* operations =
    response.mutable_get_operations();

  foreachvalue (const Slave* slave, master->slaves.registered) {
    foreachvalue (const Operation* operation, slave->operations) {
      if (approved(*operation)) {
        operations->add_operations()->CopyFrom(*operation);
      }
    }

    foreachvalue (
        const Slave::ResourceProvider& resourceProvider,
        slave->resourceProviders) {
      foreachvalue (const Operation* operation, resourceProvider.operations) {
        if (approved(*operation)) {
          operations->add_operations()->CopyFrom(*operation);
        }
      }
    }
  }

  return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
      OK(serialize(outputContentType, evolve(response)),
         stringify(outputContentType)),
      None());
}


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::getRoles(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  const vector<string> knownRoles = master->knownRoles();

  mesos::master::Response response;
  response.set_type(mesos::master::Response::GET_ROLES);

  mesos::master::Response::GetRoles* getRoles =
    response.mutable_get_roles();

  foreach (const string& name, knownRoles) {
    if (!approvers->approved<VIEW_ROLE>(name)) {
      continue;
    }

    mesos::Role* role = getRoles->add_roles();

    role->set_name(name);

    role->set_weight(master->weights.get(name).getOrElse(DEFAULT_WEIGHT));

    RoleResourceBreakdown resourceBreakdown(master, name);

    ResourceQuantities allocatedAndOffered =
      resourceBreakdown.allocated() + resourceBreakdown.offered();

    // `resources` will be deprecated in favor of
    // `offered`, `allocated`, `reserved`, and quota consumption.
    // As a result, we don't bother trying to expose more
    // than {cpus, mem, disk, gpus} since we don't know if
    // anything outside this set is of type SCALAR.
    foreach (const auto& quantity, allocatedAndOffered) {
      if (quantity.first == "cpus" || quantity.first == "mem" ||
          quantity.first == "disk" || quantity.first == "gpus") {
        Resource* resource = role->add_resources();
        resource->set_name(quantity.first);
        resource->set_type(Value::SCALAR);
        *resource->mutable_scalar() = quantity.second;
      }
    }

    Option<Role*> role_ = master->roles.get(name);

    if (role_.isSome()) {
      foreachkey (const FrameworkID& frameworkId, (*role_)->frameworks) {
        *role->add_frameworks() = frameworkId;
      }
    }
  }

  return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
      OK(serialize(outputContentType, evolve(response)),
         stringify(outputContentType)),
      None());
}


function<void(JSON::ObjectWriter*)> Master::ReadOnlyHandler::jsonifyGetState(
    const Owned<ObjectApprovers>& approvers) const
{
  // Jsonify the following message:
  //
  //   mesos::master::Response::GetState getState;
  //   *getState.mutable_get_tasks() = _getTasks(approvers);
  //   *getState.mutable_get_executors() = _getExecutors(approvers);
  //   *getState.mutable_get_frameworks() = _getFrameworks(approvers);
  //   *getState.mutable_get_agents() = _getAgents(approvers);

  // TODO(bmahler): This copies the Owned object approvers.
  return [=](JSON::ObjectWriter* writer) {
    const google::protobuf::Descriptor* descriptor =
      v1::master::Response::GetState::descriptor();

    int field;

    field = v1::master::Response::GetState::kGetTasksFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        jsonifyGetTasks(approvers));

    field = v1::master::Response::GetState::kGetExecutorsFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        jsonifyGetExecutors(approvers));

    field = v1::master::Response::GetState::kGetFrameworksFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        jsonifyGetFrameworks(approvers));

    field = v1::master::Response::GetState::kGetAgentsFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        jsonifyGetAgents(approvers));
  };
}


string Master::ReadOnlyHandler::serializeGetState(
    const Owned<ObjectApprovers>& approvers) const
{
  // Serialize the following message:
  //
  //   mesos::master::Response::GetState getState;
  //   *getState.mutable_get_tasks() = _getTasks(approvers);
  //   *getState.mutable_get_executors() = _getExecutors(approvers);
  //   *getState.mutable_get_frameworks() = _getFrameworks(approvers);
  //   *getState.mutable_get_agents() = _getAgents(approvers);

  string output;
  google::protobuf::io::StringOutputStream stream(&output);
  google::protobuf::io::CodedOutputStream writer(&stream);

  WireFormatLite::WriteBytes(
      mesos::v1::master::Response::GetState::kGetTasksFieldNumber,
      serializeGetTasks(approvers),
      &writer);

  WireFormatLite::WriteBytes(
      mesos::v1::master::Response::GetState::kGetExecutorsFieldNumber,
      serializeGetExecutors(approvers),
      &writer);

  WireFormatLite::WriteBytes(
      mesos::v1::master::Response::GetState::kGetFrameworksFieldNumber,
      serializeGetFrameworks(approvers),
      &writer);

  WireFormatLite::WriteBytes(
      mesos::v1::master::Response::GetState::kGetAgentsFieldNumber,
      serializeGetAgents(approvers),
      &writer);

  // While an explicit Trim() isn't necessary (since the coded
  // output stream is destructed before the string is returned),
  // it's a quite tricky bug to diagnose if Trim() is missed, so
  // we always do it explicitly to signal the reader about this
  // subtlety.
  writer.Trim();

  return output;
}


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::getState(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  // Serialize the following message:
  //
  //   mesos::master::Response response;
  //   response.set_type(mesos::master::Response::GET_STATE);
  //   *response.mutable_get_state() = _getState(approvers);

  switch (outputContentType) {
    case ContentType::PROTOBUF: {
      string output;
      google::protobuf::io::StringOutputStream stream(&output);
      google::protobuf::io::CodedOutputStream writer(&stream);

      WireFormatLite::WriteEnum(
          mesos::v1::master::Response::kTypeFieldNumber,
          mesos::v1::master::Response::GET_STATE,
          &writer);

      WireFormatLite::WriteBytes(
          mesos::v1::master::Response::kGetStateFieldNumber,
          serializeGetState(approvers),
          &writer);

      // We must manually trim the unused buffer space since
      // we use the string before the coded output stream is
      // destructed.
      writer.Trim();

      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          OK(std::move(output), stringify(outputContentType)),
          None());
    }

    case ContentType::JSON: {
      string body = jsonify([&](JSON::ObjectWriter* writer) {
        const google::protobuf::Descriptor* descriptor =
          v1::master::Response::descriptor();

        int field;

        field = v1::master::Response::kTypeFieldNumber;
        writer->field(
            descriptor->FindFieldByNumber(field)->name(),
            v1::master::Response::Type_Name(
                v1::master::Response::GET_STATE));

        field = v1::master::Response::kGetStateFieldNumber;
        writer->field(
            descriptor->FindFieldByNumber(field)->name(),
            jsonifyGetState(approvers));
      });

      // TODO(bmahler): Pass jsonp query parameter through here.
      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          OK(std::move(body), stringify(outputContentType)),
          None());
    }

    default:
      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          NotAcceptable("Request must accept json or protobuf"), None());
  }
}


pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>
  Master::ReadOnlyHandler::subscribe(
      ContentType outputContentType,
      const hashmap<std::string, std::string>& query,
      const process::Owned<ObjectApprovers>& approvers) const
{
  process::http::Pipe pipe;
  OK ok;

  ok.headers["Content-Type"] = stringify(outputContentType);
  ok.type = process::http::Response::PIPE;
  ok.reader = pipe.reader();

  StreamingHttpConnection<v1::master::Event> http(
      pipe.writer(), outputContentType);

  // Serialize the following event:
  //
  //   mesos::master::Event event;
  //   event.set_type(mesos::master::Event::SUBSCRIBED);
  //   *event.mutable_subscribed()->mutable_get_state() =
  //     _getState(approvers);
  //   event.mutable_subscribed()->set_heartbeat_interval_seconds(
  //       DEFAULT_HEARTBEAT_INTERVAL.secs());
  //
  //   http.send(event);

  switch (outputContentType) {
    case ContentType::PROTOBUF: {
      string serialized;
      google::protobuf::io::StringOutputStream stream(&serialized);
      google::protobuf::io::CodedOutputStream writer(&stream);

      WireFormatLite::WriteEnum(
          mesos::v1::master::Event::kTypeFieldNumber,
          mesos::v1::master::Event::SUBSCRIBED,
          &writer);

      WireFormatLite::WriteBytes(
          mesos::v1::master::Event::kSubscribedFieldNumber,
          serializeSubscribe(approvers),
          &writer);

      // We must manually trim the unused buffer space since
      // we use the string before the coded output stream is
      // destructed.
      writer.Trim();

      http.send(serialized);

      break;
    }

    case ContentType::JSON: {
      string serialized = jsonify([&](JSON::ObjectWriter* writer) {
        const google::protobuf::Descriptor* descriptor =
          v1::master::Event::descriptor();

        int field;

        field = v1::master::Event::kTypeFieldNumber;
        writer->field(
            descriptor->FindFieldByNumber(field)->name(),
            v1::master::Event::Type_Name(
                v1::master::Event::SUBSCRIBED));

        field = v1::master::Event::kSubscribedFieldNumber;
        writer->field(
            descriptor->FindFieldByNumber(field)->name(),
            jsonifySubscribe(approvers));
      });

      http.send(serialized);

      break;
    }

    default:
      return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
          NotAcceptable("Request must accept json or protobuf"), None());
  }

  mesos::master::Event heartbeatEvent;
  heartbeatEvent.set_type(mesos::master::Event::HEARTBEAT);
  http.send(heartbeatEvent);

  // This new subscriber needs to be added in the post-processing step.
  Master::ReadOnlyHandler::PostProcessing::Subscribe s = {approvers, http};

  Master::ReadOnlyHandler::PostProcessing postProcessing = { std::move(s) };

  return pair<Response, Option<Master::ReadOnlyHandler::PostProcessing>>(
      ok,
      std::move(postProcessing));
}


function<void(JSON::ObjectWriter*)> Master::ReadOnlyHandler::jsonifySubscribe(
    const Owned<ObjectApprovers>& approvers) const
{
  // Jsonify the following message:
  //
  //   mesos::master::Event::Subscribed subscribed;
  //   *subscribed.mutable_get_state() = _getState(approvers);
  //   subscribed.set_heartbeat_interval_seconds(
  //       DEFAULT_HEARTBEAT_INTERVAL.secs());

  // TODO(bmahler): This copies the Owned object approvers.
  return [=](JSON::ObjectWriter* writer) {
    const google::protobuf::Descriptor* descriptor =
      v1::master::Event::Subscribed::descriptor();

    int field;

    field = v1::master::Event::Subscribed::kGetStateFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        jsonifyGetState(approvers));

    field = v1::master::Event::Subscribed::kHeartbeatIntervalSecondsFieldNumber;
    writer->field(
        descriptor->FindFieldByNumber(field)->name(),
        DEFAULT_HEARTBEAT_INTERVAL.secs());
  };
}


string Master::ReadOnlyHandler::serializeSubscribe(
    const Owned<ObjectApprovers>& approvers) const
{
  // Serialize the following message:
  //
  //   mesos::master::Event::Subscribed subscribed;
  //   *subscribed.mutable_get_state() = _getState(approvers);
  //   subscribed.set_heartbeat_interval_seconds(
  //       DEFAULT_HEARTBEAT_INTERVAL.secs());

  string output;
  google::protobuf::io::StringOutputStream stream(&output);
  google::protobuf::io::CodedOutputStream writer(&stream);

  WireFormatLite::WriteBytes(
      mesos::v1::master::Event::Subscribed::kGetStateFieldNumber,
      serializeGetState(approvers),
      &writer);

  WireFormatLite::WriteDouble(
      mesos::v1::master::Event::Subscribed
        ::kHeartbeatIntervalSecondsFieldNumber,
      DEFAULT_HEARTBEAT_INTERVAL.secs(),
      &writer);

  // While an explicit Trim() isn't necessary (since the coded
  // output stream is destructed before the string is returned),
  // it's a quite tricky bug to diagnose if Trim() is missed, so
  // we always do it explicitly to signal the reader about this
  // subtlety.
  writer.Trim();

  return output;
}

} // namespace master {
} // namespace internal {
} // namespace mesos {
