Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
7ef5bbc4
提交
7ef5bbc4
authored
12 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
A persistent multi-version map (work in progress) - remove should return the value
上级
5e703674
隐藏空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
177 行增加
和
160 行删除
+177
-160
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+2
-2
MVRTreeMap.java
h2/src/test/org/h2/test/store/MVRTreeMap.java
+73
-71
TestMVRTree.java
h2/src/test/org/h2/test/store/TestMVRTree.java
+6
-6
TestMVStore.java
h2/src/test/org/h2/test/store/TestMVStore.java
+13
-7
TestMapFactory.java
h2/src/test/org/h2/test/store/TestMapFactory.java
+1
-1
MVMap.java
h2/src/tools/org/h2/dev/store/btree/MVMap.java
+79
-73
MVStore.java
h2/src/tools/org/h2/dev/store/btree/MVStore.java
+3
-0
没有找到文件。
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
7ef5bbc4
...
...
@@ -106,7 +106,7 @@ import org.h2.test.server.TestInit;
import
org.h2.test.store.TestCacheLIRS
;
import
org.h2.test.store.TestDataUtils
;
import
org.h2.test.store.TestMVStore
;
import
org.h2.test.store.Test
Rt
ree
;
import
org.h2.test.store.Test
MVRT
ree
;
import
org.h2.test.synth.TestBtreeIndex
;
import
org.h2.test.synth.TestCrashAPI
;
import
org.h2.test.synth.TestDiskFull
;
...
...
@@ -668,7 +668,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
TestMVStore
().
runTest
(
this
);
new
TestCacheLIRS
().
runTest
(
this
);
new
TestDataUtils
().
runTest
(
this
);
new
Test
Rt
ree
().
runTest
(
this
);
new
Test
MVRT
ree
().
runTest
(
this
);
// unit
new
TestAutoReconnect
().
runTest
(
this
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/
Rt
reeMap.java
→
h2/src/test/org/h2/test/store/
MVRT
reeMap.java
浏览文件 @
7ef5bbc4
...
...
@@ -21,12 +21,12 @@ import org.h2.util.New;
* @param <K> the key class
* @param <V> the value class
*/
public
class
Rt
reeMap
<
K
,
V
>
extends
MVMap
<
K
,
V
>
{
public
class
MVRT
reeMap
<
K
,
V
>
extends
MVMap
<
K
,
V
>
{
private
final
SpatialType
keyType
;
private
boolean
quadraticSplit
;
Rt
reeMap
(
MVStore
store
,
int
id
,
String
name
,
DataType
keyType
,
MVRT
reeMap
(
MVStore
store
,
int
id
,
String
name
,
DataType
keyType
,
DataType
valueType
,
long
createVersion
)
{
super
(
store
,
id
,
name
,
keyType
,
valueType
,
createVersion
);
this
.
keyType
=
(
SpatialType
)
keyType
;
...
...
@@ -99,46 +99,47 @@ public class RtreeMap<K, V> extends MVMap<K, V> {
return
null
;
}
protected
Page
remove
(
Page
p
,
long
writeVersion
,
Object
key
)
{
if
(!
p
.
isLeaf
())
{
protected
Object
remove
(
Page
p
,
long
writeVersion
,
Object
key
)
{
Object
result
=
null
;
if
(
p
.
isLeaf
())
{
for
(
int
i
=
0
;
i
<
p
.
getKeyCount
();
i
++)
{
if
(
contains
(
p
,
i
,
key
))
{
Page
c
=
p
.
getChildPage
(
i
);
long
oldSize
=
c
.
getTotalCount
();
Page
c2
=
remove
(
c
,
writeVersion
,
key
);
if
(
c2
==
null
)
{
// this child was deleted
if
(
p
.
getKeyCount
()
==
1
)
{
removePage
(
p
);
return
null
;
}
p
=
p
.
copyOnWrite
(
writeVersion
);
p
.
remove
(
i
);
}
else
if
(
oldSize
!=
c2
.
getTotalCount
())
{
p
=
p
.
copyOnWrite
(
writeVersion
);
Object
oldBounds
=
p
.
getKey
(
i
);
if
(!
keyType
.
isInside
(
key
,
oldBounds
))
{
p
.
setKey
(
i
,
getBounds
(
c
));
}
p
.
setChild
(
i
,
c2
);
break
;
if
(
keyType
.
equals
(
p
.
getKey
(
i
),
key
))
{
result
=
p
.
getValue
(
i
);
p
.
remove
(
i
);
if
(
p
.
getKeyCount
()
==
0
)
{
removePage
(
p
);
}
break
;
}
}
}
else
{
for
(
int
i
=
0
;
i
<
p
.
getKeyCount
();
i
++)
{
if
(
keyType
.
equals
(
p
.
getKey
(
i
),
key
))
{
if
(
p
.
getKeyCount
()
==
1
)
{
return
result
;
}
for
(
int
i
=
0
;
i
<
p
.
getKeyCount
();
i
++)
{
if
(
contains
(
p
,
i
,
key
))
{
Page
cOld
=
p
.
getChildPage
(
i
);
Page
c
=
cOld
.
copyOnWrite
(
writeVersion
);
long
oldSize
=
c
.
getTotalCount
();
result
=
remove
(
c
,
writeVersion
,
key
);
if
(
oldSize
==
c
.
getTotalCount
())
{
continue
;
}
if
(
c
.
getTotalCount
()
==
0
)
{
// this child was deleted
p
.
remove
(
i
);
if
(
p
.
getKeyCount
()
==
0
)
{
removePage
(
p
);
return
null
;
}
p
=
p
.
copyOnWrite
(
writeVersion
);
p
.
remove
(
i
);
break
;
}
Object
oldBounds
=
p
.
getKey
(
i
);
if
(!
keyType
.
isInside
(
key
,
oldBounds
))
{
p
.
setKey
(
i
,
getBounds
(
c
));
}
p
.
setChild
(
i
,
c
);
break
;
}
}
return
p
;
return
result
;
}
private
Object
getBounds
(
Page
x
)
{
...
...
@@ -149,15 +150,44 @@ public class RtreeMap<K, V> extends MVMap<K, V> {
return
bounds
;
}
public
void
put
(
K
key
,
V
data
)
{
public
void
put
(
K
key
,
V
value
)
{
putOrAdd
(
key
,
value
,
false
);
}
public
void
add
(
K
key
,
V
value
)
{
putOrAdd
(
key
,
value
,
true
);
}
public
void
putOrAdd
(
K
key
,
V
value
,
boolean
alwaysAdd
)
{
checkWrite
();
Page
oldRoot
=
root
;
if
(
get
(
key
)
!=
null
)
{
root
=
set
(
root
,
store
.
getCurrentVersion
(),
key
,
data
);
long
writeVersion
=
store
.
getCurrentVersion
();
Page
p
=
root
;
if
(
p
==
null
)
{
Object
[]
keys
=
{
key
};
Object
[]
values
=
{
value
};
p
=
Page
.
create
(
this
,
writeVersion
,
1
,
keys
,
values
,
null
,
null
,
null
,
1
,
0
);
}
else
if
(
alwaysAdd
||
get
(
key
)
==
null
)
{
if
(
p
.
getKeyCount
()
>
store
.
getMaxPageSize
())
{
// only possible if this is the root, else we would have split earlier
// (this requires maxPageSize is fixed)
p
=
p
.
copyOnWrite
(
writeVersion
);
long
totalCount
=
p
.
getTotalCount
();
Page
split
=
split
(
p
,
writeVersion
);
Object
[]
keys
=
{
getBounds
(
p
),
getBounds
(
split
)
};
long
[]
children
=
{
p
.
getPos
(),
split
.
getPos
(),
0
};
Page
[]
childrenPages
=
{
p
,
split
,
null
};
long
[]
counts
=
{
p
.
getTotalCount
(),
split
.
getTotalCount
(),
0
};
p
=
Page
.
create
(
this
,
writeVersion
,
2
,
keys
,
null
,
children
,
childrenPages
,
counts
,
totalCount
,
0
);
// now p is a node; continues
}
p
=
add
(
p
,
writeVersion
,
key
,
value
);
}
else
{
root
=
add
(
root
,
store
.
getCurrentVersion
(),
key
,
data
,
store
.
getMaxPageSize
()
);
p
=
set
(
p
,
writeVersion
,
key
,
value
);
}
markChanged
(
oldRoot
);
setRoot
(
p
);
}
protected
Page
set
(
Page
p
,
long
writeVersion
,
Object
key
,
Object
value
)
{
...
...
@@ -185,36 +215,8 @@ public class RtreeMap<K, V> extends MVMap<K, V> {
return
p
;
}
public
void
add
(
K
key
,
V
data
)
{
checkWrite
();
Page
oldRoot
=
root
;
root
=
add
(
root
,
store
.
getCurrentVersion
(),
key
,
data
,
store
.
getMaxPageSize
());
markChanged
(
oldRoot
);
}
protected
Page
add
(
Page
p
,
long
writeVersion
,
Object
key
,
Object
value
,
int
maxPageSize
)
{
if
(
p
==
null
)
{
Object
[]
keys
=
{
key
};
Object
[]
values
=
{
value
};
p
=
Page
.
create
(
this
,
writeVersion
,
1
,
keys
,
values
,
null
,
null
,
null
,
1
,
0
);
return
p
;
}
if
(
p
.
getKeyCount
()
>
maxPageSize
)
{
// only possible if this is the root, else we would have split earlier
// (this requires maxPageSize is fixed)
p
=
p
.
copyOnWrite
(
writeVersion
);
long
totalCount
=
p
.
getTotalCount
();
Page
split
=
split
(
p
,
writeVersion
);
Object
[]
keys
=
{
getBounds
(
p
),
getBounds
(
split
)
};
long
[]
children
=
{
p
.
getPos
(),
split
.
getPos
(),
0
};
Page
[]
childrenPages
=
{
p
,
split
,
null
};
long
[]
counts
=
{
p
.
getTotalCount
(),
split
.
getTotalCount
(),
0
};
p
=
Page
.
create
(
this
,
writeVersion
,
2
,
keys
,
null
,
children
,
childrenPages
,
counts
,
totalCount
,
0
);
// now p is a node; continues
}
else
if
(
p
.
isLeaf
())
{
protected
Page
add
(
Page
p
,
long
writeVersion
,
Object
key
,
Object
value
)
{
if
(
p
.
isLeaf
())
{
p
=
p
.
copyOnWrite
(
writeVersion
);
p
.
insertLeaf
(
p
.
getKeyCount
(),
key
,
value
);
return
p
;
...
...
@@ -240,7 +242,7 @@ public class RtreeMap<K, V> extends MVMap<K, V> {
}
}
Page
c
=
p
.
getChildPage
(
index
);
if
(
c
.
getKeyCount
()
>=
maxPageSize
)
{
if
(
c
.
getKeyCount
()
>=
store
.
getMaxPageSize
()
)
{
// split on the way down
c
=
c
.
copyOnWrite
(
writeVersion
);
Page
split
=
split
(
c
,
writeVersion
);
...
...
@@ -249,9 +251,9 @@ public class RtreeMap<K, V> extends MVMap<K, V> {
p
.
setChild
(
index
,
c
);
p
.
insertNode
(
index
,
getBounds
(
split
),
split
);
// now we are not sure where to add
return
add
(
p
,
writeVersion
,
key
,
value
,
maxPageSize
);
return
add
(
p
,
writeVersion
,
key
,
value
);
}
Page
c2
=
add
(
c
,
writeVersion
,
key
,
value
,
maxPageSize
);
Page
c2
=
add
(
c
,
writeVersion
,
key
,
value
);
p
=
p
.
copyOnWrite
(
writeVersion
);
Object
bounds
=
p
.
getKey
(
index
);
keyType
.
increaseBounds
(
bounds
,
key
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/Test
Rt
ree.java
→
h2/src/test/org/h2/test/store/Test
MVRT
ree.java
浏览文件 @
7ef5bbc4
...
...
@@ -22,7 +22,7 @@ import org.h2.util.New;
/**
* Tests the r-tree.
*/
public
class
Test
Rt
ree
extends
TestMVStore
{
public
class
Test
MVRT
ree
extends
TestMVStore
{
/**
* Run just this test.
...
...
@@ -46,7 +46,7 @@ public class TestRtree extends TestMVStore {
MVStore
s
;
s
=
openStore
(
fileName
);
// s.setMaxPageSize(50);
Rt
reeMap
<
SpatialKey
,
String
>
r
=
s
.
openMap
(
"data"
,
"r"
,
"s2"
,
""
);
MVRT
reeMap
<
SpatialKey
,
String
>
r
=
s
.
openMap
(
"data"
,
"r"
,
"s2"
,
""
);
// r.setQuadraticSplit(true);
Random
rand
=
new
Random
(
1
);
int
len
=
1000
;
...
...
@@ -108,7 +108,7 @@ public class TestRtree extends TestMVStore {
FileUtils
.
delete
(
fileName
);
MVStore
s
;
s
=
openStore
(
fileName
);
Rt
reeMap
<
SpatialKey
,
String
>
r
=
s
.
openMap
(
"data"
,
"r"
,
"s2"
,
""
);
MVRT
reeMap
<
SpatialKey
,
String
>
r
=
s
.
openMap
(
"data"
,
"r"
,
"s2"
,
""
);
add
(
r
,
"Bern"
,
46.57
,
7.27
,
124381
);
add
(
r
,
"Basel"
,
47.34
,
7.36
,
170903
);
add
(
r
,
"Zurich"
,
47.22
,
8.33
,
376008
);
...
...
@@ -134,7 +134,7 @@ public class TestRtree extends TestMVStore {
s
.
close
();
}
private
static
void
add
(
Rt
reeMap
<
SpatialKey
,
String
>
r
,
String
name
,
double
y
,
double
x
,
int
population
)
{
private
static
void
add
(
MVRT
reeMap
<
SpatialKey
,
String
>
r
,
String
name
,
double
y
,
double
x
,
int
population
)
{
int
id
=
r
.
size
();
float
a
=
(
float
)
((
int
)
x
+
(
x
-
(
int
)
x
)
*
5
/
3
);
float
b
=
50
-
(
float
)
((
int
)
y
+
(
y
-
(
int
)
y
)
*
5
/
3
);
...
...
@@ -143,7 +143,7 @@ public class TestRtree extends TestMVStore {
r
.
put
(
k
,
name
);
}
private
static
void
render
(
Rt
reeMap
<
SpatialKey
,
String
>
r
,
String
fileName
)
{
private
static
void
render
(
MVRT
reeMap
<
SpatialKey
,
String
>
r
,
String
fileName
)
{
int
width
=
1000
,
height
=
500
;
BufferedImage
img
=
new
BufferedImage
(
width
,
height
,
BufferedImage
.
TYPE_INT_ARGB
);
Graphics2D
g2d
=
(
Graphics2D
)
img
.
getGraphics
();
...
...
@@ -199,7 +199,7 @@ public class TestRtree extends TestMVStore {
String
fileName
=
getBaseDir
()
+
"/testRtreeRandom.h3"
;
FileUtils
.
delete
(
fileName
);
MVStore
s
=
openStore
(
fileName
);
Rt
reeMap
<
SpatialKey
,
String
>
m
=
s
.
openMap
(
"data"
,
"r"
,
"s2"
,
""
);
MVRT
reeMap
<
SpatialKey
,
String
>
m
=
s
.
openMap
(
"data"
,
"r"
,
"s2"
,
""
);
HashMap
<
SpatialKey
,
String
>
map
=
new
HashMap
<
SpatialKey
,
String
>();
Random
rand
=
new
Random
(
1
);
int
operationCount
=
1000
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMVStore.java
浏览文件 @
7ef5bbc4
...
...
@@ -113,7 +113,7 @@ public class TestMVStore extends TestBase {
assertEquals
(
"World"
,
mOld
.
get
(
"2"
));
m
.
put
(
"1"
,
"Hi"
);
m
.
remove
(
"2"
);
assertEquals
(
"Welt"
,
m
.
remove
(
"2"
)
);
s
.
store
();
s
.
close
();
...
...
@@ -351,10 +351,11 @@ public class TestMVStore extends TestBase {
// System.out.println("get: " + (System.currentTimeMillis() - t));
// t = System.currentTimeMillis();
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
m
.
remove
(
i
);
assertEquals
(
"Hello World"
,
m
.
remove
(
i
)
);
}
// System.out.println("remove: " + (System.currentTimeMillis() - t));
// System.out.println();
assertEquals
(
null
,
m
.
get
(
0
));
assertEquals
(
0
,
m
.
size
());
s
.
close
();
}
...
...
@@ -414,7 +415,7 @@ public class TestMVStore extends TestBase {
s
.
store
();
// System.out.println("store: " + (System.currentTimeMillis() - t));
// System.out.println(p.getTop(5));
m
.
remove
(
0
);
assertEquals
(
"hello 0"
,
m
.
remove
(
0
)
);
assertNull
(
m
.
get
(
0
));
for
(
int
i
=
1
;
i
<
count
;
i
++)
{
assertEquals
(
"hello "
+
i
,
m
.
get
(
i
));
...
...
@@ -492,7 +493,7 @@ public class TestMVStore extends TestBase {
s
.
store
();
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
assertEquals
(
"Hello"
,
m
.
get
(
i
));
m
.
remove
(
i
);
assertEquals
(
"Hello"
,
m
.
remove
(
i
)
);
}
s
.
store
();
s
.
close
();
...
...
@@ -527,8 +528,13 @@ public class TestMVStore extends TestBase {
break
;
case
1
:
log
(
i
+
": remove "
+
k
);
m
.
remove
(
k
);
map
.
remove
(
k
);
Integer
expected
=
map
.
remove
(
k
);
Integer
got
=
m
.
remove
(
k
);
if
(
expected
==
null
)
{
assertNull
(
got
);
}
else
{
assertEquals
(
expected
,
got
);
}
compareAll
=
true
;
break
;
default
:
...
...
@@ -637,7 +643,7 @@ public class TestMVStore extends TestBase {
m
.
put
(
i
,
"hello "
+
i
);
}
s
.
store
();
m
.
remove
(
0
);
assertEquals
(
"hello 0"
,
m
.
remove
(
0
)
);
assertNull
(
m
.
get
(
0
));
for
(
int
i
=
1
;
i
<
3
;
i
++)
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMapFactory.java
浏览文件 @
7ef5bbc4
...
...
@@ -23,7 +23,7 @@ public class TestMapFactory implements MapFactory {
if
(
mapType
.
equals
(
"s"
))
{
return
new
SequenceMap
<
K
,
V
>(
store
,
id
,
name
,
keyType
,
valueType
,
createVersion
);
}
else
if
(
mapType
.
equals
(
"r"
))
{
return
new
Rt
reeMap
<
K
,
V
>(
store
,
id
,
name
,
keyType
,
valueType
,
createVersion
);
return
new
MVRT
reeMap
<
K
,
V
>(
store
,
id
,
name
,
keyType
,
valueType
,
createVersion
);
}
else
{
throw
new
RuntimeException
(
"Unsupported map type "
+
mapType
);
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/store/btree/MVMap.java
浏览文件 @
7ef5bbc4
...
...
@@ -50,13 +50,35 @@ public class MVMap<K, V> {
* Store a key-value pair.
*
* @param key the key
* @param
data
the value
* @param
value
the value
*/
public
void
put
(
K
key
,
V
data
)
{
public
void
put
(
K
key
,
V
value
)
{
checkWrite
();
Page
oldRoot
=
root
;
root
=
put
(
oldRoot
,
store
.
getCurrentVersion
(),
key
,
data
,
store
.
getMaxPageSize
());
markChanged
(
oldRoot
);
long
writeVersion
=
store
.
getCurrentVersion
();
Page
p
=
root
;
if
(
p
==
null
)
{
Object
[]
keys
=
{
key
};
Object
[]
values
=
{
value
};
p
=
Page
.
create
(
this
,
writeVersion
,
1
,
keys
,
values
,
null
,
null
,
null
,
1
,
0
);
}
else
{
p
=
p
.
copyOnWrite
(
writeVersion
);
if
(
p
.
getKeyCount
()
>
store
.
getMaxPageSize
())
{
int
at
=
p
.
getKeyCount
()
/
2
;
long
totalCount
=
p
.
getTotalCount
();
Object
k
=
p
.
getKey
(
at
);
Page
split
=
p
.
split
(
at
);
Object
[]
keys
=
{
k
};
long
[]
children
=
{
p
.
getPos
(),
split
.
getPos
()
};
Page
[]
childrenPages
=
{
p
,
split
};
long
[]
counts
=
{
p
.
getTotalCount
(),
split
.
getTotalCount
()
};
p
=
Page
.
create
(
this
,
writeVersion
,
1
,
keys
,
null
,
children
,
childrenPages
,
counts
,
totalCount
,
0
);
// now p is a node; insert continues
}
put
(
p
,
writeVersion
,
key
,
value
);
}
setRoot
(
p
);
}
/**
...
...
@@ -67,42 +89,17 @@ public class MVMap<K, V> {
* @param writeVersion the write version
* @param key the key
* @param value the value (may not be null)
* @param maxPageSize the maximum page size
* @return the root page
*/
protected
Page
put
(
Page
p
,
long
writeVersion
,
Object
key
,
Object
value
,
int
maxPageSize
)
{
if
(
p
==
null
)
{
Object
[]
keys
=
{
key
};
Object
[]
values
=
{
value
};
p
=
Page
.
create
(
this
,
writeVersion
,
1
,
keys
,
values
,
null
,
null
,
null
,
1
,
0
);
return
p
;
}
if
(
p
.
getKeyCount
()
>
maxPageSize
)
{
// only possible if this is the root, else we would have split earlier
// (this requires maxPageSize is fixed)
p
=
p
.
copyOnWrite
(
writeVersion
);
int
at
=
p
.
getKeyCount
()
/
2
;
long
totalCount
=
p
.
getTotalCount
();
Object
k
=
p
.
getKey
(
at
);
Page
split
=
p
.
split
(
at
);
Object
[]
keys
=
{
k
};
long
[]
children
=
{
p
.
getPos
(),
split
.
getPos
()
};
Page
[]
childrenPages
=
{
p
,
split
};
long
[]
counts
=
{
p
.
getTotalCount
(),
split
.
getTotalCount
()
};
p
=
Page
.
create
(
this
,
writeVersion
,
1
,
keys
,
null
,
children
,
childrenPages
,
counts
,
totalCount
,
0
);
// now p is a node; insert continues
}
else
if
(
p
.
isLeaf
())
{
protected
void
put
(
Page
p
,
long
writeVersion
,
Object
key
,
Object
value
)
{
if
(
p
.
isLeaf
())
{
int
index
=
p
.
binarySearch
(
key
);
p
=
p
.
copyOnWrite
(
writeVersion
);
if
(
index
<
0
)
{
index
=
-
index
-
1
;
p
.
insertLeaf
(
index
,
key
,
value
);
}
else
{
p
.
setValue
(
index
,
value
);
}
return
p
;
return
;
}
// p is a node
int
index
=
p
.
binarySearch
(
key
);
...
...
@@ -111,26 +108,24 @@ public class MVMap<K, V> {
}
else
{
index
++;
}
Page
c
=
p
.
getChildPage
(
index
);
if
(
c
.
getKeyCount
()
>=
maxPageSize
)
{
Page
cOld
=
p
.
getChildPage
(
index
);
Page
c
=
cOld
.
copyOnWrite
(
writeVersion
);
if
(
c
.
getKeyCount
()
>=
store
.
getMaxPageSize
())
{
// split on the way down
c
=
c
.
copyOnWrite
(
writeVersion
);
int
at
=
c
.
getKeyCount
()
/
2
;
Object
k
=
c
.
getKey
(
at
);
Page
split
=
c
.
split
(
at
);
p
=
p
.
copyOnWrite
(
writeVersion
);
p
.
setChild
(
index
,
split
);
p
.
insertNode
(
index
,
k
,
c
);
// now we are not sure where to add
return
put
(
p
,
writeVersion
,
key
,
value
,
maxPageSize
);
put
(
p
,
writeVersion
,
key
,
value
);
return
;
}
long
oldSize
=
c
.
getTotalCount
();
Page
c2
=
put
(
c
,
writeVersion
,
key
,
value
,
maxPageSize
);
if
(
c
!=
c2
||
oldSize
!=
c2
.
getTotalCount
())
{
p
=
p
.
copyOnWrite
(
writeVersion
);
p
.
setChild
(
index
,
c2
);
put
(
c
,
writeVersion
,
key
,
value
);
if
(
cOld
!=
c
||
oldSize
!=
c
.
getTotalCount
())
{
p
.
setChild
(
index
,
c
);
}
return
p
;
}
/**
...
...
@@ -285,17 +280,15 @@ public class MVMap<K, V> {
public
void
clear
()
{
checkWrite
();
if
(
root
!=
null
)
{
Page
oldRoot
=
root
;
root
.
removeAllRecursive
();
root
=
null
;
markChanged
(
oldRoot
);
setRoot
(
null
);
}
}
/**
* Remove all entries, and close the map.
*/
public
void
remove
()
{
public
void
remove
Map
()
{
checkWrite
();
if
(
root
!=
null
)
{
root
.
removeAllRecursive
();
...
...
@@ -319,14 +312,23 @@ 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
*/
public
void
remove
(
K
key
)
{
public
V
remove
(
K
key
)
{
checkWrite
();
Page
oldRoot
=
root
;
if
(
oldRoot
!=
null
)
{
root
=
remove
(
oldRoot
,
store
.
getCurrentVersion
(),
key
);
markChanged
(
oldRoot
);
Page
p
=
root
;
if
(
p
==
null
)
{
return
null
;
}
long
writeVersion
=
store
.
getCurrentVersion
();
p
=
p
.
copyOnWrite
(
writeVersion
);
@SuppressWarnings
(
"unchecked"
)
V
result
=
(
V
)
remove
(
p
,
writeVersion
,
key
);
if
(
p
.
getTotalCount
()
==
0
)
{
p
=
null
;
}
setRoot
(
p
);
return
result
;
}
/**
...
...
@@ -335,20 +337,19 @@ public class MVMap<K, V> {
* @param p the page (may not be null)
* @param writeVersion the write version
* @param key the key
* @return the new root page (null if empty)
*/
protected
Page
remove
(
Page
p
,
long
writeVersion
,
Object
key
)
{
protected
Object
remove
(
Page
p
,
long
writeVersion
,
Object
key
)
{
int
index
=
p
.
binarySearch
(
key
);
Object
result
=
null
;
if
(
p
.
isLeaf
())
{
if
(
index
>=
0
)
{
if
(
p
.
getKeyCount
()
==
1
)
{
result
=
p
.
getValue
(
index
);
p
.
remove
(
index
);
if
(
p
.
getKeyCount
()
==
0
)
{
removePage
(
p
);
return
null
;
}
p
=
p
.
copyOnWrite
(
writeVersion
);
p
.
remove
(
index
);
}
return
p
;
return
result
;
}
// node
if
(
index
<
0
)
{
...
...
@@ -356,30 +357,35 @@ public class MVMap<K, V> {
}
else
{
index
++;
}
Page
c
=
p
.
getChildPage
(
index
);
Page
cOld
=
p
.
getChildPage
(
index
);
Page
c
=
cOld
.
copyOnWrite
(
writeVersion
);
long
oldCount
=
c
.
getTotalCount
();
Page
c2
=
remove
(
c
,
writeVersion
,
key
);
if
(
c2
==
null
)
{
result
=
remove
(
c
,
writeVersion
,
key
);
if
(
oldCount
==
c
.
getTotalCount
())
{
return
null
;
}
// TODO merge if the c key count is below the threshold
if
(
c
.
getTotalCount
()
==
0
)
{
// this child was deleted
p
=
p
.
copyOnWrite
(
writeVersion
);
p
.
remove
(
index
);
if
(
p
.
getKeyCount
()
==
0
)
{
p
.
setChild
(
index
,
c
);
removePage
(
p
);
p
=
p
.
getChildPage
(
0
);
}
else
{
p
.
remove
(
index
);
}
}
else
if
(
oldCount
!=
c2
.
getTotalCount
())
{
p
=
p
.
copyOnWrite
(
writeVersion
);
p
.
setChild
(
index
,
c2
);
}
else
{
p
.
setChild
(
index
,
c
);
}
return
p
;
return
result
;
}
protected
void
markChanged
(
Page
old
Root
)
{
if
(
oldRoot
!=
r
oot
)
{
protected
void
setRoot
(
Page
new
Root
)
{
if
(
root
!=
newR
oot
)
{
long
v
=
store
.
getCurrentVersion
();
if
(!
oldRoots
.
containsKey
(
v
))
{
oldRoots
.
put
(
v
,
oldR
oot
);
oldRoots
.
put
(
v
,
r
oot
);
}
root
=
newRoot
;
store
.
markChanged
(
this
);
}
}
...
...
@@ -516,7 +522,7 @@ public class MVMap<K, V> {
void
rollbackTo
(
long
version
)
{
checkWrite
();
if
(
version
<
createVersion
)
{
remove
();
remove
Map
();
}
else
{
// iterating in ascending order, and pick the last version -
// this is not terribly efficient if there are many versions
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/store/btree/MVStore.java
浏览文件 @
7ef5bbc4
...
...
@@ -38,6 +38,7 @@ header:
blockSize=4096
TODO:
- rename commit to incrementVersion
- implement complete java.util.Map interface
- limited support for writing to old versions (branches)
- atomic test-and-set (when supporting concurrent writes)
...
...
@@ -47,6 +48,7 @@ TODO:
- 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
...
...
@@ -56,6 +58,7 @@ TODO:
- 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.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论