// 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/blob_loader.h"

#include <lib/fit/defer.h>
#include <lib/fzl/owned-vmo-mapper.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/status.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include <algorithm>
#include <memory>
#include <vector>

#include <fbl/string_buffer.h>
#include <storage/buffer/owned_vmoid.h>

#include "src/lib/digest/digest.h"
#include "src/lib/storage/vfs/cpp/trace.h"
#include "src/lib/storage/vfs/cpp/transaction/buffered_operations_builder.h"
#include "src/storage/blobfs/blob_layout.h"
#include "src/storage/blobfs/blob_verifier.h"
#include "src/storage/blobfs/common.h"
#include "src/storage/blobfs/compression/chunked.h"
#include "src/storage/blobfs/compression/decompressor.h"
#include "src/storage/blobfs/compression/seekable_decompressor.h"
#include "src/storage/blobfs/compression_settings.h"
#include "src/storage/blobfs/format.h"
#include "src/storage/blobfs/iterator/block_iterator.h"
#include "src/storage/blobfs/transfer_buffer.h"
#include "storage/operation/operation.h"

namespace blobfs {

namespace {

// TODO(jfsulliv): Rationalize this with the size limits for chunk-compression headers.
constexpr size_t kChunkedHeaderSize = 4 * kBlobfsBlockSize;

}  // namespace

BlobLoader::BlobLoader(TransactionManager* txn_manager, BlockIteratorProvider* block_iter_provider,
                       NodeFinder* node_finder, std::shared_ptr<BlobfsMetrics> metrics,
                       storage::ResizeableVmoBuffer read_mapper, zx::vmo sandbox_vmo,
                       std::unique_ptr<ExternalDecompressorClient> decompressor_client)
    : txn_manager_(txn_manager),
      block_iter_provider_(block_iter_provider),
      node_finder_(node_finder),
      metrics_(std::move(metrics)),
      read_mapper_(std::move(read_mapper)),
      sandbox_vmo_(std::move(sandbox_vmo)),
      decompressor_client_(std::move(decompressor_client)) {}

BlobLoader::~BlobLoader() { [[maybe_unused]] auto status = read_mapper_.Detach(txn_manager_); }

zx::status<std::unique_ptr<BlobLoader>> BlobLoader::Create(
    TransactionManager* txn_manager, BlockIteratorProvider* block_iter_provider,
    NodeFinder* node_finder, std::shared_ptr<BlobfsMetrics> metrics,
    DecompressorCreatorConnector* decompression_connector) {
  auto read_mapper = storage::ResizeableVmoBuffer(txn_manager->Info().block_size);
  if (auto status = read_mapper.Attach("blobfs-loader", txn_manager); status.is_error()) {
    FX_LOGS(ERROR) << "blobfs: Failed to attach read vmo: " << status.status_string();
    return status.take_error();
  }
  zx::vmo sandbox_vmo;
  std::unique_ptr<ExternalDecompressorClient> decompressor_client = nullptr;
  if (decompression_connector) {
    if (auto status = zx::vmo::create(kDecompressionBufferSize, 0, &sandbox_vmo); status != ZX_OK) {
      return zx::error(status);
    }
    const char* name = "blobfs-sandbox";
    sandbox_vmo.set_property(ZX_PROP_NAME, name, strlen(name));
    zx::status<std::unique_ptr<ExternalDecompressorClient>> client_or =
        ExternalDecompressorClient::Create(decompression_connector, sandbox_vmo, read_mapper.vmo());
    if (!client_or.is_ok()) {
      return client_or.take_error();
    } else {
      decompressor_client = std::move(client_or.value());
    }
  }
  return zx::ok(std::unique_ptr<BlobLoader>(new BlobLoader(
      txn_manager, block_iter_provider, node_finder, std::move(metrics), std::move(read_mapper),
      std::move(sandbox_vmo), std::move(decompressor_client))));
}

zx::status<LoaderInfo> BlobLoader::LoadBlob(uint32_t node_index,
                                            const BlobCorruptionNotifier* corruption_notifier) {
  ZX_DEBUG_ASSERT(read_mapper_.vmo().is_valid());
  auto inode = node_finder_->GetNode(node_index);
  if (inode.is_error()) {
    return inode.take_error();
  }

  // LoadBlob should only be called for nonempty Inodes. If this doesn't hold, one of two things
  // happened:
  //   - Programmer error
  //   - Corruption of a blob's Inode
  // In either case it is preferable to ASSERT than to return an error here, since the first case
  // should happen only during development and in the second case there may be more corruption and
  // we want to unmount the filesystem before any more damage is done.
  ZX_ASSERT_MSG(inode->header.IsInode() && inode->header.IsAllocated(),
                "LoadBlob failed as inode->header.IsInode():%u inode->header.IsAllocated():%u",
                inode->header.IsInode(), inode->header.IsAllocated());
  ZX_ASSERT_MSG(inode->blob_size > 0, "Inode blob size should be greater than zero: %lu",
                inode->blob_size);
  TRACE_DURATION("blobfs", "BlobLoader::LoadBlob", "blob_size", inode->blob_size);

  // Create and save the layout.
  auto blob_layout_or = BlobLayout::CreateFromInode(GetBlobLayoutFormat(txn_manager_->Info()),
                                                    *inode.value(), GetBlockSize());
  if (blob_layout_or.is_error()) {
    FX_LOGS(ERROR) << "Failed to create blob layout: "
                   << zx_status_get_string(blob_layout_or.error_value());
    return blob_layout_or.take_error();
  }
  ZX_ASSERT(blob_layout_or->FileSize() == inode->blob_size);

  LoaderInfo result;
  result.node_index = node_index;
  result.layout = std::move(blob_layout_or.value());

  auto decommit_used = fit::defer([this] { Decommit(); });

  auto verifier_or =
      CreateBlobVerifier(node_index, *inode.value(), *result.layout, corruption_notifier);
  if (verifier_or.is_error())
    return verifier_or.take_error();
  result.verifier = std::move(verifier_or.value());

  if (zx_status_t status = InitForDecompression(node_index, *inode.value(), *result.layout,
                                                *result.verifier, &result.decompressor);
      status != ZX_OK) {
    return zx::error(status);
  }

  return zx::ok(std::move(result));
}

zx::status<std::unique_ptr<BlobVerifier>> BlobLoader::CreateBlobVerifier(
    uint32_t node_index, const Inode& inode, const BlobLayout& blob_layout,
    const BlobCorruptionNotifier* notifier) {
  if (blob_layout.MerkleTreeSize() == 0) {
    return BlobVerifier::CreateWithoutTree(digest::Digest(inode.merkle_root_hash), metrics_,
                                           inode.blob_size, notifier);
  }

  std::unique_ptr<BlobVerifier> verifier;

  if (auto blocks = LoadBlocks(node_index, blob_layout.MerkleTreeBlockOffset(),
                               blob_layout.MerkleTreeBlockCount());
      blocks.is_error()) {
    FX_LOGS(ERROR) << "Failed to load Merkle tree: " << blocks.status_string();
    return blocks.take_error();
  } else {
    return BlobVerifier::Create(digest::Digest(inode.merkle_root_hash), metrics_, *blocks,
                                blob_layout, notifier);
  }
}

zx_status_t BlobLoader::InitForDecompression(
    uint32_t node_index, const Inode& inode, const BlobLayout& blob_layout,
    const BlobVerifier& verifier, std::unique_ptr<SeekableDecompressor>* decompressor_out) {
  zx::status<CompressionAlgorithm> algorithm_status = AlgorithmForInode(inode);
  if (algorithm_status.is_error()) {
    FX_LOGS(ERROR) << "Cannot decode blob due to invalid compression flags.";
    return algorithm_status.status_value();
  }

  if (algorithm_status.value() == CompressionAlgorithm::kUncompressed)
    return ZX_OK;

  TRACE_DURATION("blobfs", "BlobLoader::InitDecompressor");

  // The first few blocks of data contain the seek table, which we need to read to initialize the
  // decompressor. Read these from disk.

  // We don't know exactly how long the header is, so we generally overshoot.
  // (The header should never be bigger than the size of the kChunkedHeaderSize.)
  ZX_DEBUG_ASSERT(kChunkedHeaderSize % GetBlockSize() == 0);
  uint32_t header_block_count = static_cast<uint32_t>(kChunkedHeaderSize) / GetBlockSize();
  uint32_t blocks_to_read = std::min(header_block_count, blob_layout.DataBlockCount());
  if (blocks_to_read == 0) {
    FX_LOGS(ERROR) << "No data blocks; corrupted inode?";
    return ZX_ERR_BAD_STATE;
  }

  cpp20::span<const uint8_t> bytes;
  if (auto bytes_or = LoadBlocks(node_index, blob_layout.DataBlockOffset(), blocks_to_read);
      bytes_or.is_error()) {
    FX_LOGS(ERROR) << "Failed to load compression header: " << bytes_or.status_string();
    return bytes_or.error_value();
  } else {
    uint64_t max_data_size = blob_layout.DataSizeUpperBound();
    if (bytes_or->size() > max_data_size) {
      bytes = bytes_or->subspan(0, max_data_size);
    } else {
      bytes = *bytes_or;
    }
  }

  if (zx_status_t status = SeekableChunkedDecompressor::CreateDecompressor(
          bytes,
          /*max_compressed_size=*/blob_layout.DataSizeUpperBound(), decompressor_out);
      status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to init decompressor: " << zx_status_get_string(status);
    return status;
  }

  return ZX_OK;
}

zx::status<cpp20::span<const uint8_t>> BlobLoader::LoadBlocks(uint32_t node_index,
                                                              uint32_t block_offset,
                                                              uint32_t block_count) {
  TRACE_DURATION("blobfs", "BlobLoader::LoadBlocks", "block_count", block_count);

  if (block_count > read_mapper_.capacity()) {
    if (auto status = read_mapper_.Grow(block_count); status.is_error()) {
      FX_LOGS(ERROR) << "Failed to grow buffer: " << status.status_string();
      return status.take_error();
    }
  }

  zx_status_t status;

  const uint64_t kDataStart = DataStartBlock(txn_manager_->Info());
  auto block_iter = block_iter_provider_->BlockIteratorByNodeIndex(node_index);
  if (block_iter.is_error()) {
    return block_iter.take_error();
  }
  if ((status = IterateToBlock(&block_iter.value(), block_offset)) != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to seek to starting block: " << zx_status_get_string(status);
    return zx::error(status);
  }
  std::vector<storage::BufferedOperation> operations;

  status = StreamBlocks(&block_iter.value(), block_count,
                        [&](uint64_t vmo_offset, uint64_t dev_offset, uint32_t length) {
                          operations.push_back({.vmoid = read_mapper_.GetHandle(),
                                                .op = {
                                                    .type = storage::OperationType::kRead,
                                                    .vmo_offset = vmo_offset - block_offset,
                                                    .dev_offset = kDataStart + dev_offset,
                                                    .length = length,
                                                }});
                          return ZX_OK;
                        });

  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to stream blocks: " << zx_status_get_string(status);
    return zx::error(status);
  }
  status = txn_manager_->RunRequests(operations);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to flush read transaction: " << zx_status_get_string(status);
    return zx::error(status);
  }

  return zx::ok(cpp20::span(static_cast<const uint8_t*>(read_mapper_.Data(0)),
                            uint64_t{block_count} * GetBlockSize()));
}

uint32_t BlobLoader::GetBlockSize() const { return txn_manager_->Info().block_size; }

void BlobLoader::Decommit() {
  // Ignore errors.
  [[maybe_unused]] zx_status_t status = read_mapper_.vmo().op_range(
      ZX_VMO_OP_DECOMMIT, 0, read_mapper_.capacity() * GetBlockSize(), nullptr, 0);
}

}  // namespace blobfs
