Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
cd49d27d
提交
cd49d27d
authored
12 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
A persistent multi-version map (work in progress) - implement complete java.util.Map interface
上级
7ef5bbc4
master
noel-pr1
plus33-master
pr/267
stumc-Issue#576
version-1.4.198
version-1.4.197
version-1.4.196
version-1.4.195
version-1.4.194
version-1.4.193
version-1.4.192
version-1.4.191
version-1.4.190
version-1.4.188
version-1.4.187
version-1.4.186
version-1.4.185
version-1.4.184
version-1.4.183
version-1.4.182
version-1.4.181
version-1.4.178
version-1.4.177
version-1.3
无相关合并请求
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
87 行增加
和
71 行删除
+87
-71
MVRTreeMap.java
h2/src/test/org/h2/test/store/MVRTreeMap.java
+25
-26
TestMVStore.java
h2/src/test/org/h2/test/store/TestMVStore.java
+17
-11
MVMap.java
h2/src/tools/org/h2/dev/store/btree/MVMap.java
+33
-22
MVStore.java
h2/src/tools/org/h2/dev/store/btree/MVStore.java
+9
-11
Page.java
h2/src/tools/org/h2/dev/store/btree/Page.java
+3
-1
没有找到文件。
h2/src/test/org/h2/test/store/MVRTreeMap.java
浏览文件 @
cd49d27d
...
...
@@ -150,23 +150,26 @@ public class MVRTreeMap<K, V> extends MVMap<K, V> {
return
bounds
;
}
public
void
put
(
K
key
,
V
value
)
{
putOrAdd
(
key
,
value
,
false
);
@SuppressWarnings
(
"unchecked"
)
public
V
put
(
K
key
,
V
value
)
{
return
(
V
)
putOrAdd
(
key
,
value
,
false
);
}
public
void
add
(
K
key
,
V
value
)
{
putOrAdd
(
key
,
value
,
true
);
}
public
void
putOrAdd
(
K
key
,
V
value
,
boolean
alwaysAdd
)
{
public
Object
putOrAdd
(
K
key
,
V
value
,
boolean
alwaysAdd
)
{
checkWrite
();
long
writeVersion
=
store
.
getCurrentVersion
();
Page
p
=
root
;
Object
result
;
if
(
p
==
null
)
{
Object
[]
keys
=
{
key
};
Object
[]
values
=
{
value
};
p
=
Page
.
create
(
this
,
writeVersion
,
1
,
keys
,
values
,
null
,
null
,
null
,
1
,
0
);
result
=
null
;
}
else
if
(
alwaysAdd
||
get
(
key
)
==
null
)
{
if
(
p
.
getKeyCount
()
>
store
.
getMaxPageSize
())
{
// only possible if this is the root, else we would have split earlier
...
...
@@ -183,43 +186,41 @@ public class MVRTreeMap<K, V> extends MVMap<K, V> {
totalCount
,
0
);
// now p is a node; continues
}
p
=
add
(
p
,
writeVersion
,
key
,
value
);
add
(
p
,
writeVersion
,
key
,
value
);
result
=
null
;
}
else
{
p
=
set
(
p
,
writeVersion
,
key
,
value
);
result
=
set
(
p
,
writeVersion
,
key
,
value
);
}
setRoot
(
p
);
return
result
;
}
protected
Page
set
(
Page
p
,
long
writeVersion
,
Object
key
,
Object
value
)
{
protected
Object
set
(
Page
p
,
long
writeVersion
,
Object
key
,
Object
value
)
{
if
(!
p
.
isLeaf
())
{
for
(
int
i
=
0
;
i
<
p
.
getKeyCount
();
i
++)
{
if
(
contains
(
p
,
i
,
key
))
{
Page
c
=
p
.
getChildPage
(
i
);
Page
c2
=
set
(
c
,
writeVersion
,
key
,
value
);
if
(
c
!=
c2
)
{
p
=
p
.
copyOnWrite
(
writeVersion
);
p
.
setChild
(
i
,
c2
);
break
;
Page
c
=
p
.
getChildPage
(
i
).
copyOnWrite
(
writeVersion
);
Object
result
=
set
(
c
,
writeVersion
,
key
,
value
);
if
(
result
!=
null
)
{
p
.
setChild
(
i
,
c
);
return
result
;
}
}
}
}
else
{
for
(
int
i
=
0
;
i
<
p
.
getKeyCount
();
i
++)
{
if
(
keyType
.
equals
(
p
.
getKey
(
i
),
key
))
{
p
=
p
.
copyOnWrite
(
writeVersion
);
p
.
setValue
(
i
,
value
);
break
;
return
p
.
setValue
(
i
,
value
);
}
}
}
return
p
;
return
null
;
}
protected
Page
add
(
Page
p
,
long
writeVersion
,
Object
key
,
Object
value
)
{
protected
void
add
(
Page
p
,
long
writeVersion
,
Object
key
,
Object
value
)
{
if
(
p
.
isLeaf
())
{
p
=
p
.
copyOnWrite
(
writeVersion
);
p
.
insertLeaf
(
p
.
getKeyCount
(),
key
,
value
);
return
p
;
return
;
}
// p is a node
int
index
=
-
1
;
...
...
@@ -241,25 +242,23 @@ public class MVRTreeMap<K, V> extends MVMap<K, V> {
}
}
}
Page
c
=
p
.
getChildPage
(
index
);
Page
c
=
p
.
getChildPage
(
index
)
.
copyOnWrite
(
writeVersion
)
;
if
(
c
.
getKeyCount
()
>=
store
.
getMaxPageSize
())
{
// split on the way down
c
=
c
.
copyOnWrite
(
writeVersion
);
Page
split
=
split
(
c
,
writeVersion
);
p
=
p
.
copyOnWrite
(
writeVersion
);
p
.
setKey
(
index
,
getBounds
(
c
));
p
.
setChild
(
index
,
c
);
p
.
insertNode
(
index
,
getBounds
(
split
),
split
);
// now we are not sure where to add
return
add
(
p
,
writeVersion
,
key
,
value
);
add
(
p
,
writeVersion
,
key
,
value
);
return
;
}
Page
c2
=
add
(
c
,
writeVersion
,
key
,
value
);
p
=
p
.
copyOnWrite
(
writeVersion
);
add
(
c
,
writeVersion
,
key
,
value
);
Object
bounds
=
p
.
getKey
(
index
);
keyType
.
increaseBounds
(
bounds
,
key
);
p
.
setKey
(
index
,
bounds
);
p
.
setChild
(
index
,
c2
);
return
p
;
p
.
setChild
(
index
,
c
);
}
private
Page
split
(
Page
p
,
long
writeVersion
)
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMVStore.java
浏览文件 @
cd49d27d
...
...
@@ -56,12 +56,12 @@ public class TestMVStore extends TestBase {
s
.
setMaxPageSize
(
6
);
MVMap
<
Integer
,
String
>
m
=
s
.
openMap
(
"data"
,
Integer
.
class
,
String
.
class
);
for
(
int
i
=
0
;
i
<
60
;
i
++)
{
m
.
put
(
i
,
"H
ello
"
);
m
.
put
(
i
,
"H
i
"
);
}
s
.
commit
();
s
.
store
();
for
(
int
i
=
20
;
i
<
40
;
i
++)
{
m
.
put
(
i
,
"Hello"
);
assertEquals
(
"Hi"
,
m
.
put
(
i
,
"Hello"
)
);
}
s
.
commit
();
for
(
int
i
=
10
;
i
<
15
;
i
++)
{
...
...
@@ -318,7 +318,7 @@ public class TestMVStore extends TestBase {
s
.
store
();
assertEquals
(
"1/1///"
,
m
.
get
(
"map.data"
));
assertTrue
(
m
.
containsKey
(
"chunk.1"
));
data
.
put
(
"1"
,
"Hallo"
);
assertEquals
(
"Hello"
,
data
.
put
(
"1"
,
"Hallo"
)
);
s
.
store
();
assertEquals
(
"1/1///"
,
m
.
get
(
"map.data"
));
assertTrue
(
m
.
get
(
"root.1"
).
length
()
>
0
);
...
...
@@ -341,7 +341,7 @@ public class TestMVStore extends TestBase {
MVMap
<
Integer
,
String
>
m
=
s
.
openMap
(
"data"
,
Integer
.
class
,
String
.
class
);
// t = System.currentTimeMillis();
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
m
.
put
(
i
,
"Hello World"
);
assertNull
(
m
.
put
(
i
,
"Hello World"
)
);
}
// System.out.println("put: " + (System.currentTimeMillis() - t));
// t = System.currentTimeMillis();
...
...
@@ -404,7 +404,7 @@ public class TestMVStore extends TestBase {
// p.startCollecting();
// long t = System.currentTimeMillis();
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
m
.
put
(
i
,
"hello "
+
i
);
assertNull
(
m
.
put
(
i
,
"hello "
+
i
)
);
assertEquals
(
"hello "
+
i
,
m
.
get
(
i
));
}
// System.out.println("put: " + (System.currentTimeMillis() - t));
...
...
@@ -515,6 +515,7 @@ public class TestMVStore extends TestBase {
Random
r
=
new
Random
(
1
);
int
operationCount
=
1000
;
int
maxValue
=
30
;
Integer
expected
,
got
;
for
(
int
i
=
0
;
i
<
operationCount
;
i
++)
{
int
k
=
r
.
nextInt
(
maxValue
);
int
v
=
r
.
nextInt
();
...
...
@@ -522,14 +523,19 @@ public class TestMVStore extends TestBase {
switch
(
r
.
nextInt
(
3
))
{
case
0
:
log
(
i
+
": put "
+
k
+
" = "
+
v
);
m
.
put
(
k
,
v
);
map
.
put
(
k
,
v
);
expected
=
map
.
put
(
k
,
v
);
got
=
m
.
put
(
k
,
v
);
if
(
expected
==
null
)
{
assertNull
(
got
);
}
else
{
assertEquals
(
expected
,
got
);
}
compareAll
=
true
;
break
;
case
1
:
log
(
i
+
": remove "
+
k
);
Integer
expected
=
map
.
remove
(
k
);
Integer
got
=
m
.
remove
(
k
);
expected
=
map
.
remove
(
k
);
got
=
m
.
remove
(
k
);
if
(
expected
==
null
)
{
assertNull
(
got
);
}
else
{
...
...
@@ -553,8 +559,8 @@ public class TestMVStore extends TestBase {
Iterator
<
Integer
>
itExpected
=
map
.
keySet
().
iterator
();
while
(
itExpected
.
hasNext
())
{
assertTrue
(
it
.
hasNext
());
Integer
expected
=
itExpected
.
next
();
Integer
got
=
it
.
next
();
expected
=
itExpected
.
next
();
got
=
it
.
next
();
assertEquals
(
expected
,
got
);
}
assertFalse
(
it
.
hasNext
());
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/store/btree/MVMap.java
浏览文件 @
cd49d27d
...
...
@@ -6,8 +6,11 @@
*/
package
org
.
h2
.
dev
.
store
.
btree
;
import
java.util.AbstractMap
;
import
java.util.AbstractSet
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.TreeMap
;
...
...
@@ -17,7 +20,7 @@ import java.util.TreeMap;
* @param <K> the key class
* @param <V> the value class
*/
public
class
MVMap
<
K
,
V
>
{
public
class
MVMap
<
K
,
V
>
extends
AbstractMap
<
K
,
V
>
{
protected
final
MVStore
store
;
protected
Page
root
;
...
...
@@ -51,16 +54,20 @@ public class MVMap<K, V> {
*
* @param key the key
* @param value the value
* @return the old value if the key existed, or null otherwise
*/
public
void
put
(
K
key
,
V
value
)
{
@SuppressWarnings
(
"unchecked"
)
public
V
put
(
K
key
,
V
value
)
{
checkWrite
();
long
writeVersion
=
store
.
getCurrentVersion
();
Page
p
=
root
;
Object
result
;
if
(
p
==
null
)
{
Object
[]
keys
=
{
key
};
Object
[]
values
=
{
value
};
p
=
Page
.
create
(
this
,
writeVersion
,
1
,
keys
,
values
,
null
,
null
,
null
,
1
,
0
);
result
=
null
;
}
else
{
p
=
p
.
copyOnWrite
(
writeVersion
);
if
(
p
.
getKeyCount
()
>
store
.
getMaxPageSize
())
{
...
...
@@ -76,9 +83,10 @@ public class MVMap<K, V> {
keys
,
null
,
children
,
childrenPages
,
counts
,
totalCount
,
0
);
// now p is a node; insert continues
}
put
(
p
,
writeVersion
,
key
,
value
);
result
=
put
(
p
,
writeVersion
,
key
,
value
);
}
setRoot
(
p
);
return
(
V
)
result
;
}
/**
...
...
@@ -90,16 +98,15 @@ public class MVMap<K, V> {
* @param key the key
* @param value the value (may not be null)
*/
protected
void
put
(
Page
p
,
long
writeVersion
,
Object
key
,
Object
value
)
{
protected
Object
put
(
Page
p
,
long
writeVersion
,
Object
key
,
Object
value
)
{
if
(
p
.
isLeaf
())
{
int
index
=
p
.
binarySearch
(
key
);
if
(
index
<
0
)
{
index
=
-
index
-
1
;
p
.
insertLeaf
(
index
,
key
,
value
);
}
else
{
p
.
setValue
(
index
,
value
);
return
null
;
}
return
;
return
p
.
setValue
(
index
,
value
)
;
}
// p is a node
int
index
=
p
.
binarySearch
(
key
);
...
...
@@ -108,8 +115,7 @@ public class MVMap<K, V> {
}
else
{
index
++;
}
Page
cOld
=
p
.
getChildPage
(
index
);
Page
c
=
cOld
.
copyOnWrite
(
writeVersion
);
Page
c
=
p
.
getChildPage
(
index
).
copyOnWrite
(
writeVersion
);
if
(
c
.
getKeyCount
()
>=
store
.
getMaxPageSize
())
{
// split on the way down
int
at
=
c
.
getKeyCount
()
/
2
;
...
...
@@ -118,14 +124,11 @@ public class MVMap<K, V> {
p
.
setChild
(
index
,
split
);
p
.
insertNode
(
index
,
k
,
c
);
// now we are not sure where to add
put
(
p
,
writeVersion
,
key
,
value
);
return
;
}
long
oldSize
=
c
.
getTotalCount
();
put
(
c
,
writeVersion
,
key
,
value
);
if
(
cOld
!=
c
||
oldSize
!=
c
.
getTotalCount
())
{
p
.
setChild
(
index
,
c
);
return
put
(
p
,
writeVersion
,
key
,
value
);
}
Object
result
=
put
(
c
,
writeVersion
,
key
,
value
);
p
.
setChild
(
index
,
c
);
return
result
;
}
/**
...
...
@@ -312,9 +315,9 @@ public class MVMap<K, V> {
* Remove a key-value pair, if the key exists.
*
* @param key the key
* @return the old value if the key existed
* @return the old value if the key existed
, or null otherwise
*/
public
V
remove
(
K
key
)
{
public
V
remove
(
Object
key
)
{
checkWrite
();
Page
p
=
root
;
if
(
p
==
null
)
{
...
...
@@ -468,6 +471,14 @@ public class MVMap<K, V> {
return
c
;
}
public
Set
<
Map
.
Entry
<
K
,
V
>>
entrySet
()
{
HashMap
<
K
,
V
>
map
=
new
HashMap
<
K
,
V
>();
for
(
K
k
:
keySet
())
{
map
.
put
(
k
,
get
(
k
));
}
return
map
.
entrySet
();
}
public
Set
<
K
>
keySet
()
{
checkOpen
();
final
Page
root
=
this
.
root
;
...
...
@@ -582,6 +593,10 @@ public class MVMap<K, V> {
return
id
;
}
public
boolean
equals
(
Object
o
)
{
return
this
==
o
;
}
public
int
size
()
{
long
size
=
getSize
();
return
size
>
Integer
.
MAX_VALUE
?
Integer
.
MAX_VALUE
:
(
int
)
size
;
...
...
@@ -591,10 +606,6 @@ public class MVMap<K, V> {
return
root
==
null
?
0
:
root
.
getTotalCount
();
}
public
boolean
equals
(
Object
o
)
{
return
this
==
o
;
}
long
getCreateVersion
()
{
return
createVersion
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/store/btree/MVStore.java
浏览文件 @
cd49d27d
...
...
@@ -38,27 +38,25 @@ header:
blockSize=4096
TODO:
- rename commit to incrementVersion
- implement complete java.util.Map interface
- test with very small chunks, possibly speed up very small transactions
- check what happens on concurrent reads and 1 write; multiple writes
- support all objects (using serialization)
- concurrent iterator (when to call commit; read on first hasNext())
- compact: use total max length instead of page count (liveCount)
- support background writes (store old version)
- avoid using java.util.Properties (it allocates quite a lot of memory)
- support large binaries
- support database version / schema version
- limited support for writing to old versions (branches)
- atomic test-and-set (when supporting concurrent writes)
- support background writes (store old version)
- file header could be a regular chunk, end of file the second
- possibly split chunk data into immutable and mutable
- test with very small chunks, possibly speed up very small transactions
- compact: use total max length instead of page count (liveCount)
- check what happens on concurrent reads and 1 write; multiple writes
- concurrent iterator (when to call commit)
- support large binaries
- support stores that span multiple files (chunks stored in other files)
- triggers
- support database version / schema version
- implement more counted b-tree (skip, get positions)
- merge pages if small
- r-tree: add missing features (NN search for example)
- compression: maybe hash table reset speeds up compression
- avoid using java.util.Properties (it allocates quite a lot of memory)
- support all objects (using serialization)
*/
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/store/btree/Page.java
浏览文件 @
cd49d27d
...
...
@@ -346,12 +346,14 @@ public class Page {
keys
[
index
]
=
key
;
}
public
void
setValue
(
int
index
,
Object
value
)
{
public
Object
setValue
(
int
index
,
Object
value
)
{
Object
old
=
values
[
index
];
if
((
sharedFlags
&
SHARED_VALUES
)
!=
0
)
{
values
=
Arrays
.
copyOf
(
values
,
values
.
length
);
sharedFlags
&=
~
SHARED_VALUES
;
}
values
[
index
]
=
value
;
return
old
;
}
/**
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论