提交 9447abe0 authored 作者: andrei's avatar andrei

Look Ma, no more locks!

上级 05ad3781
...@@ -10,9 +10,9 @@ import org.h2.mvstore.DataUtils; ...@@ -10,9 +10,9 @@ import org.h2.mvstore.DataUtils;
import org.h2.mvstore.MVMap; import org.h2.mvstore.MVMap;
import org.h2.mvstore.Page; import org.h2.mvstore.Page;
import org.h2.mvstore.type.DataType; import org.h2.mvstore.type.DataType;
import java.util.BitSet;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.BitSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
...@@ -99,77 +99,72 @@ public class TransactionMap<K, V> { ...@@ -99,77 +99,72 @@ public class TransactionMap<K, V> {
*/ */
public long sizeAsLong() { public long sizeAsLong() {
TransactionStore store = transaction.store; TransactionStore store = transaction.store;
store.rwLock.readLock().lock(); MVMap<Long, Object[]> undo = transaction.store.undoLog;
try {
MVMap<Long, Object[]> undo = transaction.store.undoLog;
BitSet committingTransactions;
MVMap.RootReference mapRootReference;
MVMap.RootReference undoLogRootReference;
do {
committingTransactions = store.committingTransactions.get();
mapRootReference = map.getRoot();
undoLogRootReference = store.undoLog.getRoot();
} while(committingTransactions != store.committingTransactions.get() ||
mapRootReference != map.getRoot());
Page undoRootPage = undoLogRootReference.root; BitSet committingTransactions;
long undoLogSize = undoRootPage.getTotalCount(); MVMap.RootReference mapRootReference;
Page mapRootPage = mapRootReference.root; MVMap.RootReference undoLogRootReference;
long size = mapRootPage.getTotalCount(); do {
if (undoLogSize == 0) { committingTransactions = store.committingTransactions.get();
return size; mapRootReference = map.getRoot();
} undoLogRootReference = store.undoLog.getRoot();
if (undoLogSize > size) { } while(committingTransactions != store.committingTransactions.get() ||
// the undo log is larger than the map - mapRootReference != map.getRoot());
// count the entries of the map
size = 0; Page undoRootPage = undoLogRootReference.root;
Cursor<K, VersionedValue> cursor = map.cursor(null); long undoLogSize = undoRootPage.getTotalCount();
while (cursor.hasNext()) { Page mapRootPage = mapRootReference.root;
K key = cursor.next(); long size = mapRootPage.getTotalCount();
VersionedValue data = cursor.getValue(); if (undoLogSize == 0) {
data = getValue(mapRootPage, undoRootPage, key, readLogId, data, committingTransactions); return size;
if (data != null && data.value != null) { }
size++; if (undoLogSize > size) {
} // the undo log is larger than the map -
// count the entries of the map
size = 0;
Cursor<K, VersionedValue> cursor = map.cursor(null);
while (cursor.hasNext()) {
K key = cursor.next();
VersionedValue data = cursor.getValue();
data = getValue(mapRootPage, undoRootPage, key, readLogId, data, committingTransactions);
if (data != null && data.value != null) {
size++;
} }
return size;
} }
// the undo log is smaller than the map - return size;
// scan the undo log and subtract invisible entries }
MVMap<Object, Integer> temp = transaction.store // the undo log is smaller than the map -
.createTempMap(); // scan the undo log and subtract invisible entries
try { MVMap<Object, Integer> temp = transaction.store
Cursor cursor = new Cursor<Long, Object[]>(undoRootPage, null); .createTempMap();
while (cursor.hasNext()) { try {
cursor.next(); Cursor cursor = new Cursor<Long, Object[]>(undoRootPage, null);
Object[] op = (Object[]) cursor.getValue(); while (cursor.hasNext()) {
int m = (Integer) op[0]; cursor.next();
if (m != mapId) { Object[] op = (Object[]) cursor.getValue();
// a different map - ignore int m = (Integer) op[0];
continue; if (m != mapId) {
} // a different map - ignore
@SuppressWarnings("unchecked") continue;
K key = (K) op[1]; }
VersionedValue data = map.get(mapRootPage, key); @SuppressWarnings("unchecked")
data = getValue(mapRootPage, undoRootPage, key, readLogId, data, committingTransactions); K key = (K) op[1];
if (data == null || data.value == null) { VersionedValue data = map.get(mapRootPage, key);
Integer old = temp.put(key, 1); data = getValue(mapRootPage, undoRootPage, key, readLogId, data, committingTransactions);
// count each key only once (there might be if (data == null || data.value == null) {
// multiple Integer old = temp.put(key, 1);
// changes for the same key) // count each key only once (there might be
if (old == null) { // multiple
size--; // changes for the same key)
} if (old == null) {
size--;
} }
} }
} finally {
transaction.store.store.removeMap(temp);
} }
return size;
} finally { } finally {
transaction.store.rwLock.readLock().unlock(); transaction.store.store.removeMap(temp);
} }
return size;
} }
/** /**
...@@ -420,25 +415,20 @@ public class TransactionMap<K, V> { ...@@ -420,25 +415,20 @@ public class TransactionMap<K, V> {
private VersionedValue getValue(K key, long maxLog) { private VersionedValue getValue(K key, long maxLog) {
TransactionStore store = transaction.store; TransactionStore store = transaction.store;
store.rwLock.readLock().lock(); BitSet committingTransactions;
try { MVMap.RootReference mapRootReference;
BitSet committingTransactions; MVMap.RootReference undoLogRootReference;
MVMap.RootReference mapRootReference; do {
MVMap.RootReference undoLogRootReference; committingTransactions = store.committingTransactions.get();
do { mapRootReference = map.getRoot();
committingTransactions = store.committingTransactions.get(); undoLogRootReference = store.undoLog.getRoot();
mapRootReference = map.getRoot(); } while(committingTransactions != store.committingTransactions.get() ||
undoLogRootReference = store.undoLog.getRoot(); mapRootReference != map.getRoot());
} while(committingTransactions != store.committingTransactions.get() ||
mapRootReference != map.getRoot()); Page undoRootPage = undoLogRootReference.root;
Page mapRootPage = mapRootReference.root;
Page undoRootPage = undoLogRootReference.root; VersionedValue data = map.get(mapRootPage, key);
Page mapRootPage = mapRootReference.root; return getValue(mapRootPage, undoRootPage, key, maxLog, data, store.committingTransactions.get());
VersionedValue data = map.get(mapRootPage, key);
return getValue(mapRootPage, undoRootPage, key, maxLog, data, store.committingTransactions.get());
} finally {
store.rwLock.readLock().unlock();
}
} }
/** /**
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论