blob: d3d54b39049308794e3d07688cd51f0c234c2460 [file] [log] [blame]
Alexander Afanasyev048ae422012-08-17 17:33:02 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2012 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
19 */
20
21#include "ndn-pit-queue.h"
22
23#include "ns3/ndn-face.h"
24#include "ns3/ndn-pit-entry.h"
Alexander Afanasyev0ffa7162012-08-21 22:39:22 -070025#include "ns3/log.h"
Alexander Afanasyevc23a3e32012-08-28 00:16:23 -070026#include "ns3/simulator.h"
Alexander Afanasyev048ae422012-08-17 17:33:02 -070027
28#include "ns3/assert.h"
29
30using namespace std;
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -070031using namespace boost;
Alexander Afanasyev048ae422012-08-17 17:33:02 -070032
Alexander Afanasyev0ffa7162012-08-21 22:39:22 -070033NS_LOG_COMPONENT_DEFINE ("ndn.PitQueue");
34
Alexander Afanasyev048ae422012-08-17 17:33:02 -070035namespace ns3 {
36namespace ndn {
37
Alexander Afanasyevcaeade22012-09-04 16:31:12 -070038const double MIN_WEIGHT = 0.01;
Alexander Afanasyev98c16e02012-08-28 00:02:02 -070039
Alexander Afanasyevec1e3952012-08-20 13:48:15 -070040PitQueue::PitQueue ()
Alexander Afanasyev372cbab2012-08-22 09:43:53 -070041 // : m_maxQueueSize (20)
42 : m_lastQueue (m_queues.end ())
Alexander Afanasyev048ae422012-08-17 17:33:02 -070043{
44}
Alexander Afanasyevec1e3952012-08-20 13:48:15 -070045
Alexander Afanasyev372cbab2012-08-22 09:43:53 -070046// void
47// PitQueue::SetMaxQueueSize (uint32_t size)
48// {
49// m_maxQueueSize = size;
50// }
Alexander Afanasyevec1e3952012-08-20 13:48:15 -070051
Alexander Afanasyev372cbab2012-08-22 09:43:53 -070052// uint32_t
53// PitQueue::GetMaxQueueSize () const
54// {
55// return m_maxQueueSize;
56// }
Alexander Afanasyev048ae422012-08-17 17:33:02 -070057
58
59bool
60PitQueue::Enqueue (Ptr<Face> inFace,
Alexander Afanasyev98c16e02012-08-28 00:02:02 -070061 Ptr<pit::Entry> pitEntry,
62 double updatedWeight)
Alexander Afanasyev048ae422012-08-17 17:33:02 -070063{
Alexander Afanasyev187cba22012-08-28 11:16:52 -070064 if (updatedWeight < 0) updatedWeight = 0.5;
Alexander Afanasyev98c16e02012-08-28 00:02:02 -070065 if (updatedWeight < MIN_WEIGHT) updatedWeight = MIN_WEIGHT;
66
Alexander Afanasyeved449cc2012-08-21 11:10:33 -070067 PerInFaceQueue::iterator queue = m_queues.find (inFace);
68 if (queue == m_queues.end ())
69 {
Alexander Afanasyev98c16e02012-08-28 00:02:02 -070070 pair<PerInFaceQueue::iterator, bool> itemPair =
71 m_queues.insert (make_pair (inFace, boost::make_shared< WeightedQueue > (make_tuple (Queue (), updatedWeight, 0))));
Alexander Afanasyev0ffa7162012-08-21 22:39:22 -070072 m_lastQueue = m_queues.end (); // for some reason end() iterator is invalidated when new item is inserted
Alexander Afanasyeved449cc2012-08-21 11:10:33 -070073 NS_ASSERT (itemPair.second == true);
74
75 queue = itemPair.first;
76 }
Alexander Afanasyevcaeade22012-09-04 16:31:12 -070077 else
78 {
79 queue->second->get<1> () = updatedWeight;
80 }
Alexander Afanasyevff033952012-08-23 15:45:52 -070081
Alexander Afanasyev98c16e02012-08-28 00:02:02 -070082 if ((inFace->GetLimits ().GetMaxLimit () == 0 && queue->second->get<0> ().size () > 100) ||
83 (inFace->GetLimits ().GetMaxLimit () != 0 && queue->second->get<0> ().size () >= 0.5 * inFace->GetLimits ().GetMaxLimit ()))
Alexander Afanasyevff033952012-08-23 15:45:52 -070084 {
Alexander Afanasyevec1e3952012-08-20 13:48:15 -070085 return false;
Alexander Afanasyevff033952012-08-23 15:45:52 -070086 }
Alexander Afanasyevec1e3952012-08-20 13:48:15 -070087
Alexander Afanasyev98c16e02012-08-28 00:02:02 -070088 Queue::iterator itemIterator = queue->second->get<0> ().insert (queue->second->get<0> ().end (), pitEntry);
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -070089
90 shared_ptr<fw::PitQueueTag> tag = pitEntry->GetFwTag<fw::PitQueueTag> ();
91 if (tag == shared_ptr<fw::PitQueueTag> ())
92 {
93 tag = make_shared<fw::PitQueueTag> ();
94 pitEntry->AddFwTag (tag);
95 }
96 tag->InsertQueue (queue->second, itemIterator);
Alexander Afanasyev98c16e02012-08-28 00:02:02 -070097
Alexander Afanasyevcaeade22012-09-04 16:31:12 -070098 // if (Simulator::GetContext () == 4)
99 // {
100 // cout << "====== " << Simulator::Now ().ToDouble (Time::S) << "s " << *queue->first << endl;
101 // cout << " " << m_serviceCounter << " / " << queue->second->get<1> () << " / " << queue->second->get<2> () << "\n";
102 // for (PerInFaceQueue::const_iterator somequeue = m_queues.begin ();
103 // somequeue != m_queues.end ();
104 // somequeue ++)
105 // {
106 // if (somequeue == queue) cout << "*";
107 // cout << somequeue->second->get<0> ().size () << " ";
108 // }
109 // cout << endl;
110 // }
111
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700112 UpdateWeightedRounds ();
Alexander Afanasyevcaeade22012-09-04 16:31:12 -0700113
Alexander Afanasyevec1e3952012-08-20 13:48:15 -0700114 return true;
Alexander Afanasyev048ae422012-08-17 17:33:02 -0700115}
116
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700117
Alexander Afanasyev048ae422012-08-17 17:33:02 -0700118Ptr<pit::Entry>
119PitQueue::Pop ()
120{
Alexander Afanasyevec1e3952012-08-20 13:48:15 -0700121 PerInFaceQueue::iterator queue = m_lastQueue;
122
Alexander Afanasyevc23a3e32012-08-28 00:16:23 -0700123 if (queue != m_queues.end () &&
Alexander Afanasyev187cba22012-08-28 11:16:52 -0700124 m_serviceCounter >= queue->second->get<2> ())
Alexander Afanasyevc23a3e32012-08-28 00:16:23 -0700125 {
Alexander Afanasyev187cba22012-08-28 11:16:52 -0700126 queue ++; // actually implement weighted round robin...
127 m_serviceCounter = 0;
Alexander Afanasyevc23a3e32012-08-28 00:16:23 -0700128 }
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700129
130 while (queue != m_queues.end () && queue->second->get<0> ().size () == 0) // advance iterator
Alexander Afanasyevec1e3952012-08-20 13:48:15 -0700131 {
132 queue ++;
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700133 m_serviceCounter = 0;
Alexander Afanasyevec1e3952012-08-20 13:48:15 -0700134 }
135
136 if (queue == m_queues.end ())
Alexander Afanasyev0ffa7162012-08-21 22:39:22 -0700137 {
138 queue = m_queues.begin (); // circle to the beginning
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700139 m_serviceCounter = 0;
Alexander Afanasyev0ffa7162012-08-21 22:39:22 -0700140 }
Alexander Afanasyevec1e3952012-08-20 13:48:15 -0700141
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700142 while (queue != m_queues.end () && queue->second->get<0> ().size () == 0) // advance iterator
Alexander Afanasyevec1e3952012-08-20 13:48:15 -0700143 {
144 queue ++;
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700145 m_serviceCounter = 0;
Alexander Afanasyevec1e3952012-08-20 13:48:15 -0700146 }
147
Alexander Afanasyev187cba22012-08-28 11:16:52 -0700148 m_serviceCounter ++;
149
150 // if (Simulator::GetContext () == 4)
Alexander Afanasyevc23a3e32012-08-28 00:16:23 -0700151 // {
Alexander Afanasyev187cba22012-08-28 11:16:52 -0700152 // cout << "====== " << Simulator::Now ().ToDouble (Time::S) << "s " << *queue->first << endl;
Alexander Afanasyevcaeade22012-09-04 16:31:12 -0700153 // cout << " " << m_serviceCounter << " / " << queue->second->get<1> () << " / " << queue->second->get<2> () << "\n";
Alexander Afanasyevc23a3e32012-08-28 00:16:23 -0700154 // for (PerInFaceQueue::const_iterator somequeue = m_queues.begin ();
155 // somequeue != m_queues.end ();
156 // somequeue ++)
157 // {
158 // if (somequeue == queue) cout << "*";
159 // cout << somequeue->second->get<0> ().size () << " ";
160 // }
161 // cout << endl;
162 // }
163
Alexander Afanasyev187cba22012-08-28 11:16:52 -0700164 if (queue == m_queues.end () || queue->second->get<0> ().size () == 0)
165 return 0;
166
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700167 NS_ASSERT_MSG (queue->second->get<0> ().size () != 0, "Logic error");
Alexander Afanasyev048ae422012-08-17 17:33:02 -0700168
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700169 Ptr<pit::Entry> entry = *queue->second->get<0> ().begin ();
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700170 shared_ptr<fw::PitQueueTag> tag = entry->GetFwTag<fw::PitQueueTag> ();
171 NS_ASSERT (tag != shared_ptr<fw::PitQueueTag> ());
Alexander Afanasyev048ae422012-08-17 17:33:02 -0700172
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700173#ifdef NS3_LOG_ENABLE
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700174 size_t queueSize = queue->second->get<0> ().size ();
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700175#endif
176 tag->RemoveFromQueue (queue->second);
177#ifdef NS3_LOG_ENABLE
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700178 NS_ASSERT_MSG (queue->second->get<0> ().size () == queueSize-1, "Queue size should be reduced by one");
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700179#endif
Alexander Afanasyev187cba22012-08-28 11:16:52 -0700180
Alexander Afanasyevec1e3952012-08-20 13:48:15 -0700181 m_lastQueue = queue;
182 return entry;
Alexander Afanasyev048ae422012-08-17 17:33:02 -0700183}
184
185void
186PitQueue::Remove (Ptr<Face> face)
187{
Alexander Afanasyevec1e3952012-08-20 13:48:15 -0700188 if (m_lastQueue->first == face)
Alexander Afanasyev048ae422012-08-17 17:33:02 -0700189 {
Alexander Afanasyevec1e3952012-08-20 13:48:15 -0700190 m_lastQueue++;
Alexander Afanasyev048ae422012-08-17 17:33:02 -0700191 }
Alexander Afanasyevec1e3952012-08-20 13:48:15 -0700192
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700193 PerInFaceQueue::iterator queue = m_queues.find (face);
194 if (queue == m_queues.end ())
195 return;
196
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700197 for (Queue::iterator pitEntry = queue->second->get<0> ().begin ();
198 pitEntry != queue->second->get<0> ().end ();
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700199 pitEntry ++)
200 {
201 shared_ptr<fw::PitQueueTag> tag = (*pitEntry)->GetFwTag<fw::PitQueueTag> ();
202 NS_ASSERT (tag != shared_ptr<fw::PitQueueTag> ());
203
Alexander Afanasyev6f101fc2012-08-23 16:34:34 -0700204 tag->RemoveFromQueuesExcept (queue->second);
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700205 }
206
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700207 NS_ASSERT_MSG (queue->second->get<0> ().size () == 0, "Queue size should be 0 by now");
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700208 m_queues.erase (queue);
Alexander Afanasyev048ae422012-08-17 17:33:02 -0700209}
210
211void
212PitQueue::Remove (Ptr<pit::Entry> entry)
213{
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700214 shared_ptr<fw::PitQueueTag> tag = entry->GetFwTag<fw::PitQueueTag> ();
215 if (tag == shared_ptr<fw::PitQueueTag> ())
216 return;
217
218 tag->RemoveFromAllQueues ();
Alexander Afanasyev048ae422012-08-17 17:33:02 -0700219}
220
Alexander Afanasyev5db92172012-08-21 16:52:07 -0700221bool
222PitQueue::IsEmpty () const
223{
Alexander Afanasyev0ffa7162012-08-21 22:39:22 -0700224 bool isEmpty = true;
Alexander Afanasyev5db92172012-08-21 16:52:07 -0700225
226 for (PerInFaceQueue::const_iterator queue = m_queues.begin ();
227 queue != m_queues.end ();
228 queue ++)
229 {
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700230 isEmpty &= (queue->second->get<0> ().size () == 0);
Alexander Afanasyev5db92172012-08-21 16:52:07 -0700231 }
232
233 return isEmpty;
234}
235
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700236bool
237PitQueue::IsEmpty (Ptr<Face> inFace) const
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700238{
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700239 PerInFaceQueue::const_iterator queue = m_queues.find (inFace);
240 if (queue == m_queues.end ())
241 return true;
242
243 return queue->second->get<0> ().size () == 0;
244}
245
246
247void
248PitQueue::UpdateWeightedRounds ()
249{
250 double minWeight = 100.0;
251 for (PerInFaceQueue::const_iterator queue = m_queues.begin ();
252 queue != m_queues.end ();
253 queue ++)
254 {
255 if (queue->second->get<1> () < minWeight)
256 minWeight = queue->second->get<1> ();
257 }
258
259 for (PerInFaceQueue::const_iterator queue = m_queues.begin ();
260 queue != m_queues.end ();
261 queue ++)
262 {
Alexander Afanasyevcaeade22012-09-04 16:31:12 -0700263 queue->second->get<2> () = static_cast<uint32_t>((queue->second->get<1> () / minWeight) + 0.5);
Alexander Afanasyev187cba22012-08-28 11:16:52 -0700264 if (queue->second->get<2> () < 1)
265 queue->second->get<2> () = 1;
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700266 }
Alexander Afanasyev187cba22012-08-28 11:16:52 -0700267
268 // if (m_queues.size () > 1)
269 // {
270 // cout << "Node " << Simulator::GetContext () << " (min = " << minWeight << "): ";
271 // for (PerInFaceQueue::const_iterator queue = m_queues.begin ();
272 // queue != m_queues.end ();
273 // queue ++)
274 // {
275 // cout << queue->second->get<1> () << "/" << queue->second->get<2> () << " ";
276 // }
277 // cout << endl;
278 // }
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700279}
280
281
282////////////////////////////////////////////////////////////////////////////////
283
284void
285fw::PitQueueTag::InsertQueue (boost::shared_ptr<PitQueue::WeightedQueue> queue, PitQueue::Queue::iterator iterator)
286{
287 // std::cerr << "size before: " << m_items.size () << " item: " << (*iterator)->GetPrefix ();
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700288 pair<MapOfItems::iterator, bool> item = m_items.insert (make_pair (queue, iterator));
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700289 // std::cerr << " and after: " << m_items.size () << std::endl;
290 NS_ASSERT_MSG (item.second == true, "Should be a new tag for PIT entry, but something is wrong");
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700291}
292
293void
294fw::PitQueueTag::RemoveFromAllQueues ()
295{
296 for (MapOfItems::iterator item = m_items.begin ();
297 item != m_items.end ();
298 item ++)
299 {
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700300 item->first->get<0> ().erase (item->second);
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700301 }
302 m_items.clear ();
303}
304
305void
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700306fw::PitQueueTag::RemoveFromQueue (boost::shared_ptr<PitQueue::WeightedQueue> queue)
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700307{
308 MapOfItems::iterator item = m_items.find (queue);
309 if (item == m_items.end ())
310 return;
311
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700312 item->first->get<0> ().erase (item->second);
Alexander Afanasyev38ba9b22012-08-21 13:32:43 -0700313 m_items.erase (item);
314}
Alexander Afanasyev048ae422012-08-17 17:33:02 -0700315
Alexander Afanasyev6f101fc2012-08-23 16:34:34 -0700316void
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700317fw::PitQueueTag::RemoveFromQueuesExcept (boost::shared_ptr<PitQueue::WeightedQueue> queue)
Alexander Afanasyev6f101fc2012-08-23 16:34:34 -0700318{
319 for (MapOfItems::iterator item = m_items.begin ();
320 item != m_items.end (); )
321 {
322 if (item->first == queue)
323 {
324 item ++;
325 continue;
326 }
327
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700328 item->first->get<0> ().erase (item->second);
Alexander Afanasyev6f101fc2012-08-23 16:34:34 -0700329
330 MapOfItems::iterator itemToDelete = item;
331 item ++;
332 m_items.erase (itemToDelete);
333 }
334}
335
Alexander Afanasyev98c16e02012-08-28 00:02:02 -0700336bool
337fw::PitQueueTag::IsLastOneInQueues () const
338{
339 bool lastOne = true;
340
341 for (MapOfItems::const_iterator item = m_items.begin ();
342 item != m_items.end ();
343 item ++)
344 {
345 lastOne &= (item->first->get<0> ().size () == 1);
346 }
347
348 return lastOne;
349}
350
Alexander Afanasyev6f101fc2012-08-23 16:34:34 -0700351
Alexander Afanasyev048ae422012-08-17 17:33:02 -0700352} // namespace ndn
353} // namespace ns3