提交 9ec2fad0 authored 作者: Noel Grandin's avatar Noel Grandin

fix deadlock

need to take the TransactionStore RWLock before we synchronize on the
MVMap
上级 67310c61
...@@ -946,64 +946,66 @@ public class TransactionStore { ...@@ -946,64 +946,66 @@ public class TransactionStore {
* @return the size * @return the size
*/ */
public long sizeAsLong() { public long sizeAsLong() {
long sizeRaw = map.sizeAsLong(); transaction.store.rwLock.readLock().lock();
MVMap<Long, Object[]> undo = transaction.store.undoLog; try {
long undoLogSize; long sizeRaw = map.sizeAsLong();
synchronized (undo) { MVMap<Long, Object[]> undo = transaction.store.undoLog;
undoLogSize = undo.sizeAsLong(); long undoLogSize;
} synchronized (undo) {
if (undoLogSize == 0) { undoLogSize = undo.sizeAsLong();
return sizeRaw; }
} if (undoLogSize == 0) {
if (undoLogSize > sizeRaw) { return sizeRaw;
// the undo log is larger than the map - }
// count the entries of the map if (undoLogSize > sizeRaw) {
long size = 0; // the undo log is larger than the map -
Cursor<K, VersionedValue> cursor = map.cursor(null); // count the entries of the map
while (cursor.hasNext()) { long size = 0;
VersionedValue data; Cursor<K, VersionedValue> cursor = map.cursor(null);
transaction.store.rwLock.readLock().lock(); while (cursor.hasNext()) {
try { VersionedValue data;
K key = cursor.next(); K key = cursor.next();
data = getValue(key, readLogId, cursor.getValue()); data = getValue(key, readLogId, cursor.getValue());
} finally { if (data != null && data.value != null) {
transaction.store.rwLock.readLock().unlock(); size++;
} }
if (data != null && data.value != null) {
size++;
} }
return size;
} }
return size; // the undo log is smaller than the map -
} // scan the undo log and subtract invisible entries
// the undo log is smaller than the map - synchronized (undo) {
// scan the undo log and subtract invisible entries // re-fetch in case any transaction was committed now
synchronized (undo) { long size = map.sizeAsLong();
// re-fetch in case any transaction was committed now MVMap<Object, Integer> temp = transaction.store
long size = map.sizeAsLong(); .createTempMap();
MVMap<Object, Integer> temp = transaction.store.createTempMap(); try {
try { for (Entry<Long, Object[]> e : undo.entrySet()) {
for (Entry<Long, Object[]> e : undo.entrySet()) { Object[] op = e.getValue();
Object[] op = e.getValue(); int m = (Integer) op[0];
int m = (Integer) op[0]; if (m != mapId) {
if (m != mapId) { // a different map - ignore
// a different map - ignore continue;
continue; }
} @SuppressWarnings("unchecked")
@SuppressWarnings("unchecked") K key = (K) op[1];
K key = (K) op[1]; if (get(key) == null) {
if (get(key) == null) { Integer old = temp.put(key, 1);
Integer old = temp.put(key, 1); // count each key only once (there might be
// count each key only once (there might be multiple // multiple
// changes for the same key) // changes for the same key)
if (old == null) { if (old == null) {
size--; size--;
}
} }
} }
} finally {
transaction.store.store.removeMap(temp);
} }
} finally { return size;
transaction.store.store.removeMap(temp);
} }
return size; } finally {
transaction.store.rwLock.readLock().unlock();
} }
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论