You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by ka...@apache.org on 2009/03/18 13:00:25 UTC
svn commit: r755569 - in /labs/bananadb/trunk/src:
main/java/org/apache/labs/bananadb/
main/java/org/apache/labs/bananadb/store/ site/apt/
test/java/org/apache/labs/bananadb/store/
Author: kalle
Date: Wed Mar 18 12:00:25 2009
New Revision: 755569
URL: http://svn.apache.org/viewvc?rev=755569&view=rev
Log:
BananaDB
Rehashing introduced in v0.3
Improved benchmark
Added:
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/Benchmark.java
- copied, changed from r755223, labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/Benchmark.java
labs/bananadb/trunk/src/test/java/org/apache/labs/bananadb/store/TestRehash.java
Modified:
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Accessor.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/FileHandler.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Store.java
labs/bananadb/trunk/src/site/apt/index.apt
Copied: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/Benchmark.java (from r755223, labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/Benchmark.java)
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/Benchmark.java?p2=labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/Benchmark.java&p1=labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/Benchmark.java&r1=755223&r2=755569&rev=755569&view=diff
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/Benchmark.java (original)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/Benchmark.java Wed Mar 18 12:00:25 2009
@@ -1,6 +1,5 @@
package org.apache.labs.bananadb;
-import org.apache.labs.bananadb.entity.EntityStore;
import org.apache.labs.bananadb.store.Store;
import org.apache.labs.bananadb.store.Log;
import org.apache.labs.bananadb.store.Accessor;
@@ -9,7 +8,7 @@
import java.io.File;
import java.io.IOException;
-import java.util.Random;
+import java.util.*;
import java.text.DecimalFormat;
/**
@@ -22,8 +21,15 @@
public static void main(String[] arg) throws Exception {
+ log.info("Arguments: [min value posting byte[] size] [max value posting byte[] size] [number of postings] [debug interval]");
+
Benchmark benchmark = new Benchmark();
- benchmark.store(5, 5000, 1, 10000, 100000);
+
+ if (arg.length == 4) {
+ benchmark.benchmarkStore(Integer.valueOf(arg[0]), Integer.valueOf(arg[1]), Integer.valueOf(arg[2]), Integer.valueOf(arg[3]));
+ } else {
+ benchmark.benchmarkStore(1, 10000, 1000000, 10000);
+ }
}
@@ -39,44 +45,56 @@
private DecimalFormat df = new DecimalFormat("0.000");
- private void store(int minKeySize, int maxKeySize, int minValueSize, int maxValueSize, final int size) throws IOException {
+ private void benchmarkStore(int minValueSize, int maxValueSize, final int benchmarkSize, final int debugInterval) throws IOException {
- log.info("Creating buffers..");
+ log.info("Benchmarking store. minValueSize=" + minValueSize + ", maxValueSize=" + maxValueSize + ", benchmarkSize=" + benchmarkSize + ", debugInterval=" + debugInterval);
- final byte[][] keys = createBuffers(minKeySize, maxKeySize);
final byte[][] values = createBuffers(minValueSize, maxValueSize);
+ final Set<Long> keySet = new HashSet<Long>(benchmarkSize * 2);
+ final List<Long> keyList = new ArrayList<Long>(benchmarkSize * 2);
- final Store store = new Store(new File("benchmark"));
+ for (int i = 0; i < benchmarkSize; i++) {
+ long key;
+ while (!keySet.add(key = random.nextLong())) ;
+ keyList.add(key);
+ }
- FileUtils.deleteQuietly(store.getConfiguration().getDataPath());
+ final Store store = new Store(new File("benchmark/" + System.currentTimeMillis()));
final Accessor accessor = store.createAccessor(false);
log.info("Starting benchmark..");
- final long ms = System.currentTimeMillis();
+ final long writeStart = System.currentTimeMillis();
Lock.With with = new Lock.With(accessor.getWriteLock(), 0) {
public Object doBody() throws IOException {
int replaced = 0;
+ long readStartLast = System.currentTimeMillis();
+
+ LinkedList<Long> keys = new LinkedList<Long>(keyList);
+
int cnt = 0;
- for (int i = 0; i < size; i++) {
- byte[] key = keys[random.nextInt(keys.length)];
- random.nextBytes(key);
+ for (int i = 0; i < benchmarkSize; i++) {
+ long key = keys.removeFirst();
byte[] value = values[random.nextInt(values.length)];
random.nextBytes(value);
- if (store.put(accessor, key, key.hashCode(), value) != null) {
+ if (store.put(accessor, toByteArray(key), key, value) != null) {
replaced++;
}
- if (cnt++ == 500) {
- long time = System.currentTimeMillis() - ms;
- log.info("Wrote " + i + " postings in " + (time/1000) + " seconds or " + df.format(((double)time / (double)size)) + " ms/posting. " + replaced + " replaced." );
+ if (cnt++ == debugInterval) {
+ long time = System.currentTimeMillis() - writeStart;
+ long timeLast = System.currentTimeMillis() - readStartLast;
+
+ log.info("Wrote " + i + " postings in " + (time / 1000) + " seconds or " + df.format(((double) time / (double) i)) + " ms/posting. " + df.format(((double) timeLast / (double) debugInterval)) + " ms/posting since last report.");
cnt = 1;
+ readStartLast = System.currentTimeMillis();
+
}
}
@@ -87,14 +105,77 @@
with.run();
- long time = System.currentTimeMillis() - ms;
- log.info("Wrote " + size + " postings in " + (time/1000) + " seconds or " + df.format(((double)time / (double)size)) + " ms/posting. ");
+ long time = System.currentTimeMillis() - writeStart;
+ log.info("Wrote " + benchmarkSize + " postings in " + (time / 1000) + " seconds or " + df.format(((double) time / (double) benchmarkSize)) + " ms/posting. ");
+
+
+ {
+ ArrayList<Long> keys = new ArrayList<Long>(keyList);
+ ArrayList<Long> randomOrderedKeys = new ArrayList<Long>(keyList.size());
+ for (int i = 0; i < keyList.size(); i++) {
+ randomOrderedKeys.add(keys.remove(random.nextInt(keys.size())));
+ }
+
+ log.info("Begin retreiving postings in random order");
+
+ long readStart = System.currentTimeMillis();
+ long readStartLast = System.currentTimeMillis();
+ int cnt = 0;
+ for (int i = 0; i < randomOrderedKeys.size(); i++) {
+ long key = randomOrderedKeys.get(i);
+ store.get(accessor, toByteArray(key), key);
+ if (cnt++ == debugInterval) {
+ time = System.currentTimeMillis() - readStart;
+ long timeLast = System.currentTimeMillis() - readStartLast;
+ log.info("Retreived (random keys) " + i + " postings in " + (time / 1000) + " seconds or " + df.format(((double) time / (double) i)) + " ms/posting. " + df.format(((double) timeLast / (double) debugInterval)) + " ms/posting since last report.");
+ cnt = 1;
+ readStartLast = System.currentTimeMillis();
+ }
+ }
+
+ long timeLast = System.currentTimeMillis() - readStartLast;
+
+ log.info("Retreived (random keys) " + benchmarkSize + " postings in " + (time / 1000) + " seconds or " + df.format(((double) time / (double) benchmarkSize)) + " ms/posting. " + df.format(((double) timeLast / (double) debugInterval)) + " ms/posting since last report.");
+
+
+ }
+
+
+ {
+ ArrayList<Long> reversedOrderedKeys = new ArrayList<Long>(keyList.size());
+ for (long key : keyList) {
+ reversedOrderedKeys.add(0, key);
+ }
+
+ log.info("Begin retreiving postings in reverse chronological order (i.e. maximum number of seeks in order to get a post first)");
+
+ long readStart = System.currentTimeMillis();
+ long readStartLast = System.currentTimeMillis();
+ int cnt = 0;
+ for (int i = 0; i < benchmarkSize; i++) {
+ long key = reversedOrderedKeys.get(i);
+ store.get(accessor, toByteArray(key), key);
+ if (cnt++ == debugInterval) {
+ time = System.currentTimeMillis() - readStart;
+ long timeLast = System.currentTimeMillis() - readStartLast;
+ log.info("Retreived (backwards chronologial order) " + i + " postings in " + (time / 1000) + " seconds or " + df.format(((double) time / (double) i)) + " ms/posting. " + df.format(((double) timeLast / (double) debugInterval)) + " ms/posting since last report.");
+ cnt = 1;
+ readStartLast = System.currentTimeMillis();
+ }
+ }
+
+ long timeLast = System.currentTimeMillis() - readStartLast;
+
+ log.info("Retreived (backwards chronologial order) " + benchmarkSize + " postings in " + (time / 1000) + " seconds or " + df.format(((double) time / (double) benchmarkSize)) + " ms/posting. " + df.format(((double) timeLast / (double) debugInterval)) + " ms/posting since last report.");
+
+
+ }
+
store.close();
}
-
private byte[][] createBuffers(int minSize, int maxSize) {
byte[][] buffers = new byte[maxSize - minSize][];
int index = 0;
@@ -104,4 +185,21 @@
return buffers;
}
+ public static byte[] toByteArray(long l) {
+ byte[] b = new byte[4];
+ for (int i = 0; i < 4; i++) {
+ b[3 - i] = (byte) (l >>> (i * 8));
+ }
+ return b;
+ }
+
+ public static long toLong(byte[] b) {
+ long l = 0;
+ for (int i = 0; i < 4; i++) {
+ l <<= 8;
+ l ^= (long) b[i] & 0xFF;
+ }
+ return l;
+ }
+
}
Modified: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Accessor.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Accessor.java?rev=755569&r1=755568&r2=755569&view=diff
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Accessor.java (original)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Accessor.java Wed Mar 18 12:00:25 2009
@@ -25,7 +25,10 @@
import java.util.HashMap;
/**
- * This class is not thread safe. I.e. you'll need to instantiate one per thread!
+ * File system access interface.
+ *
+ * This class hold the write lock and the random access files.
+ * It is thus <b>not thread safe</b>!
*
* @author kalle
* @see org.apache.labs.bananadb.store.Store#createAccessor(boolean)
@@ -129,7 +132,6 @@
return metadata;
}
-
public Hashtable getHashtable() throws IOException {
Metadata.Header metadataHeader = new Metadata.Header();
metadata.readHeader(metadataHeader);
@@ -381,4 +383,8 @@
public Store getStore() {
return store;
}
+
+ public String getAccess() {
+ return access;
+ }
}
Modified: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/FileHandler.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/FileHandler.java?rev=755569&r1=755568&r2=755569&view=diff
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/FileHandler.java (original)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/FileHandler.java Wed Mar 18 12:00:25 2009
@@ -52,6 +52,10 @@
format(size, (byte) 0);
}
+ public boolean exists() {
+ return getFile().exists();
+ }
+
public void format(long size, byte defaultValue) throws IOException {
log.info("Formatting " + file.getAbsolutePath() + "..");
@@ -130,6 +134,10 @@
writePosting(posting, RAF);
}
+ public void writePosting(P posting) throws IOException {
+ writePosting(posting, getRAF());
+ }
+
public abstract void writePosting(P posting, RandomAccessFile RAF) throws IOException;
// public void readPosting(P posting) throws IOException {
Modified: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Store.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Store.java?rev=755569&r1=755568&r2=755569&view=diff
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Store.java (original)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Store.java Wed Mar 18 12:00:25 2009
@@ -22,6 +22,7 @@
import java.io.IOException;
import java.io.File;
+import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -672,13 +673,95 @@
}
/**
- * Rehashes the hash table.
- * Write locking.
+ * Rehashes the hash table file.
*
- * @param resolution number of postings in new hashtable file
+ * @param accessor
+ * @param resolution resolution in number of hashtable postings in new hashtable file.
+ * @throws IOException
*/
- public void rehash(int resolution) {
- throw new UnsupportedOperationException();
+ public void rehash(final Accessor accessor, final int resolution) throws IOException {
+ Lock.With with = new Lock.With(accessor.getWriteLock(), getConfiguration().getLockWaitTimeoutMilliseconds()) {
+ public Object doBody() throws IOException {
+
+ log.info("Rehashing hashtable capacity ??? -> " + resolution);
+
+ Metadata metadata = accessor.getMetadata();
+ Metadata.Header mdh = new Metadata.Header();
+ metadata.readHeader(mdh);
+ int topOldHashCodesPartition = mdh.getCurrentHashCodesPartition();
+ mdh.setCurrentHashCodesPartition(mdh.getCurrentHashCodesPartition() + 1);
+ metadata.writeHeader(mdh);
+
+ Hashtable rehashedTable = new Hashtable(getConfiguration().getDataPath(), mdh.getCurrentHashtableId() + 1, accessor.getAccess());
+ rehashedTable.format((resolution * Hashtable.Posting.POSTING_BYTE_SIZE) + rehashedTable.getHeaderByteSize());
+ rehashedTable.open();
+
+ Hashtable.Header rehashedTableHeader = new Hashtable.Header();
+ rehashedTableHeader.setPostingsCapacity(resolution);
+ rehashedTable.writeHeader(rehashedTableHeader);
+
+ // will format a new one!
+ HashCodesPartition rehashCodesPartition = accessor.getHashCodesPartition(mdh.getCurrentHashCodesPartition());
+
+ Hashtable.Posting rehashedTablePosting = new Hashtable.Posting();
+ HashCodesPartition.Posting rehashCodePosting = new HashCodesPartition.Posting();
+ HashCodesPartition.Header rehashCodeHeader = new HashCodesPartition.Header();
+ rehashCodesPartition.readHeader(rehashCodeHeader);
+
+ for (int currentOldHashCodePostingsPartitionId = 0; currentOldHashCodePostingsPartitionId <= topOldHashCodesPartition; currentOldHashCodePostingsPartitionId++) {
+ HashCodesPartition currentOldHashCodesPartition = new HashCodesPartition(getConfiguration().getDataPath(), currentOldHashCodePostingsPartitionId, accessor.getAccess());
+ if (currentOldHashCodesPartition.exists()) {
+ currentOldHashCodesPartition.open();
+ HashCodesPartition.Header hcph = new HashCodesPartition.Header();
+ currentOldHashCodesPartition.readHeader(hcph);
+
+ HashCodesPartition.Posting hcpp = new HashCodesPartition.Posting();
+
+ int hcpStartOffset = currentOldHashCodesPartition.getHeaderByteSize();
+ while (hcpStartOffset < hcph.getNextPostingOffset()) {
+ currentOldHashCodesPartition.readPosting(hcpp, hcpStartOffset);
+ hcpStartOffset += hcpp.getPostingByteSize();
+
+ if (hcpp.getFlag() == (byte) 2) {
+ continue;
+ } else if (hcpp.getFlag() == (byte) 0) {
+ break;
+ } else if (hcpp.getFlag() != (byte) 1) {
+ log.warn("Unknown flag at offset " + hcpStartOffset + ": " + hcpp);
+ }
+
+ //
+ // insert hashcode posting in rehashedtable and rehashcodes
+ //
+ rehash(accessor, hcpp, rehashedTable, rehashedTablePosting, rehashCodesPartition, rehashCodeHeader, rehashCodePosting);
+
+ //
+ // update rehashed codes partition header
+ //
+ rehashCodeHeader.setNextPostingOffset(rehashCodeHeader.getNextPostingOffset() + rehashCodePosting.getPostingByteSize());
+ rehashCodeHeader.setBytesLeft(rehashCodeHeader.getBytesLeft() - rehashCodePosting.getPostingByteSize());
+
+ // todo if there is no space for yet another rehased code in the partition, create new partition.
+ if (rehashCodeHeader.getBytesLeft() < rehashCodePosting.getPostingByteSize()) {
+ System.currentTimeMillis();
+ }
+
+ }
+
+ currentOldHashCodesPartition.close();
+ }
+ }
+
+
+ // write meta data header so the new hash table will be used
+ metadata.readHeader(mdh);
+ mdh.setCurrentHashtableId(rehashedTable.getVersionId());
+ accessor.getMetadata().writeHeader(mdh);
+
+ return null;
+ }
+ };
+ with.run();
}
public Configuration getConfiguration() {
@@ -686,4 +769,100 @@
}
+ /**
+ * @param accessor
+ * @param hashCodePosting posting to add to rehashed table
+ * @param rehashedtable rehaseed table
+ * @param rehashedtablePosting reusable posting
+ * @param rehashCodePartition rehashed codes partition
+ * @param rehashCodeHeader current header
+ * @param rehashCodePosting reusable posting
+ * @throws IOException
+ */
+ private void rehash(Accessor accessor,
+ HashCodesPartition.Posting hashCodePosting,
+ Hashtable rehashedtable, Hashtable.Posting rehashedtablePosting,
+ HashCodesPartition rehashCodePartition, HashCodesPartition.Header rehashCodeHeader, HashCodesPartition.Posting rehashCodePosting) throws IOException {
+ //
+ // find hashcode posting and hashtable posting for the new key
+ //
+
+ int rehashedtablePostingOffset = rehashedtable.calculateHashCodePostingOffset(hashCodePosting.getKeyHashCode());
+ rehashedtable.readPosting(rehashedtablePosting, rehashedtablePostingOffset);
+ if (rehashedtablePosting.getFlag() != (byte) 1) {
+
+ // this is the first time we create a posting at this hashtable position
+ // that means there is no hash code posting either
+
+ rehashCodePosting.setFlag((byte) 1);
+ rehashCodePosting.setFirstKeyPostingPartition(hashCodePosting.getFirstKeyPostingPartition());
+ rehashCodePosting.setFirstKeyPostingPartitionOffset(hashCodePosting.getFirstKeyPostingPartitionOffset());
+ rehashCodePosting.setKeyHashCode(hashCodePosting.getKeyHashCode());
+ rehashCodePosting.setNextPostingPartition(-1);
+ rehashCodePosting.setNextPostingPartitionOffset(-1);
+
+ rehashCodePartition.writePosting(rehashCodePosting, rehashCodeHeader.getNextPostingOffset());
+
+ // update hashtable posting
+
+ rehashedtablePosting.setFlag((byte) 1);
+ rehashedtablePosting.setHashCodePostingPartition(rehashCodePartition.getPartitionId());
+ rehashedtablePosting.setHashCodePostingPartitionOffset(rehashCodeHeader.getNextPostingOffset());
+ rehashedtable.writePosting(rehashedtablePosting, rehashedtablePostingOffset);
+
+ return;
+
+ } else {
+
+ // there is a hashtable posting at the position for this hash code
+
+ //
+ // seek to the correct hash code posting
+ //
+
+ HashCodesPartition currentRehashedCodesPartition = rehashCodePartition;
+ int currentRehashCodesPostingPartitionOffset = rehashedtablePosting.getHashCodePostingPartitionOffset();
+ rehashCodePartition.readPosting(rehashCodePosting, rehashedtablePosting.getHashCodePostingPartitionOffset());
+ while (hashCodePosting.getKeyHashCode() != rehashCodePosting.getKeyHashCode()) {
+ if (rehashCodePosting.getNextPostingPartition() < 0) {
+
+ // there is no hash code posting matching this hash code.
+
+ //
+ // create new hash code posting
+ //
+
+ HashCodesPartition.Posting newHashCodePosting = new HashCodesPartition.Posting();
+ newHashCodePosting.setFlag((byte) 1);
+ newHashCodePosting.setKeyHashCode(hashCodePosting.getKeyHashCode());
+ newHashCodePosting.setNextPostingPartition(-1);
+ newHashCodePosting.setNextPostingPartitionOffset(-1);
+ newHashCodePosting.setFirstKeyPostingPartition(hashCodePosting.getFirstKeyPostingPartition());
+ newHashCodePosting.setFirstKeyPostingPartitionOffset(hashCodePosting.getFirstKeyPostingPartitionOffset());
+
+ rehashCodePartition.writePosting(newHashCodePosting, rehashCodeHeader.getNextPostingOffset());
+
+
+ //
+ // and update the current posting to point at the new one as next in chain.
+ //
+
+ rehashCodePosting.setNextPostingPartition(rehashCodePartition.getPartitionId());
+ rehashCodePosting.setNextPostingPartitionOffset(rehashCodeHeader.getNextPostingOffset());
+ currentRehashedCodesPartition.writePosting(rehashCodePosting, currentRehashCodesPostingPartitionOffset);
+
+ return;
+
+ }
+ if (rehashCodePosting.getNextPostingPartition() != currentRehashedCodesPartition.getPartitionId()) {
+ currentRehashedCodesPartition = accessor.getHashCodesPartition(rehashCodePosting.getNextPostingPartition());
+ }
+ currentRehashCodesPostingPartitionOffset = rehashCodePosting.getNextPostingPartitionOffset();
+ currentRehashedCodesPartition.readPosting(rehashCodePosting, rehashCodePosting.getNextPostingPartitionOffset());
+ }
+
+ }
+
+
+ }
}
Modified: labs/bananadb/trunk/src/site/apt/index.apt
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/site/apt/index.apt?rev=755569&r1=755568&r2=755569&view=diff
==============================================================================
--- labs/bananadb/trunk/src/site/apt/index.apt (original)
+++ labs/bananadb/trunk/src/site/apt/index.apt Wed Mar 18 12:00:25 2009
@@ -3,8 +3,8 @@
BananaDB
- BananaDB is a small (100k) embedded key/value pair database for Java
- featuring an API similar to working with any Map\<K, V\>
+ BananaDB is a small (100KB jar) embedded byte array key/value pair database for Java
+ featuring a top level API similar to working with any Map\<K, V\>
* Main features
@@ -23,30 +23,29 @@
* Upcoming features
+ * Optimized generic serialization
+
* Secondary indices
- * Incrementing sequences for key postings
+ * Optional incrementing sequences for key postings
- * Generic serialization
+* Performance and limitations
-* Speed and size limitations
+ * Relies heavy on media I/O seek, i.e. SSD and file cache is helpfull.
- * Relies heavy on media I/O seek
+ * Benchmarks on 5400RPM HDD MacBook shows that
- * Normally ~3ms to put and ~0.1ms to get() when file cache is available
+ * Adding new <byte[4], byte[random(1-5000)> postings takes about
+ 1 millisecond + (1 millisecond per 500,000 postings in DB)
- * Relies on IO seek, i.e. SSD can make even a huge DB fair to use
+ * Retrieving the
- * No speed penalty for deleting or updating key/value postings
+ * No read speed penalty due to deleting or updating key/value postings
* No limit on number of key/value postings in database.
- * Up to 180 petabytes of value postings data
-
- * Up to 140 petabytes of key postings dat
-
* Releases
Added: labs/bananadb/trunk/src/test/java/org/apache/labs/bananadb/store/TestRehash.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/test/java/org/apache/labs/bananadb/store/TestRehash.java?rev=755569&view=auto
==============================================================================
--- labs/bananadb/trunk/src/test/java/org/apache/labs/bananadb/store/TestRehash.java (added)
+++ labs/bananadb/trunk/src/test/java/org/apache/labs/bananadb/store/TestRehash.java Wed Mar 18 12:00:25 2009
@@ -0,0 +1,78 @@
+package org.apache.labs.bananadb.store;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * @author kalle
+ * @since 2009-mar-17 14:50:11
+ */
+public class TestRehash extends StoreTest {
+
+
+ @Test
+ public void testSimple() throws IOException {
+
+ Configuration configuration = new Configuration(getDirectory("rehash"));
+ configuration.setInitialCapacity(20);
+ Store store = new Store(configuration);
+ store.open();
+
+ Accessor accessor = store.createAccessor(false);
+
+ assertEquals(0, accessor.getHashtable().getVersionId());
+
+ Random random = new Random(0);
+
+ byte[][] values = new byte[256][];
+ byte[][] keys = new byte[256][];
+ long[] hashCodes = new long[256];
+ float hashCode = 0f;
+
+ for (int i = 0; i < 256; i++) {
+ keys[i] = new byte[random.nextInt(100)+1];
+ random.nextBytes(keys[i]);
+ values[i] = new byte[random.nextInt(5000)+1];
+ random.nextBytes(values[i]);
+ hashCode += 0.3f;
+ hashCodes[i] = (long)hashCode;
+
+ store.put(accessor, keys[i], hashCodes[i], values[i]);
+ }
+
+ for (int i=0; i< 256; i++) {
+ byte[] value = store.get(accessor, keys[i], hashCodes[i]);
+ assertTrue(Arrays.equals(value, values[i]));
+ }
+
+ store.rehash(accessor, 40);
+ assertEquals(1, accessor.getHashtable().getVersionId());
+
+ for (int i=0; i< 256; i++) {
+ byte[] value = store.get(accessor, keys[i], hashCodes[i]);
+ assertTrue(Arrays.equals(value, values[i]));
+ }
+
+ store.rehash(accessor, 12345);
+ assertEquals(2, accessor.getHashtable().getVersionId());
+
+ for (int i=0; i< 256; i++) {
+ byte[] value = store.get(accessor, keys[i], hashCodes[i]);
+ assertTrue(Arrays.equals(value, values[i]));
+ }
+
+ store.rehash(accessor, 4);
+ assertEquals(3, accessor.getHashtable().getVersionId());
+
+ for (int i=0; i< 256; i++) {
+ byte[] value = store.get(accessor, keys[i], hashCodes[i]);
+ assertTrue(Arrays.equals(value, values[i]));
+ }
+
+ store.close();
+
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org