// 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.

#ifndef SRC_STORAGE_F2FS_STORAGE_BUFFER_H_
#define SRC_STORAGE_F2FS_STORAGE_BUFFER_H_

namespace f2fs {

class VmoBufferKey : public fbl::DoublyLinkedListable<std::unique_ptr<VmoBufferKey>> {
 public:
  VmoBufferKey(const uint64_t offset) : vmo_offset_(offset) {}
  VmoBufferKey() = delete;
  VmoBufferKey(const VmoBufferKey &) = delete;
  VmoBufferKey &operator=(const VmoBufferKey &) = delete;
  VmoBufferKey(const VmoBufferKey &&) = delete;
  VmoBufferKey &operator=(const VmoBufferKey &&) = delete;
  uint64_t GetKey() const { return vmo_offset_; }

 private:
  const uint64_t vmo_offset_;
};

class StorageOperations;
using VmoKeyList = fbl::SizedDoublyLinkedList<std::unique_ptr<VmoBufferKey>>;

// StorageBuffer implements an allocator for pre-allocated vmo buffers attached to a VmoidRegistry
// object. When there are available buffers in the free list, allocation operations are O(1). If the
// free list is empty, a caller waits for buffers. Free operations are O(1) as well.
class StorageBuffer {
 public:
  // StorageBuffer reserves vmo buffers in |allocation_unit|. Therefore, |allocation_unit| should be
  // bigger than the number of pages requested in |ReserveWriteOperation| or |ReserveReadOperations|
  // to get the maximum performance. It should be also smaller than |blocks|, because |blocks| is
  // the total size of vmo buffers.
  StorageBuffer(BcacheMapper *bc, size_t blocks, uint32_t block_size, std::string_view label,
                uint32_t allocation_unit = 1);
  StorageBuffer() = delete;
  StorageBuffer(const StorageBuffer &) = delete;
  StorageBuffer &operator=(const StorageBuffer &) = delete;
  StorageBuffer(const StorageBuffer &&) = delete;
  StorageBuffer &operator=(const StorageBuffer &&) = delete;
  ~StorageBuffer();

  // It tries to reserve |buffer_| for |page| for writeback. If successful,
  // it copies the contents of |page| to the reserved buffer.
  zx::result<size_t> ReserveWriteOperation(Page &page) __TA_EXCLUDES(mutex_);
  // It returns StorageOperations from |reserved_keys_| and |builder| for writeback.
  StorageOperations TakeWriteOperations() __TA_EXCLUDES(mutex_);

  // It tries to reserve |buffer_| for read I/Os. If successful, it returns StorageOpeartions that
  // convey BufferedOperations to read blocks for |addrs|.
  zx::result<StorageOperations> MakeReadOperations(const std::vector<block_t> &addrs)
      __TA_EXCLUDES(mutex_);

  void ReleaseBuffers(const StorageOperations &operation) __TA_EXCLUDES(mutex_);
  const void *Data(const size_t offset) const {
    ZX_ASSERT(offset < buffer_.capacity());
    return buffer_.Data(offset);
  }

 private:
  void Init() __TA_EXCLUDES(mutex_);
  const uint64_t max_blocks_;
  const uint32_t allocation_unit_;
  storage::VmoBuffer buffer_;
  fs::BufferedOperationsBuilder builder_ __TA_GUARDED(mutex_);
  VmoKeyList free_keys_ __TA_GUARDED(mutex_);
  VmoKeyList reserved_keys_ __TA_GUARDED(mutex_);
  std::condition_variable_any cvar_;
  std::shared_mutex mutex_;
};

using OperationCallback = fit::function<void(const StorageOperations &, zx_status_t status)>;
// A utility class, holding a collection of write requests with data buffers of
// StorageBuffer, ready to be transmitted to persistent storage.
class StorageOperations {
 public:
  StorageOperations() = delete;
  StorageOperations(StorageBuffer &buffer, fs::BufferedOperationsBuilder &operations,
                    VmoKeyList &keys)
      : buffer_(buffer), operations_(operations.TakeOperations()), keys_(std::move(keys)) {}
  StorageOperations(const StorageOperations &operations) = delete;
  StorageOperations &operator=(const StorageOperations &) = delete;
  StorageOperations(const StorageOperations &&op) = delete;
  StorageOperations &operator=(const StorageOperations &&) = delete;
  StorageOperations(StorageOperations &&op) = default;
  StorageOperations &operator=(StorageOperations &&) = delete;
  ~StorageOperations() { ZX_DEBUG_ASSERT(keys_.is_empty()); }

  std::vector<storage::BufferedOperation> TakeOperations() { return std::move(operations_); }

  // When StorageOperations complete, Reader or Writer should call it to release storage
  // buffers and handle the IO completion in |callback|.
  zx_status_t Completion(zx_status_t io_status, OperationCallback callback) {
    callback(*this, io_status);
    buffer_.ReleaseBuffers(*this);
    return io_status;
  }
  bool IsEmpty() const { return keys_.is_empty(); }
  VmoKeyList TakeVmoKeys() const { return std::move(keys_); }
  VmoKeyList &VmoKeys() const { return keys_; }

 private:
  StorageBuffer &buffer_;
  std::vector<storage::BufferedOperation> operations_;
  mutable VmoKeyList keys_;
};

}  // namespace f2fs

#endif  // SRC_STORAGE_F2FS_STORAGE_BUFFER_H_
