Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
cd833fcb
提交
cd833fcb
authored
11 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
MVStore: read-only encrypted files with an old read version
上级
b7fe8ef5
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
69 行增加
和
51 行删除
+69
-51
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+28
-47
FilePathCrypt.java
h2/src/main/org/h2/store/fs/FilePathCrypt.java
+3
-4
TestMVStore.java
h2/src/test/org/h2/test/store/TestMVStore.java
+38
-0
没有找到文件。
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
cd833fcb
...
@@ -56,7 +56,6 @@ TestMVStoreDataLoss
...
@@ -56,7 +56,6 @@ TestMVStoreDataLoss
TransactionStore:
TransactionStore:
MVStore:
MVStore:
- in-place compact (first, move chunks to end of file, then move to start)
- automated 'kill process' and 'power failure' test
- automated 'kill process' and 'power failure' test
- update checkstyle
- update checkstyle
- maybe split database into multiple files, to speed up compact
- maybe split database into multiple files, to speed up compact
...
@@ -76,17 +75,20 @@ MVStore:
...
@@ -76,17 +75,20 @@ MVStore:
- maybe let a chunk point to a list of potential next chunks
- maybe let a chunk point to a list of potential next chunks
(so no fixed location header is needed), similar to a skip list
(so no fixed location header is needed), similar to a skip list
- support stores that span multiple files (chunks stored in other files)
- support stores that span multiple files (chunks stored in other files)
- triggers (can be implemented with a custom map)
- triggers (can be implemented with a custom map);
maybe implement database indexing with triggers
- store number of write operations per page (maybe defragment
- store number of write operations per page (maybe defragment
if much different than count)
if much different than count)
- r-tree: nearest neighbor search
- r-tree: nearest neighbor search
- support maps without values (just existence of the key)
- support maps without values (just existence of the key)
- support maps without keys (counted b-tree features)
- support maps without keys (counted b-tree features)
- use a small object cache (StringCache), test on Android
- use a small object value cache (StringCache), test on Android
- dump values (using a callback)
for default serialization
- MVStoreTool.dump: dump values (using a callback)
- map split / merge (fast if no overlap)
- map split / merge (fast if no overlap)
- StreamStore optimization: avoid copying bytes
(use case: partitioning)
- MVStoreTool.shrink to shrink a store (create, copy, rename, delete)
- StreamStore optimization: avoid copying bytes in memory
- Feature shrink a store (create, copy, rename, delete)
and for MVStore on Windows, auto-detect renamed file
and for MVStore on Windows, auto-detect renamed file
- ensure data is overwritten eventually if the system doesn't have a timer
- ensure data is overwritten eventually if the system doesn't have a timer
- SSD-friendly write (always in blocks of 4 MB / 1 second?)
- SSD-friendly write (always in blocks of 4 MB / 1 second?)
...
@@ -94,8 +96,7 @@ MVStore:
...
@@ -94,8 +96,7 @@ MVStore:
- implement a sharded map (in one store, multiple stores)
- implement a sharded map (in one store, multiple stores)
to support concurrent updates and writes, and very large maps
to support concurrent updates and writes, and very large maps
- implement an off-heap file system
- implement an off-heap file system
- remove change cursor, or add support for writing to branches
- add support for writing to branches
- support pluggable logging or remove log
- maybe add an optional finalizer and exit hook
- maybe add an optional finalizer and exit hook
to store committed changes
to store committed changes
- to save space when persisting very small transactions,
- to save space when persisting very small transactions,
...
@@ -119,7 +120,6 @@ MVStore:
...
@@ -119,7 +120,6 @@ MVStore:
- to save space for small chunks, combine the last partial
- to save space for small chunks, combine the last partial
block with the header
block with the header
- off-heap storage (with lower default retention time)
- off-heap storage (with lower default retention time)
- object value cache for default serialization
- temporary file storage
- temporary file storage
- simple rollback method (rollback to last committed version)
- simple rollback method (rollback to last committed version)
- MVMap to implement SortedMap, then NavigableMap
- MVMap to implement SortedMap, then NavigableMap
...
@@ -483,10 +483,10 @@ public class MVStore {
...
@@ -483,10 +483,10 @@ public class MVStore {
}
}
try
{
try
{
if
(
readOnly
)
{
if
(
readOnly
)
{
openFile
();
openFile
(
true
);
}
else
if
(!
openFile
())
{
}
else
if
(!
openFile
(
false
))
{
readOnly
=
true
;
readOnly
=
true
;
openFile
();
openFile
(
true
);
}
}
}
finally
{
}
finally
{
if
(
filePassword
!=
null
)
{
if
(
filePassword
!=
null
)
{
...
@@ -500,7 +500,7 @@ public class MVStore {
...
@@ -500,7 +500,7 @@ public class MVStore {
rollbackTo
(
rollback
);
rollbackTo
(
rollback
);
}
}
this
.
lastCommittedVersion
=
currentVersion
;
this
.
lastCommittedVersion
=
currentVersion
;
// setWriteDelay starts the thread, but only if
// setWriteDelay starts the thread, but only if
// the parameter is different than the current value
// the parameter is different than the current value
setWriteDelay
(
1000
);
setWriteDelay
(
1000
);
...
@@ -510,18 +510,17 @@ public class MVStore {
...
@@ -510,18 +510,17 @@ public class MVStore {
* Try to open the file in read or write mode.
* Try to open the file in read or write mode.
*
*
* @return if opening the file was successful, and false if the file could
* @return if opening the file was successful, and false if the file could
* not be opened in write mode because the write file format i
t
too
* not be opened in write mode because the write file format i
s
too
* high (in which case the file can be opened in read-only mode)
* high (in which case the file can be opened in read-only mode)
* @throw IllegalStateException if the file could not be opened
* @throw IllegalStateException if the file could not be opened
* because of an IOException or file format error
* because of an IOException or file format error
*/
*/
private
boolean
openFile
()
{
private
boolean
openFile
(
boolean
readOnly
)
{
IllegalStateException
exception
;
IllegalStateException
exception
;
try
{
try
{
log
(
"file open"
);
FilePath
f
=
FilePath
.
get
(
fileName
);
FilePath
f
=
FilePath
.
get
(
fileName
);
if
(
f
.
exists
()
&&
!
f
.
canWrite
())
{
if
(
f
.
exists
()
&&
!
f
.
canWrite
())
{
re
adOnly
=
tru
e
;
re
turn
fals
e
;
}
}
file
=
f
.
open
(
readOnly
?
"r"
:
"rw"
);
file
=
f
.
open
(
readOnly
?
"r"
:
"rw"
);
if
(
filePassword
!=
null
)
{
if
(
filePassword
!=
null
)
{
...
@@ -564,8 +563,7 @@ public class MVStore {
...
@@ -564,8 +563,7 @@ public class MVStore {
"The file format {0} is larger than the supported format {1}"
,
"The file format {0} is larger than the supported format {1}"
,
formatRead
,
FORMAT_READ
);
formatRead
,
FORMAT_READ
);
}
}
if
(
formatWrite
>
FORMAT_WRITE
)
{
if
(
formatWrite
>
FORMAT_WRITE
&&
!
readOnly
)
{
readOnly
=
true
;
file
.
close
();
file
.
close
();
return
false
;
return
false
;
}
}
...
@@ -573,7 +571,7 @@ public class MVStore {
...
@@ -573,7 +571,7 @@ public class MVStore {
readMeta
();
readMeta
();
}
}
}
}
exception
=
null
;
return
true
;
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
exception
=
DataUtils
.
newIllegalStateException
(
exception
=
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
DataUtils
.
ERROR_READING_FAILED
,
...
@@ -581,18 +579,14 @@ public class MVStore {
...
@@ -581,18 +579,14 @@ public class MVStore {
}
catch
(
IllegalStateException
e
)
{
}
catch
(
IllegalStateException
e
)
{
exception
=
e
;
exception
=
e
;
}
}
if
(
exception
!=
null
)
{
try
{
try
{
closeFile
(
false
);
closeFile
(
false
);
}
catch
(
Exception
e2
)
{
}
catch
(
Exception
e2
)
{
// ignore
// ignore
}
throw
exception
;
}
}
return
true
;
throw
exception
;
}
}
private
void
readMeta
()
{
private
void
readMeta
()
{
Chunk
header
=
readChunkHeader
(
rootChunkStart
);
Chunk
header
=
readChunkHeader
(
rootChunkStart
);
lastChunkId
=
header
.
id
;
lastChunkId
=
header
.
id
;
...
@@ -775,7 +769,6 @@ public class MVStore {
...
@@ -775,7 +769,6 @@ public class MVStore {
if
(
shrinkIfPossible
)
{
if
(
shrinkIfPossible
)
{
shrinkFileIfPossible
(
0
);
shrinkFileIfPossible
(
0
);
}
}
log
(
"file close"
);
if
(
fileLock
!=
null
)
{
if
(
fileLock
!=
null
)
{
fileLock
.
release
();
fileLock
.
release
();
fileLock
=
null
;
fileLock
=
null
;
...
@@ -1229,7 +1222,7 @@ public class MVStore {
...
@@ -1229,7 +1222,7 @@ public class MVStore {
* free space between chunks. This might temporarily double the file size.
* free space between chunks. This might temporarily double the file size.
* Chunks are overwritten irrespective of the current retention time. Before
* Chunks are overwritten irrespective of the current retention time. Before
* overwriting chunks and before resizing the file, syncFile() is called.
* overwriting chunks and before resizing the file, syncFile() is called.
*
*
* @return if anything was written
* @return if anything was written
*/
*/
public
synchronized
boolean
compactMoveChunks
()
{
public
synchronized
boolean
compactMoveChunks
()
{
...
@@ -1290,11 +1283,11 @@ public class MVStore {
...
@@ -1290,11 +1283,11 @@ public class MVStore {
meta
.
put
(
"chunk."
+
c
.
id
,
c
.
asString
());
meta
.
put
(
"chunk."
+
c
.
id
,
c
.
asString
());
}
}
boolean
oldReuse
=
reuseSpace
;
boolean
oldReuse
=
reuseSpace
;
// update the metadata (store at the end of the file)
// update the metadata (store at the end of the file)
reuseSpace
=
false
;
reuseSpace
=
false
;
store
();
store
();
syncFile
();
syncFile
();
// now re-use the empty space
// now re-use the empty space
...
@@ -1333,7 +1326,7 @@ public class MVStore {
...
@@ -1333,7 +1326,7 @@ public class MVStore {
return
true
;
return
true
;
}
}
/**
/**
* Force all changes to be written to the file. The default implementation
* Force all changes to be written to the file. The default implementation
* calls FileChannel.force(true).
* calls FileChannel.force(true).
...
@@ -1416,7 +1409,6 @@ public class MVStore {
...
@@ -1416,7 +1409,6 @@ public class MVStore {
if
(
move
!=
null
&&
moved
+
c
.
maxLengthLive
>
averageMaxLength
)
{
if
(
move
!=
null
&&
moved
+
c
.
maxLengthLive
>
averageMaxLength
)
{
break
;
break
;
}
}
log
(
" chunk "
+
c
.
id
+
" "
+
c
.
getFillRate
()
+
"% full; prio="
+
c
.
collectPriority
);
moved
+=
c
.
maxLengthLive
;
moved
+=
c
.
maxLengthLive
;
move
=
c
;
move
=
c
;
}
}
...
@@ -1476,7 +1468,6 @@ public class MVStore {
...
@@ -1476,7 +1468,6 @@ public class MVStore {
}
else
{
}
else
{
Chunk
c
=
getChunk
(
p
.
getPos
());
Chunk
c
=
getChunk
(
p
.
getPos
());
if
(
old
.
contains
(
c
))
{
if
(
old
.
contains
(
c
))
{
log
(
" move key:"
+
k
+
" chunk:"
+
c
.
id
);
Object
value
=
map
.
remove
(
k
);
Object
value
=
map
.
remove
(
k
);
map
.
put
(
k
,
value
);
map
.
put
(
k
,
value
);
}
}
...
@@ -1568,16 +1559,6 @@ public class MVStore {
...
@@ -1568,16 +1559,6 @@ public class MVStore {
}
}
}
}
/**
* Log the string, if logging is enabled.
*
* @param string the string to log
*/
void
log
(
String
string
)
{
// TODO logging
// System.out.println(string);
}
Compressor
getCompressor
()
{
Compressor
getCompressor
()
{
return
compressor
;
return
compressor
;
}
}
...
@@ -2051,7 +2032,7 @@ public class MVStore {
...
@@ -2051,7 +2032,7 @@ public class MVStore {
// ignore
// ignore
}
}
}
}
/**
/**
* Set the maximum delay in milliseconds to store committed changes (for
* Set the maximum delay in milliseconds to store committed changes (for
* file-based stores).
* file-based stores).
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/store/fs/FilePathCrypt.java
浏览文件 @
cd833fcb
...
@@ -102,9 +102,9 @@ public class FilePathCrypt extends FilePathWrapper {
...
@@ -102,9 +102,9 @@ public class FilePathCrypt extends FilePathWrapper {
}
}
/**
/**
* Convert a char array to a byte array
. The char array is cleared after
* Convert a char array to a byte array
, in UTF-16 format. The char array is
*
use
.
*
not cleared after use (this must be done by the caller)
.
*
*
* @param passwordChars the password characters
* @param passwordChars the password characters
* @return the byte array
* @return the byte array
*/
*/
...
@@ -117,7 +117,6 @@ public class FilePathCrypt extends FilePathWrapper {
...
@@ -117,7 +117,6 @@ public class FilePathCrypt extends FilePathWrapper {
password
[
i
+
i
]
=
(
byte
)
(
c
>>>
8
);
password
[
i
+
i
]
=
(
byte
)
(
c
>>>
8
);
password
[
i
+
i
+
1
]
=
(
byte
)
c
;
password
[
i
+
i
+
1
]
=
(
byte
)
c
;
}
}
Arrays
.
fill
(
passwordChars
,
(
char
)
0
);
return
password
;
return
password
;
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMVStore.java
浏览文件 @
cd833fcb
...
@@ -47,6 +47,7 @@ public class TestMVStore extends TestBase {
...
@@ -47,6 +47,7 @@ public class TestMVStore extends TestBase {
public
void
test
()
throws
Exception
{
public
void
test
()
throws
Exception
{
FileUtils
.
deleteRecursive
(
getBaseDir
(),
true
);
FileUtils
.
deleteRecursive
(
getBaseDir
(),
true
);
FileUtils
.
createDirectories
(
getBaseDir
());
FileUtils
.
createDirectories
(
getBaseDir
());
testNewerWriteVersion
();
testCompactFully
();
testCompactFully
();
testBackgroundExceptionListener
();
testBackgroundExceptionListener
();
testOldVersion
();
testOldVersion
();
...
@@ -91,6 +92,35 @@ public class TestMVStore extends TestBase {
...
@@ -91,6 +92,35 @@ public class TestMVStore extends TestBase {
// longer running tests
// longer running tests
testLargerThan2G
();
testLargerThan2G
();
}
}
private
void
testNewerWriteVersion
()
throws
Exception
{
String
fileName
=
getBaseDir
()
+
"/testNewerWriteVersion.h3"
;
FileUtils
.
delete
(
fileName
);
char
[]
passwordChars
;
passwordChars
=
"007"
.
toCharArray
();
MVStore
s
=
new
MVStore
.
Builder
().
encryptionKey
(
passwordChars
).
fileName
(
fileName
).
open
();
Map
<
String
,
String
>
header
=
s
.
getFileHeader
();
assertEquals
(
"1"
,
header
.
get
(
"format"
));
header
.
put
(
"formatRead"
,
"1"
);
header
.
put
(
"format"
,
"2"
);
MVMap
<
Integer
,
String
>
m
=
s
.
openMap
(
"data"
);
m
.
put
(
0
,
"Hello World"
);
s
.
store
();
s
.
close
();
passwordChars
=
"007"
.
toCharArray
();
s
=
new
MVStore
.
Builder
().
encryptionKey
(
passwordChars
).
fileName
(
fileName
).
open
();
assertTrue
(
s
.
isReadOnly
());
m
=
s
.
openMap
(
"data"
);
assertEquals
(
"Hello World"
,
m
.
get
(
0
));
s
.
close
();
}
private
void
testCompactFully
()
throws
Exception
{
private
void
testCompactFully
()
throws
Exception
{
String
fileName
=
getBaseDir
()
+
"/testCompactFully.h3"
;
String
fileName
=
getBaseDir
()
+
"/testCompactFully.h3"
;
...
@@ -343,6 +373,14 @@ public class TestMVStore extends TestBase {
...
@@ -343,6 +373,14 @@ public class TestMVStore extends TestBase {
m
=
s
.
openMap
(
"test"
);
m
=
s
.
openMap
(
"test"
);
assertEquals
(
"Hello"
,
m
.
get
(
1
));
assertEquals
(
"Hello"
,
m
.
get
(
1
));
s
.
close
();
s
.
close
();
FileUtils
.
setReadOnly
(
fileName
);
passwordChars
=
"007"
.
toCharArray
();
s
=
new
MVStore
.
Builder
().
fileName
(
fileName
).
encryptionKey
(
passwordChars
).
open
();
assertTrue
(
s
.
isReadOnly
());
FileUtils
.
delete
(
fileName
);
FileUtils
.
delete
(
fileName
);
assertFalse
(
FileUtils
.
exists
(
fileName
));
assertFalse
(
FileUtils
.
exists
(
fileName
));
}
}
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论