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/22 23:12:13 UTC
svn commit: r757265 [1/2] - in /labs/bananadb/trunk/src:
main/java/org/apache/labs/bananadb/
main/java/org/apache/labs/bananadb/entity/
main/java/org/apache/labs/bananadb/entity/isolation/
main/java/org/apache/labs/bananadb/store/ main/java/org/apache/...
Author: kalle
Date: Sun Mar 22 22:12:12 2009
New Revision: 757265
URL: http://svn.apache.org/viewvc?rev=757265&view=rev
Log:
Banana DB
Revisions on all store postings, preparation for ACID Durability
Abstract and dummy sequence manager for auto incrementing primary keys
Site
Added:
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/FileHandler.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/Metadata.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/HashCodesPartition.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/Hashtable.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/KeysPartition.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/ValuesPartition.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/lock/LockListener.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/sequence/
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/sequence/SequenceManager.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/sequence/StaticSequenceManager.java
Removed:
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/FileHandler.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/HashCodesPartition.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Hashtable.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/KeysPartition.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Metadata.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/ValuesPartition.java
Modified:
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/Benchmark.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/Transaction.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationDeadlocking.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationLastCommitWins.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationUpdated.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Accessor.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Configuration.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Store.java
labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/lock/Lock.java
labs/bananadb/trunk/src/site/apt/index.apt
labs/bananadb/trunk/src/test/java/org/apache/labs/bananadb/store/StoreTest.java
labs/bananadb/trunk/src/test/java/org/apache/labs/bananadb/store/TestStore.java
Modified: 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?rev=757265&r1=757264&r2=757265&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 Sun Mar 22 22:12:12 2009
@@ -66,7 +66,7 @@
final long writeStart = System.currentTimeMillis();
- Lock.With with = new Lock.With(accessor.getWriteLock(), 0) {
+ Lock.With with = new Lock.With(accessor.getStoreWriteLock(), 0) {
public Object doBody() throws IOException {
int replaced = 0;
Modified: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/Transaction.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/Transaction.java?rev=757265&r1=757264&r2=757265&view=diff
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/Transaction.java (original)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/Transaction.java Sun Mar 22 22:12:12 2009
@@ -19,9 +19,8 @@
import org.apache.labs.bananadb.store.lock.Lock;
-import org.apache.labs.bananadb.store.lock.SingleInstanceLockFactory;
import org.apache.labs.bananadb.store.Accessor;
-import org.apache.labs.bananadb.store.Metadata;
+import org.apache.labs.bananadb.store.data.Metadata;
import org.apache.labs.bananadb.entity.EntityStore;
import org.apache.labs.bananadb.entity.PrimaryIndex;
import org.apache.labs.bananadb.entity.isolation.Isolation;
@@ -71,7 +70,7 @@
}
public void commit() throws IOException {
- Lock.With with = new Lock.With(accessor.getWriteLock(), entityStore.getConfiguration().getLockWaitTimeoutMilliseconds()) {
+ Lock.With with = new Lock.With(accessor.getStoreWriteLock(), entityStore.getConfiguration().getLockWaitTimeoutMilliseconds()) {
public Object doBody() throws IOException {
if (accessor == null) {
throw new IOException("Transaction is not started");
Modified: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationDeadlocking.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationDeadlocking.java?rev=757265&r1=757264&r2=757265&view=diff
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationDeadlocking.java (original)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationDeadlocking.java Sun Mar 22 22:12:12 2009
@@ -1,6 +1,6 @@
package org.apache.labs.bananadb.entity.isolation;
-import org.apache.labs.bananadb.store.Metadata;
+import org.apache.labs.bananadb.store.data.Metadata;
import org.apache.labs.bananadb.entity.PrimaryIndex;
import org.apache.labs.bananadb.entity.Transaction;
Modified: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationLastCommitWins.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationLastCommitWins.java?rev=757265&r1=757264&r2=757265&view=diff
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationLastCommitWins.java (original)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationLastCommitWins.java Sun Mar 22 22:12:12 2009
@@ -1,6 +1,6 @@
package org.apache.labs.bananadb.entity.isolation;
-import org.apache.labs.bananadb.store.Metadata;
+import org.apache.labs.bananadb.store.data.Metadata;
import org.apache.labs.bananadb.entity.PrimaryIndex;
import org.apache.labs.bananadb.entity.Transaction;
Modified: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationUpdated.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationUpdated.java?rev=757265&r1=757264&r2=757265&view=diff
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationUpdated.java (original)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/entity/isolation/IsolationUpdated.java Sun Mar 22 22:12:12 2009
@@ -1,6 +1,6 @@
package org.apache.labs.bananadb.entity.isolation;
-import org.apache.labs.bananadb.store.Metadata;
+import org.apache.labs.bananadb.store.data.Metadata;
import org.apache.labs.bananadb.entity.PrimaryIndex;
import org.apache.labs.bananadb.entity.Transaction;
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=757265&r1=757264&r2=757265&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 Sun Mar 22 22:12:12 2009
@@ -19,6 +19,12 @@
import org.apache.labs.bananadb.store.lock.Lock;
+import org.apache.labs.bananadb.store.data.bananatrie.HashCodesPartition;
+import org.apache.labs.bananadb.store.data.bananatrie.Hashtable;
+import org.apache.labs.bananadb.store.data.bananatrie.KeysPartition;
+import org.apache.labs.bananadb.store.data.bananatrie.ValuesPartition;
+import org.apache.labs.bananadb.store.data.FileHandler;
+import org.apache.labs.bananadb.store.data.Metadata;
import java.io.IOException;
import java.util.Map;
@@ -41,7 +47,8 @@
private Store store;
private String access;
- private Lock writeLock;
+ private Lock storeWriteLock;
+ private Metadata.Header lockedMetadata;
private Metadata metadata;
private Hashtable hashtable;
@@ -49,11 +56,12 @@
private Map<Integer, KeysPartition> keyPartitions = new HashMap<Integer, KeysPartition>();
private Map<Integer, ValuesPartition> valuePartitions = new HashMap<Integer, ValuesPartition>();
+
Accessor(final Store store, boolean readOnly) throws IOException {
this.store = store;
access = readOnly ? "r" : "rw";
- writeLock = store.getConfiguration().getLockFactory().makeLock("lock");
- metadata = new Metadata(store.getConfiguration().getDataPath(), access);
+ storeWriteLock = store.getConfiguration().getLockFactory().makeLock("lock");
+ metadata = new Metadata(store.getConfiguration().getDataPath(), access, store.getConfiguration().getLockFactory());
if (metadata.getFile().exists()) {
metadata.open();
@@ -67,7 +75,7 @@
log.info("Creating new store..");
- Lock.With width = new Lock.With(writeLock, store.getConfiguration().getLockWaitTimeoutMilliseconds()) {
+ Lock.With width = new Lock.With(storeWriteLock, store.getConfiguration().getLockWaitTimeoutMilliseconds()) {
public Object doBody() throws IOException {
if (!metadata.getFile().exists()) {
@@ -82,7 +90,7 @@
mdh.setValuePostingsCount(0);
metadata.writeHeader(mdh);
- hashtable = new Hashtable(store.getConfiguration().getDataPath(), 0, access);
+ hashtable = new Hashtable(store.getConfiguration().getDataPath(), 0, access, store.getConfiguration().getLockFactory());
hashtable.format((store.getConfiguration().getInitialCapacity() * Hashtable.Posting.POSTING_BYTE_SIZE) + hashtable.getHeaderByteSize());
hashtable.open();
Hashtable.Header hth = new Hashtable.Header();
@@ -139,7 +147,7 @@
if (hashtable != null) {
hashtable.getRAF().close();
}
- hashtable = new Hashtable(store.getConfiguration().getDataPath(), metadataHeader.getCurrentHashtableId(), access);
+ hashtable = new Hashtable(store.getConfiguration().getDataPath(), metadataHeader.getCurrentHashtableId(), access, store.getConfiguration().getLockFactory());
hashtable.open();
}
return hashtable;
@@ -148,10 +156,10 @@
public HashCodesPartition getHashCodesPartition(int partitionId) throws IOException {
HashCodesPartition partition = hashCodesPartitions.get(partitionId);
if (partition == null) {
- partition = new HashCodesPartition(store.getConfiguration().getDataPath(), partitionId, access);
+ partition = new HashCodesPartition(store.getConfiguration().getDataPath(), partitionId, access, store.getConfiguration().getLockFactory());
if (!partition.getFile().exists()) {
final HashCodesPartition p = partition;
- Lock.With with = new Lock.With(writeLock, store.getConfiguration().getLockWaitTimeoutMilliseconds()) {
+ Lock.With with = new Lock.With(storeWriteLock, store.getConfiguration().getLockWaitTimeoutMilliseconds()) {
public Object doBody() throws IOException {
if (!p.getFile().exists()) {
p.format(store.getConfiguration().getHashCodesPartitionByteSize());
@@ -176,10 +184,10 @@
public KeysPartition getKeysPartition(int partitionId) throws IOException {
KeysPartition partition = keyPartitions.get(partitionId);
if (partition == null) {
- partition = new KeysPartition(store.getConfiguration().getDataPath(), partitionId, access);
+ partition = new KeysPartition(store.getConfiguration().getDataPath(), partitionId, access, store.getConfiguration().getLockFactory());
if (!partition.getFile().exists()) {
final KeysPartition p = partition;
- Lock.With with = new Lock.With(writeLock, store.getConfiguration().getLockWaitTimeoutMilliseconds()) {
+ Lock.With with = new Lock.With(storeWriteLock, store.getConfiguration().getLockWaitTimeoutMilliseconds()) {
public Object doBody() throws IOException {
if (!p.getFile().exists()) {
p.format(store.getConfiguration().getKeysPartitionByteSize());
@@ -204,10 +212,10 @@
public ValuesPartition getValuesPartition(int partitionId) throws IOException {
ValuesPartition partition = valuePartitions.get(partitionId);
if (partition == null) {
- partition = new ValuesPartition(store.getConfiguration().getDataPath(), partitionId, access);
+ partition = new ValuesPartition(store.getConfiguration().getDataPath(), partitionId, access, store.getConfiguration().getLockFactory());
if (!partition.getFile().exists()) {
final ValuesPartition p = partition;
- Lock.With with = new Lock.With(writeLock, store.getConfiguration().getLockWaitTimeoutMilliseconds()) {
+ Lock.With with = new Lock.With(storeWriteLock, store.getConfiguration().getLockWaitTimeoutMilliseconds()) {
public Object doBody() throws IOException {
if (!p.getFile().exists()) {
p.format(store.getConfiguration().getValuesPartitionByteSize());
@@ -376,8 +384,8 @@
}
}
- public Lock getWriteLock() {
- return writeLock;
+ public Lock getStoreWriteLock() {
+ return storeWriteLock;
}
public Store getStore() {
Modified: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Configuration.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Configuration.java?rev=757265&r1=757264&r2=757265&view=diff
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Configuration.java (original)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/Configuration.java Sun Mar 22 22:12:12 2009
@@ -20,6 +20,7 @@
import org.apache.labs.bananadb.store.lock.LockFactory;
import org.apache.labs.bananadb.store.lock.NativeFSLockFactory;
+import org.apache.labs.bananadb.store.sequence.SequenceManager;
import java.io.File;
import java.io.IOException;
@@ -64,7 +65,6 @@
*/
private double automaticRehashThreadshold = 0.125d;
-
private LockFactory lockFactory;
private long lockWaitTimeoutMilliseconds = 60000;
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=757265&r1=757264&r2=757265&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 Sun Mar 22 22:12:12 2009
@@ -19,6 +19,14 @@
*/
import org.apache.labs.bananadb.store.lock.Lock;
+import org.apache.labs.bananadb.store.data.bananatrie.HashCodesPartition;
+import org.apache.labs.bananadb.store.data.bananatrie.Hashtable;
+import org.apache.labs.bananadb.store.data.bananatrie.KeysPartition;
+import org.apache.labs.bananadb.store.data.bananatrie.ValuesPartition;
+import org.apache.labs.bananadb.store.data.Metadata;
+import org.apache.labs.bananadb.store.data.FileHandler;
+import org.apache.labs.bananadb.store.sequence.SequenceManager;
+import org.apache.labs.bananadb.store.sequence.StaticSequenceManager;
import java.io.File;
import java.io.IOException;
@@ -36,6 +44,8 @@
private static final Log log = new Log(Store.class);
private Configuration configuration;
+ private SequenceManager sequenceManager = new StaticSequenceManager();
+ private List<Accessor> accessors = new ArrayList<Accessor>();
public Store(File dataPath) throws IOException {
this(new Configuration(dataPath));
@@ -57,8 +67,10 @@
}
}
+ public SequenceManager getSequenceManager() {
+ return sequenceManager;
+ }
- private List<Accessor> accessors = new ArrayList<Accessor>();
List<Accessor> getAccessors() {
return accessors;
@@ -149,6 +161,30 @@
return valuePosting.getBytes();
}
+ public byte[] put(final Accessor accessor, final byte[] key, final long hashCode, final byte[] value) throws IOException {
+ validateKey(key);
+
+ long revision = incrementAndGetRevision(accessor);
+
+ return put(accessor, key, hashCode, value, revision);
+ }
+
+ private long incrementAndGetRevision(final Accessor accessor) throws IOException {
+ Lock.With<Long> with = new Lock.With<Long>(accessor.getStoreWriteLock(), getConfiguration().getLockWaitTimeoutMilliseconds()) {
+ public Long doBody() throws IOException {
+ Metadata metadata = accessor.getMetadata();
+ Metadata.Header mdh = new Metadata.Header();
+ metadata.readHeader(mdh);
+ mdh.setCommitVersion(mdh.getCommitVersion() + 1);
+ metadata.writeHeader(mdh);
+ return mdh.getCommitVersion();
+ }
+ };
+ long revision = with.run();
+ return revision;
+ }
+
+
/**
* Write locking.
*
@@ -159,19 +195,13 @@
* @return
* @throws IOException
*/
- public byte[] put(final Accessor accessor, final byte[] key, final long hashCode, final byte[] value) throws IOException {
+ public byte[] put(final Accessor accessor, final byte[] key, final long hashCode, final byte[] value, final long revision) throws IOException {
validateKey(key);
- Lock.With<byte[]> with = new Lock.With<byte[]>(accessor.getWriteLock(), getConfiguration().getLockWaitTimeoutMilliseconds()) {
+ Lock.With<byte[]> with = new Lock.With<byte[]>(accessor.getStoreWriteLock(), getConfiguration().getLockWaitTimeoutMilliseconds()) {
public byte[] doBody() throws IOException {
- byte[] ret = doPut(accessor, key, hashCode, value);
- Metadata metadata = accessor.getMetadata();
- Metadata.Header mdh = new Metadata.Header();
- metadata.readHeader(mdh);
- mdh.setCommitVersion(mdh.getCommitVersion() + 1);
- metadata.writeHeader(mdh);
- return ret;
+ return doPut(accessor, key, hashCode, value, revision);
}
};
return with.run();
@@ -187,7 +217,7 @@
* @return
* @throws IOException
*/
- private byte[] doPut(final Accessor accessor, final byte[] key, final long hashCode, final byte[] value) throws IOException {
+ private byte[] doPut(final Accessor accessor, final byte[] key, final long hashCode, final byte[] value, final long revision) throws IOException {
//
@@ -198,7 +228,9 @@
int newValuePostingPartitionOffset;
ValuesPartition.Posting valuePosting = new ValuesPartition.Posting();
+ valuePosting.setFlag(FileHandler.Posting.FLAG_IN_USE);
+ valuePosting.setCreatedRevision(revision);
if (value == null || value.length == 0) {
valuePosting.setBytesLength(0);
valuePosting.setBytes(null);
@@ -226,6 +258,7 @@
//
KeysPartition.Posting newKeyPosting = new KeysPartition.Posting();
+ newKeyPosting.setCreatedRevision(revision);
newKeyPosting.setFlag((byte) 1);
newKeyPosting.setBytes(key);
newKeyPosting.setBytesLength(key.length);
@@ -249,15 +282,18 @@
Hashtable hashtable = accessor.getHashtable();
Hashtable.Posting hashtablePosting = new Hashtable.Posting();
+
HashCodesPartition.Posting hashCodePosting = new HashCodesPartition.Posting();
int hashtablePostingOffset = hashtable.calculateHashCodePostingOffset(hashCode);
- hashtable.readPosting(hashtablePosting, hashtablePostingOffset);
- if (hashtablePosting.getFlag() != (byte) 1) {
+ hashtable.getRAF().seek(hashtablePostingOffset);
+ byte flag = hashtable.getRAF().readByte();
+ if (flag != FileHandler.Posting.FLAG_IN_USE) {
// this is the first time we create a posting at this hashtable position
// that means there is no hash code posting either
+ hashCodePosting.setCreatedRevision(revision);
hashCodePosting.setFlag((byte) 1);
hashCodePosting.setFirstKeyPostingPartition(newKeyPostingPartition);
hashCodePosting.setFirstKeyPostingPartitionOffset(newKeyPostingPartitionOffset);
@@ -277,6 +313,7 @@
hashtablePosting.setFlag((byte) 1);
hashtablePosting.setHashCodePostingPartition(newHashCodePostingPatition);
hashtablePosting.setHashCodePostingPartitionOffset(newHashCodePostingPatitionOffset);
+ hashtablePosting.setCreatedRevision(revision);
hashtable.writePosting(hashtablePosting, hashtablePostingOffset);
return null;
@@ -285,12 +322,14 @@
// there is a hashtable posting at the position for this hash code
+ hashtable.readPosting(hashtablePosting, hashtablePostingOffset);
+
//
// seek to the correct hash code posting
- //
+ //
HashCodesPartition hashCodesPartition = accessor.getHashCodesPartition(hashtablePosting.getHashCodePostingPartition());
- int currentHashCodesPotingPartitionOffset = hashtablePosting.getHashCodePostingPartitionOffset();
+ int currentHashCodesPostingPartitionOffset = hashtablePosting.getHashCodePostingPartitionOffset();
hashCodesPartition.readPosting(hashCodePosting, hashtablePosting.getHashCodePostingPartitionOffset());
while (hashCode != hashCodePosting.getKeyHashCode()) {
if (hashCodePosting.getNextPostingPartition() < 0) {
@@ -302,6 +341,7 @@
//
HashCodesPartition.Posting newHashCodePosting = new HashCodesPartition.Posting();
+ newHashCodePosting.setCreatedRevision(revision);
newHashCodePosting.setFlag((byte) 1);
newHashCodePosting.setKeyHashCode(hashCode);
newHashCodePosting.setNextPostingPartition(-1);
@@ -323,7 +363,7 @@
hashCodePosting.setNextPostingPartition(newHashCodePostingPartition);
hashCodePosting.setNextPostingPartitionOffset(newHashCodePostingPartitionOffset);
- hashCodesPartition.writePosting(hashCodePosting, currentHashCodesPotingPartitionOffset);
+ hashCodesPartition.writePosting(hashCodePosting, currentHashCodesPostingPartitionOffset);
return null;
@@ -331,7 +371,7 @@
if (hashCodePosting.getNextPostingPartition() != hashCodesPartition.getPartitionId()) {
hashCodesPartition = accessor.getHashCodesPartition(hashCodePosting.getNextPostingPartition());
}
- currentHashCodesPotingPartitionOffset = hashCodePosting.getNextPostingPartitionOffset();
+ currentHashCodesPostingPartitionOffset = hashCodePosting.getNextPostingPartitionOffset();
hashCodesPartition.readPosting(hashCodePosting, hashCodePosting.getNextPostingPartitionOffset());
}
@@ -385,11 +425,11 @@
hashCodePosting.setFirstKeyPostingPartition(newKeyPostingPartition);
hashCodePosting.setFirstKeyPostingPartitionOffset(newKeyPostingPartitionOffset);
- hashCodesPartition.writePosting(hashCodePosting, currentHashCodesPotingPartitionOffset);
+ hashCodesPartition.writePosting(hashCodePosting, currentHashCodesPostingPartitionOffset);
} else {
// mark old key as deleted
- keysPartition.deletePosting(currentKeyPostingPartitionOffset);
+ keysPartition.deletePosting(currentKeyPostingPartitionOffset, revision);
// update previous key posting in chain to point chain at new key posting rather than the deleted
if (previousKeyPostingPartition != currentKeyPostingPartition) {
@@ -413,7 +453,7 @@
}
// mark the old value as deleted
- valuesPartition.deletePosting(keyPosting.getValuePostingPartitionOffset());
+ valuesPartition.deletePosting(keyPosting.getValuePostingPartitionOffset(), revision);
return oldValue;
@@ -421,23 +461,29 @@
}
+ public byte[] remove(final Accessor accessor, final byte[] key, final long hashCode) throws IOException {
+ long revision = incrementAndGetRevision(accessor);
+ return remove(accessor, key, hashCode, revision);
+ }
+
/**
* Write locking.
*
* @param accessor
* @param key
* @param hashCode
+ * @param revision revision flaggad as deletion revision
* @return
* @throws IOException
*/
- public byte[] remove(final Accessor accessor, final byte[] key, final long hashCode) throws IOException {
+ public byte[] remove(final Accessor accessor, final byte[] key, final long hashCode, final long revision) throws IOException {
validateKey(key);
- Lock.With<byte[]> with = new Lock.With<byte[]>(accessor.getWriteLock(), getConfiguration().getLockWaitTimeoutMilliseconds()) {
+ Lock.With<byte[]> with = new Lock.With<byte[]>(accessor.getStoreWriteLock(), getConfiguration().getLockWaitTimeoutMilliseconds()) {
public byte[] doBody() throws IOException {
- byte[] ret = doRemove(accessor, key, hashCode);
+ byte[] ret = doRemove(accessor, key, hashCode, revision);
Metadata metadata = accessor.getMetadata();
Metadata.Header mdh = new Metadata.Header();
@@ -461,7 +507,7 @@
* @return
* @throws IOException
*/
- private byte[] doRemove(final Accessor accessor, final byte[] key, final long hashCode) throws IOException {
+ private byte[] doRemove(final Accessor accessor, final byte[] key, final long hashCode, final long revision) throws IOException {
Hashtable.Posting hashtablePosting = new Hashtable.Posting();
@@ -552,9 +598,9 @@
// so delete the hashtable and hash code posting
//
- hashCodesPartition.deletePosting(currentHashCodePostingPartitionOffset);
+ hashCodesPartition.deletePosting(currentHashCodePostingPartitionOffset, revision);
- hashtable.deletePosting(hashtablePostingOffset);
+ hashtable.deletePosting(hashtablePostingOffset, revision);
}
@@ -578,7 +624,7 @@
// mark old key as deleted
- keysPartition.deletePosting(currentKeyPostingPartitionOffset);
+ keysPartition.deletePosting(currentKeyPostingPartitionOffset, revision);
// read the old value
@@ -594,7 +640,7 @@
}
// mark the old value as deleted
- oldValuePartition.deletePosting(keyPosting.getValuePostingPartitionOffset());
+ oldValuePartition.deletePosting(keyPosting.getValuePostingPartitionOffset(), revision);
return oldValue;
@@ -679,19 +725,19 @@
* @throws IOException
*/
public void rehash(final Accessor accessor, final int resolution) throws IOException {
- Lock.With with = new Lock.With(accessor.getWriteLock(), getConfiguration().getLockWaitTimeoutMilliseconds()) {
+ Lock.With with = new Lock.With(accessor.getStoreWriteLock(), getConfiguration().getLockWaitTimeoutMilliseconds()) {
public Object doBody() throws IOException {
log.info("Rehashing hashtable capacity ??? -> " + resolution);
- Metadata metadata = accessor.getMetadata();
+ 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());
+ Hashtable rehashedTable = new Hashtable(getConfiguration().getDataPath(), mdh.getCurrentHashtableId() + 1, accessor.getAccess(), getConfiguration().getLockFactory());
rehashedTable.format((resolution * Hashtable.Posting.POSTING_BYTE_SIZE) + rehashedTable.getHeaderByteSize());
rehashedTable.open();
@@ -699,7 +745,7 @@
rehashedTableHeader.setPostingsCapacity(resolution);
rehashedTable.writeHeader(rehashedTableHeader);
- // will format a new one!
+ // will data a new one!
HashCodesPartition rehashCodesPartition = accessor.getHashCodesPartition(mdh.getCurrentHashCodesPartition());
Hashtable.Posting rehashedTablePosting = new Hashtable.Posting();
@@ -708,7 +754,7 @@
rehashCodesPartition.readHeader(rehashCodeHeader);
for (int currentOldHashCodePostingsPartitionId = 0; currentOldHashCodePostingsPartitionId <= topOldHashCodesPartition; currentOldHashCodePostingsPartitionId++) {
- HashCodesPartition currentOldHashCodesPartition = new HashCodesPartition(getConfiguration().getDataPath(), currentOldHashCodePostingsPartitionId, accessor.getAccess());
+ HashCodesPartition currentOldHashCodesPartition = new HashCodesPartition(getConfiguration().getDataPath(), currentOldHashCodePostingsPartitionId, accessor.getAccess(), getConfiguration().getLockFactory());
if (currentOldHashCodesPartition.exists()) {
currentOldHashCodesPartition.open();
HashCodesPartition.Header hcph = new HashCodesPartition.Header();
@@ -799,6 +845,8 @@
rehashCodePosting.setKeyHashCode(hashCodePosting.getKeyHashCode());
rehashCodePosting.setNextPostingPartition(-1);
rehashCodePosting.setNextPostingPartitionOffset(-1);
+ rehashCodePosting.setCreatedRevision(hashCodePosting.getCreatedRevision());
+ rehashCodePosting.setDeletedRevision(hashCodePosting.getDeletedRevision());
rehashCodePartition.writePosting(rehashCodePosting, rehashCodeHeader.getNextPostingOffset());
Added: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/FileHandler.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/FileHandler.java?rev=757265&view=auto
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/FileHandler.java (added)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/FileHandler.java Sun Mar 22 22:12:12 2009
@@ -0,0 +1,214 @@
+package org.apache.labs.bananadb.store.data;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import org.apache.labs.bananadb.store.lock.Lock;
+import org.apache.labs.bananadb.store.lock.LockFactory;
+import org.apache.labs.bananadb.store.Log;
+
+import java.io.File;
+import java.io.RandomAccessFile;
+import java.io.IOException;
+import java.io.FileOutputStream;
+import java.util.Arrays;
+
+/**
+ * @author kalle
+ * @since 2009-mar-16 15:28:29
+ */
+public abstract class FileHandler<H extends FileHandler.Header, P extends FileHandler.Posting> {
+
+ private static final Log log = new Log(FileHandler.class);
+
+ private File file;
+ private RandomAccessFile RAF;
+ private String access;
+ private Lock lock;
+
+ private H header;
+
+ protected FileHandler(File directory, int id, String suffix, String access, LockFactory lockFactory) throws IOException {
+ StringBuilder sb = new StringBuilder(15);
+ sb.append(String.valueOf(id));
+ while (sb.length() < 8) {
+ sb.insert(0, "0");
+ }
+ sb.append(".");
+ sb.append(suffix);
+ this.file = new File(directory, sb.toString());
+ this.access = access;
+
+ lock = lockFactory.makeLock(sb.toString());
+ }
+
+ public Lock getLock() {
+ return lock;
+ }
+
+ public void format(long size) throws IOException {
+ format(size, (byte) 0);
+ }
+
+ public boolean exists() {
+ return getFile().exists();
+ }
+
+ public void format(long size, byte defaultValue) throws IOException {
+ log.info("Formatting " + file.getAbsolutePath() + "..");
+
+ long ms = System.currentTimeMillis();
+
+ long leftToWrite = size;
+
+ FileOutputStream fos = new FileOutputStream(file);
+ int bufSize = Math.min(1024 * 1024, (int)(size / 5));
+ byte[] bytes = new byte[bufSize];
+ Arrays.fill(bytes, defaultValue);
+ while (leftToWrite >= bytes.length) {
+ fos.write(bytes);
+ leftToWrite -= bytes.length;
+ }
+ if (leftToWrite > 0) {
+ fos.write(bytes, defaultValue, (int) leftToWrite);
+ }
+ fos.close();
+
+ log.info("It took " + (System.currentTimeMillis() - ms) + " milliseconds to data " + file.getAbsolutePath());
+ }
+
+ public void open() throws IOException {
+ if (RAF != null) {
+ throw new IOException("Already open");
+ }
+ this.RAF = new RandomAccessFile(file, access);
+ }
+
+ public void close() throws IOException {
+ if (RAF == null) {
+ throw new IOException("Already closed");
+ }
+ RAF.close();
+ }
+
+ public abstract int getHeaderByteSize();
+
+ public File getFile() {
+ return file;
+ }
+
+ public RandomAccessFile getRAF() {
+ return RAF;
+ }
+
+ public static abstract class Header {
+ }
+
+ public static abstract class Posting {
+
+ public static final byte FLAG_NEVER_USED = (byte)0;
+ public static final byte FLAG_IN_USE = (byte)1;
+ public static final byte FLAG_DELETED = (byte)2;
+
+ public abstract int getPostingByteSize();
+ public abstract byte getFlag();
+ public abstract void setFlag(byte flag);
+ public abstract long getCreatedRevision();
+ public abstract void setCreatedRevision(long revision);
+ public abstract long getDeletedRevision();
+ public abstract void setDeletedRevision(long revision);
+
+ }
+
+// public void writePosting(P posting) throws IOException {
+// writePosting(posting, getRAF());
+// }
+
+ /**
+ * Marks the posting at the start offset as deleted
+ * @param startOffset
+ * @param revision
+ * @throws IOException
+ */
+ public void deletePosting(int startOffset, long revision) throws IOException {
+ deletePosting(startOffset, RAF, revision);
+ }
+
+ public abstract void deletePosting(int startOffset, RandomAccessFile RAF, long revision) throws IOException;
+
+ public void writePosting(P posting, int startOffset) throws IOException {
+ writePosting(posting, startOffset, getRAF());
+ }
+
+ public void writePosting(P posting, int startOffset, RandomAccessFile RAF) throws IOException {
+ RAF.seek(startOffset);
+ 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 {
+// readPosting(posting, getRAF());
+// }
+
+ public void readPosting(P posting, int startOffset) throws IOException {
+ readPosting(posting, startOffset, getRAF());
+ }
+
+ public void readPosting(P posting, int startOffset, RandomAccessFile RAF) throws IOException {
+ RAF.seek(startOffset);
+ readPosting(posting, RAF);
+ }
+
+ public abstract void readPosting(P posting, RandomAccessFile RAF) throws IOException;
+
+
+ public void writeHeader(H header) throws IOException {
+ writeHeader(header, 0, getRAF());
+ }
+
+ public void writeHeader(H header, int startOffset) throws IOException {
+ writeHeader(header, startOffset, getRAF());
+ }
+
+ public void writeHeader(H header, int startOffset, RandomAccessFile RAF) throws IOException {
+ RAF.seek(startOffset);
+ writeHeader(header, RAF);
+ }
+
+ public abstract void writeHeader(H header, RandomAccessFile RAF) throws IOException;
+
+ public void readHeader(H header) throws IOException {
+ readHeader(header, 0, RAF);
+ }
+
+ public void readHeader(H header, int startOffset) throws IOException {
+ readHeader(header, startOffset, getRAF());
+ }
+
+ public void readHeader(H header, int startOffset, RandomAccessFile RAF) throws IOException {
+ RAF.seek(startOffset);
+ readHeader(header, RAF);
+ }
+
+ public abstract void readHeader(H header, RandomAccessFile RAF) throws IOException;
+}
Added: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/Metadata.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/Metadata.java?rev=757265&view=auto
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/Metadata.java (added)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/Metadata.java Sun Mar 22 22:12:12 2009
@@ -0,0 +1,174 @@
+package org.apache.labs.bananadb.store.data;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import org.apache.labs.bananadb.store.lock.LockFactory;
+
+import java.io.RandomAccessFile;
+import java.io.IOException;
+import java.io.File;
+
+/**
+ * @author kalle
+ * @since 2009-mar-16 14:16:39
+ */
+public class Metadata extends FileHandler<Metadata.Header, FileHandler.Posting> {
+
+ public Metadata(File directory, String access, LockFactory lockFactory) throws IOException {
+ super(directory, 0, "md", access, lockFactory);
+ }
+
+ public static final int HEADER_BYTE_SIZE = 1024;
+ public int getHeaderByteSize() {
+ return HEADER_BYTE_SIZE;
+ }
+
+ public static class Header extends FileHandler.Header {
+ /**
+ * File format version.
+ */
+ private int fileFormatVersion;
+
+ /**
+ * Current hashtable file id. -- will change after rehash.
+ */
+ private int currentHashtableId;
+
+ /** Current hash codes partition used for appending new postings */
+ private int currentHashCodesPartition;
+
+ /** Current keys partition used for appending new postings */
+ private int currentKeysPartition;
+
+ /** Current values partition used for appending new postings */
+ private int currentValuesPartition;
+
+ /**
+ * Total number of value postings.
+ */
+ private long valuePostingsCount;
+
+ /**
+ * Commit version, will increase by one after each modification to the database.
+ */
+ private long commitVersion;
+
+ public int getCurrentHashCodesPartition() {
+ return currentHashCodesPartition;
+ }
+
+ public void setCurrentHashCodesPartition(int currentHashCodesPartition) {
+ this.currentHashCodesPartition = currentHashCodesPartition;
+ }
+
+ public int getCurrentKeysPartition() {
+ return currentKeysPartition;
+ }
+
+ public void setCurrentKeysPartition(int currentKeysPartition) {
+ this.currentKeysPartition = currentKeysPartition;
+ }
+
+ public int getCurrentValuesPartition() {
+ return currentValuesPartition;
+ }
+
+ public void setCurrentValuesPartition(int currentValuesPartition) {
+ this.currentValuesPartition = currentValuesPartition;
+ }
+
+ public int getFileFormatVersion() {
+ return fileFormatVersion;
+ }
+
+ public void setFileFormatVersion(int fileFormatVersion) {
+ this.fileFormatVersion = fileFormatVersion;
+ }
+
+ public int getCurrentHashtableId() {
+ return currentHashtableId;
+ }
+
+ public void setCurrentHashtableId(int currentHashtableId) {
+ this.currentHashtableId = currentHashtableId;
+ }
+
+ public long getValuePostingsCount() {
+ return valuePostingsCount;
+ }
+
+ public void setValuePostingsCount(long valuePostingsCount) {
+ this.valuePostingsCount = valuePostingsCount;
+ }
+
+ public long getCommitVersion() {
+ return commitVersion;
+ }
+
+ public void setCommitVersion(long commitVersion) {
+ this.commitVersion = commitVersion;
+ }
+
+ public long increaseCommitVersion(long value) {
+ return commitVersion += value;
+ }
+
+ public long increaseValuePostingsCount(long value) {
+ return valuePostingsCount += value;
+ }
+
+ public long decreaseValuePostingsCount(long value) {
+ return valuePostingsCount -= value;
+ }
+
+ }
+
+ public void readHeader(Header header, RandomAccessFile RAF) throws IOException {
+ header.fileFormatVersion = RAF.readInt();
+ header.commitVersion = RAF.readLong();
+ header.currentHashtableId = RAF.readInt();
+ header.currentHashCodesPartition = RAF.readInt();
+ header.currentKeysPartition = RAF.readInt();
+ header.currentValuesPartition = RAF.readInt();
+ header.valuePostingsCount = RAF.readLong();
+ System.currentTimeMillis();
+ }
+
+ public void writeHeader(Header header, RandomAccessFile RAF) throws IOException {
+ RAF.writeInt(header.fileFormatVersion);
+ RAF.writeLong(header.commitVersion);
+ RAF.writeInt(header.currentHashtableId);
+ RAF.writeInt(header.currentHashCodesPartition);
+ RAF.writeInt(header.currentKeysPartition);
+ RAF.writeInt(header.currentValuesPartition);
+ RAF.writeLong(header.valuePostingsCount);
+ }
+
+ public void writePosting(Posting posting, RandomAccessFile RAF) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void readPosting(Posting posting, RandomAccessFile RAF) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void deletePosting(int startOffset, RandomAccessFile RAF, long revision) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+}
Added: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/HashCodesPartition.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/HashCodesPartition.java?rev=757265&view=auto
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/HashCodesPartition.java (added)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/HashCodesPartition.java Sun Mar 22 22:12:12 2009
@@ -0,0 +1,239 @@
+package org.apache.labs.bananadb.store.data.bananatrie;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.labs.bananadb.store.lock.LockFactory;
+import org.apache.labs.bananadb.store.data.FileHandler;
+
+import java.io.RandomAccessFile;
+import java.io.IOException;
+import java.io.File;
+
+/**
+ * Hash code postings partition file.
+ * <p/>
+ * Chained postings. Each postings has a unique hash code value and points at how to find
+ * the key posting for this hash code.
+ * <p/>
+ * This file is affected by rehashing.
+ *
+ * @author kalle
+ * @since 2009-mar-16 14:00:37
+ */
+public class HashCodesPartition extends FileHandler<HashCodesPartition.Header, HashCodesPartition.Posting> {
+
+ private int partitionId;
+
+ public HashCodesPartition(File directory, int partitionId, String access, LockFactory lockFactory) throws IOException {
+ super(directory, partitionId, "hc", access, lockFactory);
+ this.partitionId = partitionId;
+ }
+
+ public int getPartitionId() {
+ return partitionId;
+ }
+
+ public static final int HEADER_BYTE_SIZE = 1024;
+
+ public int getHeaderByteSize() {
+ return HEADER_BYTE_SIZE;
+ }
+
+ public static class Header extends FileHandler.Header {
+
+ /**
+ * Offset in this partition for next new posting.
+ */
+ private int nextPostingOffset;
+ /**
+ * Bytes left for use in this partition.
+ */
+ private int bytesLeft;
+
+ public int getNextPostingOffset() {
+ return nextPostingOffset;
+ }
+
+ public void setNextPostingOffset(int nextPostingOffset) {
+ this.nextPostingOffset = nextPostingOffset;
+ }
+
+ public int getBytesLeft() {
+ return bytesLeft;
+ }
+
+ public void setBytesLeft(int bytesLeft) {
+ this.bytesLeft = bytesLeft;
+ }
+
+
+ }
+
+ public static final int POSTING_BYTE_SIZE = 1 + 8 + 8 + 4 + 4 + 4 + 4 + 8;
+
+ public static class Posting extends FileHandler.Posting {
+
+ public int getPostingByteSize() {
+ return POSTING_BYTE_SIZE;
+ }
+
+ /**
+ * 0 = never used
+ * 1 = in use
+ * 2 = deleted
+ */
+ private byte flag;
+
+ /**
+ * Key hash code.
+ */
+ private long keyHashCode;
+
+ private long createdRevision;
+
+
+ /**
+ * Partition id of next hash code posting with the same hashtable posting position.
+ * -1 == no more hash code postings in chain
+ */
+ private int nextPostingPartition;
+
+ /**
+ * Offset in above hash code postings partition.
+ */
+ private int nextPostingPartitionOffset;
+
+
+ /**
+ * Partition id of first key posting with this hash code.
+ */
+ private int firstKeyPostingPartition;
+
+ /**
+ * Offset in above key postings partition.
+ */
+ private int firstKeyPostingPartitionOffset;
+
+ private long deletedRevision = -1;
+
+
+ public byte getFlag() {
+ return flag;
+ }
+
+ public void setFlag(byte flag) {
+ this.flag = flag;
+ }
+
+ public long getKeyHashCode() {
+ return keyHashCode;
+ }
+
+ public void setKeyHashCode(long keyHashCode) {
+ this.keyHashCode = keyHashCode;
+ }
+
+ public int getNextPostingPartition() {
+ return nextPostingPartition;
+ }
+
+ public void setNextPostingPartition(int nextPostingPartition) {
+ this.nextPostingPartition = nextPostingPartition;
+ }
+
+ public int getNextPostingPartitionOffset() {
+ return nextPostingPartitionOffset;
+ }
+
+ public void setNextPostingPartitionOffset(int nextPostingPartitionOffset) {
+ this.nextPostingPartitionOffset = nextPostingPartitionOffset;
+ }
+
+ public int getFirstKeyPostingPartition() {
+ return firstKeyPostingPartition;
+ }
+
+ public void setFirstKeyPostingPartition(int firstKeyPostingPartition) {
+ this.firstKeyPostingPartition = firstKeyPostingPartition;
+ }
+
+ public int getFirstKeyPostingPartitionOffset() {
+ return firstKeyPostingPartitionOffset;
+ }
+
+ public void setFirstKeyPostingPartitionOffset(int firstKeyPostingPartitionOffset) {
+ this.firstKeyPostingPartitionOffset = firstKeyPostingPartitionOffset;
+ }
+
+ public long getCreatedRevision() {
+ return createdRevision;
+ }
+
+ public void setCreatedRevision(long createdRevision) {
+ this.createdRevision = createdRevision;
+ }
+
+ public long getDeletedRevision() {
+ return deletedRevision;
+ }
+
+ public void setDeletedRevision(long deletedRevision) {
+ this.deletedRevision = deletedRevision;
+ }
+ }
+
+ public void readHeader(Header header, RandomAccessFile RAF) throws IOException {
+ header.nextPostingOffset = RAF.readInt();
+ header.bytesLeft = RAF.readInt();
+ }
+
+ public void writeHeader(Header header, RandomAccessFile RAF) throws IOException {
+ RAF.writeInt(header.nextPostingOffset);
+ RAF.writeInt(header.bytesLeft);
+ }
+
+
+ public void readPosting(Posting posting, RandomAccessFile RAF) throws IOException {
+ posting.flag = RAF.readByte();
+ posting.keyHashCode = RAF.readLong();
+ posting.createdRevision = RAF.readLong();
+ posting.nextPostingPartition = RAF.readInt();
+ posting.nextPostingPartitionOffset = RAF.readInt();
+ posting.firstKeyPostingPartition = RAF.readInt();
+ posting.firstKeyPostingPartitionOffset = RAF.readInt();
+ posting.deletedRevision = RAF.readLong();
+ }
+
+ public void writePosting(Posting posting, RandomAccessFile RAF) throws IOException {
+ RAF.writeByte(posting.flag);
+ RAF.writeLong(posting.keyHashCode);
+ RAF.writeLong(posting.createdRevision);
+ RAF.writeInt(posting.nextPostingPartition);
+ RAF.writeInt(posting.nextPostingPartitionOffset);
+ RAF.writeInt(posting.firstKeyPostingPartition);
+ RAF.writeInt(posting.firstKeyPostingPartitionOffset);
+ RAF.writeLong(posting.deletedRevision);
+ }
+
+ public void deletePosting(int startOffset, RandomAccessFile RAF, long revision) throws IOException {
+ RAF.seek(startOffset);
+ RAF.writeByte((byte) 2);
+ RAF.seek(8 + 4 + 4 + 4 + 4);
+ RAF.writeLong(revision);
+ }
+}
Added: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/Hashtable.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/Hashtable.java?rev=757265&view=auto
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/Hashtable.java (added)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/Hashtable.java Sun Mar 22 22:12:12 2009
@@ -0,0 +1,193 @@
+package org.apache.labs.bananadb.store.data.bananatrie;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import org.apache.labs.bananadb.store.lock.LockFactory;
+import org.apache.labs.bananadb.store.data.FileHandler;
+
+import java.io.RandomAccessFile;
+import java.io.IOException;
+import java.io.File;
+
+/**
+ * Hashtable file. There is never more than one of these that are valid at any given time.
+ * <p/>
+ * The position in the hashtable for a given hash code is calculated as (hash & (capacity - 1)).
+ * At this position there is a posting that points at the first known hash code posting.
+ * <p/>
+ * This file is affected by rehashing.
+ *
+ * @author kalle
+ * @since 2009-mar-16 14:00:56
+ */
+public class Hashtable extends FileHandler<Hashtable.Header, Hashtable.Posting> {
+
+
+ private int versionId;
+
+ /**
+ * header as when file was openend. used only to read capacity. but that is also all the header contains..
+ */
+ private Header header;
+
+ public Hashtable(File directory, int versionId, String access, LockFactory lockFactory) throws IOException {
+ super(directory, versionId, "ht", access, lockFactory);
+ this.versionId = versionId;
+ }
+
+ @Override
+ public void open() throws IOException {
+ super.open();
+ readHeader(header = new Header());
+ }
+
+ public int getVersionId() {
+ return versionId;
+ }
+
+ public static final int HEADER_BYTE_SIZE = 1024;
+
+ public int getHeaderByteSize() {
+ return HEADER_BYTE_SIZE;
+ }
+
+ public static class Header extends FileHandler.Header {
+ /**
+ * This hashtable postings file capacity.
+ */
+ private int postingsCapacity;
+
+ public int getPostingsCapacity() {
+ return postingsCapacity;
+ }
+
+ public void setPostingsCapacity(int postingsCapacity) {
+ this.postingsCapacity = postingsCapacity;
+ }
+ }
+
+
+ public static class Posting extends FileHandler.Posting {
+
+ public static final int POSTING_BYTE_SIZE = 1 + 8 + 4 + 4 + 8;
+
+ public int getPostingByteSize() {
+ return POSTING_BYTE_SIZE;
+ }
+
+ /**
+ * 0 = never used
+ * 1 = in use
+ * 2 = deleted
+ */
+ private byte flag;
+
+ private long createdRevision;
+
+ /**
+ * Partition id of first hash code posting with this hashtable position. -1 == null
+ */
+ private int hashCodePostingPartition;
+
+ /**
+ * Offset in above hash code postings partition.
+ */
+ private int hashCodePostingPartitionOffset;
+
+ private long deletedRevision = -1;
+
+ public byte getFlag() {
+ return flag;
+ }
+
+ public void setFlag(byte flag) {
+ this.flag = flag;
+ }
+
+ public int getHashCodePostingPartition() {
+ return hashCodePostingPartition;
+ }
+
+ public void setHashCodePostingPartition(int hashCodePostingPartition) {
+ this.hashCodePostingPartition = hashCodePostingPartition;
+ }
+
+ public int getHashCodePostingPartitionOffset() {
+ return hashCodePostingPartitionOffset;
+ }
+
+ public void setHashCodePostingPartitionOffset(int hashCodePostingPartitionOffset) {
+ this.hashCodePostingPartitionOffset = hashCodePostingPartitionOffset;
+ }
+
+ public long getCreatedRevision() {
+ return createdRevision;
+ }
+
+ public void setCreatedRevision(long createdRevision) {
+ this.createdRevision = createdRevision;
+ }
+
+ public long getDeletedRevision() {
+ return deletedRevision;
+ }
+
+ public void setDeletedRevision(long deletedRevision) {
+ this.deletedRevision = deletedRevision;
+ }
+ }
+
+ public void readHeader(Header header, RandomAccessFile RAF) throws IOException {
+ header.postingsCapacity = RAF.readInt();
+ }
+
+ public void writeHeader(Header header, RandomAccessFile RAF) throws IOException {
+ RAF.writeInt(header.postingsCapacity);
+ this.header = new Header();
+ this.header.postingsCapacity = header.postingsCapacity;
+ }
+
+ public int calculateHashCodePostingOffset(long hashCode) {
+ return (int) (HEADER_BYTE_SIZE + (Posting.POSTING_BYTE_SIZE * (hashCode & (header.postingsCapacity - 1))));
+ }
+
+ public void readPosting(Posting posting, RandomAccessFile RAF) throws IOException {
+ posting.flag = RAF.readByte();
+ posting.createdRevision = RAF.readLong();
+ posting.hashCodePostingPartition = RAF.readInt();
+ posting.hashCodePostingPartitionOffset = RAF.readInt();
+ posting.deletedRevision = RAF.readLong();
+ }
+
+ public void writePosting(Posting posting, RandomAccessFile RAF) throws IOException {
+ RAF.writeByte(posting.flag);
+ RAF.writeLong(posting.createdRevision);
+ RAF.writeInt(posting.hashCodePostingPartition);
+ RAF.writeInt(posting.hashCodePostingPartitionOffset);
+ RAF.writeLong(posting.deletedRevision);
+ }
+
+ public void deletePosting(int startOffset, RandomAccessFile RAF, long revision) throws IOException {
+ RAF.seek(startOffset);
+ RAF.writeByte((byte) 2);
+ RAF.seek(8 + 4 + 4);
+ RAF.writeLong(revision);
+ }
+
+}
Added: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/KeysPartition.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/KeysPartition.java?rev=757265&view=auto
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/KeysPartition.java (added)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/KeysPartition.java Sun Mar 22 22:12:12 2009
@@ -0,0 +1,274 @@
+package org.apache.labs.bananadb.store.data.bananatrie;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import org.apache.labs.bananadb.store.lock.LockFactory;
+import org.apache.labs.bananadb.store.data.FileHandler;
+
+import java.io.IOException;
+import java.io.File;
+import java.io.RandomAccessFile;
+
+/**
+ * Key postings partition file.
+ * <p/>
+ * Chained postings. Each posting contains a unique key value and points at how to
+ * find the value associated with this key.
+ * <p/>
+ * This file is NOT affected by rehashing.
+ *
+ * @author kalle
+ * @since 2009-mar-16 14:00:22
+ */
+public class KeysPartition extends FileHandler<KeysPartition.Header, KeysPartition.Posting> {
+
+ private int partitionId;
+
+ public KeysPartition(File directory, int partitionId, String access, LockFactory lockFactory) throws IOException {
+ super(directory, partitionId, "k", access, lockFactory);
+ this.partitionId = partitionId;
+ }
+
+ public static final int HEADER_BYTE_SIZE = 1024;
+
+ public int getHeaderByteSize() {
+ return HEADER_BYTE_SIZE;
+ }
+
+ public int getPartitionId() {
+ return partitionId;
+ }
+
+ public static class Header extends FileHandler.Header {
+
+ /**
+ * Offset in this partition for next new posting.
+ */
+ private int nextPostingOffset;
+ /**
+ * Bytes left for use in this partition.
+ */
+ private int bytesLeft;
+
+ public int getNextPostingOffset() {
+ return nextPostingOffset;
+ }
+
+ public void setNextPostingOffset(int nextPostingOffset) {
+ this.nextPostingOffset = nextPostingOffset;
+ }
+
+ public int getBytesLeft() {
+ return bytesLeft;
+ }
+
+ public void setBytesLeft(int bytesLeft) {
+ this.bytesLeft = bytesLeft;
+ }
+ }
+
+ public static class Posting extends FileHandler.Posting {
+
+
+ /**
+ * 0 = never used
+ * 1 = in use
+ * 2 = deleted
+ */
+ private byte flag;
+
+ private long createdRevision;
+
+ /**
+ * Partition id of next key posting with the same hash code.
+ * -1 == end of keys chain
+ * -2 == deleted key
+ */
+ private int nextKeyPostingPartition;
+ /**
+ * Offset in above key postings partition.
+ */
+ private int nextKeyPostingPartitionOffset;
+
+ /**
+ * Key hash code
+ */
+ private long keyHashCode;
+
+ /**
+ * Paritition id of value posting. -1 == null
+ */
+ private int valuePostingPartition;
+ /**
+ * Offset in above value postings partition.
+ */
+ private int valuePostingPartitionOffset;
+
+ /**
+ * Length in bytes of serialized key.
+ */
+ private int bytesLength;
+ /**
+ * Serialized key
+ */
+ private byte[] bytes;
+
+ private long deletedRevision = -1;
+
+ public int getPostingByteSize() {
+ return 1 + 8 + 4 + 4 + 8 + 4 + 4 + 4 + bytesLength + 8;
+ }
+
+ public byte getFlag() {
+ return flag;
+ }
+
+ public void setFlag(byte flag) {
+ this.flag = flag;
+ }
+
+ public int getNextKeyPostingPartition() {
+ return nextKeyPostingPartition;
+ }
+
+ public void setNextKeyPostingPartition(int nextKeyPostingPartition) {
+ this.nextKeyPostingPartition = nextKeyPostingPartition;
+ }
+
+ public int getNextKeyPostingPartitionOffset() {
+ return nextKeyPostingPartitionOffset;
+ }
+
+ public void setNextKeyPostingPartitionOffset(int nextKeyPostingPartitionOffset) {
+ this.nextKeyPostingPartitionOffset = nextKeyPostingPartitionOffset;
+ }
+
+ public long getKeyHashCode() {
+ return keyHashCode;
+ }
+
+ public void setKeyHashCode(long keyHashCode) {
+ this.keyHashCode = keyHashCode;
+ }
+
+ public int getValuePostingPartition() {
+ return valuePostingPartition;
+ }
+
+ public void setValuePostingPartition(int valuePostingPartition) {
+ this.valuePostingPartition = valuePostingPartition;
+ }
+
+ public int getValuePostingPartitionOffset() {
+ return valuePostingPartitionOffset;
+ }
+
+ public void setValuePostingPartitionOffset(int valuePostingPartitionOffset) {
+ this.valuePostingPartitionOffset = valuePostingPartitionOffset;
+ }
+
+ public int getBytesLength() {
+ return bytesLength;
+ }
+
+ public void setBytesLength(int bytesLength) {
+ this.bytesLength = bytesLength;
+ }
+
+ public byte[] getBytes() {
+ return bytes;
+ }
+
+ public void setBytes(byte[] bytes) {
+ this.bytes = bytes;
+ }
+
+ public long getCreatedRevision() {
+ return createdRevision;
+ }
+
+ public void setCreatedRevision(long createdRevision) {
+ this.createdRevision = createdRevision;
+ }
+
+ public long getDeletedRevision() {
+ return deletedRevision;
+ }
+
+ public void setDeletedRevision(long deletedRevision) {
+ this.deletedRevision = deletedRevision;
+ }
+ }
+
+ public void readHeader(Header header, RandomAccessFile RAF) throws IOException {
+ header.nextPostingOffset = RAF.readInt();
+ header.bytesLeft = RAF.readInt();
+ }
+
+ public void writeHeader(Header header, RandomAccessFile RAF) throws IOException {
+ RAF.writeInt(header.nextPostingOffset);
+ RAF.writeInt(header.bytesLeft);
+ }
+
+ public void readPosting(Posting posting, RandomAccessFile RAF) throws IOException {
+ posting.flag = RAF.readByte();
+ posting.createdRevision = RAF.readLong();
+ posting.nextKeyPostingPartition = RAF.readInt();
+ posting.nextKeyPostingPartitionOffset = RAF.readInt();
+ posting.keyHashCode = RAF.readLong();
+ posting.valuePostingPartition = RAF.readInt();
+ posting.valuePostingPartitionOffset = RAF.readInt();
+ posting.bytesLength = RAF.readInt();
+ if (posting.bytesLength > 0) {
+ if (posting.bytes == null || posting.bytes.length != posting.bytesLength) {
+ posting.bytes = new byte[posting.bytesLength];
+ }
+ int read = RAF.read(posting.bytes, 0, posting.bytesLength);
+ if (read != posting.bytesLength) {
+ throw new IOException("Unexcpected EOF");
+ }
+ }
+ posting.deletedRevision = RAF.readLong();
+ }
+
+ public void writePosting(Posting posting, RandomAccessFile RAF) throws IOException {
+ RAF.writeByte(posting.flag);
+ RAF.writeLong(posting.createdRevision);
+ RAF.writeInt(posting.nextKeyPostingPartition);
+ RAF.writeInt(posting.nextKeyPostingPartitionOffset);
+ RAF.writeLong(posting.keyHashCode);
+ RAF.writeInt(posting.valuePostingPartition);
+ RAF.writeInt(posting.valuePostingPartitionOffset);
+ RAF.writeInt(posting.bytesLength);
+ if (posting.bytesLength > 0) {
+ RAF.write(posting.bytes, 0, posting.bytesLength);
+ }
+ RAF.writeLong(posting.deletedRevision);
+ }
+
+ public void deletePosting(int startOffset, RandomAccessFile RAF, long revision) throws IOException {
+ RAF.seek(startOffset);
+ RAF.writeByte((byte) 2);
+ RAF.skipBytes(8 + 4 + 4 + 8 + 4 + 4);
+ RAF.skipBytes(RAF.readInt());
+ RAF.writeLong(revision);
+ }
+
+
+}
Added: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/ValuesPartition.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/ValuesPartition.java?rev=757265&view=auto
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/ValuesPartition.java (added)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/data/bananatrie/ValuesPartition.java Sun Mar 22 22:12:12 2009
@@ -0,0 +1,196 @@
+package org.apache.labs.bananadb.store.data.bananatrie;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import org.apache.labs.bananadb.store.lock.LockFactory;
+import org.apache.labs.bananadb.store.data.FileHandler;
+
+import java.io.RandomAccessFile;
+import java.io.IOException;
+import java.io.File;
+
+/**
+ * Values postings partition file.
+ * <p/>
+ * This file is NOT affected by rehashing.
+ *
+ * @author kalle
+ * @since 2009-mar-16 14:00:13
+ */
+public class ValuesPartition extends FileHandler<ValuesPartition.Header, ValuesPartition.Posting> {
+
+
+ private int partitionId;
+
+ public ValuesPartition(File directory, int partitionId, String access, LockFactory lockFactory) throws IOException {
+ super(directory, partitionId, "v", access, lockFactory);
+ this.partitionId = partitionId;
+ }
+
+ public static final int HEADER_BYTE_SIZE = 1024;
+
+ public int getHeaderByteSize() {
+ return HEADER_BYTE_SIZE;
+ }
+
+ public int getPartitionId() {
+ return partitionId;
+ }
+
+
+ public static class Header extends FileHandler.Header {
+
+ /**
+ * Offset in this partition for next new posting.
+ */
+ private int nextPostingOffset;
+ /**
+ * Bytes left for use in this partition.
+ */
+ private int bytesLeft;
+
+ public int getNextPostingOffset() {
+ return nextPostingOffset;
+ }
+
+ public void setNextPostingOffset(int nextPostingOffset) {
+ this.nextPostingOffset = nextPostingOffset;
+ }
+
+ public int getBytesLeft() {
+ return bytesLeft;
+ }
+
+ public void setBytesLeft(int bytesLeft) {
+ this.bytesLeft = bytesLeft;
+ }
+ }
+
+ public static class Posting extends FileHandler.Posting {
+
+ /**
+ * 0 = never used
+ * 1 = in use
+ * 2 = deleted
+ */
+ private byte flag;
+
+ private long createdRevision;
+ private long deletedRevision = -1;
+
+ /**
+ * Length in bytes of serializaed value.
+ * 0 == null
+ */
+ private int bytesLength;
+
+ /**
+ * Serialized value.
+ */
+ private byte[] bytes;
+
+
+ public int getPostingByteSize() {
+ return 1 + 8 + 8 + 8 + 4 + bytesLength + 8;
+ }
+
+ public byte getFlag() {
+ return flag;
+ }
+
+ public void setFlag(byte flag) {
+ this.flag = flag;
+ }
+
+ public int getBytesLength() {
+ return bytesLength;
+ }
+
+ public void setBytesLength(int valueBytesLength) {
+ this.bytesLength = valueBytesLength;
+ }
+
+ public byte[] getBytes() {
+ return bytes;
+ }
+
+ public void setBytes(byte[] valueBytes) {
+ this.bytes = valueBytes;
+ }
+
+ public long getCreatedRevision() {
+ return createdRevision;
+ }
+
+ public void setCreatedRevision(long createdRevision) {
+ this.createdRevision = createdRevision;
+ }
+
+ public long getDeletedRevision() {
+ return deletedRevision;
+ }
+
+ public void setDeletedRevision(long deletedRevision) {
+ this.deletedRevision = deletedRevision;
+ }
+ }
+
+ public void readHeader(Header header, RandomAccessFile RAF) throws IOException {
+ header.nextPostingOffset = RAF.readInt();
+ header.bytesLeft = RAF.readInt();
+ }
+
+ public void writeHeader(Header header, RandomAccessFile RAF) throws IOException {
+ RAF.writeInt(header.nextPostingOffset);
+ RAF.writeInt(header.bytesLeft);
+ }
+
+ public void readPosting(Posting posting, RandomAccessFile RAF) throws IOException {
+ posting.flag = RAF.readByte();
+ posting.createdRevision = RAF.readLong();
+ posting.bytesLength = RAF.readInt();
+ if (posting.bytesLength > 0) {
+ posting.bytes = new byte[posting.bytesLength];
+ int read = RAF.read(posting.bytes, 0, posting.bytesLength);
+ if (read != posting.bytesLength) {
+ throw new IOException("Unexpected EOF");
+ }
+ }
+ posting.deletedRevision = RAF.readLong();
+ }
+
+ public void writePosting(Posting posting, RandomAccessFile RAF) throws IOException {
+ RAF.writeByte(posting.flag);
+ RAF.writeLong(posting.createdRevision);
+ RAF.writeInt(posting.bytesLength);
+ if (posting.bytesLength > 0) {
+ RAF.write(posting.bytes, 0, posting.bytesLength);
+ }
+ RAF.writeLong(posting.deletedRevision);
+ }
+
+ public void deletePosting(int startOffset, RandomAccessFile RAF, long revision) throws IOException {
+ RAF.seek(startOffset);
+ RAF.writeByte((byte) 2);
+ RAF.skipBytes(8);
+ RAF.skipBytes(RAF.readInt());
+ RAF.writeLong(revision);
+ }
+
+}
Modified: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/lock/Lock.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/lock/Lock.java?rev=757265&r1=757264&r2=757265&view=diff
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/lock/Lock.java (original)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/lock/Lock.java Sun Mar 22 22:12:12 2009
@@ -19,8 +19,13 @@
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.Set;
-/** An interprocess mutex lock.
+/**
+ * An interprocess mutex lock.
* <p>Typical use might look like:<pre>
* new Lock.With(directory.makeLock("my.lock")) {
* public Object doBody() {
@@ -31,12 +36,22 @@
*/
public abstract class Lock {
- /** How long {@link #obtain(long)} waits, in milliseconds,
- * in between attempts to acquire the lock. */
+ private Set<LockListener> listeners = new LinkedHashSet<LockListener>();
+
+ public Set<LockListener> getListeners() {
+ return listeners;
+ }
+
+ /**
+ * How long {@link #obtain(long)} waits, in milliseconds,
+ * in between attempts to acquire the lock.
+ */
public static long LOCK_POLL_INTERVAL = 1000;
- /** Pass this value to {@link #obtain(long)} to try
- * forever to obtain the lock. */
+ /**
+ * Pass this value to {@link #obtain(long)} to try
+ * forever to obtain the lock.
+ */
public static final long LOCK_OBTAIN_WAIT_FOREVER = -1;
/**
@@ -44,22 +59,32 @@
*/
private AtomicInteger lockDepth = new AtomicInteger(0);
- /** Attempts to obtain exclusive access and immediately return
- * upon success or failure.
+ /**
+ * Attempts to obtain exclusive access and immediately return
+ * upon success or failure.
+ *
* @return true iff exclusive access is obtained
+ * @throws IOException
*/
public final synchronized boolean obtain() throws IOException {
+ boolean obtained;
+ int depth = 0;
if (lockDepth.get() > 0) {
- lockDepth.incrementAndGet();
- return true;
+ depth = lockDepth.incrementAndGet();
+ obtained = true;
+ } else if (obtained = doObtain()) {
+ depth = lockDepth.incrementAndGet();
}
- boolean obtained = doObtain();
+
if (obtained) {
- lockDepth.incrementAndGet();
+ for (LockListener listener : getListeners()) {
+ listener.obtained(this, depth);
+ }
}
return obtained;
}
+
protected abstract boolean doObtain() throws IOException;
@@ -70,18 +95,20 @@
*/
protected Throwable failureReason;
- /** Attempts to obtain an exclusive lock within amount of
- * time given. Polls once per {@link #LOCK_POLL_INTERVAL}
- * (currently 1000) milliseconds until lockWaitTimeout is
- * passed.
+ /**
+ * Attempts to obtain an exclusive lock within amount of
+ * time given. Polls once per {@link #LOCK_POLL_INTERVAL}
+ * (currently 1000) milliseconds until lockWaitTimeout is
+ * passed.
+ *
* @param lockWaitTimeout length of time to wait in
- * milliseconds or {@link
- * #LOCK_OBTAIN_WAIT_FOREVER} to retry forever
+ * milliseconds or {@link
+ * #LOCK_OBTAIN_WAIT_FOREVER} to retry forever
* @return true if lock was obtained
* @throws LockObtainFailedException if lock wait times out
- * @throws IllegalArgumentException if lockWaitTimeout is
- * out of bounds
- * @throws IOException if obtain() throws IOException
+ * @throws IllegalArgumentException if lockWaitTimeout is
+ * out of bounds
+ * @throws IOException if obtain() throws IOException
*/
public boolean obtain(long lockWaitTimeout) throws LockObtainFailedException, IOException {
failureReason = null;
@@ -113,57 +140,77 @@
return locked;
}
- /** Releases exclusive access. */
+ /**
+ * Releases exclusive access.
+ */
public final synchronized void release() throws IOException {
+ int depth = 0;
+ boolean released;
if (lockDepth.get() > 1) {
- lockDepth.decrementAndGet();
- return;
- }
- if (doRelease()) {
- lockDepth.decrementAndGet();
+ depth = lockDepth.decrementAndGet();
+ released = true;
+ } else if (released = doRelease()) {
+ depth = lockDepth.decrementAndGet();
+ }
+ if (released) {
+ for (LockListener listener : getListeners()) {
+ listener.released(this, depth);
+ }
}
+
}
- /** Releases exclusive access. */
+ /**
+ * Releases exclusive access.
+ */
public abstract boolean doRelease() throws IOException;
- /** Returns true if the resource is currently locked. Note that one must
- * still call {@link #obtain()} before using the resource. */
+ /**
+ * Returns true if the resource is currently locked. Note that one must
+ * still call {@link #obtain()} before using the resource.
+ */
public abstract boolean isLocked();
- /** Utility class for executing code with exclusive access. */
+ /**
+ * Utility class for executing code with exclusive access.
+ */
public abstract static class With<T> {
private Lock lock;
- private long lockWaitTimeout;
-
-
- /** Constructs an executor that will grab the named lock. */
+ private long lockWaitTimeout;
+
+ /**
+ * Constructs an executor that will grab the named lock.
+ */
public With(Lock lock, long lockWaitTimeout) {
this.lock = lock;
this.lockWaitTimeout = lockWaitTimeout;
}
- /** Code to execute with exclusive access. */
+ /**
+ * Code to execute with exclusive access.
+ */
public abstract T doBody() throws IOException;
- /** Calls {@link #doBody} while <i>lock</i> is obtained. Blocks if lock
+ /**
+ * Calls {@link #doBody} while <i>lock</i> is obtained. Blocks if lock
* cannot be obtained immediately. Retries to obtain lock once per second
* until it is obtained, or until it has tried ten times. Lock is released when
* {@link #doBody} exits.
+ *
* @throws LockObtainFailedException if lock could not
- * be obtained
- * @throws IOException if {@link Lock#obtain} throws IOException
+ * be obtained
+ * @throws IOException if {@link Lock#obtain} throws IOException
*/
public T run() throws LockObtainFailedException, IOException {
boolean locked = false;
try {
- locked = lock.obtain(lockWaitTimeout);
- return doBody();
+ locked = lock.obtain(lockWaitTimeout);
+ return doBody();
} finally {
if (locked)
- lock.release();
+ lock.release();
}
}
}
Added: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/lock/LockListener.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/lock/LockListener.java?rev=757265&view=auto
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/lock/LockListener.java (added)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/lock/LockListener.java Sun Mar 22 22:12:12 2009
@@ -0,0 +1,18 @@
+package org.apache.labs.bananadb.store.lock;
+
+/**
+ *
+ *
+ * @author kalle
+ * @since 2009-mar-21 03:04:07
+ */
+public interface LockListener {
+
+ public abstract void obtained(Lock lock, int depth);
+ public abstract void released(Lock lock, int depth);
+
+// todo this could be useful?
+// public abstract void obtained(Lock.With lock, int depth);
+// public abstract void released(Lock.With lock, int depth);
+
+}
Added: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/sequence/SequenceManager.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/sequence/SequenceManager.java?rev=757265&view=auto
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/sequence/SequenceManager.java (added)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/sequence/SequenceManager.java Sun Mar 22 22:12:12 2009
@@ -0,0 +1,38 @@
+package org.apache.labs.bananadb.store.sequence;
+
+/**
+ * @author kalle
+ * @since 2009-mar-22 15:03:35
+ */
+public abstract class SequenceManager {
+
+
+ public abstract SequenceManager.Sequence.ReservedSequenceRange reserve(String name, int requestedSize);
+ public abstract void register(Sequence sequence);
+
+ public abstract <T> Sequence<T> sequenceFactory(Class<T> valueType, String name);
+
+ public abstract class Sequence<T> {
+
+ private String name;
+
+ protected Sequence(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public abstract Class<T> getValueType();
+ public abstract ReservedSequenceRange<T> reserve(int requestedSize);
+ protected abstract void release(ReservedSequenceRange<T> reservation);
+
+ public abstract class ReservedSequenceRange<T> {
+ public abstract int size();
+ public abstract T nextValue();
+ public abstract boolean hasNextValue();
+ }
+
+ }
+}
Added: labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/sequence/StaticSequenceManager.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/sequence/StaticSequenceManager.java?rev=757265&view=auto
==============================================================================
--- labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/sequence/StaticSequenceManager.java (added)
+++ labs/bananadb/trunk/src/main/java/org/apache/labs/bananadb/store/sequence/StaticSequenceManager.java Sun Mar 22 22:12:12 2009
@@ -0,0 +1,100 @@
+package org.apache.labs.bananadb.store.sequence;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * For tests only!
+ *
+ * @author kalle
+ * @since 2009-mar-22 15:17:25
+ */
+public class StaticSequenceManager extends SequenceManager {
+
+ private Map<String, Sequence> sequences = new HashMap<String, Sequence>();
+
+ public SequenceManager.Sequence.ReservedSequenceRange reserve(String name, int requestedSize) {
+ return sequences.get(name).reserve(requestedSize);
+ }
+
+ public void register(Sequence sequence) {
+ Sequence old = sequences.get(sequence.getName());
+ if (old != null) {
+ throw new RuntimeException("Already contains a sequence with that name: " + sequence.toString());
+ }
+ sequences.put(sequence.getName(), sequence);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> Sequence<T> sequenceFactory(Class<T> valueType, String name) {
+ if (valueType == Long.class) {
+ return (Sequence<T>) new LongSequence(name);
+ }
+ throw new UnsupportedOperationException("Unregistred value type class " + valueType.getName());
+ }
+
+ public class LongSequence extends SequenceManager.Sequence<Long> {
+
+ protected LongSequence(String name) {
+ super(name);
+ }
+
+ private AtomicLong value = new AtomicLong();
+
+ public Class<Long> getValueType() {
+ return Long.class;
+ }
+
+ public ReservedSequenceRange<Long> reserve(int requestedSize) {
+ long start = value.addAndGet(requestedSize);
+ return new LongRange(start, start + requestedSize);
+ }
+
+ protected void release(ReservedSequenceRange<Long> reservation) {
+ // ignored
+ }
+
+ public class LongRange extends ReservedSequenceRange<Long> {
+
+ private long start;
+ private long end;
+ private long size;
+ private AtomicLong current;
+
+ protected LongRange(long start, long end) {
+ this.start = start;
+ this.end = end;
+ size = end - start;
+ current = new AtomicLong(start);
+ }
+
+ public boolean hasNextValue() {
+ return current.get() < end;
+ }
+
+ public Long nextValue() {
+ if (!hasNextValue()) {
+ throw new NoSuchElementException();
+ }
+ return current.incrementAndGet();
+ }
+
+ public int size() {
+ return (int) size;
+ }
+
+ @Override
+ public String toString() {
+ return "LongRange{" +
+ "start=" + start +
+ ", end=" + end +
+ ", size=" + size +
+ ", current=" + current +
+ '}';
+ }
+ }
+
+ }
+}
Modified: labs/bananadb/trunk/src/site/apt/index.apt
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/site/apt/index.apt?rev=757265&r1=757264&r2=757265&view=diff
==============================================================================
--- labs/bananadb/trunk/src/site/apt/index.apt (original)
+++ labs/bananadb/trunk/src/site/apt/index.apt Sun Mar 22 22:12:12 2009
@@ -89,10 +89,12 @@
Compared to other databases
- Banana DB is very similar to other key/value database implementations.
+ The Banana DB API is very similar to other key/value database implementations.
+
The main reason for the existence of Banana DB
- is the lack of a key value database in Java
- that is distributed under the Apache Software License.
+ is the lack of a key value database implemented in Java
+ with a very simple consumer API
+ distributed under the Apache Software License.
I am not a lawyer. Please double-check any information regarding licensing models mentioned below.
@@ -101,11 +103,14 @@
{{{http://www.oracle.com/database/berkeley-db.html}http://www.oracle.com/database/berkeley-db.html}}
- Berkeley DB and Banana DB is more or less the same thing if you leave out the fact they
- use completly different underlying file formats. Berkeley DB is also ACID compliant
- which Banana DB is not.
+ Berkeley DB is a key/value postings database with ancestry.
+
+ The Banana DB entity store consumer API
+ is very similair to the Berkeley DB Java Edition consumer API.
+
+ Berkeley DB handles huge data dataset on HDD well, Banana DB does not.
- The Banana DB entity store API is almost identical to the Berkeley DB Java Edition API.
+ Berkeley DB is ACID compliant which Banana DB is not.
Berkeley DB has a dual license model.
@@ -123,11 +128,12 @@
{{{http://jdbm.sourceforge.net/}http://jdbm.sourceforge.net/}}
JDBM has similar features as Banana DB
- but a more complex user API compared to Banana DB.
- In addition, it also supports pluggable storage formats,
- including B+Tree and HTree storage.
- JDBM is also ACID compliant
- which Banana DB is not.
+ but a more complex consumer API compared to Banana DB.
+
+ JDBM has a pluggable storage and include support complex data formats such as B+Tree and HTree
+ and thus handles huge data dataset on HDD well, Banana DB does not.
+
+ JDBM is ACID compliant which Banana DB is not.
It is licensed with BSD open source license.
Modified: labs/bananadb/trunk/src/test/java/org/apache/labs/bananadb/store/StoreTest.java
URL: http://svn.apache.org/viewvc/labs/bananadb/trunk/src/test/java/org/apache/labs/bananadb/store/StoreTest.java?rev=757265&r1=757264&r2=757265&view=diff
==============================================================================
--- labs/bananadb/trunk/src/test/java/org/apache/labs/bananadb/store/StoreTest.java (original)
+++ labs/bananadb/trunk/src/test/java/org/apache/labs/bananadb/store/StoreTest.java Sun Mar 22 22:12:12 2009
@@ -21,6 +21,7 @@
import junit.framework.TestCase;
import java.io.File;
+import java.util.Random;
import org.apache.commons.io.FileUtils;
@@ -50,4 +51,29 @@
return path;
}
+ protected byte[][] keys;
+ protected long[] hashes;
+ protected byte[][] values;
+
+
+ protected void randomizeKeyValues(int items) {
+
+ long seed = System.currentTimeMillis();
+ System.err.println("seed = " + seed);
+ Random random = new Random(seed);
+
+
+ keys = new byte[items][];
+ hashes = new long[items];
+ values = new byte[items][];
+
+ for (int i = 0; i < items; i++) {
+ keys[i] = new byte[random.nextInt(10)+1];
+ random.nextBytes(keys[i]);
+ hashes[i] = random.nextLong();
+ values[i] = new byte[random.nextInt(1000)];
+ random.nextBytes(values[i]);
+ }
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org