110 likes | 202 Vues
Explore index-based NDN repository storage with query algorithms for fast data access and retrieval. Understand storage structure, indexes, queries, and efficient algorithms for finding data entries. Learn examples of query procedures for precise data retrieval.
E N D
Index-based NDN Repository Junxiao Shi, 2014-06-17
Overall Structure • Storage: read-write storage for id=>Data packet • Index: sorted associative container for Name=>entry • Query algorithm
Storage API • typedef<implementation-defined> Id; • Id put(const Data& data); • Data get(Id id); • forward iterator for (Id, Data) – minimalorforward iterator for (Id, fullName, KeyLocatorHash) – preferred • fullName: full Name including implicit digest • KeyLocatorHash: SHA256 hash of KeyLocator
Storage in SQL Database: Table Structure • Indexes • PRIMARY KEY id
Index API • sorted container • entry type: (Id, fullName, KeyLocatorHash) • order by fullName • bidirectional iterator • lower_bound algorithm
Query Algorithm – Helper Routines • Query type • interest • KeyLocatorHash: SHA256 hash of PublisherPublicKeyLocator selector, or null • minComponents • maxComponents • boolmatchesSimpleSelectors(Query, Index::iterator) • determines whether the Data described by the index entry can satisfy MinSuffixComponent, MaxSuffixComponent, PublisherPublicKeyLocator, Exclude
Query Algorithm – leftmost for (it = index.lower_bound(interest.getName()); it != index.end(); ++it) { if (!interest.getName().isPrefixOf(it->fullName)) return index.end(); if (matchesSimpleSelector(interest, it)) return it; }
Query Algorithm – rightmost boundary = index.lower_bound(interest.getName()); if (boundary == index.end() || !interest.getName().isPrefixOf(boundary->fullName)) return index.end(); last = index.lower_bound(interest.getName().succ()); while (true) { prev = last; --prev; if (prev == boundary) return matchesSimpleSelectors(interest, prev) ? prev : index.end(); first = index.lower_bound(prev->fullName.getPrefix(interest.getName().size() + 1); match = std::find_if(first, last, matchesSimpleSelectors); if (match != last) return match; last = first; }
Query Example – rightmost, non-exact • Dataset: /A/B/d001, /A/C/D/E/d002, /A/C/F/d003, /A/C/G/d004, /A/C/H/I/d005 • Interest /A rightmost MaxSuffixComponents=3 • boundary=/A/B/d001, last=end (one past last entry) • iteration 1: first=/A/C/H/I/d005, last=end, no match • iteration 2: first=/A/C/D/E/d002, last=/A/C/H/I/d005, match=/A/C/F/d003
Query Example – rightmost, exact • Dataset: /A/d000, /A/d000/d001, /A/d002 • Interest /A/d000 rightmost MaxSuffixComponents=0 • boundary=/A/d000, last=/A/d002 • iteration 1: first=/A/d000/d001, last=/A/d002, no match • iteration 2: prev=/A/d000, equals boundary, matchesSimpleSelectorsis true, returns /A/d000
Query Algorithm – rightmost, alternate • start with index.lower_bound(interest.getName().succ()) • iterate to the left, until a match is found • continue to the left, until fullName.at(interest.getName().size()) changes; return the last match • This algorithm is less efficient when • The dataset is a versioned file, where each version has many segments • The Interest wants to fetch the first segment of the last version • This algorithm must iterate over every segment of the last version • This algorithm is more efficient for finding the last segment in a sequence, because it calls index.lower_bound() only once