Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
900b5667
提交
900b5667
authored
11月 06, 2013
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
MVStore: simpler API
上级
e845504a
隐藏空白字符变更
内嵌
并排
正在显示
11 个修改的文件
包含
179 行增加
和
196 行删除
+179
-196
changelog.html
h2/src/docsrc/html/changelog.html
+1
-0
MVStore.java
h2/src/main/org/h2/mvstore/MVStore.java
+110
-140
OffHeapStore.java
h2/src/main/org/h2/mvstore/OffHeapStore.java
+1
-2
MVTableEngine.java
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
+2
-2
TransactionStore.java
h2/src/main/org/h2/mvstore/db/TransactionStore.java
+7
-6
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+3
-3
TestConcurrent.java
h2/src/test/org/h2/test/store/TestConcurrent.java
+9
-8
TestMVStore.java
h2/src/test/org/h2/test/store/TestMVStore.java
+28
-28
TestMVStoreBenchmark.java
h2/src/test/org/h2/test/store/TestMVStoreBenchmark.java
+6
-2
TestMVTableEngine.java
h2/src/test/org/h2/test/store/TestMVTableEngine.java
+1
-1
TestTransactionStore.java
h2/src/test/org/h2/test/store/TestTransactionStore.java
+11
-4
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
900b5667
...
...
@@ -23,6 +23,7 @@ Change Log
</li><li>
Issue 73: MySQL compatibility: support REPLACE, patch by Cemo Koc.
</li><li>
The spatial index now works in MVCC mode when using the MVStore storage.
</li><li>
MVStore: concurrency problems have been fixed.
The API has been simplified.
</li><li>
Improve error message when dropping an index that belongs to a constraint,
specify constraint in error message.
</li><li>
Issue 518: java.sql.Connection.commit() freezes after LOB modification with EXCLUSIVE connection
...
...
h2/src/main/org/h2/mvstore/MVStore.java
浏览文件 @
900b5667
...
...
@@ -59,7 +59,7 @@ TransactionStore:
MVStore:
- automated 'kill process' and 'power failure' test
- update checkstyle
- auto-compact from time to time and on close
-
feature to
auto-compact from time to time and on close
- test and possibly improve compact operation (for large dbs)
- possibly split chunk metadata into immutable and mutable
- compact: avoid processing pages using a counting bloom filter
...
...
@@ -115,6 +115,19 @@ MVStore:
- support log structured merge style operations (blind writes)
using one map per level plus bloom filter
- have a strict call order MVStore -> MVMap -> Page -> FileStore
- autocommit mode (default) and manual mode
- manual mode: combine commit and store;
rollback only to chunk
- rename writeDelay to commitDelay, default 1 s
- rollback() to rollback to the latest commit; throws exception
in autocommit mode
- fix documentation (including examples)
- autocommit commits, stores, and compacts from time to time;
the background thread should wait at least 90% of the
configured write delay to store changes
- currently, uncommitted changes are stored if there are many transient changes,
and rolled back when opening - is this really needed?
- compact* should also store uncommitted changes (if there are any)
*/
...
...
@@ -141,6 +154,7 @@ public class MVStore {
* The background thread, if any.
*/
volatile
Thread
backgroundThread
;
final
Object
backgroundThreadSync
=
new
Object
();
private
volatile
boolean
reuseSpace
=
true
;
...
...
@@ -176,9 +190,9 @@ public class MVStore {
new
ConcurrentHashMap
<
Long
,
HashMap
<
Integer
,
Chunk
>>();
/**
* The metadata map.
* The metadata map.
Write access to this map needs to be synchronized on the store.
*/
private
MVMap
Concurrent
<
String
,
String
>
meta
;
private
MVMap
<
String
,
String
>
meta
;
private
final
ConcurrentHashMap
<
Integer
,
MVMap
<?,
?>>
maps
=
new
ConcurrentHashMap
<
Integer
,
MVMap
<?,
?>>();
...
...
@@ -208,6 +222,12 @@ public class MVStore {
*/
private
long
lastStoredVersion
;
/**
* The estimated number of unsaved pages
* (this number may not be completely accurate,
* because it may be changed concurrently, and
* because temporary pages are counted)
*/
private
int
unsavedPageCount
;
private
int
unsavedPageCountMax
;
private
boolean
storeNeeded
;
...
...
@@ -220,11 +240,6 @@ public class MVStore {
private
long
lastStoreTime
;
/**
* To which version to roll back when opening the store after a crash.
*/
private
long
lastCommittedVersion
;
/**
* The earliest chunk to retain, if any.
*/
...
...
@@ -234,6 +249,8 @@ public class MVStore {
* The version of the current store operation (if any).
*/
private
volatile
long
currentStoreVersion
=
-
1
;
private
Thread
currentStoreThread
;
private
volatile
boolean
metaChanged
;
...
...
@@ -256,7 +273,7 @@ public class MVStore {
pageSplitSize
=
o
==
null
?
6
*
1024
:
(
Integer
)
o
;
o
=
config
.
get
(
"backgroundExceptionHandler"
);
this
.
backgroundExceptionHandler
=
(
UncaughtExceptionHandler
)
o
;
meta
=
new
MVMap
Concurrent
<
String
,
String
>(
StringDataType
.
INSTANCE
,
StringDataType
.
INSTANCE
);
meta
=
new
MVMap
<
String
,
String
>(
StringDataType
.
INSTANCE
,
StringDataType
.
INSTANCE
);
HashMap
<
String
,
String
>
c
=
New
.
hashMap
();
c
.
put
(
"id"
,
"0"
);
c
.
put
(
"createVersion"
,
Long
.
toString
(
currentVersion
));
...
...
@@ -320,10 +337,6 @@ public class MVStore {
readMeta
();
}
}
long
rollback
=
DataUtils
.
parseLong
(
meta
.
get
(
"rollbackOnOpen"
),
-
1
);
if
(
rollback
!=
-
1
)
{
rollbackTo
(
rollback
);
}
}
catch
(
IllegalStateException
e
)
{
try
{
closeStore
(
false
);
...
...
@@ -337,7 +350,6 @@ public class MVStore {
}
}
lastStoreTime
=
getTime
();
this
.
lastCommittedVersion
=
currentVersion
;
// setWriteDelay starts the thread, but only if
// the parameter is different than the current value
...
...
@@ -403,7 +415,7 @@ public class MVStore {
* @param builder the map builder
* @return the map
*/
public
<
M
extends
MVMap
<
K
,
V
>,
K
,
V
>
M
openMap
(
String
name
,
MVMap
.
MapBuilder
<
M
,
K
,
V
>
builder
)
{
public
synchronized
<
M
extends
MVMap
<
K
,
V
>,
K
,
V
>
M
openMap
(
String
name
,
MVMap
.
MapBuilder
<
M
,
K
,
V
>
builder
)
{
checkOpen
();
String
x
=
meta
.
get
(
"name."
+
name
);
int
id
;
...
...
@@ -445,17 +457,17 @@ public class MVStore {
* Get the metadata map. This data is for informational purposes only. The
* data is subject to change in future versions.
* <p>
* The data
should not be modified (doing so may corrupt the store). Writing
*
to it is not always detected as a modification, so that changes to it
*
might not be stored
.
* The data
in this map should not be modified (changing system data may
*
corrupt the store). If modifications are needed, they need be
*
synchronized on the store
.
* <p>
* It contains the following entries:
*
* The metadata map contains the following entries:
* <pre>
* chunk.{chunkId} = {chunk metadata}
* name.{name} = {mapId}
* map.{mapId} = {map metadata}
* root.{mapId} = {root position}
*
chunk.{chunkId} = {chunk metadata
}
*
setting.storeVersion = {version
}
* </pre>
*
* @return the metadata map
...
...
@@ -636,9 +648,8 @@ public class MVStore {
}
/**
* Close the file and the store. If there are any committed but unsaved
* changes, they are written to disk first. If any temporary data was
* written but not committed, this is rolled back. All open maps are closed.
* Close the file and the store. If there are any uncommitted changes, they
* are written to disk first. All open maps are closed.
* <p>
* It is not allowed to concurrently call close and store.
*/
...
...
@@ -648,18 +659,8 @@ public class MVStore {
}
if
(
fileStore
!=
null
&&
!
fileStore
.
isReadOnly
())
{
stopBackgroundThread
();
if
(
currentStoreVersion
>=
0
)
{
// in this case, store is called manually in another thread
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_WRITING_FAILED
,
"Can not close while storing"
);
}
if
(
hasUnsavedChanges
()
||
lastCommittedVersion
!=
currentVersion
)
{
rollbackTo
(
lastCommittedVersion
);
metaChanged
=
true
;
store
(
false
);
if
(
hasUnsavedChanges
())
{
store
();
}
}
closeStore
(
true
);
...
...
@@ -739,17 +740,6 @@ public class MVStore {
return
c
;
}
/**
* Increment the current version, without committing the changes.
*
* @return the new version
*/
public
long
incrementVersion
()
{
long
v
=
++
currentVersion
;
setWriteVersion
(
v
);
return
v
;
}
private
void
setWriteVersion
(
long
version
)
{
for
(
MVMap
<?,
?>
map
:
maps
.
values
())
{
map
.
setWriteVersion
(
version
);
...
...
@@ -768,11 +758,11 @@ public class MVStore {
* @return the new version
*/
public
long
commit
()
{
long
v
=
incrementVersion
();
lastCommittedVersion
=
v
;
if
(
writeDelay
==
0
)
{
store
(
false
);
if
(
fileStore
!=
null
)
{
return
store
();
}
long
v
=
++
currentVersion
;
setWriteVersion
(
v
);
return
v
;
}
...
...
@@ -781,29 +771,17 @@ public class MVStore {
* there are no unsaved changes, otherwise it increments the current version
* and stores the data (for file based stores).
* <p>
*
O
ne store operation may run at any time.
*
At most o
ne store operation may run at any time.
*
* @return the new version (incremented if there were changes)
*/
public
long
store
()
{
checkOpen
();
return
store
(
false
);
}
/**
* Store changes. Changes that are marked as temporary are rolled back after
* a restart.
*
* @param temp whether the changes are only temporary (not committed), and
* should be rolled back after a crash
* @return the new version (incremented if there were changes)
*/
private
synchronized
long
store
(
boolean
temp
)
{
public
synchronized
long
store
()
{
if
(
closed
)
{
return
currentVersion
;
}
if
(
fileStore
==
null
)
{
return
incrementVersion
();
throw
DataUtils
.
newIllegalStateException
(
DataUtils
.
ERROR_WRITING_FAILED
,
"This is an in-memory store"
);
}
if
(
currentStoreVersion
>=
0
)
{
// store is possibly called within store, if the meta map changed
...
...
@@ -818,37 +796,24 @@ public class MVStore {
}
try
{
currentStoreVersion
=
currentVersion
;
return
storeNow
(
temp
);
currentStoreThread
=
Thread
.
currentThread
();
return
storeNow
();
}
finally
{
// in any case reset the current store version,
// to allow closing the store
currentStoreVersion
=
-
1
;
currentStoreThread
=
null
;
}
}
private
long
storeNow
(
boolean
temp
)
{
private
long
storeNow
()
{
int
currentUnsavedPageCount
=
unsavedPageCount
;
long
storeVersion
=
currentStoreVersion
;
long
version
=
++
currentVersion
;
setWriteVersion
(
version
);
long
time
=
getTime
();
lastStoreTime
=
time
;
if
(
temp
)
{
meta
.
put
(
"rollbackOnOpen"
,
Long
.
toString
(
lastCommittedVersion
));
// find the oldest chunk to retain
long
minVersion
=
Long
.
MAX_VALUE
;
Chunk
minChunk
=
null
;
for
(
Chunk
c
:
chunks
.
values
())
{
if
(
c
.
version
<
minVersion
)
{
minVersion
=
c
.
version
;
minChunk
=
c
;
}
}
retainChunk
=
minChunk
;
}
else
{
lastCommittedVersion
=
version
;
meta
.
remove
(
"rollbackOnOpen"
);
retainChunk
=
null
;
}
retainChunk
=
null
;
// the last chunk was not completely correct in the last store()
// this needs to be updated now (it's better not to update right after
...
...
@@ -983,10 +948,9 @@ public class MVStore {
// some pages might have been changed in the meantime (in the newest version)
unsavedPageCount
=
Math
.
max
(
0
,
unsavedPageCount
-
currentUnsavedPageCount
);
if
(!
temp
)
{
metaChanged
=
false
;
lastStoredVersion
=
storeVersion
;
}
metaChanged
=
false
;
lastStoredVersion
=
storeVersion
;
return
version
;
}
...
...
@@ -1053,7 +1017,7 @@ public class MVStore {
if
(
v
>
storeVersion
)
{
continue
;
}
Map
<
Integer
,
Chunk
>
freed
=
e
.
getValue
();
Hash
Map
<
Integer
,
Chunk
>
freed
=
e
.
getValue
();
for
(
Chunk
f
:
freed
.
values
())
{
Chunk
c
=
chunks
.
get
(
f
.
id
);
if
(
c
==
null
)
{
...
...
@@ -1146,6 +1110,9 @@ public class MVStore {
* @return if there are any changes
*/
public
boolean
hasUnsavedChanges
()
{
;
// TODO maybe private; rename to hasUncommittedChanges
checkOpen
();
if
(
metaChanged
)
{
return
true
;
...
...
@@ -1281,7 +1248,7 @@ public class MVStore {
}
/**
* Force all changes to be written to the storage. The default
* Force all
stored
changes to be written to the storage. The default
* implementation calls FileChannel.force(true).
*/
public
void
sync
()
{
...
...
@@ -1484,11 +1451,13 @@ public class MVStore {
Chunk
c
=
getChunk
(
pos
);
long
version
=
currentVersion
;
if
(
map
==
meta
&&
currentStoreVersion
>=
0
)
{
// if the meta map is modified while storing,
// then this freed page needs to be registered
// with the stored chunk, so that the old chunk
// can be re-used
version
=
currentStoreVersion
;
if
(
Thread
.
currentThread
()
==
currentStoreThread
)
{
// if the meta map is modified while storing,
// then this freed page needs to be registered
// with the stored chunk, so that the old chunk
// can be re-used
version
=
currentStoreVersion
;
}
}
registerFreePage
(
version
,
c
.
id
,
DataUtils
.
getPageMaxLength
(
pos
),
1
);
}
...
...
@@ -1663,10 +1632,9 @@ public class MVStore {
}
/**
* Get the maximum number of unsaved pages. If this number is exceeded,
* the unsaved changes are stored to disk, including uncommitted changes.
* Saved uncommitted changes are rolled back when opening the store.
*
* Get the maximum number of unsaved pages. If this number is exceeded, the
* unsaved changes are stored to disk.
*
* @return the number of maximum unsaved pages
*/
public
int
getUnsavedPageCountMax
()
{
...
...
@@ -1677,8 +1645,8 @@ public class MVStore {
* Increment the number of unsaved pages.
*/
void
registerUnsavedPage
()
{
unsavedPageCount
++
;
if
(
unsavedPageC
ount
>
unsavedPageCountMax
&&
unsavedPageCountMax
>
0
)
{
int
count
=
++
unsavedPageCount
;
if
(
c
ount
>
unsavedPageCountMax
&&
unsavedPageCountMax
>
0
)
{
storeNeeded
=
true
;
}
}
...
...
@@ -1689,7 +1657,7 @@ public class MVStore {
void
beforeWrite
()
{
if
(
storeNeeded
)
{
storeNeeded
=
false
;
store
(
true
);
store
();
}
}
...
...
@@ -1711,11 +1679,21 @@ public class MVStore {
*
* @param version the new store version
*/
public
void
setStoreVersion
(
int
version
)
{
public
synchronized
void
setStoreVersion
(
int
version
)
{
checkOpen
();
markMetaChanged
();
meta
.
put
(
"setting.storeVersion"
,
Integer
.
toString
(
version
));
}
/**
* Revert to the beginning of the current version.
*/
public
void
rollback
()
{
;
// TODO document and test
rollbackTo
(
currentVersion
);
}
/**
* Revert to the beginning of the given version. All later changes (stored
...
...
@@ -1741,7 +1719,6 @@ public class MVStore {
freedPageSpace
.
clear
();
currentVersion
=
version
;
setWriteVersion
(
version
);
lastCommittedVersion
=
version
;
metaChanged
=
false
;
return
;
}
...
...
@@ -1816,12 +1793,10 @@ public class MVStore {
// rollback might have rolled back the stored chunk metadata as well
Chunk
c
=
chunks
.
get
(
lastChunkId
-
1
);
if
(
c
!=
null
)
{
markMetaChanged
();
meta
.
put
(
"chunk."
+
c
.
id
,
c
.
asString
());
}
currentVersion
=
version
;
setWriteVersion
(
version
);
lastCommittedVersion
=
version
;
}
private
void
revertTemp
(
long
storeVersion
)
{
...
...
@@ -1847,15 +1822,6 @@ public class MVStore {
return
currentVersion
;
}
/**
* Get the last committed version.
*
* @return the version
*/
public
long
getCommittedVersion
()
{
return
lastCommittedVersion
;
}
/**
* Get the file store.
*
...
...
@@ -1889,7 +1855,7 @@ public class MVStore {
* @param map the map
* @param newName the new name
*/
public
void
renameMap
(
MVMap
<?,
?>
map
,
String
newName
)
{
public
synchronized
void
renameMap
(
MVMap
<?,
?>
map
,
String
newName
)
{
checkOpen
();
DataUtils
.
checkArgument
(
map
!=
meta
,
"Renaming the meta map is not allowed"
);
...
...
@@ -1912,7 +1878,7 @@ public class MVStore {
*
* @param map the map
*/
public
void
removeMap
(
MVMap
<?,
?>
map
)
{
public
synchronized
void
removeMap
(
MVMap
<?,
?>
map
)
{
checkOpen
();
DataUtils
.
checkArgument
(
map
!=
meta
,
"Removing the meta map is not allowed"
);
...
...
@@ -1932,7 +1898,7 @@ public class MVStore {
* @param id the map id
* @return the name
*/
String
getMapName
(
int
id
)
{
synchronized
String
getMapName
(
int
id
)
{
String
m
=
meta
.
get
(
"map."
+
id
);
return
DataUtils
.
parseMap
(
m
).
get
(
"name"
);
}
...
...
@@ -1941,14 +1907,13 @@ public class MVStore {
* Store all unsaved changes, if there are any that are committed.
*/
void
storeInBackground
()
{
if
(
closed
||
unsavedPageCount
==
0
)
{
if
(
unsavedPageCount
==
0
||
closed
)
{
return
;
}
// could also store when there are many unsaved pages,
// but according to a test it doesn't really help
if
(
lastStoredVersion
>=
lastCommittedVersion
)
{
return
;
}
long
time
=
getTime
();
if
(
time
<=
lastStoreTime
+
writeDelay
)
{
return
;
...
...
@@ -1957,7 +1922,7 @@ public class MVStore {
return
;
}
try
{
store
(
true
);
store
();
}
catch
(
Exception
e
)
{
if
(
backgroundExceptionHandler
!=
null
)
{
backgroundExceptionHandler
.
uncaughtException
(
null
,
e
);
...
...
@@ -1981,13 +1946,13 @@ public class MVStore {
}
private
void
stopBackgroundThread
()
{
if
(
backgroundThread
==
null
)
{
Thread
t
=
backgroundThread
;
if
(
t
==
null
)
{
return
;
}
Thread
t
=
backgroundThread
;
backgroundThread
=
null
;
synchronized
(
this
)
{
notify
();
synchronized
(
backgroundThreadSync
)
{
backgroundThreadSync
.
notifyAll
();
}
try
{
t
.
join
();
...
...
@@ -1997,13 +1962,12 @@ public class MVStore {
}
/**
* Set the maximum delay in milliseconds to store committed changes (for
* file-based stores).
* Set the maximum delay in milliseconds to commit changes.
* <p>
* The default is 1000, meaning c
ommitted changes are stor
ed after at
* The default is 1000, meaning c
hanges are committ
ed after at
* most one second.
* <p>
* When the value is set to -1, c
ommitted c
hanges are only written when
* When the value is set to -1, changes are only written when
* calling the store method. When the value is set to 0, committed
* changes are immediately written on a commit, but please note this
* decreases performance and does still not guarantee the disk will
...
...
@@ -2012,6 +1976,8 @@ public class MVStore {
* @param millis the maximum delay
*/
public
void
setWriteDelay
(
int
millis
)
{
;
// TODO rename to commitDelay
if
(
writeDelay
==
millis
)
{
return
;
}
...
...
@@ -2050,12 +2016,17 @@ public class MVStore {
@Override
public
void
run
()
{
while
(
store
.
backgroundThread
!=
null
)
{
synchronized
(
store
)
{
while
(
true
)
{
Thread
t
=
store
.
backgroundThread
;
if
(
t
==
null
)
{
break
;
}
Object
sync
=
store
.
backgroundThreadSync
;
synchronized
(
sync
)
{
try
{
s
tore
.
wait
(
sleep
);
s
ync
.
wait
(
sleep
);
}
catch
(
InterruptedException
e
)
{
// ignore
continue
;
}
}
store
.
storeInBackground
();
...
...
@@ -2145,9 +2116,8 @@ public class MVStore {
/**
* Set the size of the write buffer, in MB (for file-based stores).
* Changes are automatically stored if the buffer grows larger than
* this. However, unless the changes are committed later on, they are
* rolled back when opening the store.
* Unless auto-commit is disabled, changes are automatically stored if
* the buffer grows larger than this.
* <p>
* The default is 4 MB.
* <p>
...
...
h2/src/main/org/h2/mvstore/OffHeapStore.java
浏览文件 @
900b5667
...
...
@@ -121,8 +121,7 @@ public class OffHeapStore extends FileStore {
@Override
public
void
close
()
{
truncate
(
0
);
freeSpace
.
clear
();
// do nothing (keep the data until it is garbage collected)
}
@Override
...
...
h2/src/main/org/h2/mvstore/db/MVTableEngine.java
浏览文件 @
900b5667
...
...
@@ -260,7 +260,7 @@ public class MVTableEngine implements TableEngine {
public
void
compactFile
(
long
maxCompactTime
)
{
store
.
setRetentionTime
(
0
);
long
start
=
System
.
currentTimeMillis
();
while
(
store
.
compact
(
9
0
))
{
while
(
store
.
compact
(
9
9
))
{
store
.
sync
();
long
time
=
System
.
currentTimeMillis
()
-
start
;
if
(
time
>
maxCompactTime
)
{
...
...
@@ -280,7 +280,7 @@ public class MVTableEngine implements TableEngine {
public
void
close
(
long
maxCompactTime
)
{
if
(!
store
.
isClosed
()
&&
store
.
getFileStore
()
!=
null
)
{
if
(!
store
.
getFileStore
().
isReadOnly
())
{
store
.
stor
e
();
transactionStore
.
clos
e
();
long
start
=
System
.
currentTimeMillis
();
while
(
store
.
compact
(
90
))
{
long
time
=
System
.
currentTimeMillis
()
-
start
;
...
...
h2/src/main/org/h2/mvstore/db/TransactionStore.java
浏览文件 @
900b5667
...
...
@@ -170,7 +170,9 @@ public class TransactionStore {
public
synchronized
void
close
()
{
// to avoid losing transaction ids
settings
.
put
(
LAST_TRANSACTION_ID
,
""
+
lastTransactionId
);
store
.
store
();
if
(
store
.
getFileStore
()
!=
null
)
{
store
.
store
();
}
}
/**
...
...
@@ -191,7 +193,6 @@ public class TransactionStore {
private
void
commitIfNeeded
()
{
if
(
store
.
getUnsavedPageCount
()
>
MAX_UNSAVED_PAGES
)
{
if
(
store
.
getFileStore
()
!=
null
)
{
store
.
commit
();
store
.
store
();
}
}
...
...
@@ -354,10 +355,10 @@ public class TransactionStore {
firstOpenTransaction
=
-
1
;
}
if
(
store
.
getWriteDelay
()
==
0
)
{
if
(
store
.
getFileStore
()
=
=
null
)
{
return
;
if
(
store
.
getFileStore
()
!
=
null
)
{
store
.
store
()
;
}
store
.
commit
()
;
return
;
}
// to avoid having to store the transaction log,
// if there is no open transaction,
...
...
@@ -1207,7 +1208,7 @@ public class TransactionStore {
*/
public
Iterator
<
K
>
keyIterator
(
K
from
,
boolean
includeUncommitted
)
{
Cursor
<
K
>
it
=
map
.
keyIterator
(
from
);
return
wrapIterator
(
it
,
false
);
return
wrapIterator
(
it
,
includeUncommitted
);
}
/**
...
...
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
900b5667
...
...
@@ -470,18 +470,18 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
prof
.
interval
=
1
;
prof
.
startCollecting
();
if
(
test
.
mvStore
)
{
TestPerformance
.
main
(
"-init"
,
"-db"
,
"9"
,
"-size"
,
"1000
0
"
);
TestPerformance
.
main
(
"-init"
,
"-db"
,
"9"
,
"-size"
,
"1000"
);
}
else
{
TestPerformance
.
main
(
"-init"
,
"-db"
,
"1"
);
}
prof
.
stopCollecting
();
System
.
out
.
println
(
prof
.
getTop
(
3
));
System
.
out
.
println
(
prof
.
getTop
(
3
0
));
if
(
test
.
mvStore
)
{
prof
=
new
Profiler
();
prof
.
depth
=
16
;
prof
.
interval
=
1
;
prof
.
startCollecting
();
TestPerformance
.
main
(
"-init"
,
"-db"
,
"1"
,
"-size"
,
"1000
0
"
);
TestPerformance
.
main
(
"-init"
,
"-db"
,
"1"
,
"-size"
,
"1000"
);
prof
.
stopCollecting
();
System
.
out
.
println
(
prof
.
getTop
(
3
));
}
...
...
h2/src/test/org/h2/test/store/TestConcurrent.java
浏览文件 @
900b5667
...
...
@@ -43,7 +43,6 @@ public class TestConcurrent extends TestMVStore {
@Override
public
void
test
()
throws
Exception
{
FileUtils
.
deleteRecursive
(
getBaseDir
(),
true
);
FileUtils
.
createDirectories
(
getBaseDir
());
FileUtils
.
deleteRecursive
(
"memFS:"
,
false
);
...
...
@@ -110,7 +109,7 @@ public class TestConcurrent extends TestMVStore {
m
.
clear
();
s
.
removeMap
(
m
);
if
(
x
%
5
==
0
)
{
s
.
incrementVersion
();
s
.
commit
();
}
}
task
.
get
();
...
...
@@ -124,9 +123,9 @@ public class TestConcurrent extends TestMVStore {
}
}
assertEquals
(
1
,
chunkCount
);
s
.
close
();
}
FileUtils
.
deleteRecursive
(
"memFS:"
,
false
);
}
private
void
testConcurrentStoreAndRemoveMap
()
throws
InterruptedException
{
...
...
@@ -159,6 +158,7 @@ public class TestConcurrent extends TestMVStore {
}
task
.
get
();
s
.
close
();
FileUtils
.
deleteRecursive
(
"memFS:"
,
false
);
}
private
void
testConcurrentStoreAndClose
()
throws
InterruptedException
{
...
...
@@ -200,6 +200,7 @@ public class TestConcurrent extends TestMVStore {
}
s
.
close
();
}
FileUtils
.
deleteRecursive
(
"memFS:"
,
false
);
}
/**
...
...
@@ -249,7 +250,7 @@ public class TestConcurrent extends TestMVStore {
}
m
.
get
(
rand
.
nextInt
(
size
));
}
s
.
incrementVersion
();
s
.
commit
();
Thread
.
sleep
(
1
);
}
task
.
get
();
...
...
@@ -341,7 +342,7 @@ public class TestConcurrent extends TestMVStore {
for
(
int
k
=
0
;
k
<
10000
;
k
++)
{
Iterator
<
Integer
>
it
=
map
.
keyIterator
(
r
.
nextInt
(
len
));
long
old
=
s
.
getCurrentVersion
();
s
.
incrementVersion
();
s
.
commit
();
s
.
setRetainVersion
(
old
-
100
);
while
(
map
.
getVersion
()
==
old
)
{
Thread
.
yield
();
...
...
@@ -423,7 +424,7 @@ public class TestConcurrent extends TestMVStore {
notDetected
.
incrementAndGet
();
}
}
s
.
incrementVersion
();
s
.
commit
();
Thread
.
sleep
(
1
);
}
task
.
get
();
...
...
@@ -438,7 +439,7 @@ public class TestConcurrent extends TestMVStore {
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
m
.
put
(
i
,
x
);
}
s
.
incrementVersion
();
s
.
commit
();
Task
task
=
new
Task
()
{
@Override
public
void
call
()
throws
Exception
{
...
...
@@ -462,7 +463,7 @@ public class TestConcurrent extends TestMVStore {
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
m
.
put
(
i
,
x
);
}
s
.
incrementVersion
();
s
.
commit
();
Thread
.
sleep
(
1
);
}
task
.
get
();
...
...
h2/src/test/org/h2/test/store/TestMVStore.java
浏览文件 @
900b5667
...
...
@@ -148,7 +148,7 @@ public class TestMVStore extends TestBase {
s
.
store
();
}
assertTrue
(
1000
<
offHeap
.
getWriteCount
());
//
s.close();
s
.
close
();
s
=
new
MVStore
.
Builder
().
fileStore
(
offHeap
).
...
...
@@ -253,7 +253,6 @@ public class TestMVStore extends TestBase {
m
=
s
.
openMap
(
"data"
);
s
.
getFileStore
().
getFile
().
close
();
m
.
put
(
1
,
"Hello"
);
s
.
commit
();
for
(
int
i
=
0
;
i
<
100
;
i
++)
{
if
(
exRef
.
get
()
!=
null
)
{
break
;
...
...
@@ -330,19 +329,19 @@ public class TestMVStore extends TestBase {
fileName
(
fileName
).
open
();
m
=
s
.
openMap
(
"data"
);
assert
Fals
e
(
m
.
containsKey
(
1
));
assert
Tru
e
(
m
.
containsKey
(
1
));
m
.
put
(
1
,
data
);
s
.
commit
();
m
.
put
(
2
,
data
);
m
.
put
(
-
1
,
data
);
s
.
store
();
m
.
put
(
-
2
,
data
);
s
.
close
();
s
=
new
MVStore
.
Builder
().
fileName
(
fileName
).
open
();
m
=
s
.
openMap
(
"data"
);
assertTrue
(
m
.
containsKey
(
1
));
assert
False
(
m
.
containsKey
(
2
));
assertTrue
(
m
.
containsKey
(
-
1
));
assert
True
(
m
.
containsKey
(-
2
));
s
.
close
();
FileUtils
.
delete
(
fileName
);
...
...
@@ -377,7 +376,7 @@ public class TestMVStore extends TestBase {
m
.
put
(
1
,
"Hello"
);
s
.
store
();
long
v
=
s
.
getCurrentVersion
();
m
.
put
(
2
,
"World"
);
m
.
put
(
2
,
"World
.
"
);
Thread
.
sleep
(
5
);
// must not store, as nothing has been committed yet
s
.
closeImmediately
();
...
...
@@ -386,9 +385,11 @@ public class TestMVStore extends TestBase {
open
();
s
.
setWriteDelay
(
1
);
m
=
s
.
openMap
(
"data"
);
assertEquals
(
null
,
m
.
get
(
2
));
assertEquals
(
"World."
,
m
.
get
(
2
));
m
.
put
(
2
,
"World"
);
s
.
commit
();
s
.
store
();
v
=
s
.
getCurrentVersion
();
m
.
put
(
3
,
"!"
);
for
(
int
i
=
100
;
i
>
0
;
i
--)
{
...
...
@@ -400,7 +401,7 @@ public class TestMVStore extends TestBase {
}
Thread
.
sleep
(
1
);
}
s
.
close
();
s
.
close
Immediately
();
s
=
new
MVStore
.
Builder
().
fileName
(
fileName
).
...
...
@@ -408,7 +409,7 @@ public class TestMVStore extends TestBase {
m
=
s
.
openMap
(
"data"
);
assertEquals
(
"Hello"
,
m
.
get
(
1
));
assertEquals
(
"World"
,
m
.
get
(
2
));
assert
False
(
m
.
containsKey
(
3
));
assert
Equals
(
"!"
,
m
.
get
(
3
));
s
.
close
();
FileUtils
.
delete
(
fileName
);
...
...
@@ -517,7 +518,7 @@ public class TestMVStore extends TestBase {
MVMap
<
Integer
,
Integer
>
map
;
map
=
s
.
openMap
(
"hello"
);
map
.
put
(
1
,
10
);
long
old
=
s
.
incrementVersion
();
long
old
=
s
.
commit
();
s
.
renameMap
(
map
,
"world"
);
map
.
put
(
2
,
20
);
assertEquals
(
"world"
,
map
.
getName
());
...
...
@@ -557,7 +558,7 @@ public class TestMVStore extends TestBase {
s
.
store
();
s
.
close
();
int
[]
expectedReadsForCacheSize
=
{
3405
,
2590
,
1924
,
1440
,
110
3
,
956
,
918
3405
,
2590
,
1924
,
1440
,
110
8
,
956
,
918
};
for
(
int
cacheSize
=
0
;
cacheSize
<=
6
;
cacheSize
+=
4
)
{
s
=
new
MVStore
.
Builder
().
...
...
@@ -816,8 +817,10 @@ public class TestMVStore extends TestBase {
MVStore
s
=
MVStore
.
open
(
fileName
);
assertEquals
(
0
,
s
.
getCurrentVersion
());
assertEquals
(
0
,
s
.
getStoreVersion
());
s
.
setStoreVersion
(
0
);
s
.
store
();
s
.
setStoreVersion
(
1
);
s
.
close
();
s
.
close
Immediately
();
s
=
MVStore
.
open
(
fileName
);
assertEquals
(
1
,
s
.
getCurrentVersion
());
assertEquals
(
0
,
s
.
getStoreVersion
());
...
...
@@ -840,7 +843,7 @@ public class TestMVStore extends TestBase {
map
.
put
(
i
,
10
*
i
);
}
Iterator
<
Integer
>
it
=
map
.
keySet
().
iterator
();
s
.
incrementVersion
();
s
.
commit
();
for
(
int
i
=
0
;
i
<
len
;
i
+=
2
)
{
map
.
remove
(
i
);
}
...
...
@@ -916,7 +919,7 @@ public class TestMVStore extends TestBase {
long
oldVersion
=
s
.
getCurrentVersion
();
// from now on, the old version is read-only
s
.
incrementVersion
();
s
.
commit
();
// more changes, in the new version
// changes can be rolled back if required
...
...
@@ -976,7 +979,7 @@ public class TestMVStore extends TestBase {
if
(
op
==
1
)
{
m
.
put
(
"1"
,
""
+
s
.
getCurrentVersion
());
}
s
.
incrementVersion
();
s
.
commit
();
}
for
(
int
j
=
0
;
j
<
s
.
getCurrentVersion
();
j
++)
{
MVMap
<
String
,
String
>
old
=
m
.
openVersion
(
j
);
...
...
@@ -997,14 +1000,14 @@ public class TestMVStore extends TestBase {
MVMap
<
String
,
String
>
m
;
m
=
s
.
openMap
(
"data"
);
long
first
=
s
.
getCurrentVersion
();
s
.
incrementVersion
();
s
.
commit
();
m
.
put
(
"1"
,
"Hello"
);
m
.
put
(
"2"
,
"World"
);
for
(
int
i
=
10
;
i
<
20
;
i
++)
{
m
.
put
(
""
+
i
,
"data"
);
}
long
old
=
s
.
getCurrentVersion
();
s
.
incrementVersion
();
s
.
commit
();
m
.
put
(
"1"
,
"Hallo"
);
m
.
put
(
"2"
,
"Welt"
);
MVMap
<
String
,
String
>
mFirst
;
...
...
@@ -1119,7 +1122,7 @@ public class TestMVStore extends TestBase {
assertTrue
(
s
.
hasUnsavedChanges
());
MVMap
<
String
,
String
>
m0
=
s
.
openMap
(
"data0"
);
m
.
put
(
"1"
,
"Hello"
);
assertEquals
(
1
,
s
.
incrementVersion
());
assertEquals
(
1
,
s
.
commit
());
s
.
rollbackTo
(
1
);
assertEquals
(
1
,
s
.
getCurrentVersion
());
assertEquals
(
"Hello"
,
m
.
get
(
"1"
));
...
...
@@ -1167,16 +1170,13 @@ public class TestMVStore extends TestBase {
assertEquals
(
"Hello"
,
m
.
get
(
"1"
));
assertFalse
(
m0
.
isReadOnly
());
m
.
put
(
"1"
,
"Hallo"
);
s
.
incrementVersion
();
s
.
commit
();
long
v3
=
s
.
getCurrentVersion
();
assertEquals
(
3
,
v3
);
long
v4
=
s
.
store
();
assertEquals
(
4
,
v4
);
assertEquals
(
4
,
s
.
getCurrentVersion
());
s
.
close
();
s
=
openStore
(
fileName
);
assertEquals
(
4
,
s
.
getCurrentVersion
());
assertEquals
(
3
,
s
.
getCurrentVersion
());
m
=
s
.
openMap
(
"data"
);
m
.
put
(
"1"
,
"Hi"
);
s
.
store
();
...
...
@@ -1185,7 +1185,7 @@ public class TestMVStore extends TestBase {
s
=
openStore
(
fileName
);
m
=
s
.
openMap
(
"data"
);
assertEquals
(
"Hi"
,
m
.
get
(
"1"
));
s
.
rollbackTo
(
v
4
);
s
.
rollbackTo
(
v
3
);
assertEquals
(
"Hallo"
,
m
.
get
(
"1"
));
s
.
close
();
...
...
@@ -1212,7 +1212,7 @@ public class TestMVStore extends TestBase {
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
m2
.
put
(
""
+
i
,
"Test"
);
}
long
v1
=
s
.
incrementVersion
();
long
v1
=
s
.
commit
();
assertEquals
(
1
,
v1
);
assertEquals
(
1
,
s
.
getCurrentVersion
());
MVMap
<
String
,
String
>
m1
=
s
.
openMap
(
"data1"
);
...
...
h2/src/test/org/h2/test/store/TestMVStoreBenchmark.java
浏览文件 @
900b5667
...
...
@@ -73,7 +73,7 @@ public class TestMVStoreBenchmark extends TestBase {
}
private
static
long
[]
getMemoryUsed
(
int
count
,
int
size
)
{
private
long
[]
getMemoryUsed
(
int
count
,
int
size
)
{
long
hash
,
tree
,
mv
;
ArrayList
<
Map
<
Integer
,
String
>>
mapList
;
long
mem
;
...
...
@@ -107,6 +107,10 @@ public class TestMVStoreBenchmark extends TestBase {
mv
=
getMemory
()
-
mem
;
mapList
.
size
();
trace
(
"hash: "
+
hash
/
1024
/
1024
+
" mb"
);
trace
(
"tree: "
+
tree
/
1024
/
1024
+
" mb"
);
trace
(
"mv: "
+
mv
/
1024
/
1024
+
" mb"
);
return
new
long
[]{
hash
,
tree
,
mv
};
}
...
...
@@ -179,7 +183,7 @@ public class TestMVStoreBenchmark extends TestBase {
}
time
=
System
.
currentTimeMillis
()
-
time
;
}
// System.out.println
(map.getClass().getName() + ": " + time);
trace
(
map
.
getClass
().
getName
()
+
": "
+
time
);
return
time
;
}
...
...
h2/src/test/org/h2/test/store/TestMVTableEngine.java
浏览文件 @
900b5667
...
...
@@ -141,7 +141,7 @@ public class TestMVTableEngine extends TestBase {
conn
.
close
();
long
sizeNew
=
FileUtils
.
size
(
getBaseDir
()
+
"/mvstore"
+
Constants
.
SUFFIX_MV_FILE
);
assertTrue
(
sizeNew
<
sizeOld
);
assertTrue
(
"new: "
+
sizeNew
+
" old: "
+
sizeOld
,
sizeNew
<
sizeOld
);
}
private
void
testTwoPhaseCommit
()
throws
Exception
{
...
...
h2/src/test/org/h2/test/store/TestTransactionStore.java
浏览文件 @
900b5667
...
...
@@ -59,6 +59,7 @@ public class TestTransactionStore extends TestBase {
private
void
testStopWhileCommitting
()
throws
Exception
{
String
fileName
=
getBaseDir
()
+
"/testStopWhileCommitting.h3"
;
FileUtils
.
delete
(
fileName
);
Random
r
=
new
Random
(
0
);
for
(
int
i
=
0
;
i
<
10
;)
{
MVStore
s
;
...
...
@@ -100,6 +101,16 @@ public class TestTransactionStore extends TestBase {
task
.
get
();
store
.
close
();
s
=
MVStore
.
open
(
fileName
);
// roll back a bit, until we have some undo log entries
assertTrue
(
s
.
hasMap
(
"undoLog"
));
for
(
int
back
=
0
;
back
<
100
;
back
++)
{
int
minus
=
r
.
nextInt
(
10
);
s
.
rollbackTo
(
Math
.
max
(
0
,
s
.
getCurrentVersion
()
-
minus
));
MVMap
<?,
?>
undo
=
s
.
openMap
(
"undoLog"
);
if
(
undo
.
size
()
>
0
)
{
break
;
}
}
ts
=
new
TransactionStore
(
s
);
List
<
Transaction
>
list
=
ts
.
getOpenTransactions
();
if
(
list
.
size
()
!=
0
)
{
...
...
@@ -111,10 +122,6 @@ public class TestTransactionStore extends TestBase {
s
.
close
();
FileUtils
.
delete
(
fileName
);
assertFalse
(
FileUtils
.
exists
(
fileName
));
FileUtils
.
delete
(
fileName
);
assertFalse
(
FileUtils
.
exists
(
fileName
));
s
.
close
();
FileUtils
.
delete
(
fileName
);
}
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论