blob: 8fd1591516519fab0c18cd440afee3b9dc7ab2b7 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2011-2015 Tsinghua University, P.R.China.
*
* This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
* contributors.
*
* ndnSIM 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.
*
* ndnSIM 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
* ndnSIM, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* @author Xiaoke Jiang <shock.jiang@gmail.com>
**/
#include "ndn-consumer-zipf-mandelbrot.hpp"
#include <math.h>
NS_LOG_COMPONENT_DEFINE("ndn.ConsumerZipfMandelbrot");
namespace ns3 {
namespace ndn {
NS_OBJECT_ENSURE_REGISTERED(ConsumerZipfMandelbrot);
TypeId
ConsumerZipfMandelbrot::GetTypeId(void)
{
static TypeId tid =
TypeId("ns3::ndn::ConsumerZipfMandelbrot")
.SetGroupName("Ndn")
.SetParent<ConsumerCbr>()
.AddConstructor<ConsumerZipfMandelbrot>()
.AddAttribute("NumberOfContents", "Number of the Contents in total", StringValue("100"),
MakeUintegerAccessor(&ConsumerZipfMandelbrot::SetNumberOfContents,
&ConsumerZipfMandelbrot::GetNumberOfContents),
MakeUintegerChecker<uint32_t>())
.AddAttribute("q", "parameter of improve rank", StringValue("0.7"),
MakeDoubleAccessor(&ConsumerZipfMandelbrot::SetQ,
&ConsumerZipfMandelbrot::GetQ),
MakeDoubleChecker<double>())
.AddAttribute("s", "parameter of power", StringValue("0.7"),
MakeDoubleAccessor(&ConsumerZipfMandelbrot::SetS,
&ConsumerZipfMandelbrot::GetS),
MakeDoubleChecker<double>());
return tid;
}
ConsumerZipfMandelbrot::ConsumerZipfMandelbrot()
: m_N(100) // needed here to make sure when SetQ/SetS are called, there is a valid value of N
, m_q(0.7)
, m_s(0.7)
, m_seqRng(CreateObject<UniformRandomVariable>())
{
// SetNumberOfContents is called by NS-3 object system during the initialization
}
ConsumerZipfMandelbrot::~ConsumerZipfMandelbrot()
{
}
void
ConsumerZipfMandelbrot::SetNumberOfContents(uint32_t numOfContents)
{
m_N = numOfContents;
NS_LOG_DEBUG(m_q << " and " << m_s << " and " << m_N);
m_Pcum = std::vector<double>(m_N + 1);
m_Pcum[0] = 0.0;
for (uint32_t i = 1; i <= m_N; i++) {
m_Pcum[i] = m_Pcum[i - 1] + 1.0 / std::pow(i + m_q, m_s);
}
for (uint32_t i = 1; i <= m_N; i++) {
m_Pcum[i] = m_Pcum[i] / m_Pcum[m_N];
NS_LOG_LOGIC("Cumulative probability [" << i << "]=" << m_Pcum[i]);
}
}
uint32_t
ConsumerZipfMandelbrot::GetNumberOfContents() const
{
return m_N;
}
void
ConsumerZipfMandelbrot::SetQ(double q)
{
m_q = q;
SetNumberOfContents(m_N);
}
double
ConsumerZipfMandelbrot::GetQ() const
{
return m_q;
}
void
ConsumerZipfMandelbrot::SetS(double s)
{
m_s = s;
SetNumberOfContents(m_N);
}
double
ConsumerZipfMandelbrot::GetS() const
{
return m_s;
}
void
ConsumerZipfMandelbrot::SendPacket()
{
if (!m_active)
return;
NS_LOG_FUNCTION_NOARGS();
uint32_t seq = std::numeric_limits<uint32_t>::max(); // invalid
// std::cout << Simulator::Now ().ToDouble (Time::S) << "s max -> " << m_seqMax << "\n";
while (m_retxSeqs.size()) {
seq = *m_retxSeqs.begin();
m_retxSeqs.erase(m_retxSeqs.begin());
// NS_ASSERT (m_seqLifetimes.find (seq) != m_seqLifetimes.end ());
// if (m_seqLifetimes.find (seq)->time <= Simulator::Now ())
// {
// NS_LOG_DEBUG ("Expire " << seq);
// m_seqLifetimes.erase (seq); // lifetime expired. Trying to find another unexpired
// sequence number
// continue;
// }
NS_LOG_DEBUG("=interest seq " << seq << " from m_retxSeqs");
break;
}
if (seq == std::numeric_limits<uint32_t>::max()) // no retransmission
{
if (m_seqMax != std::numeric_limits<uint32_t>::max()) {
if (m_seq >= m_seqMax) {
return; // we are totally done
}
}
seq = ConsumerZipfMandelbrot::GetNextSeq();
m_seq++;
}
// std::cout << Simulator::Now ().ToDouble (Time::S) << "s -> " << seq << "\n";
//
shared_ptr<Name> nameWithSequence = make_shared<Name>(m_interestName);
nameWithSequence->appendSequenceNumber(seq);
//
shared_ptr<Interest> interest = make_shared<Interest>();
interest->setNonce(m_rand->GetValue(0, std::numeric_limits<uint32_t>::max()));
interest->setName(*nameWithSequence);
// NS_LOG_INFO ("Requesting Interest: \n" << *interest);
NS_LOG_INFO("> Interest for " << seq << ", Total: " << m_seq << ", face: " << m_face->getId());
NS_LOG_DEBUG("Trying to add " << seq << " with " << Simulator::Now() << ". already "
<< m_seqTimeouts.size() << " items");
m_seqTimeouts.insert(SeqTimeout(seq, Simulator::Now()));
m_seqFullDelay.insert(SeqTimeout(seq, Simulator::Now()));
m_seqLastDelay.erase(seq);
m_seqLastDelay.insert(SeqTimeout(seq, Simulator::Now()));
m_seqRetxCounts[seq]++;
m_rtt->SentSeq(SequenceNumber32(seq), 1);
m_transmittedInterests(interest, this, m_face);
m_appLink->onReceiveInterest(*interest);
ConsumerZipfMandelbrot::ScheduleNextPacket();
}
uint32_t
ConsumerZipfMandelbrot::GetNextSeq()
{
uint32_t content_index = 1; //[1, m_N]
double p_sum = 0;
double p_random = m_seqRng->GetValue();
while (p_random == 0) {
p_random = m_seqRng->GetValue();
}
// if (p_random == 0)
NS_LOG_LOGIC("p_random=" << p_random);
for (uint32_t i = 1; i <= m_N; i++) {
p_sum = m_Pcum[i]; // m_Pcum[i] = m_Pcum[i-1] + p[i], p[0] = 0; e.g.: p_cum[1] = p[1],
// p_cum[2] = p[1] + p[2]
if (p_random <= p_sum) {
content_index = i;
break;
} // if
} // for
// content_index = 1;
NS_LOG_DEBUG("RandomNumber=" << content_index);
return content_index;
}
void
ConsumerZipfMandelbrot::ScheduleNextPacket()
{
if (m_firstTime) {
m_sendEvent = Simulator::Schedule(Seconds(0.0), &ConsumerZipfMandelbrot::SendPacket, this);
m_firstTime = false;
}
else if (!m_sendEvent.IsRunning())
m_sendEvent = Simulator::Schedule((m_random == 0) ? Seconds(1.0 / m_frequency)
: Seconds(m_random->GetValue()),
&ConsumerZipfMandelbrot::SendPacket, this);
}
} /* namespace ndn */
} /* namespace ns3 */