Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
d056ce9c
提交
d056ce9c
authored
11 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
MVStore bugfixes
上级
43e1956c
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
132 行增加
和
48 行删除
+132
-48
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+52
-30
MVStoreTool.java
h2/src/main/org/h2/mvstore/MVStoreTool.java
+52
-3
TestMVStore.java
h2/src/test/org/h2/test/store/TestMVStore.java
+3
-0
TestRandomMapOps.java
h2/src/test/org/h2/test/store/TestRandomMapOps.java
+25
-15
没有找到文件。
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
d056ce9c
...
...
@@ -108,6 +108,7 @@ MVStore:
(by truncating / deleting empty files)
- 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?
*/
...
...
@@ -513,40 +514,50 @@ public class MVStore {
}
private
void
readMeta
()
{
chunks
.
clear
();
Chunk
header
=
readChunkHeader
(
rootChunkStart
);
lastChunkId
=
header
.
id
;
chunks
.
put
(
header
.
id
,
header
);
meta
.
setRootPos
(
header
.
metaRootPos
,
-
1
);
// load chunks in reverse order, because data about previous chunks
// might only be available in later chunks
// if this is a performance problem when there are many
// chunks, the id of the previous / next chunk might need to
// be maintained
for
(
int
id
=
lastChunkId
;
id
>=
0
;
id
--)
{
String
s
=
meta
.
get
(
"chunk."
+
id
);
if
(
s
==
null
)
{
continue
;
String
s
=
meta
.
get
(
"chunk."
+
lastChunkId
);
Chunk
h2
=
Chunk
.
fromString
(
s
);
h2
.
start
=
header
.
start
;
h2
.
length
=
header
.
length
;
h2
.
metaRootPos
=
header
.
metaRootPos
;
h2
.
pageCount
=
header
.
pageCount
;
h2
.
pageCountLive
=
header
.
pageCountLive
;
h2
.
maxLength
=
header
.
maxLength
;
h2
.
maxLengthLive
=
header
.
maxLengthLive
;
chunks
.
put
(
header
.
id
,
h2
);
// we can load the chunk in any order,
// because loading chunk metadata
// might recursively load another chunk
for
(
Iterator
<
String
>
it
=
meta
.
keyIterator
(
"chunk."
);
it
.
hasNext
();)
{
s
=
it
.
next
();
if
(!
s
.
startsWith
(
"chunk."
))
{
break
;
}
s
=
meta
.
get
(
s
);
Chunk
c
=
Chunk
.
fromString
(
s
);
if
(
c
.
id
==
header
.
id
)
{
c
.
start
=
header
.
start
;
c
.
length
=
header
.
length
;
c
.
metaRootPos
=
header
.
metaRootPos
;
c
.
pageCount
=
header
.
pageCount
;
c
.
pageCountLive
=
header
.
pageCountLive
;
c
.
maxLength
=
header
.
maxLength
;
c
.
maxLengthLive
=
header
.
maxLengthLive
;
if
(!
chunks
.
containsKey
(
c
.
id
))
{
chunks
.
put
(
c
.
id
,
c
);
}
lastChunkId
=
Math
.
max
(
c
.
id
,
lastChunkId
);
chunks
.
put
(
c
.
id
,
c
);
}
// build the free space list
for
(
Chunk
c
:
chunks
.
values
())
{
if
(
c
.
pageCountLive
==
0
)
{
// remove this chunk in the next save operation
registerFreePage
(
currentVersion
,
c
.
id
,
0
,
0
);
}
}
// build the free space list
for
(
Chunk
c
:
chunks
.
values
())
{
if
(
c
.
id
>
lastChunkId
)
{
System
.
out
.
println
(
"strange!"
);
}
lastChunkId
=
Math
.
max
(
c
.
id
,
lastChunkId
);
if
(
c
.
start
==
Long
.
MAX_VALUE
)
{
;;
System
.
out
.
println
(
"??"
);
continue
;
}
int
len
=
MathUtils
.
roundUpInt
(
c
.
length
,
BLOCK_SIZE
)
+
BLOCK_SIZE
;
...
...
@@ -711,7 +722,20 @@ public class MVStore {
* @return the chunk
*/
Chunk
getChunk
(
long
pos
)
{
return
chunks
.
get
(
DataUtils
.
getPageChunkId
(
pos
));
int
chunkId
=
DataUtils
.
getPageChunkId
(
pos
);
Chunk
c
=
chunks
.
get
(
chunkId
);
if
(
c
==
null
)
{
String
s
=
meta
.
get
(
"chunk."
+
chunkId
);
if
(
s
==
null
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_FILE_CORRUPT
,
"Chunk {0} not found"
,
DataUtils
.
getPageChunkId
(
pos
));
}
c
=
Chunk
.
fromString
(
s
);
chunks
.
put
(
c
.
id
,
c
);
}
return
c
;
}
/**
...
...
@@ -1358,7 +1382,7 @@ public class MVStore {
if
(
p
==
null
)
{
// was removed later - ignore
// or the chunk no longer exists
}
else
if
(
p
.
getPos
()
<
0
)
{
}
else
if
(
p
.
getPos
()
==
0
)
{
// temporarily changed - ok
// TODO move old data if there is an uncommitted change?
}
else
{
...
...
@@ -1390,14 +1414,12 @@ public class MVStore {
Page
p
=
cache
.
get
(
pos
);
if
(
p
==
null
)
{
Chunk
c
=
getChunk
(
pos
);
if
(
c
==
null
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_FILE_CORRUPT
,
"Chunk {0} not found"
,
DataUtils
.
getPageChunkId
(
pos
));
}
long
filePos
=
c
.
start
;
filePos
+=
DataUtils
.
getPageOffset
(
pos
);
if
(
filePos
<
0
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_FILE_CORRUPT
,
"Negative position {0}"
,
filePos
);
}
p
=
Page
.
read
(
fileStore
,
map
,
pos
,
filePos
,
fileStore
.
size
());
cache
.
put
(
pos
,
p
,
p
.
getMemory
());
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/MVStoreTool.java
浏览文件 @
d056ce9c
...
...
@@ -11,6 +11,8 @@ import java.io.PrintWriter;
import
java.io.Writer
;
import
java.nio.ByteBuffer
;
import
java.nio.channels.FileChannel
;
import
org.h2.mvstore.type.StringDataType
;
import
org.h2.store.fs.FilePath
;
/**
...
...
@@ -36,6 +38,15 @@ public class MVStoreTool {
}
}
}
/**
* Read the contents of the file and write them to system out.
*
* @param fileName the name of the file
*/
public
static
void
dump
(
String
fileName
)
{
dump
(
fileName
,
new
PrintWriter
(
System
.
out
));
}
/**
* Read the contents of the file and display them in a human-readable
...
...
@@ -83,9 +94,7 @@ public class MVStoreTool {
" at "
+
pos
+
" length "
+
chunkLength
+
" pageCount "
+
pageCount
+
" root "
+
metaRootPos
+
" chunk "
+
DataUtils
.
getPageChunkId
(
metaRootPos
)
+
" offset "
+
DataUtils
.
getPageOffset
(
metaRootPos
)
+
" root "
+
getPosString
(
metaRootPos
)
+
" maxLength "
+
maxLength
+
" maxLengthLive "
+
maxLengthLive
);
ByteBuffer
chunk
=
ByteBuffer
.
allocate
(
chunkLength
);
...
...
@@ -109,6 +118,40 @@ public class MVStoreTool {
"len: "
+
pageLength
+
" entries: "
+
len
);
p
+=
pageLength
;
chunkLength
-=
pageLength
;
if
(
mapId
==
0
&&
!
compressed
)
{
String
[]
keys
=
new
String
[
len
];
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
String
k
=
StringDataType
.
INSTANCE
.
read
(
chunk
);
keys
[
i
]
=
k
;
}
if
(
node
)
{
long
[]
children
=
new
long
[
len
+
1
];
for
(
int
i
=
0
;
i
<=
len
;
i
++)
{
children
[
i
]
=
chunk
.
getLong
();
}
long
[]
counts
=
new
long
[
len
+
1
];
for
(
int
i
=
0
;
i
<=
len
;
i
++)
{
long
s
=
DataUtils
.
readVarLong
(
chunk
);
counts
[
i
]
=
s
;
}
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
pw
.
println
(
" < "
+
keys
[
i
]
+
": "
+
counts
[
i
]
+
" -> "
+
getPosString
(
children
[
i
]));
}
pw
.
println
(
" >= : "
+
counts
[
len
]
+
" -> "
+
getPosString
(
children
[
len
]));
}
else
{
// meta map leaf
String
[]
values
=
new
String
[
len
];
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
String
v
=
StringDataType
.
INSTANCE
.
read
(
chunk
);
values
[
i
]
=
v
;
}
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
pw
.
println
(
" "
+
keys
[
i
]
+
"="
+
values
[
i
]);
}
}
}
}
}
}
catch
(
IOException
e
)
{
...
...
@@ -126,5 +169,11 @@ public class MVStoreTool {
pw
.
println
();
pw
.
flush
();
}
private
static
String
getPosString
(
long
pos
)
{
return
"pos "
+
pos
+
", chunk "
+
DataUtils
.
getPageChunkId
(
pos
)
+
", offset "
+
DataUtils
.
getPageOffset
(
pos
);
}
}
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMVStore.java
浏览文件 @
d056ce9c
...
...
@@ -65,7 +65,10 @@ public class TestMVStore extends TestBase {
testCacheSize
();
testConcurrentOpen
();
testFileHeader
();
int
todoFixTestCase
;
// testFileHeaderCorruption();
testIndexSkip
();
testMinMaxNextKey
();
testStoreVersion
();
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestRandomMapOps.java
浏览文件 @
d056ce9c
...
...
@@ -66,6 +66,7 @@ public class TestRandomMapOps extends TestBase {
bestSeed
=
seed
;
best
=
op
;
failException
=
ex
;
// System.out.println("seed:" + seed + " op:" + op);
}
}
if
(
failException
!=
null
)
{
...
...
@@ -77,15 +78,13 @@ public class TestRandomMapOps extends TestBase {
private
void
testCase
()
throws
Exception
{
FileUtils
.
delete
(
fileName
);
MVStore
s
;
s
=
new
MVStore
.
Builder
().
fileName
(
fileName
).
pageSplitSize
(
50
).
writeDelay
(
0
).
open
();
s
=
openStore
(
fileName
);
MVMap
<
Integer
,
byte
[]>
m
;
if
(
concurrent
)
{
m
=
s
.
openMap
(
"data"
,
new
MVMapConcurrent
.
Builder
<
Integer
,
byte
[]>());
}
else
{
m
=
s
.
openMap
(
"data"
);
}
Random
r
=
new
Random
(
seed
);
op
=
0
;
int
size
=
getSize
(
100
,
1000
);
...
...
@@ -99,48 +98,51 @@ public class TestRandomMapOps extends TestBase {
case
1
:
case
2
:
case
3
:
log
(
op
,
k
,
v
,
"
put
"
);
log
(
op
,
k
,
v
,
"
m.put({0}, {1})
"
);
m
.
put
(
k
,
v
);
map
.
put
(
k
,
v
);
break
;
case
4
:
case
5
:
log
(
op
,
k
,
v
,
"
remove
"
);
log
(
op
,
k
,
v
,
"
m.remove({0})
"
);
m
.
remove
(
k
);
map
.
remove
(
k
);
break
;
case
6
:
log
(
op
,
k
,
v
,
"s
tore
"
);
log
(
op
,
k
,
v
,
"s
.store()
"
);
s
.
store
();
break
;
case
7
:
log
(
op
,
k
,
v
,
"
compact
"
);
log
(
op
,
k
,
v
,
"
s.compact(90)
"
);
s
.
compact
(
90
);
break
;
case
8
:
log
(
op
,
k
,
v
,
"
clear
"
);
log
(
op
,
k
,
v
,
"
m.clear()
"
);
m
.
clear
();
map
.
clear
();
break
;
case
9
:
log
(
op
,
k
,
v
,
"
commit
"
);
log
(
op
,
k
,
v
,
"
s.commit()
"
);
s
.
commit
();
break
;
case
10
:
log
(
op
,
k
,
v
,
"
reopen
"
);
log
(
op
,
k
,
v
,
"
s.commit()
"
);
s
.
commit
();
log
(
op
,
k
,
v
,
"s.close()"
);
s
.
close
();
s
=
new
MVStore
.
Builder
().
fileName
(
fileName
).
pageSplitSize
(
50
).
writeDelay
(
0
).
open
();
log
(
op
,
k
,
v
,
"s = openStore(fileName)"
);
s
=
openStore
(
fileName
);
log
(
op
,
k
,
v
,
"m = s.openMap(\"data\")"
);
m
=
s
.
openMap
(
"data"
);
break
;
case
11
:
log
(
op
,
k
,
v
,
"
compactMoveChunks
"
);
log
(
op
,
k
,
v
,
"
s.commit()
"
);
s
.
commit
();
log
(
op
,
k
,
v
,
"s.compactMoveChunks()"
);
s
.
compactMoveChunks
();
break
;
case
12
:
log
(
op
,
k
,
v
,
"
getKeyIndex
"
);
log
(
op
,
k
,
v
,
"
m.getKeyIndex({0})
"
);
ArrayList
<
Integer
>
keyList
=
new
ArrayList
<
Integer
>(
map
.
keySet
());
int
index
=
Collections
.
binarySearch
(
keyList
,
k
,
null
);
int
index2
=
(
int
)
m
.
getKeyIndex
(
k
);
...
...
@@ -167,6 +169,11 @@ public class TestRandomMapOps extends TestBase {
s
.
close
();
}
private
static
MVStore
openStore
(
String
fileName
)
{
return
new
MVStore
.
Builder
().
fileName
(
fileName
).
pageSplitSize
(
50
).
writeDelay
(
0
).
open
();
}
private
void
assertEqualsMapValues
(
byte
[]
x
,
byte
[]
y
)
{
if
(
x
==
null
||
y
==
null
)
{
if
(
x
!=
y
)
{
...
...
@@ -186,7 +193,10 @@ public class TestRandomMapOps extends TestBase {
* @param msg the message
*/
private
static
void
log
(
int
op
,
int
k
,
byte
[]
v
,
String
msg
)
{
// System.out.println(op + ": " + msg + " key: " + k + " value: " + v);
// msg = MessageFormat.format(msg, k,
// v == null ? null : "new byte[" + v.length + "]");
// System.out.println(msg + "; // op " + op);
}
}
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论