Status KsckResults::PrintTo()

in src/kudu/tools/ksck_results.cc [176:377]


Status KsckResults::PrintTo(PrintMode mode, int sections, ostream& out) {
  static const char* const kMsgCheckedFlags =
      "Flags of checked categories for $0:";
  static const char* const kMsgUnusualFlags = "Unusual flags for $0:";
  static const char* const kMsgDivergedFlags =
      "Flags of checked categories for $0 diverging from $1 flags:";

  if (mode == PrintMode::JSON_PRETTY || mode == PrintMode::JSON_COMPACT) {
    return PrintJsonTo(mode, sections, out);
  }

  // First, report on the masters and master tablet.
  if (sections & PrintSections::MASTER_SUMMARIES) {
    std::sort(cluster_status.master_summaries.begin(),
              cluster_status.master_summaries.end(),
              ServerByHealthComparator);
    RETURN_NOT_OK(PrintServerHealthSummaries(ServerType::MASTER,
                                             cluster_status.master_summaries,
                                             out));
    if (mode == PrintMode::PLAIN_FULL || cluster_status.master_consensus_conflict) {
      RETURN_NOT_OK(PrintConsensusMatrix(cluster_status.master_uuids,
                                         nullopt,
                                         cluster_status.master_consensus_state_map,
                                         out));
    }
    out << endl;

    if (!master_unusual_flag_to_servers_map.empty()) {
      out << Substitute(kMsgUnusualFlags,
                        ServerTypeToString(ServerType::MASTER)) << endl;
      RETURN_NOT_OK(PrintTaggedFlagTable(ServerType::MASTER,
                                         cluster_status.master_summaries.size(),
                                         master_unusual_flag_to_servers_map,
                                         master_unusual_flag_tags_map,
                                         out));
      out << endl;
    }

    if (!master_checked_flag_to_servers_map.empty()) {
      out << Substitute(kMsgCheckedFlags,
                        ServerTypeToString(ServerType::MASTER)) << endl;
      RETURN_NOT_OK(PrintFlagTable(ServerType::MASTER,
                                   cluster_status.master_summaries.size(),
                                   master_checked_flag_to_servers_map,
                                   out));
      out << endl;
    }

    if (!master_diverged_flag_to_servers_map.empty()) {
      out << Substitute(kMsgDivergedFlags,
                        ServerTypeToString(ServerType::MASTER),
                        ServerTypeToString(ServerType::TABLET_SERVER)) << endl;
      RETURN_NOT_OK(PrintFlagTable(ServerType::MASTER,
                                   cluster_status.master_summaries.size(),
                                   master_diverged_flag_to_servers_map,
                                   out));
      out << endl;
    }
  }

  // Then, on any special tablet server states.
  if (sections & PrintSections::TSERVER_STATES &&
      !ts_states.empty()) {
    RETURN_NOT_OK(PrintTServerStatesTable(ts_states, out));
    out << endl;
  }

  // Then, on the health of the tablet servers.
  if (sections & PrintSections::TSERVER_SUMMARIES) {
    std::sort(cluster_status.tserver_summaries.begin(),
              cluster_status.tserver_summaries.end(),
              ServerByHealthComparator);
    RETURN_NOT_OK(PrintServerHealthSummaries(ServerType::TABLET_SERVER,
                                             cluster_status.tserver_summaries,
                                             out));
    if (!cluster_status.tserver_summaries.empty()) {
      out << endl;
    }

    if (!tserver_unusual_flag_to_servers_map.empty()) {
      out << Substitute(kMsgUnusualFlags,
                        ServerTypeToString(ServerType::TABLET_SERVER)) << endl;
      RETURN_NOT_OK(PrintTaggedFlagTable(ServerType::TABLET_SERVER,
                                         cluster_status.tserver_summaries.size(),
                                         tserver_unusual_flag_to_servers_map,
                                         tserver_unusual_flag_tags_map,
                                         out));
      out << endl;
    }

    if (!tserver_checked_flag_to_servers_map.empty()) {
      out << Substitute(kMsgCheckedFlags,
                        ServerTypeToString(ServerType::TABLET_SERVER)) << endl;
      RETURN_NOT_OK(PrintFlagTable(ServerType::TABLET_SERVER,
                                   cluster_status.tserver_summaries.size(),
                                   tserver_checked_flag_to_servers_map,
                                   out));
      out << endl;
    }

    if (!tserver_diverged_flag_to_servers_map.empty()) {
      out << Substitute(kMsgDivergedFlags,
                        ServerTypeToString(ServerType::TABLET_SERVER),
                        ServerTypeToString(ServerType::MASTER)) << endl;
      RETURN_NOT_OK(PrintFlagTable(ServerType::TABLET_SERVER,
                                   cluster_status.tserver_summaries.size(),
                                   tserver_diverged_flag_to_servers_map,
                                   out));
      out << endl;
    }
  }

  // Finally, in the "server section", print the version summary.
  if (sections & PrintSections::VERSION_SUMMARIES) {
    RETURN_NOT_OK(PrintVersionTable(version_summaries,
                                    cluster_status.master_summaries.size() +
                                        cluster_status.tserver_summaries.size(),
                                    out));
    out << endl;
  }

  // Then, on each tablet.
  if (sections & PrintSections::TABLET_SUMMARIES) {
    RETURN_NOT_OK(PrintTabletSummaries(cluster_status.tablet_summaries, mode, out));
  }

  // Then, summarize the tablets by table.
  // Sort the tables so unhealthy tables are easy to see at the bottom.
  const auto sort_and_print_tables = [&] (vector<TableSummary>* table_summaries,
                                          const string& table_type) {
    std::sort(table_summaries->begin(),
              table_summaries->end(),
              [](const TableSummary &left,
                const TableSummary &right) {
                  return std::make_pair(left.TableStatus() != HealthCheckResult::HEALTHY,
                                        left.name) <
                        std::make_pair(right.TableStatus() != HealthCheckResult::HEALTHY,
                                        right.name);
              });
    return PrintTableSummaries(*table_summaries, table_type, out);
  };
  if (sections & PrintSections::SYSTEM_TABLE_SUMMARIES) {
    RETURN_NOT_OK(sort_and_print_tables(&cluster_status.system_table_summaries, "system table"));
    if (!cluster_status.system_table_summaries.empty()) {
      out << endl;
    }
  }
  if (sections & PrintSections::TABLE_SUMMARIES) {
    RETURN_NOT_OK(sort_and_print_tables(&cluster_status.table_summaries, "table"));
    if (!cluster_status.table_summaries.empty()) {
      out << endl;
    }

    // Add in a summary of the tablet replicas by tablet server, so it's easy to
    // see if some tablet servers have too many replicas.
    RETURN_NOT_OK(PrintReplicaCountByTserverSummary(mode, *this, out));
  }

  // Next, report on checksum scans.
  if (sections & PrintSections::CHECKSUM_RESULTS) {
    RETURN_NOT_OK(PrintChecksumResults(checksum_results, out));
    if (!checksum_results.tables.empty()) {
      out << endl;
    }
  }

  // And, add a summary of all the things we checked.
  if (sections & PrintSections::TOTAL_COUNT) {
    RETURN_NOT_OK(PrintTotalCounts(*this, out));
    out << endl;
  }

  // Penultimately, print the warnings.
  if (!warning_messages.empty()) {
    out << "==================" << endl;
    out << "Warnings:" << endl;
    out << "==================" << endl;
    for (const auto& s : warning_messages) {
      out << s.message().ToString() << endl;
    }
    out << endl;
  }

  // Finally, print a summary of all errors.
  if (error_messages.empty()) {
    // All good.
    out << "OK" << endl;
  } else {
    // Something went wrong.
    out << "==================" << endl;
    out << "Errors:" << endl;
    out << "==================" << endl;
    for (const auto& s : error_messages) {
      out << s.ToString() << endl;
    }
    out << endl;
    out << "FAILED" << endl;
  }

  // Remember, we only return non-OK if printing failed, not if ksck checks failed.
  return Status::OK();
}