⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kademlia.c

📁 P2P模拟器
💻 C
📖 第 1 页 / 共 5 页
字号:
    return;  assert(id);  assert(ip);}// }}}// {{{ k_bucket::k_bucketk_bucket::k_bucket(k_bucket *parent, Kademlia *k) : parent(parent), _kademlia(k){  child[0] = child[1] = 0;  nodes = 0;  replacement_cache = 0;  leaf = false;}// }}}// {{{ k_bucket::~k_bucketk_bucket::~k_bucket(){  if(leaf) {    delete nodes;    delete replacement_cache;    return;  }  delete child[0];  delete child[1];}// }}}// {{{ k_bucket::traversevoidk_bucket::traverse(k_traverser *traverser, Kademlia *k, string prefix, unsigned depth, unsigned leftright){//  Kademlia::NodeID _id = kademlia()->id();  // KDEBUG(1) << "k_bucket::traverser for " << traverser->type() << ", prefix = " << prefix << endl;  checkrep();  if(!leaf) {    if(!k->alive() || !child[0])      return;    child[0]->traverse(traverser, k, prefix + "0", depth+1, 0);    if(!k->alive() || !child[1] || leaf)      return;    child[1]->traverse(traverser, k, prefix + "1", depth+1, 1);    if(!k->alive())      return;    checkrep();    return;  }  if(!k->alive())    return;  // we're a leaf  traverser->execute(this, prefix, depth, leftright);  checkrep();}// }}}// {{{ k_bucket::find_nodevoidk_bucket::find_node(Kademlia::NodeID key, vector<k_nodeinfo*> *v,    unsigned nhits, unsigned depth){  checkrep();//  // Kademlia::NodeID _id = kademlia()->id();  Kademlia::closer::n = key;  // recurse deeper in the right direction if we can  if(!leaf) {    unsigned leftmostbit = Kademlia::getbit(key, depth);    if(v->size() < nhits)      child[leftmostbit]->find_node(key, v, nhits, depth+1);    if(v->size() < nhits)      child[leftmostbit^1]->find_node(key, v, nhits, depth+1);    checkrep();    return;  }  // collect stuff from the k-bucket itself  for(unsigned i=0; i<nodes->size(); i++) {    v->push_back(nodes->get(i));    if(v->size() >= nhits) {      checkrep();      return;    }  }  if(Kademlia::use_replacement_cache != Kademlia::FULL) {    checkrep();    return;  }  // NB: optimization.  // collect stuff from replacement cache.  for(int i = replacement_cache->size()-1; i >= 0; i--) {    v->push_back(replacement_cache->get(i));    if(v->size() >= nhits) {      checkrep();      return;    }  }  checkrep();}// }}}// {{{ k_bucket::insert// pre: id is in flyweight, its timestamp (lastts) has been set.// post: if id was already in k-bucket, its position is updated.//       if id was not in k-bucket ://              if k-bucket has space, id is added//              if k-bucket is full, id is put in replacement cachevoidk_bucket::insert(Kademlia::NodeID id, bool touch, bool init_state, string prefix, unsigned depth){  checkrep();  // assert(kademlia()->flyweight.find(id, 0));  // Kademlia::NodeID _id = kademlia()->id();  // KDEBUG(1) << "k_bucket::insert " << Kademlia::printbits(id) << ", prefix = " << prefix << endl;  // recurse deeper if we can  if(!leaf) {    unsigned leftmostbit = Kademlia::getbit(id, depth);    // KDEBUG(1) << "k_bucket::insert heading towards " << leftmostbit << endl;    child[leftmostbit]->insert(id, touch, init_state, prefix + (leftmostbit ? "1" : "0"), depth+1);    checkrep();    return;  }  // if not in k-bucket yet, or there's more space: insert it.  if(nodes->contains(id) || !nodes->full()) {    nodes->insert(id, touch);    nodes->checkrep();    return;  }  if(Kademlia::use_replacement_cache == Kademlia::DISABLED) {    checkrep();    return;  }  // we're full.  put in replacement_cache.  replacement_cache->insert(id, touch);  replacement_cache->checkrep();  checkrep();}// }}}// {{{ k_bucket::erasevoidk_bucket::erase(Kademlia::NodeID id, string prefix, unsigned depth){  checkrep();  // recurse deeper  if(!leaf) {    unsigned leftmostbit = Kademlia::getbit(id, depth);    child[leftmostbit]->erase(id, prefix + (leftmostbit ? "1" : "0"), depth+1);    checkrep();    return;  }  // if not in k-bucket itself, it must be in replacement_cache.  remove from  // there.  if(!nodes->contains(id)) {    k_nodeinfo *ki = kademlia()->flyweight[id];    if(replacement_cache->contains(ki->id))      replacement_cache->erase(ki->id);    checkrep();    return;  }  // remove from k-bucket  nodes->erase(id);  // get latest from replacement_cache to nodes  if(Kademlia::use_replacement_cache == Kademlia::DISABLED || !replacement_cache->size()) {    checkrep();    return;  }  k_nodeinfo *ki = replacement_cache->last(); // youngest  // assert(ki);  // assert(ki->id);  // assert(kademlia()->flyweight.find(ki->id, 0));  nodes->insert(ki->id, false);  replacement_cache->erase(ki->id);  checkrep();}// }}}// {{{ k_bucket::collapse// transform back from node to leafvoidk_bucket::collapse(){  // Kademlia::NodeID _id = kademlia()->id();  // KDEBUG(2) << "k_bucket::collapse" << endl;  checkrep();  if(!leaf) {    child[0]->collapse();    child[1]->collapse();  } else {    nodes->clear();    replacement_cache->clear();  }  checkrep();}// }}}// {{{ k_bucket::checkrepvoidk_bucket::checkrep(){  if(!Kademlia::docheckrep)    return;  assert(_kademlia);  if(!leaf) {    assert(child[0] && child[1]);    return;  }  // checkreps for leaf  assert(nodes);  assert(replacement_cache);  nodes->checkrep();  replacement_cache->checkrep();}// }}}// {{{ k_stabilizer::executevoidk_stabilizer::execute(k_bucket *k, string prefix, unsigned depth, unsigned leftright){  // for // KDEBUG purposes  Kademlia *mykademlia = k->kademlia();  Kademlia::NodeID _id = mykademlia->id();  if(!k->leaf || !mykademlia->alive())    return;  // return if any entry in this k-bucket is fresh  if(!Kademlia::force_stabilization) {    for(unsigned i = 0; i < k->nodes->size(); i++) {      // XXX: this is the sign of bad shit going on.  get out.      // it doesn't really, really matter that we're not completing this round of      // stabilization.  better than crashing the simulator, anyway.      k_nodeinfo *ki = k->nodes->get(i);      if(!mykademlia->flyweight[ki->id])        return;      if(now() - ki->lastts < Kademlia::refresh_rate)        return;    }  }  // Oh.  stuff in this k-bucket is old, or we don't know anything. Lookup a  // random key in this range.  Kademlia::NodeID mask = 0L;  for(unsigned i=0; i<Kademlia::idsize; i++) {    unsigned bit = 1;    if(i > depth)      bit = (unsigned) random() & 0x1;    mask |= (((Kademlia::NodeID) bit) << (Kademlia::idsize-i));  }  Kademlia::NodeID random_key = _id & mask;  // KDEBUG(2) << "k_stabilizer: prefix = " << prefix << ", mask = " << Kademlia::printbits(mask) << ", random_key = " << Kademlia::printbits(random_key) << endl;  // lookup the random key and update this k-bucket with what we learn  Kademlia::lookup_args la(mykademlia->id(), mykademlia->ip(), random_key);  la.stattype = Kademlia::STAT_STABILIZE;  Kademlia::lookup_result lr;  mykademlia->do_lookup(&la, &lr);  if(!mykademlia->alive())    return;  // update our k-buckets  NODES_ITER(&lr.results) {    mykademlia->update_k_bucket(i->id, i->ip);  }}// }}}// {{{ k_stabilized::executevoidk_stabilized::execute(k_bucket *k, string prefix, unsigned depth, unsigned leftright){  // for // KDEBUG purposes  Kademlia::NodeID _id = k->kademlia()->id();  // if we know about nodes in this part of the ID space, great.  if(!k->nodes->empty())    return;  // KDEBUG(2) << "stabilized: " << prefix << " not present, depth = " << depth << ", prefix = " << prefix << ", leftright = " << leftright << endl;  //  // Node claims there is no node to satisfy this entry in the finger table.  // Check whether that is true.  //  Kademlia::NodeID upper = 0, lower = 0;  for(unsigned i=0; i<Kademlia::idsize; i++) {    if(i < (depth-1)) {      unsigned bit = Kademlia::getbit(_id, i);      lower |= (((Kademlia::NodeID) bit) << Kademlia::idsize-i-1);      upper |= (((Kademlia::NodeID) bit) << Kademlia::idsize-i-1);    } else if(i == (depth-1) && leftright) {      lower |= (((Kademlia::NodeID) leftright) << Kademlia::idsize-i-1);      upper |= (((Kademlia::NodeID) leftright) << Kademlia::idsize-i-1);    } else if(i > (depth-1))      upper |= (((Kademlia::NodeID) 1) << Kademlia::idsize-i-1);  }  // KDEBUG(2) << "stabilized: lower = " << Kademlia::printID(lower) << endl;  // KDEBUG(2) << "stabilized: upper = " << Kademlia::printID(upper) << endl;  // yields the node with smallest id greater than lower  vector<Kademlia::NodeID>::const_iterator it = upper_bound(_v->begin(), _v->end(), lower);  // check that this is smaller than upper.  if so, then this node would  // qualify for this entry in the finger table, so the node that says there  // is no such is WRONG.  if(it != _v->end() && *it <= upper) {    // KDEBUG(2) << "stabilized: prefix " << prefix << " on depth " << depth << " is invalid, but " << Kademlia::printID(*it) << " matches " << endl;    _stabilized = false;  }  // // assert(false);}// }}}// {{{ k_finder::executevoidk_finder::execute(k_bucket *k, string prefix, unsigned depth, unsigned leftright){  if(!k->leaf)    return;  k->checkrep();  for(unsigned i = 0; i < k->nodes->size(); i++) {    if(k->nodes->get(i)->id == _n)      _found++;  }  for(int i = k->replacement_cache->size()-1; i >= 0; i--)    if(k->replacement_cache->get(i)->id == _n)      _found++;}// }}}// {{{ k_dumper::executevoidk_dumper::execute(k_bucket *k, string prefix, unsigned depth, unsigned leftright){  string spaces = "";  for(unsigned i=0; i<depth; i++)    spaces += "  ";  cout << spaces << "prefix: " << prefix << ", depth " << depth << endl;  for(unsigned i = 0; i < k->nodes->size(); i++) {    k_nodeinfo *ki = k->nodes->get(i);    cout << spaces << "  " << Kademlia::printbits(ki->id) << ", lastts = " << ki->lastts << endl;  }  cout << spaces << "prefix: " << prefix << ", depth " << depth << ", replacement cache: " << endl;  for(int i = k->replacement_cache->size()-1; i >= 0; i--) {    cout << spaces << "  " << Kademlia::printID(k->replacement_cache->get(i)->id) << ", lastts = " << k->replacement_cache->get(i)->lastts << endl;  }}// }}}// {{{ k_check::executevoidk_check::execute(k_bucket *k, string prefix, unsigned depth, unsigned leftright){  if(!k->leaf)    return;  k->checkrep();  const set<Node*> *l = Network::Instance()->getallnodes();  // go through all pointers in node  for(unsigned i = 0; i < k->nodes->size(); i++) {    // k_nodeinfo *ki = k->nodes->get(i);    for(set<Node*>::iterator pos = l->begin(); pos != l->end(); ++pos) {      Kademlia *kad = (Kademlia*) *pos;      if(kad->id() == k->kademlia()->id())        continue;      /*      for(HashMap<Kademlia::NodeID, k_nodeinfo*>::const_iterator j = kad->flyweight.begin(); j; j++)          // assert(j.value() != ki);      */    }  }  for(int i = k->replacement_cache->size()-1; i >= 0; i--) {    for(set<Node*>::iterator pos = l->begin(); pos != l->end(); ++pos) {      Kademlia *kad = (Kademlia*) *pos;      if(kad->id() == k->kademlia()->id())        continue;      /*      for(HashMap<Kademlia::NodeID, k_nodeinfo*>::const_iterator j = kad->flyweight.begin(); j; j++)          // assert(j.value() != *i);      */    }  }}// }}}#include "p2psim/bighashmap.cc"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -