提交 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; ...@@ -103,6 +103,7 @@ import org.h2.test.server.TestAutoServer;
import org.h2.test.server.TestNestedLoop; import org.h2.test.server.TestNestedLoop;
import org.h2.test.server.TestWeb; import org.h2.test.server.TestWeb;
import org.h2.test.server.TestInit; import org.h2.test.server.TestInit;
import org.h2.test.store.TestCacheConcurrentLIRS;
import org.h2.test.store.TestCacheLIRS; import org.h2.test.store.TestCacheLIRS;
import org.h2.test.store.TestCacheLongKeyLIRS; import org.h2.test.store.TestCacheLongKeyLIRS;
import org.h2.test.store.TestConcurrent; import org.h2.test.store.TestConcurrent;
...@@ -668,6 +669,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -668,6 +669,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
private void testUnit() { private void testUnit() {
// mv store // mv store
new TestCacheConcurrentLIRS().runTest(this);
new TestCacheLIRS().runTest(this); new TestCacheLIRS().runTest(this);
new TestCacheLongKeyLIRS().runTest(this); new TestCacheLongKeyLIRS().runTest(this);
new TestConcurrent().runTest(this); new TestConcurrent().runTest(this);
......
...@@ -268,7 +268,8 @@ public class CalculateHashConstant implements Runnable { ...@@ -268,7 +268,8 @@ public class CalculateHashConstant implements Runnable {
private void addCandidates(int currentHigh) { private void addCandidates(int currentHigh) {
for (int low = 0; low <= 0xffff; low++) { 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)) { if (!primeNumbers.get(low)) {
continue; continue;
} }
......
...@@ -412,8 +412,7 @@ public class MVRTreeMap<K, V> extends MVMap<K, V> { ...@@ -412,8 +412,7 @@ public class MVRTreeMap<K, V> extends MVMap<K, V> {
return null; return null;
} }
while (true) { while (true) {
CursorPos c = new CursorPos(); CursorPos c = new CursorPos(p, 0, null);
c.page = p;
if (p.isLeaf()) { if (p.isLeaf()) {
return c; return c;
} }
......
...@@ -30,7 +30,7 @@ public class TestCacheConcurrentLIRS extends TestBase { ...@@ -30,7 +30,7 @@ public class TestCacheConcurrentLIRS extends TestBase {
testConcurrent(); testConcurrent();
} }
private static void testConcurrent() { private void testConcurrent() {
final CacheLongKeyLIRS<Integer> test = CacheLongKeyLIRS.newInstance(100); final CacheLongKeyLIRS<Integer> test = CacheLongKeyLIRS.newInstance(100);
int threadCount = 8; int threadCount = 8;
final CountDownLatch wait = new CountDownLatch(1); final CountDownLatch wait = new CountDownLatch(1);
...@@ -85,7 +85,7 @@ public class TestCacheConcurrentLIRS extends TestBase { ...@@ -85,7 +85,7 @@ public class TestCacheConcurrentLIRS extends TestBase {
for (int x : getCounts) { for (int x : getCounts) {
totalCount += x; totalCount += x;
} }
System.out.println("requests: " + totalCount); trace("requests: " + totalCount);
} }
} }
...@@ -24,18 +24,13 @@ public class ChangeCursor<K, V> extends Cursor<K, V> { ...@@ -24,18 +24,13 @@ public class ChangeCursor<K, V> extends Cursor<K, V> {
public CursorPos min(Page p, K from) { public CursorPos min(Page p, K from) {
while (p != null && p.getVersion() >= minVersion) { while (p != null && p.getVersion() >= minVersion) {
if (p.isLeaf()) { if (p.isLeaf()) {
CursorPos c = new CursorPos(); return new CursorPos(p, 0, null);
c.page = p;
c.index = 0;
return c;
} }
for (int i = 0; i < p.getChildPageCount(); i++) { for (int i = 0; i < p.getChildPageCount(); i++) {
if (isChildOld(p, i)) { if (isChildOld(p, i)) {
continue; continue;
} }
CursorPos c = new CursorPos(); CursorPos c = new CursorPos(p, i, null);
c.page = p;
c.index = i;
push(c); push(c);
p = p.getChildPage(i); p = p.getChildPage(i);
break; break;
......
...@@ -21,5 +21,16 @@ public class CursorPos { ...@@ -21,5 +21,16 @@ public class CursorPos {
*/ */
public int index; 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> { ...@@ -152,10 +152,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> {
if (x < 0) { if (x < 0) {
x = -x - 1; x = -x - 1;
} }
CursorPos c = new CursorPos(); return new CursorPos(p, x, null);
c.page = p;
c.index = x;
return c;
} }
int x = key == null ? -1 : p.binarySearch(key); int x = key == null ? -1 : p.binarySearch(key);
if (x < 0) { if (x < 0) {
...@@ -163,9 +160,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> { ...@@ -163,9 +160,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> {
} else { } else {
x++; x++;
} }
CursorPos c = new CursorPos(); CursorPos c = new CursorPos(p, x, null);
c.page = p;
c.index = x;
cursor.push(c); cursor.push(c);
p = p.getChildPage(x); p = p.getChildPage(x);
} }
...@@ -448,7 +443,8 @@ public class MVMap<K, V> extends AbstractMap<K, V> { ...@@ -448,7 +443,8 @@ public class MVMap<K, V> extends AbstractMap<K, V> {
*/ */
public Iterator<K> keyIterator(K from) { public Iterator<K> keyIterator(K from) {
checkOpen(); 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> { ...@@ -478,7 +474,8 @@ public class MVMap<K, V> extends AbstractMap<K, V> {
@Override @Override
public Iterator<K> iterator() { 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 @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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论