package com.limegroup.gnutella.routing; import java.util.Iterator; import org.limewire.collection.SparseIntSet; /** * A QRTTableStorage that uses a SparseIntSet to store * the list of routing table entries. */ class SparseSetStorage implements QRTTableStorage { private final SparseIntSet set; private final int length; SparseSetStorage(int length) { this(new SparseIntSet(), length); } private SparseSetStorage(SparseIntSet set, int length) { this.set = set; this.length = length; } public void clear(int hash) { set.remove(hash); } public void compact() { set.compact(); } public double getPercentFull() { return set.size() * 100.0 / length; } public int getUnitsInUse() { // this is to approximate what a BitSetStorage would return return set.getActualMemoryUsed() / 8; } public int getUnusedUnits() { return 0; } public int numUnitsWithLoad(int load) { return -1; } public void or(QRTTableStorage other) { if (other instanceof SparseSetStorage) { SparseSetStorage optimized = (SparseSetStorage)other; set.addAll(optimized.set); } else { for (int i : other) set.add(i); } } public QRTTableStorage resize(int newSize) { if (newSize == length) return this; SparseIntSet s = new SparseIntSet(); for (int i : set) { final int firstSet = (int)(((long)i * newSize) / length); i = nextClearBit(i+1); final int lastNotSet = (int)(((long)i * newSize - 1) / length + 1); for (int j = firstSet; j < lastNotSet; j++) s.add(j); } return new SparseSetStorage(s,newSize); } public void set(int hash) { set.add(hash); } public void xor(QRTTableStorage other) { // probably slow for (int i = 0; i < length; i++) { if (get(i) != other.get(i)) set(i); else clear(i); } } public int cardinality() { return set.size(); } public boolean get(int i) { return set.contains(i); } public int maxSize() { return length; } public int nextClearBit(int i) { // slow for (int j = i; j < length; j++) { if (!set.contains(j)) return j; } return -1; } public int nextSetBit(int i) { // fast return set.nextSetBit(i); } @Override public QRTTableStorage clone() throws CloneNotSupportedException { SparseIntSet copy = new SparseIntSet(); copy.addAll(set); return new SparseSetStorage(copy, length); } @Override public boolean equals(Object o) { if (! (o instanceof QRTTableStorage)) return false; // check max sizes QRTTableStorage bf = (QRTTableStorage)o; if (bf.maxSize() != maxSize()) return false; // try fast first if (o instanceof SparseSetStorage) { SparseSetStorage sss = (SparseSetStorage)o; return set.containsAll(sss.set) && set.size() == sss.set.size(); } if (bf.cardinality() != cardinality()) return false; // otherwise iterate Iterator<Integer> it = bf.iterator(); for (int i : this) if (i != it.next()) return false; return true; } public Iterator<Integer> iterator() { return set.iterator(); } @Override public String toString() { return "SparseSetStorage: " + set; } }