// Copyright 2020 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 "src/storage/blobfs/transfer_buffer.h"

#include <lib/syslog/cpp/macros.h>

#include "src/lib/storage/vfs/cpp/trace.h"

namespace blobfs {

StorageBackedTransferBuffer::StorageBackedTransferBuffer(zx::vmo vmo, size_t size,
                                                         storage::OwnedVmoid vmoid,
                                                         TransactionManager* txn_manager,
                                                         BlockIteratorProvider* block_iter_provider,
                                                         BlobfsMetrics* metrics)
    : txn_manager_(txn_manager),
      block_iter_provider_(block_iter_provider),
      vmo_(std::move(vmo)),
      size_(size),
      vmoid_(std::move(vmoid)),
      metrics_(metrics) {}

zx::status<std::unique_ptr<StorageBackedTransferBuffer>> StorageBackedTransferBuffer::Create(
    size_t size, TransactionManager* txn_manager, BlockIteratorProvider* block_iter_provider,
    BlobfsMetrics* metrics) {
  ZX_DEBUG_ASSERT(metrics != nullptr && txn_manager != nullptr && block_iter_provider != nullptr);
  if (size % kBlobfsBlockSize != 0 || size % PAGE_SIZE != 0) {
    return zx::error(ZX_ERR_INVALID_ARGS);
  }
  zx::vmo vmo;
  zx_status_t status = zx::vmo::create(size, 0, &vmo);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Cannot create pager transfer buffer: " << zx_status_get_string(status);
    return zx::error(status);
  }
  storage::OwnedVmoid vmoid(txn_manager);
  status = vmoid.AttachVmo(vmo);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to attach pager transfer vmo: " << zx_status_get_string(status);
    return zx::error(status);
  }

  return zx::ok(std::unique_ptr<StorageBackedTransferBuffer>(new StorageBackedTransferBuffer(
      std::move(vmo), size, std::move(vmoid), txn_manager, block_iter_provider, metrics)));
}

zx::status<> StorageBackedTransferBuffer::Populate(uint64_t offset, uint64_t length,
                                                   const LoaderInfo& info) {
  // Currently our block size is saved as a variable in some places and uses a constant in others.
  // These should always match.
  ZX_ASSERT(info.layout->blobfs_block_size() == kBlobfsBlockSize);

  fs::Ticker ticker(metrics_->Collecting());
  if (offset % kBlobfsBlockSize != 0) {
    // The block math below relies on the offset being block-aligned.
    return zx::error(ZX_ERR_INVALID_ARGS);
  }

  auto block_iter = block_iter_provider_->BlockIteratorByNodeIndex(info.node_index);
  if (block_iter.is_error()) {
    return block_iter.take_error();
  }

  auto start_block = static_cast<uint32_t>((info.layout->DataOffset() + offset) / kBlobfsBlockSize);
  auto block_count =
      static_cast<uint32_t>(fbl::round_up(length, kBlobfsBlockSize) / kBlobfsBlockSize);

  TRACE_DURATION("blobfs", "StorageBackedTransferBuffer::Populate", "offset",
                 start_block * kBlobfsBlockSize, "length", block_count * kBlobfsBlockSize);

  // Navigate to the start block.
  zx_status_t status = IterateToBlock(&block_iter.value(), start_block);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to navigate to start block " << start_block << ": "
                   << zx_status_get_string(status);
    return zx::error(status);
  }

  std::vector<storage::BufferedOperation> operations;
  // Enqueue operations to read in the required blocks to the transfer buffer.
  const uint64_t data_start = DataStartBlock(txn_manager_->Info());
  status = StreamBlocks(&block_iter.value(), block_count,
                        [&](uint64_t vmo_offset, uint64_t dev_offset, uint32_t length) {
                          operations.push_back({.vmoid = vmoid_.get(),
                                                .op = {
                                                    .type = storage::OperationType::kRead,
                                                    .vmo_offset = vmo_offset - start_block,
                                                    .dev_offset = dev_offset + data_start,
                                                    .length = length,
                                                }});
                          return ZX_OK;
                        });
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to enqueue read operations: " << zx_status_get_string(status);
    return zx::error(status);
  }

  // Issue the read.
  status = txn_manager_->RunRequests(operations);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to transact read operations: " << zx_status_get_string(status);
    return zx::error(status);
  }

  // Update read metrics
  if (info.decompressor == nullptr) {
    metrics_->paged_read_metrics().IncrementDiskRead(CompressionAlgorithm::kUncompressed,
                                                     block_count * kBlobfsBlockSize, ticker.End());
  } else {
    metrics_->paged_read_metrics().IncrementDiskRead(info.decompressor->algorithm(),
                                                     block_count * kBlobfsBlockSize, ticker.End());
  }
  return zx::ok();
}

}  // namespace blobfs
