Unverified 提交 a00b17bd authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1318 from h2database/mode-append

Mode append fo MVPlainTempResult
...@@ -779,6 +779,12 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -779,6 +779,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
} }
public final RootReference getRoot() { public final RootReference getRoot() {
RootReference rootReference = getRootInternal();
return singleWriter && rootReference.getAppendCounter() > 0 ?
flushAppendBuffer(rootReference) : rootReference;
}
private RootReference getRootInternal() {
return root.get(); return root.get();
} }
...@@ -1112,7 +1118,6 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1112,7 +1118,6 @@ public class MVMap<K, V> extends AbstractMap<K, V>
} }
return rootReference; return rootReference;
} }
rootReference = flushAppendBuffer(rootReference);
RootReference updatedRootReference = new RootReference(rootReference, writeVersion, ++attempt); RootReference updatedRootReference = new RootReference(rootReference, writeVersion, ++attempt);
if(root.compareAndSet(rootReference, updatedRootReference)) { if(root.compareAndSet(rootReference, updatedRootReference)) {
removeUnusedOldVersions(updatedRootReference); removeUnusedOldVersions(updatedRootReference);
...@@ -1173,99 +1178,83 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1173,99 +1178,83 @@ public class MVMap<K, V> extends AbstractMap<K, V>
/** /**
* If map was used in append mode, this method will ensure that append buffer * If map was used in append mode, this method will ensure that append buffer
* is flushed - emptied with all entries inserted into map as a new leaf. * is flushed - emptied with all entries inserted into map as a new leaf.
* @param rootReference current RootReference
* @return potentially updated RootReference * @return potentially updated RootReference
*/ */
public RootReference flushAppendBuffer() {
return flushAppendBuffer(null);
}
private RootReference flushAppendBuffer(RootReference rootReference) { private RootReference flushAppendBuffer(RootReference rootReference) {
beforeWrite();
int attempt = 0; int attempt = 0;
while(true) { int keyCount;
if (rootReference == null) { while((keyCount = rootReference.getAppendCounter()) > 0) {
rootReference = getRoot();
}
int keyCount = rootReference.getAppendCounter();
if (keyCount == 0) {
break;
}
Page page = Page.create(this, Page page = Page.create(this,
Arrays.copyOf(keysBuffer, keyCount), Arrays.copyOf(keysBuffer, keyCount),
Arrays.copyOf(valuesBuffer, keyCount), Arrays.copyOf(valuesBuffer, keyCount),
null, keyCount, 0); null, keyCount, 0);
rootReference = appendLeafPage(rootReference, page, ++attempt); CursorPos pos = rootReference.root.getAppendCursorPos(null);
if (rootReference != null) { assert page.map == this;
break; assert pos != null;
} assert page.getKeyCount() > 0;
} Object key = page.getKey(0);
assert rootReference.getAppendCounter() == 0; assert pos.index < 0 : pos.index;
return rootReference; int index = -pos.index - 1;
} assert index == pos.page.getKeyCount() : index + " != " + pos.page.getKeyCount();
Page p = pos.page;
private RootReference appendLeafPage(RootReference rootReference, Page split, int attempt) {
CursorPos pos = rootReference.root.getAppendCursorPos(null);
assert split.map == this;
assert pos != null;
assert split.getKeyCount() > 0;
Object key = split.getKey(0);
assert pos.index < 0 : pos.index;
int index = -pos.index - 1;
assert index == pos.page.getKeyCount() : index + " != " + pos.page.getKeyCount();
Page p = pos.page;
pos = pos.parent;
CursorPos tip = pos;
int unsavedMemory = 0;
while (true) {
if (pos == null) {
if (p.getKeyCount() == 0) {
p = split;
} else {
Object keys[] = new Object[] { key };
Page.PageReference children[] = new Page.PageReference[] {
new Page.PageReference(p),
new Page.PageReference(split)};
p = Page.create(this, keys, null, children, p.getTotalCount() + split.getTotalCount(), 0);
}
break;
}
Page c = p;
p = pos.page;
index = pos.index;
pos = pos.parent; pos = pos.parent;
p = p.copy(); CursorPos tip = pos;
p.setChild(index, split); int unsavedMemory = page.getMemory();
p.insertNode(index, key, c); while (true) {
int keyCount; if (pos == null) {
if ((keyCount = p.getKeyCount()) <= store.getKeysPerPage() && if (p.getKeyCount() == 0) {
(p.getMemory() < store.getMaxPageSize() || keyCount <= (p.isLeaf() ? 1 : 2))) { p = page;
break; } else {
Object keys[] = new Object[] { key };
Page.PageReference children[] = new Page.PageReference[] {
new Page.PageReference(p),
new Page.PageReference(page)};
p = Page.create(this, keys, null, children, p.getTotalCount() + page.getTotalCount(), 0);
}
break;
}
Page c = p;
p = pos.page;
index = pos.index;
pos = pos.parent;
p = p.copy();
p.setChild(index, page);
p.insertNode(index, key, c);
if ((keyCount = p.getKeyCount()) <= store.getKeysPerPage() &&
(p.getMemory() < store.getMaxPageSize() || keyCount <= (p.isLeaf() ? 1 : 2))) {
break;
}
int at = keyCount - 2;
key = p.getKey(at);
page = p.split(at);
unsavedMemory += p.getMemory() + page.getMemory();
} }
int at = keyCount - 2;
key = p.getKey(at);
split = p.split(at);
unsavedMemory += p.getMemory() + split.getMemory();
}
unsavedMemory += p.getMemory();
while (pos != null) {
Page c = p;
p = pos.page;
p = p.copy();
p.setChild(pos.index, c);
unsavedMemory += p.getMemory(); unsavedMemory += p.getMemory();
pos = pos.parent; while (pos != null) {
} Page c = p;
RootReference updatedRootReference = new RootReference(rootReference, p, ++attempt); p = pos.page;
if(root.compareAndSet(rootReference, updatedRootReference)) { p = p.copy();
while (tip != null) { p.setChild(pos.index, c);
tip.page.removePage(); unsavedMemory += p.getMemory();
tip = tip.parent; pos = pos.parent;
} }
if (store.getFileStore() != null) { RootReference updatedRootReference = new RootReference(rootReference, p, ++attempt);
store.registerUnsavedPage(unsavedMemory); if(root.compareAndSet(rootReference, updatedRootReference)) {
while (tip != null) {
tip.page.removePage();
tip = tip.parent;
}
if (store.getFileStore() != null) {
store.registerUnsavedPage(unsavedMemory);
}
assert updatedRootReference.getAppendCounter() == 0;
return updatedRootReference;
} }
return updatedRootReference; rootReference = getRootInternal();
} }
return null; return rootReference;
} }
/** /**
...@@ -1280,7 +1269,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1280,7 +1269,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
int attempt = 0; int attempt = 0;
boolean success = false; boolean success = false;
while(!success) { while(!success) {
RootReference rootReference = getRoot(); RootReference rootReference = getRootInternal();
int appendCounter = rootReference.getAppendCounter(); int appendCounter = rootReference.getAppendCounter();
if (appendCounter >= keysPerPage) { if (appendCounter >= keysPerPage) {
rootReference = flushAppendBuffer(rootReference); rootReference = flushAppendBuffer(rootReference);
......
...@@ -3018,7 +3018,7 @@ public class MVStore { ...@@ -3018,7 +3018,7 @@ public class MVStore {
// no thread is started if the write delay is 0 // no thread is started if the write delay is 0
// (if we only had a setter in the MVStore, // (if we only had a setter in the MVStore,
// the thread would need to be started in any case) // the thread would need to be started in any case)
set("autoCommitBufferSize", 0); //set("autoCommitBufferSize", 0);
return set("autoCommitDelay", 0); return set("autoCommitDelay", 0);
} }
......
...@@ -61,14 +61,15 @@ class MVPlainTempResult extends MVTempResult { ...@@ -61,14 +61,15 @@ class MVPlainTempResult extends MVTempResult {
MVPlainTempResult(Database database, Expression[] expressions, int visibleColumnCount) { MVPlainTempResult(Database database, Expression[] expressions, int visibleColumnCount) {
super(database, expressions.length, visibleColumnCount); super(database, expressions.length, visibleColumnCount);
ValueDataType valueType = new ValueDataType(database.getCompareMode(), database, new int[columnCount]); ValueDataType valueType = new ValueDataType(database.getCompareMode(), database, new int[columnCount]);
Builder<Long, ValueArray> builder = new MVMap.Builder<Long, ValueArray>().valueType(valueType); Builder<Long, ValueArray> builder = new MVMap.Builder<Long, ValueArray>()
.valueType(valueType).singleWriter();
map = store.openMap("tmp", builder); map = store.openMap("tmp", builder);
} }
@Override @Override
public int addRow(Value[] values) { public int addRow(Value[] values) {
assert parent == null; assert parent == null;
map.put(counter++, ValueArray.get(values)); map.append(counter++, ValueArray.get(values));
return ++rowCount; return ++rowCount;
} }
......
...@@ -83,7 +83,6 @@ public final class MVSecondaryIndex extends BaseIndex implements MVIndex { ...@@ -83,7 +83,6 @@ public final class MVSecondaryIndex extends BaseIndex implements MVIndex {
ValueArray key = convertToKey(row); ValueArray key = convertToKey(row);
map.append(key, ValueNull.INSTANCE); map.append(key, ValueNull.INSTANCE);
} }
map.flushAppendBuffer();
} }
private static final class Source { private static final class Source {
......
...@@ -160,7 +160,7 @@ public abstract class MVTempResult implements ResultExternal { ...@@ -160,7 +160,7 @@ public abstract class MVTempResult implements ResultExternal {
MVTempResult(Database database, int columnCount, int visibleColumnCount) { MVTempResult(Database database, int columnCount, int visibleColumnCount) {
try { try {
String fileName = FileUtils.createTempFile("h2tmp", Constants.SUFFIX_TEMP_FILE, false, true); String fileName = FileUtils.createTempFile("h2tmp", Constants.SUFFIX_TEMP_FILE, false, true);
Builder builder = new MVStore.Builder().fileName(fileName); Builder builder = new MVStore.Builder().fileName(fileName).cacheSize(0).autoCommitDisabled();
byte[] key = database.getFileEncryptionKey(); byte[] key = database.getFileEncryptionKey();
if (key != null) { if (key != null) {
builder.encryptionKey(MVTableEngine.decodePassword(key)); builder.encryptionKey(MVTableEngine.decodePassword(key));
......
...@@ -88,7 +88,7 @@ public class TransactionMap<K, V> { ...@@ -88,7 +88,7 @@ public class TransactionMap<K, V> {
for (int i = opentransactions.nextSetBit(0); i >= 0; i = opentransactions.nextSetBit(i+1)) { for (int i = opentransactions.nextSetBit(0); i >= 0; i = opentransactions.nextSetBit(i+1)) {
MVMap<Long, Object[]> undoLog = store.undoLogs[i]; MVMap<Long, Object[]> undoLog = store.undoLogs[i];
if (undoLog != null) { if (undoLog != null) {
MVMap.RootReference rootReference = undoLog.flushAppendBuffer(); MVMap.RootReference rootReference = undoLog.getRoot();
undoLogRootReferences[i] = rootReference; undoLogRootReferences[i] = rootReference;
undoLogSize += rootReference.root.getTotalCount() + rootReference.getAppendCounter(); undoLogSize += rootReference.root.getTotalCount() + rootReference.getAppendCounter();
} }
......
...@@ -439,9 +439,7 @@ public class TransactionStore { ...@@ -439,9 +439,7 @@ public class TransactionStore {
store.renameMap(undoLog, getUndoLogName(true, transactionId)); store.renameMap(undoLog, getUndoLogName(true, transactionId));
} }
try { try {
MVMap.RootReference rootReference = undoLog.flushAppendBuffer(); Cursor<Long, Object[]> cursor = undoLog.cursor(null);
Page rootPage = rootReference.root;
Cursor<Long, Object[]> cursor = new Cursor<>(rootPage, null);
while (cursor.hasNext()) { while (cursor.hasNext()) {
Long undoKey = cursor.next(); Long undoKey = cursor.next();
Object[] op = cursor.getValue(); Object[] op = cursor.getValue();
...@@ -592,7 +590,6 @@ public class TransactionStore { ...@@ -592,7 +590,6 @@ public class TransactionStore {
void rollbackTo(Transaction t, long maxLogId, long toLogId) { void rollbackTo(Transaction t, long maxLogId, long toLogId) {
int transactionId = t.getId(); int transactionId = t.getId();
MVMap<Long, Object[]> undoLog = undoLogs[transactionId]; MVMap<Long, Object[]> undoLog = undoLogs[transactionId];
undoLog.flushAppendBuffer();
RollbackDecisionMaker decisionMaker = new RollbackDecisionMaker(this, transactionId, toLogId, t.listener); RollbackDecisionMaker decisionMaker = new RollbackDecisionMaker(this, transactionId, toLogId, t.listener);
for (long logId = maxLogId - 1; logId >= toLogId; logId--) { for (long logId = maxLogId - 1; logId >= toLogId; logId--) {
Long undoKey = getOperationId(transactionId, logId); Long undoKey = getOperationId(transactionId, logId);
...@@ -614,7 +611,6 @@ public class TransactionStore { ...@@ -614,7 +611,6 @@ public class TransactionStore {
final long toLogId) { final long toLogId) {
final MVMap<Long, Object[]> undoLog = undoLogs[t.getId()]; final MVMap<Long, Object[]> undoLog = undoLogs[t.getId()];
undoLog.flushAppendBuffer();
return new Iterator<Change>() { return new Iterator<Change>() {
private long logId = maxLogId - 1; private long logId = maxLogId - 1;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论