Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
e949b40f
提交
e949b40f
authored
12 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
A persistent multi-version map - generic data type serialization
上级
5167b8ef
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
1798 行增加
和
63 行删除
+1798
-63
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+2
-0
ObjectType.java
h2/src/test/org/h2/test/store/ObjectType.java
+1476
-0
TestDataUtils.java
h2/src/test/org/h2/test/store/TestDataUtils.java
+17
-0
TestMVStore.java
h2/src/test/org/h2/test/store/TestMVStore.java
+43
-15
TestMapFactory.java
h2/src/test/org/h2/test/store/TestMapFactory.java
+4
-0
TestObjectType.java
h2/src/test/org/h2/test/store/TestObjectType.java
+151
-0
DataUtils.java
h2/src/tools/org/h2/dev/store/btree/DataUtils.java
+57
-0
MVStore.java
h2/src/tools/org/h2/dev/store/btree/MVStore.java
+43
-20
MapFactory.java
h2/src/tools/org/h2/dev/store/btree/MapFactory.java
+1
-1
StringType.java
h2/src/tools/org/h2/dev/store/btree/StringType.java
+4
-27
没有找到文件。
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
e949b40f
...
@@ -108,6 +108,7 @@ import org.h2.test.store.TestConcurrent;
...
@@ -108,6 +108,7 @@ import org.h2.test.store.TestConcurrent;
import
org.h2.test.store.TestDataUtils
;
import
org.h2.test.store.TestDataUtils
;
import
org.h2.test.store.TestMVStore
;
import
org.h2.test.store.TestMVStore
;
import
org.h2.test.store.TestMVRTree
;
import
org.h2.test.store.TestMVRTree
;
import
org.h2.test.store.TestObjectType
;
import
org.h2.test.synth.TestBtreeIndex
;
import
org.h2.test.synth.TestBtreeIndex
;
import
org.h2.test.synth.TestCrashAPI
;
import
org.h2.test.synth.TestCrashAPI
;
import
org.h2.test.synth.TestDiskFull
;
import
org.h2.test.synth.TestDiskFull
;
...
@@ -671,6 +672,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
...
@@ -671,6 +672,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new
TestDataUtils
().
runTest
(
this
);
new
TestDataUtils
().
runTest
(
this
);
new
TestMVRTree
().
runTest
(
this
);
new
TestMVRTree
().
runTest
(
this
);
new
TestMVStore
().
runTest
(
this
);
new
TestMVStore
().
runTest
(
this
);
new
TestObjectType
().
runTest
(
this
);
// unit
// unit
new
TestAutoReconnect
().
runTest
(
this
);
new
TestAutoReconnect
().
runTest
(
this
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/ObjectType.java
0 → 100644
浏览文件 @
e949b40f
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
test
.
store
;
import
java.math.BigDecimal
;
import
java.math.BigInteger
;
import
java.nio.ByteBuffer
;
import
java.util.UUID
;
import
org.h2.dev.store.btree.DataType
;
import
org.h2.dev.store.btree.DataUtils
;
import
org.h2.dev.store.btree.MVStore
;
import
org.h2.util.Utils
;
/**
* A data type implementation for the most common data types, including
* serializable objects.
*/
public
class
ObjectType
implements
DataType
{
// TODO maybe support InputStream, Reader
// TODO maybe support ResultSet, Date, Time, Timestamp
// TODO maybe support boolean[], short[],...
static
final
int
TYPE_BOOLEAN
=
1
;
static
final
int
TYPE_BYTE
=
2
;
static
final
int
TYPE_SHORT
=
3
;
static
final
int
TYPE_INTEGER
=
4
;
static
final
int
TYPE_LONG
=
5
;
static
final
int
TYPE_BIG_INTEGER
=
6
;
static
final
int
TYPE_FLOAT
=
7
;
static
final
int
TYPE_DOUBLE
=
8
;
static
final
int
TYPE_BIG_DECIMAL
=
9
;
static
final
int
TYPE_CHARACTER
=
10
;
static
final
int
TYPE_STRING
=
11
;
static
final
int
TYPE_UUID
=
12
;
static
final
int
TYPE_BYTE_ARRAY
=
13
;
static
final
int
TYPE_INT_ARRAY
=
14
;
static
final
int
TYPE_LONG_ARRAY
=
15
;
static
final
int
TYPE_CHAR_ARRAY
=
16
;
static
final
int
TYPE_SERIALIZED_OBJECT
=
17
;
static
final
int
TAG_BOOLEAN_TRUE
=
32
;
static
final
int
TAG_INTEGER_NEGATIVE
=
33
;
static
final
int
TAG_INTEGER_FIXED
=
34
;
static
final
int
TAG_LONG_NEGATIVE
=
35
;
static
final
int
TAG_LONG_FIXED
=
36
;
static
final
int
TAG_BIG_INTEGER_0
=
37
;
static
final
int
TAG_BIG_INTEGER_1
=
38
;
static
final
int
TAG_BIG_INTEGER_SMALL
=
39
;
static
final
int
TAG_FLOAT_0
=
40
;
static
final
int
TAG_FLOAT_1
=
41
;
static
final
int
TAG_FLOAT_FIXED
=
42
;
static
final
int
TAG_DOUBLE_0
=
43
;
static
final
int
TAG_DOUBLE_1
=
44
;
static
final
int
TAG_DOUBLE_FIXED
=
45
;
static
final
int
TAG_BIG_DECIMAL_0
=
46
;
static
final
int
TAG_BIG_DECIMAL_1
=
47
;
static
final
int
TAG_BIG_DECIMAL_SMALL
=
48
;
static
final
int
TAG_BIG_DECIMAL_SMALL_SCALED
=
49
;
static
final
int
TAG_INTEGER_0_15
=
64
;
static
final
int
TAG_LONG_0_7
=
80
;
static
final
int
TAG_STRING_0_15
=
88
;
static
final
int
TAG_BYTE_ARRAY_0_15
=
104
;
static
final
int
FLOAT_ZERO_BITS
=
Float
.
floatToIntBits
(
0.0f
);
static
final
int
FLOAT_ONE_BITS
=
Float
.
floatToIntBits
(
1.0f
);
static
final
long
DOUBLE_ZERO_BITS
=
Double
.
doubleToLongBits
(
0.0d
);
static
final
long
DOUBLE_ONE_BITS
=
Double
.
doubleToLongBits
(
1.0d
);
private
AutoDetectDataType
last
=
new
StringType
(
this
);
@Override
public
int
compare
(
Object
a
,
Object
b
)
{
return
last
.
compare
(
a
,
b
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
return
last
.
getMaxLength
(
obj
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
return
last
.
getMemory
(
obj
);
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
last
.
write
(
buff
,
obj
);
}
private
AutoDetectDataType
newType
(
int
typeId
)
{
switch
(
typeId
)
{
case
TYPE_BOOLEAN:
return
new
BooleanType
(
this
);
case
TYPE_BYTE:
return
new
ByteType
(
this
);
case
TYPE_SHORT:
return
new
ShortType
(
this
);
case
TYPE_CHARACTER:
return
new
CharacterType
(
this
);
case
TYPE_INTEGER:
return
new
IntegerType
(
this
);
case
TYPE_LONG:
return
new
LongType
(
this
);
case
TYPE_FLOAT:
return
new
FloatType
(
this
);
case
TYPE_DOUBLE:
return
new
DoubleType
(
this
);
case
TYPE_BIG_INTEGER:
return
new
BigIntegerType
(
this
);
case
TYPE_BIG_DECIMAL:
return
new
BigDecimalType
(
this
);
case
TYPE_BYTE_ARRAY:
return
new
ByteArrayType
(
this
);
case
TYPE_CHAR_ARRAY:
return
new
CharArrayType
(
this
);
case
TYPE_INT_ARRAY:
return
new
IntArrayType
(
this
);
case
TYPE_LONG_ARRAY:
return
new
LongArrayType
(
this
);
case
TYPE_STRING:
return
new
StringType
(
this
);
case
TYPE_UUID:
return
new
UUIDType
(
this
);
case
TYPE_SERIALIZED_OBJECT:
return
new
SerializedObjectType
(
this
);
}
throw
new
RuntimeException
(
"Unsupported type: "
+
typeId
);
}
@Override
public
Object
read
(
ByteBuffer
buff
)
{
int
tag
=
buff
.
get
();
int
typeId
;
if
(
tag
<=
TYPE_SERIALIZED_OBJECT
)
{
typeId
=
tag
;
}
else
{
switch
(
tag
)
{
case
TAG_BOOLEAN_TRUE:
typeId
=
TYPE_BOOLEAN
;
break
;
case
TAG_INTEGER_NEGATIVE:
case
TAG_INTEGER_FIXED:
typeId
=
TYPE_INTEGER
;
break
;
case
TAG_LONG_NEGATIVE:
case
TAG_LONG_FIXED:
typeId
=
TYPE_LONG
;
break
;
case
TAG_BIG_INTEGER_0:
case
TAG_BIG_INTEGER_1:
case
TAG_BIG_INTEGER_SMALL:
typeId
=
TYPE_BIG_INTEGER
;
break
;
case
TAG_FLOAT_0:
case
TAG_FLOAT_1:
case
TAG_FLOAT_FIXED:
typeId
=
TYPE_FLOAT
;
break
;
case
TAG_DOUBLE_0:
case
TAG_DOUBLE_1:
case
TAG_DOUBLE_FIXED:
typeId
=
TYPE_DOUBLE
;
break
;
case
TAG_BIG_DECIMAL_0:
case
TAG_BIG_DECIMAL_1:
case
TAG_BIG_DECIMAL_SMALL:
case
TAG_BIG_DECIMAL_SMALL_SCALED:
typeId
=
TYPE_BIG_DECIMAL
;
break
;
default
:
if
(
tag
>=
TAG_INTEGER_0_15
&&
tag
<=
TAG_INTEGER_0_15
+
15
)
{
typeId
=
TYPE_INTEGER
;
}
else
if
(
tag
>=
TAG_STRING_0_15
&&
tag
<=
TAG_STRING_0_15
+
15
)
{
typeId
=
TYPE_STRING
;
}
else
if
(
tag
>=
TAG_LONG_0_7
&&
tag
<=
TAG_LONG_0_7
+
7
)
{
typeId
=
TYPE_LONG
;
}
else
if
(
tag
>=
TAG_BYTE_ARRAY_0_15
&&
tag
<=
TAG_BYTE_ARRAY_0_15
+
15
)
{
typeId
=
TYPE_BYTE_ARRAY
;
}
else
{
throw
new
RuntimeException
(
"Unknown tag: "
+
tag
);
}
}
}
if
(
typeId
!=
last
.
typeId
)
{
last
=
newType
(
typeId
);
}
return
last
.
read
(
buff
,
tag
);
}
@Override
public
String
asString
()
{
return
"o"
;
}
private
static
int
getTypeId
(
Object
obj
)
{
if
(
obj
instanceof
Integer
)
{
return
TYPE_INTEGER
;
}
else
if
(
obj
instanceof
String
)
{
return
TYPE_STRING
;
}
else
if
(
obj
instanceof
Long
)
{
return
TYPE_LONG
;
}
else
if
(
obj
instanceof
BigDecimal
)
{
if
(
obj
.
getClass
()
==
BigDecimal
.
class
)
{
return
TYPE_BIG_DECIMAL
;
}
}
else
if
(
obj
instanceof
byte
[])
{
return
TYPE_BYTE_ARRAY
;
}
else
if
(
obj
instanceof
Double
)
{
return
TYPE_DOUBLE
;
}
else
if
(
obj
instanceof
Float
)
{
return
TYPE_FLOAT
;
}
else
if
(
obj
instanceof
Boolean
)
{
return
TYPE_BOOLEAN
;
}
else
if
(
obj
instanceof
UUID
)
{
return
TYPE_UUID
;
}
else
if
(
obj
instanceof
Byte
)
{
return
TYPE_BYTE
;
}
else
if
(
obj
instanceof
int
[])
{
return
TYPE_INT_ARRAY
;
}
else
if
(
obj
instanceof
long
[])
{
return
TYPE_LONG_ARRAY
;
}
else
if
(
obj
instanceof
char
[])
{
return
TYPE_CHAR_ARRAY
;
}
else
if
(
obj
instanceof
Short
)
{
return
TYPE_SHORT
;
}
else
if
(
obj
instanceof
BigInteger
)
{
if
(
obj
.
getClass
()
==
BigInteger
.
class
)
{
return
TYPE_BIG_INTEGER
;
}
}
else
if
(
obj
instanceof
Character
)
{
return
TYPE_CHARACTER
;
}
if
(
obj
==
null
)
{
throw
new
NullPointerException
();
}
return
TYPE_SERIALIZED_OBJECT
;
}
AutoDetectDataType
switchType
(
Object
obj
)
{
int
typeId
=
getTypeId
(
obj
);
AutoDetectDataType
l
=
last
;
if
(
typeId
!=
l
.
typeId
)
{
l
=
last
=
newType
(
typeId
);
}
return
l
;
}
/**
* Compare the contents of two arrays.
*
* @param data1 the first array (must not be null)
* @param data2 the second array (must not be null)
* @return the result of the comparison (-1, 1 or 0)
*/
public
static
int
compareNotNull
(
char
[]
data1
,
char
[]
data2
)
{
if
(
data1
==
data2
)
{
return
0
;
}
int
len
=
Math
.
min
(
data1
.
length
,
data2
.
length
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
char
x
=
data1
[
i
];
char
x2
=
data2
[
i
];
if
(
x
!=
x2
)
{
return
x
>
x2
?
1
:
-
1
;
}
}
return
Integer
.
signum
(
data1
.
length
-
data2
.
length
);
}
/**
* Compare the contents of two arrays.
*
* @param data1 the first array (must not be null)
* @param data2 the second array (must not be null)
* @return the result of the comparison (-1, 1 or 0)
*/
public
static
int
compareNotNull
(
int
[]
data1
,
int
[]
data2
)
{
if
(
data1
==
data2
)
{
return
0
;
}
int
len
=
Math
.
min
(
data1
.
length
,
data2
.
length
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
int
x
=
data1
[
i
];
int
x2
=
data2
[
i
];
if
(
x
!=
x2
)
{
return
x
>
x2
?
1
:
-
1
;
}
}
return
Integer
.
signum
(
data1
.
length
-
data2
.
length
);
}
/**
* Compare the contents of two arrays.
*
* @param data1 the first array (must not be null)
* @param data2 the second array (must not be null)
* @return the result of the comparison (-1, 1 or 0)
*/
public
static
int
compareNotNull
(
long
[]
data1
,
long
[]
data2
)
{
if
(
data1
==
data2
)
{
return
0
;
}
int
len
=
Math
.
min
(
data1
.
length
,
data2
.
length
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
long
x
=
data1
[
i
];
long
x2
=
data2
[
i
];
if
(
x
!=
x2
)
{
return
x
>
x2
?
1
:
-
1
;
}
}
return
Integer
.
signum
(
data1
.
length
-
data2
.
length
);
}
/**
* The base class for auto-detect data types.
*/
abstract
class
AutoDetectDataType
implements
DataType
{
protected
final
ObjectType
base
;
protected
final
int
typeId
;
AutoDetectDataType
(
ObjectType
base
,
int
typeId
)
{
this
.
base
=
base
;
this
.
typeId
=
typeId
;
}
@Override
public
int
getMemory
(
Object
o
)
{
return
getType
(
o
).
getMemory
(
o
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
AutoDetectDataType
aType
=
getType
(
aObj
);
AutoDetectDataType
bType
=
getType
(
bObj
);
if
(
aType
==
bType
)
{
return
aType
.
compare
(
aObj
,
bObj
);
}
int
typeDiff
=
aType
.
typeId
-
bType
.
typeId
;
return
Integer
.
signum
(
typeDiff
);
}
@Override
public
int
getMaxLength
(
Object
o
)
{
return
getType
(
o
).
getMaxLength
(
o
);
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
o
)
{
getType
(
o
).
write
(
buff
,
o
);
}
@Override
public
final
Object
read
(
ByteBuffer
buff
)
{
throw
new
RuntimeException
();
}
AutoDetectDataType
getType
(
Object
o
)
{
return
base
.
switchType
(
o
);
}
abstract
Object
read
(
ByteBuffer
buff
,
int
tag
);
@Override
public
String
asString
()
{
return
"o"
+
typeId
;
}
}
/**
* The type for boolean true and false.
*/
class
BooleanType
extends
AutoDetectDataType
{
BooleanType
(
ObjectType
base
)
{
super
(
base
,
TYPE_BOOLEAN
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
Boolean
&&
bObj
instanceof
Boolean
)
{
Boolean
a
=
(
Boolean
)
aObj
;
Boolean
b
=
(
Boolean
)
bObj
;
return
a
.
compareTo
(
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
return
obj
instanceof
Boolean
?
0
:
super
.
getMemory
(
obj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
return
obj
instanceof
Boolean
?
1
:
super
.
getMaxLength
(
obj
);
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
Boolean
)
{
int
tag
=
((
Boolean
)
obj
)
?
TAG_BOOLEAN_TRUE
:
TYPE_BOOLEAN
;
buff
.
put
((
byte
)
tag
);
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
return
tag
==
TYPE_BOOLEAN
?
Boolean
.
FALSE
:
Boolean
.
TRUE
;
}
}
/**
* The type for byte objects.
*/
class
ByteType
extends
AutoDetectDataType
{
ByteType
(
ObjectType
base
)
{
super
(
base
,
TYPE_BYTE
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
Byte
&&
bObj
instanceof
Byte
)
{
Byte
a
=
(
Byte
)
aObj
;
Byte
b
=
(
Byte
)
bObj
;
return
a
.
compareTo
(
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
return
obj
instanceof
Byte
?
0
:
super
.
getMemory
(
obj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
return
obj
instanceof
Byte
?
2
:
super
.
getMaxLength
(
obj
);
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
Byte
)
{
buff
.
put
((
byte
)
TYPE_BYTE
);
buff
.
put
(((
Byte
)
obj
).
byteValue
());
}
else
{
super
.
write
(
buff
,
obj
);
}
}
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
return
Byte
.
valueOf
(
buff
.
get
());
}
}
/**
* The type for character objects.
*/
class
CharacterType
extends
AutoDetectDataType
{
CharacterType
(
ObjectType
base
)
{
super
(
base
,
TYPE_CHARACTER
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
Character
&&
bObj
instanceof
Character
)
{
Character
a
=
(
Character
)
aObj
;
Character
b
=
(
Character
)
bObj
;
return
a
.
compareTo
(
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
return
obj
instanceof
Character
?
24
:
super
.
getMemory
(
obj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
return
obj
instanceof
Character
?
3
:
super
.
getMaxLength
(
obj
);
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
Character
)
{
buff
.
put
((
byte
)
TYPE_CHARACTER
);
buff
.
putChar
(((
Character
)
obj
).
charValue
());
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
return
Character
.
valueOf
(
buff
.
getChar
());
}
}
/**
* The type for short objects.
*/
class
ShortType
extends
AutoDetectDataType
{
ShortType
(
ObjectType
base
)
{
super
(
base
,
TYPE_SHORT
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
Short
&&
bObj
instanceof
Short
)
{
Short
a
=
(
Short
)
aObj
;
Short
b
=
(
Short
)
bObj
;
return
a
.
compareTo
(
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
return
obj
instanceof
Short
?
24
:
super
.
getMemory
(
obj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
return
obj
instanceof
Short
?
3
:
super
.
getMaxLength
(
obj
);
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
Short
)
{
buff
.
put
((
byte
)
TYPE_SHORT
);
buff
.
putShort
(((
Short
)
obj
).
shortValue
());
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
return
Short
.
valueOf
(
buff
.
getShort
());
}
}
/**
* The type for integer objects.
*/
class
IntegerType
extends
AutoDetectDataType
{
IntegerType
(
ObjectType
base
)
{
super
(
base
,
TYPE_INTEGER
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
Integer
&&
bObj
instanceof
Integer
)
{
Integer
a
=
(
Integer
)
aObj
;
Integer
b
=
(
Integer
)
bObj
;
return
a
.
compareTo
(
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
return
obj
instanceof
Integer
?
24
:
super
.
getMemory
(
obj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
return
obj
instanceof
Integer
?
1
+
DataUtils
.
MAX_VAR_INT_LEN
:
super
.
getMaxLength
(
obj
);
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
Integer
)
{
int
x
=
(
Integer
)
obj
;
if
(
x
<
0
)
{
// -Integer.MIN_VALUE is smaller than 0
if
(-
x
<
0
||
-
x
>
DataUtils
.
COMPRESSED_VAR_INT_MAX
)
{
buff
.
put
((
byte
)
TAG_INTEGER_FIXED
);
buff
.
putInt
(
x
);
}
else
{
buff
.
put
((
byte
)
TAG_INTEGER_NEGATIVE
);
DataUtils
.
writeVarInt
(
buff
,
-
x
);
}
}
else
if
(
x
<=
15
)
{
buff
.
put
((
byte
)
(
TAG_INTEGER_0_15
+
x
));
}
else
if
(
x
<=
DataUtils
.
COMPRESSED_VAR_INT_MAX
)
{
buff
.
put
((
byte
)
TYPE_INTEGER
);
DataUtils
.
writeVarInt
(
buff
,
x
);
}
else
{
buff
.
put
((
byte
)
TAG_INTEGER_FIXED
);
buff
.
putInt
(
x
);
}
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
switch
(
tag
)
{
case
TYPE_INTEGER:
return
DataUtils
.
readVarInt
(
buff
);
case
TAG_INTEGER_NEGATIVE:
return
-
DataUtils
.
readVarInt
(
buff
);
case
TAG_INTEGER_FIXED:
return
buff
.
getInt
();
}
return
tag
-
TAG_INTEGER_0_15
;
}
}
/**
* The type for long objects.
*/
class
LongType
extends
AutoDetectDataType
{
LongType
(
ObjectType
base
)
{
super
(
base
,
TYPE_LONG
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
Long
&&
bObj
instanceof
Long
)
{
Long
a
=
(
Long
)
aObj
;
Long
b
=
(
Long
)
bObj
;
return
a
.
compareTo
(
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
return
obj
instanceof
Long
?
30
:
super
.
getMemory
(
obj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
return
obj
instanceof
Long
?
1
+
DataUtils
.
MAX_VAR_LONG_LEN
:
super
.
getMaxLength
(
obj
);
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
Long
)
{
long
x
=
(
Long
)
obj
;
if
(
x
<
0
)
{
// -Long.MIN_VALUE is smaller than 0
if
(-
x
<
0
||
-
x
>
DataUtils
.
COMPRESSED_VAR_LONG_MAX
)
{
buff
.
put
((
byte
)
TAG_LONG_FIXED
);
buff
.
putLong
(
x
);
}
else
{
buff
.
put
((
byte
)
TAG_LONG_NEGATIVE
);
DataUtils
.
writeVarLong
(
buff
,
-
x
);
}
}
else
if
(
x
<=
7
)
{
buff
.
put
((
byte
)
(
TAG_LONG_0_7
+
x
));
}
else
if
(
x
<=
DataUtils
.
COMPRESSED_VAR_LONG_MAX
)
{
buff
.
put
((
byte
)
TYPE_LONG
);
DataUtils
.
writeVarLong
(
buff
,
x
);
}
else
{
buff
.
put
((
byte
)
TAG_LONG_FIXED
);
buff
.
putLong
(
x
);
}
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
switch
(
tag
)
{
case
TYPE_LONG:
return
DataUtils
.
readVarLong
(
buff
);
case
TAG_LONG_NEGATIVE:
return
-
DataUtils
.
readVarLong
(
buff
);
case
TAG_LONG_FIXED:
return
buff
.
getLong
();
}
return
Long
.
valueOf
(
tag
-
TAG_LONG_0_7
);
}
}
/**
* The type for float objects.
*/
class
FloatType
extends
AutoDetectDataType
{
FloatType
(
ObjectType
base
)
{
super
(
base
,
TYPE_FLOAT
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
Float
&&
bObj
instanceof
Float
)
{
Float
a
=
(
Float
)
aObj
;
Float
b
=
(
Float
)
bObj
;
return
a
.
compareTo
(
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
return
obj
instanceof
Float
?
24
:
super
.
getMemory
(
obj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
return
obj
instanceof
Float
?
1
+
DataUtils
.
MAX_VAR_INT_LEN
:
super
.
getMaxLength
(
obj
);
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
Float
)
{
float
x
=
(
Float
)
obj
;
int
f
=
Float
.
floatToIntBits
(
x
);
if
(
f
==
ObjectType
.
FLOAT_ZERO_BITS
)
{
buff
.
put
((
byte
)
TAG_FLOAT_0
);
}
else
if
(
f
==
ObjectType
.
FLOAT_ONE_BITS
)
{
buff
.
put
((
byte
)
TAG_FLOAT_1
);
}
else
{
int
value
=
Integer
.
reverse
(
f
);
if
(
value
>=
0
&&
value
<=
DataUtils
.
COMPRESSED_VAR_INT_MAX
)
{
buff
.
put
((
byte
)
TYPE_FLOAT
);
DataUtils
.
writeVarInt
(
buff
,
value
);
}
else
{
buff
.
put
((
byte
)
TAG_FLOAT_FIXED
);
buff
.
putFloat
(
x
);
}
}
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
switch
(
tag
)
{
case
TAG_FLOAT_0:
return
0
f
;
case
TAG_FLOAT_1:
return
1
f
;
case
TAG_FLOAT_FIXED:
return
buff
.
getFloat
();
}
return
Float
.
intBitsToFloat
(
Integer
.
reverse
(
DataUtils
.
readVarInt
(
buff
)));
}
}
/**
* The type for double objects.
*/
class
DoubleType
extends
AutoDetectDataType
{
DoubleType
(
ObjectType
base
)
{
super
(
base
,
TYPE_DOUBLE
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
Double
&&
bObj
instanceof
Double
)
{
Double
a
=
(
Double
)
aObj
;
Double
b
=
(
Double
)
bObj
;
return
a
.
compareTo
(
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
return
obj
instanceof
Double
?
30
:
super
.
getMemory
(
obj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
return
obj
instanceof
Double
?
1
+
DataUtils
.
MAX_VAR_LONG_LEN
:
super
.
getMaxLength
(
obj
);
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
Double
)
{
double
x
=
(
Double
)
obj
;
long
d
=
Double
.
doubleToLongBits
(
x
);
if
(
d
==
ObjectType
.
DOUBLE_ZERO_BITS
)
{
buff
.
put
((
byte
)
TAG_DOUBLE_0
);
}
else
if
(
d
==
ObjectType
.
DOUBLE_ONE_BITS
)
{
buff
.
put
((
byte
)
TAG_DOUBLE_1
);
}
else
{
long
value
=
Long
.
reverse
(
d
);
if
(
value
>=
0
&&
value
<=
DataUtils
.
COMPRESSED_VAR_LONG_MAX
)
{
buff
.
put
((
byte
)
TYPE_DOUBLE
);
DataUtils
.
writeVarLong
(
buff
,
value
);
}
else
{
buff
.
put
((
byte
)
TAG_DOUBLE_FIXED
);
buff
.
putDouble
(
x
);
}
}
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
switch
(
tag
)
{
case
TAG_DOUBLE_0:
return
0
d
;
case
TAG_DOUBLE_1:
return
1
d
;
case
TAG_DOUBLE_FIXED:
return
buff
.
getDouble
();
}
return
Double
.
longBitsToDouble
(
Long
.
reverse
(
DataUtils
.
readVarLong
(
buff
)));
}
}
/**
* The type for BigInteger objects.
*/
class
BigIntegerType
extends
AutoDetectDataType
{
BigIntegerType
(
ObjectType
base
)
{
super
(
base
,
TYPE_BIG_INTEGER
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
BigInteger
&&
bObj
instanceof
BigInteger
)
{
BigInteger
a
=
(
BigInteger
)
aObj
;
BigInteger
b
=
(
BigInteger
)
bObj
;
return
a
.
compareTo
(
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
return
obj
instanceof
BigInteger
?
100
:
super
.
getMemory
(
obj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
if
(!(
obj
instanceof
BigInteger
))
{
return
super
.
getMaxLength
(
obj
);
}
BigInteger
x
=
(
BigInteger
)
obj
;
if
(
BigInteger
.
ZERO
.
equals
(
x
)
||
BigInteger
.
ONE
.
equals
(
x
))
{
return
1
;
}
int
bits
=
x
.
bitLength
();
if
(
bits
<=
63
)
{
return
1
+
DataUtils
.
MAX_VAR_LONG_LEN
;
}
byte
[]
bytes
=
x
.
toByteArray
();
return
1
+
DataUtils
.
MAX_VAR_INT_LEN
+
bytes
.
length
;
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
BigInteger
)
{
BigInteger
x
=
(
BigInteger
)
obj
;
if
(
BigInteger
.
ZERO
.
equals
(
x
))
{
buff
.
put
((
byte
)
TAG_BIG_INTEGER_0
);
}
else
if
(
BigInteger
.
ONE
.
equals
(
x
))
{
buff
.
put
((
byte
)
TAG_BIG_INTEGER_1
);
}
else
{
int
bits
=
x
.
bitLength
();
if
(
bits
<=
63
)
{
buff
.
put
((
byte
)
TAG_BIG_INTEGER_SMALL
);
DataUtils
.
writeVarLong
(
buff
,
x
.
longValue
());
}
else
{
buff
.
put
((
byte
)
TYPE_BIG_INTEGER
);
byte
[]
bytes
=
x
.
toByteArray
();
DataUtils
.
writeVarInt
(
buff
,
bytes
.
length
);
buff
.
put
(
bytes
);
}
}
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
switch
(
tag
)
{
case
TAG_BIG_INTEGER_0:
return
BigInteger
.
ZERO
;
case
TAG_BIG_INTEGER_1:
return
BigInteger
.
ONE
;
case
TAG_BIG_INTEGER_SMALL:
return
BigInteger
.
valueOf
(
DataUtils
.
readVarLong
(
buff
));
}
int
len
=
DataUtils
.
readVarInt
(
buff
);
byte
[]
bytes
=
Utils
.
newBytes
(
len
);
buff
.
get
(
bytes
);
return
new
BigInteger
(
bytes
);
}
}
/**
* The type for BigDecimal objects.
*/
class
BigDecimalType
extends
AutoDetectDataType
{
BigDecimalType
(
ObjectType
base
)
{
super
(
base
,
TYPE_BIG_DECIMAL
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
BigDecimal
&&
bObj
instanceof
BigDecimal
)
{
BigDecimal
a
=
(
BigDecimal
)
aObj
;
BigDecimal
b
=
(
BigDecimal
)
bObj
;
return
a
.
compareTo
(
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
return
obj
instanceof
BigDecimal
?
150
:
super
.
getMemory
(
obj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
if
(!(
obj
instanceof
BigDecimal
))
{
return
super
.
getMaxLength
(
obj
);
}
BigDecimal
x
=
(
BigDecimal
)
obj
;
if
(
BigDecimal
.
ZERO
.
equals
(
x
)
||
BigDecimal
.
ONE
.
equals
(
x
))
{
return
1
;
}
int
scale
=
x
.
scale
();
BigInteger
b
=
x
.
unscaledValue
();
int
bits
=
b
.
bitLength
();
if
(
bits
<=
63
)
{
if
(
scale
==
0
)
{
return
1
+
DataUtils
.
MAX_VAR_LONG_LEN
;
}
return
1
+
DataUtils
.
MAX_VAR_INT_LEN
+
DataUtils
.
MAX_VAR_LONG_LEN
;
}
byte
[]
bytes
=
b
.
toByteArray
();
return
1
+
DataUtils
.
MAX_VAR_INT_LEN
+
DataUtils
.
MAX_VAR_INT_LEN
+
bytes
.
length
;
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
BigDecimal
)
{
BigDecimal
x
=
(
BigDecimal
)
obj
;
if
(
BigDecimal
.
ZERO
.
equals
(
x
))
{
buff
.
put
((
byte
)
TAG_BIG_DECIMAL_0
);
}
else
if
(
BigDecimal
.
ONE
.
equals
(
x
))
{
buff
.
put
((
byte
)
TAG_BIG_DECIMAL_1
);
}
else
{
int
scale
=
x
.
scale
();
BigInteger
b
=
x
.
unscaledValue
();
int
bits
=
b
.
bitLength
();
if
(
bits
<
64
)
{
if
(
scale
==
0
)
{
buff
.
put
((
byte
)
TAG_BIG_DECIMAL_SMALL
);
}
else
{
buff
.
put
((
byte
)
TAG_BIG_DECIMAL_SMALL_SCALED
);
DataUtils
.
writeVarInt
(
buff
,
scale
);
}
DataUtils
.
writeVarLong
(
buff
,
b
.
longValue
());
}
else
{
buff
.
put
((
byte
)
TYPE_BIG_DECIMAL
);
DataUtils
.
writeVarInt
(
buff
,
scale
);
byte
[]
bytes
=
b
.
toByteArray
();
DataUtils
.
writeVarInt
(
buff
,
bytes
.
length
);
buff
.
put
(
bytes
);
}
}
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
switch
(
tag
)
{
case
TAG_BIG_DECIMAL_0:
return
BigDecimal
.
ZERO
;
case
TAG_BIG_DECIMAL_1:
return
BigDecimal
.
ONE
;
case
TAG_BIG_DECIMAL_SMALL:
return
BigDecimal
.
valueOf
(
DataUtils
.
readVarLong
(
buff
));
case
TAG_BIG_DECIMAL_SMALL_SCALED:
int
scale
=
DataUtils
.
readVarInt
(
buff
);
return
BigDecimal
.
valueOf
(
DataUtils
.
readVarLong
(
buff
),
scale
);
}
int
scale
=
DataUtils
.
readVarInt
(
buff
);
int
len
=
DataUtils
.
readVarInt
(
buff
);
byte
[]
bytes
=
Utils
.
newBytes
(
len
);
buff
.
get
(
bytes
);
BigInteger
b
=
new
BigInteger
(
bytes
);
return
new
BigDecimal
(
b
,
scale
);
}
}
/**
* The type for string objects.
*/
class
StringType
extends
AutoDetectDataType
{
StringType
(
ObjectType
base
)
{
super
(
base
,
TYPE_STRING
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
if
(!(
obj
instanceof
String
))
{
return
super
.
getMemory
(
obj
);
}
return
MVStore
.
STRING_TYPE
.
getMemory
(
obj
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
String
&&
bObj
instanceof
String
)
{
return
MVStore
.
STRING_TYPE
.
compare
(
aObj
,
bObj
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
if
(!(
obj
instanceof
String
))
{
return
super
.
getMaxLength
(
obj
);
}
return
1
+
MVStore
.
STRING_TYPE
.
getMaxLength
(
obj
);
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(!(
obj
instanceof
String
))
{
super
.
write
(
buff
,
obj
);
return
;
}
String
s
=
(
String
)
obj
;
int
len
=
s
.
length
();
if
(
len
<=
15
)
{
buff
.
put
((
byte
)
(
TAG_STRING_0_15
+
len
));
}
else
{
buff
.
put
((
byte
)
TYPE_STRING
);
DataUtils
.
writeVarInt
(
buff
,
len
);
}
DataUtils
.
writeStringData
(
buff
,
s
,
len
);
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
int
len
;
if
(
tag
==
TYPE_STRING
)
{
len
=
DataUtils
.
readVarInt
(
buff
);
}
else
{
len
=
tag
-
TAG_STRING_0_15
;
}
return
DataUtils
.
readString
(
buff
,
len
);
}
}
/**
* The type for UUID objects.
*/
class
UUIDType
extends
AutoDetectDataType
{
UUIDType
(
ObjectType
base
)
{
super
(
base
,
TYPE_UUID
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
return
obj
instanceof
UUID
?
40
:
super
.
getMemory
(
obj
);
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
UUID
&&
bObj
instanceof
UUID
)
{
UUID
a
=
(
UUID
)
aObj
;
UUID
b
=
(
UUID
)
bObj
;
return
a
.
compareTo
(
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
if
(!(
obj
instanceof
UUID
))
{
return
super
.
getMaxLength
(
obj
);
}
return
17
;
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(!(
obj
instanceof
UUID
))
{
super
.
write
(
buff
,
obj
);
return
;
}
buff
.
put
((
byte
)
TYPE_UUID
);
UUID
a
=
(
UUID
)
obj
;
buff
.
putLong
(
a
.
getMostSignificantBits
());
buff
.
putLong
(
a
.
getLeastSignificantBits
());
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
long
a
=
buff
.
getLong
(),
b
=
buff
.
getLong
();
return
new
UUID
(
a
,
b
);
}
}
/**
* The type for byte arrays.
*/
class
ByteArrayType
extends
AutoDetectDataType
{
ByteArrayType
(
ObjectType
base
)
{
super
(
base
,
TYPE_BYTE_ARRAY
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
if
(!(
obj
instanceof
byte
[]))
{
return
super
.
getMemory
(
obj
);
}
return
24
+
((
byte
[])
obj
).
length
;
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
byte
[]
&&
bObj
instanceof
byte
[])
{
byte
[]
a
=
(
byte
[])
aObj
;
byte
[]
b
=
(
byte
[])
bObj
;
return
Utils
.
compareNotNull
(
a
,
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
if
(!(
obj
instanceof
byte
[]))
{
return
super
.
getMaxLength
(
obj
);
}
return
1
+
DataUtils
.
MAX_VAR_INT_LEN
+
((
byte
[])
obj
).
length
;
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
byte
[])
{
byte
[]
data
=
(
byte
[])
obj
;
int
len
=
data
.
length
;
if
(
len
<=
15
)
{
buff
.
put
((
byte
)
(
TAG_BYTE_ARRAY_0_15
+
len
));
}
else
{
buff
.
put
((
byte
)
TYPE_BYTE_ARRAY
);
DataUtils
.
writeVarInt
(
buff
,
data
.
length
);
}
buff
.
put
(
data
);
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
int
len
;
if
(
tag
==
TYPE_BYTE_ARRAY
)
{
len
=
DataUtils
.
readVarInt
(
buff
);
}
else
{
len
=
tag
-
TAG_BYTE_ARRAY_0_15
;
}
byte
[]
data
=
new
byte
[
len
];
buff
.
get
(
data
);
return
data
;
}
}
/**
* The type for char arrays.
*/
class
CharArrayType
extends
AutoDetectDataType
{
CharArrayType
(
ObjectType
base
)
{
super
(
base
,
TYPE_CHAR_ARRAY
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
if
(!(
obj
instanceof
char
[]))
{
return
super
.
getMemory
(
obj
);
}
return
24
+
2
*
((
char
[])
obj
).
length
;
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
char
[]
&&
bObj
instanceof
char
[])
{
char
[]
a
=
(
char
[])
aObj
;
char
[]
b
=
(
char
[])
bObj
;
return
compareNotNull
(
a
,
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
if
(!(
obj
instanceof
char
[]))
{
return
super
.
getMaxLength
(
obj
);
}
return
1
+
DataUtils
.
MAX_VAR_INT_LEN
+
2
*
((
char
[])
obj
).
length
;
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
char
[])
{
buff
.
put
((
byte
)
TYPE_CHAR_ARRAY
);
char
[]
data
=
(
char
[])
obj
;
int
len
=
data
.
length
;
DataUtils
.
writeVarInt
(
buff
,
len
);
buff
.
asCharBuffer
().
put
(
data
);
buff
.
position
(
buff
.
position
()
+
len
+
len
);
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
int
len
=
DataUtils
.
readVarInt
(
buff
);
char
[]
data
=
new
char
[
len
];
buff
.
asCharBuffer
().
get
(
data
);
buff
.
position
(
buff
.
position
()
+
len
+
len
);
return
data
;
}
}
/**
* The type for char arrays.
*/
class
IntArrayType
extends
AutoDetectDataType
{
IntArrayType
(
ObjectType
base
)
{
super
(
base
,
TYPE_INT_ARRAY
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
if
(!(
obj
instanceof
int
[]))
{
return
super
.
getMemory
(
obj
);
}
return
24
+
4
*
((
int
[])
obj
).
length
;
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
int
[]
&&
bObj
instanceof
int
[])
{
int
[]
a
=
(
int
[])
aObj
;
int
[]
b
=
(
int
[])
bObj
;
return
compareNotNull
(
a
,
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
if
(!(
obj
instanceof
int
[]))
{
return
super
.
getMaxLength
(
obj
);
}
return
1
+
DataUtils
.
MAX_VAR_INT_LEN
+
4
*
((
int
[])
obj
).
length
;
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
int
[])
{
buff
.
put
((
byte
)
TYPE_INT_ARRAY
);
int
[]
data
=
(
int
[])
obj
;
int
len
=
data
.
length
;
DataUtils
.
writeVarInt
(
buff
,
len
);
buff
.
asIntBuffer
().
put
(
data
);
buff
.
position
(
buff
.
position
()
+
4
*
len
);
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
int
len
=
DataUtils
.
readVarInt
(
buff
);
int
[]
data
=
new
int
[
len
];
buff
.
asIntBuffer
().
get
(
data
);
buff
.
position
(
buff
.
position
()
+
4
*
len
);
return
data
;
}
}
/**
* The type for char arrays.
*/
class
LongArrayType
extends
AutoDetectDataType
{
LongArrayType
(
ObjectType
base
)
{
super
(
base
,
TYPE_LONG_ARRAY
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
if
(!(
obj
instanceof
long
[]))
{
return
super
.
getMemory
(
obj
);
}
return
24
+
8
*
((
long
[])
obj
).
length
;
}
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
instanceof
long
[]
&&
bObj
instanceof
long
[])
{
long
[]
a
=
(
long
[])
aObj
;
long
[]
b
=
(
long
[])
bObj
;
return
compareNotNull
(
a
,
b
);
}
return
super
.
compare
(
aObj
,
bObj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
if
(!(
obj
instanceof
long
[]))
{
return
super
.
getMaxLength
(
obj
);
}
return
1
+
DataUtils
.
MAX_VAR_INT_LEN
+
8
*
((
long
[])
obj
).
length
;
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
if
(
obj
instanceof
long
[])
{
buff
.
put
((
byte
)
TYPE_LONG_ARRAY
);
long
[]
data
=
(
long
[])
obj
;
int
len
=
data
.
length
;
DataUtils
.
writeVarInt
(
buff
,
len
);
buff
.
asLongBuffer
().
put
(
data
);
buff
.
position
(
buff
.
position
()
+
8
*
len
);
}
else
{
super
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
int
len
=
DataUtils
.
readVarInt
(
buff
);
long
[]
data
=
new
long
[
len
];
buff
.
asLongBuffer
().
get
(
data
);
buff
.
position
(
buff
.
position
()
+
8
*
len
);
return
data
;
}
}
/**
* The type for serialized objects.
*/
class
SerializedObjectType
extends
AutoDetectDataType
{
SerializedObjectType
(
ObjectType
base
)
{
super
(
base
,
TYPE_SERIALIZED_OBJECT
);
}
@SuppressWarnings
(
"unchecked"
)
@Override
public
int
compare
(
Object
aObj
,
Object
bObj
)
{
if
(
aObj
==
bObj
)
{
return
0
;
}
DataType
ta
=
getType
(
aObj
);
DataType
tb
=
getType
(
bObj
);
if
(
ta
!=
this
&&
ta
==
tb
)
{
return
ta
.
compare
(
aObj
,
bObj
);
}
// TODO ensure comparable type (both may be comparable but not
// with each other)
if
(
aObj
instanceof
Comparable
)
{
if
(
aObj
.
getClass
().
isAssignableFrom
(
bObj
.
getClass
()))
{
return
((
Comparable
<
Object
>)
aObj
).
compareTo
(
bObj
);
}
}
if
(
bObj
instanceof
Comparable
)
{
if
(
bObj
.
getClass
().
isAssignableFrom
(
aObj
.
getClass
()))
{
return
-((
Comparable
<
Object
>)
bObj
).
compareTo
(
aObj
);
}
}
byte
[]
a
=
Utils
.
serialize
(
aObj
);
byte
[]
b
=
Utils
.
serialize
(
bObj
);
return
Utils
.
compareNotNull
(
a
,
b
);
}
@Override
public
int
getMemory
(
Object
obj
)
{
DataType
t
=
getType
(
obj
);
if
(
t
==
this
)
{
return
1000
;
}
return
t
.
getMemory
(
obj
);
}
@Override
public
int
getMaxLength
(
Object
obj
)
{
DataType
t
=
getType
(
obj
);
if
(
t
==
this
)
{
byte
[]
data
=
Utils
.
serialize
(
obj
);
return
1
+
DataUtils
.
MAX_VAR_INT_LEN
+
data
.
length
;
}
return
t
.
getMaxLength
(
obj
);
}
@Override
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
DataType
t
=
getType
(
obj
);
if
(
t
==
this
)
{
buff
.
put
((
byte
)
TYPE_SERIALIZED_OBJECT
);
byte
[]
data
=
Utils
.
serialize
(
obj
);
DataUtils
.
writeVarInt
(
buff
,
data
.
length
);
buff
.
put
(
data
);
}
else
{
t
.
write
(
buff
,
obj
);
}
}
@Override
public
Object
read
(
ByteBuffer
buff
,
int
tag
)
{
int
len
=
DataUtils
.
readVarInt
(
buff
);
byte
[]
data
=
new
byte
[
len
];
buff
.
get
(
data
);
return
Utils
.
deserialize
(
data
);
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestDataUtils.java
浏览文件 @
e949b40f
...
@@ -26,6 +26,7 @@ public class TestDataUtils extends TestBase {
...
@@ -26,6 +26,7 @@ public class TestDataUtils extends TestBase {
public
void
test
()
throws
Exception
{
public
void
test
()
throws
Exception
{
testMap
();
testMap
();
testMaxShortVarIntVarLong
();
testVarIntVarLong
();
testVarIntVarLong
();
testCheckValue
();
testCheckValue
();
testPagePos
();
testPagePos
();
...
@@ -50,6 +51,22 @@ public class TestDataUtils extends TestBase {
...
@@ -50,6 +51,22 @@ public class TestDataUtils extends TestBase {
assertEquals
(
"\"test\""
,
m
.
get
(
"d"
));
assertEquals
(
"\"test\""
,
m
.
get
(
"d"
));
}
}
private
void
testMaxShortVarIntVarLong
()
{
ByteBuffer
buff
=
ByteBuffer
.
allocate
(
100
);
DataUtils
.
writeVarInt
(
buff
,
DataUtils
.
COMPRESSED_VAR_INT_MAX
);
assertEquals
(
3
,
buff
.
position
());
buff
.
rewind
();
DataUtils
.
writeVarInt
(
buff
,
DataUtils
.
COMPRESSED_VAR_INT_MAX
+
1
);
assertEquals
(
4
,
buff
.
position
());
buff
.
rewind
();
DataUtils
.
writeVarLong
(
buff
,
DataUtils
.
COMPRESSED_VAR_LONG_MAX
);
assertEquals
(
7
,
buff
.
position
());
buff
.
rewind
();
DataUtils
.
writeVarLong
(
buff
,
DataUtils
.
COMPRESSED_VAR_LONG_MAX
+
1
);
assertEquals
(
8
,
buff
.
position
());
buff
.
rewind
();
}
private
void
testVarIntVarLong
()
{
private
void
testVarIntVarLong
()
{
ByteBuffer
buff
=
ByteBuffer
.
allocate
(
100
);
ByteBuffer
buff
=
ByteBuffer
.
allocate
(
100
);
for
(
long
x
=
0
;
x
<
1000
;
x
++)
{
for
(
long
x
=
0
;
x
<
1000
;
x
++)
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMVStore.java
浏览文件 @
e949b40f
...
@@ -12,7 +12,6 @@ import java.util.Random;
...
@@ -12,7 +12,6 @@ import java.util.Random;
import
java.util.TreeMap
;
import
java.util.TreeMap
;
import
org.h2.dev.store.btree.MVMap
;
import
org.h2.dev.store.btree.MVMap
;
import
org.h2.dev.store.btree.MVStore
;
import
org.h2.dev.store.btree.MVStore
;
import
org.h2.jaqu.bytecode.Null
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.test.TestBase
;
import
org.h2.test.TestBase
;
import
org.h2.util.New
;
import
org.h2.util.New
;
...
@@ -32,6 +31,7 @@ public class TestMVStore extends TestBase {
...
@@ -32,6 +31,7 @@ public class TestMVStore extends TestBase {
}
}
public
void
test
()
throws
InterruptedException
{
public
void
test
()
throws
InterruptedException
{
testObjects
();
testExample
();
testExample
();
testIterateOverChanges
();
testIterateOverChanges
();
testOpenStoreCloseLoop
();
testOpenStoreCloseLoop
();
...
@@ -52,8 +52,31 @@ public class TestMVStore extends TestBase {
...
@@ -52,8 +52,31 @@ public class TestMVStore extends TestBase {
testSimple
();
testSimple
();
}
}
private
void
testObjects
()
{
String
fileName
=
getBaseDir
()
+
"/testObjects.h3"
;
FileUtils
.
delete
(
fileName
);
MVStore
s
;
Map
<
Object
,
Object
>
map
;
s
=
MVStore
.
open
(
fileName
,
new
TestMapFactory
());
map
=
s
.
openMap
(
"test"
);
map
.
put
(
1
,
"Hello"
);
map
.
put
(
"2"
,
200
);
map
.
put
(
new
Object
[
1
],
new
Object
[]{
1
,
"2"
});
s
.
store
();
s
.
close
();
s
=
MVStore
.
open
(
fileName
,
new
TestMapFactory
());
map
=
s
.
openMap
(
"test"
);
assertEquals
(
"Hello"
,
map
.
get
(
1
).
toString
());
assertEquals
(
200
,
((
Integer
)
map
.
get
(
"2"
)).
intValue
());
Object
[]
x
=
(
Object
[])
map
.
get
(
new
Object
[
1
]);
assertEquals
(
2
,
x
.
length
);
assertEquals
(
1
,
((
Integer
)
x
[
0
]).
intValue
());
assertEquals
(
"2"
,
(
String
)
x
[
1
]);
s
.
close
();
}
private
void
testExample
()
{
private
void
testExample
()
{
String
fileName
=
getBaseDir
()
+
"/test
OpenClos
e.h3"
;
String
fileName
=
getBaseDir
()
+
"/test
Exampl
e.h3"
;
FileUtils
.
delete
(
fileName
);
FileUtils
.
delete
(
fileName
);
// open the store (in-memory if fileName is null)
// open the store (in-memory if fileName is null)
...
@@ -649,29 +672,34 @@ public class TestMVStore extends TestBase {
...
@@ -649,29 +672,34 @@ public class TestMVStore extends TestBase {
}
}
private
void
testKeyValueClasses
()
{
private
void
testKeyValueClasses
()
{
String
fileName
=
getBaseDir
()
+
"/testKeyValueClasses.h3"
;
MVStore
s
;
FileUtils
.
delete
(
fileName
);
s
=
MVStore
.
open
(
null
);
MVStore
s
=
openStore
(
fileName
);
s
.
openMap
(
"test"
,
String
.
class
,
String
.
class
);
MVMap
<
Integer
,
String
>
is
=
s
.
openMap
(
"intString"
,
Integer
.
class
,
String
.
class
);
is
.
put
(
1
,
"Hello"
);
MVMap
<
Integer
,
Integer
>
ii
=
s
.
openMap
(
"intInt"
,
Integer
.
class
,
Integer
.
class
);
ii
.
put
(
1
,
10
);
MVMap
<
String
,
Integer
>
si
=
s
.
openMap
(
"stringInt"
,
String
.
class
,
Integer
.
class
);
si
.
put
(
"Test"
,
10
);
MVMap
<
String
,
String
>
ss
=
s
.
openMap
(
"stringString"
,
String
.
class
,
String
.
class
);
ss
.
put
(
"Hello"
,
"World"
);
try
{
try
{
s
.
openMap
(
"
invalid"
,
Null
.
class
,
Integer
.
class
);
s
.
openMap
(
"
unsupportedKey"
,
ArrayList
.
class
,
String
.
class
);
fail
();
fail
();
}
catch
(
RuntimeException
e
)
{
}
catch
(
RuntimeException
e
)
{
// expected
// expected
}
}
try
{
try
{
s
.
openMap
(
"
invalid"
,
Integer
.
class
,
Null
.
class
);
s
.
openMap
(
"
unsupportedValue"
,
String
.
class
,
ArrayList
.
class
);
fail
();
fail
();
}
catch
(
RuntimeException
e
)
{
}
catch
(
RuntimeException
e
)
{
// expected
// expected
}
}
s
.
close
();
String
fileName
=
getBaseDir
()
+
"/testKeyValueClasses.h3"
;
FileUtils
.
delete
(
fileName
);
s
=
openStore
(
fileName
);
MVMap
<
Integer
,
String
>
is
=
s
.
openMap
(
"intString"
,
Integer
.
class
,
String
.
class
);
is
.
put
(
1
,
"Hello"
);
MVMap
<
Integer
,
Integer
>
ii
=
s
.
openMap
(
"intInt"
,
Integer
.
class
,
Integer
.
class
);
ii
.
put
(
1
,
10
);
MVMap
<
String
,
Integer
>
si
=
s
.
openMap
(
"stringInt"
,
String
.
class
,
Integer
.
class
);
si
.
put
(
"Test"
,
10
);
MVMap
<
String
,
String
>
ss
=
s
.
openMap
(
"stringString"
,
String
.
class
,
String
.
class
);
ss
.
put
(
"Hello"
,
"World"
);
s
.
store
();
s
.
store
();
s
.
close
();
s
.
close
();
s
=
openStore
(
fileName
);
s
=
openStore
(
fileName
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestMapFactory.java
浏览文件 @
e949b40f
...
@@ -41,6 +41,8 @@ public class TestMapFactory implements MapFactory {
...
@@ -41,6 +41,8 @@ public class TestMapFactory implements MapFactory {
return
RowType
.
fromString
(
s
,
this
);
return
RowType
.
fromString
(
s
,
this
);
case
's'
:
case
's'
:
return
SpatialType
.
fromString
(
s
);
return
SpatialType
.
fromString
(
s
);
case
'o'
:
return
new
ObjectType
();
}
}
throw
new
RuntimeException
(
"Unknown data type "
+
s
);
throw
new
RuntimeException
(
"Unknown data type "
+
s
);
}
}
...
@@ -49,6 +51,8 @@ public class TestMapFactory implements MapFactory {
...
@@ -49,6 +51,8 @@ public class TestMapFactory implements MapFactory {
public
String
getDataType
(
Class
<?>
objectClass
)
{
public
String
getDataType
(
Class
<?>
objectClass
)
{
if
(
objectClass
==
Integer
.
class
)
{
if
(
objectClass
==
Integer
.
class
)
{
return
"i"
;
return
"i"
;
}
else
if
(
Object
.
class
==
Object
.
class
)
{
return
"o"
;
}
}
throw
new
RuntimeException
(
"Unsupported object class "
+
objectClass
.
toString
());
throw
new
RuntimeException
(
"Unsupported object class "
+
objectClass
.
toString
());
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/store/TestObjectType.java
0 → 100644
浏览文件 @
e949b40f
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
test
.
store
;
import
java.math.BigDecimal
;
import
java.math.BigInteger
;
import
java.nio.ByteBuffer
;
import
java.sql.Timestamp
;
import
java.util.Arrays
;
import
java.util.Random
;
import
java.util.UUID
;
import
org.h2.test.TestBase
;
/**
* Test the ObjectType class.
*/
public
class
TestObjectType
extends
TestBase
{
/**
* Run just this test.
*
* @param a ignored
*/
public
static
void
main
(
String
...
a
)
throws
Exception
{
TestBase
.
createCaller
().
init
().
test
();
}
@Override
public
void
test
()
{
testCommonValues
();
}
private
void
testCommonValues
()
{
BigInteger
largeBigInt
=
BigInteger
.
probablePrime
(
200
,
new
Random
(
1
));
ObjectType
ot
=
new
ObjectType
();
assertEquals
(
"o"
,
ot
.
asString
());
Object
[]
array
=
{
false
,
true
,
Byte
.
MIN_VALUE
,
(
byte
)
-
1
,
(
byte
)
0
,
(
byte
)
1
,
Byte
.
MAX_VALUE
,
Short
.
MIN_VALUE
,
(
short
)
-
1
,
(
short
)
0
,
(
short
)
1
,
Short
.
MAX_VALUE
,
Integer
.
MIN_VALUE
,
Integer
.
MIN_VALUE
+
1
,
-
1000
,
-
100
,
-
1
,
0
,
1
,
2
,
14
,
15
,
16
,
17
,
100
,
Integer
.
MAX_VALUE
-
1
,
Integer
.
MAX_VALUE
,
Long
.
MIN_VALUE
,
Long
.
MIN_VALUE
+
1
,
-
1000L
,
-
1L
,
0L
,
1L
,
2L
,
14L
,
15L
,
16L
,
17L
,
100L
,
Long
.
MAX_VALUE
-
1
,
Long
.
MAX_VALUE
,
largeBigInt
.
negate
(),
BigInteger
.
valueOf
(-
1
),
BigInteger
.
ZERO
,
BigInteger
.
ONE
,
BigInteger
.
TEN
,
largeBigInt
,
Float
.
NEGATIVE_INFINITY
,
-
Float
.
MAX_VALUE
,
-
1
f
,
-
0
f
,
0
f
,
Float
.
MIN_VALUE
,
1
f
,
Float
.
MAX_VALUE
,
Float
.
POSITIVE_INFINITY
,
Float
.
NaN
,
Double
.
NEGATIVE_INFINITY
,
-
Double
.
MAX_VALUE
,
-
1
d
,
-
0
d
,
0
d
,
Double
.
MIN_VALUE
,
1
d
,
Double
.
MAX_VALUE
,
Double
.
POSITIVE_INFINITY
,
Double
.
NaN
,
BigDecimal
.
valueOf
(
Double
.
MAX_VALUE
).
negate
(),
new
BigDecimal
(
largeBigInt
).
negate
(),
BigDecimal
.
valueOf
(-
100.0
),
BigDecimal
.
ZERO
,
BigDecimal
.
ONE
,
BigDecimal
.
TEN
,
BigDecimal
.
valueOf
(
Long
.
MAX_VALUE
),
new
BigDecimal
(
largeBigInt
),
BigDecimal
.
valueOf
(
Double
.
MAX_VALUE
),
Character
.
MIN_VALUE
,
'0'
,
'a'
,
Character
.
MAX_VALUE
,
""
,
" "
,
" "
,
"123456789012345"
,
"1234567890123456"
,
new
String
(
new
char
[
100
]).
replace
((
char
)
0
,
'x'
),
new
String
(
new
char
[
100000
]).
replace
((
char
)
0
,
'x'
),
"y"
,
"\u1234"
,
"\u2345"
,
"\u6789"
,
"\uffff"
,
new
UUID
(
Long
.
MIN_VALUE
,
Long
.
MIN_VALUE
),
new
UUID
(
Long
.
MIN_VALUE
,
0
),
new
UUID
(
0
,
0
),
new
UUID
(
Long
.
MAX_VALUE
,
Long
.
MAX_VALUE
),
new
byte
[
0
],
new
byte
[
1
],
new
byte
[
15
],
new
byte
[
16
],
new
byte
[
10000
],
new
byte
[]
{
(
byte
)
1
},
new
int
[
0
],
new
int
[
1
],
new
int
[
15
],
new
int
[
16
],
new
int
[
10000
],
new
int
[]
{
(
byte
)
1
},
new
long
[
0
],
new
long
[
1
],
new
long
[
15
],
new
long
[
16
],
new
long
[
10000
],
new
long
[]
{
(
byte
)
1
},
new
char
[
0
],
new
char
[
1
],
new
char
[
10000
],
new
char
[]
{
(
char
)
1
},
new
java
.
util
.
Date
(
0
),
new
java
.
util
.
Date
(
1000
),
new
Timestamp
(
2000
),
new
Timestamp
(
3000
),
new
java
.
util
.
Date
(
4000
),
new
java
.
util
.
Date
(
5000
),
new
Object
[
0
],
new
Object
[]
{
1
},
new
Object
[]
{
0.0
,
"Hello"
,
null
,
Double
.
NaN
},
new
Object
[
100
]
};
Object
otherType
=
false
;
Object
last
=
null
;
for
(
Object
x
:
array
)
{
test
(
otherType
,
x
);
if
(
last
!=
null
)
{
int
comp
=
ot
.
compare
(
x
,
last
);
if
(
comp
<=
0
)
{
ot
.
compare
(
x
,
last
);
fail
(
x
.
getClass
().
getName
()
+
": "
+
x
.
toString
()
+
" "
+
comp
);
}
assertTrue
(
x
.
toString
(),
ot
.
compare
(
last
,
x
)
<
0
);
}
if
(
last
!=
null
&&
last
.
getClass
()
!=
x
.
getClass
())
{
otherType
=
last
;
}
last
=
x
;
}
}
private
void
test
(
Object
last
,
Object
x
)
{
ObjectType
ot
=
new
ObjectType
();
// switch to the last type before every operation,
// to test switching types
ot
.
getMemory
(
last
);
assertTrue
(
ot
.
getMemory
(
x
)
>=
0
);
ot
.
getMemory
(
last
);
assertTrue
(
ot
.
getMaxLength
(
x
)
>=
1
);
ot
.
getMemory
(
last
);
assertEquals
(
0
,
ot
.
compare
(
x
,
x
));
ByteBuffer
buff
=
ByteBuffer
.
allocate
(
ot
.
getMaxLength
(
x
)
+
1
);
ot
.
getMemory
(
last
);
ot
.
write
(
buff
,
x
);
buff
.
put
((
byte
)
123
);
buff
.
flip
();
ot
.
getMemory
(
last
);
Object
y
=
ot
.
read
(
buff
);
assertEquals
(
123
,
buff
.
get
());
assertEquals
(
0
,
buff
.
remaining
());
assertEquals
(
x
.
getClass
().
getName
(),
y
.
getClass
().
getName
());
ot
.
getMemory
(
last
);
assertEquals
(
0
,
ot
.
compare
(
x
,
y
));
if
(
x
.
getClass
().
isArray
())
{
if
(
x
instanceof
byte
[])
{
assertTrue
(
Arrays
.
equals
((
byte
[])
x
,
(
byte
[])
y
));
}
else
if
(
x
instanceof
char
[])
{
assertTrue
(
Arrays
.
equals
((
char
[])
x
,
(
char
[])
y
));
}
else
if
(
x
instanceof
int
[])
{
assertTrue
(
Arrays
.
equals
((
int
[])
x
,
(
int
[])
y
));
}
else
if
(
x
instanceof
long
[])
{
assertTrue
(
Arrays
.
equals
((
long
[])
x
,
(
long
[])
y
));
}
else
{
assertTrue
(
Arrays
.
equals
((
Object
[])
x
,
(
Object
[])
y
));
}
}
else
{
assertEquals
(
x
.
hashCode
(),
y
.
hashCode
());
assertTrue
(
x
.
equals
(
y
));
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/store/btree/DataUtils.java
浏览文件 @
e949b40f
...
@@ -42,6 +42,18 @@ public class DataUtils {
...
@@ -42,6 +42,18 @@ public class DataUtils {
*/
*/
public
static
final
int
MAX_VAR_LONG_LEN
=
10
;
public
static
final
int
MAX_VAR_LONG_LEN
=
10
;
/**
* The maximum integer that needs less space when using variable size
* encoding (only 3 bytes instead of 4).
*/
public
static
final
int
COMPRESSED_VAR_INT_MAX
=
0x1fffff
;
/**
* The maximum long that needs less space when using variable size
* encoding (only 7 bytes instead of 8).
*/
public
static
final
long
COMPRESSED_VAR_LONG_MAX
=
0x1ffffffffffff
L
;
/**
/**
* Get the length of the variable size int.
* Get the length of the variable size int.
*
*
...
@@ -149,6 +161,51 @@ public class DataUtils {
...
@@ -149,6 +161,51 @@ public class DataUtils {
buff
.
put
((
byte
)
x
);
buff
.
put
((
byte
)
x
);
}
}
/**
* Write characters from a string (without the length).
*
* @param buff the target buffer
* @param s the string
* @param len the number of characters
*/
public
static
void
writeStringData
(
ByteBuffer
buff
,
String
s
,
int
len
)
{
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
int
c
=
s
.
charAt
(
i
);
if
(
c
<
0x80
)
{
buff
.
put
((
byte
)
c
);
}
else
if
(
c
>=
0x800
)
{
buff
.
put
((
byte
)
(
0xe0
|
(
c
>>
12
)));
buff
.
put
((
byte
)
(((
c
>>
6
)
&
0x3f
)));
buff
.
put
((
byte
)
(
c
&
0x3f
));
}
else
{
buff
.
put
((
byte
)
(
0xc0
|
(
c
>>
6
)));
buff
.
put
((
byte
)
(
c
&
0x3f
));
}
}
}
/**
* Read a string.
*
* @param buff the source buffer
* @param len the number of characters
* @return the value
*/
public
static
String
readString
(
ByteBuffer
buff
,
int
len
)
{
char
[]
chars
=
new
char
[
len
];
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
int
x
=
buff
.
get
()
&
0xff
;
if
(
x
<
0x80
)
{
chars
[
i
]
=
(
char
)
x
;
}
else
if
(
x
>=
0xe0
)
{
chars
[
i
]
=
(
char
)
(((
x
&
0xf
)
<<
12
)
+
((
buff
.
get
()
&
0x3f
)
<<
6
)
+
(
buff
.
get
()
&
0x3f
));
}
else
{
chars
[
i
]
=
(
char
)
(((
x
&
0x1f
)
<<
6
)
+
(
buff
.
get
()
&
0x3f
));
}
}
return
new
String
(
chars
);
}
/**
/**
* Write a variable size int.
* Write a variable size int.
*
*
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/store/btree/MVStore.java
浏览文件 @
e949b40f
...
@@ -35,7 +35,6 @@ header:
...
@@ -35,7 +35,6 @@ header:
H:3,blockSize=4096,...
H:3,blockSize=4096,...
TODO:
TODO:
- support all objects (using serialization)
- concurrent iterator (when to increment version; read on first hasNext())
- concurrent iterator (when to increment version; read on first hasNext())
- how to iterate (just) over deleted pages / entries
- how to iterate (just) over deleted pages / entries
- compact: use total max length instead of page count (liveCount)
- compact: use total max length instead of page count (liveCount)
...
@@ -60,6 +59,9 @@ TODO:
...
@@ -60,6 +59,9 @@ TODO:
- recovery: ensure data is not overwritten for 1 minute
- recovery: ensure data is not overwritten for 1 minute
- pluggable caching (specially for in-memory file systems)
- pluggable caching (specially for in-memory file systems)
- file locking
- file locking
- allocate memory Utils.newBytes
- unified exception handling
- check if locale specific string comparison can make data disappear
*/
*/
...
@@ -73,7 +75,10 @@ public class MVStore {
...
@@ -73,7 +75,10 @@ public class MVStore {
*/
*/
public
static
final
boolean
ASSERT
=
false
;
public
static
final
boolean
ASSERT
=
false
;
private
static
final
StringType
STRING_TYPE
=
new
StringType
();
/**
* A string data type.
*/
public
static
final
StringType
STRING_TYPE
=
new
StringType
();
private
final
String
fileName
;
private
final
String
fileName
;
private
final
MapFactory
mapFactory
;
private
final
MapFactory
mapFactory
;
...
@@ -169,6 +174,41 @@ public class MVStore {
...
@@ -169,6 +174,41 @@ public class MVStore {
return
(
T
)
m
;
return
(
T
)
m
;
}
}
/**
* Open a map with the previous key and value type (if the map already
* exists), or Object if not.
*
* @param <K> the key type
* @param <V> the value type
* @param name the name of the map
* @return the map
*/
public
<
K
,
V
>
MVMap
<
K
,
V
>
openMap
(
String
name
)
{
String
keyType
=
getDataType
(
Object
.
class
);
String
valueType
=
getDataType
(
Object
.
class
);
@SuppressWarnings
(
"unchecked"
)
MVMap
<
K
,
V
>
m
=
(
MVMap
<
K
,
V
>)
openMap
(
name
,
""
,
keyType
,
valueType
);
return
m
;
}
/**
* Open a map.
*
* @param <K> the key type
* @param <V> the value type
* @param name the name of the map
* @param keyClass the key class
* @param valueClass the value class
* @return the map
*/
public
<
K
,
V
>
MVMap
<
K
,
V
>
openMap
(
String
name
,
Class
<
K
>
keyClass
,
Class
<
V
>
valueClass
)
{
String
keyType
=
getDataType
(
keyClass
);
String
valueType
=
getDataType
(
valueClass
);
@SuppressWarnings
(
"unchecked"
)
MVMap
<
K
,
V
>
m
=
(
MVMap
<
K
,
V
>)
openMap
(
name
,
""
,
keyType
,
valueType
);
return
m
;
}
/**
/**
* Open a map.
* Open a map.
*
*
...
@@ -187,6 +227,7 @@ public class MVStore {
...
@@ -187,6 +227,7 @@ public class MVStore {
int
id
;
int
id
;
long
root
;
long
root
;
long
createVersion
;
long
createVersion
;
// TODO use the json formatting for map metadata
if
(
identifier
==
null
)
{
if
(
identifier
==
null
)
{
id
=
++
lastMapId
;
id
=
++
lastMapId
;
createVersion
=
currentVersion
;
createVersion
=
currentVersion
;
...
@@ -259,24 +300,6 @@ public class MVStore {
...
@@ -259,24 +300,6 @@ public class MVStore {
}
}
}
}
/**
* Open a map.
*
* @param <K> the key type
* @param <V> the value type
* @param name the name of the map
* @param keyClass the key class
* @param valueClass the value class
* @return the map
*/
public
<
K
,
V
>
MVMap
<
K
,
V
>
openMap
(
String
name
,
Class
<
K
>
keyClass
,
Class
<
V
>
valueClass
)
{
String
keyType
=
getDataType
(
keyClass
);
String
valueType
=
getDataType
(
valueClass
);
@SuppressWarnings
(
"unchecked"
)
MVMap
<
K
,
V
>
m
=
(
MVMap
<
K
,
V
>)
openMap
(
name
,
""
,
keyType
,
valueType
);
return
m
;
}
/**
/**
* Remove a map.
* Remove a map.
*
*
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/store/btree/MapFactory.java
浏览文件 @
e949b40f
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
package
org
.
h2
.
dev
.
store
.
btree
;
package
org
.
h2
.
dev
.
store
.
btree
;
/**
/**
* A factory for data types.
* A factory for
maps and
data types.
*/
*/
public
interface
MapFactory
{
public
interface
MapFactory
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/store/btree/StringType.java
浏览文件 @
e949b40f
...
@@ -18,46 +18,23 @@ public class StringType implements DataType {
...
@@ -18,46 +18,23 @@ public class StringType implements DataType {
}
}
public
int
getMaxLength
(
Object
obj
)
{
public
int
getMaxLength
(
Object
obj
)
{
return
DataUtils
.
MAX_VAR_INT_LEN
+
obj
.
toString
().
length
()
*
3
;
return
DataUtils
.
MAX_VAR_INT_LEN
+
3
*
obj
.
toString
().
length
()
;
}
}
public
int
getMemory
(
Object
obj
)
{
public
int
getMemory
(
Object
obj
)
{
return
obj
.
toString
().
length
()
*
2
+
48
;
return
24
+
2
*
obj
.
toString
().
length
()
;
}
}
public
String
read
(
ByteBuffer
buff
)
{
public
String
read
(
ByteBuffer
buff
)
{
int
len
=
DataUtils
.
readVarInt
(
buff
);
int
len
=
DataUtils
.
readVarInt
(
buff
);
char
[]
chars
=
new
char
[
len
];
return
DataUtils
.
readString
(
buff
,
len
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
int
x
=
buff
.
get
()
&
0xff
;
if
(
x
<
0x80
)
{
chars
[
i
]
=
(
char
)
x
;
}
else
if
(
x
>=
0xe0
)
{
chars
[
i
]
=
(
char
)
(((
x
&
0xf
)
<<
12
)
+
((
buff
.
get
()
&
0x3f
)
<<
6
)
+
(
buff
.
get
()
&
0x3f
));
}
else
{
chars
[
i
]
=
(
char
)
(((
x
&
0x1f
)
<<
6
)
+
(
buff
.
get
()
&
0x3f
));
}
}
return
new
String
(
chars
);
}
}
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
public
void
write
(
ByteBuffer
buff
,
Object
obj
)
{
String
s
=
obj
.
toString
();
String
s
=
obj
.
toString
();
int
len
=
s
.
length
();
int
len
=
s
.
length
();
DataUtils
.
writeVarInt
(
buff
,
len
);
DataUtils
.
writeVarInt
(
buff
,
len
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
DataUtils
.
writeStringData
(
buff
,
s
,
len
);
int
c
=
s
.
charAt
(
i
);
if
(
c
<
0x80
)
{
buff
.
put
((
byte
)
c
);
}
else
if
(
c
>=
0x800
)
{
buff
.
put
((
byte
)
(
0xe0
|
(
c
>>
12
)));
buff
.
put
((
byte
)
(((
c
>>
6
)
&
0x3f
)));
buff
.
put
((
byte
)
(
c
&
0x3f
));
}
else
{
buff
.
put
((
byte
)
(
0xc0
|
(
c
>>
6
)));
buff
.
put
((
byte
)
(
c
&
0x3f
));
}
}
}
}
public
String
asString
()
{
public
String
asString
()
{
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论