ndn-subscription-consumer.cpp 10.3 KB
Newer Older
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2011-2015  Regents of the University of California.
 *
 * 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/>.
 **/

#include "ns3/ptr.h"
#include "ns3/log.h"
#include "ns3/simulator.h"
#include "ns3/packet.h"
#include "ns3/callback.h"
#include "ns3/string.h"
#include "ns3/boolean.h"
#include "ns3/uinteger.h"
#include "ns3/integer.h"
#include "ns3/double.h"

#include <string>
32
#include <algorithm>
33
#include <set>
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
34
#include "ndn-subscription-consumer.hpp"
caminha's avatar
caminha committed
35
36
#include <ndn-cxx/lp/tags.hpp>
#include "ndn-cxx/util/time.hpp"
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
37
38
39
40

namespace ns3 {
namespace ndn {

41
42
NS_LOG_COMPONENT_DEFINE("ndn.SubscriptionConsumer");

Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
43
NS_OBJECT_ENSURE_REGISTERED(SubscriptionConsumer);
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
44
45

TypeId
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
46
SubscriptionConsumer::GetTypeId(void)
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
47
48
{
  static TypeId tid =
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
49
    TypeId("ns3::ndn::SubscriptionConsumer")
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
50
51
      .SetGroupName("Ndn")
      .SetParent<Consumer>()
52
53
      .AddConstructor<SubscriptionConsumer>()
      .AddAttribute("SubscriptionInterval", "Interval of subscription interest", TimeValue(Seconds(1.0)),
Renato CJN's avatar
Renato CJN committed
54
55
56
57
										MakeTimeAccessor(&SubscriptionConsumer::m_subscriptionInterval), MakeTimeChecker())
			.AddTraceSource("ConsumerStreamsReused",
										  "Number of consumer streams detected as already existing or equivalent to existing ones",
										  MakeTraceSourceAccessor (&SubscriptionConsumer::interestSatisfactionRatio),
caminha's avatar
caminha committed
58
											"ns3::TracedValueCallback::Double")
caminha's avatar
caminha committed
59
60
61
62
			.AddTraceSource("ValidSubCount",
											"Number of consumer streams answered by the producers",
											MakeTraceSourceAccessor (&SubscriptionConsumer::validSubCountPerc),
											"ns3::TracedValueCallback::Double")
caminha's avatar
caminha committed
63
64
65
66
			.AddTraceSource("FirstReceivedDataDelay",
											"Time between the application start and the time the first data was received",
											MakeTraceSourceAccessor (&SubscriptionConsumer::firstDataDelay),
											"ns3::TracedValueCallback::Time");
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
67
68
69
70

  return tid;
}

caminha's avatar
caminha committed
71
SubscriptionConsumer::SubscriptionConsumer()
caminha's avatar
caminha committed
72
: Consumer(), subscriptionCount(1), hasReceivedFirstdata(false) {}
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
73

Renato CJN's avatar
Renato CJN committed
74
75
76
77
void
SubscriptionConsumer::StartApplication()
{
	startTime = Simulator::Now();
caminha's avatar
caminha committed
78
79
	hasReceivedFirstdata = false;
	firstDataDelay = Seconds(0);
Renato CJN's avatar
Renato CJN committed
80
81
82
	Consumer::StartApplication();
}

caminha's avatar
caminha committed
83
84
size_t SubscriptionConsumer::globalSubscriptionCount = 0;

85
86
87
88
89
90
91
92
void
SubscriptionConsumer::ScheduleNextPacket()
{
  NS_LOG_FUNCTION_NOARGS();

  SendPacket();
}

Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
93
void
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
94
SubscriptionConsumer::SendPacket()
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
95
{
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
96
  NS_LOG_FUNCTION_NOARGS();
Renato CJN's avatar
Renato CJN committed
97

Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
98
99
100
  if (!m_active)
    return;

101
  Ptr<UniformRandomVariable> rand = CreateObject<UniformRandomVariable>();
102

Renato CJN's avatar
Renato CJN committed
103
  if (randomInterestPrefixes.empty())
104
	  {
Renato CJN's avatar
Renato CJN committed
105
		  subscriptionCount = 1;
caminha's avatar
caminha committed
106
107
		  randomInterestPrefixes.resize(1);
		  randomInterestPrefixes[0] = m_interestName;
108
	  }
109
  auto rng = CreateObject<UniformRandomVariable>();
caminha's avatar
caminha committed
110
  BOOST_ASSERT_MSG(subscriptionCount > 0 , "Subscription count must be set");
111
  NS_LOG_DEBUG("randomBrokerPrefixes: " << randomInterestPrefixes.size());
112
  NS_LOG_DEBUG("subscriptionCount: " << subscriptionCount);
caminha's avatar
caminha committed
113
114
//  globalSubscriptionCount += subscriptionCount;
//  NS_LOG_UNCOND("globalSubscriptionCount: " << globalSubscriptionCount);
caminha's avatar
caminha committed
115

116
  for (int i=0; i<subscriptionCount; i++)
117
  {
118
119
120
121
122
123
124
  	uint prefixIdx;
  	do { prefixIdx = rng->GetInteger(0, randomInterestPrefixes.size()-1); }
  	while (pickedPrefixes.find(prefixIdx) != pickedPrefixes.end());
  	pickedPrefixes.insert(prefixIdx);

  	auto it = randomInterestPrefixes.begin();
  	std::advance(it, prefixIdx);
caminha's avatar
caminha committed
125
	  shared_ptr<Name> nameWithTransformation = make_shared<Name>(*it);
126
	  if ( useParams || !transformationsAndParameters.empty())
127
		{
128
129
130
131
132
133
134
135
136
137
		  if(!transformationsAndParameters.empty())
			{
			  params.clearTranformations();
			  params.clearTransformationParams();
			  for (const auto& transformationAndParams : this->transformationsAndParameters)
				{
				  params.addTransformation(transformationAndParams.first);
				  for (const auto& paramAndChoices : transformationAndParams.second)
					{
					  uint i = rand->GetInteger(0, paramAndChoices.second.size()-1);
caminha's avatar
caminha committed
138
139
					  params.addTransformationParam(transformationAndParams.first,
																					paramAndChoices.first, paramAndChoices.second.at(i));
140
141
142
					}
				}
			}
caminha's avatar
caminha committed
143
		  params.appendTransformationsToName(nameWithTransformation);
144
		}
145

caminha's avatar
caminha committed
146
//	  toBeReceived.push_back(*nameWithTransformation);
caminha's avatar
caminha committed
147
	  shared_ptr<Interest> interest = make_shared<Interest>(*nameWithTransformation);
148
149
150
151
152
153
154
155
	  interest->setNonce(m_rand->GetValue(0, std::numeric_limits<uint32_t>::max()));
	  interest->setCanBePrefix(true);
	  time::milliseconds subInterval(m_subscriptionInterval.GetMilliSeconds());
	  interest->setSubscription(subInterval);
	  time::milliseconds interestLifeTime(m_interestLifeTime.GetMilliSeconds());
	  interest->setInterestLifetime(interestLifeTime);

	  if ( useParams ) interest->setParameters(params.wireEncode());
caminha's avatar
caminha committed
156
//	  NS_LOG_INFO ("Requesting Interest: \n" << *interest);
157

caminha's avatar
caminha committed
158
//	  WillSendOutInterest(i);
159

Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
160
	  NS_LOG_DEBUG("Sending " << interest->getName() << " " << m_subscriptionInterval.GetSeconds() << "sec");
161
162
	  m_transmittedInterests(interest, this, m_face);
	  m_appLink->onReceiveInterest(*interest);
caminha's avatar
caminha committed
163
164
	  avgDataDelay[*nameWithTransformation] = 0;
	  localPrefixNames[*nameWithTransformation] = 0;
165
  }
caminha's avatar
caminha committed
166
  interestTransmission = time::steady_clock::now();
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
167
168
}

169
170
SubscriptionConsumer::randomTransformations
	SubscriptionConsumer::transformationsAndParameters;
171

Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
172
void
173
174
SubscriptionConsumer::setRandomTransformations
	(SubscriptionConsumer::randomTransformations randomStuff)
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
175
{
176
  transformationsAndParameters = randomStuff;
Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
177
178
}

caminha's avatar
caminha committed
179
SubscriptionConsumer::InterestPrefixes
Renato CJN's avatar
Renato CJN committed
180
	SubscriptionConsumer::randomInterestPrefixes;
181
182

void
caminha's avatar
caminha committed
183
SubscriptionConsumer::setRandomInterestPrefixes(InterestPrefixes prefAndCounts)
184
{
Renato CJN's avatar
Renato CJN committed
185
  randomInterestPrefixes = prefAndCounts;
186
}
187

caminha's avatar
caminha committed
188
189
190
191
192
193
SubscriptionConsumer::InterestPrefixes
SubscriptionConsumer::getRandomInterestPrefixes()
{
	return randomInterestPrefixes;
}

Renato CJN's avatar
Renato CJN committed
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
void
SubscriptionConsumer::addPrefix(Name prefix)
{
	prefixList.push_back(prefix);
}

void
SubscriptionConsumer::resetPrefixList()
{
	prefixList.clear();
}

void
SubscriptionConsumer::OnData(shared_ptr<const Data> data)
{
209
	NS_LOG_FUNCTION(data->getName() << m_subscriptionInterval.GetMinutes());
caminha's avatar
caminha committed
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
	auto it = std::find_if(localPrefixNames.begin(), localPrefixNames.end(), [&](const std::pair<Name, uint> item){
		return item.first.isPrefixOf(data->getName());
	});
	BOOST_ASSERT(it != localPrefixNames.end());

	auto data_timestamp = data->getName().at(-1).toSteadyClockTimeStamp();
	long time_since_transmission = time::duration_cast<time::milliseconds>(data_timestamp - interestTransmission).count();
	long time_until_next = time_since_transmission / m_subscriptionInterval.GetMilliSeconds();
	long drift = std::min(time_until_next, (long)m_subscriptionInterval.GetMilliSeconds() - time_until_next);
//	NS_LOG_UNCOND("Drift: " << drift << "ms");
	BOOST_ASSERT(drift < 10000);


	localPrefixNames[it->first] += 1;
	avgDataDelay[it->first] += time::duration_cast<time::milliseconds>(time::steady_clock::now() - data_timestamp).count();

caminha's avatar
caminha committed
226
	receivedDatapkts++;
caminha's avatar
caminha committed
227
228
229
230
	if (!hasReceivedFirstdata)
		{
			hasReceivedFirstdata = true;
			firstDataDelay = Simulator::Now() - startTime;
caminha's avatar
caminha committed
231
			firstDataTime = Simulator::Now();
caminha's avatar
caminha committed
232
233
		}

caminha's avatar
caminha committed
234
235
236
237
238
239
240
241
242
243
//	if (!toBeReceived.empty())
//		{
//			Time currOperationTime = Simulator::Now() - startTime;
////			if (currOperationTime > 4 * m_subscriptionInterval)
////				{
////					BOOST_THROW_EXCEPTION(std::logic_error("Too much data has been lost on node " + ::ndn::to_string(m_node->GetId()) + " missing " + ::ndn::to_string(toBeReceived.size()) + "sources"));
////				}
//			auto it = std::find_if(toBeReceived.begin(), toBeReceived.end(),
//				  		   [&](const Name& name) { return name.isPrefixOf(data->getName()); });
//			if (it != toBeReceived.end())
244
//				{
caminha's avatar
caminha committed
245
246
//					toBeReceived.erase(it);
//					NS_LOG_DEBUG("First data from " << *it << " received, " << ::ndn::to_string(toBeReceived.size()) << " remaining");
247
//				}
caminha's avatar
caminha committed
248
//		}
caminha's avatar
caminha committed
249
250
251
252
253
254
255
256
257

	App::OnData(data);
}

void
SubscriptionConsumer::OnTimeout(uint32_t sequenceNumber)
{
	BOOST_THROW_EXCEPTION(std::logic_error("There should not be interest timeouts"));
	Consumer::OnTimeout(sequenceNumber);
Renato CJN's avatar
Renato CJN committed
258
259
260
261
262
}

void
SubscriptionConsumer::StopApplication()
{
caminha's avatar
caminha committed
263
	NS_LOG_FUNCTION_NOARGS();
caminha's avatar
caminha committed
264

265
266
	if (hasReceivedFirstdata)
		{
caminha's avatar
caminha committed
267
268
			const Time streamDuration = Simulator::Now() - firstDataTime;

caminha's avatar
caminha committed
269
270
			const uint validSubCount = std::count_if(localPrefixNames.begin(), localPrefixNames.end(),
																							 [](const auto& item) { return item.second > 0; });
caminha's avatar
caminha committed
271
			this->validSubCountPerc = (100.0 * validSubCount)/subscriptionCount;
caminha's avatar
caminha committed
272
273
274

			const long expectedreceivedDatas = std::ceil(streamDuration / m_subscriptionInterval) + 1;// - acceptableLoss;

caminha's avatar
caminha committed
275
276
277
278
279
			for (auto it=localPrefixNames.begin(); it!=localPrefixNames.end(); it++)
				{
					interestSatisfactionRatio += 100.0 * it->second / expectedreceivedDatas;
					avgDataDelay[it->first] /= it->second;
				}
caminha's avatar
caminha committed
280

caminha's avatar
caminha committed
281
			interestSatisfactionRatio /= validSubCount;
282
		}
caminha's avatar
caminha committed
283
	App::StopApplication();
Renato CJN's avatar
Renato CJN committed
284
285
286
287
288
289
290
}

double
SubscriptionConsumer::getInterestSatisfactionRatio() const
{
	return interestSatisfactionRatio.Get();
}
291

caminha's avatar
caminha committed
292
293
294
295
296
297
double
SubscriptionConsumer::getValidSubCountPerc() const
{
	return validSubCountPerc.Get();
}

caminha's avatar
caminha committed
298
299
300
301
302
303
304
305
Time
SubscriptionConsumer::getFirstDataDelay() const
{
	if (!hasReceivedFirstdata)
		NS_LOG_LOGIC("Has not received any data");
	return firstDataDelay;
}

306
307
308
309
310
311
bool
SubscriptionConsumer::receivedFirstData() const
{
	return hasReceivedFirstdata;
}

312
313
314
315
316
317
void
SubscriptionConsumer::setSubscriptionCount(size_t count)
{
	subscriptionCount = count;
}

caminha's avatar
caminha committed
318
319
320
321
322
323
size_t
SubscriptionConsumer::getSubscriptionCount() const
{
	return subscriptionCount;
}

caminha's avatar
caminha committed
324
325
326
327
328
329
std::set<uint>
SubscriptionConsumer::getPickedPrefixes () const
{
	return pickedPrefixes;
}

caminha's avatar
caminha committed
330
331
332
333
334
335
Time
SubscriptionConsumer::GetSubInterval() const
{
	return m_subscriptionInterval;
}

caminha's avatar
caminha committed
336
337
338
339
340
341
std::map<Name, double>
SubscriptionConsumer::getAvgDataDelay() const
{
	return avgDataDelay;
}

Renato Caminha Juaçaba Neto's avatar
Renato Caminha Juaçaba Neto committed
342
343
} // namespace ndn
} // namespace ns3