提交 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>
}
public final RootReference getRoot() {
RootReference rootReference = getRootInternal();
return singleWriter ? flushAppendBuffer(rootReference) : rootReference;
}
private RootReference getRootInternal() {
return root.get();
}
......@@ -1112,7 +1117,6 @@ public class MVMap<K, V> extends AbstractMap<K, V>
}
return rootReference;
}
rootReference = flushAppendBuffer(rootReference);
RootReference updatedRootReference = new RootReference(rootReference, writeVersion, ++attempt);
if(root.compareAndSet(rootReference, updatedRootReference)) {
removeUnusedOldVersions(updatedRootReference);
......@@ -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
* is flushed - emptied with all entries inserted into map as a new leaf.
* @param rootReference current RootReference
* @return potentially updated RootReference
*/
public RootReference flushAppendBuffer() {
return flushAppendBuffer(null);
}
private RootReference flushAppendBuffer(RootReference rootReference) {
int attempt = 0;
while(true) {
if (rootReference == null) {
rootReference = getRoot();
}
int keyCount = rootReference.getAppendCounter();
if (keyCount == 0) {
break;
}
int keyCount;
while((keyCount = rootReference.getAppendCounter()) > 0) {
Page page = Page.create(this,
Arrays.copyOf(keysBuffer, keyCount),
Arrays.copyOf(valuesBuffer, keyCount),
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);
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;
CursorPos pos = rootReference.root.getAppendCursorPos(null);
assert page.map == this;
assert pos != null;
assert page.getKeyCount() > 0;
Object key = page.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;
p = p.copy();
p.setChild(index, split);
p.insertNode(index, key, c);
int keyCount;
if ((keyCount = p.getKeyCount()) <= store.getKeysPerPage() &&
(p.getMemory() < store.getMaxPageSize() || keyCount <= (p.isLeaf() ? 1 : 2))) {
break;
CursorPos tip = pos;
int unsavedMemory = 0;
while (true) {
if (pos == null) {
if (p.getKeyCount() == 0) {
p = page;
} 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();
pos = pos.parent;
}
RootReference updatedRootReference = new RootReference(rootReference, p, ++attempt);
if(root.compareAndSet(rootReference, updatedRootReference)) {
while (tip != null) {
tip.page.removePage();
tip = tip.parent;
while (pos != null) {
Page c = p;
p = pos.page;
p = p.copy();
p.setChild(pos.index, c);
unsavedMemory += p.getMemory();
pos = pos.parent;
}
if (store.getFileStore() != null) {
store.registerUnsavedPage(unsavedMemory);
RootReference updatedRootReference = new RootReference(rootReference, p, ++attempt);
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>
int attempt = 0;
boolean success = false;
while(!success) {
RootReference rootReference = getRoot();
RootReference rootReference = getRootInternal();
int appendCounter = rootReference.getAppendCounter();
if (appendCounter >= keysPerPage) {
rootReference = flushAppendBuffer(rootReference);
......
......@@ -83,7 +83,6 @@ public final class MVSecondaryIndex extends BaseIndex implements MVIndex {
ValueArray key = convertToKey(row);
map.append(key, ValueNull.INSTANCE);
}
map.flushAppendBuffer();
}
private static final class Source {
......
......@@ -88,7 +88,7 @@ public class TransactionMap<K, V> {
for (int i = opentransactions.nextSetBit(0); i >= 0; i = opentransactions.nextSetBit(i+1)) {
MVMap<Long, Object[]> undoLog = store.undoLogs[i];
if (undoLog != null) {
MVMap.RootReference rootReference = undoLog.flushAppendBuffer();
MVMap.RootReference rootReference = undoLog.getRoot();
undoLogRootReferences[i] = rootReference;
undoLogSize += rootReference.root.getTotalCount() + rootReference.getAppendCounter();
}
......
......@@ -439,9 +439,7 @@ public class TransactionStore {
store.renameMap(undoLog, getUndoLogName(true, transactionId));
}
try {
MVMap.RootReference rootReference = undoLog.flushAppendBuffer();
Page rootPage = rootReference.root;
Cursor<Long, Object[]> cursor = new Cursor<>(rootPage, null);
Cursor<Long, Object[]> cursor = undoLog.cursor(null);
while (cursor.hasNext()) {
Long undoKey = cursor.next();
Object[] op = cursor.getValue();
......@@ -592,7 +590,6 @@ public class TransactionStore {
void rollbackTo(Transaction t, long maxLogId, long toLogId) {
int transactionId = t.getId();
MVMap<Long, Object[]> undoLog = undoLogs[transactionId];
undoLog.flushAppendBuffer();
RollbackDecisionMaker decisionMaker = new RollbackDecisionMaker(this, transactionId, toLogId, t.listener);
for (long logId = maxLogId - 1; logId >= toLogId; logId--) {
Long undoKey = getOperationId(transactionId, logId);
......@@ -614,7 +611,6 @@ public class TransactionStore {
final long toLogId) {
final MVMap<Long, Object[]> undoLog = undoLogs[t.getId()];
undoLog.flushAppendBuffer();
return new Iterator<Change>() {
private long logId = maxLogId - 1;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论