Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
d3bd6b1d
提交
d3bd6b1d
authored
9 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
MVStore: power failure could corrupt the store, if writes were re-ordered.
上级
ba429036
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
288 行增加
和
152 行删除
+288
-152
changelog.html
h2/src/docsrc/html/changelog.html
+2
-0
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+224
-128
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+1
-0
TestReorderWrites.java
h2/src/test/org/h2/test/poweroff/TestReorderWrites.java
+47
-14
TestMVStore.java
h2/src/test/org/h2/test/store/TestMVStore.java
+7
-4
FilePathReorderWrites.java
h2/src/test/org/h2/test/utils/FilePathReorderWrites.java
+7
-6
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
d3bd6b1d
...
@@ -21,6 +21,8 @@ Change Log
...
@@ -21,6 +21,8 @@ Change Log
<h2>
Next Version (unreleased)
</h2>
<h2>
Next Version (unreleased)
</h2>
<ul>
<ul>
<li>
MVStore: power failure could corrupt the store, if writes were re-ordered.
</li>
<li>
For compatibility with other databases, support for (double and float)
<li>
For compatibility with other databases, support for (double and float)
-0.0 has been removed. 0.0 is used instead.
-0.0 has been removed. 0.0 is used instead.
</li>
</li>
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
d3bd6b1d
差异被折叠。
点击展开。
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
d3bd6b1d
...
@@ -795,6 +795,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
...
@@ -795,6 +795,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest
(
new
TestMVTableEngine
());
addTest
(
new
TestMVTableEngine
());
addTest
(
new
TestObjectDataType
());
addTest
(
new
TestObjectDataType
());
addTest
(
new
TestRandomMapOps
());
addTest
(
new
TestRandomMapOps
());
addTest
(
new
TestReorderWrites
());
addTest
(
new
TestSpinLock
());
addTest
(
new
TestSpinLock
());
addTest
(
new
TestStreamStore
());
addTest
(
new
TestStreamStore
());
addTest
(
new
TestTransactionStore
());
addTest
(
new
TestTransactionStore
());
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/poweroff/TestReorderWrites.java
浏览文件 @
d3bd6b1d
...
@@ -13,6 +13,7 @@ import java.util.Map;
...
@@ -13,6 +13,7 @@ import java.util.Map;
import
java.util.Random
;
import
java.util.Random
;
import
org.h2.mvstore.MVStore
;
import
org.h2.mvstore.MVStore
;
import
org.h2.mvstore.MVStoreTool
;
import
org.h2.store.fs.FilePath
;
import
org.h2.store.fs.FilePath
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.test.TestBase
;
import
org.h2.test.TestBase
;
...
@@ -24,6 +25,8 @@ import org.h2.test.utils.FilePathReorderWrites;
...
@@ -24,6 +25,8 @@ import org.h2.test.utils.FilePathReorderWrites;
*/
*/
public
class
TestReorderWrites
extends
TestBase
{
public
class
TestReorderWrites
extends
TestBase
{
private
static
final
boolean
LOG
=
false
;
/**
/**
* Run just this test.
* Run just this test.
*
*
...
@@ -35,16 +38,16 @@ public class TestReorderWrites extends TestBase {
...
@@ -35,16 +38,16 @@ public class TestReorderWrites extends TestBase {
@Override
@Override
public
void
test
()
throws
Exception
{
public
void
test
()
throws
Exception
{
testMVStore
();
testFileSystem
();
testFileSystem
();
// testMVStore();
}
}
private
void
testMVStore
()
{
private
void
testMVStore
()
{
FilePathReorderWrites
fs
=
FilePathReorderWrites
.
register
();
FilePathReorderWrites
fs
=
FilePathReorderWrites
.
register
();
String
fileName
=
"reorder:memFS:test.mv"
;
String
fileName
=
"reorder:memFS:test.mv"
;
Random
r
=
new
Random
(
1
);
for
(
int
i
=
0
;
i
<
1000
;
i
++)
{
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
log
(
i
+
" --------------------------------"
);
System
.
out
.
println
(
i
+
" tst --------------------------------"
);
Random
r
=
new
Random
(
i
);
fs
.
setPowerOffCountdown
(
100
,
i
);
fs
.
setPowerOffCountdown
(
100
,
i
);
FileUtils
.
delete
(
fileName
);
FileUtils
.
delete
(
fileName
);
MVStore
store
=
new
MVStore
.
Builder
().
MVStore
store
=
new
MVStore
.
Builder
().
...
@@ -52,12 +55,12 @@ public class TestReorderWrites extends TestBase {
...
@@ -52,12 +55,12 @@ public class TestReorderWrites extends TestBase {
autoCommitDisabled
().
open
();
autoCommitDisabled
().
open
();
// store.setRetentionTime(10);
// store.setRetentionTime(10);
Map
<
Integer
,
byte
[]>
map
=
store
.
openMap
(
"data"
);
Map
<
Integer
,
byte
[]>
map
=
store
.
openMap
(
"data"
);
map
.
put
(
0
,
new
byte
[
1
]);
map
.
put
(
-
1
,
new
byte
[
1
]);
store
.
commit
();
store
.
commit
();
// if (r.nextBoolean()) {
store
.
getFileStore
().
sync
();
store
.
getFileStore
().
sync
(
);
int
stop
=
4
+
r
.
nextInt
(
20
);
//}
log
(
"synched start"
);
fs
.
setPowerOffCountdown
(
4
+
r
.
nextInt
(
20
)
,
i
);
fs
.
setPowerOffCountdown
(
stop
,
i
);
try
{
try
{
for
(
int
j
=
1
;
j
<
100
;
j
++)
{
for
(
int
j
=
1
;
j
<
100
;
j
++)
{
Map
<
Integer
,
Integer
>
newMap
=
store
.
openMap
(
"d"
+
j
);
Map
<
Integer
,
Integer
>
newMap
=
store
.
openMap
(
"d"
+
j
);
...
@@ -69,31 +72,61 @@ public class TestReorderWrites extends TestBase {
...
@@ -69,31 +72,61 @@ public class TestReorderWrites extends TestBase {
}
else
{
}
else
{
map
.
put
(
key
,
new
byte
[
len
]);
map
.
put
(
key
,
new
byte
[
len
]);
}
}
log
(
"op "
+
j
+
": "
);
store
.
commit
();
store
.
commit
();
switch
(
r
.
nextInt
(
10
))
{
case
0
:
log
(
"op compact"
);
store
.
compact
(
100
,
10
*
1024
);
break
;
case
1
:
log
(
"op compactMoveChunks"
);
store
.
compactMoveChunks
();
log
(
"op compactMoveChunks done"
);
break
;
}
}
}
// write has to fail at some point
// write has to fail at some point
fail
();
fail
();
}
catch
(
IllegalStateException
e
)
{
}
catch
(
IllegalStateException
e
)
{
log
(
"stop "
+
e
);
// expected
// expected
}
}
store
.
close
();
try
{
System
.
out
.
println
(
"-------------------------------- test"
);
store
.
close
();
}
catch
(
IllegalStateException
e
)
{
// expected
store
.
closeImmediately
();
}
log
(
"verify"
);
fs
.
setPowerOffCountdown
(
100
,
0
);
fs
.
setPowerOffCountdown
(
100
,
0
);
System
.
out
.
println
(
"file size: "
+
FileUtils
.
size
(
fileName
));
if
(
LOG
)
{
MVStoreTool
.
dump
(
fileName
,
true
);
}
store
=
new
MVStore
.
Builder
().
store
=
new
MVStore
.
Builder
().
fileName
(
fileName
).
fileName
(
fileName
).
autoCommitDisabled
().
open
();
autoCommitDisabled
().
open
();
map
=
store
.
openMap
(
"data"
);
map
=
store
.
openMap
(
"data"
);
assertEquals
(
1
,
map
.
get
(
0
).
length
);
if
(!
map
.
containsKey
(-
1
))
{
fail
(
"key not found, size="
+
map
.
size
()
+
" i="
+
i
);
}
else
{
assertEquals
(
"i="
+
i
,
1
,
map
.
get
(-
1
).
length
);
}
for
(
int
j
=
0
;
j
<
100
;
j
++)
{
for
(
int
j
=
0
;
j
<
100
;
j
++)
{
Map
<
Integer
,
Integer
>
newMap
=
store
.
openMap
(
"d"
+
j
);
Map
<
Integer
,
Integer
>
newMap
=
store
.
openMap
(
"d"
+
j
);
newMap
.
get
(
j
);
newMap
.
get
(
j
);
}
}
//
map.keySet();
map
.
keySet
();
store
.
close
();
store
.
close
();
}
}
}
}
private
static
void
log
(
String
message
)
{
if
(
LOG
)
{
System
.
out
.
println
(
message
);
}
}
private
void
testFileSystem
()
throws
IOException
{
private
void
testFileSystem
()
throws
IOException
{
FilePathReorderWrites
fs
=
FilePathReorderWrites
.
register
();
FilePathReorderWrites
fs
=
FilePathReorderWrites
.
register
();
String
fileName
=
"reorder:memFS:test"
;
String
fileName
=
"reorder:memFS:test"
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMVStore.java
浏览文件 @
d3bd6b1d
...
@@ -948,6 +948,10 @@ public class TestMVStore extends TestBase {
...
@@ -948,6 +948,10 @@ public class TestMVStore extends TestBase {
break
;
break
;
}
}
}
}
// the last chunk is at the end
s
.
setReuseSpace
(
false
);
map
=
s
.
openMap
(
"test2"
);
map
.
put
(
1
,
new
byte
[
1000
]);
s
.
close
();
s
.
close
();
FilePath
f
=
FilePath
.
get
(
fileName
);
FilePath
f
=
FilePath
.
get
(
fileName
);
int
blockSize
=
4
*
1024
;
int
blockSize
=
4
*
1024
;
...
@@ -976,6 +980,8 @@ public class TestMVStore extends TestBase {
...
@@ -976,6 +980,8 @@ public class TestMVStore extends TestBase {
s
=
openStore
(
fileName
);
s
=
openStore
(
fileName
);
map
=
s
.
openMap
(
"test"
);
map
=
s
.
openMap
(
"test"
);
assertEquals
(
100
,
map
.
get
(
0
).
length
);
assertEquals
(
100
,
map
.
get
(
0
).
length
);
map
=
s
.
openMap
(
"test2"
);
assertFalse
(
map
.
containsKey
(
1
));
s
.
close
();
s
.
close
();
}
else
{
}
else
{
// both headers are corrupt
// both headers are corrupt
...
@@ -1414,7 +1420,7 @@ public class TestMVStore extends TestBase {
...
@@ -1414,7 +1420,7 @@ public class TestMVStore extends TestBase {
assertEquals
(
0
,
m
.
size
());
assertEquals
(
0
,
m
.
size
());
s
.
commit
();
s
.
commit
();
// ensure only nodes are read, but not leaves
// ensure only nodes are read, but not leaves
assertEquals
(
4
1
,
s
.
getFileStore
().
getReadCount
());
assertEquals
(
4
5
,
s
.
getFileStore
().
getReadCount
());
assertTrue
(
s
.
getFileStore
().
getWriteCount
()
<
5
);
assertTrue
(
s
.
getFileStore
().
getWriteCount
()
<
5
);
s
.
close
();
s
.
close
();
}
}
...
@@ -1579,7 +1585,6 @@ public class TestMVStore extends TestBase {
...
@@ -1579,7 +1585,6 @@ public class TestMVStore extends TestBase {
data
.
put
(
"2"
,
"World"
);
data
.
put
(
"2"
,
"World"
);
s
.
commit
();
s
.
commit
();
assertEquals
(
1
,
s
.
getCurrentVersion
());
assertEquals
(
1
,
s
.
getCurrentVersion
());
assertFalse
(
m
.
containsKey
(
"chunk.2"
));
assertEquals
(
"[data]"
,
s
.
getMapNames
().
toString
());
assertEquals
(
"[data]"
,
s
.
getMapNames
().
toString
());
assertEquals
(
"data"
,
s
.
getMapName
(
data
.
getId
()));
assertEquals
(
"data"
,
s
.
getMapName
(
data
.
getId
()));
...
@@ -1599,8 +1604,6 @@ public class TestMVStore extends TestBase {
...
@@ -1599,8 +1604,6 @@ public class TestMVStore extends TestBase {
s
.
rollbackTo
(
1
);
s
.
rollbackTo
(
1
);
assertEquals
(
"Hello"
,
data
.
get
(
"1"
));
assertEquals
(
"Hello"
,
data
.
get
(
"1"
));
assertEquals
(
"World"
,
data
.
get
(
"2"
));
assertEquals
(
"World"
,
data
.
get
(
"2"
));
assertFalse
(
m
.
containsKey
(
"chunk.1"
));
assertFalse
(
m
.
containsKey
(
"chunk.2"
));
s
.
close
();
s
.
close
();
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/utils/FilePathReorderWrites.java
浏览文件 @
d3bd6b1d
...
@@ -105,10 +105,11 @@ public class FilePathReorderWrites extends FilePathWrapper {
...
@@ -105,10 +105,11 @@ public class FilePathReorderWrites extends FilePathWrapper {
if
(
powerFailureCountdown
==
0
)
{
if
(
powerFailureCountdown
==
0
)
{
return
;
return
;
}
}
if
(
--
powerFailureCountdown
>
0
)
{
if
(
powerFailureCountdown
<
0
)
{
return
;
throw
POWER_FAILURE
;
}
}
if
(
powerFailureCountdown
>=
-
1
)
{
powerFailureCountdown
--;
if
(
powerFailureCountdown
==
0
)
{
powerFailureCountdown
--;
powerFailureCountdown
--;
throw
POWER_FAILURE
;
throw
POWER_FAILURE
;
}
}
...
@@ -122,7 +123,7 @@ public class FilePathReorderWrites extends FilePathWrapper {
...
@@ -122,7 +123,7 @@ public class FilePathReorderWrites extends FilePathWrapper {
IOUtils
.
copy
(
in
,
out
);
IOUtils
.
copy
(
in
,
out
);
FileChannel
base
=
getBase
().
open
(
mode
);
FileChannel
base
=
getBase
().
open
(
mode
);
FileChannel
readBase
=
copy
.
open
(
mode
);
FileChannel
readBase
=
copy
.
open
(
mode
);
return
new
File
PowerFailure
(
this
,
base
,
readBase
);
return
new
File
ReorderWrites
(
this
,
base
,
readBase
);
}
}
@Override
@Override
...
@@ -140,7 +141,7 @@ public class FilePathReorderWrites extends FilePathWrapper {
...
@@ -140,7 +141,7 @@ public class FilePathReorderWrites extends FilePathWrapper {
/**
/**
* An file that checks for errors before each write operation.
* An file that checks for errors before each write operation.
*/
*/
class
File
PowerFailure
extends
FileBase
{
class
File
ReorderWrites
extends
FileBase
{
private
final
FilePathReorderWrites
file
;
private
final
FilePathReorderWrites
file
;
/**
/**
...
@@ -162,7 +163,7 @@ class FilePowerFailure extends FileBase {
...
@@ -162,7 +163,7 @@ class FilePowerFailure extends FileBase {
private
int
id
;
private
int
id
;
File
PowerFailure
(
FilePathReorderWrites
file
,
FileChannel
base
,
FileChannel
readBase
)
{
File
ReorderWrites
(
FilePathReorderWrites
file
,
FileChannel
base
,
FileChannel
readBase
)
{
this
.
file
=
file
;
this
.
file
=
file
;
this
.
base
=
base
;
this
.
base
=
base
;
this
.
readBase
=
readBase
;
this
.
readBase
=
readBase
;
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论