blob: 3add035e7a3ca735a5f2ffab1d76e3a489972a07 [file] [log] [blame]
Junxiao Shi0fcb41e2014-01-24 10:29:43 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07003 * Copyright (c) 2014 Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -08009 *
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 *
24 * \author Ilya Moiseenko <iliamo@ucla.edu>
Junxiao Shi0fcb41e2014-01-24 10:29:43 -070025 */
26
Junxiao Shi0fcb41e2014-01-24 10:29:43 -070027#include "cs.hpp"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060028#include "core/logger.hpp"
29
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -080030#include <ndn-cpp-dev/util/crypto.hpp>
31
32#define SKIPLIST_MAX_LAYERS 32
33#define SKIPLIST_PROBABILITY 50 // 50% ( p = 1/2 )
34
35NFD_LOG_INIT("ContentStore");
Alexander Afanasyevb927a3a2014-01-24 10:41:47 -080036
Alexander Afanasyev18bbf812014-01-29 01:40:23 -080037namespace nfd {
Junxiao Shi0fcb41e2014-01-24 10:29:43 -070038
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -080039Cs::Cs(int nMaxPackets)
40 : m_nMaxPackets(nMaxPackets)
Junxiao Shi0fcb41e2014-01-24 10:29:43 -070041{
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -070042 srand (time::toUnixTimestamp(time::system_clock::now()).count());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -080043 SkipListLayer* zeroLayer = new SkipListLayer();
44 m_skipList.push_back(zeroLayer);
Junxiao Shi0fcb41e2014-01-24 10:29:43 -070045}
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -080046
Junxiao Shi0fcb41e2014-01-24 10:29:43 -070047Cs::~Cs()
48{
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -080049 /// \todo Fix memory leak
50}
51
52size_t
53Cs::size() const
54{
55 return (*m_skipList.begin())->size(); // size of the first layer in a skip list
56}
57
58void
59Cs::setLimit(size_t nMaxPackets)
60{
61 m_nMaxPackets = nMaxPackets;
62
63 while (isFull())
64 {
65 evictItem();
66 }
67}
68
69size_t
70Cs::getLimit() const
71{
72 return m_nMaxPackets;
73}
74
75//Reference: "Skip Lists: A Probabilistic Alternative to Balanced Trees" by W.Pugh
76std::pair< shared_ptr<cs::Entry>, bool>
77Cs::insertToSkipList(const Data& data, bool isUnsolicited)
78{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -070079 NFD_LOG_TRACE("insertToSkipList() " << data.getName() << ", "
80 << "skipList size " << size());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -080081
82 shared_ptr<cs::Entry> entry = make_shared<cs::Entry>(data, isUnsolicited);
83
84 bool insertInFront = false;
85 bool isIterated = false;
86 SkipList::reverse_iterator topLayer = m_skipList.rbegin();
87 SkipListLayer::iterator updateTable[SKIPLIST_MAX_LAYERS];
88 SkipListLayer::iterator head = (*topLayer)->begin();
89
90 if ( !(*topLayer)->empty() )
91 {
92 //start from the upper layer towards bottom
93 int layer = m_skipList.size() - 1;
94 for (SkipList::reverse_iterator rit = topLayer; rit != m_skipList.rend(); ++rit)
95 {
96 //if we didn't do any iterations on the higher layers, start from the begin() again
97 if ( !isIterated )
98 head = (*rit)->begin();
99
100 updateTable[layer] = head;
101
102 if (head != (*rit)->end())
103 {
104 // it can happen when begin() contains the element in front of which we need to insert
105 if ( !isIterated && ((*head)->getName() >= entry->getName()) )
106 {
107 --updateTable[layer];
108 insertInFront = true;
109 }
110 else
111 {
112 SkipListLayer::iterator it = head;
113
114 while ((*it)->getName() < entry->getName())
115 {
116 head = it;
117 updateTable[layer] = it;
118 isIterated = true;
119
120 ++it;
121 if (it == (*rit)->end())
122 break;
123 }
124 }
125 }
126
127 if (layer > 0)
128 head = (*head)->getIterators().find(layer - 1)->second; // move HEAD to the lower layer
129
130 layer--;
131 }
132 }
133 else
134 {
135 updateTable[0] = (*topLayer)->begin(); //initialization
136 }
137
138 head = updateTable[0];
139 ++head; // look at the next slot to check if it contains a duplicate
140
141 bool isCsEmpty = (size() == 0);
142 bool isInBoundaries = (head != (*m_skipList.begin())->end());
143 bool isNameIdentical = false;
144 if (!isCsEmpty && isInBoundaries)
145 {
146 isNameIdentical = (*head)->getName() == entry->getName();
147 }
148
149 //check if this is a duplicate packet
150 if (isNameIdentical)
151 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700152 NFD_LOG_TRACE("Duplicate name (with digest)");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800153
154 (*head)->setData(data, entry->getDigest()); //updates stale time
155
156 return std::make_pair(*head, false);
157 }
158
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700159 NFD_LOG_TRACE("Not a duplicate");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800160
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700161 size_t randomLayer = pickRandomLayer();
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800162
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700163 while ( m_skipList.size() < randomLayer + 1)
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800164 {
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700165 SkipListLayer* newLayer = new SkipListLayer();
166 m_skipList.push_back(newLayer);
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800167
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700168 updateTable[(m_skipList.size() - 1)] = newLayer->begin();
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800169 }
170
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700171 size_t layer = 0;
172 for (SkipList::iterator i = m_skipList.begin();
173 i != m_skipList.end() && layer <= randomLayer; ++i)
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800174 {
175 if (updateTable[layer] == (*i)->end() && !insertInFront)
176 {
177 (*i)->push_back(entry);
178 SkipListLayer::iterator last = (*i)->end();
179 --last;
180 entry->setIterator(layer, last);
181
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700182 NFD_LOG_TRACE("pushback " << &(*last));
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800183 }
184 else if (updateTable[layer] == (*i)->end() && insertInFront)
185 {
186 (*i)->push_front(entry);
187 entry->setIterator(layer, (*i)->begin());
188
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700189 NFD_LOG_TRACE("pushfront ");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800190 }
191 else
192 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700193 NFD_LOG_TRACE("insertafter");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800194 ++updateTable[layer]; // insert after
195 SkipListLayer::iterator position = (*i)->insert(updateTable[layer], entry);
196 entry->setIterator(layer, position); // save iterator where item was inserted
197 }
198 layer++;
199 }
200
201 printSkipList();
202
203 return std::make_pair(entry, true);
Junxiao Shi0fcb41e2014-01-24 10:29:43 -0700204}
205
206bool
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800207Cs::insert(const Data& data, bool isUnsolicited)
Junxiao Shi0fcb41e2014-01-24 10:29:43 -0700208{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700209 NFD_LOG_TRACE("insert() " << data.getName());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800210
211 if (isFull())
212 {
213 evictItem();
214 }
215
216 //pointer and insertion status
217 std::pair< shared_ptr<cs::Entry>, bool> entry = insertToSkipList(data, isUnsolicited);
218
219 //new entry
220 if (entry.first && (entry.second == true))
221 {
222 m_contentByArrival.push(entry.first);
223 m_contentByStaleness.push(entry.first);
224
225 if (entry.first->isUnsolicited())
226 m_unsolicitedContent.push(entry.first);
227
228 return true;
229 }
230
Junxiao Shi0fcb41e2014-01-24 10:29:43 -0700231 return false;
232}
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800233
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700234size_t
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800235Cs::pickRandomLayer() const
Junxiao Shi0fcb41e2014-01-24 10:29:43 -0700236{
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800237 int layer = -1;
238 int randomValue;
239
240 do
241 {
242 layer++;
243 randomValue = rand() % 100 + 1;
244 }
245 while ( (randomValue < SKIPLIST_PROBABILITY) && (layer < SKIPLIST_MAX_LAYERS) );
246
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700247 return static_cast<size_t>(layer);
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800248}
249
250bool
251Cs::isFull() const
252{
253 if (size() >= m_nMaxPackets) //size of the first layer vs. max size
254 return true;
255
256 return false;
257}
258
259bool
260Cs::eraseFromSkipList(shared_ptr<cs::Entry> entry)
261{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700262 NFD_LOG_TRACE("eraseFromSkipList() " << entry->getName());
263 NFD_LOG_TRACE("SkipList size " << size());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800264
265 bool isErased = false;
266
267 int layer = m_skipList.size() - 1;
268 for (SkipList::reverse_iterator rit = m_skipList.rbegin(); rit != m_skipList.rend(); ++rit)
269 {
270 const std::map<int, std::list< shared_ptr<cs::Entry> >::iterator>& iterators = entry->getIterators();
271 std::map<int, std::list< shared_ptr<cs::Entry> >::iterator>::const_iterator it = iterators.find(layer);
272 if (it != iterators.end())
273 {
274 (*rit)->erase(it->second);
275 entry->removeIterator(layer);
276 isErased = true;
277 }
278
279 layer--;
280 }
281
282 printSkipList();
283
284 //remove layers that do not contain any elements (starting from the second layer)
285 for (SkipList::iterator it = (++m_skipList.begin()); it != m_skipList.end();)
286 {
287 if ((*it)->empty())
288 {
289 it = m_skipList.erase(it);
290 }
291 else
292 ++it;
293 }
294
295 return isErased;
296}
297
298bool
299Cs::evictItem()
300{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700301 NFD_LOG_TRACE("evictItem()");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800302
303 //because there is a possibility that this item is in a queue, but no longer in skiplist
304 while ( !m_unsolicitedContent.empty() )
305 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700306 NFD_LOG_TRACE("Evict from unsolicited queue");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800307
308 shared_ptr<cs::Entry> entry = m_unsolicitedContent.front();
309 m_unsolicitedContent.pop();
310 bool isErased = eraseFromSkipList(entry);
311
312 if (isErased)
313 return true;
314 }
315
316 //because there is a possibility that this item is in a queue, but no longer in skiplist
317 int nIterations = size() * 0.01; // 1% of the Content Store
318 while ( !m_contentByStaleness.empty() )
319 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700320 NFD_LOG_TRACE("Evict from staleness queue");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800321
322 shared_ptr<cs::Entry> entry = m_contentByStaleness.top();
323
324 //because stale time could be updated by the duplicate packet
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700325 if (entry->getStaleTime() < time::steady_clock::now())
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800326 {
327 m_contentByStaleness.pop();
328 bool isErased = eraseFromSkipList(entry);
329
330 if (isErased)
331 return true;
332 }
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700333 else if ( (entry->getStaleTime() > time::steady_clock::now()) && entry->wasRefreshedByDuplicate() )
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800334 {
335 m_contentByStaleness.pop();
336 m_contentByStaleness.push(entry); // place in a right order
337
338 nIterations--;
339 // if 1% of the CS are non-expired refreshed CS entries (allocated sequentially),
340 // then stop to prevent too many iterations
341 if ( nIterations <= 0 )
342 break;
343 }
344 else //no further item will be expired, stop
345 {
346 break;
347 }
348 }
349
350 //because there is a possibility that this item is in a queue, but no longer in skiplist
351 while ( !m_contentByArrival.empty() )
352 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700353 NFD_LOG_TRACE("Evict from arrival queue");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800354
355 shared_ptr<cs::Entry> entry = m_contentByArrival.front();
356 m_contentByArrival.pop();
357 bool isErased = eraseFromSkipList(entry);
358
359 if (isErased)
360 return true;
361 }
362
363 return false;
364}
365
366const Data*
367Cs::find(const Interest& interest) const
368{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700369 NFD_LOG_TRACE("find() " << interest.getName());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800370
371 bool isIterated = false;
372 SkipList::const_reverse_iterator topLayer = m_skipList.rbegin();
373 SkipListLayer::iterator head = (*topLayer)->begin();
374
375 if ( !(*topLayer)->empty() )
376 {
377 //start from the upper layer towards bottom
378 int layer = m_skipList.size() - 1;
379 for (SkipList::const_reverse_iterator rit = topLayer; rit != m_skipList.rend(); ++rit)
380 {
381 //if we didn't do any iterations on the higher layers, start from the begin() again
382 if (!isIterated)
383 head = (*rit)->begin();
384
385 if (head != (*rit)->end())
386 {
387 // it happens when begin() contains the element we want to find
388 if ( !isIterated && (interest.getName().isPrefixOf((*head)->getName())) )
389 {
390 if (layer > 0)
391 {
392 layer--;
393 continue; // try lower layer
394 }
395 else
396 {
397 isIterated = true;
398 }
399 }
400 else
401 {
402 SkipListLayer::iterator it = head;
403
404 while ( (*it)->getName() < interest.getName() )
405 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700406 NFD_LOG_TRACE((*it)->getName() << " < " << interest.getName());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800407 head = it;
408 isIterated = true;
409
410 ++it;
411 if (it == (*rit)->end())
412 break;
413 }
414 }
415 }
416
417 if (layer > 0)
418 {
419 head = (*head)->getIterators().find(layer - 1)->second; // move HEAD to the lower layer
420 }
421 else //if we reached the first layer
422 {
423 if ( isIterated )
424 return selectChild(interest, head);
425 }
426
427 layer--;
428 }
429 }
430
Alexander Afanasyevc9765df2014-01-25 19:24:27 -0800431 return 0;
Junxiao Shi0fcb41e2014-01-24 10:29:43 -0700432}
433
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800434// because skip list is a probabilistic data structure and the way it is traversed,
435// there is no guarantee that startingPoint is an element preceding the leftmost child
436const Data*
437Cs::selectChild(const Interest& interest, SkipListLayer::iterator startingPoint) const
438{
439 BOOST_ASSERT( startingPoint != (*m_skipList.begin())->end() );
440
441 if (startingPoint != (*m_skipList.begin())->begin())
442 {
443 BOOST_ASSERT( (*startingPoint)->getName() < interest.getName() );
444 }
445
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700446 NFD_LOG_TRACE("selectChild() " << interest.getChildSelector() << " " << (*startingPoint)->getName());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800447
448 bool hasLeftmostSelector = (interest.getChildSelector() <= 0);
449 bool hasRightmostSelector = !hasLeftmostSelector;
450
451 if (hasLeftmostSelector)
452 {
453 bool doesInterestContainDigest = recognizeInterestWithDigest(interest, *startingPoint);
454 bool isInPrefix = false;
455
456 if (doesInterestContainDigest)
457 {
458 isInPrefix = interest.getName().getPrefix(-1).isPrefixOf((*startingPoint)->getName());
459 }
460 else
461 {
462 isInPrefix = interest.getName().isPrefixOf((*startingPoint)->getName());
463 }
464
465 if (isInPrefix)
466 {
467 if (doesComplyWithSelectors(interest, *startingPoint))
468 {
469 return &(*startingPoint)->getData();
470 }
471 }
472 }
473
474 //iterate to the right
475 SkipListLayer::iterator rightmost = startingPoint;
476 if (startingPoint != (*m_skipList.begin())->end())
477 {
478 SkipListLayer::iterator rightmostCandidate = startingPoint;
479 Name currentChildPrefix("");
480
481 while (true)
482 {
483 ++rightmostCandidate;
484
485 bool isInBoundaries = (rightmostCandidate != (*m_skipList.begin())->end());
486 bool isInPrefix = false;
487 bool doesInterestContainDigest = false;
488 if (isInBoundaries)
489 {
490 doesInterestContainDigest = recognizeInterestWithDigest(interest, *rightmostCandidate);
491
492 if (doesInterestContainDigest)
493 {
494 isInPrefix = interest.getName().getPrefix(-1).isPrefixOf((*rightmostCandidate)->getName());
495 }
496 else
497 {
498 isInPrefix = interest.getName().isPrefixOf((*rightmostCandidate)->getName());
499 }
500 }
501
502 if (isInPrefix)
503 {
504 if (doesComplyWithSelectors(interest, *rightmostCandidate))
505 {
506 if (hasLeftmostSelector)
507 {
508 return &(*rightmostCandidate)->getData();
509 }
510
511 if (hasRightmostSelector)
512 {
513 if (doesInterestContainDigest)
514 {
515 // get prefix which is one component longer than Interest name (without digest)
516 const Name& childPrefix = (*rightmostCandidate)->getName().getPrefix(interest.getName().size());
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700517 NFD_LOG_TRACE("Child prefix" << childPrefix);
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800518
519 if ( currentChildPrefix.empty() || (childPrefix != currentChildPrefix) )
520 {
521 currentChildPrefix = childPrefix;
522 rightmost = rightmostCandidate;
523 }
524 }
525 else
526 {
527 // get prefix which is one component longer than Interest name
528 const Name& childPrefix = (*rightmostCandidate)->getName().getPrefix(interest.getName().size() + 1);
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700529 NFD_LOG_TRACE("Child prefix" << childPrefix);
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800530
531 if ( currentChildPrefix.empty() || (childPrefix != currentChildPrefix) )
532 {
533 currentChildPrefix = childPrefix;
534 rightmost = rightmostCandidate;
535 }
536 }
537 }
538 }
539 }
540 else
541 break;
542 }
543 }
544
545 if (rightmost != startingPoint)
546 {
547 return &(*rightmost)->getData();
548 }
549
550 if (hasRightmostSelector) // if rightmost was not found, try starting point
551 {
552 bool doesInterestContainDigest = recognizeInterestWithDigest(interest, *startingPoint);
553 bool isInPrefix = false;
554
555 if (doesInterestContainDigest)
556 {
557 isInPrefix = interest.getName().getPrefix(-1).isPrefixOf((*startingPoint)->getName());
558 }
559 else
560 {
561 isInPrefix = interest.getName().isPrefixOf((*startingPoint)->getName());
562 }
563
564 if (isInPrefix)
565 {
566 if (doesComplyWithSelectors(interest, *startingPoint))
567 {
568 return &(*startingPoint)->getData();
569 }
570 }
571 }
572
573 return 0;
574}
575
576bool
577Cs::doesComplyWithSelectors(const Interest& interest, shared_ptr<cs::Entry> entry) const
578{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700579 NFD_LOG_TRACE("doesComplyWithSelectors()");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800580
581 /// \todo The following detection is not correct
582 /// 1. If data name ends with 32-octet component doesn't mean that this component is digest
583 /// 2. Only min/max selectors (both 0) can be specified, all other selectors do not make sense
584 /// for interests with digest (though not sure if we need to enforce this)
585 bool doesInterestContainDigest = recognizeInterestWithDigest(interest, entry);
586 if ( doesInterestContainDigest )
587 {
588 const ndn::name::Component& last = interest.getName().get(-1);
589 const ndn::ConstBufferPtr& digest = entry->getDigest();
590
591 BOOST_ASSERT(digest->size() == last.value_size());
592 BOOST_ASSERT(digest->size() == ndn::crypto::SHA256_DIGEST_SIZE);
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700593
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800594 if (std::memcmp(digest->buf(), last.value(), ndn::crypto::SHA256_DIGEST_SIZE) != 0)
595 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700596 NFD_LOG_TRACE("violates implicit digest");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800597 return false;
598 }
599 }
600
601 if ( !doesInterestContainDigest )
602 {
603 if (interest.getMinSuffixComponents() >= 0)
604 {
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700605 size_t minDataNameLength = interest.getName().size() + interest.getMinSuffixComponents();
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800606
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700607 bool isSatisfied = (minDataNameLength <= entry->getName().size());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800608 if ( !isSatisfied )
609 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700610 NFD_LOG_TRACE("violates minComponents");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800611 return false;
612 }
613 }
614
615 if (interest.getMaxSuffixComponents() >= 0)
616 {
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700617 size_t maxDataNameLength = interest.getName().size() + interest.getMaxSuffixComponents();
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800618
Alexander Afanasyevefea8fe2014-03-23 00:00:35 -0700619 bool isSatisfied = (maxDataNameLength >= entry->getName().size());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800620 if ( !isSatisfied )
621 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700622 NFD_LOG_TRACE("violates maxComponents");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800623 return false;
624 }
625 }
626 }
627
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700628 if (interest.getMustBeFresh() && entry->getStaleTime() < time::steady_clock::now())
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800629 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700630 NFD_LOG_TRACE("violates mustBeFresh");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800631 return false;
632 }
633
634 if ( doesInterestContainDigest )
635 {
636 const ndn::name::Component& lastComponent = entry->getName().get(-1);
637
638 if ( !lastComponent.empty() )
639 {
640 if (interest.getExclude().isExcluded(lastComponent))
641 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700642 NFD_LOG_TRACE("violates exclusion");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800643 return false;
644 }
645 }
646 }
647 else
648 {
649 if (entry->getName().size() >= interest.getName().size() + 1)
650 {
651 const ndn::name::Component& nextComponent = entry->getName().get(interest.getName().size());
652
653 if ( !nextComponent.empty() )
654 {
655 if (interest.getExclude().isExcluded(nextComponent))
656 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700657 NFD_LOG_TRACE("violates exclusion");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800658 return false;
659 }
660 }
661 }
662 }
663
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700664 NFD_LOG_TRACE("complies");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800665 return true;
666}
667
668bool
669Cs::recognizeInterestWithDigest(const Interest& interest, shared_ptr<cs::Entry> entry) const
670{
671 // only when min selector is not specified or specified with value of 0
672 // and Interest's name length is exactly the length of the name of CS entry
673 if (interest.getMinSuffixComponents() <= 0 &&
674 interest.getName().size() == (entry->getName().size()))
675 {
676 const ndn::name::Component& last = interest.getName().get(-1);
677 if (last.value_size() == ndn::crypto::SHA256_DIGEST_SIZE)
678 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700679 NFD_LOG_TRACE("digest recognized");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800680 return true;
681 }
682 }
683
684 return false;
685}
686
687void
688Cs::erase(const Name& exactName)
689{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700690 NFD_LOG_TRACE("insert() " << exactName << ", "
691 << "skipList size " << size());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800692
693 bool isIterated = false;
694 SkipListLayer::iterator updateTable[SKIPLIST_MAX_LAYERS];
695 SkipList::reverse_iterator topLayer = m_skipList.rbegin();
696 SkipListLayer::iterator head = (*topLayer)->begin();
697
698 if ( !(*topLayer)->empty() )
699 {
700 //start from the upper layer towards bottom
701 int layer = m_skipList.size() - 1;
702 for (SkipList::reverse_iterator rit = topLayer; rit != m_skipList.rend(); ++rit)
703 {
704 //if we didn't do any iterations on the higher layers, start from the begin() again
705 if ( !isIterated )
706 head = (*rit)->begin();
707
708 updateTable[layer] = head;
709
710 if (head != (*rit)->end())
711 {
712 // it can happen when begin() contains the element we want to remove
713 if ( !isIterated && ((*head)->getName() == exactName) )
714 {
715 eraseFromSkipList(*head);
716 return;
717 }
718 else
719 {
720 SkipListLayer::iterator it = head;
721
722 while ((*it)->getName() < exactName)
723 {
724 head = it;
725 updateTable[layer] = it;
726 isIterated = true;
727
728 ++it;
729 if ( it == (*rit)->end() )
730 break;
731 }
732 }
733 }
734
735 if (layer > 0)
736 head = (*head)->getIterators().find(layer - 1)->second; // move HEAD to the lower layer
737
738 layer--;
739 }
740 }
741 else
742 {
743 return;
744 }
745
746 head = updateTable[0];
747 ++head; // look at the next slot to check if it contains the item we want to remove
748
749 bool isCsEmpty = (size() == 0);
750 bool isInBoundaries = (head != (*m_skipList.begin())->end());
751 bool isNameIdentical = false;
752 if (!isCsEmpty && isInBoundaries)
753 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700754 NFD_LOG_TRACE("Identical? " << (*head)->getName());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800755 isNameIdentical = (*head)->getName() == exactName;
756 }
757
758 if (isNameIdentical)
759 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700760 NFD_LOG_TRACE("Found target " << (*head)->getName());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800761 eraseFromSkipList(*head);
762 }
763
764 printSkipList();
765}
766
767void
768Cs::printSkipList() const
769{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700770 NFD_LOG_TRACE("print()");
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800771 //start from the upper layer towards bottom
772 int layer = m_skipList.size() - 1;
773 for (SkipList::const_reverse_iterator rit = m_skipList.rbegin(); rit != m_skipList.rend(); ++rit)
774 {
775 for (SkipListLayer::iterator it = (*rit)->begin(); it != (*rit)->end(); ++it)
776 {
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700777 NFD_LOG_TRACE("Layer " << layer << " " << (*it)->getName());
Ilya Moiseenko76cf77a2014-03-05 14:35:51 -0800778 }
779 layer--;
780 }
781}
Junxiao Shi0fcb41e2014-01-24 10:29:43 -0700782
Alexander Afanasyev18bbf812014-01-29 01:40:23 -0800783} //namespace nfd