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

📄 chordfinger.c

📁 P2P模拟器
💻 C
字号:
/* * Copyright (c) 2003-2005 Jinyang Li *                    Massachusetts Institute of Technology *  * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: *  * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */#include  "chordfinger.h"#include "observers/chordobserver.h"#include <iostream>using namespace std;extern bool static_sim;ChordFinger::ChordFinger(IPAddress i, Args &a, LocTable *l) : Chord(i, a, l)  {  _base = a.nget<uint>("base",2,10);  _fingerlets = a.nget<uint>("fingerlets",1,10);  _stab_finger_running = false;  _stab_finger_outstanding = 0;  _stab_finger_timer = a.nget<uint>("fingertimer",10000,10);}//XXX oracle out of datevoidChordFinger::oracle_node_died(IDMap n){  Chord::oracle_node_died(n);  IDMap tmp = loctable->succ(n.id);  if (tmp.ip != n.ip) return;  //lost one of my finger?  vector<IDMap> ids = ChordObserver::Instance(NULL)->get_sorted_nodes();  uint sz = ids.size();  CHID lap = (CHID) -1;  while (lap > 1) {    lap = lap / _base;    for (uint j = 1; j <= (_base-1); j++) {      if (ConsistentHash::between(me.id+lap*j, me.id+lap*(j+1), n.id)) {	loctable->del_node(n);	//get a replacement	IDMap tmpf;	tmpf.id = me.id + j * lap;	uint s_pos = upper_bound(ids.begin(),ids.end(),tmpf, Chord::IDMap::cmp) - ids.begin();	s_pos = s_pos % sz;	if (ConsistentHash::between(tmpf.id, tmpf.id + lap, ids[s_pos].id)) 	  loctable->add_node(ids[s_pos]);	return;      }    }  }  assert(0);}voidChordFinger::oracle_node_joined(IDMap n){  Chord::oracle_node_joined(n);  IDMap tmp = loctable->succ(n.id);  if (tmp.ip == n.ip) return;  //is the new node one of my finger?  CHID lap = (CHID) -1;  while (lap > 1) {    lap = lap / _base;    for (uint j = 1; j <= (_base-1); j++) {      if (ConsistentHash::between(me.id+lap*j, me.id+lap*(j+1), n.id)) {	IDMap s = loctable->succ(me.id + lap * j);	if (ConsistentHash::between(me.id+lap*j, me.id+lap*(j+1), s.id)) {	  //choose the closer one in IDspace	  if (ConsistentHash::between(me.id,s.id,n.id)) {	    loctable->del_node(s);	    loctable->add_node(n);	  }	} else {	  loctable->add_node(n);	} 	return;      }    }  }  assert(0);}voidChordFinger::initstate(){  vector<IDMap> ids = ChordObserver::Instance(NULL)->get_sorted_nodes();  uint sz = ids.size();  uint my_pos = find(ids.begin(), ids.end(), me) - ids.begin();  assert(ids[my_pos].id == me.id);  CHID min_lap = ids[(my_pos+1) % sz].id - me.id;  CHID lap = (CHID) -1;  IDMap tmpf;  while (lap > min_lap) {    lap = lap / _base;    for (uint j = 1; j <= (_base -1); j++) {      if (lap * j < min_lap) continue;      tmpf.id = lap * j + me.id;      uint s_pos = upper_bound(ids.begin(), ids.end(), tmpf, Chord::IDMap::cmp) - ids.begin();      s_pos = s_pos % sz;      if (ConsistentHash::between(tmpf.id, tmpf.id + lap, ids[s_pos].id))	  loctable->add_node(ids[s_pos]);    }  }  Chord::initstate();}voidChordFinger::fix_fingers(bool restart){  vector<IDMap> scs = loctable->succs(me.id + 1, _nsucc);  CDEBUG(3) << "fix_fingers start sz " << loctable->size() << endl;  uint new_fingers,valid_fingers, skipped_fingers, dead_fingers, check_fingers,missing_finger;  missing_finger = dead_fingers = new_fingers = valid_fingers = skipped_fingers = dead_fingers = check_fingers = 0;  if (scs.size() == 0) return;  vector<IDMap> v;  CHID finger;  Chord::IDMap currf, prevf, prevfpred;  bool ok;  CHID lap = (CHID) -1;  prevf.ip = 0;  prevfpred.ip = 0;    while (1) {    lap = lap/_base;    for (uint j = (_base-1); j >= 1; j--) {      finger = lap * j + me.id;      if (ConsistentHash::between(me.id,scs[scs.size()-1].id, finger))	goto FINGER_DONE;      check_fingers++;      currf = loctable->succ(finger);      if (currf.ip == me.ip) currf.ip = 0;            if ((!restart) && (currf.ip)) { 	if (ConsistentHash::between(finger,finger+lap,currf.id)) {	  LocTable::idmapwrap *naked = loctable->get_naked_node(currf.id);	  assert(naked);	  if ((now()-naked->n.timestamp) < _stab_finger_timer) {	    skipped_fingers++;	    continue;	  }else{	    assert(currf.ip!=prevf.ip);	    //just ping this finger to see if it is alive	    prevf = currf;	    prevfpred.ip = 0;	    get_predsucc_args gpa;	    get_predsucc_ret gpr;	    gpa.pred = true;	    gpa.m = (_fingerlets - 1);	    ok = failure_detect(currf, &Chord::get_predsucc_handler, &gpa, &gpr, TYPE_FINGER_UP,0,0);	    if (!alive()) return;	    if(ok) {	      valid_fingers++;	      record_stat(currf.ip,me.ip,TYPE_FINGER_UP,1+gpr.v.size());	      assert(gpr.dst.ip == currf.ip);	      loctable->add_node(gpr.dst);	      prevfpred = gpr.n;	      if (ConsistentHash::between(finger,finger+lap,prevfpred.id)) 		loctable->add_node(prevfpred);	      for(uint k = 0; k < gpr.v.size(); k++) 		loctable->add_node(gpr.v[k]); //XXX: i am not careful about who to add, might add dead nodes again	      continue;	    } else {	      dead_fingers++;	      loctable->del_node(currf);	    }	  }	} else {	  missing_finger++;	  if ((prevf.ip == currf.ip) && (prevfpred.ip)) {	    if (ConsistentHash::between(finger,finger+lap,prevfpred.id)) {	      loctable->add_node(prevfpred);	      continue;	    } else if (prevfpred.ip && ConsistentHash::between(prevfpred.id,prevf.id,finger)) {	      //skip;	      continue;	    }	  }	}      }      if (_recurs)	v = find_successors_recurs(finger, _fingerlets, TYPE_FINGER_LOOKUP, NULL);      else	v = find_successors(finger, _fingerlets, TYPE_FINGER_LOOKUP, 0);      if (v.size() > 0) 	CDEBUG(3) << "fix_fingers " << j << " finger " << printID(finger) 	  << "get " << v[0].ip << "," << printID(v[0].id) << endl;      new_fingers++;      for(uint k = 0; k <v.size();k++) 	loctable->add_node(v[k]); //XXX: might add dead nodes again and again    }  }FINGER_DONE:  CDEBUG(3) << "fix_fingers done sz " << loctable->size() << " fingers "     << check_fingers << " skipped " << skipped_fingers << " valid "     << valid_fingers << " dead " << dead_fingers << " missing " <<     missing_finger << " new " << new_fingers << endl;  return;}voidChordFinger::join(Args *args){  Chord::join(args);  if ((static_sim) || !alive()) return;  //schedule finger stabilizer  if (!_stab_finger_running) {    _stab_finger_running = true;    reschedule_finger_stabilizer((void *)1); //a hack, no null means restart fixing fingres  }else if (_join_scheduled == 0) {    ChordFinger::fix_fingers();  }}voidChordFinger::reschedule_finger_stabilizer(void *x){  //printf("%s start stabilizing\n",ts());  if (!alive()) {    _stab_finger_running = false;    return;  }  _stab_finger_running = true;  if (_stab_finger_outstanding > 0) {  }else{    _stab_finger_outstanding++;    fix_fingers(x!=NULL);    _stab_finger_outstanding--;    assert(_stab_finger_outstanding == 0);  }  delaycb(_stab_finger_timer, &ChordFinger::reschedule_finger_stabilizer, (void *)0);}boolChordFinger::stabilized(vector<CHID> lid){  bool ret = Chord::stabilized(lid);  if (!ret) return ret;  uint sz = lid.size();  uint my_pos = find(lid.begin(), lid.end(), me.id) - lid.begin();  assert(lid[my_pos] == me.id);  CHID min_lap = lid[(my_pos+1) % sz] - me.id;  vector<CHID>::iterator it;  CHID finger;  uint pos;  CHID lap = (CHID) -1;  IDMap succ;  uint numf = 0;  while (lap > min_lap) {    lap = lap / _base;    for (uint j = 1; j <= (_base - 1); j++) {      if ((lap * j) < min_lap) continue;      finger = lap * j + me.id;      it = upper_bound(lid.begin(), lid.end(), finger);      pos = it - lid.begin();      if (pos >= lid.size()) {	pos = 0;      }      succ = loctable->succ(finger);      if (lid[pos] != succ.id) {	// printf("%s not stabilized, %qx,%d finger (%qx) should be %qx instead of (%u,%qx)\n", ts(), lap, j, finger, lid[pos], succ.ip, succ.id); 	return false;      }      numf++;    }  }  return true;}voidChordFinger::dump(){  Chord::dump();  IDMap succ = loctable->succ(me.id + 1);  CHID min_lap = succ.id - me.id;  CHID lap = (CHID) -1;  CHID finger;  while (lap > min_lap) {    lap = lap / _base;    for (uint j = 1; j <= (_base - 1); j++) {      if ((lap * j) < min_lap) continue;      finger = lap * j + me.id;      succ = loctable->succ(finger);      if (succ.ip > 0)  {        // printf("%qx: finger: %qx,%d : %qx : succ %qx\n", me.id, lap, j, finger, succ.id);      }    }  }}

⌨️ 快捷键说明

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