提交 79d089e9 authored 作者: Thomas Mueller's avatar Thomas Mueller

MVStore: imported BLOB and CLOB data sometimes disappeared. This was caused by a…

MVStore: imported BLOB and CLOB data sometimes disappeared. This was caused by a bug in the ObjectDataType comparison.
上级 feb86a16
...@@ -423,10 +423,10 @@ public class ObjectDataType implements DataType { ...@@ -423,10 +423,10 @@ public class ObjectDataType implements DataType {
public int compare(Object aObj, Object bObj) { public int compare(Object aObj, Object bObj) {
AutoDetectDataType aType = getType(aObj); AutoDetectDataType aType = getType(aObj);
AutoDetectDataType bType = getType(bObj); AutoDetectDataType bType = getType(bObj);
if (aType == bType) { int typeDiff = aType.typeId - bType.typeId;
if (typeDiff == 0) {
return aType.compare(aObj, bObj); return aType.compare(aObj, bObj);
} }
int typeDiff = aType.typeId - bType.typeId;
return Integer.signum(typeDiff); return Integer.signum(typeDiff);
} }
......
...@@ -292,7 +292,7 @@ public class LobStorageMap implements LobStorageInterface { ...@@ -292,7 +292,7 @@ public class LobStorageMap implements LobStorageInterface {
Object[] key = new Object[] {streamStoreId, lobId }; Object[] key = new Object[] {streamStoreId, lobId };
refMap.remove(key); refMap.remove(key);
// check if there are more entries for this streamStoreId // check if there are more entries for this streamStoreId
key = new Object[] {streamStoreId, 0 }; key = new Object[] {streamStoreId, 0L };
value = refMap.ceilingKey(key); value = refMap.ceilingKey(key);
boolean hasMoreEntries = false; boolean hasMoreEntries = false;
if (value != null) { if (value != null) {
......
...@@ -11,6 +11,8 @@ import java.io.FileOutputStream; ...@@ -11,6 +11,8 @@ import java.io.FileOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.ConcurrentModificationException; import java.util.ConcurrentModificationException;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
...@@ -20,6 +22,8 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -20,6 +22,8 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.h2.mvstore.DataUtils; import org.h2.mvstore.DataUtils;
import org.h2.mvstore.MVMap; import org.h2.mvstore.MVMap;
import org.h2.mvstore.MVStore; import org.h2.mvstore.MVStore;
import org.h2.mvstore.WriteBuffer;
import org.h2.mvstore.type.ObjectDataType;
import org.h2.store.fs.FileChannelInputStream; import org.h2.store.fs.FileChannelInputStream;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase; import org.h2.test.TestBase;
...@@ -46,6 +50,7 @@ public class TestConcurrent extends TestMVStore { ...@@ -46,6 +50,7 @@ public class TestConcurrent extends TestMVStore {
FileUtils.createDirectories(getBaseDir()); FileUtils.createDirectories(getBaseDir());
FileUtils.deleteRecursive("memFS:", false); FileUtils.deleteRecursive("memFS:", false);
testConcurrentDataType();
testConcurrentAutoCommitAndChange(); testConcurrentAutoCommitAndChange();
testConcurrentReplaceAndRead(); testConcurrentReplaceAndRead();
testConcurrentChangeAndCompact(); testConcurrentChangeAndCompact();
...@@ -60,6 +65,61 @@ public class TestConcurrent extends TestMVStore { ...@@ -60,6 +65,61 @@ public class TestConcurrent extends TestMVStore {
testConcurrentRead(); testConcurrentRead();
} }
private void testConcurrentDataType() throws InterruptedException {
final ObjectDataType type = new ObjectDataType();
final Object[] data = new Object[]{
null,
-1,
1,
10,
"Hello",
new Object[]{ new byte[]{(byte) -1, (byte) 1}, null},
new Object[]{ new byte[]{(byte) 1, (byte) -1}, 10},
new Object[]{ new byte[]{(byte) -1, (byte) 1}, 20L},
new Object[]{ new byte[]{(byte) 1, (byte) -1}, 5},
};
Arrays.sort(data, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
return type.compare(o1, o2);
}
});
Task[] tasks = new Task[2];
for (int i = 0; i < tasks.length; i++) {
tasks[i] = new Task() {
@Override
public void call() throws Exception {
Random r = new Random();
WriteBuffer buff = new WriteBuffer();
while (!stop) {
int a = r.nextInt(data.length);
int b = r.nextInt(data.length);
int comp;
if (r.nextBoolean()) {
comp = type.compare(a, b);
} else {
comp = -type.compare(b, a);
}
buff.clear();
type.write(buff, a);
buff.clear();
type.write(buff, b);
if (a == b) {
assertEquals(0, comp);
} else {
assertEquals(a > b ? 1 : -1, comp);
}
}
}
};
tasks[i].execute();
}
Thread.sleep(100);
for (Task t : tasks) {
t.get();
}
}
private void testConcurrentAutoCommitAndChange() throws InterruptedException { private void testConcurrentAutoCommitAndChange() throws InterruptedException {
String fileName = "memFS:testConcurrentChangeAndBackgroundCompact"; String fileName = "memFS:testConcurrentChangeAndBackgroundCompact";
FileUtils.delete(fileName); FileUtils.delete(fileName);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论