Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
a5d679bf
提交
a5d679bf
authored
12 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
A persistent tree map (work in progress).
上级
e392b3bf
显示空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
212 行增加
和
121 行删除
+212
-121
TestTreeMapStore.java
h2/src/test/org/h2/test/unit/TestTreeMapStore.java
+58
-11
BtreeMap.java
h2/src/tools/org/h2/dev/store/btree/BtreeMap.java
+52
-0
BtreeMapStore.java
h2/src/tools/org/h2/dev/store/btree/BtreeMapStore.java
+40
-27
Page.java
h2/src/tools/org/h2/dev/store/btree/Page.java
+62
-83
没有找到文件。
h2/src/test/org/h2/test/unit/TestTreeMapStore.java
浏览文件 @
a5d679bf
...
...
@@ -43,7 +43,8 @@ public class TestTreeMapStore extends TestBase {
FileUtils
.
delete
(
fileName
);
BtreeMapStore
s
=
BtreeMapStore
.
open
(
fileName
);
BtreeMap
<
Integer
,
String
>
m
=
s
.
openMap
(
"data"
,
Integer
.
class
,
String
.
class
);
int
count
=
10000
;
// int count = 0;
int
count
=
2000
;
// Profiler p = new Profiler();
// p.startCollecting();
// long t = System.currentTimeMillis();
...
...
@@ -71,6 +72,14 @@ public class TestTreeMapStore extends TestBase {
for
(
int
i
=
1
;
i
<
count
;
i
++)
{
assertEquals
(
"hello "
+
i
,
m
.
get
(
i
));
}
for
(
int
i
=
1
;
i
<
count
;
i
++)
{
m
.
remove
(
i
);
}
s
.
store
();
assertNull
(
m
.
get
(
0
));
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
assertNull
(
m
.
get
(
i
));
}
s
.
close
();
}
...
...
@@ -95,6 +104,24 @@ public class TestTreeMapStore extends TestBase {
assertTrue
(
"initial: "
+
initialLength
+
" len: "
+
len
,
len
<=
initialLength
*
3
);
}
}
long
len
=
FileUtils
.
size
(
fileName
);
// System.out.println("len0: " + len);
BtreeMapStore
s
=
BtreeMapStore
.
open
(
fileName
);
BtreeMap
<
Integer
,
String
>
m
=
s
.
openMap
(
"data"
,
Integer
.
class
,
String
.
class
);
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
m
.
remove
(
i
);
}
s
.
store
();
s
.
compact
();
s
.
close
();
len
=
FileUtils
.
size
(
fileName
);
// System.out.println("len1: " + len);
s
=
BtreeMapStore
.
open
(
fileName
);
m
=
s
.
openMap
(
"data"
,
Integer
.
class
,
String
.
class
);
s
.
compact
();
s
.
close
();
len
=
FileUtils
.
size
(
fileName
);
// System.out.println("len2: " + len);
}
private
void
testReuseSpace
()
{
...
...
@@ -129,16 +156,35 @@ public class TestTreeMapStore extends TestBase {
BtreeMap
<
Integer
,
Integer
>
m
=
s
.
openMap
(
"data"
,
Integer
.
class
,
Integer
.
class
);
TreeMap
<
Integer
,
Integer
>
map
=
new
TreeMap
<
Integer
,
Integer
>();
Random
r
=
new
Random
(
1
);
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
int
k
=
r
.
nextInt
(
20
);
int
operationCount
=
1000
;
int
maxValue
=
20
;
for
(
int
i
=
0
;
i
<
operationCount
;
i
++)
{
int
k
=
r
.
nextInt
(
maxValue
);
int
v
=
r
.
nextInt
();
if
(
r
.
nextBoolean
())
{
boolean
compareAll
;
switch
(
r
.
nextInt
(
3
))
{
case
0
:
m
.
put
(
k
,
v
);
map
.
put
(
k
,
v
);
}
else
{
compareAll
=
true
;
break
;
case
1
:
m
.
remove
(
k
);
map
.
remove
(
k
);
compareAll
=
true
;
break
;
default
:
Integer
a
=
map
.
get
(
k
);
Integer
b
=
m
.
get
(
k
);
if
(
a
==
null
||
b
==
null
)
{
assertTrue
(
a
==
b
);
}
else
{
assertEquals
(
a
.
intValue
(),
b
.
intValue
());
}
compareAll
=
false
;
break
;
}
if
(
compareAll
)
{
Iterator
<
Integer
>
it
=
m
.
keyIterator
(
null
);
Iterator
<
Integer
>
it2
=
map
.
keySet
().
iterator
();
while
(
it2
.
hasNext
())
{
...
...
@@ -147,6 +193,7 @@ public class TestTreeMapStore extends TestBase {
}
assertFalse
(
it
.
hasNext
());
}
}
s
.
close
();
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/store/btree/BtreeMap.java
浏览文件 @
a5d679bf
...
...
@@ -395,6 +395,27 @@ public class BtreeMap<K, V> {
return
name
;
}
/**
* Read a variable size long.
*
* @param buff the source buffer
* @return the value
*/
static
long
readVarLong
(
ByteBuffer
buff
)
{
long
x
=
buff
.
get
();
if
(
x
>=
0
)
{
return
x
;
}
x
&=
0x7f
;
for
(
int
s
=
7
;;
s
+=
7
)
{
long
b
=
buff
.
get
();
x
|=
(
b
&
0x7f
)
<<
s
;
if
(
b
>=
0
)
{
return
x
;
}
}
}
/**
* Read a variable size int.
*
...
...
@@ -449,6 +470,23 @@ public class BtreeMap<K, V> {
return
5
;
}
/**
* Get the length of the variable size long.
*
* @param x the value
* @return the length in bytes
*/
static
int
getVarLongLen
(
long
x
)
{
int
i
=
1
;
while
(
true
)
{
x
>>>=
7
;
if
(
x
==
0
)
{
return
i
;
}
i
++;
}
}
/**
* Write a variable size int.
*
...
...
@@ -463,4 +501,18 @@ public class BtreeMap<K, V> {
buff
.
put
((
byte
)
x
);
}
/**
* Write a variable size int.
*
* @param buff the target buffer
* @param x the value
*/
static
void
writeVarLong
(
ByteBuffer
buff
,
long
x
)
{
while
((
x
&
~
0x7f
)
!=
0
)
{
buff
.
put
((
byte
)
(
0x80
|
(
x
&
0x7f
)));
x
>>>=
7
;
}
buff
.
put
((
byte
)
x
);
}
}
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/store/btree/BtreeMapStore.java
浏览文件 @
a5d679bf
...
...
@@ -83,6 +83,10 @@ public class BtreeMapStore {
private
int
loadCount
;
// TODO support quota (per map, per storage)
// TODO support r-tree
// TODO support triggers and events (possibly on a different layer)
private
BtreeMapStore
(
String
fileName
)
{
this
.
fileName
=
fileName
;
}
...
...
@@ -260,7 +264,10 @@ public class BtreeMapStore {
for
(
BtreeMap
<?,
?>
m
:
mapsChanged
.
values
())
{
meta
.
put
(
"map."
+
m
.
getName
(),
String
.
valueOf
(
Long
.
MAX_VALUE
)
+
","
+
m
.
getKeyType
().
getName
()
+
","
+
m
.
getValueType
().
getName
());
lenEstimate
+=
m
.
getRoot
().
lengthIncludingTempChildren
();
Page
p
=
m
.
getRoot
();
if
(
p
!=
null
)
{
lenEstimate
+=
p
.
lengthIncludingTempChildren
();
}
}
int
blockId
=
++
lastBlockId
;
Block
b
=
new
Block
(
blockId
);
...
...
@@ -311,7 +318,10 @@ public class BtreeMapStore {
meta
.
put
(
"block."
+
b
.
id
,
b
.
toString
());
int
count
=
0
;
for
(
BtreeMap
<?,
?>
m
:
mapsChanged
.
values
())
{
count
+=
m
.
getRoot
().
countTemp
();
Page
p
=
m
.
getRoot
();
if
(
p
!=
null
)
{
count
+=
p
.
countTemp
();
}
}
count
+=
meta
.
getRoot
().
countTemp
();
...
...
@@ -329,7 +339,10 @@ public class BtreeMapStore {
buff
.
putInt
(
b
.
id
);
buff
.
putInt
(
metaRootOffset
);
for
(
BtreeMap
<?,
?>
m
:
mapsChanged
.
values
())
{
m
.
getRoot
().
storeTemp
(
buff
);
Page
p
=
m
.
getRoot
();
if
(
p
!=
null
)
{
p
.
storeTemp
(
buff
);
}
}
meta
.
getRoot
().
storeTemp
(
buff
);
if
(
buff
.
hasRemaining
())
{
...
...
@@ -507,6 +520,9 @@ public class BtreeMapStore {
Class
<?>
vt
=
BtreeMap
.
getClass
(
d
[
2
]);
BtreeMap
<?,
?>
oldData
=
BtreeMap
.
open
(
this
,
"old-"
+
k
,
kt
,
vt
);
long
oldDataRoot
=
Long
.
parseLong
(
d
[
0
]);
if
(
oldDataRoot
==
0
)
{
// no rows
}
else
{
oldData
.
setRoot
(
oldDataRoot
);
@SuppressWarnings
(
"unchecked"
)
BtreeMap
<
Object
,
Object
>
data
=
(
BtreeMap
<
Object
,
Object
>)
maps
.
get
(
k
);
...
...
@@ -530,6 +546,7 @@ public class BtreeMapStore {
}
}
}
}
for
(
int
o
:
oldBlocks
)
{
blocks
.
remove
(
o
);
}
...
...
@@ -594,7 +611,7 @@ public class BtreeMapStore {
/**
* A block of data.
*/
static
class
Block
implements
Comparable
<
Block
>
{
static
class
Block
{
public
int
collectPriority
;
int
id
;
long
start
;
...
...
@@ -632,10 +649,6 @@ public class BtreeMapStore {
return
entryCount
==
0
?
0
:
100
*
liveCount
/
entryCount
;
}
public
int
compareTo
(
Block
o
)
{
return
start
==
o
.
start
?
0
:
start
<
o
.
start
?
-
1
:
1
;
}
public
int
hashCode
()
{
return
id
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/store/btree/Page.java
浏览文件 @
a5d679bf
...
...
@@ -63,6 +63,8 @@ class Page {
}
private
Page
copyOnWrite
()
{
// TODO avoid creating objects (arrays) that are then not used
// possibly add shortcut for copy with add / copy with remove
long
t
=
map
.
getTransaction
();
if
(
transaction
==
t
)
{
return
this
;
...
...
@@ -103,15 +105,6 @@ class Page {
return
id
;
}
/**
* Set the page id.
*
* @param id the new id
*/
void
setId
(
long
id
)
{
this
.
id
=
id
;
}
/**
* Get the value for the given key, or null if not found.
*
...
...
@@ -259,7 +252,7 @@ class Page {
}
}
private
int
size
()
{
private
int
keyCount
()
{
return
keys
.
length
;
}
...
...
@@ -325,9 +318,9 @@ class Page {
parent
.
children
[
parentIndex
]
=
p
.
id
;
}
if
(!
p
.
isLeaf
())
{
if
(
p
.
size
()
>=
MAX_SIZE
)
{
if
(
p
.
keyCount
()
>=
MAX_SIZE
)
{
// TODO almost duplicate code
int
pos
=
p
.
size
()
/
2
;
int
pos
=
p
.
keyCount
()
/
2
;
Object
k
=
p
.
keys
[
pos
];
Page
split
=
p
.
splitNode
(
pos
);
if
(
parent
==
null
)
{
...
...
@@ -354,8 +347,8 @@ class Page {
}
index
=
-
index
-
1
;
p
.
insert
(
index
,
key
,
value
,
0
);
if
(
p
.
size
()
>=
MAX_SIZE
)
{
int
pos
=
p
.
size
()
/
2
;
if
(
p
.
keyCount
()
>=
MAX_SIZE
)
{
int
pos
=
p
.
keyCount
()
/
2
;
Object
k
=
p
.
keys
[
pos
];
Page
split
=
p
.
splitLeaf
(
pos
);
if
(
parent
==
null
)
{
...
...
@@ -387,43 +380,39 @@ class Page {
* @return the new root node
*/
static
Page
remove
(
Page
p
,
Object
key
)
{
// TODO avoid separate lookup
if
(
p
.
find
(
key
)
==
null
)
{
return
p
;
}
p
=
p
.
copyOnWrite
();
Page
top
=
p
;
Page
parent
=
null
;
int
parentIndex
=
0
;
while
(
true
)
{
if
(
parent
!=
null
)
{
parent
.
children
[
parentIndex
]
=
p
.
id
;
}
int
index
=
p
.
findKey
(
key
);
if
(
p
.
isLeaf
())
{
if
(
index
>=
0
)
{
if
(
p
.
keyCount
()
==
1
)
{
return
null
;
}
p
=
p
.
copyOnWrite
();
p
.
remove
(
index
);
}
else
{
// not found?
throw
new
RuntimeException
(
"Not found: "
+
key
);
}
if
(
p
.
size
()
==
0
)
{
if
(
parent
!=
null
)
{
parent
.
remove
(
parentIndex
);
// TODO recursive, or on the way down
// not found
}
return
p
;
}
break
;
}
// node
if
(
index
<
0
)
{
index
=
-
index
-
1
;
}
parent
=
p
;
parentIndex
=
index
;
p
=
p
.
map
.
readPage
(
p
.
children
[
index
]);
Page
c
=
p
.
map
.
readPage
(
p
.
children
[
index
]);
Page
c2
=
remove
(
c
,
key
);
if
(
c2
==
c
)
{
// not found
}
else
if
(
c2
==
null
)
{
// child was deleted
p
=
p
.
copyOnWrite
();
p
.
remove
(
index
);
if
(
p
.
keyCount
()
==
0
)
{
p
=
c2
;
}
return
top
;
}
else
{
p
=
p
.
copyOnWrite
();
p
.
children
[
index
]
=
c2
.
id
;
}
return
p
;
}
private
void
insert
(
int
index
,
Object
key
,
Object
value
,
long
child
)
{
...
...
@@ -461,16 +450,6 @@ class Page {
}
}
// int x = findKey(key);
// if (x >= 0) {
// return values[x];
// }
// x = -x - 1;
// Page p = map.readPage(children[x]);
// return p.find(key);
// return null;
// }
private
void
read
(
ByteBuffer
buff
)
{
boolean
node
=
buff
.
get
()
==
1
;
if
(
node
)
{
...
...
@@ -502,9 +481,9 @@ class Page {
void
write
(
ByteBuffer
buff
)
{
if
(
children
!=
null
)
{
buff
.
put
((
byte
)
1
);
int
size
=
children
.
length
;
BtreeMap
.
writeVarInt
(
buff
,
size
);
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
int
len
=
children
.
length
;
BtreeMap
.
writeVarInt
(
buff
,
len
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
long
c
=
map
.
readPage
(
children
[
i
]).
storedId
;
buff
.
putLong
(
c
);
if
(
i
<
keys
.
length
)
{
...
...
@@ -513,9 +492,9 @@ class Page {
}
}
else
{
buff
.
put
((
byte
)
0
);
int
size
=
keys
.
length
;
BtreeMap
.
writeVarInt
(
buff
,
size
);
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
int
len
=
keys
.
length
;
BtreeMap
.
writeVarInt
(
buff
,
len
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
map
.
getKeyType
().
write
(
buff
,
keys
[
i
]);
map
.
getValueType
().
write
(
buff
,
values
[
i
]);
}
...
...
@@ -528,17 +507,17 @@ class Page {
* @return the length
*/
int
lengthIncludingTempChildren
()
{
int
len
=
length
();
int
byteCount
=
length
();
if
(
children
!=
null
)
{
int
size
=
children
.
length
;
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
int
len
=
children
.
length
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
long
c
=
children
[
i
];
if
(
c
<
0
)
{
len
+=
map
.
readPage
(
c
).
lengthIncludingTempChildren
();
byteCount
+=
map
.
readPage
(
c
).
lengthIncludingTempChildren
();
}
}
}
return
len
;
return
byteCount
;
}
/**
...
...
@@ -551,8 +530,8 @@ class Page {
this
.
storedId
=
pageId
;
pageId
+=
length
();
if
(
children
!=
null
)
{
int
size
=
children
.
length
;
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
int
len
=
children
.
length
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
long
c
=
children
[
i
];
if
(
c
<
0
)
{
pageId
=
map
.
readPage
(
c
).
updatePageIds
(
pageId
);
...
...
@@ -571,8 +550,8 @@ class Page {
long
storeTemp
(
ByteBuffer
buff
)
{
write
(
buff
);
if
(
children
!=
null
)
{
int
size
=
children
.
length
;
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
int
len
=
children
.
length
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
long
c
=
children
[
i
];
if
(
c
<
0
)
{
children
[
i
]
=
map
.
readPage
(
c
).
storeTemp
(
buff
);
...
...
@@ -608,25 +587,25 @@ class Page {
* @return the length
*/
int
length
()
{
int
len
=
1
;
int
byteCount
=
1
;
if
(
children
!=
null
)
{
int
size
=
children
.
length
;
len
+=
BtreeMap
.
getVarIntLen
(
size
);
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
len
+=
8
;
int
len
=
children
.
length
;
byteCount
+=
BtreeMap
.
getVarIntLen
(
len
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
byteCount
+=
8
;
if
(
i
<
keys
.
length
)
{
len
+=
map
.
getKeyType
().
length
(
keys
[
i
]);
byteCount
+=
map
.
getKeyType
().
length
(
keys
[
i
]);
}
}
}
else
{
int
size
=
keys
.
length
;
len
+=
BtreeMap
.
getVarIntLen
(
size
);
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
len
+=
map
.
getKeyType
().
length
(
keys
[
i
]);
len
+=
map
.
getValueType
().
length
(
values
[
i
]);
int
len
=
keys
.
length
;
byteCount
+=
BtreeMap
.
getVarIntLen
(
len
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
byteCount
+=
map
.
getKeyType
().
length
(
keys
[
i
]);
byteCount
+=
map
.
getValueType
().
length
(
values
[
i
]);
}
}
return
len
;
return
byteCount
;
}
private
static
void
copyWithGap
(
Object
src
,
Object
dst
,
int
oldSize
,
int
gapIndex
)
{
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论