Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
bd50328e
提交
bd50328e
authored
12 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
A persistent multi-version map: support store() in a background thread
上级
0aa0c2be
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
无相关合并请求
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
65 行增加
和
31 行删除
+65
-31
mvstore.html
h2/src/docsrc/html/mvstore.html
+5
-1
MVMap.java
h2/src/main/org/h2/mvstore/MVMap.java
+4
-2
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+24
-20
Page.java
h2/src/main/org/h2/mvstore/Page.java
+5
-1
ObjectType.java
h2/src/main/org/h2/mvstore/type/ObjectType.java
+1
-1
TestMVStore.java
h2/src/test/org/h2/test/store/TestMVStore.java
+26
-6
没有找到文件。
h2/src/docsrc/html/mvstore.html
浏览文件 @
bd50328e
...
...
@@ -243,10 +243,14 @@ Caching is done on the page level.
The page cache is a concurrent LIRS cache,
which should be resistant against scan operations.
</p><p>
Concurrent modification operations on the maps are currently not supported,
Concurrent modification operations on a map are currently not supported
(the same as
<code>
HashMap
</code>
and
<code>
TreeMap
</code>
),
however it is planned to support an additional map implementation
that supports concurrent writes
(at the cost of speed if used in a single thread, same as
<code>
ConcurrentHashMap
</code>
).
</p><p>
Storing changes can occur concurrently to modifying the data,
as
<code>
store()
</code>
operates on a snapshot.
</p>
<h3>
Log Structured Storage
</h3>
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/MVMap.java
浏览文件 @
bd50328e
...
...
@@ -682,9 +682,11 @@ public class MVMap<K, V> extends AbstractMap<K, V>
* Set the position of the root page.
*
* @param rootPos the position, 0 for empty
* @param version the version of the root
*/
void
setRootPos
(
long
rootPos
)
{
void
setRootPos
(
long
rootPos
,
long
version
)
{
root
=
rootPos
==
0
?
Page
.
createEmpty
(
this
,
-
1
)
:
readPage
(
rootPos
);
root
.
setVersion
(
version
);
}
/**
...
...
@@ -899,7 +901,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
Page
newest
=
null
;
// need to copy because it can change
Page
r
=
root
;
if
(
r
.
getVersion
()
==
version
)
{
if
(
r
.
getVersion
()
<=
version
&&
r
.
getVersion
()
>=
0
)
{
newest
=
r
;
}
else
{
// find the newest page that has a getVersion() <= version
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
bd50328e
...
...
@@ -40,10 +40,9 @@ header:
H:3,...
TODO:
- build script
- test concurrent storing in a background thread
- store store creation in file header, and seconds since creation
-- in chunk header (plus a counter)
-- in chunk header (plus a counter)
- ensure time never goes backwards
- recovery: keep some old chunks; don't overwritten
-- for 5 minutes (configurable)
- allocate memory with Utils.newBytes and so on
...
...
@@ -91,7 +90,8 @@ TODO:
- and maps without keys (counted b-tree)
- use a small object cache (StringCache)
- dump values
- tool to import / manipulate CSV files
- tool to import / manipulate CSV files (maybe concurrently)
- map split / merge (fast if no overlap)
*/
...
...
@@ -216,7 +216,7 @@ public class MVStore {
String
r
=
oldMeta
.
get
(
"root."
+
template
.
getId
());
long
rootPos
=
r
==
null
?
0
:
Long
.
parseLong
(
r
);
MVMap
<?,
?>
m
=
template
.
openReadOnly
();
m
.
setRootPos
(
rootPos
);
m
.
setRootPos
(
rootPos
,
version
);
return
(
T
)
m
;
}
...
...
@@ -286,7 +286,7 @@ public class MVStore {
root
=
r
==
null
?
0
:
Long
.
parseLong
(
r
);
}
m
.
open
(
this
,
c
);
m
.
setRootPos
(
root
);
m
.
setRootPos
(
root
,
-
1
);
maps
.
put
(
name
,
m
);
return
(
T
)
m
;
}
...
...
@@ -317,7 +317,7 @@ public class MVStore {
}
c
=
readChunkHeader
(
c
.
start
);
MVMap
<
String
,
String
>
oldMeta
=
meta
.
openReadOnly
();
oldMeta
.
setRootPos
(
c
.
metaRootPos
);
oldMeta
.
setRootPos
(
c
.
metaRootPos
,
version
);
return
oldMeta
;
}
...
...
@@ -414,7 +414,7 @@ public class MVStore {
Chunk
header
=
readChunkHeader
(
rootChunkStart
);
lastChunkId
=
header
.
id
;
chunks
.
put
(
header
.
id
,
header
);
meta
.
setRootPos
(
header
.
metaRootPos
);
meta
.
setRootPos
(
header
.
metaRootPos
,
-
1
);
Iterator
<
String
>
it
=
meta
.
keyIterator
(
"chunk."
);
while
(
it
.
hasNext
())
{
String
s
=
it
.
next
();
...
...
@@ -553,6 +553,10 @@ public class MVStore {
return
currentVersion
;
}
int
currentUnsavedPageCount
=
unsavedPageCount
;
long
storeVersion
=
currentVersion
;
long
version
=
incrementVersion
();
// the last chunk was not completely correct in the last store()
// this needs to be updated now (it's better not to update right after
// storing, because that would modify the meta map again)
...
...
@@ -565,7 +569,7 @@ public class MVStore {
c
.
maxLengthLive
=
Long
.
MAX_VALUE
;
c
.
start
=
Long
.
MAX_VALUE
;
c
.
length
=
Integer
.
MAX_VALUE
;
c
.
version
=
currentVersion
+
1
;
c
.
version
=
version
;
chunks
.
put
(
c
.
id
,
c
);
meta
.
put
(
"chunk."
+
c
.
id
,
c
.
asString
());
...
...
@@ -574,7 +578,7 @@ public class MVStore {
if
(
m
==
meta
||
!
m
.
hasUnsavedChanges
())
{
continue
;
}
Page
p
=
m
.
getRoot
();
Page
p
=
m
.
openVersion
(
storeVersion
).
getRoot
();
if
(
p
.
getTotalCount
()
==
0
)
{
meta
.
put
(
"root."
+
m
.
getId
(),
"0"
);
}
else
{
...
...
@@ -606,7 +610,7 @@ public class MVStore {
if
(
m
==
meta
||
!
m
.
hasUnsavedChanges
())
{
continue
;
}
Page
p
=
m
.
getRoot
();
Page
p
=
m
.
openVersion
(
storeVersion
).
getRoot
();
if
(
p
.
getTotalCount
()
>
0
)
{
long
root
=
p
.
writeUnsavedRecursive
(
c
,
buff
);
meta
.
put
(
"root."
+
m
.
getId
(),
""
+
root
);
...
...
@@ -654,11 +658,11 @@ public class MVStore {
rootChunkStart
=
filePos
;
revertTemp
();
long
version
=
incrementVersion
();
// write the new version (after the commit)
writeFileHeader
();
shrinkFileIfPossible
(
1
);
unsavedPageCount
=
0
;
// some pages might have been changed in the meantime (in the newest version)
unsavedPageCount
=
Math
.
max
(
0
,
unsavedPageCount
-
currentUnsavedPageCount
);
return
version
;
}
...
...
@@ -756,7 +760,7 @@ public class MVStore {
return
false
;
}
for
(
MVMap
<?,
?>
m
:
mapsChanged
.
values
())
{
if
(
m
.
hasUnsavedChanges
())
{
if
(
m
==
meta
||
m
.
hasUnsavedChanges
())
{
return
true
;
}
}
...
...
@@ -867,6 +871,9 @@ public class MVStore {
}
Chunk
.
fromHeader
(
buff
,
chunk
.
start
);
int
chunkLength
=
chunk
.
length
;
// mark a change, even if it doesn't look like there was a change
// as changes in the metadata alone are not detected
markChanged
(
meta
);
while
(
buff
.
position
()
<
chunkLength
)
{
int
start
=
buff
.
position
();
int
pageLength
=
buff
.
getInt
();
...
...
@@ -1161,14 +1168,11 @@ public class MVStore {
if
(
last
!=
null
)
{
if
(
last
.
version
>=
version
)
{
revertTemp
();
}
if
(
last
.
version
>
version
)
{
loadFromFile
=
true
;
while
(
last
!=
null
&&
last
.
version
>
version
)
{
chunks
.
remove
(
lastChunkId
);
do
{
last
=
chunks
.
remove
(
lastChunkId
);
lastChunkId
--;
last
=
chunks
.
get
(
lastChunkId
);
}
}
while
(
last
.
version
>
version
&&
chunks
.
size
()
>
0
);
rootChunkStart
=
last
.
start
;
writeFileHeader
();
readFileHeader
();
...
...
@@ -1183,7 +1187,7 @@ public class MVStore {
if
(
loadFromFile
)
{
String
r
=
meta
.
get
(
"root."
+
m
.
getId
());
long
root
=
r
==
null
?
0
:
Long
.
parseLong
(
r
);
m
.
setRootPos
(
root
);
m
.
setRootPos
(
root
,
version
);
}
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/Page.java
浏览文件 @
bd50328e
...
...
@@ -37,7 +37,7 @@ public class Page {
private
static
final
Object
[]
EMPTY_OBJECT_ARRAY
=
new
Object
[
0
];
private
final
MVMap
<?,
?>
map
;
private
final
long
version
;
private
long
version
;
private
long
pos
;
private
long
totalCount
;
private
int
keyCount
;
...
...
@@ -886,4 +886,8 @@ public class Page {
return
mem
;
}
void
setVersion
(
long
version
)
{
this
.
version
=
version
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/type/ObjectType.java
浏览文件 @
bd50328e
...
...
@@ -77,7 +77,7 @@ public class ObjectType implements DataType {
static
final
int
TAG_BYTE_ARRAY_0_15
=
104
;
/**
* Contants for floating point synchronization.
* Con
s
tants for floating point synchronization.
*/
static
final
int
FLOAT_ZERO_BITS
=
Float
.
floatToIntBits
(
0.0f
);
static
final
int
FLOAT_ONE_BITS
=
Float
.
floatToIntBits
(
1.0f
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMVStore.java
浏览文件 @
bd50328e
...
...
@@ -111,7 +111,8 @@ public class TestMVStore extends TestBase {
map
=
s
.
openMap
(
"test"
);
for
(
int
i
=
0
;
i
<
1024
;
i
+=
128
)
{
for
(
int
j
=
0
;
j
<
i
;
j
++)
{
map
.
get
(
j
);
String
x
=
map
.
get
(
j
);
assertEquals
(
10240
,
x
.
length
());
}
}
assertEquals
(
expectedReadsForCacheSize
[
cacheSize
],
...
...
@@ -410,11 +411,14 @@ public class TestMVStore extends TestBase {
// concurrently with further modifications)
// this will print Hello World
// System.out.println(oldMap.get(1));
assertEquals
(
"Hello"
,
oldMap
.
get
(
1
));
// System.out.println(oldMap.get(2));
assertEquals
(
"World"
,
oldMap
.
get
(
2
));
oldMap
.
close
();
// print the newest version ("Hi")
// System.out.println(map.get(1));
assertEquals
(
"Hi"
,
map
.
get
(
1
));
// close the store - this doesn't write to disk
s
.
close
();
...
...
@@ -504,12 +508,16 @@ public class TestMVStore extends TestBase {
assertTrue
(
mOld
.
isReadOnly
());
s
.
getCurrentVersion
();
s
.
setRetainChunk
(
0
);
long
old
2
=
s
.
store
();
long
old
3
=
s
.
store
();
// the old version is still available
assertEquals
(
"Hello"
,
mOld
.
get
(
"1"
));
assertEquals
(
"World"
,
mOld
.
get
(
"2"
));
mOld
=
m
.
openVersion
(
old3
);
assertEquals
(
"Hallo"
,
mOld
.
get
(
"1"
));
assertEquals
(
"Welt"
,
mOld
.
get
(
"2"
));
m
.
put
(
"1"
,
"Hi"
);
assertEquals
(
"Welt"
,
m
.
remove
(
"2"
));
s
.
store
();
...
...
@@ -519,7 +527,8 @@ public class TestMVStore extends TestBase {
m
=
s
.
openMap
(
"data"
,
String
.
class
,
String
.
class
);
assertEquals
(
"Hi"
,
m
.
get
(
"1"
));
assertEquals
(
null
,
m
.
get
(
"2"
));
mOld
=
m
.
openVersion
(
old2
);
mOld
=
m
.
openVersion
(
old3
);
assertEquals
(
"Hallo"
,
mOld
.
get
(
"1"
));
assertEquals
(
"Welt"
,
mOld
.
get
(
"2"
));
s
.
close
();
...
...
@@ -635,23 +644,25 @@ public class TestMVStore extends TestBase {
assertFalse
(
m0
.
isReadOnly
());
m
.
put
(
"1"
,
"Hallo"
);
s
.
incrementVersion
();
assertEquals
(
3
,
s
.
getCurrentVersion
());
long
v3
=
s
.
getCurrentVersion
();
assertEquals
(
3
,
v3
);
long
v4
=
s
.
store
();
assertEquals
(
4
,
v4
);
assertEquals
(
4
,
s
.
getCurrentVersion
());
s
.
close
();
s
=
openStore
(
fileName
);
assertEquals
(
4
,
s
.
getCurrentVersion
());
s
.
setRetainChunk
(
0
);
m
=
s
.
openMap
(
"data"
,
String
.
class
,
String
.
class
);
m
.
put
(
"1"
,
"H
ello
"
);
m
.
put
(
"1"
,
"H
i
"
);
s
.
store
();
s
.
close
();
s
=
openStore
(
fileName
);
s
.
setRetainChunk
(
0
);
m
=
s
.
openMap
(
"data"
,
String
.
class
,
String
.
class
);
assertEquals
(
"H
ello
"
,
m
.
get
(
"1"
));
assertEquals
(
"H
i
"
,
m
.
get
(
"1"
));
s
.
rollbackTo
(
v4
);
assertEquals
(
"Hallo"
,
m
.
get
(
"1"
));
s
.
close
();
...
...
@@ -715,6 +726,10 @@ public class TestMVStore extends TestBase {
data
.
put
(
"1"
,
"Hello"
);
data
.
put
(
"2"
,
"World"
);
s
.
store
();
assertEquals
(
1
,
s
.
getCurrentVersion
());
assertTrue
(
m
.
containsKey
(
"chunk.1"
));
assertFalse
(
m
.
containsKey
(
"chunk.2"
));
assertEquals
(
"id:1,name:data,type:btree,createVersion:0,key:,value:"
,
m
.
get
(
"map.data"
));
assertTrue
(
m
.
containsKey
(
"chunk.1"
));
...
...
@@ -725,9 +740,14 @@ public class TestMVStore extends TestBase {
assertTrue
(
m
.
get
(
"root.1"
).
length
()
>
0
);
assertTrue
(
m
.
containsKey
(
"chunk.1"
));
assertTrue
(
m
.
containsKey
(
"chunk.2"
));
assertEquals
(
2
,
s
.
getCurrentVersion
());
s
.
rollbackTo
(
1
);
assertEquals
(
"Hello"
,
data
.
get
(
"1"
));
assertEquals
(
"World"
,
data
.
get
(
"2"
));
assertTrue
(
m
.
containsKey
(
"chunk.1"
));
assertFalse
(
m
.
containsKey
(
"chunk.2"
));
s
.
close
();
}
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论