Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
769193eb
提交
769193eb
authored
7月 10, 2013
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
MVStore: error codes; fix MVRTreeMap iterators
上级
aed6260d
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
452 行增加
和
121 行删除
+452
-121
Chunk.java
h2/src/main/org/h2/mvstore/Chunk.java
+1
-0
Cursor.java
h2/src/main/org/h2/mvstore/Cursor.java
+15
-15
DataUtils.java
h2/src/main/org/h2/mvstore/DataUtils.java
+93
-9
FreeSpaceList.java
h2/src/main/org/h2/mvstore/FreeSpaceList.java
+4
-0
MVMap.java
h2/src/main/org/h2/mvstore/MVMap.java
+4
-3
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+69
-24
Page.java
h2/src/main/org/h2/mvstore/Page.java
+8
-2
MVTableEngine.java
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
+49
-9
TransactionStore.java
h2/src/main/org/h2/mvstore/db/TransactionStore.java
+9
-4
MVRTreeMap.java
h2/src/main/org/h2/mvstore/rtree/MVRTreeMap.java
+200
-55
没有找到文件。
h2/src/main/org/h2/mvstore/Chunk.java
浏览文件 @
769193eb
...
...
@@ -95,6 +95,7 @@ public class Chunk {
static
Chunk
fromHeader
(
ByteBuffer
buff
,
long
start
)
{
if
(
buff
.
get
()
!=
'c'
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_FILE_CORRUPT
,
"File corrupt reading chunk at position {0}"
,
start
);
}
int
length
=
buff
.
getInt
();
...
...
h2/src/main/org/h2/mvstore/Cursor.java
浏览文件 @
769193eb
...
...
@@ -15,27 +15,19 @@ import java.util.Iterator;
*/
public
class
Cursor
<
K
>
implements
Iterator
<
K
>
{
pr
otected
final
MVMap
<
K
,
?>
map
;
pr
otected
final
K
from
;
pr
otected
CursorPos
pos
;
pr
otected
K
current
;
pr
ivate
final
MVMap
<
K
,
?>
map
;
pr
ivate
final
K
from
;
pr
ivate
CursorPos
pos
;
pr
ivate
K
current
;
private
final
Page
root
;
private
boolean
initialized
;
protected
Cursor
(
MVMap
<
K
,
?>
map
,
Page
root
,
K
from
)
{
Cursor
(
MVMap
<
K
,
?>
map
,
Page
root
,
K
from
)
{
this
.
map
=
map
;
this
.
root
=
root
;
this
.
from
=
from
;
}
@Override
public
K
next
()
{
hasNext
();
K
c
=
current
;
fetchNext
();
return
c
;
}
@Override
public
boolean
hasNext
()
{
if
(!
initialized
)
{
...
...
@@ -46,6 +38,14 @@ public class Cursor<K> implements Iterator<K> {
return
current
!=
null
;
}
@Override
public
K
next
()
{
hasNext
();
K
c
=
current
;
fetchNext
();
return
c
;
}
/**
* Skip over that many entries. This method is relatively fast (for this map
* implementation) even if many entries need to be skipped.
...
...
@@ -82,7 +82,7 @@ public class Cursor<K> implements Iterator<K> {
* @param p the page to start
* @param from the key to search
*/
pr
otected
void
min
(
Page
p
,
K
from
)
{
pr
ivate
void
min
(
Page
p
,
K
from
)
{
while
(
true
)
{
if
(
p
.
isLeaf
())
{
int
x
=
from
==
null
?
0
:
p
.
binarySearch
(
from
);
...
...
@@ -107,7 +107,7 @@ public class Cursor<K> implements Iterator<K> {
* Fetch the next entry if there is one.
*/
@SuppressWarnings
(
"unchecked"
)
pr
otected
void
fetchNext
()
{
pr
ivate
void
fetchNext
()
{
while
(
pos
!=
null
)
{
if
(
pos
.
index
<
pos
.
page
.
getKeyCount
())
{
current
=
(
K
)
pos
.
page
.
getKey
(
pos
.
index
++);
...
...
h2/src/main/org/h2/mvstore/DataUtils.java
浏览文件 @
769193eb
...
...
@@ -24,6 +24,57 @@ import org.h2.util.New;
*/
public
class
DataUtils
{
/**
* An error occurred while reading from the file.
*/
public
static
final
int
ERROR_READING_FAILED
=
1
;
/**
* An error occurred when trying to write to the file.
*/
public
static
final
int
ERROR_WRITING_FAILED
=
2
;
/**
* An internal error occurred. This could be a bug, or a memory corruption
* (for example caused by out of memory).
*/
public
static
final
int
ERROR_INTERNAL
=
3
;
/**
* The object is already closed.
*/
public
static
final
int
ERROR_CLOSED
=
4
;
/**
* The file format is not supported.
*/
public
static
final
int
ERROR_UNSUPPORTED_FORMAT
=
5
;
/**
* The file is corrupt or (for encrypted files) the encryption key is wrong.
*/
public
static
final
int
ERROR_FILE_CORRUPT
=
6
;
/**
* The file is locked.
*/
public
static
final
int
ERROR_FILE_LOCKED
=
7
;
/**
* An error occurred when serializing or de-serializing.
*/
public
static
final
int
ERROR_SERIALIZATION
=
8
;
/**
* The transaction store is corrupt.
*/
public
static
final
int
ERROR_TRANSACTION_CORRUPT
=
100
;
/**
* A lock timeout occurred.
*/
public
static
final
int
ERROR_TRANSACTION_LOCK_TIMEOUT
=
101
;
/**
* The type for leaf page.
*/
...
...
@@ -332,6 +383,7 @@ public class DataUtils {
dst
.
rewind
();
}
catch
(
IOException
e
)
{
throw
newIllegalStateException
(
ERROR_READING_FAILED
,
"Reading from {0} failed; length {1} at {2}"
,
file
,
dst
.
remaining
(),
pos
,
e
);
}
...
...
@@ -353,6 +405,7 @@ public class DataUtils {
}
while
(
src
.
remaining
()
>
0
);
}
catch
(
IOException
e
)
{
throw
newIllegalStateException
(
ERROR_WRITING_FAILED
,
"Writing to {0} failed; length {1} at {2}"
,
file
,
src
.
remaining
(),
pos
,
e
);
}
...
...
@@ -518,13 +571,17 @@ public class DataUtils {
*
* @param s the list
* @return the map
* @throws IllegalStateException if parsing failed
*/
public
static
HashMap
<
String
,
String
>
parseMap
(
String
s
)
{
HashMap
<
String
,
String
>
map
=
New
.
hashMap
();
for
(
int
i
=
0
,
size
=
s
.
length
();
i
<
size
;)
{
int
startKey
=
i
;
i
=
s
.
indexOf
(
':'
,
i
);
checkArgument
(
i
>=
0
,
"Not a map"
);
if
(
i
<
0
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_FILE_CORRUPT
,
"Not a map: {0}"
,
s
);
}
String
key
=
s
.
substring
(
startKey
,
i
++);
StringBuilder
buff
=
new
StringBuilder
();
while
(
i
<
size
)
{
...
...
@@ -596,7 +653,7 @@ public class DataUtils {
public
static
IllegalArgumentException
newIllegalArgumentException
(
String
message
,
Object
...
arguments
)
{
return
initCause
(
new
IllegalArgumentException
(
MessageFormat
.
format
(
message
,
arguments
)
+
" "
+
getVersion
(
)),
formatMessage
(
0
,
message
,
arguments
)),
arguments
);
}
...
...
@@ -608,16 +665,18 @@ public class DataUtils {
*/
public
static
UnsupportedOperationException
newUnsupportedOperationException
(
String
message
)
{
return
new
UnsupportedOperationException
(
message
+
" "
+
getVersion
(
));
return
new
UnsupportedOperationException
(
formatMessage
(
0
,
message
));
}
/**
* Create a new ConcurrentModificationException.
*
* @param message the message
* @return the exception
*/
public
static
ConcurrentModificationException
newConcurrentModificationException
()
{
return
new
ConcurrentModificationException
(
getVersion
());
public
static
ConcurrentModificationException
newConcurrentModificationException
(
String
message
)
{
return
new
ConcurrentModificationException
(
formatMessage
(
0
,
message
));
}
/**
...
...
@@ -628,9 +687,9 @@ public class DataUtils {
* @return the exception
*/
public
static
IllegalStateException
newIllegalStateException
(
String
message
,
Object
...
arguments
)
{
int
errorCode
,
String
message
,
Object
...
arguments
)
{
return
initCause
(
new
IllegalStateException
(
MessageFormat
.
format
(
message
,
arguments
)
+
" "
+
getVersion
(
)),
formatMessage
(
errorCode
,
message
,
arguments
)),
arguments
);
}
...
...
@@ -644,10 +703,35 @@ public class DataUtils {
}
return
e
;
}
private
static
String
formatMessage
(
int
errorCode
,
String
message
,
Object
...
arguments
)
{
return
MessageFormat
.
format
(
message
,
arguments
)
+
" "
+
getVersionAndCode
(
errorCode
);
}
private
static
String
getVersion
(
)
{
private
static
String
getVersion
AndCode
(
int
errorCode
)
{
return
"["
+
Constants
.
VERSION_MAJOR
+
"."
+
Constants
.
VERSION_MINOR
+
"."
+
Constants
.
BUILD_ID
+
"]"
;
Constants
.
VERSION_MINOR
+
"."
+
Constants
.
BUILD_ID
+
"/"
+
errorCode
+
"]"
;
}
/**
* Get the error code from an exception message.
*
* @param m the message
* @return the error code, or 0 if none
*/
public
static
int
getErrorCode
(
String
m
)
{
if
(
m
.
endsWith
(
"]"
))
{
int
dash
=
m
.
lastIndexOf
(
'/'
);
if
(
dash
>=
0
)
{
String
s
=
m
.
substring
(
dash
+
1
,
m
.
length
()
-
1
);
try
{
return
Integer
.
parseInt
(
s
);
}
catch
(
NumberFormatException
e
)
{
// no error code
}
}
}
return
0
;
}
/**
...
...
h2/src/main/org/h2/mvstore/FreeSpaceList.java
浏览文件 @
769193eb
...
...
@@ -53,6 +53,7 @@ public class FreeSpaceList {
}
}
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_INTERNAL
,
"Could not find a free page to allocate"
);
}
...
...
@@ -75,10 +76,12 @@ public class FreeSpaceList {
}
if
(
found
==
null
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_INTERNAL
,
"Cannot find spot to mark chunk as used in free list: {0}"
,
c
);
}
if
(
chunkStart
+
required
>
found
.
start
+
found
.
length
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_INTERNAL
,
"Chunk runs over edge of free space: {0}"
,
c
);
}
if
(
found
.
start
==
chunkStart
)
{
...
...
@@ -127,6 +130,7 @@ public class FreeSpaceList {
}
if
(
found
==
null
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_INTERNAL
,
"Cannot find spot to mark chunk as unused in free list: {0}"
,
c
);
}
if
(
chunkStart
+
required
+
1
==
found
.
start
)
{
...
...
h2/src/main/org/h2/mvstore/MVMap.java
浏览文件 @
769193eb
...
...
@@ -907,7 +907,8 @@ public class MVMap<K, V> extends AbstractMap<K, V>
*/
protected
void
checkOpen
()
{
if
(
closed
)
{
throw
DataUtils
.
newIllegalStateException
(
"This map is closed"
);
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_CLOSED
,
"This map is closed"
);
}
}
...
...
@@ -937,7 +938,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
if
(
writing
)
{
// try to detect concurrent modification
// on a best-effort basis
throw
DataUtils
.
newConcurrentModificationException
();
throw
DataUtils
.
newConcurrentModificationException
(
getName
()
);
}
}
...
...
@@ -1004,7 +1005,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
public
MVMap
<
K
,
V
>
openVersion
(
long
version
)
{
if
(
readOnly
)
{
throw
DataUtils
.
newUnsupportedOperationException
(
"This map is read-only
-
need to call the method on the writable map"
);
"This map is read-only
;
need to call the method on the writable map"
);
}
DataUtils
.
checkArgument
(
version
>=
createVersion
,
"Unknown version {0}; this map was created in version is {1}"
,
...
...
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
769193eb
...
...
@@ -10,6 +10,7 @@ import java.io.IOException;
import
java.nio.ByteBuffer
;
import
java.nio.channels.FileChannel
;
import
java.nio.channels.FileLock
;
import
java.nio.channels.OverlappingFileLockException
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
...
...
@@ -436,6 +437,10 @@ public class MVStore {
/**
* Open the store.
*
* @throws IllegalStateException if the file is corrupt, or an exception
* occurred while opening
* @throws IllegalArgumentException if the directory does not exist
*/
void
open
()
{
meta
=
new
MVMapConcurrent
<
String
,
String
>(
StringDataType
.
INSTANCE
,
StringDataType
.
INSTANCE
);
...
...
@@ -476,11 +481,13 @@ public class MVStore {
* Try to open the file in read or write mode.
*
* @return if opening the file was successful, and false if the file could
* not be opened in write mode because the write file format it too
* high (in which case the file can be opened in read-only mode)
* @throw IllegalStateException if the file could not be opened at all
* not be opened in write mode because the write file format it too
* high (in which case the file can be opened in read-only mode)
* @throw IllegalStateException if the file could not be opened
* because of an IOException or file format error
*/
private
boolean
openFile
()
{
IllegalStateException
exception
;
try
{
log
(
"file open"
);
FilePath
f
=
FilePath
.
get
(
fileName
);
...
...
@@ -493,16 +500,19 @@ public class MVStore {
file
=
new
FilePathCrypt
.
FileCrypt
(
fileName
,
password
,
file
);
}
file
=
FilePathCache
.
wrap
(
file
);
if
(
readOnly
)
{
fileLock
=
file
.
tryLock
(
0
,
Long
.
MAX_VALUE
,
true
);
if
(
fileLock
==
null
)
{
throw
new
IOException
(
"The file is locked: "
+
fileName
);
}
}
else
{
fileLock
=
file
.
tryLock
();
if
(
fileLock
==
null
)
{
throw
new
IOException
(
"The file is locked: "
+
fileName
);
try
{
if
(
readOnly
)
{
fileLock
=
file
.
tryLock
(
0
,
Long
.
MAX_VALUE
,
true
);
}
else
{
fileLock
=
file
.
tryLock
();
}
}
catch
(
OverlappingFileLockException
e
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_FILE_LOCKED
,
"The file is locked: {0}"
,
fileName
,
e
);
}
if
(
fileLock
==
null
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_FILE_LOCKED
,
"The file is locked: {0}"
,
fileName
);
}
fileSize
=
file
.
size
();
if
(
fileSize
==
0
)
{
...
...
@@ -521,8 +531,9 @@ public class MVStore {
int
formatRead
=
x
==
null
?
formatWrite
:
Integer
.
parseInt
(
x
);
if
(
formatRead
>
FORMAT_READ
)
{
throw
DataUtils
.
newIllegalStateException
(
"The file format {0} is larger than the supported format {1}"
,
formatRead
,
FORMAT_READ
);
DataUtils
.
ERROR_UNSUPPORTED_FORMAT
,
"The file format {0} is larger than the supported format {1}"
,
formatRead
,
FORMAT_READ
);
}
if
(
formatWrite
>
FORMAT_WRITE
)
{
readOnly
=
true
;
...
...
@@ -533,14 +544,21 @@ public class MVStore {
readMeta
();
}
}
}
catch
(
Exception
e
)
{
exception
=
null
;
}
catch
(
IOException
e
)
{
exception
=
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_READING_FAILED
,
"Could not open file {0}"
,
fileName
,
e
);
}
catch
(
IllegalStateException
e
)
{
exception
=
e
;
}
if
(
exception
!=
null
)
{
try
{
closeFile
(
false
);
}
catch
(
Exception
e2
)
{
// ignore
}
throw
DataUtils
.
newIllegalStateException
(
"Could not open file {0}"
,
fileName
,
e
);
throw
exception
;
}
return
true
;
}
...
...
@@ -603,7 +621,12 @@ public class MVStore {
for
(
int
i
=
0
;
i
<
3
*
BLOCK_SIZE
;
i
+=
BLOCK_SIZE
)
{
String
s
=
new
String
(
buff
.
array
(),
i
,
BLOCK_SIZE
,
Constants
.
UTF8
)
.
trim
();
HashMap
<
String
,
String
>
m
=
DataUtils
.
parseMap
(
s
);
HashMap
<
String
,
String
>
m
;
try
{
m
=
DataUtils
.
parseMap
(
s
);
}
catch
(
IllegalArgumentException
e
)
{
continue
;
}
String
f
=
m
.
remove
(
"fletcher"
);
if
(
f
==
null
)
{
continue
;
...
...
@@ -630,7 +653,8 @@ public class MVStore {
}
}
if
(
currentVersion
<
0
)
{
throw
DataUtils
.
newIllegalStateException
(
"File header is corrupt"
);
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_FILE_CORRUPT
,
"File header is corrupt: {0}"
,
fileName
);
}
lastStoredVersion
=
-
1
;
}
...
...
@@ -645,8 +669,11 @@ public class MVStore {
int
checksum
=
DataUtils
.
getFletcher32
(
bytes
,
bytes
.
length
/
2
*
2
);
DataUtils
.
appendMap
(
buff
,
"fletcher"
,
Integer
.
toHexString
(
checksum
));
bytes
=
buff
.
toString
().
getBytes
(
Constants
.
UTF8
);
DataUtils
.
checkArgument
(
bytes
.
length
<=
BLOCK_SIZE
,
"File header too large: {0}"
,
buff
);
if
(
bytes
.
length
>
BLOCK_SIZE
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_UNSUPPORTED_FORMAT
,
"File header too large: {0}"
,
buff
);
}
return
bytes
;
}
...
...
@@ -720,6 +747,7 @@ public class MVStore {
maps
.
clear
();
}
catch
(
Exception
e
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_WRITING_FAILED
,
"Closing failed for file {0}"
,
fileName
,
e
);
}
finally
{
file
=
null
;
...
...
@@ -799,7 +827,8 @@ public class MVStore {
return
currentVersion
;
}
if
(
readOnly
)
{
throw
DataUtils
.
newIllegalStateException
(
"This store is read-only"
);
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_WRITING_FAILED
,
"This store is read-only"
);
}
int
currentUnsavedPageCount
=
unsavedPageCount
;
long
storeVersion
=
currentStoreVersion
=
currentVersion
;
...
...
@@ -893,7 +922,8 @@ public class MVStore {
if
(
ASSERT
)
{
if
(
freedPages
.
size
()
>
0
)
{
throw
DataUtils
.
newIllegalStateException
(
"Temporary freed chunks"
);
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_INTERNAL
,
"Temporary freed chunks"
);
}
}
...
...
@@ -1002,14 +1032,17 @@ public class MVStore {
c
.
pageCountLive
+=
f
.
pageCountLive
;
if
(
c
.
pageCountLive
<
0
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_INTERNAL
,
"Corrupt page count {0}"
,
c
.
pageCountLive
);
}
if
(
c
.
maxLengthLive
<
0
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_INTERNAL
,
"Corrupt max length {0}"
,
c
.
maxLengthLive
);
}
if
(
c
.
pageCount
==
0
&&
c
.
maxLengthLive
>
0
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_INTERNAL
,
"Corrupt max length {0}"
,
c
.
maxLengthLive
);
}
modified
.
add
(
c
);
...
...
@@ -1060,6 +1093,7 @@ public class MVStore {
file
.
truncate
(
used
);
}
catch
(
IOException
e
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_WRITING_FAILED
,
"Could not truncate file {0} to size {1}"
,
fileName
,
used
,
e
);
}
...
...
@@ -1259,6 +1293,7 @@ public class MVStore {
Chunk
c
=
getChunk
(
pos
);
if
(
c
==
null
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_FILE_CORRUPT
,
"Chunk {0} not found"
,
DataUtils
.
getPageChunkId
(
pos
));
}
...
...
@@ -1682,7 +1717,8 @@ public class MVStore {
private
void
checkOpen
()
{
if
(
closed
)
{
throw
DataUtils
.
newIllegalStateException
(
"This store is closed"
);
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_CLOSED
,
"This store is closed"
);
}
}
...
...
@@ -1741,6 +1777,15 @@ public class MVStore {
store
(
true
);
}
/**
* Set the read cache size in MB.
*
* @param mb the cache size in MB.
*/
public
void
setCacheSize
(
long
mb
)
{
cache
.
setMaxMemory
(
mb
*
1024
*
1024
);
}
public
boolean
isReadOnly
()
{
return
readOnly
;
}
...
...
h2/src/main/org/h2/mvstore/Page.java
浏览文件 @
769193eb
...
...
@@ -429,6 +429,7 @@ public class Page {
}
if
(
check
!=
totalCount
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_INTERNAL
,
"Expected: {0} got: {1}"
,
check
,
totalCount
);
}
}
...
...
@@ -694,6 +695,7 @@ public class Page {
int
pageLength
=
buff
.
getInt
();
if
(
pageLength
>
maxLength
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_FILE_CORRUPT
,
"File corrupted, expected length =< {0}, got {1}"
,
maxLength
,
pageLength
);
}
...
...
@@ -701,6 +703,7 @@ public class Page {
int
mapId
=
DataUtils
.
readVarInt
(
buff
);
if
(
mapId
!=
map
.
getId
())
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_FILE_CORRUPT
,
"File corrupted, expected map id {0}, got {1}"
,
map
.
getId
(),
mapId
);
}
...
...
@@ -709,6 +712,7 @@ public class Page {
^
DataUtils
.
getCheckValue
(
pageLength
);
if
(
check
!=
(
short
)
checkTest
)
{
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_FILE_CORRUPT
,
"File corrupted, expected check value {0}, got {1}"
,
checkTest
,
check
);
}
...
...
@@ -818,7 +822,8 @@ public class Page {
^
DataUtils
.
getCheckValue
(
pageLength
);
buff
.
putShort
(
start
+
4
,
(
short
)
check
);
if
(
pos
!=
0
)
{
throw
DataUtils
.
newIllegalStateException
(
"Page already stored"
);
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_INTERNAL
,
"Page already stored"
);
}
pos
=
DataUtils
.
getPagePos
(
chunkId
,
start
,
pageLength
,
type
);
long
max
=
DataUtils
.
getPageMaxLength
(
pos
);
...
...
@@ -901,7 +906,8 @@ public class Page {
public
int
getMemory
()
{
if
(
MVStore
.
ASSERT
)
{
if
(
memory
!=
calculateMemory
())
{
throw
DataUtils
.
newIllegalStateException
(
"Memory calculation error"
);
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_INTERNAL
,
"Memory calculation error"
);
}
}
return
memory
;
...
...
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
浏览文件 @
769193eb
...
...
@@ -11,13 +11,16 @@ import java.util.List;
import
org.h2.api.TableEngine
;
import
org.h2.command.ddl.CreateTableData
;
import
org.h2.constant.ErrorCode
;
import
org.h2.engine.Constants
;
import
org.h2.engine.Database
;
import
org.h2.engine.Session
;
import
org.h2.message.DbException
;
import
org.h2.mvstore.DataUtils
;
import
org.h2.mvstore.MVStore
;
import
org.h2.mvstore.db.TransactionStore.Transaction
;
import
org.h2.store.InDoubtTransaction
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.table.RegularTable
;
import
org.h2.table.TableBase
;
import
org.h2.util.New
;
...
...
@@ -26,13 +29,14 @@ import org.h2.util.New;
* A table engine that internally uses the MVStore.
*/
public
class
MVTableEngine
implements
TableEngine
{
@Override
public
TableBase
createTable
(
CreateTableData
data
)
{
Database
db
=
data
.
session
.
getDatabase
();
if
(!
data
.
persistData
||
(
data
.
temporary
&&
!
data
.
persistIndexes
))
{
return
new
RegularTable
(
data
);
}
/**
* Initialize the MVStore.
*
* @param db the database
* @return the store
*/
public
static
Store
init
(
Database
db
)
{
Store
store
=
db
.
getMvStore
();
if
(
store
==
null
)
{
byte
[]
key
=
db
.
getFilePasswordHash
();
...
...
@@ -41,9 +45,19 @@ public class MVTableEngine implements TableEngine {
if
(
dbPath
==
null
)
{
store
=
new
Store
(
db
,
builder
.
open
());
}
else
{
builder
.
fileName
(
dbPath
+
Constants
.
SUFFIX_MV_FILE
);
String
fileName
=
dbPath
+
Constants
.
SUFFIX_MV_FILE
;
builder
.
fileName
(
fileName
);
if
(
db
.
isReadOnly
())
{
builder
.
readOnly
();
}
else
{
// possibly create the directory
boolean
exists
=
FileUtils
.
exists
(
fileName
);
if
(
exists
&&
!
FileUtils
.
canWrite
(
fileName
))
{
// read only
}
else
{
String
dir
=
FileUtils
.
getParent
(
fileName
);
FileUtils
.
createDirectories
(
dir
);
}
}
if
(
key
!=
null
)
{
char
[]
password
=
new
char
[
key
.
length
];
...
...
@@ -52,10 +66,32 @@ public class MVTableEngine implements TableEngine {
}
builder
.
encryptionKey
(
password
);
}
store
=
new
Store
(
db
,
builder
.
open
());
try
{
store
=
new
Store
(
db
,
builder
.
open
());
}
catch
(
IllegalStateException
e
)
{
int
errorCode
=
DataUtils
.
getErrorCode
(
e
.
getMessage
());
if
(
errorCode
==
DataUtils
.
ERROR_FILE_CORRUPT
)
{
if
(
key
!=
null
)
{
throw
DbException
.
get
(
ErrorCode
.
FILE_ENCRYPTION_ERROR_1
,
fileName
);
}
}
else
if
(
errorCode
==
DataUtils
.
ERROR_FILE_LOCKED
)
{
throw
DbException
.
get
(
ErrorCode
.
DATABASE_ALREADY_OPEN_1
,
fileName
);
}
throw
DbException
.
get
(
ErrorCode
.
FILE_CORRUPTED_1
,
fileName
);
}
}
db
.
setMvStore
(
store
);
}
return
store
;
}
@Override
public
TableBase
createTable
(
CreateTableData
data
)
{
Database
db
=
data
.
session
.
getDatabase
();
if
(!
data
.
persistData
||
(
data
.
temporary
&&
!
data
.
persistIndexes
))
{
return
new
RegularTable
(
data
);
}
Store
store
=
init
(
db
);
MVTable
table
=
new
MVTable
(
data
,
store
);
store
.
openTables
.
add
(
table
);
table
.
init
(
data
.
session
);
...
...
@@ -188,6 +224,10 @@ public class MVTableEngine implements TableEngine {
return
result
;
}
public
void
setCacheSize
(
int
kb
)
{
store
.
setCacheSize
(
kb
*
1024
);
}
}
/**
...
...
h2/src/main/org/h2/mvstore/db/TransactionStore.java
浏览文件 @
769193eb
...
...
@@ -111,7 +111,9 @@ public class TransactionStore {
}
Long
lastKey
=
preparedTransactions
.
lastKey
();
if
(
lastKey
!=
null
&&
lastKey
.
longValue
()
>
lastTransactionId
)
{
throw
DataUtils
.
newIllegalStateException
(
"Last transaction not stored"
);
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_TRANSACTION_CORRUPT
,
"Last transaction not stored"
);
}
if
(
undoLog
.
size
()
>
0
)
{
long
[]
key
=
undoLog
.
firstKey
();
...
...
@@ -616,7 +618,8 @@ public class TransactionStore {
*/
void
checkNotClosed
()
{
if
(
status
==
STATUS_CLOSED
)
{
throw
DataUtils
.
newIllegalStateException
(
"Transaction is closed"
);
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_CLOSED
,
"Transaction is closed"
);
}
}
...
...
@@ -749,14 +752,16 @@ public class TransactionStore {
// wait until it is committed, or until the lock timeout
long
timeout
=
transaction
.
store
.
lockTimeout
;
if
(
timeout
==
0
)
{
throw
DataUtils
.
newIllegalStateException
(
"Lock timeout"
);
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_TRANSACTION_LOCK_TIMEOUT
,
"Lock timeout"
);
}
if
(
start
==
0
)
{
start
=
System
.
currentTimeMillis
();
}
else
{
long
t
=
System
.
currentTimeMillis
()
-
start
;
if
(
t
>
timeout
)
{
throw
DataUtils
.
newIllegalStateException
(
"Lock timeout"
);
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_TRANSACTION_LOCK_TIMEOUT
,
"Lock timeout"
);
}
// TODO use wait/notify instead, or remove the feature
try
{
...
...
h2/src/main/org/h2/mvstore/rtree/MVRTreeMap.java
浏览文件 @
769193eb
...
...
@@ -8,8 +8,8 @@ package org.h2.mvstore.rtree;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
org.h2.mvstore.Cursor
;
import
org.h2.mvstore.CursorPos
;
import
org.h2.mvstore.DataUtils
;
import
org.h2.mvstore.MVMap
;
import
org.h2.mvstore.Page
;
import
org.h2.mvstore.type.DataType
;
...
...
@@ -63,7 +63,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
*/
public
Iterator
<
SpatialKey
>
findIntersectingKeys
(
SpatialKey
x
)
{
checkOpen
();
return
new
RTreeCursor
(
this
,
root
,
x
)
{
return
new
RTreeCursor
(
root
,
x
)
{
@Override
protected
boolean
check
(
boolean
leaf
,
SpatialKey
key
,
SpatialKey
test
)
{
return
keyType
.
isOverlap
(
key
,
test
);
...
...
@@ -79,7 +79,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
*/
public
Iterator
<
SpatialKey
>
findContainedKeys
(
SpatialKey
x
)
{
checkOpen
();
return
new
RTreeCursor
(
this
,
root
,
x
)
{
return
new
RTreeCursor
(
root
,
x
)
{
@Override
protected
boolean
check
(
boolean
leaf
,
SpatialKey
key
,
SpatialKey
test
)
{
if
(
leaf
)
{
...
...
@@ -479,78 +479,223 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
/**
* A cursor to iterate over a subset of the keys.
*/
static
class
RTreeCursor
extends
Cursor
<
SpatialKey
>
{
protected
RTreeCursor
(
MVRTreeMap
<?>
map
,
Page
root
,
SpatialKey
from
)
{
super
(
map
,
root
,
from
);
static
class
RTreeCursor
implements
Iterator
<
SpatialKey
>
{
private
final
SpatialKey
filter
;
private
CursorPos
pos
;
private
SpatialKey
current
;
private
final
Page
root
;
private
boolean
initialized
;
protected
RTreeCursor
(
Page
root
,
SpatialKey
filter
)
{
this
.
root
=
root
;
this
.
filter
=
filter
;
}
@Override
public
void
skip
(
long
n
)
{
if
(!
hasNext
())
{
return
;
}
while
(
n
--
>
0
)
{
public
boolean
hasNext
()
{
if
(!
initialized
)
{
// init
pos
=
new
CursorPos
(
root
,
0
,
null
);
fetchNext
();
initialized
=
true
;
}
return
current
!=
null
;
}
/**
* Check a given key.
*
* @param leaf if the key is from a leaf page
* @param key the stored key
* @param test the user-supplied test key
* @return true if there is a match
*/
protected
boolean
check
(
boolean
leaf
,
SpatialKey
key
,
SpatialKey
test
)
{
return
true
;
public
void
skip
(
long
n
)
{
while
(
hasNext
()
&&
n
--
>
0
)
{
fetchNext
();
}
}
@Override
protected
void
min
(
Page
p
,
SpatialKey
x
)
{
while
(
true
)
{
if
(
p
.
isLeaf
())
{
pos
=
new
CursorPos
(
p
,
0
,
pos
);
return
;
}
boolean
found
=
false
;
for
(
int
i
=
0
;
i
<
p
.
getKeyCount
();
i
++)
{
if
(
check
(
false
,
(
SpatialKey
)
p
.
getKey
(
i
),
x
))
{
pos
=
new
CursorPos
(
p
,
i
+
1
,
pos
);
p
=
p
.
getChildPage
(
i
);
found
=
true
;
break
;
}
}
if
(!
found
)
{
break
;
}
public
SpatialKey
next
()
{
if
(!
hasNext
())
{
return
null
;
}
SpatialKey
c
=
current
;
fetchNext
();
return
c
;
}
@Override
public
void
remove
()
{
throw
DataUtils
.
newUnsupportedOperationException
(
"Removing is not supported"
);
}
/**
* Fetch the next entry if there is one.
*/
protected
void
fetchNext
()
{
while
(
pos
!=
null
)
{
while
(
pos
.
index
<
pos
.
page
.
getKeyCount
())
{
SpatialKey
k
=
(
SpatialKey
)
pos
.
page
.
getKey
(
pos
.
index
++);
if
(
check
(
true
,
k
,
from
))
{
current
=
k
;
return
;
Page
p
=
pos
.
page
;
if
(
p
.
isLeaf
())
{
while
(
pos
.
index
<
p
.
getKeyCount
())
{
SpatialKey
c
=
(
SpatialKey
)
p
.
getKey
(
pos
.
index
++);
if
(
filter
==
null
||
check
(
true
,
c
,
filter
))
{
current
=
c
;
return
;
}
}
}
else
{
boolean
found
=
false
;
while
(
pos
.
index
<
p
.
getKeyCount
())
{
int
index
=
pos
.
index
++;
SpatialKey
c
=
(
SpatialKey
)
p
.
getKey
(
index
);
if
(
filter
==
null
||
check
(
false
,
c
,
filter
))
{
Page
child
=
pos
.
page
.
getChildPage
(
index
);
pos
=
new
CursorPos
(
child
,
0
,
pos
);
found
=
true
;
break
;
}
}
if
(
found
)
{
continue
;
}
}
// parent
pos
=
pos
.
parent
;
if
(
pos
==
null
)
{
break
;
}
MVRTreeMap
<?>
m
=
(
MVRTreeMap
<?>)
map
;
if
(
pos
.
index
<
m
.
getChildPageCount
(
pos
.
page
))
{
min
(
pos
.
page
.
getChildPage
(
pos
.
index
++),
from
);
}
}
current
=
null
;
}
// if(pos==null || pos.page != p) {
// pos = new CursorPos(p, i + 1, pos);
// } else {
// pos.index = i + 1;
// }
// p = p.getChildPage(i);
// found = true;
// break;
// }
// }
//
// if (pos.index < pos.page.getKeyCount()) {
// pos.index++;
// }
// current = (SpatialKey) pos.page.getKey(pos.index++);
// return;
// }
// pos = pos.parent;
// if (pos == null) {
// break;
// }
// if (pos.index < m.getChildPageCount(pos.page)) {
// min(pos.page.getChildPage(pos.index++), null);
// }
// }
// current = null;
// }
/**
* Check a given key.
*
* @param leaf if the key is from a leaf page
* @param key the stored key
* @param test the user-supplied test key
* @return true if there is a match
*/
protected
boolean
check
(
boolean
leaf
,
SpatialKey
key
,
SpatialKey
test
)
{
return
true
;
}
//// @Override
// protected void min2(Page p, SpatialKey x) {
// while (true) {
// if (p.isLeaf()) {
// pos = new CursorPos(p, 0, pos);
// return;
// } else if(pos != null && pos.page != p ) {
// pos = new CursorPos(p, 0, pos);
// }
// boolean found = false;
// int firstChildIndex = 0;
// if(pos!=null && pos.page == p) {
// firstChildIndex = pos.index;
// }
// for (int i = firstChildIndex; i < p.getKeyCount(); i++) {
// if (check(false, (SpatialKey) p.getKey(i), x)) {
// if(pos==null || pos.page != p) {
// pos = new CursorPos(p, i + 1, pos);
// } else {
// pos.index = i + 1;
// }
// p = p.getChildPage(i);
// found = true;
// break;
// }
// }
// if (!found) {
// if(pos==null || pos.page.isLeaf()) {
// break;
// } else {
// pos = pos.parent;
// if(pos!=null) {
// p = pos.page;
// } else {
// //No more entries
// break;
// }
// }
// }
// }
// }
//
// @Override
// protected void min(Page p, SpatialKey x) {
// // x
// }
//
// protected void min3(Page p, SpatialKey x) {
// while (true) {
// if (p.isLeaf()) {
// pos = new CursorPos(p, 0, pos);
// return;
// }
// boolean found = false;
// for (int i = 0; i < p.getKeyCount(); i++) {
// if (check(false, (SpatialKey) p.getKey(i), x)) {
// pos = new CursorPos(p, i + 1, pos);
// p = p.getChildPage(i);
// found = true;
// break;
// }
// }
// if (!found) {
// if (pos == null) {
// return;
// }
// pos = pos.parent;
// break;
// }
// }
// }
//
// @Override
// protected void fetchNext() {
// while (pos != null) {
// while (pos.index < pos.page.getKeyCount()) {
// SpatialKey k = (SpatialKey) pos.page.getKey(pos.index++);
// if (check(true, k, from)) {
// current = k;
// return;
// }
// }
// pos = pos.parent;
// if (pos == null) {
// break;
// }
// MVRTreeMap<?> m = (MVRTreeMap<?>) map;
// if (pos.index < m.getChildPageCount(pos.page)) {
// min(pos.page.getChildPage(pos.index++), from);
// }
// }
// current = null;
// }
}
@Override
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论