提交 71dc1bef authored 作者: Thomas Mueller's avatar Thomas Mueller

A persistent multi-version map: simplified cursor (WIP)

上级 89225438
......@@ -103,6 +103,7 @@ import org.h2.test.server.TestAutoServer;
import org.h2.test.server.TestNestedLoop;
import org.h2.test.server.TestWeb;
import org.h2.test.server.TestInit;
import org.h2.test.store.TestCacheConcurrentLIRS;
import org.h2.test.store.TestCacheLIRS;
import org.h2.test.store.TestCacheLongKeyLIRS;
import org.h2.test.store.TestConcurrent;
......@@ -668,6 +669,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
private void testUnit() {
// mv store
new TestCacheConcurrentLIRS().runTest(this);
new TestCacheLIRS().runTest(this);
new TestCacheLongKeyLIRS().runTest(this);
new TestConcurrent().runTest(this);
......
......@@ -268,7 +268,8 @@ public class CalculateHashConstant implements Runnable {
private void addCandidates(int currentHigh) {
for (int low = 0; low <= 0xffff; low++) {
// the lower 16 bits have to be a prime number
// the lower 16 bits don't have to be a prime number
// but it seems that's a good restriction
if (!primeNumbers.get(low)) {
continue;
}
......
......@@ -412,8 +412,7 @@ public class MVRTreeMap<K, V> extends MVMap<K, V> {
return null;
}
while (true) {
CursorPos c = new CursorPos();
c.page = p;
CursorPos c = new CursorPos(p, 0, null);
if (p.isLeaf()) {
return c;
}
......
......@@ -30,7 +30,7 @@ public class TestCacheConcurrentLIRS extends TestBase {
testConcurrent();
}
private static void testConcurrent() {
private void testConcurrent() {
final CacheLongKeyLIRS<Integer> test = CacheLongKeyLIRS.newInstance(100);
int threadCount = 8;
final CountDownLatch wait = new CountDownLatch(1);
......@@ -85,7 +85,7 @@ public class TestCacheConcurrentLIRS extends TestBase {
for (int x : getCounts) {
totalCount += x;
}
System.out.println("requests: " + totalCount);
trace("requests: " + totalCount);
}
}
......@@ -24,18 +24,13 @@ public class ChangeCursor<K, V> extends Cursor<K, V> {
public CursorPos min(Page p, K from) {
while (p != null && p.getVersion() >= minVersion) {
if (p.isLeaf()) {
CursorPos c = new CursorPos();
c.page = p;
c.index = 0;
return c;
return new CursorPos(p, 0, null);
}
for (int i = 0; i < p.getChildPageCount(); i++) {
if (isChildOld(p, i)) {
continue;
}
CursorPos c = new CursorPos();
c.page = p;
c.index = i;
CursorPos c = new CursorPos(p, i, null);
push(c);
p = p.getChildPage(i);
break;
......
......@@ -21,5 +21,16 @@ public class CursorPos {
*/
public int index;
/**
* The position in the parent page, if any.
*/
public CursorPos parent;
public CursorPos(Page page, int index, CursorPos parent) {
this.page = page;
this.index = index;
this.parent = parent;
}
}
......@@ -152,10 +152,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> {
if (x < 0) {
x = -x - 1;
}
CursorPos c = new CursorPos();
c.page = p;
c.index = x;
return c;
return new CursorPos(p, x, null);
}
int x = key == null ? -1 : p.binarySearch(key);
if (x < 0) {
......@@ -163,9 +160,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> {
} else {
x++;
}
CursorPos c = new CursorPos();
c.page = p;
c.index = x;
CursorPos c = new CursorPos(p, x, null);
cursor.push(c);
p = p.getChildPage(x);
}
......@@ -448,7 +443,8 @@ public class MVMap<K, V> extends AbstractMap<K, V> {
*/
public Iterator<K> keyIterator(K from) {
checkOpen();
return new Cursor<K, V>(this, root, from);
return new RangeCursor<K, V>(root, from);
// return new Cursor<K, V>(this, root, from);
}
/**
......@@ -478,7 +474,8 @@ public class MVMap<K, V> extends AbstractMap<K, V> {
@Override
public Iterator<K> iterator() {
return new Cursor<K, V>(MVMap.this, root, null);
return new RangeCursor<K, V>(root, null);
// return new Cursor<K, V>(MVMap.this, root, null);
}
@Override
......
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.dev.store.btree;
import java.util.Iterator;
/**
* A cursor to iterate over elements in ascending order.
*
* @param <K> the key type
* @param <V> the value type
*/
public class RangeCursor<K, V> implements Iterator<K> {
protected final K from;
protected Page root;
protected CursorPos pos;
protected K current;
RangeCursor(Page root, K from) {
this.root = root;
this.from = from;
}
public K next() {
K c = current;
fetchNext();
return c;
}
public boolean hasNext() {
if (root != null) {
// initialize
min(root, from);
root = null;
fetchNext();
}
return current != null;
}
public void remove() {
throw new UnsupportedOperationException();
}
private void min(Page p, K from) {
while (true) {
if (p.isLeaf()) {
int x = from == null ? 0 : p.binarySearch(from);
if (x < 0) {
x = -x - 1;
}
pos = new CursorPos(p, x, pos);
break;
}
int x = from == null ? -1 : p.binarySearch(from);
if (x < 0) {
x = -x - 1;
} else {
x++;
}
pos = new CursorPos(p, x + 1, pos);
p = p.getChildPage(x);
}
}
@SuppressWarnings("unchecked")
private void fetchNext() {
while (pos != null) {
if (pos.index < pos.page.getKeyCount()) {
current = (K) pos.page.getKey(pos.index++);
return;
}
pos = pos.parent;
if (pos == null) {
break;
}
if (pos.index < pos.page.getChildPageCount()) {
min(pos.page.getChildPage(pos.index++), null);
}
}
current = null;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论