Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
871b0a8e
提交
871b0a8e
authored
11月 28, 2012
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
A persistent multi-version map: prepare initial release
上级
f2afe926
显示空白字符变更
内嵌
并排
正在显示
26 个修改的文件
包含
474 行增加
和
316 行删除
+474
-316
fragments.html
h2/src/docsrc/html/fragments.html
+1
-0
mvstore.html
h2/src/docsrc/html/mvstore.html
+95
-28
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+114
-114
IntegerType.java
h2/src/test/org/h2/test/store/IntegerType.java
+0
-45
RowType.java
h2/src/test/org/h2/test/store/RowType.java
+7
-5
SampleTypeFactory.java
h2/src/test/org/h2/test/store/SampleTypeFactory.java
+41
-0
SequenceMap.java
h2/src/test/org/h2/test/store/SequenceMap.java
+9
-9
TestConcurrent.java
h2/src/test/org/h2/test/store/TestConcurrent.java
+3
-2
TestMVRTree.java
h2/src/test/org/h2/test/store/TestMVRTree.java
+33
-17
TestMVStore.java
h2/src/test/org/h2/test/store/TestMVStore.java
+48
-49
TestObjectType.java
h2/src/test/org/h2/test/store/TestObjectType.java
+1
-0
MVMap.java
h2/src/tools/org/h2/dev/store/btree/MVMap.java
+9
-4
MVStore.java
h2/src/tools/org/h2/dev/store/btree/MVStore.java
+40
-21
MVStoreBuilder.java
h2/src/tools/org/h2/dev/store/btree/MVStoreBuilder.java
+1
-0
MVStoreTool.java
h2/src/tools/org/h2/dev/store/btree/MVStoreTool.java
+1
-1
Page.java
h2/src/tools/org/h2/dev/store/btree/Page.java
+1
-0
CacheLongKeyLIRS.java
h2/src/tools/org/h2/dev/store/cache/CacheLongKeyLIRS.java
+1
-1
FilePathCache.java
h2/src/tools/org/h2/dev/store/cache/FilePathCache.java
+1
-2
MVRTreeMap.java
h2/src/tools/org/h2/dev/store/rtree/MVRTreeMap.java
+5
-5
SpatialKey.java
h2/src/tools/org/h2/dev/store/rtree/SpatialKey.java
+1
-1
SpatialType.java
h2/src/tools/org/h2/dev/store/rtree/SpatialType.java
+2
-2
DataType.java
h2/src/tools/org/h2/dev/store/type/DataType.java
+4
-1
DataTypeFactory.java
h2/src/tools/org/h2/dev/store/type/DataTypeFactory.java
+14
-5
ObjectType.java
h2/src/tools/org/h2/dev/store/type/ObjectType.java
+2
-3
ObjectTypeFactory.java
h2/src/tools/org/h2/dev/store/type/ObjectTypeFactory.java
+38
-0
StringType.java
h2/src/tools/org/h2/dev/store/type/StringType.java
+2
-1
没有找到文件。
h2/src/docsrc/html/fragments.html
浏览文件 @
871b0a8e
...
@@ -94,6 +94,7 @@ translate -->
...
@@ -94,6 +94,7 @@ translate -->
<a
href=
"build.html"
>
Build
</a><br
/>
<a
href=
"build.html"
>
Build
</a><br
/>
<a
href=
"links.html"
>
Links
</a><br
/>
<a
href=
"links.html"
>
Links
</a><br
/>
<a
href=
"jaqu.html"
>
JaQu
</a><br
/>
<a
href=
"jaqu.html"
>
JaQu
</a><br
/>
<a
href=
"mvstore.html"
>
MVStore
</a><br
/>
<br
/>
<br
/>
</div>
</div>
...
...
h2/src/docsrc/html/mvstore.html
浏览文件 @
871b0a8e
...
@@ -7,7 +7,7 @@ Initial Developer: H2 Group
...
@@ -7,7 +7,7 @@ Initial Developer: H2 Group
-->
-->
<html
xmlns=
"http://www.w3.org/1999/xhtml"
lang=
"en"
xml:lang=
"en"
>
<html
xmlns=
"http://www.w3.org/1999/xhtml"
lang=
"en"
xml:lang=
"en"
>
<head><meta
http-equiv=
"Content-Type"
content=
"text/html;charset=utf-8"
/><title>
<head><meta
http-equiv=
"Content-Type"
content=
"text/html;charset=utf-8"
/><title>
JaQu
MVStore
</title><link
rel=
"stylesheet"
type=
"text/css"
href=
"stylesheet.css"
/>
</title><link
rel=
"stylesheet"
type=
"text/css"
href=
"stylesheet.css"
/>
<!-- [search] { -->
<!-- [search] { -->
<script
type=
"text/javascript"
src=
"navigation.js"
></script>
<script
type=
"text/javascript"
src=
"navigation.js"
></script>
...
@@ -34,33 +34,38 @@ JaQu
...
@@ -34,33 +34,38 @@ JaQu
Future Plans
</a><br
/>
Future Plans
</a><br
/>
<h2
id=
"overview"
>
Overview
</h2>
<h2
id=
"overview"
>
Overview
</h2>
<p>
The MVStore is work in progress, and is planned to be the next storage subsystem of H2.
</p>
<ul><li>
MVStore stands for multi-version store.
<ul><li>
MVStore stands for multi-version store.
</li><li>
Each store contains a number of maps (using the
<code>
java.util.Map
</code>
interface).
</li><li>
Each store contains a number of maps (using the
<code>
java.util.Map
</code>
interface).
</li><li>
The data can be persisted to disk (like a key-value store or a database).
</li><li>
The data can be persisted to disk (like a key-value store or a database).
</li><li>
Fully in-memory operation is supported.
</li><li>
Fully in-memory operation is supported.
</li><li>
It is intended to be fast, simple to use, and small.
</li><li>
It is intended to be fast, simple to use, and small.
</li><li>
Old versions of the data can be read concurrently with all other operations.
</li><li>
Old versions of the data can be read concurrently with all other operations.
</li><li>
Transaction are supported (currently only one transaction
can be open at any
time).
</li><li>
Transaction are supported (currently only one transaction
at a
time).
</li><li>
Transactions (even if they are persisted) can be rolled back.
</li><li>
Transactions (even if they are persisted) can be rolled back.
</li><li>
The tool is very modular. It supports pluggable data types / serialization,
</li><li>
The tool is very modular. It supports pluggable data types / serialization,
pluggable map implementations (B-tree and R-tree currently), BLOB storage,
pluggable map implementations (B-tree and R-tree currently), BLOB storage,
and a file system abstraction that supports encryption and compressed
and a file system abstraction to support encryption and compressed read-only files.
read-only files.
</li></ul>
</li></ul>
<h2
id=
"example_code"
>
Example Code
</h2>
<h2
id=
"example_code"
>
Example Code
</h2>
<h3>
Map Operations and Versioning
</h3>
<p>
The following sample code show how to create a store,
open a map, add some data, and access the current and an old version.
</p>
<pre>
<pre>
// open the store (in-memory if fileName is null)
// open the store (in-memory if fileName is null)
MVStore s = MVStore.open(fileName);
MVStore s = MVStore.open(fileName);
// create/get the map "data"
// create/get the map named "data"
// the String.class, String.class will be optional later
MVMap
<Integer
,
String
>
map = s.openMap("data");
MVMap
<String
,
String
>
map = s.openMap("data",
String.class, String.class);
// add some data
// add some data
map.put(
"1"
, "Hello");
map.put(
1
, "Hello");
map.put(
"2"
, "World");
map.put(
2
, "World");
// get the current version, for later use
// get the current version, for later use
long oldVersion = s.getCurrentVersion();
long oldVersion = s.getCurrentVersion();
...
@@ -71,11 +76,11 @@ s.incrementVersion();
...
@@ -71,11 +76,11 @@ s.incrementVersion();
// more changes, in the new version
// more changes, in the new version
// changes can be rolled back if required
// changes can be rolled back if required
// changes always go into 'head' (the newest version)
// changes always go into 'head' (the newest version)
map.put(
"1"
, "Hi");
map.put(
1
, "Hi");
map.remove(
"2"
);
map.remove(
2
);
// access the old data (before incrementVersion)
// access the old data (before incrementVersion)
MVMap
<
String
,
String
>
oldMap =
MVMap
<
Integer
,
String
>
oldMap =
map.openVersion(oldVersion);
map.openVersion(oldVersion);
// store the newest data to disk
// store the newest data to disk
...
@@ -84,16 +89,62 @@ s.store();
...
@@ -84,16 +89,62 @@ s.store();
// print the old version (can be done
// print the old version (can be done
// concurrently with further modifications)
// concurrently with further modifications)
// this will print Hello World
// this will print Hello World
System.out.println(oldMap.get("1"));
System.out.println(oldMap.get(1));
System.out.println(oldMap.get("2"));
System.out.println(oldMap.get(2));
oldMap.close();
// print the newest version ("Hi")
// print the newest version ("Hi")
System.out.println(map.get(
"1"
));
System.out.println(map.get(
1
));
// close the store - this doesn't write to disk
// close the store - this doesn't write to disk
s.close();
s.close();
</pre>
</pre>
<h3>
Store Builder
</h3>
<p>
The
<code>
MVStoreBuilder
</code>
provides a fluid interface
to build a store if more complex configuration options are used.
</p>
<pre>
MVStore s = MVStoreBuilder.
fileBased(fileName).
cacheSizeMB(10).
readOnly().
open();
</pre>
<h3>
R-Tree
</h3>
<p>
The
<code>
MVRTreeMap
</code>
is an R-tree implementation
that supports fast spatial queries.
</p>
<pre>
// create an in-memory store
MVStore s = MVStore.open(null);
// create an R-tree map
// the key has 2 dimensions, the value is a string
MVRTreeMap
<String>
r = MVRTreeMap.create(2, new ObjectType());
// open the map
r = s.openMap("data", r);
// add two key-value pairs
// the first value is the key id (to make the key unique)
// then the min x, max x, min y, max y
r.add(new SpatialKey(0, -3f, -2f, 2f, 3f), "left");
r.add(new SpatialKey(1, 3f, 4f, 4f, 5f), "right");
// iterate over the intersecting keys
Iterator
<SpatialKey>
it =
r.findIntersectingKeys(new SpatialKey(0, 0f, 9f, 3f, 6f));
for (SpatialKey k; it.hasNext();) {
k = it.next();
System.out.println(k + ": " + r.get(k));
}
s.close();
</pre>
<h2
id=
"features"
>
Features
</h2>
<h2
id=
"features"
>
Features
</h2>
...
@@ -103,13 +154,18 @@ Each store supports a set of named maps.
...
@@ -103,13 +154,18 @@ Each store supports a set of named maps.
A map is sorted by key, and supports the common lookup operations,
A map is sorted by key, and supports the common lookup operations,
including access to the first and last key, iterate over some or all keys, and so on.
including access to the first and last key, iterate over some or all keys, and so on.
</p><p>
</p><p>
Also supported, and unusual for maps, is fast index lookup, as if the map would be a list
Also supported, and very uncommon for maps, is fast index lookup.
(get the key at the given index, get the index of a certain key), and fast skipping within an iterator.
The keys of the map can be accessed like a list
Internally, each map is organized in the form of a counted B+-tree.
(get the key at the given index, get the index of a certain key).
That means getting the median of two keys is trivial,
and it allows to very quickly count ranges.
The iterator supports fast skipping.
This is possible because internally, each map is organized in the form of a counted B+-tree.
</p><p>
</p><p>
In database terms, a map can be a table, where the key of the map is the primary key of the table,
In database terms, a map can be
used like
a table, where the key of the map is the primary key of the table,
and the value is the row. A map can also represent an index, where the key of the map is the key
and the value is the row. A map can also represent an index, where the key of the map is the key
of the index, and the value of the map is the primary key of the table.
of the index, and the value of the map is the primary key of the table (for non-unique indexes
the key of the map must also contain the primary key).
</p>
</p>
<h3>
Versions / Transactions
</h3>
<h3>
Versions / Transactions
</h3>
...
@@ -189,9 +245,11 @@ use less memory on average.
...
@@ -189,9 +245,11 @@ use less memory on average.
<h3>
Pluggable Data Types
</h3>
<h3>
Pluggable Data Types
</h3>
<p>
<p>
Serialization is pluggable. The default serialization currently only supports string values and keys,
Serialization is pluggable. The default serialization currently supports many common data types,
but there is a sample plugin that supports many common data types,
and uses Java serialization for other objects. The following classes are currently directly supported:
and uses Java serialization for other objects.
<code>
Boolean, Byte, Short, Character, Integer, Long, Float, Double, BigInteger, BigDecimal,
byte[], char[], int[], long[], String, UUID
</code>
.
The plan is to add more common classes (date, time, timestamp, object array).
</p><p>
</p><p>
Parameterized data types are supported
Parameterized data types are supported
(for example one could build a string data type that limits the length for some reason).
(for example one could build a string data type that limits the length for some reason).
...
@@ -232,7 +290,7 @@ which should be resistant against scan operations.
...
@@ -232,7 +290,7 @@ which should be resistant against scan operations.
Concurrent modification operations on the maps are currently not supported,
Concurrent modification operations on the maps are currently not supported,
however it is planned to support an additional map implementation
however it is planned to support an additional map implementation
that supports concurrent writes
that supports concurrent writes
(at the cost of speed if used in a single thread, same as
ConcurrentHashMap
).
(at the cost of speed if used in a single thread, same as
<code>
ConcurrentHashMap
</code>
).
</p>
</p>
<h3>
File System Abstraction, File Locking and Online Backup
</h3>
<h3>
File System Abstraction, File Locking and Online Backup
</h3>
...
@@ -251,9 +309,18 @@ Files can be opened in read-only mode, in which case a shared lock is used.
...
@@ -251,9 +309,18 @@ Files can be opened in read-only mode, in which case a shared lock is used.
The persisted data can be backed up to a different file at any time,
The persisted data can be backed up to a different file at any time,
even during write operations (online backup).
even during write operations (online backup).
To do that, automatic disk space reuse needs to be first disabled, so that
To do that, automatic disk space reuse needs to be first disabled, so that
new data is always appended at the end of the file. Then, the file
new data is always appended at the end of the file.
Then, the file can be copied (the file handle is available to the application).
</p>
</p>
<h3>
Tools
</h3>
<p>
There is a builder for store instances (
<code>
MVStoreBuilder
</code>
)
with a fluent API to simplify building a store instance.
</p>
<p>
There is a tool (
<code>
MVStoreTool
</code>
) to dump the contents of a file.
</p>
<h2
id=
"differences"
>
Similar Projects and Differences to Other Storage Engines
</h2>
<h2
id=
"differences"
>
Similar Projects and Differences to Other Storage Engines
</h2>
<p>
<p>
...
@@ -261,7 +328,7 @@ Unlike similar storage engines like LevelDB and Kyoto Cabinet, the MVStore is wr
...
@@ -261,7 +328,7 @@ Unlike similar storage engines like LevelDB and Kyoto Cabinet, the MVStore is wr
and can easily be embedded in a Java application.
and can easily be embedded in a Java application.
</p><p>
</p><p>
The MVStore is somewhat similar to the Berkeley DB Java Edition because it is also written in Java,
The MVStore is somewhat similar to the Berkeley DB Java Edition because it is also written in Java,
and
also a log structured storage, but the MVStore licensing
is more liberal.
and
is also a log structured storage, but the H2 license
is more liberal.
</p><p>
</p><p>
Like SQLite, the MVStore keeps all data in one file.
Like SQLite, the MVStore keeps all data in one file.
The plan is to make the MVStore easier to use and faster than SQLite on Android
The plan is to make the MVStore easier to use and faster than SQLite on Android
...
@@ -269,7 +336,7 @@ The plan is to make the MVStore easier to use and faster than SQLite on Android
...
@@ -269,7 +336,7 @@ The plan is to make the MVStore easier to use and faster than SQLite on Android
</p><p>
</p><p>
The API of the MVStore is similar to MapDB (previously known as JDBM) from Jan Kotek,
The API of the MVStore is similar to MapDB (previously known as JDBM) from Jan Kotek,
and some code is shared between MapDB and JDBM.
and some code is shared between MapDB and JDBM.
However,
the MVStore
is a log structured storage.
However,
unlike MapDB, the MVStore uses
is a log structured storage.
</p>
</p>
<h2
id=
"current_state"
>
Current State
</h2>
<h2
id=
"current_state"
>
Current State
</h2>
...
...
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
871b0a8e
...
@@ -555,120 +555,120 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
...
@@ -555,120 +555,120 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
beforeTest
();
beforeTest
();
// db
// db
new
TestScriptSimple
().
runTest
(
this
);
//
new TestScriptSimple().runTest(this);
new
TestScript
().
runTest
(
this
);
//
new TestScript().runTest(this);
new
TestAlter
().
runTest
(
this
);
//
new TestAlter().runTest(this);
new
TestAlterSchemaRename
().
runTest
(
this
);
//
new TestAlterSchemaRename().runTest(this);
new
TestAutoRecompile
().
runTest
(
this
);
//
new TestAutoRecompile().runTest(this);
new
TestBitField
().
runTest
(
this
);
//
new TestBitField().runTest(this);
new
TestBackup
().
runTest
(
this
);
//
new TestBackup().runTest(this);
new
TestBigDb
().
runTest
(
this
);
//
new TestBigDb().runTest(this);
new
TestBigResult
().
runTest
(
this
);
//
new TestBigResult().runTest(this);
new
TestCases
().
runTest
(
this
);
//
new TestCases().runTest(this);
new
TestCheckpoint
().
runTest
(
this
);
//
new TestCheckpoint().runTest(this);
new
TestCluster
().
runTest
(
this
);
//
new TestCluster().runTest(this);
new
TestCompatibility
().
runTest
(
this
);
//
new TestCompatibility().runTest(this);
new
TestCsv
().
runTest
(
this
);
//
new TestCsv().runTest(this);
new
TestDateStorage
().
runTest
(
this
);
//
new TestDateStorage().runTest(this);
new
TestDeadlock
().
runTest
(
this
);
//
new TestDeadlock().runTest(this);
new
TestEncryptedDb
().
runTest
(
this
);
//
new TestEncryptedDb().runTest(this);
new
TestExclusive
().
runTest
(
this
);
//
new TestExclusive().runTest(this);
new
TestFullText
().
runTest
(
this
);
//
new TestFullText().runTest(this);
new
TestFunctionOverload
().
runTest
(
this
);
//
new TestFunctionOverload().runTest(this);
new
TestFunctions
().
runTest
(
this
);
//
new TestFunctions().runTest(this);
new
TestInit
().
runTest
(
this
);
//
new TestInit().runTest(this);
new
TestIndex
().
runTest
(
this
);
//
new TestIndex().runTest(this);
new
TestLargeBlob
().
runTest
(
this
);
//
new TestLargeBlob().runTest(this);
new
TestLinkedTable
().
runTest
(
this
);
//
new TestLinkedTable().runTest(this);
new
TestListener
().
runTest
(
this
);
//
new TestListener().runTest(this);
new
TestLob
().
runTest
(
this
);
//
new TestLob().runTest(this);
new
TestMemoryUsage
().
runTest
(
this
);
//
new TestMemoryUsage().runTest(this);
new
TestMultiConn
().
runTest
(
this
);
//
new TestMultiConn().runTest(this);
new
TestMultiDimension
().
runTest
(
this
);
//
new TestMultiDimension().runTest(this);
new
TestMultiThread
().
runTest
(
this
);
//
new TestMultiThread().runTest(this);
new
TestMultiThreadedKernel
().
runTest
(
this
);
//
new TestMultiThreadedKernel().runTest(this);
new
TestOpenClose
().
runTest
(
this
);
//
new TestOpenClose().runTest(this);
new
TestOptimizations
().
runTest
(
this
);
//
new TestOptimizations().runTest(this);
new
TestOutOfMemory
().
runTest
(
this
);
//
new TestOutOfMemory().runTest(this);
new
TestPowerOff
().
runTest
(
this
);
//
new TestPowerOff().runTest(this);
new
TestQueryCache
().
runTest
(
this
);
//
new TestQueryCache().runTest(this);
new
TestReadOnly
().
runTest
(
this
);
//
new TestReadOnly().runTest(this);
new
TestRecursiveQueries
().
runTest
(
this
);
//
new TestRecursiveQueries().runTest(this);
new
TestRights
().
runTest
(
this
);
//
new TestRights().runTest(this);
new
TestRunscript
().
runTest
(
this
);
//
new TestRunscript().runTest(this);
new
TestSQLInjection
().
runTest
(
this
);
//
new TestSQLInjection().runTest(this);
new
TestSessionsLocks
().
runTest
(
this
);
//
new TestSessionsLocks().runTest(this);
new
TestSelectCountNonNullColumn
().
runTest
(
this
);
//
new TestSelectCountNonNullColumn().runTest(this);
new
TestSequence
().
runTest
(
this
);
//
new TestSequence().runTest(this);
new
TestSpaceReuse
().
runTest
(
this
);
//
new TestSpaceReuse().runTest(this);
new
TestSpeed
().
runTest
(
this
);
//
new TestSpeed().runTest(this);
new
TestTableEngines
().
runTest
(
this
);
//
new TestTableEngines().runTest(this);
new
TestTempTables
().
runTest
(
this
);
//
new TestTempTables().runTest(this);
new
TestTransaction
().
runTest
(
this
);
//
new TestTransaction().runTest(this);
new
TestTriggersConstraints
().
runTest
(
this
);
//
new TestTriggersConstraints().runTest(this);
new
TestTwoPhaseCommit
().
runTest
(
this
);
//
new TestTwoPhaseCommit().runTest(this);
new
TestView
().
runTest
(
this
);
//
new TestView().runTest(this);
new
TestViewAlterTable
().
runTest
(
this
);
//
new TestViewAlterTable().runTest(this);
new
TestViewDropView
().
runTest
(
this
);
//
new TestViewDropView().runTest(this);
//
// jaqu
//
// jaqu
new
AliasMapTest
().
runTest
(
this
);
//
new AliasMapTest().runTest(this);
new
AnnotationsTest
().
runTest
(
this
);
//
new AnnotationsTest().runTest(this);
new
ClobTest
().
runTest
(
this
);
//
new ClobTest().runTest(this);
new
ModelsTest
().
runTest
(
this
);
//
new ModelsTest().runTest(this);
new
SamplesTest
().
runTest
(
this
);
//
new SamplesTest().runTest(this);
new
UpdateTest
().
runTest
(
this
);
//
new UpdateTest().runTest(this);
//
// jdbc
//
// jdbc
new
TestBatchUpdates
().
runTest
(
this
);
//
new TestBatchUpdates().runTest(this);
new
TestCallableStatement
().
runTest
(
this
);
//
new TestCallableStatement().runTest(this);
new
TestCancel
().
runTest
(
this
);
//
new TestCancel().runTest(this);
new
TestDatabaseEventListener
().
runTest
(
this
);
//
new TestDatabaseEventListener().runTest(this);
new
TestDriver
().
runTest
(
this
);
//
new TestDriver().runTest(this);
new
TestJavaObject
().
runTest
(
this
);
//
new TestJavaObject().runTest(this);
new
TestLimitUpdates
().
runTest
(
this
);
//
new TestLimitUpdates().runTest(this);
new
TestLobApi
().
runTest
(
this
);
//
new TestLobApi().runTest(this);
new
TestManyJdbcObjects
().
runTest
(
this
);
//
new TestManyJdbcObjects().runTest(this);
new
TestMetaData
().
runTest
(
this
);
//
new TestMetaData().runTest(this);
new
TestNativeSQL
().
runTest
(
this
);
//
new TestNativeSQL().runTest(this);
new
TestPreparedStatement
().
runTest
(
this
);
//
new TestPreparedStatement().runTest(this);
new
TestResultSet
().
runTest
(
this
);
//
new TestResultSet().runTest(this);
new
TestStatement
().
runTest
(
this
);
//
new TestStatement().runTest(this);
new
TestTransactionIsolation
().
runTest
(
this
);
//
new TestTransactionIsolation().runTest(this);
new
TestUpdatableResultSet
().
runTest
(
this
);
//
new TestUpdatableResultSet().runTest(this);
new
TestZloty
().
runTest
(
this
);
//
new TestZloty().runTest(this);
//
// jdbcx
//
// jdbcx
new
TestConnectionPool
().
runTest
(
this
);
//
new TestConnectionPool().runTest(this);
new
TestDataSource
().
runTest
(
this
);
//
new TestDataSource().runTest(this);
new
TestXA
().
runTest
(
this
);
//
new TestXA().runTest(this);
new
TestXASimple
().
runTest
(
this
);
//
new TestXASimple().runTest(this);
//
// server
//
// server
new
TestAutoServer
().
runTest
(
this
);
//
new TestAutoServer().runTest(this);
new
TestNestedLoop
().
runTest
(
this
);
//
new TestNestedLoop().runTest(this);
new
TestWeb
().
runTest
(
this
);
//
new TestWeb().runTest(this);
//
// mvcc & row level locking
//
// mvcc & row level locking
new
TestMvcc1
().
runTest
(
this
);
//
new TestMvcc1().runTest(this);
new
TestMvcc2
().
runTest
(
this
);
//
new TestMvcc2().runTest(this);
new
TestMvcc3
().
runTest
(
this
);
//
new TestMvcc3().runTest(this);
new
TestMvccMultiThreaded
().
runTest
(
this
);
//
new TestMvccMultiThreaded().runTest(this);
new
TestRowLocks
().
runTest
(
this
);
//
new TestRowLocks().runTest(this);
//
// synth
//
// synth
new
TestBtreeIndex
().
runTest
(
this
);
//
new TestBtreeIndex().runTest(this);
new
TestDiskFull
().
runTest
(
this
);
//
new TestDiskFull().runTest(this);
new
TestCrashAPI
().
runTest
(
this
);
//
new TestCrashAPI().runTest(this);
new
TestFuzzOptimizations
().
runTest
(
this
);
//
new TestFuzzOptimizations().runTest(this);
new
TestLimit
().
runTest
(
this
);
//
new TestLimit().runTest(this);
new
TestRandomSQL
().
runTest
(
this
);
//
new TestRandomSQL().runTest(this);
new
TestRandomCompare
().
runTest
(
this
);
//
new TestRandomCompare().runTest(this);
new
TestKillRestart
().
runTest
(
this
);
//
new TestKillRestart().runTest(this);
new
TestKillRestartMulti
().
runTest
(
this
);
//
new TestKillRestartMulti().runTest(this);
new
TestMultiThreaded
().
runTest
(
this
);
//
new TestMultiThreaded().runTest(this);
new
TestOuterJoins
().
runTest
(
this
);
//
new TestOuterJoins().runTest(this);
new
TestNestedJoins
().
runTest
(
this
);
//
new TestNestedJoins().runTest(this);
afterTest
();
afterTest
();
}
}
...
...
h2/src/test/org/h2/test/store/IntegerType.java
deleted
100644 → 0
浏览文件 @
f2afe926
/*
* 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.nio.ByteBuffer
;
import
org.h2.dev.store.btree.DataType
;
import
org.h2.dev.store.btree.DataUtils
;
/**
* An integer type.
*/
class
IntegerType
implements
DataType
{
public
static
final
IntegerType
INSTANCE
=
new
IntegerType
();
public
int
compare
(
Object
a
,
Object
b
)
{
return
((
Integer
)
a
).
compareTo
((
Integer
)
b
);
}
public
int
getMaxLength
(
Object
obj
)
{
return
DataUtils
.
MAX_VAR_INT_LEN
;
}
public
int
getMemory
(
Object
obj
)
{
return
20
;
}
public
Integer
read
(
ByteBuffer
buff
)
{
return
DataUtils
.
readVarInt
(
buff
);
}
public
void
write
(
ByteBuffer
buff
,
Object
x
)
{
DataUtils
.
writeVarInt
(
buff
,
(
Integer
)
x
);
}
public
String
asString
()
{
return
"i"
;
}
}
h2/src/test/org/h2/test/store/RowType.java
浏览文件 @
871b0a8e
...
@@ -7,9 +7,9 @@
...
@@ -7,9 +7,9 @@
package
org
.
h2
.
test
.
store
;
package
org
.
h2
.
test
.
store
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
org.h2.dev.store.btree.DataType
;
import
org.h2.dev.store.btree.DataUtils
;
import
org.h2.dev.store.btree.DataUtils
;
import
org.h2.dev.store.btree.DataTypeFactory
;
import
org.h2.dev.store.type.DataType
;
import
org.h2.dev.store.type.DataTypeFactory
;
import
org.h2.util.StringUtils
;
import
org.h2.util.StringUtils
;
/**
/**
...
@@ -17,6 +17,8 @@ import org.h2.util.StringUtils;
...
@@ -17,6 +17,8 @@ import org.h2.util.StringUtils;
*/
*/
public
class
RowType
implements
DataType
{
public
class
RowType
implements
DataType
{
static
final
String
PREFIX
=
"org.h2.test.store.row"
;
private
final
DataType
[]
types
;
private
final
DataType
[]
types
;
RowType
(
DataType
[]
types
)
{
RowType
(
DataType
[]
types
)
{
...
@@ -86,7 +88,7 @@ public class RowType implements DataType {
...
@@ -86,7 +88,7 @@ public class RowType implements DataType {
public
String
asString
()
{
public
String
asString
()
{
StringBuilder
buff
=
new
StringBuilder
();
StringBuilder
buff
=
new
StringBuilder
();
buff
.
append
(
'r'
);
buff
.
append
(
PREFIX
);
buff
.
append
(
'('
);
buff
.
append
(
'('
);
for
(
int
i
=
0
;
i
<
types
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
types
.
length
;
i
++)
{
if
(
i
>
0
)
{
if
(
i
>
0
)
{
...
@@ -106,10 +108,10 @@ public class RowType implements DataType {
...
@@ -106,10 +108,10 @@ public class RowType implements DataType {
* @return the row type
* @return the row type
*/
*/
static
RowType
fromString
(
String
t
,
DataTypeFactory
factory
)
{
static
RowType
fromString
(
String
t
,
DataTypeFactory
factory
)
{
if
(!
t
.
startsWith
(
"r("
)
||
!
t
.
endsWith
(
")"
))
{
if
(!
t
.
startsWith
(
PREFIX
)
||
!
t
.
endsWith
(
")"
))
{
throw
new
RuntimeException
(
"Unknown type: "
+
t
);
throw
new
RuntimeException
(
"Unknown type: "
+
t
);
}
}
t
=
t
.
substring
(
2
,
t
.
length
()
-
1
);
t
=
t
.
substring
(
PREFIX
.
length
()
,
t
.
length
()
-
1
);
String
[]
array
=
StringUtils
.
arraySplit
(
t
,
','
,
false
);
String
[]
array
=
StringUtils
.
arraySplit
(
t
,
','
,
false
);
DataType
[]
types
=
new
DataType
[
array
.
length
];
DataType
[]
types
=
new
DataType
[
array
.
length
];
for
(
int
i
=
0
;
i
<
array
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
array
.
length
;
i
++)
{
...
...
h2/src/test/org/h2/test/store/SampleTypeFactory.java
0 → 100644
浏览文件 @
871b0a8e
/*
* 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
org.h2.dev.store.type.DataType
;
import
org.h2.dev.store.type.DataTypeFactory
;
/**
* A data type factory.
*/
public
class
SampleTypeFactory
implements
DataTypeFactory
{
private
DataTypeFactory
parent
;
@Override
public
void
setParent
(
DataTypeFactory
parent
)
{
this
.
parent
=
parent
;
}
@Override
public
DataType
buildDataType
(
String
s
)
{
// if ("org.h2.test.store.int".equals(s)) {
// return new IntegerType();
// } else
if
(
s
.
startsWith
(
RowType
.
PREFIX
))
{
return
RowType
.
fromString
(
s
,
this
);
}
return
parent
.
buildDataType
(
s
);
}
@Override
public
String
getDataType
(
Class
<?>
objectClass
)
{
// if (objectClass == Integer.class) {
// return "org.h2.test.store.int";
// }
return
parent
.
getDataType
(
objectClass
);
}
}
h2/src/test/org/h2/test/store/SequenceMap.java
浏览文件 @
871b0a8e
...
@@ -16,7 +16,7 @@ import org.h2.dev.store.btree.MVStore;
...
@@ -16,7 +16,7 @@ import org.h2.dev.store.btree.MVStore;
/**
/**
* A custom map returning the keys and values values 1 .. 10.
* A custom map returning the keys and values values 1 .. 10.
*/
*/
public
class
SequenceMap
extends
MVMap
<
Integer
,
Stri
ng
>
{
public
class
SequenceMap
extends
MVMap
<
Long
,
Lo
ng
>
{
/**
/**
* The minimum value.
* The minimum value.
...
@@ -29,7 +29,7 @@ public class SequenceMap extends MVMap<Integer, String> {
...
@@ -29,7 +29,7 @@ public class SequenceMap extends MVMap<Integer, String> {
int
max
=
10
;
int
max
=
10
;
public
SequenceMap
()
{
public
SequenceMap
()
{
super
(
IntegerType
.
INSTANCE
,
IntegerType
.
INSTANCE
);
super
(
null
,
null
);
}
}
public
void
open
(
MVStore
store
,
HashMap
<
String
,
String
>
config
)
{
public
void
open
(
MVStore
store
,
HashMap
<
String
,
String
>
config
)
{
...
@@ -37,14 +37,14 @@ public class SequenceMap extends MVMap<Integer, String> {
...
@@ -37,14 +37,14 @@ public class SequenceMap extends MVMap<Integer, String> {
setReadOnly
(
true
);
setReadOnly
(
true
);
}
}
public
Set
<
Integer
>
keySet
()
{
public
Set
<
Long
>
keySet
()
{
return
new
AbstractSet
<
Integer
>()
{
return
new
AbstractSet
<
Long
>()
{
@Override
@Override
public
Iterator
<
Integer
>
iterator
()
{
public
Iterator
<
Long
>
iterator
()
{
return
new
Iterator
<
Integer
>()
{
return
new
Iterator
<
Long
>()
{
int
x
=
min
;
long
x
=
min
;
@Override
@Override
public
boolean
hasNext
()
{
public
boolean
hasNext
()
{
...
@@ -52,8 +52,8 @@ public class SequenceMap extends MVMap<Integer, String> {
...
@@ -52,8 +52,8 @@ public class SequenceMap extends MVMap<Integer, String> {
}
}
@Override
@Override
public
Integer
next
()
{
public
Long
next
()
{
return
Integer
.
valueOf
(
x
++);
return
Long
.
valueOf
(
x
++);
}
}
@Override
@Override
...
...
h2/src/test/org/h2/test/store/TestConcurrent.java
浏览文件 @
871b0a8e
...
@@ -17,6 +17,7 @@ import java.util.Random;
...
@@ -17,6 +17,7 @@ import java.util.Random;
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.dev.store.btree.MVStoreBuilder
;
import
org.h2.dev.store.btree.MVStoreBuilder
;
import
org.h2.dev.store.type.ObjectTypeFactory
;
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.Task
;
import
org.h2.util.Task
;
...
@@ -132,8 +133,8 @@ public class TestConcurrent extends TestMVStore {
...
@@ -132,8 +133,8 @@ public class TestConcurrent extends TestMVStore {
private
void
testConcurrentIterate
()
{
private
void
testConcurrentIterate
()
{
MVStore
s
=
MVStoreBuilder
.
inMemory
().
MVStore
s
=
MVStoreBuilder
.
inMemory
().
with
(
new
SampleData
TypeFactory
()).
open
();
with
(
new
Object
TypeFactory
()).
open
();
s
.
set
Max
PageSize
(
3
);
s
.
setPageSize
(
3
);
final
MVMap
<
Integer
,
Integer
>
map
=
s
.
openMap
(
"test"
);
final
MVMap
<
Integer
,
Integer
>
map
=
s
.
openMap
(
"test"
);
final
int
len
=
10
;
final
int
len
=
10
;
final
Random
r
=
new
Random
();
final
Random
r
=
new
Random
();
...
...
h2/src/test/org/h2/test/store/TestMVRTree.java
浏览文件 @
871b0a8e
...
@@ -21,7 +21,10 @@ import javax.imageio.ImageIO;
...
@@ -21,7 +21,10 @@ import javax.imageio.ImageIO;
import
javax.imageio.ImageWriter
;
import
javax.imageio.ImageWriter
;
import
javax.imageio.stream.FileImageOutputStream
;
import
javax.imageio.stream.FileImageOutputStream
;
import
org.h2.dev.store.btree.MVStore
;
import
org.h2.dev.store.btree.MVStore
;
import
org.h2.dev.store.btree.StringType
;
import
org.h2.dev.store.rtree.MVRTreeMap
;
import
org.h2.dev.store.rtree.SpatialKey
;
import
org.h2.dev.store.type.ObjectType
;
import
org.h2.dev.store.type.StringType
;
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
;
...
@@ -41,10 +44,38 @@ public class TestMVRTree extends TestMVStore {
...
@@ -41,10 +44,38 @@ public class TestMVRTree extends TestMVStore {
}
}
public
void
test
()
{
public
void
test
()
{
testExample
();
testMany
();
testMany
();
testSimple
();
testSimple
();
testRandom
();
testRandom
();
testCustomMapType
();
}
private
void
testExample
()
{
// create an in-memory store
MVStore
s
=
MVStore
.
open
(
null
);
// create an R-tree map
// the key has 2 dimensions, the value is a string
MVRTreeMap
<
String
>
r
=
MVRTreeMap
.
create
(
2
,
new
ObjectType
());
// open the map
r
=
s
.
openMap
(
"data"
,
r
);
// add two key-value pairs
// the first value is the key id (to make the key unique)
// then the min x, max x, min y, max y
r
.
add
(
new
SpatialKey
(
0
,
-
3
f
,
-
2
f
,
2
f
,
3
f
),
"left"
);
r
.
add
(
new
SpatialKey
(
1
,
3
f
,
4
f
,
4
f
,
5
f
),
"right"
);
// iterate over the intersecting keys
Iterator
<
SpatialKey
>
it
=
r
.
findIntersectingKeys
(
new
SpatialKey
(
0
,
0
f
,
9
f
,
3
f
,
6
f
));
for
(
SpatialKey
k
;
it
.
hasNext
();)
{
k
=
it
.
next
();
// System.out.println(k + ": " + r.get(k));
assertTrue
(
k
!=
null
);
}
s
.
close
();
}
}
private
void
testMany
()
{
private
void
testMany
()
{
...
@@ -276,19 +307,4 @@ public class TestMVRTree extends TestMVStore {
...
@@ -276,19 +307,4 @@ public class TestMVRTree extends TestMVStore {
s
.
close
();
s
.
close
();
}
}
private
void
testCustomMapType
()
{
String
fileName
=
getBaseDir
()
+
"/testMapType.h3"
;
FileUtils
.
delete
(
fileName
);
MVStore
s
;
s
=
openStore
(
fileName
);
SequenceMap
seq
=
new
SequenceMap
();
seq
=
s
.
openMap
(
"data"
,
seq
);
StringBuilder
buff
=
new
StringBuilder
();
for
(
int
x
:
seq
.
keySet
())
{
buff
.
append
(
x
).
append
(
';'
);
}
assertEquals
(
"1;2;3;4;5;6;7;8;9;10;"
,
buff
.
toString
());
s
.
close
();
}
}
}
h2/src/test/org/h2/test/store/TestMVStore.java
浏览文件 @
871b0a8e
...
@@ -14,11 +14,13 @@ import java.util.Map;
...
@@ -14,11 +14,13 @@ import java.util.Map;
import
java.util.Random
;
import
java.util.Random
;
import
java.util.TreeMap
;
import
java.util.TreeMap
;
import
org.h2.dev.store.btree.Cursor
;
import
org.h2.dev.store.btree.Cursor
;
import
org.h2.dev.store.btree.DataType
;
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.dev.store.btree.MVStoreBuilder
;
import
org.h2.dev.store.btree.MVStoreBuilder
;
import
org.h2.dev.store.btree.StringType
;
import
org.h2.dev.store.type.DataType
;
import
org.h2.dev.store.type.ObjectType
;
import
org.h2.dev.store.type.ObjectTypeFactory
;
import
org.h2.dev.store.type.StringType
;
import
org.h2.store.fs.FilePath
;
import
org.h2.store.fs.FilePath
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.test.TestBase
;
import
org.h2.test.TestBase
;
...
@@ -40,6 +42,7 @@ public class TestMVStore extends TestBase {
...
@@ -40,6 +42,7 @@ public class TestMVStore extends TestBase {
public
void
test
()
throws
Exception
{
public
void
test
()
throws
Exception
{
FileUtils
.
deleteRecursive
(
getBaseDir
(),
true
);
FileUtils
.
deleteRecursive
(
getBaseDir
(),
true
);
testCustomMapType
();
testCacheSize
();
testCacheSize
();
testConcurrentOpen
();
testConcurrentOpen
();
testFileHeader
();
testFileHeader
();
...
@@ -70,12 +73,27 @@ public class TestMVStore extends TestBase {
...
@@ -70,12 +73,27 @@ public class TestMVStore extends TestBase {
testSimple
();
testSimple
();
}
}
private
void
testCustomMapType
()
{
String
fileName
=
getBaseDir
()
+
"/testMapType.h3"
;
FileUtils
.
delete
(
fileName
);
MVStore
s
;
s
=
openStore
(
fileName
);
SequenceMap
seq
=
new
SequenceMap
();
seq
=
s
.
openMap
(
"data"
,
seq
);
StringBuilder
buff
=
new
StringBuilder
();
for
(
long
x
:
seq
.
keySet
())
{
buff
.
append
(
x
).
append
(
';'
);
}
assertEquals
(
"1;2;3;4;5;6;7;8;9;10;"
,
buff
.
toString
());
s
.
close
();
}
private
void
testCacheSize
()
{
private
void
testCacheSize
()
{
String
fileName
=
getBaseDir
()
+
"/testCacheSize.h3"
;
String
fileName
=
getBaseDir
()
+
"/testCacheSize.h3"
;
MVStore
s
;
MVStore
s
;
MVMap
<
Integer
,
String
>
map
;
MVMap
<
Integer
,
String
>
map
;
s
=
MVStoreBuilder
.
fileBased
(
fileName
).
s
=
MVStoreBuilder
.
fileBased
(
fileName
).
with
(
new
SampleData
TypeFactory
()).
open
();
with
(
new
Object
TypeFactory
()).
open
();
map
=
s
.
openMap
(
"test"
);
map
=
s
.
openMap
(
"test"
);
// add 10 MB of data
// add 10 MB of data
for
(
int
i
=
0
;
i
<
1024
;
i
++)
{
for
(
int
i
=
0
;
i
<
1024
;
i
++)
{
...
@@ -89,7 +107,7 @@ public class TestMVStore extends TestBase {
...
@@ -89,7 +107,7 @@ public class TestMVStore extends TestBase {
for
(
int
cacheSize
=
0
;
cacheSize
<=
6
;
cacheSize
+=
4
)
{
for
(
int
cacheSize
=
0
;
cacheSize
<=
6
;
cacheSize
+=
4
)
{
s
=
MVStoreBuilder
.
fileBased
(
fileName
).
s
=
MVStoreBuilder
.
fileBased
(
fileName
).
cacheSizeMB
(
1
+
3
*
cacheSize
).
cacheSizeMB
(
1
+
3
*
cacheSize
).
with
(
new
SampleData
TypeFactory
()).
open
();
with
(
new
Object
TypeFactory
()).
open
();
map
=
s
.
openMap
(
"test"
);
map
=
s
.
openMap
(
"test"
);
for
(
int
i
=
0
;
i
<
1024
;
i
+=
128
)
{
for
(
int
i
=
0
;
i
<
1024
;
i
+=
128
)
{
for
(
int
j
=
0
;
j
<
i
;
j
++)
{
for
(
int
j
=
0
;
j
<
i
;
j
++)
{
...
@@ -179,7 +197,7 @@ public class TestMVStore extends TestBase {
...
@@ -179,7 +197,7 @@ public class TestMVStore extends TestBase {
private
void
testIndexSkip
()
{
private
void
testIndexSkip
()
{
MVStore
s
=
openStore
(
null
);
MVStore
s
=
openStore
(
null
);
s
.
set
Max
PageSize
(
4
);
s
.
setPageSize
(
4
);
MVMap
<
Integer
,
Integer
>
map
=
s
.
openMap
(
"test"
);
MVMap
<
Integer
,
Integer
>
map
=
s
.
openMap
(
"test"
);
for
(
int
i
=
0
;
i
<
100
;
i
+=
2
)
{
for
(
int
i
=
0
;
i
<
100
;
i
+=
2
)
{
map
.
put
(
i
,
10
*
i
);
map
.
put
(
i
,
10
*
i
);
...
@@ -240,7 +258,7 @@ public class TestMVStore extends TestBase {
...
@@ -240,7 +258,7 @@ public class TestMVStore extends TestBase {
for
(
int
i
=
3
;
i
<
20
;
i
++)
{
for
(
int
i
=
3
;
i
<
20
;
i
++)
{
s
=
openStore
(
null
);
s
=
openStore
(
null
);
s
.
set
Max
PageSize
(
4
);
s
.
setPageSize
(
4
);
map
=
s
.
openMap
(
"test"
);
map
=
s
.
openMap
(
"test"
);
for
(
int
j
=
3
;
j
<
i
;
j
++)
{
for
(
int
j
=
3
;
j
<
i
;
j
++)
{
map
.
put
(
j
*
2
,
j
*
20
);
map
.
put
(
j
*
2
,
j
*
20
);
...
@@ -310,7 +328,7 @@ public class TestMVStore extends TestBase {
...
@@ -310,7 +328,7 @@ public class TestMVStore extends TestBase {
MVStore
s
;
MVStore
s
;
Map
<
Integer
,
Integer
>
map
;
Map
<
Integer
,
Integer
>
map
;
s
=
MVStoreBuilder
.
inMemory
().
s
=
MVStoreBuilder
.
inMemory
().
with
(
new
SampleData
TypeFactory
()).
open
();
with
(
new
Object
TypeFactory
()).
open
();
map
=
s
.
openMap
(
"test"
);
map
=
s
.
openMap
(
"test"
);
int
len
=
100
;
int
len
=
100
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
...
@@ -336,7 +354,7 @@ public class TestMVStore extends TestBase {
...
@@ -336,7 +354,7 @@ public class TestMVStore extends TestBase {
MVStore
s
;
MVStore
s
;
Map
<
Object
,
Object
>
map
;
Map
<
Object
,
Object
>
map
;
s
=
MVStoreBuilder
.
fileBased
(
fileName
).
s
=
MVStoreBuilder
.
fileBased
(
fileName
).
with
(
new
SampleData
TypeFactory
()).
open
();
with
(
new
Object
TypeFactory
()).
open
();
map
=
s
.
openMap
(
"test"
);
map
=
s
.
openMap
(
"test"
);
map
.
put
(
1
,
"Hello"
);
map
.
put
(
1
,
"Hello"
);
map
.
put
(
"2"
,
200
);
map
.
put
(
"2"
,
200
);
...
@@ -344,7 +362,7 @@ public class TestMVStore extends TestBase {
...
@@ -344,7 +362,7 @@ public class TestMVStore extends TestBase {
s
.
store
();
s
.
store
();
s
.
close
();
s
.
close
();
s
=
MVStoreBuilder
.
fileBased
(
fileName
).
s
=
MVStoreBuilder
.
fileBased
(
fileName
).
with
(
new
SampleData
TypeFactory
()).
open
();
with
(
new
Object
TypeFactory
()).
open
();
map
=
s
.
openMap
(
"test"
);
map
=
s
.
openMap
(
"test"
);
assertEquals
(
"Hello"
,
map
.
get
(
1
).
toString
());
assertEquals
(
"Hello"
,
map
.
get
(
1
).
toString
());
assertEquals
(
200
,
((
Integer
)
map
.
get
(
"2"
)).
intValue
());
assertEquals
(
200
,
((
Integer
)
map
.
get
(
"2"
)).
intValue
());
...
@@ -362,14 +380,12 @@ public class TestMVStore extends TestBase {
...
@@ -362,14 +380,12 @@ public class TestMVStore extends TestBase {
// open the store (in-memory if fileName is null)
// open the store (in-memory if fileName is null)
MVStore
s
=
MVStore
.
open
(
fileName
);
MVStore
s
=
MVStore
.
open
(
fileName
);
// create/get the map "data"
// create/get the map named "data"
// the String.class, String.class will be optional later
MVMap
<
Integer
,
String
>
map
=
s
.
openMap
(
"data"
);
MVMap
<
String
,
String
>
map
=
s
.
openMap
(
"data"
,
String
.
class
,
String
.
class
);
// add some data
// add some data
map
.
put
(
"1"
,
"Hello"
);
map
.
put
(
1
,
"Hello"
);
map
.
put
(
"2"
,
"World"
);
map
.
put
(
2
,
"World"
);
// get the current version, for later use
// get the current version, for later use
long
oldVersion
=
s
.
getCurrentVersion
();
long
oldVersion
=
s
.
getCurrentVersion
();
...
@@ -380,11 +396,11 @@ public class TestMVStore extends TestBase {
...
@@ -380,11 +396,11 @@ public class TestMVStore extends TestBase {
// more changes, in the new version
// more changes, in the new version
// changes can be rolled back if required
// changes can be rolled back if required
// changes always go into 'head' (the newest version)
// changes always go into 'head' (the newest version)
map
.
put
(
"1"
,
"Hi"
);
map
.
put
(
1
,
"Hi"
);
map
.
remove
(
"2"
);
map
.
remove
(
2
);
// access the old data (before incrementVersion)
// access the old data (before incrementVersion)
MVMap
<
String
,
String
>
oldMap
=
MVMap
<
Integer
,
String
>
oldMap
=
map
.
openVersion
(
oldVersion
);
map
.
openVersion
(
oldVersion
);
// store the newest data to disk
// store the newest data to disk
...
@@ -393,12 +409,12 @@ public class TestMVStore extends TestBase {
...
@@ -393,12 +409,12 @@ public class TestMVStore extends TestBase {
// print the old version (can be done
// print the old version (can be done
// concurrently with further modifications)
// concurrently with further modifications)
// this will print Hello World
// this will print Hello World
// System.out.println(oldMap.get(
"1"
));
// System.out.println(oldMap.get(
1
));
// System.out.println(oldMap.get(
"2"
));
// System.out.println(oldMap.get(
2
));
oldMap
.
close
();
oldMap
.
close
();
// print the newest version ("Hi")
// print the newest version ("Hi")
// System.out.println(map.get(
"1"
));
// System.out.println(map.get(
1
));
// close the store - this doesn't write to disk
// close the store - this doesn't write to disk
s
.
close
();
s
.
close
();
...
@@ -429,7 +445,7 @@ public class TestMVStore extends TestBase {
...
@@ -429,7 +445,7 @@ public class TestMVStore extends TestBase {
String
fileName
=
getBaseDir
()
+
"/testIterate.h3"
;
String
fileName
=
getBaseDir
()
+
"/testIterate.h3"
;
FileUtils
.
delete
(
fileName
);
FileUtils
.
delete
(
fileName
);
MVStore
s
=
openStore
(
fileName
);
MVStore
s
=
openStore
(
fileName
);
s
.
set
Max
PageSize
(
6
);
s
.
setPageSize
(
6
);
MVMap
<
Integer
,
String
>
m
=
s
.
openMap
(
"data"
,
Integer
.
class
,
String
.
class
);
MVMap
<
Integer
,
String
>
m
=
s
.
openMap
(
"data"
,
Integer
.
class
,
String
.
class
);
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
m
.
put
(
i
,
"Hi"
);
m
.
put
(
i
,
"Hi"
);
...
@@ -538,14 +554,14 @@ public class TestMVStore extends TestBase {
...
@@ -538,14 +554,14 @@ public class TestMVStore extends TestBase {
MVStore
s
;
MVStore
s
;
MVMap
<
Integer
,
String
>
m
;
MVMap
<
Integer
,
String
>
m
;
s
=
openStore
(
fileName
);
s
=
openStore
(
fileName
);
s
.
set
Max
PageSize
(
700
);
s
.
setPageSize
(
700
);
m
=
s
.
openMap
(
"data"
,
Integer
.
class
,
String
.
class
);
m
=
s
.
openMap
(
"data"
,
Integer
.
class
,
String
.
class
);
for
(
int
i
=
0
;
i
<
1000
;
i
++)
{
for
(
int
i
=
0
;
i
<
1000
;
i
++)
{
m
.
put
(
i
,
"Hello World"
);
m
.
put
(
i
,
"Hello World"
);
assertEquals
(
i
+
1
,
m
.
size
());
assertEquals
(
i
+
1
,
m
.
size
());
}
}
assertEquals
(
1000
,
m
.
size
());
assertEquals
(
1000
,
m
.
size
());
assertEquals
(
2
79
,
s
.
getUnsavedPageCount
());
assertEquals
(
2
84
,
s
.
getUnsavedPageCount
());
s
.
store
();
s
.
store
();
assertEquals
(
3
,
s
.
getFileWriteCount
());
assertEquals
(
3
,
s
.
getFileWriteCount
());
s
.
close
();
s
.
close
();
...
@@ -556,7 +572,7 @@ public class TestMVStore extends TestBase {
...
@@ -556,7 +572,7 @@ public class TestMVStore extends TestBase {
assertEquals
(
0
,
m
.
size
());
assertEquals
(
0
,
m
.
size
());
s
.
store
();
s
.
store
();
// ensure only nodes are read, but not leaves
// ensure only nodes are read, but not leaves
assertEquals
(
36
,
s
.
getFileReadCount
());
assertEquals
(
41
,
s
.
getFileReadCount
());
assertEquals
(
2
,
s
.
getFileWriteCount
());
assertEquals
(
2
,
s
.
getFileWriteCount
());
s
.
close
();
s
.
close
();
}
}
...
@@ -652,7 +668,7 @@ public class TestMVStore extends TestBase {
...
@@ -652,7 +668,7 @@ public class TestMVStore extends TestBase {
FileUtils
.
delete
(
fileName
);
FileUtils
.
delete
(
fileName
);
MVStore
s
=
openStore
(
fileName
);
MVStore
s
=
openStore
(
fileName
);
assertEquals
(
0
,
s
.
getCurrentVersion
());
assertEquals
(
0
,
s
.
getCurrentVersion
());
s
.
set
Max
PageSize
(
5
);
s
.
setPageSize
(
5
);
MVMap
<
String
,
String
>
m
=
s
.
openMap
(
"data"
,
String
.
class
,
String
.
class
);
MVMap
<
String
,
String
>
m
=
s
.
openMap
(
"data"
,
String
.
class
,
String
.
class
);
s
.
rollbackTo
(
0
);
s
.
rollbackTo
(
0
);
assertTrue
(
m
.
isClosed
());
assertTrue
(
m
.
isClosed
());
...
@@ -753,11 +769,11 @@ public class TestMVStore extends TestBase {
...
@@ -753,11 +769,11 @@ public class TestMVStore extends TestBase {
FileUtils
.
delete
(
fileName
);
FileUtils
.
delete
(
fileName
);
MVStore
s
=
openStore
(
fileName
);
MVStore
s
=
openStore
(
fileName
);
// s.setCompressor(null);
// s.setCompressor(null);
s
.
set
Max
PageSize
(
40
);
s
.
setPageSize
(
40
);
MVMap
<
Integer
,
Object
[]>
m
=
new
MVMap
<
Integer
,
Object
[]>(
MVMap
<
Integer
,
Object
[]>
m
=
new
MVMap
<
Integer
,
Object
[]>(
IntegerType
.
INSTANCE
,
new
ObjectType
()
,
new
RowType
(
new
DataType
[]
{
new
RowType
(
new
DataType
[]
{
IntegerType
.
INSTANCE
,
new
ObjectType
()
,
StringType
.
INSTANCE
,
StringType
.
INSTANCE
,
StringType
.
INSTANCE
StringType
.
INSTANCE
})
})
...
@@ -965,26 +981,9 @@ public class TestMVStore extends TestBase {
...
@@ -965,26 +981,9 @@ public class TestMVStore extends TestBase {
}
}
private
void
testKeyValueClasses
()
{
private
void
testKeyValueClasses
()
{
MVStore
s
;
s
=
MVStore
.
open
(
null
);
s
.
openMap
(
"test"
,
String
.
class
,
String
.
class
);
try
{
s
.
openMap
(
"unsupportedKey"
,
ArrayList
.
class
,
String
.
class
);
fail
();
}
catch
(
RuntimeException
e
)
{
// expected
}
try
{
s
.
openMap
(
"unsupportedValue"
,
String
.
class
,
ArrayList
.
class
);
fail
();
}
catch
(
RuntimeException
e
)
{
// expected
}
s
.
close
();
String
fileName
=
getBaseDir
()
+
"/testKeyValueClasses.h3"
;
String
fileName
=
getBaseDir
()
+
"/testKeyValueClasses.h3"
;
FileUtils
.
delete
(
fileName
);
FileUtils
.
delete
(
fileName
);
s
=
openStore
(
fileName
);
MVStore
s
=
openStore
(
fileName
);
MVMap
<
Integer
,
String
>
is
=
s
.
openMap
(
"intString"
,
Integer
.
class
,
String
.
class
);
MVMap
<
Integer
,
String
>
is
=
s
.
openMap
(
"intString"
,
Integer
.
class
,
String
.
class
);
is
.
put
(
1
,
"Hello"
);
is
.
put
(
1
,
"Hello"
);
MVMap
<
Integer
,
Integer
>
ii
=
s
.
openMap
(
"intInt"
,
Integer
.
class
,
Integer
.
class
);
MVMap
<
Integer
,
Integer
>
ii
=
s
.
openMap
(
"intInt"
,
Integer
.
class
,
Integer
.
class
);
...
@@ -1089,8 +1088,8 @@ public class TestMVStore extends TestBase {
...
@@ -1089,8 +1088,8 @@ public class TestMVStore extends TestBase {
*/
*/
protected
static
MVStore
openStore
(
String
fileName
)
{
protected
static
MVStore
openStore
(
String
fileName
)
{
MVStore
store
=
MVStoreBuilder
.
fileBased
(
fileName
).
MVStore
store
=
MVStoreBuilder
.
fileBased
(
fileName
).
with
(
new
Sample
Data
TypeFactory
()).
open
();
with
(
new
SampleTypeFactory
()).
open
();
store
.
set
Max
PageSize
(
1000
);
store
.
setPageSize
(
1000
);
return
store
;
return
store
;
}
}
...
...
h2/src/test/org/h2/test/store/TestObjectType.java
浏览文件 @
871b0a8e
...
@@ -13,6 +13,7 @@ import java.sql.Timestamp;
...
@@ -13,6 +13,7 @@ import java.sql.Timestamp;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Random
;
import
java.util.Random
;
import
java.util.UUID
;
import
java.util.UUID
;
import
org.h2.dev.store.type.ObjectType
;
import
org.h2.test.TestBase
;
import
org.h2.test.TestBase
;
/**
/**
...
...
h2/src/tools/org/h2/dev/store/btree/MVMap.java
浏览文件 @
871b0a8e
...
@@ -16,6 +16,7 @@ import java.util.List;
...
@@ -16,6 +16,7 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.Set
;
import
java.util.concurrent.ConcurrentMap
;
import
java.util.concurrent.ConcurrentMap
;
import
org.h2.dev.store.type.DataType
;
import
org.h2.util.New
;
import
org.h2.util.New
;
/**
/**
...
@@ -72,7 +73,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -72,7 +73,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
checkWrite
();
checkWrite
();
long
writeVersion
=
store
.
getCurrentVersion
();
long
writeVersion
=
store
.
getCurrentVersion
();
Page
p
=
root
.
copyOnWrite
(
writeVersion
);
Page
p
=
root
.
copyOnWrite
(
writeVersion
);
if
(
p
.
getMemory
()
>
store
.
get
Max
PageSize
()
&&
p
.
getKeyCount
()
>
1
)
{
if
(
p
.
getMemory
()
>
store
.
getPageSize
()
&&
p
.
getKeyCount
()
>
1
)
{
int
at
=
p
.
getKeyCount
()
/
2
;
int
at
=
p
.
getKeyCount
()
/
2
;
long
totalCount
=
p
.
getTotalCount
();
long
totalCount
=
p
.
getTotalCount
();
Object
k
=
p
.
getKey
(
at
);
Object
k
=
p
.
getKey
(
at
);
...
@@ -118,7 +119,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -118,7 +119,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
index
++;
index
++;
}
}
Page
c
=
p
.
getChildPage
(
index
).
copyOnWrite
(
writeVersion
);
Page
c
=
p
.
getChildPage
(
index
).
copyOnWrite
(
writeVersion
);
if
(
c
.
getMemory
()
>
store
.
get
Max
PageSize
()
&&
c
.
getKeyCount
()
>
1
)
{
if
(
c
.
getMemory
()
>
store
.
getPageSize
()
&&
c
.
getKeyCount
()
>
1
)
{
// split on the way down
// split on the way down
int
at
=
c
.
getKeyCount
()
/
2
;
int
at
=
c
.
getKeyCount
()
/
2
;
Object
k
=
c
.
getKey
(
at
);
Object
k
=
c
.
getKey
(
at
);
...
@@ -957,8 +958,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
...
@@ -957,8 +958,12 @@ public class MVMap<K, V> extends AbstractMap<K, V>
DataUtils
.
appendMap
(
buff
,
"name"
,
name
);
DataUtils
.
appendMap
(
buff
,
"name"
,
name
);
DataUtils
.
appendMap
(
buff
,
"type"
,
getType
());
DataUtils
.
appendMap
(
buff
,
"type"
,
getType
());
DataUtils
.
appendMap
(
buff
,
"createVersion"
,
createVersion
);
DataUtils
.
appendMap
(
buff
,
"createVersion"
,
createVersion
);
if
(
keyType
!=
null
)
{
DataUtils
.
appendMap
(
buff
,
"key"
,
keyType
.
asString
());
DataUtils
.
appendMap
(
buff
,
"key"
,
keyType
.
asString
());
}
if
(
valueType
!=
null
)
{
DataUtils
.
appendMap
(
buff
,
"value"
,
valueType
.
asString
());
DataUtils
.
appendMap
(
buff
,
"value"
,
valueType
.
asString
());
}
return
buff
.
toString
();
return
buff
.
toString
();
}
}
...
...
h2/src/tools/org/h2/dev/store/btree/MVStore.java
浏览文件 @
871b0a8e
...
@@ -19,8 +19,12 @@ import java.util.Iterator;
...
@@ -19,8 +19,12 @@ import java.util.Iterator;
import
java.util.Map
;
import
java.util.Map
;
import
org.h2.compress.CompressLZF
;
import
org.h2.compress.CompressLZF
;
import
org.h2.compress.Compressor
;
import
org.h2.compress.Compressor
;
import
org.h2.dev.store.FilePathCache
;
import
org.h2.dev.store.cache.CacheLongKeyLIRS
;
import
org.h2.dev.store.cache.CacheLongKeyLIRS
;
import
org.h2.dev.store.cache.FilePathCache
;
import
org.h2.dev.store.type.DataType
;
import
org.h2.dev.store.type.DataTypeFactory
;
import
org.h2.dev.store.type.ObjectTypeFactory
;
import
org.h2.dev.store.type.StringType
;
import
org.h2.store.fs.FilePath
;
import
org.h2.store.fs.FilePath
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.store.fs.FileUtils
;
import
org.h2.util.New
;
import
org.h2.util.New
;
...
@@ -36,6 +40,9 @@ header:
...
@@ -36,6 +40,9 @@ header:
H:3,...
H:3,...
TODO:
TODO:
- support serialization by default
- build script
- test concurrent storing in a background thread
- store store creation in file header, and seconds since creation in chunk header (plus a counter)
- store store creation in file header, and seconds since creation in chunk header (plus a counter)
- recovery: keep some old chunks; don't overwritten for 5 minutes (configurable)
- recovery: keep some old chunks; don't overwritten for 5 minutes (configurable)
- allocate memory with Utils.newBytes and so on
- allocate memory with Utils.newBytes and so on
...
@@ -69,9 +76,13 @@ TODO:
...
@@ -69,9 +76,13 @@ TODO:
- triggers (can be implemented with a custom map)
- triggers (can be implemented with a custom map)
- store write operations per page (maybe defragment if much different than count)
- store write operations per page (maybe defragment if much different than count)
- r-tree: nearest neighbor search
- r-tree: nearest neighbor search
- use FileChannel by default (nio file system)
- use FileChannel by default (nio file system)
, but: an interrupt close the FileChannel
- auto-save temporary data if it uses too much memory, but revert it on startup if needed.
- auto-save temporary data if it uses too much memory, but revert it on startup if needed.
- map and chunk metadata: do not store default values
- map and chunk metadata: do not store default values
- support maps without values (non-unique indexes), and maps without keys (counted b-tree)
- use a small object cache (StringCache)
- dump values
- tool to import / manipulate CSV files
*/
*/
...
@@ -92,7 +103,7 @@ public class MVStore {
...
@@ -92,7 +103,7 @@ public class MVStore {
private
final
String
fileName
;
private
final
String
fileName
;
private
final
DataTypeFactory
dataTypeFactory
;
private
final
DataTypeFactory
dataTypeFactory
;
private
int
maxPageSize
=
4
*
1024
;
private
int
pageSize
=
6
*
1024
;
private
FileChannel
file
;
private
FileChannel
file
;
private
FileLock
fileLock
;
private
FileLock
fileLock
;
...
@@ -104,8 +115,7 @@ public class MVStore {
...
@@ -104,8 +115,7 @@ public class MVStore {
* split in 16 segments. The stack move distance is 2% of the expected
* split in 16 segments. The stack move distance is 2% of the expected
* number of entries.
* number of entries.
*/
*/
private
final
CacheLongKeyLIRS
<
Page
>
cache
=
CacheLongKeyLIRS
.
newInstance
(
private
CacheLongKeyLIRS
<
Page
>
cache
;
16
*
1024
*
1024
,
2048
,
16
,
16
*
1024
*
1024
/
2048
*
2
/
100
);
private
int
lastChunkId
;
private
int
lastChunkId
;
private
final
HashMap
<
Integer
,
Chunk
>
chunks
=
New
.
hashMap
();
private
final
HashMap
<
Integer
,
Chunk
>
chunks
=
New
.
hashMap
();
...
@@ -145,12 +155,21 @@ public class MVStore {
...
@@ -145,12 +155,21 @@ public class MVStore {
MVStore
(
HashMap
<
String
,
Object
>
config
)
{
MVStore
(
HashMap
<
String
,
Object
>
config
)
{
this
.
config
=
config
;
this
.
config
=
config
;
this
.
fileName
=
(
String
)
config
.
get
(
"fileName"
);
this
.
fileName
=
(
String
)
config
.
get
(
"fileName"
);
this
.
dataTypeFactory
=
(
DataTypeFactory
)
config
.
get
(
"dataTypeFactory"
);
DataTypeFactory
parent
=
new
ObjectTypeFactory
();
DataTypeFactory
f
=
(
DataTypeFactory
)
config
.
get
(
"dataTypeFactory"
);
if
(
f
==
null
)
{
f
=
parent
;
}
else
{
f
.
setParent
(
parent
);
}
this
.
dataTypeFactory
=
f
;
this
.
readOnly
=
"r"
.
equals
(
config
.
get
(
"openMode"
));
this
.
readOnly
=
"r"
.
equals
(
config
.
get
(
"openMode"
));
this
.
compressor
=
"0"
.
equals
(
config
.
get
(
"compression"
))
?
null
:
new
CompressLZF
();
this
.
compressor
=
"0"
.
equals
(
config
.
get
(
"compression"
))
?
null
:
new
CompressLZF
();
if
(
fileName
!=
null
)
{
Object
s
=
config
.
get
(
"cacheSize"
);
Object
s
=
config
.
get
(
"cacheSize"
);
if
(
s
!=
null
)
{
int
mb
=
s
==
null
?
16
:
Integer
.
parseInt
(
s
.
toString
());
cache
.
setMaxMemory
(
Integer
.
parseInt
(
s
.
toString
())
*
1024
*
1024
);
cache
=
CacheLongKeyLIRS
.
newInstance
(
mb
*
1024
*
1024
,
2048
,
16
,
mb
*
1024
*
1024
/
2048
*
2
/
100
);
}
}
}
}
...
@@ -519,7 +538,7 @@ public class MVStore {
...
@@ -519,7 +538,7 @@ public class MVStore {
return
currentVersion
;
return
currentVersion
;
}
}
// the last chunk was not completely correct in the last s
av
e()
// the last chunk was not completely correct in the last s
tor
e()
// this needs to be updated now (it's better not to update right after
// this needs to be updated now (it's better not to update right after
// storing, because that would modify the meta map again)
// storing, because that would modify the meta map again)
Chunk
c
=
chunks
.
get
(
lastChunkId
);
Chunk
c
=
chunks
.
get
(
lastChunkId
);
...
@@ -944,24 +963,24 @@ public class MVStore {
...
@@ -944,24 +963,24 @@ public class MVStore {
}
}
/**
/**
* Set the
maximum amount of memory a page should contain
, in bytes. Larger
* Set the
amount of memory a page should contain at most
, in bytes. Larger
* pages are split. The default is
4
KB. This is not a limit in the page
* pages are split. The default is
6
KB. This is not a limit in the page
* size
, as pages with one entry can be larger. As a rule of thumb, pages
* size
(pages with one entry can get larger), it is just the point where
*
should not be larger than 1 MB, for caching to work efficiently
.
*
pages are split
.
*
*
* @param
maxP
ageSize the page size
* @param
p
ageSize the page size
*/
*/
public
void
set
MaxPageSize
(
int
maxP
ageSize
)
{
public
void
set
PageSize
(
int
p
ageSize
)
{
this
.
maxPageSize
=
maxP
ageSize
;
this
.
pageSize
=
p
ageSize
;
}
}
/**
/**
* Get the
maximum
page size, in bytes.
* Get the page size, in bytes.
*
*
* @return the
maximum
page size
* @return the page size
*/
*/
public
int
get
Max
PageSize
()
{
public
int
getPageSize
()
{
return
maxP
ageSize
;
return
p
ageSize
;
}
}
Compressor
getCompressor
()
{
Compressor
getCompressor
()
{
...
...
h2/src/tools/org/h2/dev/store/btree/MVStoreBuilder.java
浏览文件 @
871b0a8e
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
package
org
.
h2
.
dev
.
store
.
btree
;
package
org
.
h2
.
dev
.
store
.
btree
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
org.h2.dev.store.type.DataTypeFactory
;
import
org.h2.util.New
;
import
org.h2.util.New
;
/**
/**
...
...
h2/src/tools/org/h2/dev/store/btree/MVStore
Utils
.java
→
h2/src/tools/org/h2/dev/store/btree/MVStore
Tool
.java
浏览文件 @
871b0a8e
...
@@ -19,7 +19,7 @@ import org.h2.store.fs.FileUtils;
...
@@ -19,7 +19,7 @@ import org.h2.store.fs.FileUtils;
/**
/**
* Utility methods used in combination with the MVStore.
* Utility methods used in combination with the MVStore.
*/
*/
public
class
MVStore
Utils
{
public
class
MVStore
Tool
{
/**
/**
* Runs this tool.
* Runs this tool.
...
...
h2/src/tools/org/h2/dev/store/btree/Page.java
浏览文件 @
871b0a8e
...
@@ -11,6 +11,7 @@ import java.nio.ByteBuffer;
...
@@ -11,6 +11,7 @@ import java.nio.ByteBuffer;
import
java.nio.channels.FileChannel
;
import
java.nio.channels.FileChannel
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
org.h2.compress.Compressor
;
import
org.h2.compress.Compressor
;
import
org.h2.dev.store.type.DataType
;
/**
/**
* A page (a node or a leaf).
* A page (a node or a leaf).
...
...
h2/src/tools/org/h2/dev/store/cache/CacheLongKeyLIRS.java
浏览文件 @
871b0a8e
...
@@ -148,7 +148,7 @@ public class CacheLongKeyLIRS<V> {
...
@@ -148,7 +148,7 @@ public class CacheLongKeyLIRS<V> {
* @param key the key (may not be null)
* @param key the key (may not be null)
* @return the old value, or null if there was no resident entry
* @return the old value, or null if there was no resident entry
*/
*/
public
synchronized
V
remove
(
long
key
)
{
public
V
remove
(
long
key
)
{
int
hash
=
getHash
(
key
);
int
hash
=
getHash
(
key
);
return
getSegment
(
hash
).
remove
(
key
,
hash
);
return
getSegment
(
hash
).
remove
(
key
,
hash
);
}
}
...
...
h2/src/tools/org/h2/dev/store/FilePathCache.java
→
h2/src/tools/org/h2/dev/store/
cache/
FilePathCache.java
浏览文件 @
871b0a8e
...
@@ -4,13 +4,12 @@
...
@@ -4,13 +4,12 @@
* (http://h2database.com/html/license.html).
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
* Initial Developer: H2 Group
*/
*/
package
org
.
h2
.
dev
.
store
;
package
org
.
h2
.
dev
.
store
.
cache
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.nio.channels.FileChannel
;
import
java.nio.channels.FileChannel
;
import
java.nio.channels.FileLock
;
import
java.nio.channels.FileLock
;
import
org.h2.dev.store.cache.CacheLongKeyLIRS
;
import
org.h2.store.fs.FileBase
;
import
org.h2.store.fs.FileBase
;
import
org.h2.store.fs.FilePathWrapper
;
import
org.h2.store.fs.FilePathWrapper
;
...
...
h2/src/t
est/org/h2/test/stor
e/MVRTreeMap.java
→
h2/src/t
ools/org/h2/dev/store/rtre
e/MVRTreeMap.java
浏览文件 @
871b0a8e
...
@@ -4,15 +4,15 @@
...
@@ -4,15 +4,15 @@
* (http://h2database.com/html/license.html).
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
* Initial Developer: H2 Group
*/
*/
package
org
.
h2
.
test
.
stor
e
;
package
org
.
h2
.
dev
.
store
.
rtre
e
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
org.h2.dev.store.btree.Cursor
;
import
org.h2.dev.store.btree.Cursor
;
import
org.h2.dev.store.btree.CursorPos
;
import
org.h2.dev.store.btree.CursorPos
;
import
org.h2.dev.store.btree.DataType
;
import
org.h2.dev.store.btree.MVMap
;
import
org.h2.dev.store.btree.MVMap
;
import
org.h2.dev.store.btree.Page
;
import
org.h2.dev.store.btree.Page
;
import
org.h2.dev.store.type.DataType
;
import
org.h2.util.New
;
import
org.h2.util.New
;
/**
/**
...
@@ -50,7 +50,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
...
@@ -50,7 +50,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
checkOpen
();
checkOpen
();
return
new
RTreeCursor
(
this
,
root
,
x
)
{
return
new
RTreeCursor
(
this
,
root
,
x
)
{
protected
boolean
check
(
boolean
leaf
,
SpatialKey
key
,
SpatialKey
test
)
{
protected
boolean
check
(
boolean
leaf
,
SpatialKey
key
,
SpatialKey
test
)
{
return
keyType
.
contains
(
key
,
test
);
return
keyType
.
isOverlap
(
key
,
test
);
}
}
};
};
}
}
...
@@ -201,7 +201,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
...
@@ -201,7 +201,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
Page
p
=
root
.
copyOnWrite
(
writeVersion
);
Page
p
=
root
.
copyOnWrite
(
writeVersion
);
Object
result
;
Object
result
;
if
(
alwaysAdd
||
get
(
key
)
==
null
)
{
if
(
alwaysAdd
||
get
(
key
)
==
null
)
{
if
(
p
.
getMemory
()
>
store
.
get
Max
PageSize
()
&&
p
.
getKeyCount
()
>
1
)
{
if
(
p
.
getMemory
()
>
store
.
getPageSize
()
&&
p
.
getKeyCount
()
>
1
)
{
// only possible if this is the root, else we would have split earlier
// only possible if this is the root, else we would have split earlier
// (this requires maxPageSize is fixed)
// (this requires maxPageSize is fixed)
long
totalCount
=
p
.
getTotalCount
();
long
totalCount
=
p
.
getTotalCount
();
...
@@ -283,7 +283,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
...
@@ -283,7 +283,7 @@ public class MVRTreeMap<V> extends MVMap<SpatialKey, V> {
}
}
}
}
Page
c
=
p
.
getChildPage
(
index
).
copyOnWrite
(
writeVersion
);
Page
c
=
p
.
getChildPage
(
index
).
copyOnWrite
(
writeVersion
);
if
(
c
.
getMemory
()
>
store
.
get
Max
PageSize
()
&&
c
.
getKeyCount
()
>
1
)
{
if
(
c
.
getMemory
()
>
store
.
getPageSize
()
&&
c
.
getKeyCount
()
>
1
)
{
// split on the way down
// split on the way down
Page
split
=
split
(
c
,
writeVersion
);
Page
split
=
split
(
c
,
writeVersion
);
p
=
p
.
copyOnWrite
(
writeVersion
);
p
=
p
.
copyOnWrite
(
writeVersion
);
...
...
h2/src/t
est/org/h2/test/stor
e/SpatialKey.java
→
h2/src/t
ools/org/h2/dev/store/rtre
e/SpatialKey.java
浏览文件 @
871b0a8e
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
* (http://h2database.com/html/license.html).
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
* Initial Developer: H2 Group
*/
*/
package
org
.
h2
.
test
.
stor
e
;
package
org
.
h2
.
dev
.
store
.
rtre
e
;
import
java.util.Arrays
;
import
java.util.Arrays
;
...
...
h2/src/t
est/org/h2/test/stor
e/SpatialType.java
→
h2/src/t
ools/org/h2/dev/store/rtre
e/SpatialType.java
浏览文件 @
871b0a8e
...
@@ -4,12 +4,12 @@
...
@@ -4,12 +4,12 @@
* (http://h2database.com/html/license.html).
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
* Initial Developer: H2 Group
*/
*/
package
org
.
h2
.
test
.
stor
e
;
package
org
.
h2
.
dev
.
store
.
rtre
e
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
org.h2.dev.store.btree.DataType
;
import
org.h2.dev.store.btree.DataUtils
;
import
org.h2.dev.store.btree.DataUtils
;
import
org.h2.dev.store.type.DataType
;
/**
/**
* A spatial data type. This class supports up to 255 dimensions. Each dimension
* A spatial data type. This class supports up to 255 dimensions. Each dimension
...
...
h2/src/tools/org/h2/dev/store/
btre
e/DataType.java
→
h2/src/tools/org/h2/dev/store/
typ
e/DataType.java
浏览文件 @
871b0a8e
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
* (http://h2database.com/html/license.html).
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
* Initial Developer: H2 Group
*/
*/
package
org
.
h2
.
dev
.
store
.
btre
e
;
package
org
.
h2
.
dev
.
store
.
typ
e
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
...
@@ -58,6 +58,9 @@ public interface DataType {
...
@@ -58,6 +58,9 @@ public interface DataType {
/**
/**
* Get the stable string representation that is used to build this data
* Get the stable string representation that is used to build this data
* type.
* type.
* <p>
* To avoid conflict with the default factory, the returned string should
* start with the package name of the type factory.
*
*
* @return the string representation
* @return the string representation
*/
*/
...
...
h2/src/tools/org/h2/dev/store/
btre
e/DataTypeFactory.java
→
h2/src/tools/org/h2/dev/store/
typ
e/DataTypeFactory.java
浏览文件 @
871b0a8e
...
@@ -4,27 +4,36 @@
...
@@ -4,27 +4,36 @@
* (http://h2database.com/html/license.html).
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
* Initial Developer: H2 Group
*/
*/
package
org
.
h2
.
dev
.
store
.
btree
;
package
org
.
h2
.
dev
.
store
.
type
;
/**
/**
* A factory for maps and data types.
* A factory for maps and data types.
*/
*/
public
interface
DataTypeFactory
{
public
interface
DataTypeFactory
{
/**
* Set the parent factory.
*
* @param parent the parent factory
*/
void
setParent
(
DataTypeFactory
parent
);
/**
/**
* Parse the data type.
* Parse the data type.
*
*
* @param dataType the string and type specific meta data
* @param dataType the string and type specific meta data
* @return the type
* @return the type
, or null if unknown
*/
*/
DataType
buildDataType
(
String
dataType
);
DataType
buildDataType
(
String
dataType
);
/**
/**
* Get the data type object for the given class.
* Get the data type identifier for the given class.
* <p>
* To avoid conflict with the default factory, the returned string should
* start with the package name of the type factory.
*
*
* @param objectClass the class
* @param objectClass the class
* @return the data type
object
* @return the data type
identifier, or null if not supported
*/
*/
String
getDataType
(
Class
<?>
objectClass
);
String
getDataType
(
Class
<?>
objectClass
);
...
...
h2/src/t
est/org/h2/test/stor
e/ObjectType.java
→
h2/src/t
ools/org/h2/dev/store/typ
e/ObjectType.java
浏览文件 @
871b0a8e
...
@@ -4,13 +4,12 @@
...
@@ -4,13 +4,12 @@
* (http://h2database.com/html/license.html).
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
* Initial Developer: H2 Group
*/
*/
package
org
.
h2
.
test
.
stor
e
;
package
org
.
h2
.
dev
.
store
.
typ
e
;
import
java.math.BigDecimal
;
import
java.math.BigDecimal
;
import
java.math.BigInteger
;
import
java.math.BigInteger
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.util.UUID
;
import
java.util.UUID
;
import
org.h2.dev.store.btree.DataType
;
import
org.h2.dev.store.btree.DataUtils
;
import
org.h2.dev.store.btree.DataUtils
;
import
org.h2.util.Utils
;
import
org.h2.util.Utils
;
...
@@ -652,7 +651,7 @@ public class ObjectType implements DataType {
...
@@ -652,7 +651,7 @@ public class ObjectType implements DataType {
/**
/**
* The type for long objects.
* The type for long objects.
*/
*/
class
LongType
extends
AutoDetectDataType
{
public
class
LongType
extends
AutoDetectDataType
{
LongType
(
ObjectType
base
)
{
LongType
(
ObjectType
base
)
{
super
(
base
,
TYPE_LONG
);
super
(
base
,
TYPE_LONG
);
...
...
h2/src/t
est/org/h2/test/store/SampleData
TypeFactory.java
→
h2/src/t
ools/org/h2/dev/store/type/Object
TypeFactory.java
浏览文件 @
871b0a8e
...
@@ -3,43 +3,36 @@
...
@@ -3,43 +3,36 @@
* 1.0, and under the Eclipse Public License, Version 1.0
* 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html). Initial Developer: H2 Group
* (http://h2database.com/html/license.html). Initial Developer: H2 Group
*/
*/
package
org
.
h2
.
test
.
stor
e
;
package
org
.
h2
.
dev
.
store
.
typ
e
;
import
org.h2.dev.store.btree.DataType
;
import
org.h2.dev.store.rtree.SpatialType
;
import
org.h2.dev.store.btree.DataTypeFactory
;
import
org.h2.dev.store.btree.StringType
;
/**
/**
* A data type factory.
* A data type factory.
*/
*/
public
class
SampleData
TypeFactory
implements
DataTypeFactory
{
public
class
Object
TypeFactory
implements
DataTypeFactory
{
@Override
@Override
public
DataType
buildDataType
(
String
s
)
{
public
void
setParent
(
DataTypeFactory
parent
)
{
if
(
s
.
length
()
==
0
)
{
// never called for this factory
return
new
StringType
();
}
}
switch
(
s
.
charAt
(
0
))
{
case
'i'
:
@Override
return
new
IntegerType
();
public
DataType
buildDataType
(
String
s
)
{
case
'r'
:
if
(
"s"
.
equals
(
s
))
{
return
RowType
.
fromString
(
s
,
this
);
case
's'
:
return
SpatialType
.
fromString
(
s
);
return
SpatialType
.
fromString
(
s
);
case
'o'
:
}
else
if
(
"o"
.
equals
(
s
))
{
return
new
ObjectType
();
return
new
ObjectType
();
}
}
throw
new
RuntimeException
(
"Unknown data type "
+
s
)
;
return
null
;
}
}
@Override
@Override
public
String
getDataType
(
Class
<?>
objectClass
)
{
public
String
getDataType
(
Class
<?>
objectClass
)
{
if
(
objectClass
==
Integer
.
class
)
{
if
(
objectClass
==
SpatialType
.
class
)
{
return
"i"
;
return
"s"
;
}
else
if
(
Object
.
class
==
Object
.
class
)
{
return
"o"
;
}
}
throw
new
RuntimeException
(
"Unsupported object class "
+
objectClass
.
toString
())
;
return
"o"
;
}
}
}
}
h2/src/tools/org/h2/dev/store/
btre
e/StringType.java
→
h2/src/tools/org/h2/dev/store/
typ
e/StringType.java
浏览文件 @
871b0a8e
...
@@ -4,9 +4,10 @@
...
@@ -4,9 +4,10 @@
* (http://h2database.com/html/license.html).
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
* Initial Developer: H2 Group
*/
*/
package
org
.
h2
.
dev
.
store
.
btre
e
;
package
org
.
h2
.
dev
.
store
.
typ
e
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
org.h2.dev.store.btree.DataUtils
;
/**
/**
* A string type.
* A string type.
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论