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