38 compute(
const void* buffer,
size_t length)
48 compute(
const void* buffer,
size_t length)
65 for (
size_t i = 0, last = std::min(prefixLen, name.size()); i < last; ++i) {
66 const name::Component& comp = name[i];
67 h ^= HashFunc::compute(comp.data(), comp.size());
77 size_t last = std::min(prefixLen, name.size());
79 seq.reserve(last + 1);
84 for (
size_t i = 0; i < last; ++i) {
85 const name::Component& comp = name[i];
86 h ^= HashFunc::compute(comp.data(), comp.size());
102 BOOST_ASSERT(
prev ==
nullptr);
103 BOOST_ASSERT(
next ==
nullptr);
122 BOOST_ASSERT(m_options.
minSize > 0);
133 this->computeThresholds();
138 for (
size_t i = 0; i < m_buckets.size(); ++i) {
147 Hashtable::attach(
size_t bucket,
Node* node)
149 node->
prev =
nullptr;
150 node->
next = m_buckets[bucket];
152 if (node->
next !=
nullptr) {
153 BOOST_ASSERT(node->
next->
prev ==
nullptr);
157 m_buckets[bucket] = node;
161 Hashtable::detach(
size_t bucket, Node* node)
163 if (node->prev !=
nullptr) {
164 BOOST_ASSERT(node->prev->next == node);
165 node->prev->next = node->next;
168 BOOST_ASSERT(m_buckets[bucket] == node);
169 m_buckets[bucket] = node->next;
172 if (node->next !=
nullptr) {
173 BOOST_ASSERT(node->next->prev == node);
174 node->next->prev = node->prev;
177 node->prev = node->next =
nullptr;
180 std::pair<const Node*, bool>
181 Hashtable::findOrInsert(
const Name& name,
size_t prefixLen,
HashValue h,
bool allowInsert)
185 for (
const Node* node = m_buckets[bucket]; node !=
nullptr; node = node->next) {
186 if (node->hash == h && name.compare(0, prefixLen, node->entry.getName()) == 0) {
187 NFD_LOG_TRACE(
"found " << name.getPrefix(prefixLen) <<
" hash=" << h <<
" bucket=" << bucket);
188 return {node,
false};
193 NFD_LOG_TRACE(
"not-found " << name.getPrefix(prefixLen) <<
" hash=" << h <<
" bucket=" << bucket);
194 return {
nullptr,
false};
197 Node* node =
new Node(h, name.getPrefix(prefixLen));
198 this->attach(bucket, node);
199 NFD_LOG_TRACE(
"insert " << node->entry.getName() <<
" hash=" << h <<
" bucket=" << bucket);
202 if (m_size > m_expandThreshold) {
203 this->resize(
static_cast<size_t>(m_options.
expandFactor * this->getNBuckets()));
213 return const_cast<Hashtable*
>(
this)->findOrInsert(name, prefixLen, h,
false).first;
219 BOOST_ASSERT(hashes.at(prefixLen) ==
computeHash(name, prefixLen));
220 return const_cast<Hashtable*
>(
this)->findOrInsert(name, prefixLen, hashes[prefixLen],
false).first;
223 std::pair<const Node*, bool>
226 BOOST_ASSERT(hashes.at(prefixLen) ==
computeHash(name, prefixLen));
227 return this->findOrInsert(name, prefixLen, hashes[prefixLen],
true);
233 BOOST_ASSERT(node !=
nullptr);
239 this->detach(bucket, node);
243 if (m_size < m_shrinkThreshold) {
244 size_t newNBuckets = std::max(m_options.
minSize,
245 static_cast<size_t>(m_options.
shrinkFactor * this->getNBuckets()));
246 this->resize(newNBuckets);
251 Hashtable::computeThresholds()
255 NFD_LOG_TRACE(
"thresholds expand=" << m_expandThreshold <<
" shrink=" << m_shrinkThreshold);
259 Hashtable::resize(
size_t newNBuckets)
266 std::vector<Node*> oldBuckets;
267 oldBuckets.swap(m_buckets);
268 m_buckets.resize(newNBuckets);
270 for (Node* head : oldBuckets) {
273 this->attach(bucket, node);
277 this->computeThresholds();
uint32 CityHash32(const char *s, size_t len)
uint64 CityHash64(const char *s, size_t len)
An entry in the name tree.
Entry * getParent() const noexcept
const Name & getName() const noexcept
A hashtable for fast exact name lookup.
void erase(Node *node)
Delete node.
std::pair< const Node *, bool > insert(const Name &name, size_t prefixLen, const HashSequence &hashes)
Find or insert node for name.getPrefix(prefixLen).
const Node * find(const Name &name, size_t prefixLen) const
Find node for name.getPrefix(prefixLen).
Hashtable(const Options &options)
~Hashtable()
Deallocates all nodes.
size_t computeBucketIndex(HashValue h) const
size_t getNBuckets() const
Node(HashValue h, const Name &name)
#define NFD_LOG_INIT(name)
std::vector< HashValue > HashSequence
A sequence of hash values.
HashValue computeHash(const Name &name, size_t prefixLen)
Computes hash value of name.getPrefix(prefixLen).
Node * getNode(const Entry &entry)
std::conditional_t<(sizeof(HashValue) > 4), Hash64, Hash32 > HashFunc
A type with a compute() static method to compute the hash value from a raw buffer.
void foreachNode(N *head, const F &func)
Invoke a function for each node in a doubly linked list.
size_t HashValue
A single hash value.
HashSequence computeHashes(const Name &name, size_t prefixLen)
Computes hash values for each prefix of name.getPrefix(prefixLen).
Provides options for Hashtable.
float expandFactor
When the hashtable is expanded, its new size will be nBuckets*expandFactor.
float shrinkLoadFactor
If the hashtable has less than nBuckets*shrinkLoadFactor nodes, it will be shrunk.
float shrinkFactor
When the hashtable is shrunk, its new size will be max(nBuckets*shrinkFactor, minSize).
float expandLoadFactor
If the hashtable has more than nBuckets*expandLoadFactor nodes, it will be expanded.
HashtableOptions(size_t size=16)
Constructor.
size_t minSize
Minimal number of buckets.
size_t initialSize
Initial number of buckets.