提交 7b346b46 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Add ceilingKey() and floorKey() with tests

上级 56a3ab02
...@@ -1345,6 +1345,22 @@ public class TransactionStore { ...@@ -1345,6 +1345,22 @@ public class TransactionStore {
return key; return key;
} }
/**
* Get the smallest key that is larger than or equal to this key,
* or null if no such key exists.
*
* @param key the key (may not be null)
* @return the result
*/
public K ceilingKey(K key) {
key = map.ceilingKey(key);
while (key != null && get(key) == null) {
// Use higherKey() for the next attempts, otherwise we'll get an infinite loop
key = higherKey(key);
}
return key;
}
/** /**
* Get one of the previous or next keys. There might be no value * Get one of the previous or next keys. There might be no value
* available for the returned key. * available for the returned key.
...@@ -1362,6 +1378,22 @@ public class TransactionStore { ...@@ -1362,6 +1378,22 @@ public class TransactionStore {
return map.getKey(index + offset); return map.getKey(index + offset);
} }
/**
* Get the largest key that is smaller than or equal to this key,
* or null if no such key exists.
*
* @param key the key (may not be null)
* @return the result
*/
public K floorKey(K key) {
key = map.floorKey(key);
while (key != null && get(key) == null) {
// Use lowerKey() for the next attempts, otherwise we'll get an infinite loop
key = lowerKey(key);
}
return key;
}
/** /**
* Get the largest key that is smaller than the given key, or null if no * Get the largest key that is smaller than the given key, or null if no
* such key exists. * such key exists.
......
...@@ -19,9 +19,11 @@ import org.h2.mvstore.DataUtils; ...@@ -19,9 +19,11 @@ import org.h2.mvstore.DataUtils;
import org.h2.mvstore.MVMap; import org.h2.mvstore.MVMap;
import org.h2.mvstore.MVStore; import org.h2.mvstore.MVStore;
import org.h2.mvstore.db.TransactionStore; import org.h2.mvstore.db.TransactionStore;
import org.h2.mvstore.db.ValueDataType;
import org.h2.mvstore.db.TransactionStore.Change; import org.h2.mvstore.db.TransactionStore.Change;
import org.h2.mvstore.db.TransactionStore.Transaction; import org.h2.mvstore.db.TransactionStore.Transaction;
import org.h2.mvstore.db.TransactionStore.TransactionMap; import org.h2.mvstore.db.TransactionStore.TransactionMap;
import org.h2.mvstore.type.ObjectDataType;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.New; import org.h2.util.New;
...@@ -44,6 +46,7 @@ public class TestTransactionStore extends TestBase { ...@@ -44,6 +46,7 @@ public class TestTransactionStore extends TestBase {
@Override @Override
public void test() throws Exception { public void test() throws Exception {
FileUtils.createDirectories(getBaseDir()); FileUtils.createDirectories(getBaseDir());
testHCLFKey();
testConcurrentAddRemove(); testConcurrentAddRemove();
testConcurrentAdd(); testConcurrentAdd();
testCountWithOpenTransactions(); testCountWithOpenTransactions();
...@@ -62,6 +65,48 @@ public class TestTransactionStore extends TestBase { ...@@ -62,6 +65,48 @@ public class TestTransactionStore extends TestBase {
testStoreMultiThreadedReads(); testStoreMultiThreadedReads();
} }
private void testHCLFKey() {
MVStore s = MVStore.open(null);
final TransactionStore ts = new TransactionStore(s);
ts.init();
Transaction t = ts.begin();
ObjectDataType keyType = new ObjectDataType();
TransactionMap<Long, Long> map = t.openMap("test", keyType, keyType);
map.put(10L, 100L);
map.put(20L, 200L);
map.put(30L, 300L);
map.put(40L, 400L);
t.commit();
t = ts.begin();
map = t.openMap("test", keyType, keyType);
map.put(15L, 150L);
// The same transaction
assertEquals((Object) 15L, map.higherKey(10L));
t = ts.begin();
map = t.openMap("test", keyType, keyType);
// Another transaction
// higherKey()
assertEquals((Object) 20L, map.higherKey(10L));
assertEquals((Object) 20L, map.higherKey(15L));
assertNull(map.higherKey(40L));
// ceilingKey()
assertEquals((Object) 10L, map.ceilingKey(10L));
assertEquals((Object) 20L, map.ceilingKey(15L));
assertEquals((Object) 40L, map.ceilingKey(40L));
assertNull(map.higherKey(45L));
// lowerKey()
assertNull(map.lowerKey(10L));
assertEquals((Object) 10L, map.lowerKey(15L));
assertEquals((Object) 10L, map.lowerKey(20L));
assertEquals((Object) 20L, map.lowerKey(25L));
// floorKey()
assertNull(map.floorKey(5L));
assertEquals((Object) 10L, map.floorKey(10L));
assertEquals((Object) 10L, map.floorKey(15L));
assertEquals((Object) 30L, map.floorKey(35L));
s.close();
}
private static void testConcurrentAddRemove() throws InterruptedException { private static void testConcurrentAddRemove() throws InterruptedException {
MVStore s = MVStore.open(null); MVStore s = MVStore.open(null);
int threadCount = 3; int threadCount = 3;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论