Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
0b219336
提交
0b219336
authored
11 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Formatting, javadocs
上级
58bea228
隐藏空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
177 行增加
和
86 行删除
+177
-86
SysProperties.java
h2/src/main/org/h2/constant/SysProperties.java
+1
-1
Database.java
h2/src/main/org/h2/engine/Database.java
+1
-1
DataUtils.java
h2/src/main/org/h2/mvstore/DataUtils.java
+5
-5
FileStore.java
h2/src/main/org/h2/mvstore/FileStore.java
+121
-19
MVMap.java
h2/src/main/org/h2/mvstore/MVMap.java
+3
-3
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+28
-39
OffHeapStore.java
h2/src/main/org/h2/mvstore/OffHeapStore.java
+18
-18
没有找到文件。
h2/src/main/org/h2/constant/SysProperties.java
浏览文件 @
0b219336
...
...
@@ -175,7 +175,7 @@ public class SysProperties {
* maximum delay.
*/
public
static
final
int
DELAY_WRONG_PASSWORD_MAX
=
Utils
.
getProperty
(
"h2.delayWrongPasswordMax"
,
4000
);
/**
* System property <code>h2.javaSystemCompiler</code> (default: true).<br />
* Whether to use the Java system compiler
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/Database.java
浏览文件 @
0b219336
...
...
@@ -2498,7 +2498,7 @@ public class Database implements DataHandler {
conn
.
setTraceLevel
(
TraceSystem
.
OFF
);
return
conn
;
}
public
void
setLogMode
(
int
log
)
{
if
(
log
<
0
||
log
>
2
)
{
throw
DbException
.
getInvalidValueException
(
"LOG"
,
log
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/DataUtils.java
浏览文件 @
0b219336
...
...
@@ -122,7 +122,7 @@ public class DataUtils {
* The estimated number of bytes used per child entry.
*/
public
static
final
int
PAGE_MEMORY_CHILD
=
16
;
/**
* Name of the character encoding format.
*/
...
...
@@ -137,7 +137,7 @@ public class DataUtils {
* The maximum byte to grow a buffer at a time.
*/
private
static
final
int
MAX_GROW
=
16
*
1024
*
1024
;
/**
* Get the length of the variable size int.
*
...
...
@@ -805,7 +805,7 @@ public class DataUtils {
/**
* Parse a string as a number.
*
*
* @param x the number
* @param defaultValue if x is null
* @return the parsed value
...
...
@@ -818,14 +818,14 @@ public class DataUtils {
try
{
return
Long
.
parseLong
(
x
);
}
catch
(
NumberFormatException
e
)
{
throw
newIllegalStateException
(
ERROR_FILE_CORRUPT
,
throw
newIllegalStateException
(
ERROR_FILE_CORRUPT
,
"Error parsing the value {0} as a long"
,
x
,
e
);
}
}
/**
* Try to parse a string as a number.
*
*
* @param x the number
* @param defaultValue if x is null
* @param errorValue if parsing fails
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/FileStore.java
浏览文件 @
0b219336
...
...
@@ -24,28 +24,64 @@ import org.h2.store.fs.FilePathNio;
*/
public
class
FileStore
{
/**
* The number of read operations.
*/
protected
long
readCount
;
/**
* The number of write operations.
*/
protected
long
writeCount
;
/**
* The free spaces between the chunks. The first block to use is block 2
* (the first two blocks are the store header).
*/
protected
final
FreeSpaceBitSet
freeSpace
=
new
FreeSpaceBitSet
(
2
,
MVStore
.
BLOCK_SIZE
);
/**
* The file name.
*/
protected
String
fileName
;
/**
* Whether this store is read-only.
*/
protected
boolean
readOnly
;
/**
* The file size (cached).
*/
protected
long
fileSize
;
/**
* The file.
*/
protected
FileChannel
file
;
protected
FileLock
fileLock
;
/**
* The encrypted file (if encryption is used).
*/
protected
FileChannel
encryptedFile
;
/**
* The file lock.
*/
protected
FileLock
fileLock
;
@Override
public
String
toString
()
{
return
fileName
;
}
/**
* Read from the file.
*
* @param pos the write position
* @param len the number of bytes to read
* @return the byte buffer
*/
public
ByteBuffer
readFully
(
long
pos
,
int
len
)
{
readCount
++;
ByteBuffer
dst
=
ByteBuffer
.
allocate
(
len
);
...
...
@@ -53,12 +89,27 @@ public class FileStore {
return
dst
;
}
/**
* Write to the file.
*
* @param pos the write position
* @param src the source buffer
*/
public
void
writeFully
(
long
pos
,
ByteBuffer
src
)
{
writeCount
++;
fileSize
=
Math
.
max
(
fileSize
,
pos
+
src
.
remaining
());
DataUtils
.
writeFully
(
file
,
pos
,
src
);
}
/**
* Try to open the file.
*
* @param fileName the file name
* @param readOnly whether the file should only be opened in read-only mode,
* even if the file is writable
* @param encryptionKey the encryption key, or null if encryption is not
* used
*/
public
void
open
(
String
fileName
,
boolean
readOnly
,
char
[]
encryptionKey
)
{
if
(
fileName
!=
null
&&
fileName
.
indexOf
(
':'
)
<
0
)
{
// NIO is used, unless a different file system is specified
...
...
@@ -80,6 +131,7 @@ public class FileStore {
file
=
f
.
open
(
readOnly
?
"r"
:
"rw"
);
if
(
encryptionKey
!=
null
)
{
byte
[]
password
=
FilePathCrypt
.
getPasswordBytes
(
encryptionKey
);
encryptedFile
=
file
;
file
=
new
FilePathCrypt
.
FileCrypt
(
fileName
,
password
,
file
);
}
file
=
FilePathCache
.
wrap
(
file
);
...
...
@@ -104,7 +156,10 @@ public class FileStore {
"Could not open file {0}"
,
fileName
,
e
);
}
}
/**
* Close this store.
*/
public
void
close
()
{
try
{
if
(
fileLock
!=
null
)
{
...
...
@@ -121,7 +176,10 @@ public class FileStore {
file
=
null
;
}
}
/**
* Flush all changes.
*/
public
void
sync
()
{
try
{
file
.
force
(
true
);
...
...
@@ -131,11 +189,21 @@ public class FileStore {
"Could not sync file {0}"
,
fileName
,
e
);
}
}
/**
* Get the file size.
*
* @return the file size
*/
public
long
size
()
{
return
fileSize
;
}
/**
* Truncate the file.
*
* @param size the new file size
*/
public
void
truncate
(
long
size
)
{
try
{
writeCount
++;
...
...
@@ -150,29 +218,43 @@ public class FileStore {
}
/**
* Get the file instance in use. The application may read from the file (for
* example for online backup), but not write to it or truncate it.
*
* Get the file instance in use.
* <p>
* The application may read from the file (for example for online backup),
* but not write to it or truncate it.
*
* @return the file
*/
public
FileChannel
getFile
()
{
return
file
;
}
/**
* Get the encrypted file instance, if encryption is used.
* <p>
* The application may read from the file (for example for online backup),
* but not write to it or truncate it.
*
* @return the encrypted file, or null if encryption is not used
*/
public
FileChannel
getEncryptedFile
()
{
return
encryptedFile
;
}
/**
* Get the number of write operations since this store was opened.
* Get the number of write operations since this store was opened.
* For file based stores, this is the number of file write operations.
*
*
* @return the number of write operations
*/
public
long
getWriteCount
()
{
return
writeCount
;
}
/**
* Get the number of read operations since this store was opened.
* For file based stores, this is the number of file read operations.
*
*
* @return the number of read operations
*/
public
long
getReadCount
()
{
...
...
@@ -183,14 +265,31 @@ public class FileStore {
return
readOnly
;
}
/**
* Get the default retention time for this store in milliseconds.
*
* @return the retention time
*/
public
int
getDefaultRetentionTime
()
{
return
45000
;
}
public
void
markUsed
(
long
start
,
int
len
)
{
freeSpace
.
markUsed
(
start
,
len
);
/**
* Mark the space as in use.
*
* @param pos the position in bytes
* @param length the number of bytes
*/
public
void
markUsed
(
long
pos
,
int
length
)
{
freeSpace
.
markUsed
(
pos
,
length
);
}
/**
* Allocate a number of blocks and mark them as used.
*
* @param length the number of bytes to allocate
* @return the start position in bytes
*/
public
long
allocate
(
int
length
)
{
return
freeSpace
.
allocate
(
length
);
}
...
...
@@ -213,6 +312,9 @@ public class FileStore {
return
freeSpace
.
getFirstFree
();
}
/**
* Mark the file as empty.
*/
public
void
clear
()
{
freeSpace
.
clear
();
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/MVMap.java
浏览文件 @
0b219336
...
...
@@ -986,7 +986,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
/**
* Get the number of entries, as a integer. Integer.MAX_VALUE is returned if
* there are more than this entries.
*
*
* @return the number of entries, as an integer
*/
@Override
...
...
@@ -994,10 +994,10 @@ public class MVMap<K, V> extends AbstractMap<K, V>
long
size
=
sizeAsLong
();
return
size
>
Integer
.
MAX_VALUE
?
Integer
.
MAX_VALUE
:
(
int
)
size
;
}
/**
* Get the number of entries, as a long.
*
*
* @return the number of entries
*/
public
long
sizeAsLong
()
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
0b219336
...
...
@@ -48,7 +48,7 @@ TestMVStoreDataLoss
MVTableEngine:
- use StreamStore
- when the MVStore was enabled before, use it again
(probably by checking existence of the mvstore file)
(probably by checking existence of the mvstore file)
TransactionStore:
...
...
@@ -62,46 +62,32 @@ MVStore:
- defragment (re-creating maps, specially those with small pages)
- chunk header: store changed chunk data as row; maybe after the root
- chunk checksum (header, last page, 2 bytes per page?)
- on insert, if the child page is already full, don't load and modify it
split directly (specially for leaves with one large entry)
- maybe let a chunk point to a list of potential next chunks
(so no fixed location header is needed), similar to a skip list
- triggers (can be implemented with a custom map);
maybe implement database indexing with triggers
- store number of write operations per page (maybe defragment
if much different than count)
- r-tree: nearest neighbor search
- support maps without values (just existence of the key)
- support maps without keys (counted b-tree features)
- use a small object value cache (StringCache), test on Android
for default serialization
- MVStoreTool.dump: dump values (using a callback)
- map split / merge (fast if no overlap)
(use case: partitioning)
- StreamStore optimization: avoid copying bytes in memory
- Feature shrink a store (create, copy, rename, delete)
and for MVStore on Windows, auto-detect renamed file
- ensure data is overwritten eventually if the system doesn't have a
real-time clock (Raspberry Pi) and if there are few writes per startup
- ensure data is overwritten eventually if the system doesn't have a
real-time clock (Raspberry Pi) and if there are few writes per startup
- SSD-friendly write (always in blocks of 4 MB / 1 second?)
- close the file on out of memory or disk write error (out of disk space or so)
- implement a sharded map (in one store, multiple stores)
to support concurrent updates and writes, and very large maps
- maybe support for writing to branches
- maybe add an optional finalizer and exit hook
to store committed changes
- to save space when persisting very small transactions,
use a transaction log where only the deltas are stored
- serialization for lists, sets, sets, sorted sets, maps, sorted maps
- maybe rename 'rollback' to 'revert' to distinguish from transactions
- support other compression algorithms (deflate, LZ4,...)
- only retain the last version, unless explicitly set (setRetainVersion)
- support opening (existing) maps by id
- more consistent null handling (keys/values sometimes may be null)
- autocommit (to avoid having to call commit,
as it could be called too often or it is easily forgotten)
- remove features that are not really needed; simplify the code
possibly using a separate layer or tools
(retainVersion?)
- rename "store" to "save", as "store" is used in "storeVersion"
- MVStoreTool.dump should dump the data if possible;
possibly using a callback for serialization
...
...
@@ -114,8 +100,8 @@ MVStore:
- simple rollback method (rollback to last committed version)
- MVMap to implement SortedMap, then NavigableMap
- Test with OSGi
- storage that splits database into multiple files,
to speed up compact and allow using trim
- storage that splits database into multiple files,
to speed up compact and allow using trim
(by truncating / deleting empty files)
*/
...
...
@@ -138,20 +124,20 @@ public class MVStore {
private
static
final
int
FORMAT_WRITE
=
1
;
private
static
final
int
FORMAT_READ
=
1
;
/**
* The background thread, if any.
*/
volatile
Thread
backgroundThread
;
private
volatile
boolean
reuseSpace
=
true
;
private
boolean
closed
;
private
FileStore
fileStore
;
private
final
int
pageSplitSize
;
private
long
rootChunkStart
;
/**
...
...
@@ -189,7 +175,7 @@ public class MVStore {
private
ByteBuffer
writeBuffer
;
private
int
lastMapId
;
private
long
retainVersion
=
-
1
;
/**
...
...
@@ -197,7 +183,7 @@ public class MVStore {
* (old) compressed pages.
*/
private
final
boolean
compress
;
private
final
Compressor
compressor
=
new
CompressLZF
();
private
final
UncaughtExceptionHandler
backgroundExceptionHandler
;
...
...
@@ -208,7 +194,7 @@ public class MVStore {
* The version of the last stored chunk.
*/
private
long
lastStoredVersion
;
private
int
unsavedPageCount
;
private
int
unsavedPageCountMax
;
...
...
@@ -245,6 +231,7 @@ public class MVStore {
/**
* Create and open the store.
*
* @param config the configuration to use
* @throws IllegalStateException if the file is corrupt, or an exception
* occurred while opening
* @throws IllegalArgumentException if the directory does not exist
...
...
@@ -302,7 +289,7 @@ public class MVStore {
if
(
format
>
FORMAT_WRITE
&&
!
fileStore
.
isReadOnly
())
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_UNSUPPORTED_FORMAT
,
"The write format {0} is larger than the supported format {1}, "
+
"The write format {0} is larger than the supported format {1}, "
+
"and the file was not opened in read-only mode"
,
format
,
FORMAT_WRITE
);
}
...
...
@@ -316,7 +303,7 @@ public class MVStore {
if
(
rootChunkStart
>
0
)
{
readMeta
();
}
}
}
long
rollback
=
DataUtils
.
parseLong
(
meta
.
get
(
"rollbackOnOpen"
),
-
1
);
if
(
rollback
!=
-
1
)
{
rollbackTo
(
rollback
);
...
...
@@ -682,12 +669,14 @@ public class MVStore {
if
(
shrinkIfPossible
)
{
shrinkFileIfPossible
(
0
);
}
// release memory early - this is important when called
// because of out of memory
cache
.
clear
();
for
(
MVMap
<?,
?>
m
:
New
.
arrayList
(
maps
.
values
()))
{
m
.
close
();
}
meta
=
null
;
chunks
.
clear
();
cache
.
clear
();
maps
.
clear
();
try
{
fileStore
.
close
();
...
...
@@ -1074,7 +1063,7 @@ public class MVStore {
/**
* Get the position of the last used byte.
*
*
* @return the position
*/
private
long
getEndPosition
()
{
...
...
@@ -1498,7 +1487,7 @@ public class MVStore {
* depending on the operating system and hardware.
* <p>
* This setting is not persisted.
*
*
* @param ms how many milliseconds to retain old chunks (0 to overwrite them
* as early as possible)
*/
...
...
@@ -1518,7 +1507,7 @@ public class MVStore {
/**
* Get the oldest version to retain in memory.
*
*
* @return the version
*/
public
long
getRetainVersion
()
{
...
...
@@ -1533,7 +1522,7 @@ public class MVStore {
/**
* Get the oldest version to retain in memory, which is the manually set
* retain version, or the current store version (whatever is older).
*
*
* @return the version
*/
long
getRetainOrStoreVersion
()
{
...
...
@@ -1791,7 +1780,7 @@ public class MVStore {
/**
* Get the file store.
*
*
* @return the file store
*/
public
FileStore
getFileStore
()
{
...
...
@@ -1884,9 +1873,9 @@ public class MVStore {
*
* @param mb the cache size in MB.
*/
public
void
setCacheSize
(
long
mb
)
{
public
void
setCacheSize
(
int
mb
)
{
if
(
cache
!=
null
)
{
cache
.
setMaxMemory
(
mb
*
1024
*
1024
);
cache
.
setMaxMemory
(
(
long
)
mb
*
1024
*
1024
);
}
}
...
...
@@ -2099,10 +2088,10 @@ public class MVStore {
Thread
.
UncaughtExceptionHandler
exceptionHandler
)
{
return
set
(
"backgroundExceptionHandler"
,
exceptionHandler
);
}
/**
* Use the provided file store instead of the default one.
*
*
* @param store the file store
* @return this
*/
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/mvstore/OffHeapStore.java
浏览文件 @
0b219336
...
...
@@ -16,24 +16,24 @@ import java.util.TreeMap;
* memory.
*/
public
class
OffHeapStore
extends
FileStore
{
private
final
TreeMap
<
Long
,
ByteBuffer
>
memory
=
new
TreeMap
<
Long
,
ByteBuffer
>();
@Override
public
void
open
(
String
fileName
,
boolean
readOnly
,
char
[]
encryptionKey
)
{
// nothing to do
}
@Override
public
String
toString
()
{
return
memory
.
toString
();
}
@Override
public
ByteBuffer
readFully
(
long
pos
,
int
len
)
{
Entry
<
Long
,
ByteBuffer
>
memEntry
=
memory
.
floorEntry
(
pos
);
if
(
memEntry
==
null
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
"Could not read from position {0}"
,
pos
);
}
readCount
++;
...
...
@@ -44,20 +44,20 @@ public class OffHeapStore extends FileStore {
read
.
limit
(
len
+
offset
);
return
read
.
slice
();
}
@Override
public
void
free
(
long
pos
,
int
length
)
{
freeSpace
.
free
(
pos
,
length
);
ByteBuffer
buff
=
memory
.
remove
(
pos
);
ByteBuffer
buff
=
memory
.
remove
(
pos
);
if
(
buff
==
null
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
"Could not find entry at position {0}"
,
pos
);
}
else
if
(
buff
.
remaining
()
!=
length
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
"Partial remove is not supported at position {0}"
,
pos
);
}
}
@Override
public
void
writeFully
(
long
pos
,
ByteBuffer
src
)
{
fileSize
=
Math
.
max
(
fileSize
,
pos
+
src
.
remaining
());
...
...
@@ -73,7 +73,7 @@ public class OffHeapStore extends FileStore {
int
length
=
src
.
remaining
();
if
(
prevPos
==
pos
)
{
if
(
prevLength
!=
length
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
"Could not write to position {0}; partial overwrite is not supported"
,
pos
);
}
writeCount
++;
...
...
@@ -82,12 +82,12 @@ public class OffHeapStore extends FileStore {
return
;
}
if
(
prevPos
+
prevLength
>
pos
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
"Could not write to position {0}; partial overwrite is not supported"
,
pos
);
}
writeNewEntry
(
pos
,
src
);
}
private
void
writeNewEntry
(
long
pos
,
ByteBuffer
src
)
{
writeCount
++;
int
length
=
src
.
remaining
();
...
...
@@ -112,27 +112,27 @@ public class OffHeapStore extends FileStore {
}
ByteBuffer
buff
=
memory
.
get
(
pos
);
if
(
buff
.
capacity
()
>
size
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
"Could not truncate to {0}; partial truncate is not supported"
,
pos
);
}
it
.
remove
();
}
}
@Override
public
void
close
()
{
truncate
(
0
);
freeSpace
.
clear
();
}
@Override
public
void
sync
()
{
// nothing to do
}
@Override
public
int
getDefaultRetentionTime
()
{
return
0
;
}
}
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论