// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <errno.h>
#include <fbl/string_buffer.h>
#include <fbl/unique_fd.h>
#include <fcntl.h>
#include <fuchsia/hardware/block/c/fidl.h>
#include <fuchsia/io/c/fidl.h>
#include <fuchsia/minfs/c/fidl.h>
#include <fuchsia/minfs/llcpp/fidl.h>
#include <fuchsia/storage/metrics/c/fidl.h>
#include <getopt.h>
#include <lib/fdio/cpp/caller.h>
#include <minfs/metrics.h>
#include <stdio.h>
#include <stdlib.h>
#include <storage-metrics/block-metrics.h>
#include <storage-metrics/fs-metrics.h>
#include <string.h>
#include <unistd.h>
#include <zircon/device/block.h>
#include <zircon/types.h>

#include <utility>

namespace {

using MinfsFidlMetrics = ::llcpp::fuchsia::minfs::Metrics;

int Usage() {
  fprintf(stdout, "usage: storage-metrics [ <option>* ] [paths]\n");
  fprintf(stdout,
          " storage-metrics reports metrics for storage components (block"
          " devices and filesystems). It is currently limited to minfs\n");
  fprintf(stdout, " --clear : clears metrics on block devices supporting paths\n");
  fprintf(stdout,
          " --enable_metrics=[true|false] : enables or disables metrics"
          " for the filesystems supporting path\n");
  fprintf(stdout, " --help : Show this help message\n");
  return -1;
}

// Type to track whether whether a boolean flag without a default value has been set
enum class BooleanFlagState { kUnset, kEnable, kDisable };

struct StorageMetricOptions {
  // True indicates that a call to retrieve block device metrics should also clear those metrics.
  bool clear_block = false;
  // Value passed to a filesystem toggle metrics request.
  BooleanFlagState enable_fs_metrics = BooleanFlagState::kUnset;
};

void PrintFsMetrics(const MinfsFidlMetrics& metrics, const char* path) {
  minfs::MinfsMetrics minfs_metrics(&metrics);
  printf("Filesystem Metrics for: %s\n", path);
  printf("General IO metrics\n");
  minfs_metrics.Dump(stdout, true);
  minfs_metrics.Dump(stdout, false);
  // minfs_metrics.Dump(stdout);
  printf("\n");
}

// Sends a FIDL call to enable or disable filesystem metrics for path
zx_status_t EnableFsMetrics(const char* path, bool enable) {
  fbl::unique_fd fd(open(path, O_RDONLY | O_DIRECTORY));
  if (!fd) {
    fprintf(stderr, "Error opening %s, errno %d (%s)\n", path, errno, strerror(errno));
    return ZX_ERR_IO;
  }

  zx_status_t status;
  fdio_cpp::FdioCaller caller(std::move(fd));
  zx_status_t rc = fuchsia_minfs_MinfsToggleMetrics(caller.borrow_channel(), enable, &status);
  if (rc != ZX_OK || status != ZX_OK) {
    fprintf(stderr, "Error toggling metrics for %s, status %d\n", path,
            (rc != ZX_OK) ? rc : status);
    return (rc != ZX_OK) ? rc : status;
  }
  return status;
}

// Retrieves the Filesystem metrics for path. Only supports Minfs.
zx_status_t GetFsMetrics(const char* path, MinfsFidlMetrics* out_metrics) {
  fbl::unique_fd fd(open(path, O_RDONLY | O_DIRECTORY));
  if (!fd) {
    fprintf(stderr, "Error opening %s, errno %d (%s)\n", path, errno, strerror(errno));
    return ZX_ERR_IO;
  }

  fdio_cpp::FdioCaller caller(std::move(fd));
  auto result = llcpp::fuchsia::minfs::Minfs::Call::GetMetrics(caller.channel());
  if (!result.ok()) {
    fprintf(stderr, "Error getting metrics for %s, status %d\n", path, result.status());
    return result.status();
  }
  if (result.value().status == ZX_ERR_UNAVAILABLE) {
    fprintf(stderr, "Metrics Unavailable for %s\n", path);
    return result.status();
  }
  if (result.value().status != ZX_OK) {
    fprintf(stderr, "Error getting metrics for %s, status %d\n", path, result.value().status);
    return result.value().status;
  }
  if (!result.value().metrics) {
    fprintf(stderr, "Error getting metrics for %s, returned metrics was null\n", path);
    return ZX_ERR_INTERNAL;
  }
  *out_metrics = *result.value().metrics;
  return ZX_OK;
}

void PrintBlockMetrics(const char* dev, const fuchsia_hardware_block_BlockStats& stats) {
  printf("Block Metrics for device path: %s\n", dev);
  storage_metrics::BlockDeviceMetrics metrics(&stats);
  metrics.Dump(stdout);
}

// Retrieves metrics for the block device at dev. Clears metrics if clear is true.
zx_status_t GetBlockMetrics(const char* dev, bool clear, fuchsia_hardware_block_BlockStats* stats) {
  fbl::unique_fd fd(open(dev, O_RDONLY));
  if (!fd) {
    fprintf(stderr, "Error opening %s, errno %d (%s)\n", dev, errno, strerror(errno));
    return ZX_ERR_IO;
  }
  fdio_cpp::FdioCaller caller(std::move(fd));
  zx_status_t status;
  zx_status_t io_status =
      fuchsia_hardware_block_BlockGetStats(caller.borrow_channel(), clear, &status, stats);
  if (io_status != ZX_OK) {
    status = io_status;
  }
  if (status != ZX_OK) {
    fprintf(stderr, "Error getting stats for %s\n", dev);
    return status;
  }
  return ZX_OK;
}

void ParseCommandLineArguments(int argc, char** argv, StorageMetricOptions* options) {
  static const struct option opts[] = {
      {"clear", optional_argument, NULL, 'c'},
      {"enable_metrics", optional_argument, NULL, 'e'},
      {"help", no_argument, NULL, 'h'},
      {0, 0, 0, 0},
  };
  for (int opt; (opt = getopt_long(argc, argv, "c::e::h", opts, nullptr)) != -1;) {
    switch (opt) {
      case 'c':
        options->clear_block = (optarg == nullptr || strcmp(optarg, "true") == 0);
        break;
      case 'e':
        options->enable_fs_metrics = (optarg == nullptr || strcmp(optarg, "true") == 0)
                                         ? BooleanFlagState::kEnable
                                         : BooleanFlagState::kDisable;
        break;
      case 'h':
        __FALLTHROUGH;
      default:
        Usage();
    }
  }
}

// Retrieves filesystem metrics for the filesystem at path and prints them.
void RunFsMetrics(const fbl::StringBuffer<PATH_MAX> path, const StorageMetricOptions options) {
  fbl::unique_fd fd(open(path.c_str(), O_RDONLY | O_ADMIN));
  if (!fd) {
    fd.reset(open(path.c_str(), O_RDONLY));
    if (!fd) {
      fprintf(stderr, "storage-metrics could not open target: %s, errno %d (%s)\n", path.c_str(),
              errno, strerror(errno));
      return;
    }
  }

  fuchsia_io_FilesystemInfo info;
  zx_status_t status;
  fdio_cpp::FdioCaller caller(std::move(fd));
  zx_status_t io_status =
      fuchsia_io_DirectoryAdminQueryFilesystem(caller.borrow_channel(), &status, &info);
  if (io_status != ZX_OK || status != ZX_OK) {
    fprintf(stderr, "storage-metrics could not open %s, status %d\n", path.c_str(),
            (io_status != ZX_OK) ? io_status : status);
    return;
  }

  // Skip any filesystems that aren't minfs
  info.name[fuchsia_io_MAX_FS_NAME_BUFFER - 1] = '\0';
  const char* name = reinterpret_cast<const char*>(info.name);
  if (strcmp(name, "minfs") != 0) {
    fprintf(stderr, "storage-metrics does not support filesystem type %s\n", name);
    return;
  }

  zx_status_t rc;
  // The order of these conditionals allows for stats to be output regardless of the
  // value of enable.
  if (options.enable_fs_metrics == BooleanFlagState::kEnable) {
    rc = EnableFsMetrics(path.c_str(), true);
    if (rc != ZX_OK) {
      fprintf(stderr,
              "storage-metrics could not enable filesystem metrics for %s,"
              " status %d\n",
              path.c_str(), rc);
      return;
    }
  }
  MinfsFidlMetrics metrics;
  rc = GetFsMetrics(path.c_str(), &metrics);
  if (rc == ZX_OK) {
    PrintFsMetrics(metrics, path.c_str());
  } else {
    fprintf(stderr,
            "storage-metrics could not get filesystem metrics for %s,"
            " status %d\n",
            path.c_str(), rc);
    return;
  }
  if (options.enable_fs_metrics == BooleanFlagState::kDisable) {
    rc = EnableFsMetrics(path.c_str(), false);
    if (rc != ZX_OK) {
      fprintf(stderr,
              "storage-metrics could not disable filesystem metrics for %s,"
              " status %d\n",
              path.c_str(), rc);
    }
  }
}

// Retrieves and prints metrics for the block device associated with the filesystem at path.
void RunBlockMetrics(const fbl::StringBuffer<PATH_MAX> path, const StorageMetricOptions options) {
  fbl::unique_fd fd(open(path.c_str(), O_RDONLY | O_ADMIN));
  if (!fd) {
    fd.reset(open(path.c_str(), O_RDONLY));
    if (!fd) {
      fprintf(stderr, "storage-metrics could not open target: %s, errno %d (%s)\n", path.c_str(),
              errno, strerror(errno));
      return;
    }
  }

  char device_buffer[1024];
  size_t path_len;
  zx_status_t status;
  fdio_cpp::FdioCaller caller(std::move(fd));
  zx_status_t io_status = fuchsia_io_DirectoryAdminGetDevicePath(
      caller.borrow_channel(), &status, device_buffer, sizeof(device_buffer) - 1, &path_len);
  const char* device_path = nullptr;
  if (io_status == ZX_OK && status == ZX_OK) {
    device_buffer[path_len] = '\0';
    device_path = device_buffer;
  }

  zx_status_t rc;
  fuchsia_hardware_block_BlockStats stats;
  if (device_path != nullptr) {
    rc = GetBlockMetrics(device_path, options.clear_block, &stats);
    if (rc == ZX_OK) {
      PrintBlockMetrics(device_path, stats);
    } else {
      fprintf(stderr,
              "storage-metrics could not retrieve block metrics for %s,"
              " status %d\n",
              path.c_str(), rc);
    }
  } else {
    // Maybe this is not a filesystem. See if this happens to be a block device.
    // TODO(auradkar): We need better args parsing to consider fs and block
    // device seperately.
    rc = GetBlockMetrics(path.c_str(), options.clear_block, &stats);
    if (rc != ZX_OK) {
      fprintf(stderr,
              "storage-metrics could not retrieve block metrics for %s,"
              " status %d\n",
              path.c_str(), rc);
    }
    PrintBlockMetrics(path.c_str(), stats);
  }
}

}  // namespace

int main(int argc, char** argv) {
  StorageMetricOptions options;
  ParseCommandLineArguments(argc, argv, &options);
  // Iterate through the remaining arguments, which are all paths
  for (int i = optind; i < argc; i++) {
    fbl::StringBuffer<PATH_MAX> path;
    path.Append(argv[i]);

    printf("Metrics for: %s\n", path.c_str());
    RunFsMetrics(path, options);
    RunBlockMetrics(path, options);
    printf("\n");
  }

  return 0;
}
