/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2019,  Regents of the University of California,
 *                           Arizona Board of Regents,
 *                           Colorado State University,
 *                           University Pierre & Marie Curie, Sorbonne University,
 *                           Washington University in St. Louis,
 *                           Beijing Institute of Technology,
 *                           The University of Memphis.
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "asf-measurements.hpp"

namespace nfd {
namespace fw {
namespace asf {

NFD_LOG_INIT(AsfMeasurements);

const RttStats::Rtt RttStats::RTT_TIMEOUT(-1.0);
const RttStats::Rtt RttStats::RTT_NO_MEASUREMENT(0.0);
const double RttStats::ALPHA = 0.125;

RttStats::RttStats()
  : m_srtt(RTT_NO_MEASUREMENT)
  , m_rtt(RTT_NO_MEASUREMENT)
{
}

void
RttStats::addRttMeasurement(RttEstimator::Duration& durationRtt)
{
  m_rtt = static_cast<RttStats::Rtt>(durationRtt.count());

  m_rttEstimator.addMeasurement(durationRtt);

  m_srtt = computeSrtt(m_srtt, m_rtt);
}

RttStats::Rtt
RttStats::computeSrtt(Rtt previousSrtt, Rtt currentRtt)
{
  if (previousSrtt == RTT_NO_MEASUREMENT) {
    return currentRtt;
  }

  return Rtt(ALPHA * currentRtt + (1 - ALPHA) * previousSrtt);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

FaceInfo::FaceInfo()
  : m_isTimeoutScheduled(false)
  , m_nSilentTimeouts(0)
{
}

FaceInfo::~FaceInfo()
{
  cancelTimeoutEvent();
  scheduler::cancel(m_measurementExpirationId);
}

void
FaceInfo::setTimeoutEvent(const scheduler::EventId& id, const Name& interestName)
{
  if (!m_isTimeoutScheduled) {
    m_timeoutEventId = id;
    m_isTimeoutScheduled = true;
    m_lastInterestName = interestName;
  }
  else {
    NDN_THROW(FaceInfo::Error("Tried to schedule a timeout for a face that already has a timeout scheduled"));
  }
}

void
FaceInfo::cancelTimeoutEvent()
{
  scheduler::cancel(m_timeoutEventId);
  m_isTimeoutScheduled = false;
}

void
FaceInfo::cancelTimeoutEvent(const Name& prefix)
{
  if (isTimeoutScheduled() && doesNameMatchLastInterest(prefix)) {
    cancelTimeoutEvent();
  }
}

bool
FaceInfo::doesNameMatchLastInterest(const Name& name)
{
  return m_lastInterestName.isPrefixOf(name);
}

void
FaceInfo::recordRtt(const shared_ptr<pit::Entry>& pitEntry, const Face& inFace)
{
  // Calculate RTT
  pit::OutRecordCollection::const_iterator outRecord = pitEntry->getOutRecord(inFace, 0);

  if (outRecord == pitEntry->out_end()) { // no out-record
    NFD_LOG_TRACE(pitEntry->getInterest() << " dataFrom inFace=" << inFace.getId() << " no-out-record");
    return;
  }

  time::steady_clock::Duration steadyRtt = time::steady_clock::now() - outRecord->getLastRenewed();
  RttEstimator::Duration durationRtt = time::duration_cast<RttEstimator::Duration>(steadyRtt);

  m_rttStats.addRttMeasurement(durationRtt);

  NFD_LOG_TRACE("Recording RTT for FaceId: " << inFace.getId()
                                             << " RTT: "    << m_rttStats.getRtt()
                                             << " SRTT: "   << m_rttStats.getSrtt());
}

void
FaceInfo::recordTimeout(const Name& interestName)
{
  m_rttStats.recordTimeout();
  cancelTimeoutEvent(interestName);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

NamespaceInfo::NamespaceInfo()
  : m_isProbingDue(false)
  , m_hasFirstProbeBeenScheduled(false)
{
}

FaceInfo*
NamespaceInfo::getFaceInfo(const fib::Entry& fibEntry, FaceId faceId)
{
  FaceInfoTable::iterator it = m_fit.find(faceId);

  if (it != m_fit.end()) {
    return &it->second;
  }
  else {
    return nullptr;
  }
}

FaceInfo&
NamespaceInfo::getOrCreateFaceInfo(const fib::Entry& fibEntry, FaceId faceId)
{
  FaceInfoTable::iterator it = m_fit.find(faceId);

  FaceInfo* info = nullptr;

  if (it == m_fit.end()) {
    const auto& pair = m_fit.emplace(faceId, FaceInfo());
    info = &pair.first->second;

    extendFaceInfoLifetime(*info, faceId);
  }
  else {
    info = &it->second;
  }

  return *info;
}

void
NamespaceInfo::expireFaceInfo(FaceId faceId)
{
  m_fit.erase(faceId);
}

void
NamespaceInfo::extendFaceInfoLifetime(FaceInfo& info, FaceId faceId)
{
  // Cancel previous expiration
  scheduler::cancel(info.getMeasurementExpirationEventId());

  // Refresh measurement
  auto id = scheduler::schedule(AsfMeasurements::MEASUREMENTS_LIFETIME, [=] { expireFaceInfo(faceId); });
  info.setMeasurementExpirationEventId(id);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

constexpr time::microseconds AsfMeasurements::MEASUREMENTS_LIFETIME;

AsfMeasurements::AsfMeasurements(MeasurementsAccessor& measurements)
  : m_measurements(measurements)
{
}

FaceInfo*
AsfMeasurements::getFaceInfo(const fib::Entry& fibEntry, const Interest& interest, FaceId faceId)
{
  NamespaceInfo& info = getOrCreateNamespaceInfo(fibEntry, interest);
  return info.getFaceInfo(fibEntry, faceId);
}

FaceInfo&
AsfMeasurements::getOrCreateFaceInfo(const fib::Entry& fibEntry, const Interest& interest,
                                     FaceId faceId)
{
  NamespaceInfo& info = getOrCreateNamespaceInfo(fibEntry, interest);
  return info.getOrCreateFaceInfo(fibEntry, faceId);
}

NamespaceInfo*
AsfMeasurements::getNamespaceInfo(const Name& prefix)
{
  measurements::Entry* me = m_measurements.findLongestPrefixMatch(prefix);
  if (me == nullptr) {
    return nullptr;
  }

  // Set or update entry lifetime
  extendLifetime(*me);

  NamespaceInfo* info = me->insertStrategyInfo<NamespaceInfo>().first;
  BOOST_ASSERT(info != nullptr);
  return info;
}

NamespaceInfo&
AsfMeasurements::getOrCreateNamespaceInfo(const fib::Entry& fibEntry, const Interest& interest)
{
  measurements::Entry* me = m_measurements.get(fibEntry);

  // If the FIB entry is not under the strategy's namespace, find a part of the prefix
  // that falls under the strategy's namespace
  for (size_t prefixLen = fibEntry.getPrefix().size() + 1;
       me == nullptr && prefixLen <= interest.getName().size(); ++prefixLen) {
    me = m_measurements.get(interest.getName().getPrefix(prefixLen));
  }

  // Either the FIB entry or the Interest's name must be under this strategy's namespace
  BOOST_ASSERT(me != nullptr);

  // Set or update entry lifetime
  extendLifetime(*me);

  NamespaceInfo* info = me->insertStrategyInfo<NamespaceInfo>().first;
  BOOST_ASSERT(info != nullptr);
  return *info;
}

void
AsfMeasurements::extendLifetime(measurements::Entry& me)
{
  m_measurements.extendLifetime(me, MEASUREMENTS_LIFETIME);
}

} // namespace asf
} // namespace fw
} // namespace nfd
