/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "common/libs/fs/epoll.h"

#include <sys/epoll.h>

#include <memory>
#include <optional>
#include <set>
#include <shared_mutex>

#include "common/libs/fs/shared_fd.h"
#include "common/libs/utils/result.h"

namespace cuttlefish {

Result<Epoll> Epoll::Create() {
  int fd = epoll_create1(EPOLL_CLOEXEC);
  if (fd == -1) {
    return CF_ERRNO("Failed to create epoll");
  }
  SharedFD shared{std::shared_ptr<FileInstance>(new FileInstance(fd, 0))};
  return Epoll(shared);
}

Epoll::Epoll() = default;

Epoll::Epoll(SharedFD epoll_fd) : epoll_fd_(epoll_fd) {}

Epoll::Epoll(Epoll&& other) {
  std::unique_lock own_watched(watched_mutex_, std::defer_lock);
  std::unique_lock own_epoll(epoll_mutex_, std::defer_lock);
  std::unique_lock other_epoll(other.epoll_mutex_, std::defer_lock);
  std::unique_lock other_watched(other.watched_mutex_, std::defer_lock);
  std::lock(own_watched, own_epoll, other_epoll, other_watched);

  epoll_fd_ = std::move(other.epoll_fd_);
  watched_ = std::move(other.watched_);
}

Epoll& Epoll::operator=(Epoll&& other) {
  std::unique_lock own_watched(watched_mutex_, std::defer_lock);
  std::unique_lock own_epoll(epoll_mutex_, std::defer_lock);
  std::unique_lock other_epoll(other.epoll_mutex_, std::defer_lock);
  std::unique_lock other_watched(other.watched_mutex_, std::defer_lock);
  std::lock(own_watched, own_epoll, other_epoll, other_watched);

  epoll_fd_ = std::move(other.epoll_fd_);
  watched_ = std::move(other.watched_);
  return *this;
}

Result<void> Epoll::Add(SharedFD fd, uint32_t events) {
  std::unique_lock watched_lock(watched_mutex_, std::defer_lock);
  std::shared_lock epoll_lock(epoll_mutex_, std::defer_lock);
  std::lock(watched_lock, epoll_lock);
  CF_EXPECT(epoll_fd_->IsOpen(), "Empty Epoll instance");

  if (watched_.count(fd) != 0) {
    return CF_ERRNO("Watched set already contains fd");
  }
  epoll_event event;
  event.events = events;
  event.data.fd = fd->fd_;
  int success = epoll_ctl(epoll_fd_->fd_, EPOLL_CTL_ADD, fd->fd_, &event);
  if (success != 0 && errno == EEXIST) {
    // We're already tracking this fd, don't drop it from the set.
    return CF_ERRNO("epoll_ctl: File descriptor was already present");
  } else if (success != 0) {
    return CF_ERRNO("epoll_ctl: Add failed");
  }
  watched_.insert(fd);
  return {};
}

Result<void> Epoll::AddOrModify(SharedFD fd, uint32_t events) {
  std::unique_lock watched_lock(watched_mutex_, std::defer_lock);
  std::shared_lock epoll_lock(epoll_mutex_, std::defer_lock);
  std::lock(watched_lock, epoll_lock);
  CF_EXPECT(epoll_fd_->IsOpen(), "Empty Epoll instance");

  epoll_event event;
  event.events = events;
  event.data.fd = fd->fd_;
  int operation = watched_.count(fd) == 0 ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
  int success = epoll_ctl(epoll_fd_->fd_, operation, fd->fd_, &event);
  if (success != 0) {
    std::string operation_str = operation == EPOLL_CTL_ADD ? "add" : "modify";
    return CF_ERRNO("epoll_ctl: Operation " << operation_str << " failed");
  }
  watched_.insert(fd);
  return {};
}

Result<void> Epoll::Modify(SharedFD fd, uint32_t events) {
  std::unique_lock watched_lock(watched_mutex_, std::defer_lock);
  std::shared_lock epoll_lock(epoll_mutex_, std::defer_lock);
  std::lock(watched_lock, epoll_lock);
  CF_EXPECT(epoll_fd_->IsOpen(), "Empty Epoll instance");

  if (watched_.count(fd) == 0) {
    return CF_ERR("Watched set did not contain fd");
  }
  epoll_event event;
  event.events = events;
  event.data.fd = fd->fd_;
  int success = epoll_ctl(epoll_fd_->fd_, EPOLL_CTL_MOD, fd->fd_, &event);
  if (success != 0) {
    return CF_ERRNO("epoll_ctl: Modify failed");
  }
  return {};
}

Result<void> Epoll::Delete(SharedFD fd) {
  std::unique_lock watched_lock(watched_mutex_, std::defer_lock);
  std::shared_lock epoll_lock(epoll_mutex_, std::defer_lock);
  std::lock(watched_lock, epoll_lock);
  CF_EXPECT(epoll_fd_->IsOpen(), "Empty Epoll instance");

  if (watched_.count(fd) == 0) {
    return CF_ERR("Watched set did not contain fd");
  }
  int success = epoll_ctl(epoll_fd_->fd_, EPOLL_CTL_DEL, fd->fd_, nullptr);
  if (success != 0) {
    return CF_ERRNO("epoll_ctl: Delete failed");
  }
  watched_.erase(fd);
  return {};
}

Result<std::optional<EpollEvent>> Epoll::Wait() {
  epoll_event event;
  int success;
  {
    std::shared_lock lock(epoll_mutex_);
    CF_EXPECT(epoll_fd_->IsOpen(), "Empty Epoll instance");
    success = epoll_wait(epoll_fd_->fd_, &event, 1, -1);
  }
  if (success == -1) {
    return CF_ERRNO("epoll_wait failed");
  } else if (success == 0) {
    return {};
  } else if (success != 1) {
    return CF_ERR("epoll_wait returned an unexpected value");
  }
  EpollEvent ret;
  ret.events = event.events;
  std::shared_lock lock(watched_mutex_);
  for (const auto& watched : watched_) {
    if (watched->fd_ == event.data.fd) {
      ret.fd = watched;
      break;
    }
  }
  if (!ret.fd->IsOpen()) {
    // Couldn't find the matching SharedFD to the file descriptor. We probably
    // lost the race to lock watched_mutex_ against a delete call. Treat this
    // as a spurious wakeup.
    return {};
  }
  return ret;
}

}  // namespace cuttlefish
