Author: j16sdiz
Date: 2008-07-28 15:02:32 +0000 (Mon, 28 Jul 2008)
New Revision: 21448
Modified:
branches/saltedhashstore/freenet/src/freenet/support/BinaryBloomFilter.java
branches/saltedhashstore/freenet/src/freenet/support/BloomFilter.java
Log:
move more methods to abstract class
Modified:
branches/saltedhashstore/freenet/src/freenet/support/BinaryBloomFilter.java
===================================================================
--- branches/saltedhashstore/freenet/src/freenet/support/BinaryBloomFilter.java
2008-07-28 14:27:21 UTC (rev 21447)
+++ branches/saltedhashstore/freenet/src/freenet/support/BinaryBloomFilter.java
2008-07-28 15:02:32 UTC (rev 21448)
@@ -7,25 +7,12 @@
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
-import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel.MapMode;
-import java.security.MessageDigest;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import freenet.crypt.SHA256;
-
/**
* @author sdiz
*/
public class BinaryBloomFilter extends BloomFilter {
- protected ByteBuffer filter;
- protected final int length;
- /** Number of hash functions */
- protected final int k;
- private ReadWriteLock lock = new ReentrantReadWriteLock();
- private boolean needRebuild;
-
/**
* Constructor
*
@@ -33,12 +20,8 @@
* length in bits
*/
public BinaryBloomFilter(int length, int k) {
- if (length % 8 != 0)
- throw new IllegalArgumentException();
-
+ super(length, k);
filter = ByteBuffer.allocate(length / 8);
- this.length = length;
- this.k = k;
}
/**
@@ -51,80 +34,26 @@
* @throws IOException
*/
public BinaryBloomFilter(File file, int length, int k) throws
IOException {
- if (length % 8 != 0)
- throw new IllegalArgumentException();
+ super(length, k);
if (!file.exists() || file.length() != length / 8)
needRebuild = true;
RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.setLength(length / 8);
filter = raf.getChannel().map(MapMode.READ_WRITE, 0, length /
8).load();
-
- this.length = length;
- this.k = k;
}
@Override
- public void addKey(byte[] key) {
- int[] hashes = getHashes(key);
- lock.writeLock().lock();
- try {
- for (int i = 0; i < k; i++)
- setBit(hashes[i]);
- } finally {
- lock.writeLock().unlock();
- }
-
- if (forkedFilter != null)
- forkedFilter.addKey(key);
- }
-
- @Override
- public void removeKey(byte[] key) {
+ public void removeKey(byte[] key) {
// ignore
}
@Override
- public boolean checkFilter(byte[] key) {
- int[] hashes = getHashes(key);
- lock.readLock().lock();
- try {
- for (int i = 0; i < k; i++)
- if (!getBit(hashes[i]))
- return false;
- } finally {
- lock.readLock().unlock();
- }
- return true;
- }
-
- private int[] getHashes(byte[] key) {
- int[] hashes = new int[k];
-
- MessageDigest md = SHA256.getMessageDigest();
- try {
- byte[] lastDigest = key;
- ByteBuffer bf = ByteBuffer.wrap(lastDigest);
-
- for (int i = 0; i < k; i++) {
- if (bf.remaining() < 4) {
- lastDigest = md.digest(lastDigest);
- bf = ByteBuffer.wrap(lastDigest);
- }
-
- hashes[i] = (int) ((bf.getInt() &
Long.MAX_VALUE) % length);
- }
- } finally {
- SHA256.returnMessageDigest(md);
- }
-
- return hashes;
- }
-
protected boolean getBit(int offset) {
return (filter.get(offset / 8) & (1 << (offset % 8))) != 0;
}
+ @Override
protected void setBit(int offset) {
byte b = filter.get(offset / 8);
b |= 1 << (offset % 8);
@@ -132,20 +61,12 @@
}
@Override
- public void force() {
- if (filter instanceof MappedByteBuffer) {
- ((MappedByteBuffer) filter).force();
- }
+ protected void unsetBit(int offset) {
+ // NO-OP
}
- protected BinaryBloomFilter forkedFilter;
-
- /**
- * Create an empty, in-memory copy of bloom filter. New updates are
written to both filters.
- * This is written back to disk on #merge()
- */
@Override
- public void fork(int k) {
+ public void fork(int k) {
lock.writeLock().lock();
try {
forkedFilter = new BinaryBloomFilter(length, k);
@@ -153,55 +74,4 @@
lock.writeLock().unlock();
}
}
-
- @Override
- public void discard() {
- lock.writeLock().lock();
- try {
- forkedFilter = null;
- } finally {
- lock.writeLock().unlock();
- }
- }
-
- @Override
- public void merge() {
- lock.writeLock().lock();
- try {
- if (forkedFilter == null)
- return;
-
- filter.position(0);
- forkedFilter.filter.position(0);
-
- filter.put(forkedFilter.filter);
-
- filter.position(0);
- forkedFilter = null;
- } finally {
- lock.writeLock().unlock();
- }
- }
-
- @Override
- protected void finalize() {
- if (filter != null) {
- force();
- }
- filter = null;
- forkedFilter = null;
- }
-
- @Override
- public int getK() {
- return k;
- }
-
-
- @Override
- public boolean needRebuild() {
- boolean _needRebuild = needRebuild;
- needRebuild = false;
- return _needRebuild;
- }
}
Modified: branches/saltedhashstore/freenet/src/freenet/support/BloomFilter.java
===================================================================
--- branches/saltedhashstore/freenet/src/freenet/support/BloomFilter.java
2008-07-28 14:27:21 UTC (rev 21447)
+++ branches/saltedhashstore/freenet/src/freenet/support/BloomFilter.java
2008-07-28 15:02:32 UTC (rev 21448)
@@ -1,7 +1,140 @@
package freenet.support;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.security.MessageDigest;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import freenet.crypt.SHA256;
+
public abstract class BloomFilter {
+ protected ByteBuffer filter;
+
+ /** Number of hash functions */
+ protected final int k;
+ protected final int length;
+
+ protected ReadWriteLock lock = new ReentrantReadWriteLock();
+
+ protected BloomFilter(int length, int k) {
+ if (length % 8 != 0)
+ throw new IllegalArgumentException();
+
+ this.length = length;
+ this.k = k;
+ }
+
+ //-- Core
+ public void addKey(byte[] key) {
+ int[] hashes = getHashes(key);
+ lock.writeLock().lock();
+ try {
+ for (int i = 0; i < hashes.length; i++)
+ setBit(hashes[i]);
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ if (forkedFilter != null)
+ forkedFilter.addKey(key);
+ }
+
+ public boolean checkFilter(byte[] key) {
+ int[] hashes = getHashes(key);
+ lock.readLock().lock();
+ try {
+ for (int i = 0; i < hashes.length; i++)
+ if (!getBit(hashes[i]))
+ return false;
+ } finally {
+ lock.readLock().unlock();
+ }
+ return true;
+ }
+
+ public void removeKey(byte[] key) {
+ int[] hashes = getHashes(key);
+ lock.writeLock().lock();
+ try {
+ for (int i = 0; i < hashes.length; i++)
+ unsetBit(hashes[i]);
+ } finally {
+ lock.writeLock().unlock();
+ }
+
+ if (forkedFilter != null)
+ forkedFilter.addKey(key);
+ }
+
+ //-- Bits and Hashes
+ protected abstract boolean getBit(int offset);
+
+ protected abstract void setBit(int offset);
+
+ protected abstract void unsetBit(int offset);
+
+ protected int[] getHashes(byte[] key) {
+ int[] hashes = new int[k];
+
+ MessageDigest md = SHA256.getMessageDigest();
+ try {
+ byte[] lastDigest = key;
+ ByteBuffer bf = ByteBuffer.wrap(lastDigest);
+
+ for (int i = 0; i < k; i++) {
+ if (bf.remaining() < 4) {
+ lastDigest = md.digest(lastDigest);
+ bf = ByteBuffer.wrap(lastDigest);
+ }
+
+ hashes[i] = (int) ((bf.getInt() &
Long.MAX_VALUE) % length);
+ }
+ } finally {
+ SHA256.returnMessageDigest(md);
+ }
+
+ return hashes;
+ }
+
+ //-- Fork & Merge
+ protected BloomFilter forkedFilter;
+
/**
+ * Create an empty, in-memory copy of bloom filter. New updates are
written to both filters.
+ * This is written back to disk on #merge()
+ */
+ public abstract void fork(int k);
+
+ public void merge() {
+ lock.writeLock().lock();
+ try {
+ if (forkedFilter == null)
+ return;
+
+ filter.position(0);
+ forkedFilter.filter.position(0);
+
+ filter.put(forkedFilter.filter);
+
+ filter.position(0);
+ forkedFilter = null;
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ public void discard() {
+ lock.writeLock().lock();
+ try {
+ forkedFilter = null;
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ //-- Misc.
+ /**
* Calculate optimal K value
*
* @param filterLength
@@ -20,26 +153,31 @@
return (int) k;
}
- public abstract void addKey(byte[] key);
+ public int getK() {
+ return k;
+ }
- public abstract void removeKey(byte[] key);
+ protected boolean needRebuild;
- public abstract boolean checkFilter(byte[] key);
+ public boolean needRebuild() {
+ boolean _needRebuild = needRebuild;
+ needRebuild = false;
+ return _needRebuild;
- public abstract void force();
+ }
- /**
- * Create an empty, in-memory copy of bloom filter. New updates are
written to both filters.
- * This is written back to disk on #merge()
- */
- public abstract void fork(int k);
+ public void force() {
+ if (filter instanceof MappedByteBuffer) {
+ ((MappedByteBuffer) filter).force();
+ }
+ }
- public abstract void discard();
-
- public abstract void merge();
-
- public abstract int getK();
-
- public abstract boolean needRebuild();
-
+ @Override
+ protected void finalize() {
+ if (filter != null) {
+ force();
+ }
+ filter = null;
+ forkedFilter = null;
+ }
}
\ No newline at end of file