提交 5631940a authored 作者: Thomas Mueller's avatar Thomas Mueller

MVStore bugfixes

上级 979413fb
...@@ -84,13 +84,14 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -84,13 +84,14 @@ public class MVMap<K, V> extends AbstractMap<K, V>
* *
* @param p the page * @param p the page
* @param writeVersion the write version * @param writeVersion the write version
* @param removeOld whether the old page should be marked as deleted
* @return a page with the given write version * @return a page with the given write version
*/ */
protected Page copyOnWrite(Page p, long writeVersion) { protected Page copyOnWrite(Page p, long writeVersion, boolean removeOld) {
if (p.getVersion() == writeVersion) { if (p.getVersion() == writeVersion) {
return p; return p;
} }
return p.copy(writeVersion); return p.copy(writeVersion, removeOld);
} }
/** /**
...@@ -107,7 +108,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -107,7 +108,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
beforeWrite(); beforeWrite();
try { try {
long v = writeVersion; long v = writeVersion;
Page p = copyOnWrite(root, v); Page p = copyOnWrite(root, v, true);
p = splitRootIfNeeded(p, v); p = splitRootIfNeeded(p, v);
Object result = put(p, v, key, value); Object result = put(p, v, key, value);
newRoot(p); newRoot(p);
...@@ -166,14 +167,14 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -166,14 +167,14 @@ public class MVMap<K, V> extends AbstractMap<K, V>
} else { } else {
index++; index++;
} }
Page c = copyOnWrite(p.getChildPage(index), writeVersion); Page c = copyOnWrite(p.getChildPage(index), writeVersion, true);
if (c.getMemory() > store.getPageSplitSize() && c.getKeyCount() > 1) { if (c.getMemory() > store.getPageSplitSize() && c.getKeyCount() > 1) {
// split on the way down // split on the way down
int at = c.getKeyCount() / 2; int at = c.getKeyCount() / 2;
Object k = c.getKey(at); Object k = c.getKey(at);
Page split = c.split(at); Page split = c.split(at);
p.setChild(index, split); p.setChild(index, split);
p.setCounts(index, c); p.setCounts(index, split);
p.insertNode(index, k, c); p.insertNode(index, k, c);
// now we are not sure where to add // now we are not sure where to add
return put(p, writeVersion, key, value); return put(p, writeVersion, key, value);
...@@ -551,7 +552,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -551,7 +552,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
beforeWrite(); beforeWrite();
try { try {
long v = writeVersion; long v = writeVersion;
Page p = copyOnWrite(root, v); Page p = copyOnWrite(root, v, true);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
V result = (V) remove(p, v, key); V result = (V) remove(p, v, key);
newRoot(p); newRoot(p);
...@@ -670,11 +671,12 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -670,11 +671,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
index++; index++;
} }
Page cOld = p.getChildPage(index); Page cOld = p.getChildPage(index);
Page c = copyOnWrite(cOld, writeVersion); Page c = copyOnWrite(cOld, writeVersion, false);
result = remove(c, writeVersion, key); result = remove(c, writeVersion, key);
if (result == null) { if (result == null) {
return null; return null;
} }
cOld.removePage();
if (c.getTotalCount() == 0) { if (c.getTotalCount() == 0) {
// this child was deleted // this child was deleted
if (p.getKeyCount() == 0) { if (p.getKeyCount() == 0) {
......
...@@ -29,8 +29,8 @@ public class MVMapConcurrent<K, V> extends MVMap<K, V> { ...@@ -29,8 +29,8 @@ public class MVMapConcurrent<K, V> extends MVMap<K, V> {
} }
@Override @Override
protected Page copyOnWrite(Page p, long writeVersion) { protected Page copyOnWrite(Page p, long writeVersion, boolean removeOld) {
return p.copy(writeVersion); return p.copy(writeVersion, removeOld);
} }
@Override @Override
...@@ -48,7 +48,7 @@ public class MVMapConcurrent<K, V> extends MVMap<K, V> { ...@@ -48,7 +48,7 @@ public class MVMapConcurrent<K, V> extends MVMap<K, V> {
get(key); get(key);
long v = writeVersion; long v = writeVersion;
synchronized (this) { synchronized (this) {
Page p = copyOnWrite(root, v); Page p = copyOnWrite(root, v, true);
p = splitRootIfNeeded(p, v); p = splitRootIfNeeded(p, v);
V result = (V) put(p, v, key, value); V result = (V) put(p, v, key, value);
newRoot(p); newRoot(p);
...@@ -75,7 +75,7 @@ public class MVMapConcurrent<K, V> extends MVMap<K, V> { ...@@ -75,7 +75,7 @@ public class MVMapConcurrent<K, V> extends MVMap<K, V> {
} }
long v = writeVersion; long v = writeVersion;
synchronized (this) { synchronized (this) {
Page p = copyOnWrite(root, v); Page p = copyOnWrite(root, v, true);
result = (V) remove(p, v, key); result = (V) remove(p, v, key);
newRoot(p); newRoot(p);
} }
......
...@@ -330,7 +330,10 @@ public class MVStore { ...@@ -330,7 +330,10 @@ public class MVStore {
// setWriteDelay starts the thread, but only if // setWriteDelay starts the thread, but only if
// the parameter is different than the current value // the parameter is different than the current value
setWriteDelay(1000);
o = config.get("writeDelay");
int writeDelay = o == null ? 1000 : (Integer) o;
setWriteDelay(writeDelay);
} }
/** /**
...@@ -2104,6 +2107,20 @@ public class MVStore { ...@@ -2104,6 +2107,20 @@ public class MVStore {
return set("fileStore", store); return set("fileStore", store);
} }
/**
* Set the initial write delay.
*
* @param writeDelay the write delay
* @return this
*/
public Builder writeDelay(int writeDelay) {
// we have a separate config option so that
// no thread is started if the write delay is 0
// (if we only had a setter in the MVStore,
// the thread would need to be started in any case)
return set("writeDelay", writeDelay);
}
/** /**
* Open the store. * Open the store.
* *
......
...@@ -267,10 +267,14 @@ public class Page { ...@@ -267,10 +267,14 @@ public class Page {
* Create a copy of this page. * Create a copy of this page.
* *
* @param version the new version * @param version the new version
* @param removeOld whether the old page should be marked as deleted
* @return a page with the given version * @return a page with the given version
*/ */
public Page copy(long version) { public Page copy(long version, boolean removeOld) {
removePage(); if (removeOld) {
int todoRemoveAtCaller;
removePage();
}
Page newPage = create(map, version, Page newPage = create(map, version,
keyCount, keys, values, children, childrenPages, keyCount, keys, values, children, childrenPages,
counts, totalCount, counts, totalCount,
......
...@@ -169,7 +169,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> { ...@@ -169,7 +169,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
// this will mark the old page as deleted // this will mark the old page as deleted
// so we need to update the parent in any case // so we need to update the parent in any case
// (otherwise the old page might be deleted again) // (otherwise the old page might be deleted again)
Page c = copyOnWrite(cOld, writeVersion); Page c = copyOnWrite(cOld, writeVersion, true);
long oldSize = c.getTotalCount(); long oldSize = c.getTotalCount();
result = remove(c, writeVersion, key); result = remove(c, writeVersion, key);
p.setChild(i, c); p.setChild(i, c);
...@@ -224,7 +224,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> { ...@@ -224,7 +224,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
beforeWrite(); beforeWrite();
try { try {
long v = writeVersion; long v = writeVersion;
Page p = copyOnWrite(root, v); Page p = copyOnWrite(root, v, true);
Object result; Object result;
if (alwaysAdd || get(key) == null) { if (alwaysAdd || get(key) == null) {
if (p.getMemory() > store.getPageSplitSize() && p.getKeyCount() > 1) { if (p.getMemory() > store.getPageSplitSize() && p.getKeyCount() > 1) {
...@@ -268,13 +268,15 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> { ...@@ -268,13 +268,15 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
if (!p.isLeaf()) { if (!p.isLeaf()) {
for (int i = 0; i < p.getKeyCount(); i++) { for (int i = 0; i < p.getKeyCount(); i++) {
if (contains(p, i, key)) { if (contains(p, i, key)) {
Page c = copyOnWrite(p.getChildPage(i), writeVersion); Page c = copyOnWrite(p.getChildPage(i), writeVersion, true);
Object result = set(c, writeVersion, key, value); Object result = set(c, writeVersion, key, value);
if (result != null) { if (result == null) {
p.setChild(i, c); throw DataUtils.newIllegalStateException(
p.setCounts(i, c); DataUtils.ERROR_INTERNAL, "Key did not exist");
return result;
} }
p.setChild(i, c);
p.setCounts(i, c);
return result;
} }
} }
} else { } else {
...@@ -312,11 +314,11 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> { ...@@ -312,11 +314,11 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
} }
} }
} }
Page c = copyOnWrite(p.getChildPage(index), writeVersion); Page c = copyOnWrite(p.getChildPage(index), writeVersion, true);
if (c.getMemory() > store.getPageSplitSize() && c.getKeyCount() > 1) { if (c.getMemory() > store.getPageSplitSize() && c.getKeyCount() > 1) {
// split on the way down // split on the way down
Page split = split(c, writeVersion); Page split = split(c, writeVersion);
p = copyOnWrite(p, writeVersion); p = copyOnWrite(p, writeVersion, true);
p.setKey(index, getBounds(c)); p.setKey(index, getBounds(c));
p.setChild(index, c); p.setChild(index, c);
p.setCounts(index, c); p.setCounts(index, c);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论