use of org.h2.store.Page in project h2database by h2database.
the class MVRTreeMap method splitQuadratic.
private Page splitQuadratic(Page p, long writeVersion) {
Page splitA = newPage(p.isLeaf(), writeVersion);
Page splitB = newPage(p.isLeaf(), writeVersion);
float largest = Float.MIN_VALUE;
int ia = 0, ib = 0;
for (int a = 0; a < p.getKeyCount(); a++) {
Object objA = p.getKey(a);
for (int b = 0; b < p.getKeyCount(); b++) {
if (a == b) {
continue;
}
Object objB = p.getKey(b);
float area = keyType.getCombinedArea(objA, objB);
if (area > largest) {
largest = area;
ia = a;
ib = b;
}
}
}
move(p, splitA, ia);
if (ia < ib) {
ib--;
}
move(p, splitB, ib);
Object boundsA = keyType.createBoundingBox(splitA.getKey(0));
Object boundsB = keyType.createBoundingBox(splitB.getKey(0));
while (p.getKeyCount() > 0) {
float diff = 0, bestA = 0, bestB = 0;
int best = 0;
for (int i = 0; i < p.getKeyCount(); i++) {
Object o = p.getKey(i);
float incA = keyType.getAreaIncrease(boundsA, o);
float incB = keyType.getAreaIncrease(boundsB, o);
float d = Math.abs(incA - incB);
if (d > diff) {
diff = d;
bestA = incA;
bestB = incB;
best = i;
}
}
if (bestA < bestB) {
keyType.increaseBounds(boundsA, p.getKey(best));
move(p, splitA, best);
} else {
keyType.increaseBounds(boundsB, p.getKey(best));
move(p, splitB, best);
}
}
while (splitB.getKeyCount() > 0) {
move(splitB, p, 0);
}
return splitA;
}
use of org.h2.store.Page in project h2database by h2database.
the class MVRTreeMap method splitLinear.
private Page splitLinear(Page p, long writeVersion) {
ArrayList<Object> keys = New.arrayList();
for (int i = 0; i < p.getKeyCount(); i++) {
keys.add(p.getKey(i));
}
int[] extremes = keyType.getExtremes(keys);
if (extremes == null) {
return splitQuadratic(p, writeVersion);
}
Page splitA = newPage(p.isLeaf(), writeVersion);
Page splitB = newPage(p.isLeaf(), writeVersion);
move(p, splitA, extremes[0]);
if (extremes[1] > extremes[0]) {
extremes[1]--;
}
move(p, splitB, extremes[1]);
Object boundsA = keyType.createBoundingBox(splitA.getKey(0));
Object boundsB = keyType.createBoundingBox(splitB.getKey(0));
while (p.getKeyCount() > 0) {
Object o = p.getKey(0);
float a = keyType.getAreaIncrease(boundsA, o);
float b = keyType.getAreaIncrease(boundsB, o);
if (a < b) {
keyType.increaseBounds(boundsA, o);
move(p, splitA, 0);
} else {
keyType.increaseBounds(boundsB, o);
move(p, splitB, 0);
}
}
while (splitB.getKeyCount() > 0) {
move(splitB, p, 0);
}
return splitA;
}
use of org.h2.store.Page in project h2database by h2database.
the class MVRTreeMap method move.
private static void move(Page source, Page target, int sourceIndex) {
Object k = source.getKey(sourceIndex);
if (source.isLeaf()) {
Object v = source.getValue(sourceIndex);
target.insertLeaf(0, k, v);
} else {
Page c = source.getChildPage(sourceIndex);
target.insertNode(0, k, c);
}
source.remove(sourceIndex);
}
use of org.h2.store.Page in project h2database by h2database.
the class MVRTreeMap method add.
private void add(Page p, long writeVersion, Object key, Object value) {
if (p.isLeaf()) {
p.insertLeaf(p.getKeyCount(), key, value);
return;
}
// p is a node
int index = -1;
for (int i = 0; i < p.getKeyCount(); i++) {
if (contains(p, i, key)) {
index = i;
break;
}
}
if (index < 0) {
// a new entry, we don't know where to add yet
float min = Float.MAX_VALUE;
for (int i = 0; i < p.getKeyCount(); i++) {
Object k = p.getKey(i);
float areaIncrease = keyType.getAreaIncrease(k, key);
if (areaIncrease < min) {
index = i;
min = areaIncrease;
}
}
}
Page c = p.getChildPage(index).copy(writeVersion);
if (c.getMemory() > store.getPageSplitSize() && c.getKeyCount() > 4) {
// split on the way down
Page split = split(c, writeVersion);
p.setKey(index, getBounds(c));
p.setChild(index, c);
p.insertNode(index, getBounds(split), split);
// now we are not sure where to add
add(p, writeVersion, key, value);
return;
}
add(c, writeVersion, key, value);
Object bounds = p.getKey(index);
keyType.increaseBounds(bounds, key);
p.setKey(index, bounds);
p.setChild(index, c);
}
use of org.h2.store.Page in project h2database by h2database.
the class MVRTreeMap method set.
/**
* Update the value for the given key. The key must exist.
*
* @param p the page
* @param writeVersion the write version
* @param key the key
* @param value the new value
* @return the old value (never null)
*/
private Object set(Page p, long writeVersion, Object key, Object value) {
if (p.isLeaf()) {
for (int i = 0; i < p.getKeyCount(); i++) {
if (keyType.equals(p.getKey(i), key)) {
p.setKey(i, key);
return p.setValue(i, value);
}
}
} else {
for (int i = 0; i < p.getKeyCount(); i++) {
if (contains(p, i, key)) {
Page c = p.getChildPage(i);
if (get(c, key) != null) {
c = c.copy(writeVersion);
Object result = set(c, writeVersion, key, value);
p.setChild(i, c);
return result;
}
}
}
}
throw DataUtils.newIllegalStateException(DataUtils.ERROR_INTERNAL, "Not found: {0}", key);
}
Aggregations