Contact Management

- There was an improvement in the paper page 64 to set a contact as stale and replace it if it's stale, but only if there is a replacement, otherwise just keep a stale count. The stale count is the amount of time a contact failed to respond to a request.
- The above feature is now implemented now.
- Added the management of stale contacts code to insert and removal
This commit is contained in:
Joshua Kissoon 2014-04-28 21:23:04 +05:30
parent b1bfba6d93
commit 4e643c7f3f
3 changed files with 71 additions and 9 deletions

View File

@ -45,7 +45,13 @@ public interface Bucket
public boolean containsNode(Node n);
/**
* Remove a contact from this bucket
* Remove a contact from this bucket.
*
* If there are replacement contacts in the replacement cache,
* select the last seen one and put it into the bucket while removing the required contact.
*
* If there are no contacts in the replacement cache, then we just mark the contact requested to be removed as stale.
* Marking as stale would actually be incrementing the stale count of the contact.
*
* @param c The contact to remove
*

View File

@ -19,6 +19,15 @@ public class Contact implements Comparable<Contact>
private final Node n;
private long lastSeen;
/**
* Stale as described by Kademlia paper page 64
* When a contact fails to respond, if the replacement cache is empty and there is no replacement for the contact,
* just mark it as stale.
*
* Now when a new contact is added, if the contact is stale, it is removed.
*/
private int staleCount;
/**
* Create a contact object
*
@ -59,6 +68,22 @@ public class Contact implements Comparable<Contact>
return c.getNode().equals(this.getNode());
}
/**
* Increments the amount of times this count has failed to respond to a request.
*/
public void incrementStaleCount()
{
staleCount++;
}
/**
* @return Integer Stale count
*/
public int staleCount()
{
return this.staleCount;
}
@Override
public int compareTo(Contact o)
{

View File

@ -57,11 +57,38 @@ public class KadBucket implements Bucket
}
else
{
/* If the bucket is filled, we put the contacts in the replacement cache */
/* If the bucket is filled, so put the contacts in the replacement cache */
if (contacts.size() >= this.config.k())
{
/* Bucket is filled, place this contact in the replacement cache */
this.insertIntoCache(c);
/* If the cache is empty, we check if any contacts are stale and replace the stalest one */
Contact stalest = null;
for (Contact tmp : this.contacts.keySet())
{
if (tmp.staleCount() > this.config.stale())
{
/* Contact is stale */
if (stalest == null)
{
stalest = tmp;
}
else if (tmp.staleCount() > stalest.staleCount())
{
stalest = tmp;
}
}
}
/* If we have a stale contact, remove it and add the new contact to the bucket */
if (stalest != null)
{
this.contacts.remove(stalest);
this.insert(c);
}
else
{
/* No stale contact, lets insert this into replacement cache */
this.insertIntoReplacementCache(c);
}
}
else
{
@ -97,15 +124,19 @@ public class KadBucket implements Bucket
return false;
}
this.contacts.remove(c);
/* If there are replacement contacts in the replacement cache, lets put them into the bucket */
if (!this.replacementCache.isEmpty())
{
/* Replace the contact with one from the replacement cache */
this.contacts.remove(c);
Contact replacement = this.replacementCache.firstKey();
this.contacts.put(replacement, replacement);
this.replacementCache.remove(replacement);
}
else
{
/* There is no replacement, just increment the contact's stale count */
this.contacts.get(c).incrementStaleCount();
}
return true;
}
@ -137,14 +168,14 @@ public class KadBucket implements Bucket
/**
* When the bucket is filled, we keep extra contacts in the replacement cache.
*/
private void insertIntoCache(Contact c)
private void insertIntoReplacementCache(Contact c)
{
/* Just return if this contact is already in our replacement cache */
if (this.replacementCache.containsKey(c))
{
return;
}
/* if our cache is filled, we remove the least recently seen contact */
if (this.replacementCache.size() > this.config.k())
{