From 1eef862cc33e6f4fad021a1870c7a8af2fd93b7c Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 17 Nov 2010 15:42:23 +0000 Subject: 2010-11-18 Tatsuhiro Tsujikawa Replaced BNode with DHTBucketTreeNode which is 2 times efficient. * src/BNode.cc: Removed * src/BNode.h: Removed * src/DHTBucketTree.cc * src/DHTBucketTree.h * src/DHTRoutingTable.cc * src/DHTRoutingTable.h * src/Makefile.am * test/BNodeTest.cc: Removed * test/DHTBucketTreeTest.cc * test/Makefile.am --- src/DHTBucketTree.cc | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 src/DHTBucketTree.cc (limited to 'src/DHTBucketTree.cc') diff --git a/src/DHTBucketTree.cc b/src/DHTBucketTree.cc new file mode 100644 index 00000000..d7f0ae56 --- /dev/null +++ b/src/DHTBucketTree.cc @@ -0,0 +1,233 @@ +/* */ +#include "DHTBucketTree.h" + +#include +#include + +#include "DHTBucket.h" +#include "DHTNode.h" + +namespace aria2 { + +DHTBucketTreeNode::DHTBucketTreeNode +(DHTBucketTreeNode* left, + DHTBucketTreeNode* right) + : parent_(0), + left_(left), + right_(right) +{ + resetRelation(); +} + +DHTBucketTreeNode::DHTBucketTreeNode(const SharedHandle& bucket) + : parent_(0), + left_(0), + right_(0), + bucket_(bucket) +{ + memcpy(minId_, bucket_->getMinID(), DHT_ID_LENGTH); + memcpy(maxId_, bucket_->getMaxID(), DHT_ID_LENGTH); +} + +DHTBucketTreeNode::~DHTBucketTreeNode() +{ + delete left_; + delete right_; +} + +void DHTBucketTreeNode::resetRelation() +{ + left_->setParent(this); + right_->setParent(this); + memcpy(minId_, left_->getMinId(), DHT_ID_LENGTH); + memcpy(maxId_, right_->getMaxId(), DHT_ID_LENGTH); +} + +DHTBucketTreeNode* DHTBucketTreeNode::dig(const unsigned char* key) +{ + if(leaf()) { + return 0; + } + if(left_->isInRange(key)) { + return left_; + } else { + return right_; + } +} + +bool DHTBucketTreeNode::isInRange(const unsigned char* key) const +{ + return + !std::lexicographical_compare(&key[0], &key[DHT_ID_LENGTH], + &minId_[0], &minId_[DHT_ID_LENGTH]) && + !std::lexicographical_compare(&maxId_[0], &maxId_[DHT_ID_LENGTH], + &key[0], &key[DHT_ID_LENGTH]); +} + +void DHTBucketTreeNode::split() +{ + SharedHandle leftBucket = bucket_->split(); + left_ = new DHTBucketTreeNode(leftBucket); + right_ = new DHTBucketTreeNode(bucket_); + bucket_.reset(); + resetRelation(); +} + +namespace dht { + +DHTBucketTreeNode* findTreeNodeFor +(DHTBucketTreeNode* root, const unsigned char* key) +{ + if(root->leaf()) { + return root; + } else { + return findTreeNodeFor(root->dig(key), key); + } +} + +SharedHandle findBucketFor +(DHTBucketTreeNode* root, const unsigned char* key) +{ + DHTBucketTreeNode* leaf = findTreeNodeFor(root, key); + return leaf->getBucket(); +} + +namespace { +void collectNodes +(std::vector >& nodes, + const SharedHandle& bucket) +{ + std::vector > goodNodes; + bucket->getGoodNodes(goodNodes); + nodes.insert(nodes.end(), goodNodes.begin(), goodNodes.end()); +} +} // namespace + +namespace { +void collectDownwardLeftFirst +(std::vector >& nodes, DHTBucketTreeNode* tnode) +{ + if(tnode->leaf()) { + collectNodes(nodes, tnode->getBucket()); + } else { + collectDownwardLeftFirst(nodes, tnode->getLeft()); + if(nodes.size() < DHTBucket::K) { + collectDownwardLeftFirst(nodes, tnode->getRight()); + } + } +} +} //namespace + +namespace { +void collectDownwardRightFirst +(std::vector >& nodes, DHTBucketTreeNode* tnode) +{ + if(tnode->leaf()) { + collectNodes(nodes, tnode->getBucket()); + } else { + collectDownwardRightFirst(nodes, tnode->getRight()); + if(nodes.size() < DHTBucket::K) { + collectDownwardRightFirst(nodes, tnode->getLeft()); + } + } +} +} //namespace + +namespace { +void collectUpward +(std::vector >& nodes, DHTBucketTreeNode* from) +{ + while(1) { + DHTBucketTreeNode* parent = from->getParent(); + if(!parent) { + break; + } + if(parent->getLeft() == from) { + collectNodes(nodes, parent->getRight()->getBucket()); + } else { + collectNodes(nodes, parent->getLeft()->getBucket()); + } + from = parent; + parent = parent->getParent(); + if(DHTBucket::K <= nodes.size()) { + break; + } + } +} +} // namespace + +void findClosestKNodes +(std::vector >& nodes, + DHTBucketTreeNode* root, + const unsigned char* key) +{ + size_t nodesSize = nodes.size(); + if(DHTBucket::K <= nodesSize) { + return; + } + DHTBucketTreeNode* leaf = findTreeNodeFor(root, key); + if(leaf == root) { + collectNodes(nodes, leaf->getBucket()); + } else { + DHTBucketTreeNode* parent = leaf->getParent(); + if(parent->getLeft() == leaf) { + collectDownwardLeftFirst(nodes, parent); + } else { + collectDownwardRightFirst(nodes, parent); + } + if(nodes.size() < DHTBucket::K) { + collectUpward(nodes, parent); + } + } + if(DHTBucket::K < nodes.size()) { + nodes.erase(nodes.begin()+DHTBucket::K, nodes.end()); + } +} + +void enumerateBucket +(std::vector >& buckets, DHTBucketTreeNode* root) +{ + if(root->leaf()) { + buckets.push_back(root->getBucket()); + } else { + enumerateBucket(buckets, root->getLeft()); + enumerateBucket(buckets, root->getRight()); + } +} + +} // namespace dht + +} // namespace aria2 -- cgit