提交 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,41 +1177,22 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1173,41 +1177,22 @@ 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);
if (rootReference != null) {
break;
}
}
assert rootReference.getAppendCounter() == 0;
return rootReference;
}
private RootReference appendLeafPage(RootReference rootReference, Page split, int attempt) {
CursorPos pos = rootReference.root.getAppendCursorPos(null); CursorPos pos = rootReference.root.getAppendCursorPos(null);
assert split.map == this; assert page.map == this;
assert pos != null; assert pos != null;
assert split.getKeyCount() > 0; assert page.getKeyCount() > 0;
Object key = split.getKey(0); Object key = page.getKey(0);
assert pos.index < 0 : pos.index; assert pos.index < 0 : pos.index;
int index = -pos.index - 1; int index = -pos.index - 1;
assert index == pos.page.getKeyCount() : index + " != " + pos.page.getKeyCount(); assert index == pos.page.getKeyCount() : index + " != " + pos.page.getKeyCount();
...@@ -1218,13 +1203,13 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1218,13 +1203,13 @@ public class MVMap<K, V> extends AbstractMap<K, V>
while (true) { while (true) {
if (pos == null) { if (pos == null) {
if (p.getKeyCount() == 0) { if (p.getKeyCount() == 0) {
p = split; p = page;
} else { } else {
Object keys[] = new Object[] { key }; Object keys[] = new Object[] { key };
Page.PageReference children[] = new Page.PageReference[] { Page.PageReference children[] = new Page.PageReference[] {
new Page.PageReference(p), new Page.PageReference(p),
new Page.PageReference(split)}; new Page.PageReference(page)};
p = Page.create(this, keys, null, children, p.getTotalCount() + split.getTotalCount(), 0); p = Page.create(this, keys, null, children, p.getTotalCount() + page.getTotalCount(), 0);
} }
break; break;
} }
...@@ -1233,17 +1218,16 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1233,17 +1218,16 @@ public class MVMap<K, V> extends AbstractMap<K, V>
index = pos.index; index = pos.index;
pos = pos.parent; pos = pos.parent;
p = p.copy(); p = p.copy();
p.setChild(index, split); p.setChild(index, page);
p.insertNode(index, key, c); p.insertNode(index, key, c);
int keyCount;
if ((keyCount = p.getKeyCount()) <= store.getKeysPerPage() && if ((keyCount = p.getKeyCount()) <= store.getKeysPerPage() &&
(p.getMemory() < store.getMaxPageSize() || keyCount <= (p.isLeaf() ? 1 : 2))) { (p.getMemory() < store.getMaxPageSize() || keyCount <= (p.isLeaf() ? 1 : 2))) {
break; break;
} }
int at = keyCount - 2; int at = keyCount - 2;
key = p.getKey(at); key = p.getKey(at);
split = p.split(at); page = p.split(at);
unsavedMemory += p.getMemory() + split.getMemory(); unsavedMemory += p.getMemory() + page.getMemory();
} }
unsavedMemory += p.getMemory(); unsavedMemory += p.getMemory();
while (pos != null) { while (pos != null) {
...@@ -1263,9 +1247,12 @@ public class MVMap<K, V> extends AbstractMap<K, V> ...@@ -1263,9 +1247,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
if (store.getFileStore() != null) { if (store.getFileStore() != null) {
store.registerUnsavedPage(unsavedMemory); store.registerUnsavedPage(unsavedMemory);
} }
assert updatedRootReference.getAppendCounter() == 0;
return updatedRootReference; return updatedRootReference;
} }
return null; rootReference = getRootInternal();
}
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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论