Methods Summary |
---|
protected void | addNode(DHTRouterContactImpl node)
// MGP: notify that node added to bucket
node.setBucketEntry();
router.notifyAdded(node);
buckets.add( node );
requestNodeAdd( node, false );
|
protected com.aelitis.azureus.core.dht.router.DHTRouterContact | addReplacement(DHTRouterContactImpl replacement, int max_rep_per_node)
if ( max_rep_per_node == 0 ){
return( null );
}
// we ping the oldest bucket entry only if we "improve" matters in the replacement
boolean try_ping = false;
if( replacements == null ){
try_ping = true;
replacements = new ArrayList();
}else{
if ( replacements.size() == max_rep_per_node ){
// if this replacement is known to be alive, replace any existing
// replacements that haven't been known to be alive
if ( replacement.hasBeenAlive() ){
for (int i=0;i<replacements.size();i++){
DHTRouterContactImpl r = (DHTRouterContactImpl)replacements.get(i);
if ( !r.hasBeenAlive()){
try_ping = true;
// MGP: kicking out a replacement that was never alive
router.notifyRemoved(r);
replacements.remove(i);
break;
}
}
// no unknown existing replacements but this is "newer" than the existing
// ones so replace the oldest one
if ( replacements.size() == max_rep_per_node ){
DHTRouterContactImpl removed = (DHTRouterContactImpl) replacements.remove(0);
// MGP: kicking out the oldest replacement
router.notifyRemoved(removed);
}
}else{
// replace old unknown ones with newer unknown ones
for (int i=0;i<replacements.size();i++){
DHTRouterContactImpl r = (DHTRouterContactImpl)replacements.get(i);
if ( !r.hasBeenAlive()){
// MGP: kicking out an older replacement that was never alive
router.notifyRemoved(r);
replacements.remove(i);
break;
}
}
}
}else{
try_ping = true;
}
}
if ( replacements.size() == max_rep_per_node ){
// no room, drop the contact
return( null );
}
// MGP: notify observers contact added as a replacement
replacement.setReplacement();
router.notifyAdded(replacement);
replacements.add( replacement );
if ( try_ping ){
for (int i=0;i<buckets.size();i++){
DHTRouterContactImpl c = (DHTRouterContactImpl)buckets.get(i);
// don't ping ourselves or someone already being pinged
if ( !( router.isID(c.getID()) || c.getPingOutstanding())){
c.setPingOutstanding( true );
router.requestPing( c );
break;
}
}
}
return( replacement );
|
protected void | alive(DHTRouterContactImpl contact)
// DHTLog.log( DHTLog.getString( contact.getID()) + ": alive" );
contact.setPingOutstanding( false );
// record whether was alive
boolean was_alive = contact.isAlive();
if ( buckets.remove( contact )){
contact.setAlive();
if (!was_alive) {
// MGP: notify observers that now alive
router.notifyNowAlive(contact);
}
// MGP: simply reinserting, so do not notify observers that added to bucket
buckets.add( contact );
}else if ( replacements.remove( contact )){
long last_time = contact.getFirstFailOrLastAliveTime();
contact.setAlive();
if (!was_alive) {
// MGP: notify observers that now alive
router.notifyNowAlive(contact);
}
// this is a good time to probe the contacts as we know a
// replacement is alive and therefore in a position to replace a
// dead bucket entry. Only do this if we haven't heard from this contact
// recently
if ( contact.getLastAliveTime() - last_time > 30000 ){
for (int i=0;i<buckets.size();i++){
DHTRouterContactImpl c = (DHTRouterContactImpl)buckets.get(i);
// don't ping ourselves or someone already being pinged
if ( !( router.isID(c.getID()) || c.getPingOutstanding())){
c.setPingOutstanding( true );
router.requestPing( c );
break;
}
}
}
// MGP: simply reinserting, so do not notify observers that added to replacments
replacements.add( contact );
}
|
protected java.lang.String | contactsToString(java.util.List contacts)
String res = "{";
for (int i=0;i<contacts.size();i++){
res += (i==0?"":", ") + ((DHTRouterContactImpl)contacts.get(i)).getString();
}
return( res + "}" );
|
protected boolean | containsRouterNodeID()
return( contains_router_node_id );
|
protected void | dead(DHTRouterContactImpl contact, boolean force)
// DHTLog.log( DHTLog.getString( contact.getID()) + ": dead" );
contact.setPingOutstanding( false );
// record whether was failing
boolean was_failing = contact.isFailing();
if ( contact.setFailed() || force ){
// check the contact is still present
if ( buckets.remove( contact )){
if (!was_failing) {
// MGP: first notify observers that now failing
router.notifyNowFailing(contact);
}
// MGP: notify that removed from bucket
router.notifyRemoved(contact);
if ( replacements != null && replacements.size() > 0 ){
// take most recent alive one and add to buckets
boolean replaced = false;
for (int i=replacements.size()-1;i>=0;i--){
DHTRouterContactImpl rep = (DHTRouterContactImpl)replacements.get(i);
if ( rep.hasBeenAlive()){
DHTLog.log( DHTLog.getString( contact.getID()) + ": using live replacement " + DHTLog.getString(rep.getID()));
// MGP: notify that a replacement was promoted to the bucket
rep.setBucketEntry();
router.notifyLocationChanged(rep);
replacements.remove( rep );
buckets.add( rep );
replaced = true;
requestNodeAdd( rep, false );
break;
}
}
// non alive - just take most recently added
if ( !replaced ){
DHTRouterContactImpl rep = (DHTRouterContactImpl)replacements.remove( replacements.size() - 1 );
DHTLog.log( DHTLog.getString( contact.getID()) + ": using unknown replacement " + DHTLog.getString(rep.getID()));
// MGP: notify that a replacement was promoted to the bucket
rep.setBucketEntry();
router.notifyLocationChanged(rep);
buckets.add( rep );
// add-node logic will ping the node if its not known to
// be alive
requestNodeAdd( rep, false );
}
}
}else{
if (!was_failing) {
// MGP: first notify observers that now failing
router.notifyNowFailing(contact);
}
// MGP: notify that removed from replacement list
router.notifyRemoved(contact);
replacements.remove( contact );
}
}
|
protected java.util.List | getBuckets()
return( buckets );
|
protected int | getDepth()
return( depth );
|
protected com.aelitis.azureus.core.dht.router.impl.DHTRouterNodeImpl | getLeft()
return( left );
|
protected java.util.List | getReplacements()
return( replacements );
|
protected com.aelitis.azureus.core.dht.router.impl.DHTRouterNodeImpl | getRight()
return( right );
|
protected long | getTimeSinceLastLookup()
long now = SystemTime.getCurrentTime();
if ( now < last_lookup_time ){
// clock changed, don't know so make as large as possible
return( Long.MAX_VALUE );
}
return( now - last_lookup_time );
|
public void | print(java.lang.String indent, java.lang.String prefix)
if ( left == null ){
router.log(
indent + prefix +
": buckets = " + buckets.size() + contactsToString( buckets) +
", replacements = " + (replacements==null?"null":( replacements.size() + contactsToString( replacements ))) +
(contains_router_node_id?" *":" ") +
(this==router.getSmallestSubtree()?"SST":"") +
" tsll=" + getTimeSinceLastLookup());
}else{
router.log( indent + prefix + ":" + (contains_router_node_id?" *":" ") +
(this==router.getSmallestSubtree()?"SST":""));
left.print( indent + " ", prefix + "1" );
right.print( indent + " ", prefix + "0" );
}
|
protected void | requestNodeAdd(DHTRouterContactImpl contact, boolean definite_change)
// DOS problem here - if a node deliberately flicked between
// instance IDs we'll get into an update frenzy.
long now = SystemTime.getCurrentTime();
if ( now - contact.getLastAddedTime() > 10000 ){
contact.setLastAddedTime( now );
router.requestNodeAdd( contact );
}else{
// only produce a warning if this is a definite change from one id to
// another (as opposed to a change from "unknown" to another)
if ( definite_change ){
router.log( "requestNodeAdd for " + contact.getString() + " denied as too soon after previous ");
}
}
|
protected void | setLastLookupTime()
last_lookup_time = SystemTime.getCurrentTime();
|
protected void | split(com.aelitis.azureus.core.dht.router.impl.DHTRouterNodeImpl new_left, com.aelitis.azureus.core.dht.router.impl.DHTRouterNodeImpl new_right)
buckets = null;
if ( replacements != null ){
Debug.out( "DHTRouterNode: inconsistenct - splitting a node with replacements" );
}
left = new_left;
right = new_right;
|
protected DHTRouterContactImpl | updateExistingNode(byte[] node_id, com.aelitis.azureus.core.dht.router.DHTRouterContactAttachment attachment, boolean known_to_be_alive)
for (int k=0;k<buckets.size();k++){
DHTRouterContactImpl contact = (DHTRouterContactImpl)buckets.get(k);
if ( Arrays.equals(node_id, contact.getID())){
if ( known_to_be_alive ){
// MGP: will update observers of updated status in this method
alive( contact );
}
// might be the same node but back after a restart. we need to
// treat this differently as we need to kick off the "store"
// events as required.
int new_id = attachment.getInstanceID();
// if the new-id is zero this represents us hearing about a contact
// indirectly (imported or returned as a query). In this case we
// don't use this information as an indication of the target's
// instance identity because it isn't!
if ( new_id != 0 ){
int old_id = contact.getAttachment().getInstanceID();
if ( old_id != new_id ){
DHTLog.log( "Instance ID changed for " +
DHTLog.getString( contact.getID())+
": old = " + old_id + ", new = " + new_id );
contact.setAttachment( attachment );
// if the instance id was 0, this means that it was unknown
// (e.g. contact imported). We still need to go ahead and treat
// as a new node
requestNodeAdd( contact, old_id != 0 );
}
}
return( contact );
}
}
// check replacements as well
if ( replacements != null ){
for (int k=0;k<replacements.size();k++){
DHTRouterContactImpl contact = (DHTRouterContactImpl)replacements.get(k);
if ( Arrays.equals(node_id, contact.getID())){
if ( known_to_be_alive ){
// MGP: will update observers of updated status in this method
alive( contact );
}
return( contact );
}
}
}
return( null );
|