注:本章笔记中将包含一下文件:KBucketTrimmer.java RandomIfOldTrimmer.java TandomTrimmer.java RejectTrimmer.java SelectionCollection.java XORComparator.java等六个文件
这是一个范型接口interface,我们知道当一个bucket 很大的时候就需要split,但是split是有数量和次数限制的,当上述情况同时发生的时候我们就需要调用trimmer相关的来进行修正,具体怎么修正继续看其他文件,这里只是定义类一个interface,接口中只有一个函数,返回值为bool类型,看主食应该是如果节点插入进入到buckety汇总那么就返回true,而如果没有返回false。接受两个参数,一个是接受KBucket< K >d的,另一个接受K类型的用来表示要添加的节点
package net.i2p.kademlia;
import net.i2p.data.SimpleDataStructure;
/**
* Called when a kbucket can no longer be split and is too big
* @since 0.9.2 in i2psnark, moved to core in 0.9.10
*/
public interface KBucketTrimmer<K extends SimpleDataStructure> {
/**
* Called from add() just before adding the entry.
* You may call getEntries() and/or remove() from here.
* Do NOT call add().
* To always discard a newer entry, always return false.
*
* @param kbucket the kbucket that is now too big
* @return true to actually add the entry.
*/
public boolean trim(KBucket<K> kbucket, K toAdd);
}
这是一个范型类,实现了KBucketTrimmer这个interface,。在函数trim中,如果要添加的的bucket的size仍旧小于最大值,那么就可以继续添加,返回true,而如果size 大于或者等于最大值,那么就需要随机移除一个,使用i2pappcontext中的random.nextint来获取随机的,然后使用kbucket.remove函数来移除,然后返回true
i2pappcontext已经多次出现了,下一个文件用来记录这个文件的笔记
package net.i2p.kademlia;
import java.util.ArrayList;
import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.data.SimpleDataStructure;
/**
* Removes a random element. Not resistant to flooding.
* @since 0.9.2 in i2psnark, moved to core in 0.9.10
*/
public class RandomTrimmer<T extends SimpleDataStructure> implements KBucketTrimmer<T> {
protected final I2PAppContext _ctx;
private final int _max;
public RandomTrimmer(I2PAppContext ctx, int max) {
_ctx = ctx;
_max = max;
}
public boolean trim(KBucket<T> kbucket, T toAdd) {
List<T> e = new ArrayList<T>(kbucket.getEntries());
int sz = e.size();
// concurrency
if (sz < _max)
return true;
T toRemove = e.get(_ctx.random().nextInt(sz));
kbucket.remove(toRemove);
return true;
}
}
这个函数继承了RandomTrimmer,功能一样,也是随机移除一个key,但是发生的条件是如果一个bucket在五分钟之内没有更新或者说没有任何改动的情况下,就需要调用这个函数来随机remove一个key,构造函数调用父类,
package net.i2p.kademlia;
import net.i2p.I2PAppContext;
import net.i2p.data.SimpleDataStructure;
/**
* Removes a random element, but only if the bucket hasn't changed in 5 minutes.
* @since 0.9.2 in i2psnark, moved to core in 0.9.10
*/
public class RandomIfOldTrimmer<T extends SimpleDataStructure> extends RandomTrimmer<T> {
public RandomIfOldTrimmer(I2PAppContext ctx, int max) {
super(ctx, max);
}
public boolean trim(KBucket<T> kbucket, T toAdd) {
if (kbucket.getLastChanged() > _ctx.clock().now() - 5*60*1000)
return false;
return super.trim(kbucket, toAdd);
}
}
package net.i2p.kademlia;
import net.i2p.data.SimpleDataStructure;
/**
* Removes nothing and always rejects the add. Flood resistant..
* @since 0.9.2 in i2psnark, moved to core in 0.9.10
*/
public class RejectTrimmer<T extends SimpleDataStructure> implements KBucketTrimmer<T> {
public boolean trim(KBucket<T> kbucket, T toAdd) {
return false;
}
}
使用xor异或距离来对base key的hash进行排序。
package net.i2p.kademlia;
import java.io.Serializable;
import java.util.Comparator;
import net.i2p.data.SimpleDataStructure;
/**
* Help sort Hashes in relation to a base key using the XOR metric
*
* @since 0.9.2 in i2psnark, moved to core in 0.9.10
*/
public class XORComparator<T extends SimpleDataStructure> implements Comparator<T>, Serializable {
private final byte[] _base;
/**
* @param target key to compare distances with
*/
public XORComparator(T target) {
_base = target.getData();
}
public int compare(T lhs, T rhs) {
// same as the following but byte-by-byte for efficiency
//byte lhsDelta[] = DataHelper.xor(lhs.getData(), _base);
//byte rhsDelta[] = DataHelper.xor(rhs.getData(), _base);
//return DataHelper.compareTo(lhsDelta, rhsDelta);
byte lhsb[] = lhs.getData();
byte rhsb[] = rhs.getData();
for (int i = 0; i < _base.length; i++) {
int ld = (lhsb[i] ^ _base[i]) & 0xff;
int rd = (rhsb[i] ^ _base[i]) & 0xff;
if (ld < rd)
return -1;
if (ld > rd)
return 1;
}
return 0;
}
}
首先创建一个字节数组 byte[] _base来,该类继承SimpleDataStructure 实现Comparator< T >,和Serializable。
到现在kademlia就将所有的 文件的源代码的笔记写完了,之后或许会考虑i2pappcontext 以及从顶上下来看代码