Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
09769f17
提交
09769f17
authored
12 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
MVStore: larger stores (multiple GB) are now much faster.
上级
f8db2f80
全部展开
显示空白字符变更
内嵌
并排
正在显示
13 个修改的文件
包含
261 行增加
和
426 行删除
+261
-426
changelog.html
h2/src/docsrc/html/changelog.html
+2
-1
ChangeCursor.java
h2/src/main/org/h2/mvstore/ChangeCursor.java
+0
-222
Chunk.java
h2/src/main/org/h2/mvstore/Chunk.java
+9
-1
FreeSpaceList.java
h2/src/main/org/h2/mvstore/FreeSpaceList.java
+83
-41
MVMap.java
h2/src/main/org/h2/mvstore/MVMap.java
+0
-12
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+105
-72
Page.java
h2/src/main/org/h2/mvstore/Page.java
+5
-1
TransactionStore.java
h2/src/main/org/h2/mvstore/TransactionStore.java
+6
-3
MVTableEngine.java
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
+2
-1
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+4
-0
TestBase.java
h2/src/test/org/h2/test/TestBase.java
+3
-3
TestMVStore.java
h2/src/test/org/h2/test/store/TestMVStore.java
+35
-62
TestMVTableEngine.java
h2/src/test/org/h2/test/store/TestMVTableEngine.java
+7
-7
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
09769f17
...
@@ -18,7 +18,8 @@ Change Log
...
@@ -18,7 +18,8 @@ Change Log
<h1>
Change Log
</h1>
<h1>
Change Log
</h1>
<h2>
Next Version (unreleased)
</h2>
<h2>
Next Version (unreleased)
</h2>
<ul><li>
When using local temporary tables and not dropping them manually before closing the session,
<ul><li>
MVStore: larger stores (multiple GB) are now much faster.
</li><li>
When using local temporary tables and not dropping them manually before closing the session,
and then killing the process could result in a database that couldn't be opened (except when using
and then killing the process could result in a database that couldn't be opened (except when using
the recover tool).
the recover tool).
</li><li>
Support TRUNC(timestamp) for improved Oracle compatiblity.
</li><li>
Support TRUNC(timestamp) for improved Oracle compatiblity.
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/ChangeCursor.java
deleted
100644 → 0
浏览文件 @
f8db2f80
/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
mvstore
;
import
java.util.Iterator
;
/**
* A cursor to iterate over all keys in new pages.
*
* @param <K> the key type
* @param <V> the value type
*/
public
class
ChangeCursor
<
K
,
V
>
implements
Iterator
<
K
>
{
private
final
MVMap
<
K
,
V
>
map
;
private
final
Page
root1
,
root2
;
/**
* The state of this cursor.
* 0: not initialized
* 1: reading from root1
* 2: reading from root2
* 3: closed
*/
private
int
state
;
private
CursorPos
pos1
,
pos2
;
private
K
current
;
ChangeCursor
(
MVMap
<
K
,
V
>
map
,
Page
root1
,
Page
root2
)
{
this
.
map
=
map
;
this
.
root1
=
root1
;
this
.
root2
=
root2
;
}
public
K
next
()
{
K
c
=
current
;
fetchNext
();
return
c
;
}
public
boolean
hasNext
()
{
if
(
state
==
0
)
{
pos1
=
new
CursorPos
(
root1
,
0
,
null
);
pos1
=
min
(
pos1
);
state
=
1
;
fetchNext
();
}
return
current
!=
null
;
}
public
void
remove
()
{
throw
DataUtils
.
newUnsupportedOperationException
(
"Removing is not supported"
);
}
private
void
fetchNext
()
{
while
(
fetchNextKey
())
{
if
(
pos1
==
null
||
pos2
==
null
)
{
break
;
}
@SuppressWarnings
(
"unchecked"
)
V
v1
=
(
V
)
map
.
binarySearch
(
root1
,
current
);
@SuppressWarnings
(
"unchecked"
)
V
v2
=
(
V
)
map
.
binarySearch
(
root2
,
current
);
if
(!
v1
.
equals
(
v2
))
{
break
;
}
}
}
private
boolean
fetchNextKey
()
{
while
(
true
)
{
if
(
state
==
3
)
{
return
false
;
}
if
(
state
==
1
)
{
// read from root1
pos1
=
fetchNext
(
pos1
);
if
(
pos1
==
null
)
{
// reached the end of pos1
state
=
2
;
pos2
=
null
;
continue
;
}
pos2
=
find
(
root2
,
current
);
if
(
pos2
==
null
)
{
// not found in root2
return
true
;
}
if
(!
pos1
.
page
.
equals
(
pos2
.
page
))
{
// the page is different,
// so the entry has possibly changed
return
true
;
}
while
(
true
)
{
pos1
=
pos1
.
parent
;
if
(
pos1
==
null
)
{
// reached end of pos1
state
=
2
;
pos2
=
null
;
break
;
}
pos2
=
pos2
.
parent
;
if
(
pos2
==
null
||
!
pos1
.
page
.
equals
(
pos2
.
page
))
{
if
(
pos1
.
index
+
1
<
map
.
getChildPageCount
(
pos1
.
page
))
{
pos1
=
new
CursorPos
(
pos1
.
page
.
getChildPage
(++
pos1
.
index
),
0
,
pos1
);
pos1
=
min
(
pos1
);
break
;
}
}
}
}
if
(
state
==
2
)
{
if
(
pos2
==
null
)
{
// init reading from root2
pos2
=
new
CursorPos
(
root2
,
0
,
null
);
pos2
=
min
(
pos2
);
}
// read from root2
pos2
=
fetchNext
(
pos2
);
if
(
pos2
==
null
)
{
// reached the end of pos2
state
=
3
;
current
=
null
;
continue
;
}
pos1
=
find
(
root1
,
current
);
if
(
pos1
!=
null
)
{
// found a corresponding record
// so it was not deleted
// but now we may need to skip pages
if
(!
pos1
.
page
.
equals
(
pos2
.
page
))
{
// the page is different
pos1
=
null
;
continue
;
}
while
(
true
)
{
pos2
=
pos2
.
parent
;
if
(
pos2
==
null
)
{
// reached end of pos1
state
=
3
;
current
=
null
;
pos1
=
null
;
break
;
}
pos1
=
pos1
.
parent
;
if
(
pos1
==
null
||
!
pos2
.
page
.
equals
(
pos1
.
page
))
{
if
(
pos2
.
index
+
1
<
map
.
getChildPageCount
(
pos2
.
page
))
{
pos2
=
new
CursorPos
(
pos2
.
page
.
getChildPage
(++
pos2
.
index
),
0
,
pos2
);
pos2
=
min
(
pos2
);
break
;
}
}
}
pos1
=
null
;
continue
;
}
// found no corresponding record
// so it was deleted
return
true
;
}
}
}
private
CursorPos
find
(
Page
p
,
K
key
)
{
// TODO combine with RangeCursor.min
// possibly move to MVMap
CursorPos
pos
=
null
;
while
(
true
)
{
if
(
p
.
isLeaf
())
{
int
x
=
key
==
null
?
0
:
p
.
binarySearch
(
key
);
if
(
x
<
0
)
{
return
null
;
}
return
new
CursorPos
(
p
,
x
,
pos
);
}
int
x
=
key
==
null
?
-
1
:
p
.
binarySearch
(
key
);
if
(
x
<
0
)
{
x
=
-
x
-
1
;
}
else
{
x
++;
}
pos
=
new
CursorPos
(
p
,
x
,
pos
);
p
=
p
.
getChildPage
(
x
);
}
}
@SuppressWarnings
(
"unchecked"
)
private
CursorPos
fetchNext
(
CursorPos
p
)
{
while
(
p
!=
null
)
{
if
(
p
.
index
<
p
.
page
.
getKeyCount
())
{
current
=
(
K
)
p
.
page
.
getKey
(
p
.
index
++);
return
p
;
}
p
=
p
.
parent
;
if
(
p
==
null
)
{
break
;
}
if
(
p
.
index
+
1
<
map
.
getChildPageCount
(
p
.
page
))
{
p
=
new
CursorPos
(
p
.
page
.
getChildPage
(++
p
.
index
),
0
,
p
);
p
=
min
(
p
);
}
}
current
=
null
;
return
p
;
}
private
static
CursorPos
min
(
CursorPos
p
)
{
while
(
true
)
{
if
(
p
.
page
.
isLeaf
())
{
return
p
;
}
Page
c
=
p
.
page
.
getChildPage
(
0
);
p
=
new
CursorPos
(
c
,
0
,
p
);
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/Chunk.java
浏览文件 @
09769f17
...
@@ -42,10 +42,15 @@ public class Chunk {
...
@@ -42,10 +42,15 @@ public class Chunk {
int
length
;
int
length
;
/**
/**
* The
number of pages
.
* The
total number of pages in this chunk
.
*/
*/
int
pageCount
;
int
pageCount
;
/**
* The number of pages still alive.
*/
int
pageCountLive
;
/**
/**
* The sum of the max length of all pages.
* The sum of the max length of all pages.
*/
*/
...
@@ -101,6 +106,7 @@ public class Chunk {
...
@@ -101,6 +106,7 @@ public class Chunk {
Chunk
c
=
new
Chunk
(
chunkId
);
Chunk
c
=
new
Chunk
(
chunkId
);
c
.
length
=
length
;
c
.
length
=
length
;
c
.
pageCount
=
pageCount
;
c
.
pageCount
=
pageCount
;
c
.
pageCountLive
=
pageCount
;
c
.
start
=
start
;
c
.
start
=
start
;
c
.
metaRootPos
=
metaRootPos
;
c
.
metaRootPos
=
metaRootPos
;
c
.
maxLength
=
maxLength
;
c
.
maxLength
=
maxLength
;
...
@@ -136,6 +142,7 @@ public class Chunk {
...
@@ -136,6 +142,7 @@ public class Chunk {
c
.
start
=
Long
.
parseLong
(
map
.
get
(
"start"
));
c
.
start
=
Long
.
parseLong
(
map
.
get
(
"start"
));
c
.
length
=
Integer
.
parseInt
(
map
.
get
(
"length"
));
c
.
length
=
Integer
.
parseInt
(
map
.
get
(
"length"
));
c
.
pageCount
=
Integer
.
parseInt
(
map
.
get
(
"pageCount"
));
c
.
pageCount
=
Integer
.
parseInt
(
map
.
get
(
"pageCount"
));
c
.
pageCountLive
=
Integer
.
parseInt
(
map
.
get
(
"pageCountLive"
));
c
.
maxLength
=
Long
.
parseLong
(
map
.
get
(
"maxLength"
));
c
.
maxLength
=
Long
.
parseLong
(
map
.
get
(
"maxLength"
));
c
.
maxLengthLive
=
Long
.
parseLong
(
map
.
get
(
"maxLengthLive"
));
c
.
maxLengthLive
=
Long
.
parseLong
(
map
.
get
(
"maxLengthLive"
));
c
.
metaRootPos
=
Long
.
parseLong
(
map
.
get
(
"metaRoot"
));
c
.
metaRootPos
=
Long
.
parseLong
(
map
.
get
(
"metaRoot"
));
...
@@ -169,6 +176,7 @@ public class Chunk {
...
@@ -169,6 +176,7 @@ public class Chunk {
"maxLengthLive:"
+
maxLengthLive
+
","
+
"maxLengthLive:"
+
maxLengthLive
+
","
+
"metaRoot:"
+
metaRootPos
+
","
+
"metaRoot:"
+
metaRootPos
+
","
+
"pageCount:"
+
pageCount
+
","
+
"pageCount:"
+
pageCount
+
","
+
"pageCountLive:"
+
pageCountLive
+
","
+
"start:"
+
start
+
","
+
"start:"
+
start
+
","
+
"time:"
+
time
+
","
+
"time:"
+
time
+
","
+
"version:"
+
version
;
"version:"
+
version
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/FreeSpaceList.java
浏览文件 @
09769f17
/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
mvstore
;
package
org
.
h2
.
mvstore
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
/**
* A list that maintains ranges of free space (in pages) in a file.
*/
public
class
FreeSpaceList
{
public
class
FreeSpaceList
{
/** the first 2 pages are occupied by the file header. */
/**
* The first 2 pages are occupied by the file header.
*/
private
static
final
int
FIRST_FREE_PAGE
=
2
;
private
static
final
int
FIRST_FREE_PAGE
=
2
;
/** I use max_value/2 to avoid overflow errors during arithmetic. */
private
static
final
int
MAX_NO_PAGES
=
Integer
.
MAX_VALUE
/
2
;
/**
* The maximum number of pages. Smaller than than MAX_VALUE to avoid
* overflow errors during arithmetic operations.
*/
private
static
final
int
MAX_PAGE_COUNT
=
Integer
.
MAX_VALUE
/
2
;
private
List
<
PageRange
>
freeSpaceList
=
new
ArrayList
<
PageRange
>();
private
List
<
PageRange
>
freeSpaceList
=
new
ArrayList
<
PageRange
>();
public
FreeSpaceList
()
{
public
FreeSpaceList
()
{
freeSpaceList
.
add
(
new
PageRange
(
FIRST_FREE_PAGE
,
MAX_NO_PAGES
)
);
clear
(
);
}
}
private
static
final
class
PageRange
{
/**
/** the start point, in pages */
* Reset the list.
public
int
start
;
*/
/** the length, in pages */
public
synchronized
void
clear
()
{
public
int
length
;
freeSpaceList
.
clear
();
freeSpaceList
.
add
(
new
PageRange
(
FIRST_FREE_PAGE
,
MAX_PAGE_COUNT
));
public
PageRange
(
int
start
,
int
length
)
{
this
.
start
=
start
;
this
.
length
=
length
;
}
@Override
public
String
toString
()
{
return
"start:"
+
start
+
" length:"
+
length
;
}
}
}
/**
/**
* @return position in pages
* Allocate a number of pages.
*
* @param length the number of bytes to allocate
* @return the position in pages
*/
*/
public
synchronized
int
allocatePages
(
long
length
)
{
public
synchronized
int
allocatePages
(
long
length
)
{
int
required
=
(
int
)
(
length
/
MVStore
.
BLOCK_SIZE
)
+
1
;
int
required
=
(
int
)
(
length
/
MVStore
.
BLOCK_SIZE
)
+
1
;
...
@@ -43,9 +52,15 @@ public class FreeSpaceList {
...
@@ -43,9 +52,15 @@ public class FreeSpaceList {
return
pr
.
start
;
return
pr
.
start
;
}
}
}
}
throw
DataUtils
.
newIllegalStateException
(
"could not find a free page to allocate"
);
throw
DataUtils
.
newIllegalStateException
(
"Could not find a free page to allocate"
);
}
}
/**
* Mark a chunk as used.
*
* @param c the chunk
*/
public
synchronized
void
markUsed
(
Chunk
c
)
{
public
synchronized
void
markUsed
(
Chunk
c
)
{
int
chunkStart
=
(
int
)
(
c
.
start
/
MVStore
.
BLOCK_SIZE
);
int
chunkStart
=
(
int
)
(
c
.
start
/
MVStore
.
BLOCK_SIZE
);
int
required
=
(
int
)
((
c
.
start
+
c
.
length
)
/
MVStore
.
BLOCK_SIZE
)
+
2
-
chunkStart
;
int
required
=
(
int
)
((
c
.
start
+
c
.
length
)
/
MVStore
.
BLOCK_SIZE
)
+
2
-
chunkStart
;
...
@@ -59,11 +74,12 @@ public class FreeSpaceList {
...
@@ -59,11 +74,12 @@ public class FreeSpaceList {
i
++;
i
++;
}
}
if
(
found
==
null
)
{
if
(
found
==
null
)
{
throw
DataUtils
.
newIllegalStateException
(
"cannot find spot to mark chunk as used in free list, "
throw
DataUtils
.
newIllegalStateException
(
+
c
.
toString
()
);
"Cannot find spot to mark chunk as used in free list: {0}"
,
c
);
}
}
if
(
chunkStart
+
required
>
found
.
start
+
found
.
length
)
{
if
(
chunkStart
+
required
>
found
.
start
+
found
.
length
)
{
throw
DataUtils
.
newIllegalStateException
(
"chunk runs over edge of free space, "
+
c
.
toString
());
throw
DataUtils
.
newIllegalStateException
(
"Chunk runs over edge of free space: {0}"
,
c
);
}
}
if
(
found
.
start
==
chunkStart
)
{
if
(
found
.
start
==
chunkStart
)
{
// if the used-chunk is at the beginning of a free-space-range
// if the used-chunk is at the beginning of a free-space-range
...
@@ -92,6 +108,11 @@ public class FreeSpaceList {
...
@@ -92,6 +108,11 @@ public class FreeSpaceList {
}
}
}
}
/**
* Mark the chunk as free.
*
* @param c the chunk
*/
public
synchronized
void
markFree
(
Chunk
c
)
{
public
synchronized
void
markFree
(
Chunk
c
)
{
int
chunkStart
=
(
int
)
(
c
.
start
/
MVStore
.
BLOCK_SIZE
);
int
chunkStart
=
(
int
)
(
c
.
start
/
MVStore
.
BLOCK_SIZE
);
int
required
=
(
c
.
length
/
MVStore
.
BLOCK_SIZE
)
+
1
;
int
required
=
(
c
.
length
/
MVStore
.
BLOCK_SIZE
)
+
1
;
...
@@ -105,15 +126,15 @@ public class FreeSpaceList {
...
@@ -105,15 +126,15 @@ public class FreeSpaceList {
i
++;
i
++;
}
}
if
(
found
==
null
)
{
if
(
found
==
null
)
{
throw
DataUtils
.
newIllegalStateException
(
"cannot find spot to mark chunk as unused in free list, "
throw
DataUtils
.
newIllegalStateException
(
+
c
.
toString
()
);
"Cannot find spot to mark chunk as unused in free list: {0}"
,
c
);
}
}
if
(
chunkStart
+
required
+
1
==
found
.
start
)
{
if
(
chunkStart
+
required
+
1
==
found
.
start
)
{
// if the used-chunk is adjacent to the beginning of a
// if the used-chunk is adjacent to the beginning of a
// free-space-range
// free-space-range
found
.
start
=
chunkStart
;
found
.
start
=
chunkStart
;
found
.
length
+=
required
;
found
.
length
+=
required
;
// compact
ify-free-list
: merge the previous entry into this one if
// compact: merge the previous entry into this one if
// they are now adjacent
// they are now adjacent
if
(
i
>
0
)
{
if
(
i
>
0
)
{
PageRange
previous
=
freeSpaceList
.
get
(
i
-
1
);
PageRange
previous
=
freeSpaceList
.
get
(
i
-
1
);
...
@@ -129,7 +150,7 @@ public class FreeSpaceList {
...
@@ -129,7 +150,7 @@ public class FreeSpaceList {
PageRange
previous
=
freeSpaceList
.
get
(
i
-
1
);
PageRange
previous
=
freeSpaceList
.
get
(
i
-
1
);
if
(
previous
.
start
+
previous
.
length
+
1
==
chunkStart
)
{
if
(
previous
.
start
+
previous
.
length
+
1
==
chunkStart
)
{
previous
.
length
+=
required
;
previous
.
length
+=
required
;
// compact
ify-free-list
: merge the next entry into this one if
// compact: merge the next entry into this one if
// they are now adjacent
// they are now adjacent
if
(
previous
.
start
+
previous
.
length
+
1
==
found
.
start
)
{
if
(
previous
.
start
+
previous
.
length
+
1
==
found
.
start
)
{
previous
.
length
+=
found
.
length
;
previous
.
length
+=
found
.
length
;
...
@@ -144,23 +165,44 @@ public class FreeSpaceList {
...
@@ -144,23 +165,44 @@ public class FreeSpaceList {
freeSpaceList
.
add
(
i
,
newRange
);
freeSpaceList
.
add
(
i
,
newRange
);
}
}
public
synchronized
void
clear
()
{
public
String
toString
()
{
freeSpaceList
.
clear
();
StringBuilder
buff
=
new
StringBuilder
();
freeSpaceList
.
add
(
new
PageRange
(
FIRST_FREE_PAGE
,
MAX_NO_PAGES
));
}
/** debug method */
public
void
dumpFreeList
()
{
StringBuilder
buf
=
new
StringBuilder
(
"free list : "
);
boolean
first
=
true
;
boolean
first
=
true
;
for
(
PageRange
p
r
:
freeSpaceList
)
{
for
(
PageRange
r
:
freeSpaceList
)
{
if
(
first
)
{
if
(
first
)
{
first
=
false
;
first
=
false
;
}
else
{
}
else
{
buf
.
append
(
", "
);
buf
f
.
append
(
", "
);
}
}
buf
.
append
(
pr
.
start
+
"-"
+
(
pr
.
start
+
p
r
.
length
-
1
));
buf
f
.
append
(
r
.
start
+
"-"
+
(
r
.
start
+
r
.
length
-
1
));
}
}
System
.
out
.
println
(
buf
.
toString
()
);
return
buff
.
toString
(
);
}
}
/**
* A range of free pages.
*/
private
static
final
class
PageRange
{
/**
* The starting point, in pages.
*/
public
int
start
;
/**
* The length, in pages.
*/
public
int
length
;
public
PageRange
(
int
start
,
int
length
)
{
this
.
start
=
start
;
this
.
length
=
length
;
}
@Override
public
String
toString
()
{
return
"start:"
+
start
+
" length:"
+
length
;
}
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/MVMap.java
浏览文件 @
09769f17
...
@@ -773,18 +773,6 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -773,18 +773,6 @@ public class MVMap<K, V> extends AbstractMap<K, V>
return
new
Cursor
<
K
>(
this
,
root
,
from
);
return
new
Cursor
<
K
>(
this
,
root
,
from
);
}
}
/**
* Iterate over all keys in changed pages.
*
* @param version the old version
* @return the iterator
*/
public
Iterator
<
K
>
changeIterator
(
long
version
)
{
checkOpen
();
MVMap
<
K
,
V
>
old
=
openVersion
(
version
);
return
new
ChangeCursor
<
K
,
V
>(
this
,
root
,
old
.
root
);
}
public
Set
<
Map
.
Entry
<
K
,
V
>>
entrySet
()
{
public
Set
<
Map
.
Entry
<
K
,
V
>>
entrySet
()
{
HashMap
<
K
,
V
>
map
=
new
HashMap
<
K
,
V
>();
HashMap
<
K
,
V
>
map
=
new
HashMap
<
K
,
V
>();
for
(
K
k
:
keySet
())
{
for
(
K
k
:
keySet
())
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
09769f17
差异被折叠。
点击展开。
h2/src/main/org/h2/mvstore/Page.java
浏览文件 @
09769f17
...
@@ -814,11 +814,15 @@ public class Page {
...
@@ -814,11 +814,15 @@ public class Page {
^
DataUtils
.
getCheckValue
(
start
)
^
DataUtils
.
getCheckValue
(
start
)
^
DataUtils
.
getCheckValue
(
pageLength
);
^
DataUtils
.
getCheckValue
(
pageLength
);
buff
.
putShort
(
start
+
4
,
(
short
)
check
);
buff
.
putShort
(
start
+
4
,
(
short
)
check
);
this
.
pos
=
DataUtils
.
getPagePos
(
chunkId
,
start
,
pageLength
,
type
);
if
(
pos
!=
0
)
{
throw
DataUtils
.
newIllegalStateException
(
"Page already stored"
);
}
pos
=
DataUtils
.
getPagePos
(
chunkId
,
start
,
pageLength
,
type
);
long
max
=
DataUtils
.
getPageMaxLength
(
pos
);
long
max
=
DataUtils
.
getPageMaxLength
(
pos
);
chunk
.
maxLength
+=
max
;
chunk
.
maxLength
+=
max
;
chunk
.
maxLengthLive
+=
max
;
chunk
.
maxLengthLive
+=
max
;
chunk
.
pageCount
++;
chunk
.
pageCount
++;
chunk
.
pageCountLive
++;
return
buff
;
return
buff
;
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/TransactionStore.java
浏览文件 @
09769f17
...
@@ -90,6 +90,7 @@ public class TransactionStore {
...
@@ -90,6 +90,7 @@ public class TransactionStore {
MVMapConcurrent
.
Builder
<
long
[],
Object
[]>
builder
=
MVMapConcurrent
.
Builder
<
long
[],
Object
[]>
builder
=
new
MVMapConcurrent
.
Builder
<
long
[],
Object
[]>().
new
MVMapConcurrent
.
Builder
<
long
[],
Object
[]>().
valueType
(
valueType
);
valueType
(
valueType
);
// TODO escape other map names, to avoid conflicts
undoLog
=
store
.
openMap
(
"undoLog"
,
builder
);
undoLog
=
store
.
openMap
(
"undoLog"
,
builder
);
init
();
init
();
}
}
...
@@ -220,8 +221,9 @@ public class TransactionStore {
...
@@ -220,8 +221,9 @@ public class TransactionStore {
void
commit
(
Transaction
t
,
long
maxLogId
)
{
void
commit
(
Transaction
t
,
long
maxLogId
)
{
store
.
incrementVersion
();
store
.
incrementVersion
();
for
(
long
logId
=
0
;
logId
<
maxLogId
;
logId
++)
{
for
(
long
logId
=
0
;
logId
<
maxLogId
;
logId
++)
{
Object
[]
op
=
undoLog
.
get
(
new
long
[]
{
long
[]
undoKey
=
new
long
[]
{
t
.
getId
(),
logId
});
t
.
getId
(),
logId
};
Object
[]
op
=
undoLog
.
get
(
undoKey
);
int
opType
=
(
Integer
)
op
[
0
];
int
opType
=
(
Integer
)
op
[
0
];
if
(
opType
==
Transaction
.
OP_REMOVE
)
{
if
(
opType
==
Transaction
.
OP_REMOVE
)
{
int
mapId
=
(
Integer
)
op
[
1
];
int
mapId
=
(
Integer
)
op
[
1
];
...
@@ -238,7 +240,7 @@ public class TransactionStore {
...
@@ -238,7 +240,7 @@ public class TransactionStore {
map
.
remove
(
key
);
map
.
remove
(
key
);
}
}
}
}
undoLog
.
remove
(
logId
);
undoLog
.
remove
(
undoKey
);
}
}
openTransactions
.
remove
(
t
.
getId
());
openTransactions
.
remove
(
t
.
getId
());
openTransactionMap
.
remove
(
t
.
getId
());
openTransactionMap
.
remove
(
t
.
getId
());
...
@@ -858,6 +860,7 @@ public class TransactionStore {
...
@@ -858,6 +860,7 @@ public class TransactionStore {
}
}
public
void
removeMap
()
{
public
void
removeMap
()
{
// TODO remove in a transaction
mapWrite
.
removeMap
();
mapWrite
.
removeMap
();
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
浏览文件 @
09769f17
...
@@ -116,7 +116,8 @@ public class MVTableEngine implements TableEngine {
...
@@ -116,7 +116,8 @@ public class MVTableEngine implements TableEngine {
* @param store the store
* @param store the store
*/
*/
static
void
store
(
MVStore
store
)
{
static
void
store
(
MVStore
store
)
{
store
.
compact
(
50
);
int
test
;
// store.compact(50);
store
.
store
();
store
.
store
();
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
09769f17
...
@@ -203,6 +203,9 @@ java org.pitest.mutationtest.MutationCoverageReport
...
@@ -203,6 +203,9 @@ java org.pitest.mutationtest.MutationCoverageReport
--targetTests org.h2.test.store.TestStreamStore
--targetTests org.h2.test.store.TestStreamStore
--sourceDirs src/test,src/tools
--sourceDirs src/test,src/tools
Dump heap on out of memory:
-XX:+HeapDumpOnOutOfMemoryError
Random test:
Random test:
java15
java15
cd h2database/h2/bin
cd h2database/h2/bin
...
@@ -536,6 +539,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
...
@@ -536,6 +539,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
ssl
=
false
;
ssl
=
false
;
traceLevelFile
=
0
;
traceLevelFile
=
0
;
test
();
test
();
testUnit
();
big
=
false
;
big
=
false
;
cipher
=
"AES"
;
cipher
=
"AES"
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/TestBase.java
浏览文件 @
09769f17
...
@@ -600,9 +600,9 @@ public abstract class TestBase {
...
@@ -600,9 +600,9 @@ public abstract class TestBase {
*/
*/
public
void
assertEquals
(
java
.
util
.
Date
expected
,
java
.
util
.
Date
actual
)
{
public
void
assertEquals
(
java
.
util
.
Date
expected
,
java
.
util
.
Date
actual
)
{
if
(
expected
!=
actual
&&
!
expected
.
equals
(
actual
))
{
if
(
expected
!=
actual
&&
!
expected
.
equals
(
actual
))
{
final
DateFormat
df
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss.SSS"
);
DateFormat
df
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss.SSS"
);
final
SimpleTimeZone
GMT_TIMEZONE
=
new
SimpleTimeZone
(
0
,
"Z"
);
SimpleTimeZone
gmt
=
new
SimpleTimeZone
(
0
,
"Z"
);
df
.
setTimeZone
(
GMT_TIMEZONE
);
df
.
setTimeZone
(
gmt
);
fail
(
"Expected: "
+
df
.
format
(
expected
)
+
" actual: "
+
df
.
format
(
actual
));
fail
(
"Expected: "
+
df
.
format
(
expected
)
+
" actual: "
+
df
.
format
(
actual
));
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMVStore.java
浏览文件 @
09769f17
...
@@ -8,7 +8,6 @@ package org.h2.test.store;
...
@@ -8,7 +8,6 @@ package org.h2.test.store;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.nio.channels.FileChannel
;
import
java.nio.channels.FileChannel
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Random
;
import
java.util.Random
;
...
@@ -22,7 +21,6 @@ import org.h2.mvstore.type.StringDataType;
...
@@ -22,7 +21,6 @@ import org.h2.mvstore.type.StringDataType;
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
;
import
org.h2.util.New
;
/**
/**
* Tests the MVStore.
* Tests the MVStore.
...
@@ -35,7 +33,10 @@ public class TestMVStore extends TestBase {
...
@@ -35,7 +33,10 @@ public class TestMVStore extends TestBase {
* @param a ignored
* @param a ignored
*/
*/
public
static
void
main
(
String
...
a
)
throws
Exception
{
public
static
void
main
(
String
...
a
)
throws
Exception
{
TestBase
.
createCaller
().
init
().
test
();
TestBase
test
=
TestBase
.
createCaller
().
init
();
test
.
config
.
traceTest
=
true
;
test
.
config
.
big
=
true
;
test
.
test
();
}
}
public
void
test
()
throws
Exception
{
public
void
test
()
throws
Exception
{
...
@@ -61,7 +62,6 @@ public class TestMVStore extends TestBase {
...
@@ -61,7 +62,6 @@ public class TestMVStore extends TestBase {
testIterateOldVersion
();
testIterateOldVersion
();
testObjects
();
testObjects
();
testExample
();
testExample
();
testIterateOverChanges
();
testOpenStoreCloseLoop
();
testOpenStoreCloseLoop
();
testVersion
();
testVersion
();
testTruncateFile
();
testTruncateFile
();
...
@@ -79,11 +79,11 @@ public class TestMVStore extends TestBase {
...
@@ -79,11 +79,11 @@ public class TestMVStore extends TestBase {
testIterate
();
testIterate
();
testCloseTwice
();
testCloseTwice
();
testSimple
();
testSimple
();
// this test will run out of memory on a 32-bit VM before it gets to the part we need it to test
if
(
"64"
.
equals
(
System
.
getProperty
(
"sun.arch.data.model"
)))
{
// longer running tests
testLargerThan2G
();
testLargerThan2G
();
}
}
}
private
void
testAtomicOperations
()
{
private
void
testAtomicOperations
()
{
String
fileName
=
getBaseDir
()
+
"/testAtomicOperations.h3"
;
String
fileName
=
getBaseDir
()
+
"/testAtomicOperations.h3"
;
...
@@ -705,39 +705,6 @@ public class TestMVStore extends TestBase {
...
@@ -705,39 +705,6 @@ public class TestMVStore extends TestBase {
}
}
}
}
private
void
testIterateOverChanges
()
{
String
fileName
=
getBaseDir
()
+
"/testIterate.h3"
;
FileUtils
.
delete
(
fileName
);
MVStore
s
=
openStore
(
fileName
);
s
.
setPageSize
(
6
);
MVMap
<
Integer
,
String
>
m
=
s
.
openMap
(
"data"
);
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
m
.
put
(
i
,
"Hi"
);
}
s
.
incrementVersion
();
s
.
store
();
for
(
int
i
=
20
;
i
<
40
;
i
++)
{
assertEquals
(
"Hi"
,
m
.
put
(
i
,
"Hello"
));
}
long
old
=
s
.
getCurrentVersion
();
s
.
incrementVersion
();
for
(
int
i
=
10
;
i
<
15
;
i
++)
{
m
.
put
(
i
,
"Hallo"
);
}
m
.
put
(
50
,
"Hallo"
);
for
(
int
i
=
90
;
i
<
93
;
i
++)
{
assertEquals
(
"Hi"
,
m
.
remove
(
i
));
}
assertEquals
(
null
,
m
.
put
(
100
,
"Hallo"
));
Iterator
<
Integer
>
it
=
m
.
changeIterator
(
old
);
ArrayList
<
Integer
>
list
=
New
.
arrayList
();
while
(
it
.
hasNext
())
{
list
.
add
(
it
.
next
());
}
assertEquals
(
"[10, 11, 12, 13, 14, 50, 100, 90, 91, 92]"
,
list
.
toString
());
s
.
close
();
}
private
void
testOldVersion
()
{
private
void
testOldVersion
()
{
MVStore
s
;
MVStore
s
;
for
(
int
op
=
0
;
op
<=
1
;
op
++)
{
for
(
int
op
=
0
;
op
<=
1
;
op
++)
{
...
@@ -1031,8 +998,8 @@ public class TestMVStore extends TestBase {
...
@@ -1031,8 +998,8 @@ public class TestMVStore extends TestBase {
assertEquals
(
"name:data"
,
m
.
get
(
"map."
+
id
));
assertEquals
(
"name:data"
,
m
.
get
(
"map."
+
id
));
assertTrue
(
m
.
get
(
"root.1"
).
length
()
>
0
);
assertTrue
(
m
.
get
(
"root.1"
).
length
()
>
0
);
assertTrue
(
m
.
containsKey
(
"chunk.1"
));
assertTrue
(
m
.
containsKey
(
"chunk.1"
));
assertEquals
(
"id:1,length:2
46,maxLength:224,maxLengthLive:0
,"
+
assertEquals
(
"id:1,length:2
63,maxLength:288,maxLengthLive:288
,"
+
"metaRoot:27487791092
2,pageCount
:2,"
+
"metaRoot:27487791092
4,pageCount:2,pageCountLive
:2,"
+
"start:8192,time:0,version:1"
,
m
.
get
(
"chunk.1"
));
"start:8192,time:0,version:1"
,
m
.
get
(
"chunk.1"
));
assertTrue
(
m
.
containsKey
(
"chunk.2"
));
assertTrue
(
m
.
containsKey
(
"chunk.2"
));
...
@@ -1397,30 +1364,36 @@ public class TestMVStore extends TestBase {
...
@@ -1397,30 +1364,36 @@ public class TestMVStore extends TestBase {
s
.
close
();
s
.
close
();
}
}
private
void
testLargerThan2G
()
{
private
void
testLargerThan2G
()
throws
IOException
{
if
(!
config
.
big
)
{
return
;
}
String
fileName
=
getBaseDir
()
+
"/testLargerThan2G.h3"
;
String
fileName
=
getBaseDir
()
+
"/testLargerThan2G.h3"
;
FileUtils
.
delete
(
fileName
);
FileUtils
.
delete
(
fileName
);
MVStore
store
=
new
MVStore
.
Builder
().
cacheSize
(
16
).
MVStore
store
=
new
MVStore
.
Builder
().
cacheSize
(
800
).
fileName
(
fileName
).
writeBufferSize
(
0
).
writeDelay
(-
1
)
fileName
(
fileName
).
open
();
.
open
();
MVMap
<
Integer
,
String
>
map
=
store
.
openMap
(
"test"
);
long
last
=
System
.
currentTimeMillis
();
MVMap
<
String
,
String
>
map
=
store
.
openMap
(
"test"
);
String
data
=
new
String
(
new
char
[
2500
]).
replace
((
char
)
0
,
'x'
);
int
totalWrite
=
15000000
;
for
(
int
i
=
0
;;
i
++)
{
int
lineStored
=
0
;
map
.
put
(
i
,
data
);
while
(
lineStored
<=
totalWrite
)
{
if
(
i
%
10000
==
0
)
{
lineStored
++;
long
version
=
store
.
commit
();
String
actualKey
=
lineStored
+
" just for length length length "
+
lineStored
;
store
.
setRetainVersion
(
version
);
String
value
=
"Just a a string that is kinda long long long but not too much much much much much much much much much "
long
time
=
System
.
currentTimeMillis
();
+
lineStored
;
if
(
time
-
last
>
2000
)
{
long
mb
=
store
.
getFile
().
size
()
/
1024
/
1024
;
map
.
put
(
actualKey
,
value
);
trace
(
mb
+
"/4500"
);
if
(
mb
>
4500
)
{
if
(
lineStored
%
1000000
==
0
)
{
break
;
store
.
store
();
}
last
=
time
;
}
}
}
}
store
.
store
();
}
store
.
commit
();
store
.
close
();
store
.
close
();
FileUtils
.
delete
(
fileName
);
}
}
/**
/**
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMVTableEngine.java
浏览文件 @
09769f17
...
@@ -36,7 +36,7 @@ public class TestMVTableEngine extends TestBase {
...
@@ -36,7 +36,7 @@ public class TestMVTableEngine extends TestBase {
public
void
test
()
throws
Exception
{
public
void
test
()
throws
Exception
{
testEncryption
();
testEncryption
();
testReadOnly
();
testReadOnly
();
//
testReuseDiskSpace();
testReuseDiskSpace
();
testDataTypes
();
testDataTypes
();
testLocking
();
testLocking
();
testSimple
();
testSimple
();
...
@@ -87,8 +87,8 @@ public class TestMVTableEngine extends TestBase {
...
@@ -87,8 +87,8 @@ public class TestMVTableEngine extends TestBase {
";DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine"
;
";DEFAULT_TABLE_ENGINE=org.h2.mvstore.db.MVTableEngine"
;
Connection
conn
;
Connection
conn
;
Statement
stat
;
Statement
stat
;
long
maxSize
Half
=
0
;
long
maxSize
=
0
;
for
(
int
i
=
0
;
i
<
1
0
;
i
++)
{
for
(
int
i
=
0
;
i
<
2
0
;
i
++)
{
conn
=
getConnection
(
dbName
);
conn
=
getConnection
(
dbName
);
for
(
MVTableEngine
.
Store
s
:
MVTableEngine
.
getStores
())
{
for
(
MVTableEngine
.
Store
s
:
MVTableEngine
.
getStores
())
{
s
.
getStore
().
setRetentionTime
(
0
);
s
.
getStore
().
setRetentionTime
(
0
);
...
@@ -100,10 +100,10 @@ public class TestMVTableEngine extends TestBase {
...
@@ -100,10 +100,10 @@ public class TestMVTableEngine extends TestBase {
conn
.
close
();
conn
.
close
();
long
size
=
FileUtils
.
size
(
getBaseDir
()
+
"/mvstore"
long
size
=
FileUtils
.
size
(
getBaseDir
()
+
"/mvstore"
+
Constants
.
SUFFIX_MV_FILE
);
+
Constants
.
SUFFIX_MV_FILE
);
if
(
i
<
6
)
{
if
(
i
<
10
)
{
maxSize
Half
=
Math
.
max
(
size
,
maxSizeHalf
);
maxSize
=
(
int
)
(
Math
.
max
(
size
,
maxSize
)
*
1.1
);
}
else
if
(
size
>
maxSize
Half
)
{
}
else
if
(
size
>
maxSize
)
{
fail
(
i
+
" size: "
+
size
+
" max: "
+
maxSize
Half
);
fail
(
i
+
" size: "
+
size
+
" max: "
+
maxSize
);
}
}
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论