// Copyright 2022 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/f2fs/f2fs.h"

namespace f2fs {

#ifdef __Fuchsia__
SegmentWriteBuffer::SegmentWriteBuffer(storage::VmoidRegistry *vmoid_registry, size_t blocks,
                                       uint32_t block_size, PageType type) {
  ZX_DEBUG_ASSERT(type < PageType::kNrPageType);
  ZX_ASSERT(buffer_.Initialize(vmoid_registry, blocks, block_size,
                               kVmoBufferLabels[static_cast<uint32_t>(type)].data()) == ZX_OK);
}
#else  // __Fuchsia__
SegmentWriteBuffer::SegmentWriteBuffer(Bcache *bc, size_t blocks, uint32_t block_size,
                                       PageType type)
    : buffer_(blocks, block_size) {}
#endif

PageOperations SegmentWriteBuffer::TakeOperations() {
  std::lock_guard lock(mutex_);
  return PageOperations(builder_.TakeOperations(), std::move(pages_),
                        [this](const PageOperations &op) { ReleaseBuffers(op); });
}

void SegmentWriteBuffer::ReleaseBuffers(const PageOperations &operation) {
  if (!operation.Empty()) {
    // Decrease count_ to allow waiters to reserve buffer_.
    std::lock_guard lock(mutex_);
    count_ = safemath::CheckSub(count_, operation.GetLength()).ValueOrDie();
    cvar_.notify_all();
  }
}

zx::status<size_t> SegmentWriteBuffer::ReserveOperation(storage::Operation &operation,
                                                        LockedPage &page) {
  std::lock_guard lock(mutex_);
  // Wait until there is a room in |buffer_|.
  while (count_ == buffer_.capacity()) {
    if (auto wait_result = cvar_.wait_for(mutex_, kWriteTimeOut);
        wait_result == std::cv_status::timeout) {
      return zx::error(ZX_ERR_TIMED_OUT);
    }
  }

  operation.vmo_offset = start_index_;
  // Copy |page| to |buffer| at |start_index_|.
  if (operation.type == storage::OperationType::kWrite) {
    std::memcpy(buffer_.Data(start_index_), page->GetAddress(), page->BlockSize());
  }
  // Here, |operation| can be merged into a previous operation.
  builder_.Add(operation, &buffer_);
  pages_.push_back(page.release());
  if (++start_index_ == buffer_.capacity()) {
    start_index_ = 0;
  }
  ++count_;
  return zx::ok(pages_.size());
}

SegmentWriteBuffer::~SegmentWriteBuffer() { ZX_DEBUG_ASSERT(pages_.size() == 0); }

Writer::Writer(Bcache *bc) : transaction_handler_(bc) {
  for (const auto type : {PageType::kData, PageType::kNode, PageType::kMeta}) {
    write_buffer_[static_cast<uint32_t>(type)] =
        std::make_unique<SegmentWriteBuffer>(bc, kDefaultBlocksPerSegment, kBlockSize, type);
  }
}

Writer::~Writer() {
  sync_completion_t completion;
  ScheduleSubmitPages(&completion);
  ZX_ASSERT(sync_completion_wait(&completion, ZX_TIME_INFINITE) == ZX_OK);
}

void Writer::EnqueuePage(storage::Operation &operation, LockedPage &page, PageType type) {
  ZX_DEBUG_ASSERT(type < PageType::kNrPageType);
  auto ret = write_buffer_[static_cast<uint32_t>(type)]->ReserveOperation(operation, page);
  if (ret.is_error()) {
    // Should not happen.
    ZX_ASSERT(0);
  } else if (ret.value() >= kDefaultBlocksPerSegment / 2) {
    // Submit Pages once they are merged as much as a half of segment.
    ScheduleSubmitPages(nullptr, type);
  }
}

fpromise::promise<> Writer::SubmitPages(sync_completion_t *completion, PageType type) {
  auto operations = write_buffer_[static_cast<uint32_t>(type)]->TakeOperations();
  if (operations.Empty()) {
    if (completion) {
      return fpromise::make_promise([completion]() { sync_completion_signal(completion); });
    }
    return fpromise::make_ok_promise();
  }
  return fpromise::make_promise(
      [this, completion, type, operations = std::move(operations)]() mutable {
        zx_status_t ret = ZX_OK;
        if (ret = transaction_handler_->RunRequests(operations.TakeOperations()); ret != ZX_OK) {
          FX_LOGS(WARNING) << "[f2fs] RunRequest fails with " << ret;
        }
        operations.Completion([ret, type](fbl::RefPtr<Page> page) {
          if (ret != ZX_OK && page->IsUptodate()) {
            if (type == PageType::kMeta || ret == ZX_ERR_UNAVAILABLE) {
              // When it fails to write metadata or the block device is not available,
              // set kCpErrorFlag to enter read-only mode.
              page->GetVnode().Vfs()->GetSuperblockInfo().SetCpFlags(CpFlag::kCpErrorFlag);
            } else {
              // When IO errors occur with node and data Pages, just set a dirty flag
              // to retry it with another LBA.
              LockedPage locked_page(page);
              locked_page->SetDirty();
            }
          }
          page->ClearWriteback();
          return ret;
        });
        if (completion) {
          sync_completion_signal(completion);
        }
      });
}

void Writer::ScheduleTask(fpromise::pending_task task) {
#ifdef __Fuchsia__
  executor_.schedule_task(std::move(task));
#else   // __Fuchsia__
  auto result = fpromise::run_single_threaded(task.take_promise());
  assert(result.is_ok());
#endif  // __Fuchsia__
}

void Writer::ScheduleSubmitPages(sync_completion_t *completion, PageType type) {
  auto task = (type == PageType::kNrPageType)
                  ? SubmitPages(nullptr, PageType::kData)
                        .then([this](fpromise::result<> &result) {
                          return SubmitPages(nullptr, PageType::kNode);
                        })
                        .then([this, completion](fpromise::result<> &result) {
                          return SubmitPages(completion, PageType::kMeta);
                        })
                  : SubmitPages(completion, type);
  ScheduleTask(std::move(task));
}

}  // namespace f2fs
