Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
152f7ba7
提交
152f7ba7
authored
11 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
MVTableEngine: improve tests
上级
24505f0e
隐藏空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
143 行增加
和
39 行删除
+143
-39
mvstore.html
h2/src/docsrc/html/mvstore.html
+6
-1
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+2
-0
FilePathMem.java
h2/src/main/org/h2/store/fs/FilePathMem.java
+13
-6
FilePathRec.java
h2/src/main/org/h2/store/fs/FilePathRec.java
+19
-0
TestFullText.java
h2/src/test/org/h2/test/db/TestFullText.java
+21
-19
TestKillProcessWhileWriting.java
...c/test/org/h2/test/store/TestKillProcessWhileWriting.java
+10
-6
TestReopen.java
h2/src/test/org/h2/test/unit/TestReopen.java
+22
-5
FilePathUnstable.java
h2/src/test/org/h2/test/utils/FilePathUnstable.java
+50
-2
没有找到文件。
h2/src/docsrc/html/mvstore.html
浏览文件 @
152f7ba7
...
...
@@ -383,8 +383,13 @@ meaning outside of the regular garbage collected heap. This allows to use very l
stores without having to increase the JVM heap (which would increase Java garbage collection
pauses a lot). Memory is allocated using
<code>
ByteBuffer.allocateDirect
</code>
.
One chunk is allocated at a time (each chunk is usually a few MB large), so that
allocation cost is low.
allocation cost is low.
To use the off-heap storage, call:
</p>
<pre>
OffHeapStore offHeap = new OffHeapStore();
MVStore s = new MVStore.Builder().
fileStore(offHeap).open();
</pre>
<h3
id=
"fileSystem"
>
File System Abstraction, File Locking and Online Backup
</h3>
<p>
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
152f7ba7
...
...
@@ -110,6 +110,8 @@ MVStore:
- add new feature to file systems that avoid copying data
(reads should return a ByteBuffer, not write into one)
- do we need to store a dummy chunk entry in the chunk itself?
currently yes, as some fields are not set in the chunk header
- off-heap LIRS cache (the LIRS cache should use a map factory)
*/
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/fs/FilePathMem.java
浏览文件 @
152f7ba7
...
...
@@ -30,6 +30,7 @@ import org.h2.util.New;
public
class
FilePathMem
extends
FilePath
{
private
static
final
TreeMap
<
String
,
FileMemData
>
MEMORY_FILES
=
new
TreeMap
<
String
,
FileMemData
>();
private
static
final
FileMemData
DIRECTORY
=
new
FileMemData
(
""
,
false
);
@Override
public
FilePathMem
getPath
(
String
path
)
{
...
...
@@ -90,7 +91,9 @@ public class FilePathMem extends FilePath {
synchronized
(
MEMORY_FILES
)
{
for
(
String
n
:
MEMORY_FILES
.
tailMap
(
name
).
keySet
())
{
if
(
n
.
startsWith
(
name
))
{
list
.
add
(
getPath
(
n
));
if
(!
n
.
equals
(
name
)
&&
n
.
indexOf
(
'/'
,
name
.
length
()
+
1
)
<
0
)
{
list
.
add
(
getPath
(
n
));
}
}
else
{
break
;
}
...
...
@@ -120,10 +123,9 @@ public class FilePathMem extends FilePath {
if
(
isRoot
())
{
return
true
;
}
// TODO in memory file system currently
// does not really support directories
synchronized
(
MEMORY_FILES
)
{
return
MEMORY_FILES
.
get
(
name
)
==
null
;
FileMemData
d
=
MEMORY_FILES
.
get
(
name
);
return
d
==
DIRECTORY
;
}
}
...
...
@@ -145,10 +147,12 @@ public class FilePathMem extends FilePath {
@Override
public
void
createDirectory
()
{
if
(
exists
()
&&
isDirectory
()
)
{
if
(
exists
())
{
throw
DbException
.
get
(
ErrorCode
.
FILE_CREATION_FAILED_1
,
name
+
" (a file with this name already exists)"
);
}
// TODO directories are not really supported
synchronized
(
MEMORY_FILES
)
{
MEMORY_FILES
.
put
(
name
,
DIRECTORY
);
}
}
@Override
...
...
@@ -174,6 +178,9 @@ public class FilePathMem extends FilePath {
private
FileMemData
getMemoryFile
()
{
synchronized
(
MEMORY_FILES
)
{
FileMemData
m
=
MEMORY_FILES
.
get
(
name
);
if
(
m
==
DIRECTORY
)
{
throw
DbException
.
get
(
ErrorCode
.
FILE_CREATION_FAILED_1
,
name
+
" (a directory with this name already exists)"
);
}
if
(
m
==
null
)
{
m
=
new
FileMemData
(
name
,
compressed
());
MEMORY_FILES
.
put
(
name
,
m
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/fs/FilePathRec.java
浏览文件 @
152f7ba7
...
...
@@ -154,6 +154,11 @@ class FileRec extends FileBase {
return
channel
.
read
(
dst
);
}
@Override
public
int
read
(
ByteBuffer
dst
,
long
position
)
throws
IOException
{
return
channel
.
read
(
dst
,
position
);
}
@Override
public
FileChannel
position
(
long
pos
)
throws
IOException
{
channel
.
position
(
pos
);
...
...
@@ -185,6 +190,20 @@ class FileRec extends FileBase {
rec
.
log
(
Recorder
.
WRITE
,
name
,
buff
,
channel
.
position
());
return
result
;
}
@Override
public
int
write
(
ByteBuffer
src
,
long
position
)
throws
IOException
{
byte
[]
buff
=
src
.
array
();
int
len
=
src
.
remaining
();
if
(
src
.
position
()
!=
0
||
len
!=
buff
.
length
)
{
byte
[]
b
=
new
byte
[
len
];
System
.
arraycopy
(
buff
,
src
.
arrayOffset
()
+
src
.
position
(),
b
,
0
,
len
);
buff
=
b
;
}
int
result
=
channel
.
write
(
src
,
position
);
rec
.
log
(
Recorder
.
WRITE
,
name
,
buff
,
position
);
return
result
;
}
@Override
public
synchronized
FileLock
tryLock
(
long
position
,
long
size
,
boolean
shared
)
throws
IOException
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/db/TestFullText.java
浏览文件 @
152f7ba7
...
...
@@ -57,26 +57,28 @@ public class TestFullText extends TestBase {
testPerformance
(
false
);
testReopen
(
false
);
testDropIndex
(
false
);
try
{
Class
.
forName
(
LUCENE_FULLTEXT_CLASS_NAME
);
testCreateDropLucene
();
testUuidPrimaryKey
(
true
);
testMultiThreaded
(
true
);
testMultiThreaded
(
false
);
testTransaction
(
true
);
test
(
true
,
"VARCHAR"
);
test
(
true
,
"CLOB"
);
testPerformance
(
true
);
testReopen
(
true
);
testDropIndex
(
true
);
}
catch
(
ClassNotFoundException
e
)
{
println
(
"Class not found, not tested: "
+
LUCENE_FULLTEXT_CLASS_NAME
);
// ok
}
catch
(
NoClassDefFoundError
e
)
{
println
(
"Class not found, not tested: "
+
LUCENE_FULLTEXT_CLASS_NAME
);
// ok
if
(!
config
.
reopen
)
{
try
{
Class
.
forName
(
LUCENE_FULLTEXT_CLASS_NAME
);
testCreateDropLucene
();
testUuidPrimaryKey
(
true
);
testMultiThreaded
(
true
);
testMultiThreaded
(
false
);
testTransaction
(
true
);
test
(
true
,
"VARCHAR"
);
test
(
true
,
"CLOB"
);
testPerformance
(
true
);
testReopen
(
true
);
testDropIndex
(
true
);
}
catch
(
ClassNotFoundException
e
)
{
println
(
"Class not found, not tested: "
+
LUCENE_FULLTEXT_CLASS_NAME
);
// ok
}
catch
(
NoClassDefFoundError
e
)
{
println
(
"Class not found, not tested: "
+
LUCENE_FULLTEXT_CLASS_NAME
);
// ok
}
FullText
.
closeAll
();
}
FullText
.
closeAll
();
deleteDb
(
"fullText"
);
deleteDb
(
"fullTextReopen"
);
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestKillProcessWhileWriting.java
浏览文件 @
152f7ba7
...
...
@@ -9,7 +9,6 @@ import java.util.Random;
import
org.h2.mvstore.MVMap
;
import
org.h2.mvstore.MVStore
;
import
org.h2.store.fs.FilePathCrypt
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.test.TestBase
;
import
org.h2.test.utils.FilePathUnstable
;
...
...
@@ -29,28 +28,33 @@ public class TestKillProcessWhileWriting extends TestBase {
* @param a ignored
*/
public
static
void
main
(
String
...
a
)
throws
Exception
{
TestBase
.
createCaller
().
init
().
test
();
TestBase
test
=
TestBase
.
createCaller
().
init
();
test
.
config
.
big
=
true
;
test
.
test
();
}
@Override
public
void
test
()
throws
Exception
{
fs
=
FilePathUnstable
.
register
();
fs
.
setPartialWrites
(
false
);
test
(
"unstable:memFS:killProcess.h3"
);
i
nt
todo
;
// need to test with a file system splits writes into blocks of 4 KB
FilePathCrypt
.
register
(
);
test
(
"unstable:crypt:0007:memFS:killProcess.h3"
);
i
f
(
config
.
big
)
{
fs
.
setPartialWrites
(
true
);
test
(
"unstable:memFS:killProcess.h3"
);
}
}
private
void
test
(
String
fileName
)
throws
Exception
{
for
(
seed
=
0
;
seed
<
10
;
seed
++)
{
this
.
fileName
=
fileName
;
fs
.
setSeed
(
seed
);
FileUtils
.
delete
(
fileName
);
test
(
Integer
.
MAX_VALUE
);
int
max
=
Integer
.
MAX_VALUE
-
fs
.
getDiskFullCount
()
+
10
;
assertTrue
(
""
+
(
max
-
10
),
max
>
0
);
for
(
int
i
=
0
;
i
<
max
;
i
++)
{
fs
.
setSeed
(
seed
);
test
(
i
);
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/unit/TestReopen.java
浏览文件 @
152f7ba7
...
...
@@ -71,7 +71,8 @@ public class TestReopen extends TestBase implements Recorder {
if
(
op
!=
Recorder
.
WRITE
&&
op
!=
Recorder
.
TRUNCATE
)
{
return
;
}
if
(!
fileName
.
endsWith
(
Constants
.
SUFFIX_PAGE_FILE
))
{
if
(!
fileName
.
endsWith
(
Constants
.
SUFFIX_PAGE_FILE
)
&&
!
fileName
.
endsWith
(
Constants
.
SUFFIX_MV_FILE
))
{
return
;
}
if
(
testing
)
{
...
...
@@ -98,14 +99,22 @@ public class TestReopen extends TestBase implements Recorder {
System
.
out
.
println
(
"+ write #"
+
writeCount
+
" verify #"
+
verifyCount
);
try
{
IOUtils
.
copyFiles
(
fileName
,
testDatabase
+
Constants
.
SUFFIX_PAGE_FILE
);
if
(
fileName
.
endsWith
(
Constants
.
SUFFIX_PAGE_FILE
))
{
IOUtils
.
copyFiles
(
fileName
,
testDatabase
+
Constants
.
SUFFIX_PAGE_FILE
);
}
else
{
IOUtils
.
copyFiles
(
fileName
,
testDatabase
+
Constants
.
SUFFIX_MV_FILE
);
}
verifyCount
++;
// avoid using the Engine class to avoid deadlocks
Properties
p
=
new
Properties
();
String
userName
=
getUser
();
p
.
setProperty
(
"user"
,
userName
);
p
.
setProperty
(
"password"
,
getPassword
());
ConnectionInfo
ci
=
new
ConnectionInfo
(
"jdbc:h2:"
+
testDatabase
+
";FILE_LOCK=NO;TRACE_LEVEL_FILE=0"
,
p
);
String
url
=
"jdbc:h2:"
+
testDatabase
+
";FILE_LOCK=NO;TRACE_LEVEL_FILE=0"
;
if
(
config
.
mvStore
)
{
url
+=
";MV_STORE=TRUE"
;
}
ConnectionInfo
ci
=
new
ConnectionInfo
(
url
,
p
);
Database
database
=
new
Database
(
ci
,
null
);
// close the database
Session
session
=
database
.
getSystemSession
();
...
...
@@ -145,10 +154,18 @@ public class TestReopen extends TestBase implements Recorder {
}
testDatabase
+=
"X"
;
try
{
IOUtils
.
copyFiles
(
fileName
,
testDatabase
+
Constants
.
SUFFIX_PAGE_FILE
);
if
(
fileName
.
endsWith
(
Constants
.
SUFFIX_PAGE_FILE
))
{
IOUtils
.
copyFiles
(
fileName
,
testDatabase
+
Constants
.
SUFFIX_PAGE_FILE
);
}
else
{
IOUtils
.
copyFiles
(
fileName
,
testDatabase
+
Constants
.
SUFFIX_MV_FILE
);
}
// avoid using the Engine class to avoid deadlocks
Properties
p
=
new
Properties
();
ConnectionInfo
ci
=
new
ConnectionInfo
(
"jdbc:h2:"
+
testDatabase
+
";FILE_LOCK=NO"
,
p
);
String
url
=
"jdbc:h2:"
+
testDatabase
+
";FILE_LOCK=NO"
;
if
(
config
.
mvStore
)
{
url
+=
";MV_STORE=TRUE"
;
}
ConnectionInfo
ci
=
new
ConnectionInfo
(
url
,
p
);
Database
database
=
new
Database
(
ci
,
null
);
// close the database
database
.
removeSession
(
null
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/utils/FilePathUnstable.java
浏览文件 @
152f7ba7
...
...
@@ -13,6 +13,8 @@ import java.nio.ByteBuffer;
import
java.nio.channels.FileChannel
;
import
java.nio.channels.FileLock
;
import
java.util.List
;
import
java.util.Random
;
import
org.h2.store.fs.FileBase
;
import
org.h2.store.fs.FilePath
;
import
org.h2.store.fs.FilePathWrapper
;
...
...
@@ -28,6 +30,10 @@ public class FilePathUnstable extends FilePathWrapper {
private
static
final
IOException
DISK_FULL
=
new
IOException
(
"Disk full"
);
private
static
int
diskFullOffCount
;
private
static
boolean
partialWrites
;
private
static
Random
random
=
new
Random
(
1
);
/**
* Register the file system.
...
...
@@ -38,6 +44,42 @@ public class FilePathUnstable extends FilePathWrapper {
FilePath
.
register
(
INSTANCE
);
return
INSTANCE
;
}
/**
* Whether partial writes are possible (writing only part of the data).
*
* @param partialWrites true to enable
*/
public
void
setPartialWrites
(
boolean
partialWrites
)
{
FilePathUnstable
.
partialWrites
=
partialWrites
;
}
boolean
getPartialWrites
()
{
return
partialWrites
;
}
/**
* Set the random seed.
*
* @param seed the new seed
*/
public
void
setSeed
(
long
seed
)
{
random
.
setSeed
(
seed
);
}
/**
* Get a buffer with a subset (the head) of the data of the source buffer.
*
* @param src the source buffer
* @return a buffer with a subset of the data
*/
ByteBuffer
getRandomSubset
(
ByteBuffer
src
)
{
int
len
=
src
.
remaining
();
len
=
Math
.
min
(
4096
,
Math
.
min
(
len
,
1
+
random
.
nextInt
(
len
)));
ByteBuffer
temp
=
ByteBuffer
.
allocate
(
len
);
src
.
get
(
temp
.
array
());
return
temp
;
}
/**
* Check if the simulated problem occurred.
...
...
@@ -52,7 +94,7 @@ public class FilePathUnstable extends FilePathWrapper {
if
(--
diskFullOffCount
>
0
)
{
return
;
}
if
(
diskFullOffCount
>=
-
4
)
{
if
(
diskFullOffCount
>=
-
1
)
{
diskFullOffCount
--;
throw
DISK_FULL
;
}
...
...
@@ -231,12 +273,18 @@ class FileUnstable extends FileBase {
@Override
public
int
write
(
ByteBuffer
src
)
throws
IOException
{
checkError
();
if
(
file
.
getPartialWrites
())
{
return
channel
.
write
(
file
.
getRandomSubset
(
src
));
}
return
channel
.
write
(
src
);
}
@Override
public
int
write
(
ByteBuffer
src
,
long
position
)
throws
IOException
{
checkError
();
if
(
file
.
getPartialWrites
())
{
return
channel
.
write
(
file
.
getRandomSubset
(
src
),
position
);
}
return
channel
.
write
(
src
,
position
);
}
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论