提交 1293f1e9 authored 作者: Andrei Tokar's avatar Andrei Tokar

make append mode of MVMap more transparent

上级 d7c0e317
...@@ -779,6 +779,11 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -779,6 +779,11 @@ public class MVMap<K, V> extends AbstractMap<K, V>
} }
public final RootReference getRoot() { public final RootReference getRoot() {
RootReference rootReference = getRootInternal();
return singleWriter ? flushAppendBuffer(rootReference) : rootReference;
}
private RootReference getRootInternal() {
return root.get(); return root.get();
} }
...@@ -1112,7 +1117,6 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1112,7 +1117,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 +1177,82 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1173,99 +1177,82 @@ 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) {
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 = 0;
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 +1267,7 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1280,7 +1267,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);
......
...@@ -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 {
......
...@@ -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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论