提交 35c2d677 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Implement Map in TransactionMap

上级 8f3a8e36
...@@ -950,10 +950,11 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -950,10 +950,11 @@ public class MVMap<K, V> extends AbstractMap<K, V>
} }
/** /**
* Get the number of entries, as a integer. Integer.MAX_VALUE is returned if * Get the number of entries, as a integer. {@link Integer#MAX_VALUE} is
* there are more than this entries. * returned if there are more than this entries.
* *
* @return the number of entries, as an integer * @return the number of entries, as an integer
* @see #sizeAsLong()
*/ */
@Override @Override
public final int size() { public final int size() {
......
...@@ -12,10 +12,12 @@ import org.h2.mvstore.Page; ...@@ -12,10 +12,12 @@ import org.h2.mvstore.Page;
import org.h2.mvstore.type.DataType; import org.h2.mvstore.type.DataType;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.BitSet; import java.util.BitSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set;
/** /**
* A map that supports transactions. * A map that supports transactions.
...@@ -23,7 +25,7 @@ import java.util.NoSuchElementException; ...@@ -23,7 +25,7 @@ import java.util.NoSuchElementException;
* @param <K> the key type * @param <K> the key type
* @param <V> the value type * @param <V> the value type
*/ */
public class TransactionMap<K, V> { public class TransactionMap<K, V> extends AbstractMap<K, V> {
/** /**
* The map used for writing (the latest version). * The map used for writing (the latest version).
...@@ -53,6 +55,19 @@ public class TransactionMap<K, V> { ...@@ -53,6 +55,19 @@ public class TransactionMap<K, V> {
return new TransactionMap<>(transaction, map); return new TransactionMap<>(transaction, map);
} }
/**
* Get the number of entries, as a integer. {@link Integer#MAX_VALUE} is
* returned if there are more than this entries.
*
* @return the number of entries, as an integer
* @see #sizeAsLong()
*/
@Override
public final int size() {
long size = sizeAsLong();
return size > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) size;
}
/** /**
* Get the size of the raw map. This includes uncommitted entries, and * Get the size of the raw map. This includes uncommitted entries, and
* transiently removed entries, so it is the maximum number of entries. * transiently removed entries, so it is the maximum number of entries.
...@@ -178,7 +193,8 @@ public class TransactionMap<K, V> { ...@@ -178,7 +193,8 @@ public class TransactionMap<K, V> {
* @param key the key * @param key the key
* @throws IllegalStateException if a lock timeout occurs * @throws IllegalStateException if a lock timeout occurs
*/ */
public V remove(K key) { @Override
public V remove(Object key) {
return set(key, (V)null); return set(key, (V)null);
} }
...@@ -193,6 +209,7 @@ public class TransactionMap<K, V> { ...@@ -193,6 +209,7 @@ public class TransactionMap<K, V> {
* @return the old value * @return the old value
* @throws IllegalStateException if a lock timeout occurs * @throws IllegalStateException if a lock timeout occurs
*/ */
@Override
public V put(K key, V value) { public V put(K key, V value) {
DataUtils.checkArgument(value != null, "The value may not be null"); DataUtils.checkArgument(value != null, "The value may not be null");
return set(key, value); return set(key, value);
...@@ -207,6 +224,7 @@ public class TransactionMap<K, V> { ...@@ -207,6 +224,7 @@ public class TransactionMap<K, V> {
* @param value the new value (not null) * @param value the new value (not null)
* @return the old value * @return the old value
*/ */
// Do not add @Override, code should be compatible with Java 7
public V putIfAbsent(K key, V value) { public V putIfAbsent(K key, V value) {
DataUtils.checkArgument(value != null, "The value may not be null"); DataUtils.checkArgument(value != null, "The value may not be null");
TxDecisionMaker decisionMaker = new TxDecisionMaker.PutIfAbsentDecisionMaker(map.getId(), key, value, TxDecisionMaker decisionMaker = new TxDecisionMaker.PutIfAbsentDecisionMaker(map.getId(), key, value,
...@@ -245,12 +263,12 @@ public class TransactionMap<K, V> { ...@@ -245,12 +263,12 @@ public class TransactionMap<K, V> {
return result; return result;
} }
private V set(K key, V value) { private V set(Object key, V value) {
TxDecisionMaker decisionMaker = new TxDecisionMaker.PutDecisionMaker(map.getId(), key, value, transaction); TxDecisionMaker decisionMaker = new TxDecisionMaker.PutDecisionMaker(map.getId(), key, value, transaction);
return set(key, decisionMaker); return set(key, decisionMaker);
} }
private V set(K key, TxDecisionMaker decisionMaker) { private V set(Object key, TxDecisionMaker decisionMaker) {
TransactionStore store = transaction.store; TransactionStore store = transaction.store;
Transaction blockingTransaction; Transaction blockingTransaction;
long sequenceNumWhenStarted; long sequenceNumWhenStarted;
...@@ -262,7 +280,9 @@ public class TransactionMap<K, V> { ...@@ -262,7 +280,9 @@ public class TransactionMap<K, V> {
// since TxDecisionMaker has it embedded, // since TxDecisionMaker has it embedded,
// MVRTreeMap has weird traversal logic based on it, // MVRTreeMap has weird traversal logic based on it,
// and any non-null value will do // and any non-null value will do
result = map.put(key, VersionedValue.DUMMY, decisionMaker); @SuppressWarnings("unchecked")
K k = (K) key;
result = map.put(k, VersionedValue.DUMMY, decisionMaker);
MVMap.Decision decision = decisionMaker.getDecision(); MVMap.Decision decision = decisionMaker.getDecision();
assert decision != null; assert decision != null;
...@@ -343,8 +363,9 @@ public class TransactionMap<K, V> { ...@@ -343,8 +363,9 @@ public class TransactionMap<K, V> {
* @param key the key * @param key the key
* @return the value or null * @return the value or null
*/ */
@Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public V get(K key) { public V get(Object key) {
VersionedValue data = map.get(key); VersionedValue data = map.get(key);
if (data == null) { if (data == null) {
// doesn't exist or deleted by a committed transaction // doesn't exist or deleted by a committed transaction
...@@ -370,7 +391,8 @@ public class TransactionMap<K, V> { ...@@ -370,7 +391,8 @@ public class TransactionMap<K, V> {
* @param key the key * @param key the key
* @return true if the map contains an entry for this key * @return true if the map contains an entry for this key
*/ */
public boolean containsKey(K key) { @Override
public boolean containsKey(Object key) {
return get(key) != null; return get(key) != null;
} }
...@@ -403,11 +425,34 @@ public class TransactionMap<K, V> { ...@@ -403,11 +425,34 @@ public class TransactionMap<K, V> {
/** /**
* Clear the map. * Clear the map.
*/ */
@Override
public void clear() { public void clear() {
// TODO truncate transactionally? // TODO truncate transactionally?
map.clear(); map.clear();
} }
@Override
public Set<Entry<K, V>> entrySet() {
return new AbstractSet<Entry<K, V>>() {
@Override
public Iterator<Entry<K, V>> iterator() {
return entryIterator(null, null);
}
@Override
public int size() {
return TransactionMap.this.size();
}
@Override
public boolean contains(Object o) {
return TransactionMap.this.containsKey(o);
}
};
}
/** /**
* Get the first key. * Get the first key.
* *
...@@ -693,4 +738,5 @@ public class TransactionMap<K, V> { ...@@ -693,4 +738,5 @@ public class TransactionMap<K, V> {
"Removal is not supported"); "Removal is not supported");
} }
} }
} }
...@@ -13,6 +13,7 @@ import java.sql.Statement; ...@@ -13,6 +13,7 @@ import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map.Entry;
import java.util.Random; import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
...@@ -235,6 +236,7 @@ public class TestTransactionStore extends TestBase { ...@@ -235,6 +236,7 @@ public class TestTransactionStore extends TestBase {
Random r = new Random(1); Random r = new Random(1);
for (int i = 0; i < size * 3; i++) { for (int i = 0; i < size * 3; i++) {
assertEquals("op: " + i, size, map1.size());
assertEquals("op: " + i, size, (int) map1.sizeAsLong()); assertEquals("op: " + i, size, (int) map1.sizeAsLong());
// keep the first 10%, and add 10% // keep the first 10%, and add 10%
int k = size / 10 + r.nextInt(size); int k = size / 10 + r.nextInt(size);
...@@ -507,6 +509,7 @@ public class TestTransactionStore extends TestBase { ...@@ -507,6 +509,7 @@ public class TestTransactionStore extends TestBase {
Transaction tx, tx2; Transaction tx, tx2;
TransactionMap<String, String> m, m2; TransactionMap<String, String> m, m2;
Iterator<String> it, it2; Iterator<String> it, it2;
Iterator<Entry<String, String>> entryIt;
tx = ts.begin(); tx = ts.begin();
m = tx.openMap("test"); m = tx.openMap("test");
...@@ -532,6 +535,15 @@ public class TestTransactionStore extends TestBase { ...@@ -532,6 +535,15 @@ public class TestTransactionStore extends TestBase {
assertEquals("3", it.next()); assertEquals("3", it.next());
assertFalse(it.hasNext()); assertFalse(it.hasNext());
entryIt = m.entrySet().iterator();
assertTrue(entryIt.hasNext());
assertEquals("1", entryIt.next().getKey());
assertTrue(entryIt.hasNext());
assertEquals("2", entryIt.next().getKey());
assertTrue(entryIt.hasNext());
assertEquals("3", entryIt.next().getKey());
assertFalse(entryIt.hasNext());
it2 = m2.keyIterator(null); it2 = m2.keyIterator(null);
assertTrue(it2.hasNext()); assertTrue(it2.hasNext());
assertEquals("1", it2.next()); assertEquals("1", it2.next());
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论