/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 "EvictionController.hpp"

#include <chrono>

#include <boost/thread/lock_types.hpp>

#include "CacheImpl.hpp"
#include "CacheRegionHelper.hpp"
#include "DistributedSystem.hpp"
#include "RegionInternal.hpp"
#include "util/Log.hpp"

namespace {
const char* const NC_EC_Thread = "NC EC Thread";
const std::chrono::seconds EVICTION_TIMEOUT{1};
}  // namespace

namespace apache {
namespace geode {
namespace client {

EvictionController::EvictionController(int64_t max_heap_size,
                                       int64_t heap_size_delta,
                                       CacheImpl* cache)
    : cache_{cache},
      running_{false},
      max_heap_size_{max_heap_size << 20ULL},
      heap_size_delta_{heap_size_delta / 100.0f},
      heap_size_{0} {
  LOGINFO("Maximum heap size for Heap LRU set to %ld bytes", max_heap_size_);
}

void EvictionController::start() {
  running_ = true;
  thread_ = std::thread(&EvictionController::svc, this);

  LOGFINE("Eviction Controller started");
}

void EvictionController::stop() {
  running_ = false;
  cv_.notify_one();
  thread_.join();

  regions_.clear();
  LOGFINE("Eviction controller stopped");
}

void EvictionController::svc() {
  std::mutex mutex;
  DistributedSystemImpl::setThreadName(NC_EC_Thread);

  while (running_) {
    {
      std::unique_lock<std::mutex> lock(mutex);
      cv_.wait(lock,
               [this] { return !running_ || heap_size_ > max_heap_size_; });
    }

    checkHeapSize();
  }
}

void EvictionController::incrementHeapSize(int64_t delta) {
  heap_size_ += delta;
  cv_.notify_one();

  // We could block here if we wanted to prevent any further memory use
  // until the evictions had been completed.
}

void EvictionController::checkHeapSize() {
  int64_t heap_size = heap_size_;
  if (heap_size <= max_heap_size_) {
    return;
  }

  float percentage =
      static_cast<float>(heap_size - max_heap_size_) / max_heap_size_ +
      heap_size_delta_;

  LOGFINE(
      "EvictionController::process_delta: evicting %.03f%% of the entries. "
      "Heap size is: %lld / %lld",
      percentage * 100.0f, heap_size, max_heap_size_);

  evict(percentage);
}

void EvictionController::registerRegion(const std::string& name) {
  boost::unique_lock<decltype(regions_mutex_)> lock(regions_mutex_);
  if (regions_.insert(name).second) {
    LOGFINE("Registered region with Heap LRU eviction controller: name is " +
            name);
  }
}

void EvictionController::unregisterRegion(const std::string& name) {
  boost::unique_lock<decltype(regions_mutex_)> lock(regions_mutex_);
  if (regions_.erase(name) > 0) {
    LOGFINE("Deregistered region with Heap LRU eviction controller: name is " +
            name);
  }
}

void EvictionController::evict(float percentage) {
  // TODO:  Shouldn't we take the CacheImpl::m_regions
  // lock here? Otherwise we might invoke eviction on a region
  // that has been destroyed or is being destroyed.
  // Its important to not hold this lock for too long
  // because it prevents new regions from getting created or destroyed
  // On the flip side, this requires a copy of the registered region list
  // every time eviction is ordered and that might not be cheap
  //@TODO: Discuss with team

  std::vector<std::string> regions;
  {
    boost::shared_lock<decltype(regions_mutex_)> lock(regions_mutex_);
    regions.reserve(regions_.size());
    regions.insert(regions.end(), regions_.begin(), regions_.end());
  }

  for (const auto& regionName : regions) {
    if (auto region = std::dynamic_pointer_cast<RegionInternal>(
            cache_->getRegion(regionName))) {
      region->evict(percentage);
    }
  }
}

}  // namespace client
}  // namespace geode
}  // namespace apache
