// Copyright 2019 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/test/integration/load_generator.h"

#include <errno.h>
#include <fcntl.h>

#include <fbl/auto_lock.h>
#include <gtest/gtest.h>

namespace blobfs {

// Make sure we do not exceed maximum fd count.
static_assert(FDIO_MAX_FD >= 256);
constexpr uint32_t kMaxBlobs = FDIO_MAX_FD - 32;

enum class BlobList::QueueId : uint32_t { kCreated = 0, kTruncated, kWritten };

void BlobList::GenerateLoad(uint32_t num_operations, unsigned int* rand_state) {
  auto one_operation = [&]() {
    switch (rand_r(rand_state) % 6) {
      case 0:
        CreateBlob(rand_state);
        break;
      case 1:
        TruncateBlob();
        break;
      case 2:
        WriteData();
        break;
      case 3:
        ReadData();
        break;
      case 4:
        ReopenBlob();
        break;
      case 5:
        UnlinkBlob(rand_state);
        break;
    }
  };
  for (uint32_t i = 0; i < num_operations; ++i) {
    ASSERT_NO_FATAL_FAILURE(one_operation());
  }
}

void BlobList::VerifyFiles() {
  fbl::AutoLock al(&list_lock_);
  for (auto it = lists_[static_cast<uint32_t>(QueueId::kWritten)].begin();
       it != lists_[static_cast<uint32_t>(QueueId::kWritten)].end(); ++it) {
    it->fd.reset(open(it->info->path, O_RDONLY));
    ASSERT_NO_FATAL_FAILURE(
        VerifyContents(it->fd.get(), it->info->data.get(), it->info->size_data));
  }
}

void BlobList::CloseFiles() {
  CloseFilesFromQueue(QueueId::kCreated);
  CloseFilesFromQueue(QueueId::kTruncated);
  CloseFilesFromQueue(QueueId::kWritten);
}

BlobFile BlobList::GetFileFrom(QueueId queue) {
  BlobFile file;
  fbl::AutoLock al(&list_lock_);
  if (lists_[static_cast<uint32_t>(queue)].empty()) {
    return file;
  }

  file = std::move(lists_[static_cast<uint32_t>(queue)].front());
  lists_[static_cast<uint32_t>(queue)].pop_front();
  return file;
}

void BlobList::PushFileInto(QueueId queue, BlobFile file) {
  fbl::AutoLock al(&list_lock_);
  lists_[static_cast<uint32_t>(queue)].push_back(std::move(file));
}

BlobList::QueueId BlobList::GetRandomQueue(unsigned int* rand_state) const {
  uint32_t value = rand_r(rand_state) % static_cast<uint32_t>(QueueId::kWritten);
  return static_cast<QueueId>(value);
}

void BlobList::CloseFilesFromQueue(QueueId queue) {
  fbl::AutoLock al(&list_lock_);
  for (auto it = lists_[static_cast<uint32_t>(queue)].begin();
       it != lists_[static_cast<uint32_t>(queue)].end(); ++it) {
    it->fd.reset();
  }
}

void BlobList::CreateBlob(unsigned int* rand_state, size_t num_writes) {
  std::unique_ptr<BlobInfo> info =
      GenerateRandomBlob(mount_path_, 1 + (rand_r(rand_state) % (1 << 16)));

  BlobFile file(std::move(info), num_writes);

  file.fd.reset(open(file.info->path, O_CREAT | O_RDWR));
  ASSERT_TRUE(file.fd);

  {
    fbl::AutoLock al(&list_lock_);

    if (blob_count_ < kMaxBlobs) {
      lists_[static_cast<uint32_t>(QueueId::kCreated)].push_back(std::move(file));
      blob_count_++;
    }
  }

  if (file.info) {
    // Failed to insert.
    ASSERT_EQ(0, unlink(file.info->path));
  }
}

void BlobList::TruncateBlob() {
  BlobFile file = GetFileFrom(QueueId::kCreated);
  if (!file.info) {
    return;
  }

  // If we are going to run out of space on the underlying blobfs partition, the
  // ZX_ERR_NO_SPACE is going to come up here. if we run out of space, put the
  // kEmpty blob back onto the blob list.
  if (ftruncate(file.fd.get(), file.info->size_data) != 0) {
    ASSERT_EQ(errno, ENOSPC) << "ftruncate returned an unrecoverable error";
  }

  PushFileInto(QueueId::kTruncated, std::move(file));
}

void BlobList::WriteData() {
  BlobFile file = GetFileFrom(QueueId::kTruncated);
  if (!file.info) {
    return;
  }

  size_t to_write = file.bytes_remaining / file.writes_remaining;
  size_t bytes_offset = file.info->size_data - file.bytes_remaining;
  ASSERT_EQ(write(file.fd.get(), file.info->data.get() + bytes_offset, to_write),
            static_cast<ssize_t>(to_write));

  file.writes_remaining--;
  file.bytes_remaining -= to_write;

  if (file.bytes_remaining == 0) {
    PushFileInto(QueueId::kWritten, std::move(file));
  } else {
    PushFileInto(QueueId::kTruncated, std::move(file));
  }
}

void BlobList::ReadData() {
  BlobFile file = GetFileFrom(QueueId::kWritten);
  if (!file.info) {
    return;
  }

  ASSERT_NO_FATAL_FAILURE(
      VerifyContents(file.fd.get(), file.info->data.get(), file.info->size_data));

  PushFileInto(QueueId::kWritten, std::move(file));
}

void BlobList::UnlinkBlob(unsigned int* rand_state) {
  QueueId queue = GetRandomQueue(rand_state);
  BlobFile file = GetFileFrom(queue);
  if (!file.info) {
    return;
  }

  ASSERT_EQ(0, unlink(file.info->path));
  file.fd.reset();
  {
    fbl::AutoLock al(&list_lock_);
    blob_count_--;
  }
}

void BlobList::ReopenBlob() {
  BlobFile file = GetFileFrom(QueueId::kWritten);
  if (!file.info) {
    return;
  }

  file.fd.reset(open(file.info->path, O_RDONLY));
  ASSERT_TRUE(file.fd);

  PushFileInto(QueueId::kWritten, std::move(file));
}

}  // namespace blobfs
